From ec63324a7123d02b72794d4ec36cd2f16bca6064 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 16:42:28 +0000 Subject: [PATCH 1/2] Bump actions/checkout from 7.0.0 to 7.0.1 in the actions-minor group Bumps the actions-minor group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v7...v7.0.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build_addon.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_addon.yml b/.github/workflows/build_addon.yml index 3aabae42..8009fcfd 100644 --- a/.github/workflows/build_addon.yml +++ b/.github/workflows/build_addon.yml @@ -52,7 +52,7 @@ jobs: if: ${{ startsWith(github.ref, 'refs/tags/') }} needs: ["build"] steps: - - uses: actions/checkout@v7.0.0 + - uses: actions/checkout@v7.0.1 - name: download releases files uses: actions/download-artifact@v8.0.1 - name: Display structure of downloaded files From b80a762f34289cfc05ca0c6b9c08f7999f0af547 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 16:42:45 +0000 Subject: [PATCH 2/2] Pre-commit auto-fix --- addon/globalPlugins/remoteClient/__init__.py | 1996 +-- .../remoteClient/configuration.py | 122 +- .../remoteClient/connection_info.py | 23 +- addon/globalPlugins/remoteClient/dialogs.py | 975 +- .../remoteClient/keyboard_hook.py | 10 +- .../lib32/Cryptodome/Cipher/AES.py | 289 +- .../lib32/Cryptodome/Cipher/AES.pyi | 129 +- .../lib32/Cryptodome/Cipher/ARC2.py | 168 +- .../lib32/Cryptodome/Cipher/ARC2.pyi | 24 +- .../lib32/Cryptodome/Cipher/ARC4.py | 203 +- .../lib32/Cryptodome/Cipher/ARC4.pyi | 16 +- .../lib32/Cryptodome/Cipher/Blowfish.py | 154 +- .../lib32/Cryptodome/Cipher/Blowfish.pyi | 24 +- .../lib32/Cryptodome/Cipher/CAST.py | 144 +- .../lib32/Cryptodome/Cipher/CAST.pyi | 26 +- .../lib32/Cryptodome/Cipher/ChaCha20.py | 430 +- .../lib32/Cryptodome/Cipher/ChaCha20.pyi | 26 +- .../Cryptodome/Cipher/ChaCha20_Poly1305.py | 435 +- .../Cryptodome/Cipher/ChaCha20_Poly1305.pyi | 36 +- .../lib32/Cryptodome/Cipher/DES.py | 144 +- .../lib32/Cryptodome/Cipher/DES.pyi | 26 +- .../lib32/Cryptodome/Cipher/DES3.py | 180 +- .../lib32/Cryptodome/Cipher/DES3.pyi | 24 +- .../lib32/Cryptodome/Cipher/PKCS1_OAEP.py | 394 +- .../lib32/Cryptodome/Cipher/PKCS1_OAEP.pyi | 46 +- .../lib32/Cryptodome/Cipher/PKCS1_v1_5.py | 304 +- .../lib32/Cryptodome/Cipher/PKCS1_v1_5.pyi | 23 +- .../lib32/Cryptodome/Cipher/Salsa20.py | 241 +- .../lib32/Cryptodome/Cipher/Salsa20.pyi | 31 +- .../lib32/Cryptodome/Cipher/_EKSBlowfish.py | 126 +- .../lib32/Cryptodome/Cipher/_EKSBlowfish.pyi | 5 +- .../lib32/Cryptodome/Cipher/__init__.py | 143 +- .../lib32/Cryptodome/Cipher/_mode_cbc.py | 386 +- .../lib32/Cryptodome/Cipher/_mode_cbc.pyi | 29 +- .../lib32/Cryptodome/Cipher/_mode_ccm.py | 1262 +- .../lib32/Cryptodome/Cipher/_mode_ccm.pyi | 81 +- .../lib32/Cryptodome/Cipher/_mode_cfb.py | 393 +- .../lib32/Cryptodome/Cipher/_mode_cfb.pyi | 32 +- .../lib32/Cryptodome/Cipher/_mode_ctr.py | 718 +- .../lib32/Cryptodome/Cipher/_mode_ctr.pyi | 37 +- .../lib32/Cryptodome/Cipher/_mode_eax.py | 718 +- .../lib32/Cryptodome/Cipher/_mode_eax.pyi | 68 +- .../lib32/Cryptodome/Cipher/_mode_ecb.py | 362 +- .../lib32/Cryptodome/Cipher/_mode_ecb.pyi | 21 +- .../lib32/Cryptodome/Cipher/_mode_gcm.py | 974 +- .../lib32/Cryptodome/Cipher/_mode_gcm.pyi | 66 +- .../lib32/Cryptodome/Cipher/_mode_kw.py | 236 +- .../lib32/Cryptodome/Cipher/_mode_kwp.py | 184 +- .../lib32/Cryptodome/Cipher/_mode_ocb.py | 847 +- .../lib32/Cryptodome/Cipher/_mode_ocb.pyi | 49 +- .../lib32/Cryptodome/Cipher/_mode_ofb.py | 378 +- .../lib32/Cryptodome/Cipher/_mode_ofb.pyi | 29 +- .../lib32/Cryptodome/Cipher/_mode_openpgp.py | 243 +- .../lib32/Cryptodome/Cipher/_mode_openpgp.pyi | 19 +- .../lib32/Cryptodome/Cipher/_mode_siv.py | 535 +- .../lib32/Cryptodome/Cipher/_mode_siv.pyi | 51 +- .../Cryptodome/Cipher/_pkcs1_oaep_decode.py | 51 +- .../lib32/Cryptodome/Hash/BLAKE2b.py | 347 +- .../lib32/Cryptodome/Hash/BLAKE2b.pyi | 45 +- .../lib32/Cryptodome/Hash/BLAKE2s.py | 347 +- .../lib32/Cryptodome/Hash/BLAKE2s.pyi | 30 +- .../lib32/Cryptodome/Hash/CMAC.py | 560 +- .../lib32/Cryptodome/Hash/CMAC.pyi | 38 +- .../lib32/Cryptodome/Hash/HMAC.py | 290 +- .../lib32/Cryptodome/Hash/HMAC.pyi | 26 +- .../lib32/Cryptodome/Hash/KMAC128.py | 223 +- .../lib32/Cryptodome/Hash/KMAC128.pyi | 45 +- .../lib32/Cryptodome/Hash/KMAC256.py | 58 +- .../lib32/Cryptodome/Hash/KMAC256.pyi | 5 +- .../lib32/Cryptodome/Hash/KangarooTwelve.py | 295 +- .../lib32/Cryptodome/Hash/KangarooTwelve.pyi | 15 +- .../remoteClient/lib32/Cryptodome/Hash/MD2.py | 235 +- .../lib32/Cryptodome/Hash/MD2.pyi | 19 +- .../remoteClient/lib32/Cryptodome/Hash/MD4.py | 244 +- .../lib32/Cryptodome/Hash/MD4.pyi | 19 +- .../remoteClient/lib32/Cryptodome/Hash/MD5.py | 272 +- .../lib32/Cryptodome/Hash/MD5.pyi | 19 +- .../lib32/Cryptodome/Hash/Poly1305.py | 352 +- .../lib32/Cryptodome/Hash/Poly1305.pyi | 26 +- .../lib32/Cryptodome/Hash/RIPEMD.py | 2 - .../lib32/Cryptodome/Hash/RIPEMD160.py | 241 +- .../lib32/Cryptodome/Hash/RIPEMD160.pyi | 19 +- .../remoteClient/lib32/Cryptodome/Hash/SHA.py | 1 - .../lib32/Cryptodome/Hash/SHA.pyi | 1 - .../lib32/Cryptodome/Hash/SHA1.py | 271 +- .../lib32/Cryptodome/Hash/SHA1.pyi | 19 +- .../lib32/Cryptodome/Hash/SHA224.py | 273 +- .../lib32/Cryptodome/Hash/SHA224.pyi | 19 +- .../lib32/Cryptodome/Hash/SHA256.py | 272 +- .../lib32/Cryptodome/Hash/SHA256.pyi | 21 +- .../lib32/Cryptodome/Hash/SHA384.py | 271 +- .../lib32/Cryptodome/Hash/SHA384.pyi | 19 +- .../lib32/Cryptodome/Hash/SHA3_224.py | 296 +- .../lib32/Cryptodome/Hash/SHA3_224.pyi | 18 +- .../lib32/Cryptodome/Hash/SHA3_256.py | 296 +- .../lib32/Cryptodome/Hash/SHA3_256.pyi | 18 +- .../lib32/Cryptodome/Hash/SHA3_384.py | 296 +- .../lib32/Cryptodome/Hash/SHA3_384.pyi | 18 +- .../lib32/Cryptodome/Hash/SHA3_512.py | 286 +- .../lib32/Cryptodome/Hash/SHA3_512.pyi | 18 +- .../lib32/Cryptodome/Hash/SHA512.py | 307 +- .../lib32/Cryptodome/Hash/SHA512.pyi | 24 +- .../lib32/Cryptodome/Hash/SHAKE128.py | 225 +- .../lib32/Cryptodome/Hash/SHAKE128.pyi | 13 +- .../lib32/Cryptodome/Hash/SHAKE256.py | 227 +- .../lib32/Cryptodome/Hash/SHAKE256.pyi | 13 +- .../lib32/Cryptodome/Hash/TupleHash128.py | 160 +- .../lib32/Cryptodome/Hash/TupleHash128.pyi | 24 +- .../lib32/Cryptodome/Hash/TupleHash256.py | 61 +- .../lib32/Cryptodome/Hash/TupleHash256.pyi | 4 +- .../lib32/Cryptodome/Hash/TurboSHAKE128.py | 218 +- .../lib32/Cryptodome/Hash/TurboSHAKE128.pyi | 13 +- .../lib32/Cryptodome/Hash/TurboSHAKE256.py | 34 +- .../lib32/Cryptodome/Hash/TurboSHAKE256.pyi | 4 +- .../lib32/Cryptodome/Hash/__init__.py | 121 +- .../lib32/Cryptodome/Hash/cSHAKE128.py | 254 +- .../lib32/Cryptodome/Hash/cSHAKE128.pyi | 14 +- .../lib32/Cryptodome/Hash/cSHAKE256.py | 37 +- .../lib32/Cryptodome/Hash/cSHAKE256.pyi | 3 +- .../lib32/Cryptodome/Hash/keccak.py | 270 +- .../lib32/Cryptodome/Hash/keccak.pyi | 34 +- .../remoteClient/lib32/Cryptodome/IO/PEM.py | 276 +- .../remoteClient/lib32/Cryptodome/IO/PEM.pyi | 15 +- .../remoteClient/lib32/Cryptodome/IO/PKCS8.py | 379 +- .../lib32/Cryptodome/IO/PKCS8.pyi | 24 +- .../remoteClient/lib32/Cryptodome/IO/_PBES.py | 886 +- .../lib32/Cryptodome/IO/_PBES.pyi | 34 +- .../lib32/Cryptodome/IO/__init__.py | 2 +- .../lib32/Cryptodome/Math/Numbers.py | 21 +- .../lib32/Cryptodome/Math/Numbers.pyi | 3 +- .../lib32/Cryptodome/Math/Primality.py | 638 +- .../lib32/Cryptodome/Math/Primality.pyi | 24 +- .../lib32/Cryptodome/Math/_IntegerBase.py | 739 +- .../lib32/Cryptodome/Math/_IntegerBase.pyi | 125 +- .../lib32/Cryptodome/Math/_IntegerCustom.py | 208 +- .../lib32/Cryptodome/Math/_IntegerCustom.pyi | 2 +- .../lib32/Cryptodome/Math/_IntegerGMP.py | 1431 +- .../lib32/Cryptodome/Math/_IntegerGMP.pyi | 3 +- .../lib32/Cryptodome/Math/_IntegerNative.py | 691 +- .../lib32/Cryptodome/Math/_IntegerNative.pyi | 3 +- .../lib32/Cryptodome/Protocol/DH.py | 314 +- .../lib32/Cryptodome/Protocol/DH.pyi | 12 +- .../lib32/Cryptodome/Protocol/HPKE.py | 952 +- .../lib32/Cryptodome/Protocol/KDF.py | 1108 +- .../lib32/Cryptodome/Protocol/KDF.pyi | 72 +- .../Cryptodome/Protocol/SecretSharing.py | 487 +- .../Cryptodome/Protocol/SecretSharing.pyi | 31 +- .../lib32/Cryptodome/Protocol/__init__.py | 2 +- .../lib32/Cryptodome/Protocol/__init__.pyi | 2 +- .../lib32/Cryptodome/PublicKey/DSA.py | 1124 +- .../lib32/Cryptodome/PublicKey/DSA.pyi | 52 +- .../lib32/Cryptodome/PublicKey/ECC.py | 2386 ++-- .../lib32/Cryptodome/PublicKey/ECC.pyi | 103 +- .../lib32/Cryptodome/PublicKey/ElGamal.py | 451 +- .../lib32/Cryptodome/PublicKey/ElGamal.pyi | 18 +- .../lib32/Cryptodome/PublicKey/RSA.py | 1473 +- .../lib32/Cryptodome/PublicKey/RSA.pyi | 123 +- .../lib32/Cryptodome/PublicKey/__init__.py | 137 +- .../lib32/Cryptodome/PublicKey/_curve.py | 46 +- .../lib32/Cryptodome/PublicKey/_edwards.py | 143 +- .../lib32/Cryptodome/PublicKey/_montgomery.py | 238 +- .../lib32/Cryptodome/PublicKey/_nist_ecc.py | 405 +- .../lib32/Cryptodome/PublicKey/_openssh.py | 168 +- .../lib32/Cryptodome/PublicKey/_point.py | 1008 +- .../lib32/Cryptodome/PublicKey/_point.pyi | 79 +- .../lib32/Cryptodome/Random/__init__.py | 35 +- .../lib32/Cryptodome/Random/__init__.pyi | 13 +- .../lib32/Cryptodome/Random/random.py | 193 +- .../lib32/Cryptodome/Random/random.pyi | 22 +- .../Cryptodome/SelfTest/Cipher/__init__.py | 115 +- .../Cryptodome/SelfTest/Cipher/common.py | 900 +- .../Cryptodome/SelfTest/Cipher/test_AES.py | 3726 +++-- .../Cryptodome/SelfTest/Cipher/test_ARC2.py | 322 +- .../Cryptodome/SelfTest/Cipher/test_ARC4.py | 849 +- .../SelfTest/Cipher/test_Blowfish.py | 249 +- .../Cryptodome/SelfTest/Cipher/test_CAST.py | 102 +- .../Cryptodome/SelfTest/Cipher/test_CBC.py | 986 +- .../Cryptodome/SelfTest/Cipher/test_CCM.py | 2046 +-- .../Cryptodome/SelfTest/Cipher/test_CFB.py | 726 +- .../Cryptodome/SelfTest/Cipher/test_CTR.py | 954 +- .../SelfTest/Cipher/test_ChaCha20.py | 820 +- .../SelfTest/Cipher/test_ChaCha20_Poly1305.py | 1500 +- .../Cryptodome/SelfTest/Cipher/test_DES.py | 1112 +- .../Cryptodome/SelfTest/Cipher/test_DES3.py | 280 +- .../Cryptodome/SelfTest/Cipher/test_EAX.py | 1499 +- .../Cryptodome/SelfTest/Cipher/test_GCM.py | 1873 +-- .../Cryptodome/SelfTest/Cipher/test_KW.py | 308 +- .../Cryptodome/SelfTest/Cipher/test_OCB.py | 1673 ++- .../Cryptodome/SelfTest/Cipher/test_OFB.py | 340 +- .../SelfTest/Cipher/test_OpenPGP.py | 290 +- .../Cryptodome/SelfTest/Cipher/test_SIV.py | 1025 +- .../SelfTest/Cipher/test_Salsa20.py | 552 +- .../SelfTest/Cipher/test_pkcs1_15.py | 413 +- .../SelfTest/Cipher/test_pkcs1_oaep.py | 707 +- .../Cryptodome/SelfTest/Hash/__init__.py | 113 +- .../lib32/Cryptodome/SelfTest/Hash/common.py | 429 +- .../Cryptodome/SelfTest/Hash/test_BLAKE2.py | 803 +- .../Cryptodome/SelfTest/Hash/test_CMAC.py | 685 +- .../Cryptodome/SelfTest/Hash/test_HMAC.py | 997 +- .../Cryptodome/SelfTest/Hash/test_KMAC.py | 617 +- .../SelfTest/Hash/test_KangarooTwelve.py | 471 +- .../Cryptodome/SelfTest/Hash/test_MD2.py | 65 +- .../Cryptodome/SelfTest/Hash/test_MD4.py | 61 +- .../Cryptodome/SelfTest/Hash/test_MD5.py | 96 +- .../Cryptodome/SelfTest/Hash/test_Poly1305.py | 900 +- .../SelfTest/Hash/test_RIPEMD160.py | 81 +- .../Cryptodome/SelfTest/Hash/test_SHA1.py | 93 +- .../Cryptodome/SelfTest/Hash/test_SHA224.py | 60 +- .../Cryptodome/SelfTest/Hash/test_SHA256.py | 131 +- .../Cryptodome/SelfTest/Hash/test_SHA384.py | 62 +- .../Cryptodome/SelfTest/Hash/test_SHA3_224.py | 90 +- .../Cryptodome/SelfTest/Hash/test_SHA3_256.py | 91 +- .../Cryptodome/SelfTest/Hash/test_SHA3_384.py | 90 +- .../Cryptodome/SelfTest/Hash/test_SHA3_512.py | 90 +- .../Cryptodome/SelfTest/Hash/test_SHA512.py | 212 +- .../Cryptodome/SelfTest/Hash/test_SHAKE.py | 179 +- .../SelfTest/Hash/test_TupleHash.py | 542 +- .../SelfTest/Hash/test_TurboSHAKE.py | 578 +- .../Cryptodome/SelfTest/Hash/test_cSHAKE.py | 254 +- .../Cryptodome/SelfTest/Hash/test_keccak.py | 391 +- .../lib32/Cryptodome/SelfTest/IO/__init__.py | 21 +- .../lib32/Cryptodome/SelfTest/IO/test_PBES.py | 176 +- .../Cryptodome/SelfTest/IO/test_PKCS8.py | 325 +- .../Cryptodome/SelfTest/Math/__init__.py | 32 +- .../Cryptodome/SelfTest/Math/test_Numbers.py | 2040 ++- .../SelfTest/Math/test_Primality.py | 175 +- .../Cryptodome/SelfTest/Math/test_modexp.py | 266 +- .../Cryptodome/SelfTest/Math/test_modmult.py | 108 +- .../Cryptodome/SelfTest/Protocol/__init__.py | 39 +- .../Cryptodome/SelfTest/Protocol/test_HPKE.py | 884 +- .../Cryptodome/SelfTest/Protocol/test_KDF.py | 1845 ++- .../SelfTest/Protocol/test_SecretSharing.py | 473 +- .../Cryptodome/SelfTest/Protocol/test_ecdh.py | 1537 +- .../SelfTest/Protocol/test_rfc1751.py | 48 +- .../Cryptodome/SelfTest/PublicKey/__init__.py | 73 +- .../Cryptodome/SelfTest/PublicKey/test_DSA.py | 368 +- .../SelfTest/PublicKey/test_ECC_Curve25519.py | 465 +- .../SelfTest/PublicKey/test_ECC_Curve448.py | 479 +- .../SelfTest/PublicKey/test_ECC_Ed25519.py | 575 +- .../SelfTest/PublicKey/test_ECC_Ed448.py | 631 +- .../SelfTest/PublicKey/test_ECC_NIST.py | 2680 ++-- .../SelfTest/PublicKey/test_ElGamal.py | 356 +- .../Cryptodome/SelfTest/PublicKey/test_RSA.py | 467 +- .../PublicKey/test_import_Curve25519.py | 584 +- .../PublicKey/test_import_Curve448.py | 573 +- .../SelfTest/PublicKey/test_import_DSA.py | 650 +- .../SelfTest/PublicKey/test_import_ECC.py | 4542 +++--- .../SelfTest/PublicKey/test_import_RSA.py | 896 +- .../Cryptodome/SelfTest/Random/__init__.py | 21 +- .../Cryptodome/SelfTest/Random/test_random.py | 267 +- .../Cryptodome/SelfTest/Signature/__init__.py | 26 +- .../Cryptodome/SelfTest/Signature/test_dss.py | 2425 ++-- .../SelfTest/Signature/test_eddsa.py | 1051 +- .../SelfTest/Signature/test_pkcs1_15.py | 517 +- .../Cryptodome/SelfTest/Signature/test_pss.py | 579 +- .../Cryptodome/SelfTest/Util/__init__.py | 41 +- .../Cryptodome/SelfTest/Util/test_Counter.py | 54 +- .../Cryptodome/SelfTest/Util/test_Padding.py | 203 +- .../Cryptodome/SelfTest/Util/test_asn1.py | 1542 +- .../Cryptodome/SelfTest/Util/test_number.py | 304 +- .../Cryptodome/SelfTest/Util/test_rfc1751.py | 43 +- .../Cryptodome/SelfTest/Util/test_strxor.py | 458 +- .../lib32/Cryptodome/SelfTest/__init__.py | 113 +- .../lib32/Cryptodome/SelfTest/__main__.py | 12 +- .../lib32/Cryptodome/SelfTest/loader.py | 431 +- .../lib32/Cryptodome/SelfTest/st_common.py | 32 +- .../lib32/Cryptodome/Signature/DSS.py | 707 +- .../lib32/Cryptodome/Signature/DSS.pyi | 27 +- .../lib32/Cryptodome/Signature/PKCS1_PSS.py | 24 +- .../lib32/Cryptodome/Signature/PKCS1_PSS.pyi | 30 +- .../lib32/Cryptodome/Signature/PKCS1_v1_5.py | 21 +- .../lib32/Cryptodome/Signature/PKCS1_v1_5.pyi | 12 +- .../lib32/Cryptodome/Signature/__init__.py | 2 +- .../lib32/Cryptodome/Signature/eddsa.py | 552 +- .../lib32/Cryptodome/Signature/eddsa.pyi | 15 +- .../lib32/Cryptodome/Signature/pkcs1_15.py | 369 +- .../lib32/Cryptodome/Signature/pkcs1_15.pyi | 15 +- .../lib32/Cryptodome/Signature/pss.py | 668 +- .../lib32/Cryptodome/Signature/pss.pyi | 25 +- .../lib32/Cryptodome/Util/Counter.py | 94 +- .../lib32/Cryptodome/Util/Counter.pyi | 11 +- .../lib32/Cryptodome/Util/Padding.py | 127 +- .../lib32/Cryptodome/Util/Padding.pyi | 6 +- .../lib32/Cryptodome/Util/RFC1751.py | 2474 +++- .../lib32/Cryptodome/Util/__init__.py | 3 +- .../lib32/Cryptodome/Util/_cpu_features.py | 12 +- .../lib32/Cryptodome/Util/_file_system.py | 27 +- .../lib32/Cryptodome/Util/_file_system.pyi | 3 +- .../lib32/Cryptodome/Util/_raw_api.py | 510 +- .../lib32/Cryptodome/Util/_raw_api.pyi | 36 +- .../lib32/Cryptodome/Util/asn1.py | 1846 +-- .../lib32/Cryptodome/Util/asn1.pyi | 143 +- .../lib32/Cryptodome/Util/number.py | 11779 ++++++++++++++-- .../lib32/Cryptodome/Util/number.pyi | 28 +- .../lib32/Cryptodome/Util/py3compat.py | 230 +- .../lib32/Cryptodome/Util/py3compat.pyi | 12 +- .../lib32/Cryptodome/Util/strxor.py | 207 +- .../lib32/Cryptodome/Util/strxor.pyi | 4 +- .../remoteClient/lib32/Cryptodome/__init__.py | 14 +- .../lib32/Cryptodome/__init__.pyi | 4 +- .../lib64/Cryptodome/Cipher/AES.py | 289 +- .../lib64/Cryptodome/Cipher/AES.pyi | 129 +- .../lib64/Cryptodome/Cipher/ARC2.py | 168 +- .../lib64/Cryptodome/Cipher/ARC2.pyi | 24 +- .../lib64/Cryptodome/Cipher/ARC4.py | 203 +- .../lib64/Cryptodome/Cipher/ARC4.pyi | 16 +- .../lib64/Cryptodome/Cipher/Blowfish.py | 154 +- .../lib64/Cryptodome/Cipher/Blowfish.pyi | 24 +- .../lib64/Cryptodome/Cipher/CAST.py | 144 +- .../lib64/Cryptodome/Cipher/CAST.pyi | 26 +- .../lib64/Cryptodome/Cipher/ChaCha20.py | 430 +- .../lib64/Cryptodome/Cipher/ChaCha20.pyi | 26 +- .../Cryptodome/Cipher/ChaCha20_Poly1305.py | 435 +- .../Cryptodome/Cipher/ChaCha20_Poly1305.pyi | 36 +- .../lib64/Cryptodome/Cipher/DES.py | 144 +- .../lib64/Cryptodome/Cipher/DES.pyi | 26 +- .../lib64/Cryptodome/Cipher/DES3.py | 180 +- .../lib64/Cryptodome/Cipher/DES3.pyi | 24 +- .../lib64/Cryptodome/Cipher/PKCS1_OAEP.py | 394 +- .../lib64/Cryptodome/Cipher/PKCS1_OAEP.pyi | 46 +- .../lib64/Cryptodome/Cipher/PKCS1_v1_5.py | 304 +- .../lib64/Cryptodome/Cipher/PKCS1_v1_5.pyi | 23 +- .../lib64/Cryptodome/Cipher/Salsa20.py | 241 +- .../lib64/Cryptodome/Cipher/Salsa20.pyi | 31 +- .../lib64/Cryptodome/Cipher/_EKSBlowfish.py | 126 +- .../lib64/Cryptodome/Cipher/_EKSBlowfish.pyi | 5 +- .../lib64/Cryptodome/Cipher/__init__.py | 143 +- .../lib64/Cryptodome/Cipher/_mode_cbc.py | 386 +- .../lib64/Cryptodome/Cipher/_mode_cbc.pyi | 29 +- .../lib64/Cryptodome/Cipher/_mode_ccm.py | 1262 +- .../lib64/Cryptodome/Cipher/_mode_ccm.pyi | 81 +- .../lib64/Cryptodome/Cipher/_mode_cfb.py | 393 +- .../lib64/Cryptodome/Cipher/_mode_cfb.pyi | 32 +- .../lib64/Cryptodome/Cipher/_mode_ctr.py | 718 +- .../lib64/Cryptodome/Cipher/_mode_ctr.pyi | 37 +- .../lib64/Cryptodome/Cipher/_mode_eax.py | 718 +- .../lib64/Cryptodome/Cipher/_mode_eax.pyi | 68 +- .../lib64/Cryptodome/Cipher/_mode_ecb.py | 362 +- .../lib64/Cryptodome/Cipher/_mode_ecb.pyi | 21 +- .../lib64/Cryptodome/Cipher/_mode_gcm.py | 974 +- .../lib64/Cryptodome/Cipher/_mode_gcm.pyi | 66 +- .../lib64/Cryptodome/Cipher/_mode_kw.py | 236 +- .../lib64/Cryptodome/Cipher/_mode_kwp.py | 184 +- .../lib64/Cryptodome/Cipher/_mode_ocb.py | 847 +- .../lib64/Cryptodome/Cipher/_mode_ocb.pyi | 49 +- .../lib64/Cryptodome/Cipher/_mode_ofb.py | 378 +- .../lib64/Cryptodome/Cipher/_mode_ofb.pyi | 29 +- .../lib64/Cryptodome/Cipher/_mode_openpgp.py | 243 +- .../lib64/Cryptodome/Cipher/_mode_openpgp.pyi | 19 +- .../lib64/Cryptodome/Cipher/_mode_siv.py | 535 +- .../lib64/Cryptodome/Cipher/_mode_siv.pyi | 51 +- .../Cryptodome/Cipher/_pkcs1_oaep_decode.py | 51 +- .../lib64/Cryptodome/Hash/BLAKE2b.py | 347 +- .../lib64/Cryptodome/Hash/BLAKE2b.pyi | 45 +- .../lib64/Cryptodome/Hash/BLAKE2s.py | 347 +- .../lib64/Cryptodome/Hash/BLAKE2s.pyi | 30 +- .../lib64/Cryptodome/Hash/CMAC.py | 560 +- .../lib64/Cryptodome/Hash/CMAC.pyi | 38 +- .../lib64/Cryptodome/Hash/HMAC.py | 290 +- .../lib64/Cryptodome/Hash/HMAC.pyi | 26 +- .../lib64/Cryptodome/Hash/KMAC128.py | 223 +- .../lib64/Cryptodome/Hash/KMAC128.pyi | 45 +- .../lib64/Cryptodome/Hash/KMAC256.py | 58 +- .../lib64/Cryptodome/Hash/KMAC256.pyi | 5 +- .../lib64/Cryptodome/Hash/KangarooTwelve.py | 295 +- .../lib64/Cryptodome/Hash/KangarooTwelve.pyi | 15 +- .../remoteClient/lib64/Cryptodome/Hash/MD2.py | 235 +- .../lib64/Cryptodome/Hash/MD2.pyi | 19 +- .../remoteClient/lib64/Cryptodome/Hash/MD4.py | 244 +- .../lib64/Cryptodome/Hash/MD4.pyi | 19 +- .../remoteClient/lib64/Cryptodome/Hash/MD5.py | 272 +- .../lib64/Cryptodome/Hash/MD5.pyi | 19 +- .../lib64/Cryptodome/Hash/Poly1305.py | 352 +- .../lib64/Cryptodome/Hash/Poly1305.pyi | 26 +- .../lib64/Cryptodome/Hash/RIPEMD.py | 2 - .../lib64/Cryptodome/Hash/RIPEMD160.py | 241 +- .../lib64/Cryptodome/Hash/RIPEMD160.pyi | 19 +- .../remoteClient/lib64/Cryptodome/Hash/SHA.py | 1 - .../lib64/Cryptodome/Hash/SHA.pyi | 1 - .../lib64/Cryptodome/Hash/SHA1.py | 271 +- .../lib64/Cryptodome/Hash/SHA1.pyi | 19 +- .../lib64/Cryptodome/Hash/SHA224.py | 273 +- .../lib64/Cryptodome/Hash/SHA224.pyi | 19 +- .../lib64/Cryptodome/Hash/SHA256.py | 272 +- .../lib64/Cryptodome/Hash/SHA256.pyi | 21 +- .../lib64/Cryptodome/Hash/SHA384.py | 271 +- .../lib64/Cryptodome/Hash/SHA384.pyi | 19 +- .../lib64/Cryptodome/Hash/SHA3_224.py | 296 +- .../lib64/Cryptodome/Hash/SHA3_224.pyi | 18 +- .../lib64/Cryptodome/Hash/SHA3_256.py | 296 +- .../lib64/Cryptodome/Hash/SHA3_256.pyi | 18 +- .../lib64/Cryptodome/Hash/SHA3_384.py | 296 +- .../lib64/Cryptodome/Hash/SHA3_384.pyi | 18 +- .../lib64/Cryptodome/Hash/SHA3_512.py | 286 +- .../lib64/Cryptodome/Hash/SHA3_512.pyi | 18 +- .../lib64/Cryptodome/Hash/SHA512.py | 307 +- .../lib64/Cryptodome/Hash/SHA512.pyi | 24 +- .../lib64/Cryptodome/Hash/SHAKE128.py | 225 +- .../lib64/Cryptodome/Hash/SHAKE128.pyi | 13 +- .../lib64/Cryptodome/Hash/SHAKE256.py | 227 +- .../lib64/Cryptodome/Hash/SHAKE256.pyi | 13 +- .../lib64/Cryptodome/Hash/TupleHash128.py | 160 +- .../lib64/Cryptodome/Hash/TupleHash128.pyi | 24 +- .../lib64/Cryptodome/Hash/TupleHash256.py | 61 +- .../lib64/Cryptodome/Hash/TupleHash256.pyi | 4 +- .../lib64/Cryptodome/Hash/TurboSHAKE128.py | 218 +- .../lib64/Cryptodome/Hash/TurboSHAKE128.pyi | 13 +- .../lib64/Cryptodome/Hash/TurboSHAKE256.py | 34 +- .../lib64/Cryptodome/Hash/TurboSHAKE256.pyi | 4 +- .../lib64/Cryptodome/Hash/__init__.py | 121 +- .../lib64/Cryptodome/Hash/cSHAKE128.py | 254 +- .../lib64/Cryptodome/Hash/cSHAKE128.pyi | 14 +- .../lib64/Cryptodome/Hash/cSHAKE256.py | 37 +- .../lib64/Cryptodome/Hash/cSHAKE256.pyi | 3 +- .../lib64/Cryptodome/Hash/keccak.py | 270 +- .../lib64/Cryptodome/Hash/keccak.pyi | 34 +- .../remoteClient/lib64/Cryptodome/IO/PEM.py | 276 +- .../remoteClient/lib64/Cryptodome/IO/PEM.pyi | 15 +- .../remoteClient/lib64/Cryptodome/IO/PKCS8.py | 379 +- .../lib64/Cryptodome/IO/PKCS8.pyi | 24 +- .../remoteClient/lib64/Cryptodome/IO/_PBES.py | 886 +- .../lib64/Cryptodome/IO/_PBES.pyi | 34 +- .../lib64/Cryptodome/IO/__init__.py | 2 +- .../lib64/Cryptodome/Math/Numbers.py | 21 +- .../lib64/Cryptodome/Math/Numbers.pyi | 3 +- .../lib64/Cryptodome/Math/Primality.py | 638 +- .../lib64/Cryptodome/Math/Primality.pyi | 24 +- .../lib64/Cryptodome/Math/_IntegerBase.py | 739 +- .../lib64/Cryptodome/Math/_IntegerBase.pyi | 125 +- .../lib64/Cryptodome/Math/_IntegerCustom.py | 208 +- .../lib64/Cryptodome/Math/_IntegerCustom.pyi | 2 +- .../lib64/Cryptodome/Math/_IntegerGMP.py | 1431 +- .../lib64/Cryptodome/Math/_IntegerGMP.pyi | 3 +- .../lib64/Cryptodome/Math/_IntegerNative.py | 691 +- .../lib64/Cryptodome/Math/_IntegerNative.pyi | 3 +- .../lib64/Cryptodome/Protocol/DH.py | 314 +- .../lib64/Cryptodome/Protocol/DH.pyi | 12 +- .../lib64/Cryptodome/Protocol/HPKE.py | 952 +- .../lib64/Cryptodome/Protocol/KDF.py | 1108 +- .../lib64/Cryptodome/Protocol/KDF.pyi | 72 +- .../Cryptodome/Protocol/SecretSharing.py | 487 +- .../Cryptodome/Protocol/SecretSharing.pyi | 31 +- .../lib64/Cryptodome/Protocol/__init__.py | 2 +- .../lib64/Cryptodome/Protocol/__init__.pyi | 2 +- .../lib64/Cryptodome/PublicKey/DSA.py | 1124 +- .../lib64/Cryptodome/PublicKey/DSA.pyi | 52 +- .../lib64/Cryptodome/PublicKey/ECC.py | 2386 ++-- .../lib64/Cryptodome/PublicKey/ECC.pyi | 103 +- .../lib64/Cryptodome/PublicKey/ElGamal.py | 451 +- .../lib64/Cryptodome/PublicKey/ElGamal.pyi | 18 +- .../lib64/Cryptodome/PublicKey/RSA.py | 1473 +- .../lib64/Cryptodome/PublicKey/RSA.pyi | 123 +- .../lib64/Cryptodome/PublicKey/__init__.py | 137 +- .../lib64/Cryptodome/PublicKey/_curve.py | 46 +- .../lib64/Cryptodome/PublicKey/_edwards.py | 143 +- .../lib64/Cryptodome/PublicKey/_montgomery.py | 238 +- .../lib64/Cryptodome/PublicKey/_nist_ecc.py | 405 +- .../lib64/Cryptodome/PublicKey/_openssh.py | 168 +- .../lib64/Cryptodome/PublicKey/_point.py | 1008 +- .../lib64/Cryptodome/PublicKey/_point.pyi | 79 +- .../lib64/Cryptodome/Random/__init__.py | 35 +- .../lib64/Cryptodome/Random/__init__.pyi | 13 +- .../lib64/Cryptodome/Random/random.py | 193 +- .../lib64/Cryptodome/Random/random.pyi | 22 +- .../Cryptodome/SelfTest/Cipher/__init__.py | 115 +- .../Cryptodome/SelfTest/Cipher/common.py | 900 +- .../Cryptodome/SelfTest/Cipher/test_AES.py | 3726 +++-- .../Cryptodome/SelfTest/Cipher/test_ARC2.py | 322 +- .../Cryptodome/SelfTest/Cipher/test_ARC4.py | 849 +- .../SelfTest/Cipher/test_Blowfish.py | 249 +- .../Cryptodome/SelfTest/Cipher/test_CAST.py | 102 +- .../Cryptodome/SelfTest/Cipher/test_CBC.py | 986 +- .../Cryptodome/SelfTest/Cipher/test_CCM.py | 2046 +-- .../Cryptodome/SelfTest/Cipher/test_CFB.py | 726 +- .../Cryptodome/SelfTest/Cipher/test_CTR.py | 954 +- .../SelfTest/Cipher/test_ChaCha20.py | 820 +- .../SelfTest/Cipher/test_ChaCha20_Poly1305.py | 1500 +- .../Cryptodome/SelfTest/Cipher/test_DES.py | 1112 +- .../Cryptodome/SelfTest/Cipher/test_DES3.py | 280 +- .../Cryptodome/SelfTest/Cipher/test_EAX.py | 1499 +- .../Cryptodome/SelfTest/Cipher/test_GCM.py | 1873 +-- .../Cryptodome/SelfTest/Cipher/test_KW.py | 308 +- .../Cryptodome/SelfTest/Cipher/test_OCB.py | 1673 ++- .../Cryptodome/SelfTest/Cipher/test_OFB.py | 340 +- .../SelfTest/Cipher/test_OpenPGP.py | 290 +- .../Cryptodome/SelfTest/Cipher/test_SIV.py | 1025 +- .../SelfTest/Cipher/test_Salsa20.py | 552 +- .../SelfTest/Cipher/test_pkcs1_15.py | 413 +- .../SelfTest/Cipher/test_pkcs1_oaep.py | 707 +- .../Cryptodome/SelfTest/Hash/__init__.py | 113 +- .../lib64/Cryptodome/SelfTest/Hash/common.py | 429 +- .../Cryptodome/SelfTest/Hash/test_BLAKE2.py | 803 +- .../Cryptodome/SelfTest/Hash/test_CMAC.py | 685 +- .../Cryptodome/SelfTest/Hash/test_HMAC.py | 997 +- .../Cryptodome/SelfTest/Hash/test_KMAC.py | 617 +- .../SelfTest/Hash/test_KangarooTwelve.py | 471 +- .../Cryptodome/SelfTest/Hash/test_MD2.py | 65 +- .../Cryptodome/SelfTest/Hash/test_MD4.py | 61 +- .../Cryptodome/SelfTest/Hash/test_MD5.py | 96 +- .../Cryptodome/SelfTest/Hash/test_Poly1305.py | 900 +- .../SelfTest/Hash/test_RIPEMD160.py | 81 +- .../Cryptodome/SelfTest/Hash/test_SHA1.py | 93 +- .../Cryptodome/SelfTest/Hash/test_SHA224.py | 60 +- .../Cryptodome/SelfTest/Hash/test_SHA256.py | 131 +- .../Cryptodome/SelfTest/Hash/test_SHA384.py | 62 +- .../Cryptodome/SelfTest/Hash/test_SHA3_224.py | 90 +- .../Cryptodome/SelfTest/Hash/test_SHA3_256.py | 91 +- .../Cryptodome/SelfTest/Hash/test_SHA3_384.py | 90 +- .../Cryptodome/SelfTest/Hash/test_SHA3_512.py | 90 +- .../Cryptodome/SelfTest/Hash/test_SHA512.py | 212 +- .../Cryptodome/SelfTest/Hash/test_SHAKE.py | 179 +- .../SelfTest/Hash/test_TupleHash.py | 542 +- .../SelfTest/Hash/test_TurboSHAKE.py | 578 +- .../Cryptodome/SelfTest/Hash/test_cSHAKE.py | 254 +- .../Cryptodome/SelfTest/Hash/test_keccak.py | 391 +- .../lib64/Cryptodome/SelfTest/IO/__init__.py | 21 +- .../lib64/Cryptodome/SelfTest/IO/test_PBES.py | 176 +- .../Cryptodome/SelfTest/IO/test_PKCS8.py | 325 +- .../Cryptodome/SelfTest/Math/__init__.py | 32 +- .../Cryptodome/SelfTest/Math/test_Numbers.py | 2040 ++- .../SelfTest/Math/test_Primality.py | 175 +- .../Cryptodome/SelfTest/Math/test_modexp.py | 266 +- .../Cryptodome/SelfTest/Math/test_modmult.py | 108 +- .../Cryptodome/SelfTest/Protocol/__init__.py | 39 +- .../Cryptodome/SelfTest/Protocol/test_HPKE.py | 884 +- .../Cryptodome/SelfTest/Protocol/test_KDF.py | 1845 ++- .../SelfTest/Protocol/test_SecretSharing.py | 473 +- .../Cryptodome/SelfTest/Protocol/test_ecdh.py | 1537 +- .../SelfTest/Protocol/test_rfc1751.py | 48 +- .../Cryptodome/SelfTest/PublicKey/__init__.py | 73 +- .../Cryptodome/SelfTest/PublicKey/test_DSA.py | 368 +- .../SelfTest/PublicKey/test_ECC_Curve25519.py | 465 +- .../SelfTest/PublicKey/test_ECC_Curve448.py | 479 +- .../SelfTest/PublicKey/test_ECC_Ed25519.py | 575 +- .../SelfTest/PublicKey/test_ECC_Ed448.py | 631 +- .../SelfTest/PublicKey/test_ECC_NIST.py | 2680 ++-- .../SelfTest/PublicKey/test_ElGamal.py | 356 +- .../Cryptodome/SelfTest/PublicKey/test_RSA.py | 467 +- .../PublicKey/test_import_Curve25519.py | 584 +- .../PublicKey/test_import_Curve448.py | 573 +- .../SelfTest/PublicKey/test_import_DSA.py | 650 +- .../SelfTest/PublicKey/test_import_ECC.py | 4542 +++--- .../SelfTest/PublicKey/test_import_RSA.py | 896 +- .../Cryptodome/SelfTest/Random/__init__.py | 21 +- .../Cryptodome/SelfTest/Random/test_random.py | 267 +- .../Cryptodome/SelfTest/Signature/__init__.py | 26 +- .../Cryptodome/SelfTest/Signature/test_dss.py | 2425 ++-- .../SelfTest/Signature/test_eddsa.py | 1051 +- .../SelfTest/Signature/test_pkcs1_15.py | 517 +- .../Cryptodome/SelfTest/Signature/test_pss.py | 579 +- .../Cryptodome/SelfTest/Util/__init__.py | 41 +- .../Cryptodome/SelfTest/Util/test_Counter.py | 54 +- .../Cryptodome/SelfTest/Util/test_Padding.py | 203 +- .../Cryptodome/SelfTest/Util/test_asn1.py | 1542 +- .../Cryptodome/SelfTest/Util/test_number.py | 304 +- .../Cryptodome/SelfTest/Util/test_rfc1751.py | 43 +- .../Cryptodome/SelfTest/Util/test_strxor.py | 458 +- .../lib64/Cryptodome/SelfTest/__init__.py | 113 +- .../lib64/Cryptodome/SelfTest/__main__.py | 12 +- .../lib64/Cryptodome/SelfTest/loader.py | 431 +- .../lib64/Cryptodome/SelfTest/st_common.py | 32 +- .../lib64/Cryptodome/Signature/DSS.py | 707 +- .../lib64/Cryptodome/Signature/DSS.pyi | 27 +- .../lib64/Cryptodome/Signature/PKCS1_PSS.py | 24 +- .../lib64/Cryptodome/Signature/PKCS1_PSS.pyi | 30 +- .../lib64/Cryptodome/Signature/PKCS1_v1_5.py | 21 +- .../lib64/Cryptodome/Signature/PKCS1_v1_5.pyi | 12 +- .../lib64/Cryptodome/Signature/__init__.py | 2 +- .../lib64/Cryptodome/Signature/eddsa.py | 552 +- .../lib64/Cryptodome/Signature/eddsa.pyi | 15 +- .../lib64/Cryptodome/Signature/pkcs1_15.py | 369 +- .../lib64/Cryptodome/Signature/pkcs1_15.pyi | 15 +- .../lib64/Cryptodome/Signature/pss.py | 668 +- .../lib64/Cryptodome/Signature/pss.pyi | 25 +- .../lib64/Cryptodome/Util/Counter.py | 94 +- .../lib64/Cryptodome/Util/Counter.pyi | 11 +- .../lib64/Cryptodome/Util/Padding.py | 127 +- .../lib64/Cryptodome/Util/Padding.pyi | 6 +- .../lib64/Cryptodome/Util/RFC1751.py | 2474 +++- .../lib64/Cryptodome/Util/__init__.py | 3 +- .../lib64/Cryptodome/Util/_cpu_features.py | 12 +- .../lib64/Cryptodome/Util/_file_system.py | 27 +- .../lib64/Cryptodome/Util/_file_system.pyi | 3 +- .../lib64/Cryptodome/Util/_raw_api.py | 510 +- .../lib64/Cryptodome/Util/_raw_api.pyi | 36 +- .../lib64/Cryptodome/Util/asn1.py | 1846 +-- .../lib64/Cryptodome/Util/asn1.pyi | 143 +- .../lib64/Cryptodome/Util/number.py | 11779 ++++++++++++++-- .../lib64/Cryptodome/Util/number.pyi | 28 +- .../lib64/Cryptodome/Util/py3compat.py | 230 +- .../lib64/Cryptodome/Util/py3compat.pyi | 12 +- .../lib64/Cryptodome/Util/strxor.py | 207 +- .../lib64/Cryptodome/Util/strxor.pyi | 4 +- .../remoteClient/lib64/Cryptodome/__init__.py | 14 +- .../lib64/Cryptodome/__init__.pyi | 4 +- .../remoteClient/nvda_patcher.py | 7 +- addon/globalPlugins/remoteClient/server.py | 21 +- addon/globalPlugins/remoteClient/session.py | 685 +- addon/globalPlugins/remoteClient/transport.py | 650 +- addon/installTasks.py | 2 +- 600 files changed, 137520 insertions(+), 102007 deletions(-) diff --git a/addon/globalPlugins/remoteClient/__init__.py b/addon/globalPlugins/remoteClient/__init__.py index 42db0da5..d5619e53 100755 --- a/addon/globalPlugins/remoteClient/__init__.py +++ b/addon/globalPlugins/remoteClient/__init__.py @@ -1,918 +1,1078 @@ -import addonHandler -import api -import configobj -import core -import braille -import ctypes -import ctypes.wintypes -import globalVars -import gui -from gui import NVDASettingsDialog -import IAccessibleHandler -import json -import logging -import os -import queueHandler -try: - from winAPI.secureDesktop import post_secureDesktopStateChange -except: - post_secureDesktopStateChange = None -try: - from utils import security -except: - pass -import buildVersion -import shlobj -import speech -import socket -import ssl -import sys -import threading -import ui -import uuid -import wx -import base64 -from config import conf as nvda_conf -from globalPluginHandler import GlobalPlugin as _GlobalPlugin -from keyboardHandler import KeyboardInputGesture -from logHandler import log -from scriptHandler import script -from winUser import WM_QUIT - -logger = logging.getLogger(__name__) - -from . import bridge -from . import configuration -from . import cues -from . import dialogs -if buildVersion.version_year < 2025: - from . import keyboard_hook -else: - import inputCore -from . import local_machine -from . import serializer -from . import server -from . import url_handler -from .socket_utils import SERVER_PORT, address_to_hostport, hostport_to_address, wrap_socket -from .transport import RelayTransport, TransportEvents - -from .session import MasterSession, SlaveSession -try: - addonHandler.initTranslation() -except addonHandler.AddonError: - log.warning( - "Unable to initialise translations. This may be because the addon is running from NVDA scratchpad." - ) -speakOnDemand = {"speakOnDemand": True} if buildVersion.version_year >= 2024 else {} -if buildVersion.version_year < 2025: - logging.getLogger("keyboard_hook").addHandler(logging.StreamHandler(sys.stdout)) - -client = None - -class GlobalPlugin(_GlobalPlugin): - # Translators: script category for add-on gestures - scriptCategory = _("TeleNVDA") - - def __init__(self, *args, **kwargs): - global client - super().__init__(*args, **kwargs) - for addon in addonHandler.getAvailableAddons(): - if addon.name == "remote" and not addon.isDisabled: - raise RuntimeError("TeleNVDA cannot be used while NVDA Remote is running. Please, disable NVDA Remote and restart NVDA.") - self.local_machine = local_machine.LocalMachine() - self.slave_session = None - self.master_session = None - self.create_menu() - NVDASettingsDialog.categoryClasses.append(dialogs.OptionsDialog) - self.connecting = False - self.muted = False # Used to know if mute remote was activated manually - self.url_handler_window = url_handler.URLHandlerWindow(callback=self.verify_connect) - url_handler.register_url_handler() - self.master_transport = None - self.slave_transport = None - self.server = None - self.hook_thread = None - self.sending_keys = False - self.key_modifiers = set() - self.hostPendingModifiers = set() - self.ignoreGesture = False - self.guestScripts = (self.script_sendKeys, self.script_ignoreNextGesture) - self.sd_server = None - self.sd_relay = None - self.sd_bridge = None - try: - configuration.get_config() - except configobj.ParseError: - os.remove(os.path.abspath(os.path.join(globalVars.appArgs.configPath, configuration.CONFIG_FILE_NAME))) - queueHandler.queueFunction(queueHandler.eventQueue, wx.CallAfter, wx.MessageBox, _("Your NVDA Remote configuration was corrupted and has been reset."), _("NVDA Remote Configuration Error"), wx.OK|wx.ICON_EXCLAMATION) - if hasattr(shlobj, 'SHGetKnownFolderPath'): - self.temp_location = os.path.join(shlobj.SHGetKnownFolderPath(shlobj.FolderId.PROGRAM_DATA), 'temp') - else: - self.temp_location = os.path.join(shlobj.SHGetFolderPath(0, shlobj.CSIDL_COMMON_APPDATA), 'temp') - self.ipc_file = os.path.join(self.temp_location, 'remote.ipc') - self.sd_focused = False - if post_secureDesktopStateChange: - post_secureDesktopStateChange.register(self.onSecureDesktopChange) - if hasattr(globalVars, 'teleNVDA'): - self.postStartupHandler() - core.postNvdaStartup.register(self.postStartupHandler) - globalVars.teleNVDA = None - client = self - - def postStartupHandler(self): - cs = configuration.get_config()['controlserver'] - if globalVars.appArgs.secure: - self.handle_secure_desktop() - if cs['autoconnect'] and not self.master_session and not self.slave_session: - wx.CallLater(50,self.perform_autoconnect) - - def perform_autoconnect(self): - cs = configuration.get_config()['controlserver'] - channel = cs['key'] - encryption_key = cs['encryption_key'] - if cs['self_hosted']: - port = cs['port'] - address = ('localhost',port) - UPNP = cs['UPNP'] - self.start_control_server(port, channel, UPNP) - else: - address = address_to_hostport(cs['host']) - if cs['connection_type']==0: - self.connect_as_slave(address, channel, encryption_key) - else: - self.connect_as_master(address, channel, encryption_key) - - def create_menu(self): - self.menu = wx.Menu() - tools_menu = gui.mainFrame.sysTrayIcon.toolsMenu - # Translators: Item in TeleNVDA submenu to connect to a remote computer. - self.connect_item = self.menu.Append(wx.ID_ANY, _("Connect..."), _("Remotely connect to another computer running NVDA Remote Access or TeleNVDA")) - gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.do_connect, self.connect_item) - # Translators: Item in TeleNVDA submenu to disconnect from a remote computer. - self.disconnect_item = self.menu.Append(wx.ID_ANY, _("Disconnect"), _("Disconnect from another computer running NVDA Remote Access or TeleNVDA")) - gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_disconnect_item, self.disconnect_item) - self.menu.Remove(self.disconnect_item.Id) - # Translators: Menu item in TeleNVDA submenu to mute speech and sounds from the remote computer. - self.mute_item = self.menu.Append(wx.ID_ANY, _("Mute remote"), _("Mute speech and sounds from the remote computer")) - self.mute_item.Enable(False) - gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_mute_item, self.mute_item) - # Translators: Menu item in TeleNVDA submenu to push clipboard content to the remote computer. - self.push_clipboard_item = self.menu.Append(wx.ID_ANY, _("&Push clipboard"), _("Push the clipboard to the other machine")) - self.push_clipboard_item.Enable(False) - gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_push_clipboard_item, self.push_clipboard_item) - # Translators: Menu item in TeleNVDA submenu to send a file to the remote computer. - self.send_file_item = self.menu.Append(wx.ID_ANY, _("Send &file..."), _("Send a file to the other machine")) - self.send_file_item.Enable(False) - gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_send_file_item, self.send_file_item) - self.copyLinkMenu = wx.Menu() - # Translators: Menu item in TeleNVDA submenu to copy a link to the current session compatible with NVDA Remote. - self.copy_link_remote_item = self.copyLinkMenu .Append(wx.ID_ANY, _("NVDA &Remote protocol (recommended)"), _("Copy a link to the remote session compatible with both NVDA Remote and TeleNVDA")) - self.copy_link_remote_item.Enable(False) - gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_copy_link_remote_item, self.copy_link_remote_item) - # Translators: Menu item in TeleNVDA submenu to copy a link to the current session compatible with TeleNVDA. - self.copy_link_tele_item = self.copyLinkMenu .Append(wx.ID_ANY, _("&TeleNVDA protocol"), _("Copy a link to the remote session compatible only with TeleNVDA")) - self.copy_link_tele_item.Enable(False) - gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_copy_link_tele_item, self.copy_link_tele_item) - # Translators: Menu item in TeleNVDA submenu to copy a link to the current session. - self.copy_link_item=self.menu.AppendSubMenu(self.copyLinkMenu, _("Copy &link"), _("Copy a link to the remote session")) - # Translators: Menu item in TeleNVDA submenu to open add-on options. - self.options_item = self.menu.Append(wx.ID_ANY, _("&Options..."), _("Options")) - gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_options_item, self.options_item) - # Translators: Menu item in TeleNVDA submenu to send Control+Alt+Delete to the remote computer. - self.send_ctrl_alt_del_item = self.menu.Append(wx.ID_ANY, _("Send Ctrl+Alt+Del"), _("Send Ctrl+Alt+Del")) - gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_send_ctrl_alt_del, self.send_ctrl_alt_del_item) - self.send_ctrl_alt_del_item.Enable(False) - - # Translators: Label of menu in NVDA tools menu. - self.remote_item=tools_menu.AppendSubMenu(self.menu, _("R&emote"), _("TeleNVDA")) - - def terminate(self): - global client - if post_secureDesktopStateChange: - post_secureDesktopStateChange.unregister(self.onSecureDesktopChange) - self.disconnect() - self.local_machine.terminate() - self.local_machine = None - NVDASettingsDialog.categoryClasses.remove(dialogs.OptionsDialog) - self.copyLinkMenu.Remove(self.copy_link_remote_item.Id) - self.copy_link_remote_item.Destroy() - self.copy_link_remote_item=None - self.copyLinkMenu.Remove(self.copy_link_tele_item.Id) - self.copy_link_tele_item.Destroy() - self.copy_link_tele_item=None - try: - self.menu.Remove(self.connect_item.Id) - self.menu.Remove(self.disconnect_item.Id) - except: - pass - self.connect_item.Destroy() - self.connect_item=None - self.disconnect_item.Destroy() - self.disconnect_item=None - self.menu.Remove(self.mute_item.Id) - self.mute_item.Destroy() - self.mute_item=None - self.menu.Remove(self.push_clipboard_item.Id) - self.push_clipboard_item.Destroy() - self.push_clipboard_item=None - self.menu.Remove(self.send_file_item.Id) - self.send_file_item.Destroy() - self.send_file_item=None - self.menu.Remove(self.copy_link_item.Id) - self.copy_link_item.Destroy() - self.copy_link_item = None - self.menu.Remove(self.options_item.Id) - self.options_item.Destroy() - self.options_item=None - self.menu.Remove(self.send_ctrl_alt_del_item.Id) - self.send_ctrl_alt_del_item.Destroy() - self.send_ctrl_alt_del_item=None - tools_menu = gui.mainFrame.sysTrayIcon.toolsMenu - tools_menu.Remove(self.remote_item.Id) - self.remote_item.Destroy() - self.remote_item=None - try: - self.menu.Destroy() - self.copyLinkMenu.Destroy() - except (RuntimeError, AttributeError): - pass - try: - os.unlink(self.ipc_file) - except: - pass - self.menu=None - url_handler.unregister_url_handler() - self.url_handler_window.destroy() - self.url_handler_window=None - core.postNvdaStartup.unregister(self.postStartupHandler) - client = None - - def on_disconnect_item(self, evt): - if evt: - evt.Skip() - def disconnect_as_slave_with_alert(): - if (self.slave_transport is not None - and configuration.get_config()['ui']['alert_before_slave_disconnect'] - and not gui.message.isModalMessageBoxActive()): # Check if a modal message box is open - result = gui.messageBox( - # Translators: question before disconnecting - message=_("Are you sure you want to disconnect the controlled computer?"), - # Translators: question title - caption=_("Warning!"), - style=wx.YES | wx.NO | wx.ICON_WARNING - ) - if result == wx.YES: - self.disconnect() - elif (self.master_transport is not None - or (self.slave_transport is not None - and not configuration.get_config()['ui']['alert_before_slave_disconnect'])): - self.disconnect() - wx.CallAfter(disconnect_as_slave_with_alert) - - def on_mute_item(self, evt): - if evt: - evt.Skip() - if not self.muted: - # Translators: Menu item in TeleNVDA submenu to unmute speech and sounds from the remote computer. - self.mute_item.SetItemLabel(_("Unmute remote")) - ui.message(_("Mute speech and sounds from the remote computer")) - if not configuration.get_config()['ui']['mute_when_controlling_local_machine']: - self.local_machine.is_muted = True - self.muted = True - else: - # Translators: Menu item in TeleNVDA submenu to mute speech and sounds from the remote computer. - self.mute_item.SetItemLabel(_("Mute remote")) - ui.message(_("Unmute speech and sounds from the remote computer")) - if not configuration.get_config()['ui']['mute_when_controlling_local_machine']: - self.local_machine.is_muted = False - self.muted = False - - def on_push_clipboard_item(self, evt): - connector = self.slave_transport or self.master_transport - try: - connector.send(type='set_clipboard_text', text=api.getClipData()) - cues.clipboard_pushed() - except TypeError: - log.exception("Unable to push clipboard") - - - def on_send_file_item(self, evt): - connector = self.slave_transport or self.master_transport - if not getattr(connector, 'connected', False): - ui.message(_("Not connected.")) - return - if globalVars.appArgs.secure: - return - # Check if a file dialog is already open - if getattr(self, 'is_send_file_dialog_open', False): - return - # Set the flag to True, indicating that the file dialog is open - setattr(self, 'is_send_file_dialog_open', True) - fd = wx.FileDialog(gui.mainFrame, - # Translators: message displayed in transfer file dialog when sending a file - message=_("Choose the file you want to send to the remote computer"), - # Translators: supported file types when sending or receiving files - wildcard=_("All files (*.*)") + "|*.*", - defaultDir=os.environ['userprofile'], style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_PREVIEW) - if fd.ShowModal() != wx.ID_OK: - # Reset the flag to False after the file dialog is closed - setattr(self, 'is_send_file_dialog_open', False) - return - # Reset the flag to False after the file dialog is closed - setattr(self, 'is_send_file_dialog_open', False) - filename = os.path.basename(fd.GetPath()) - try: - f = open(fd.GetPath(), "rb") - file_content = f.read() - f.close() - except: - logger.exception("Unable to read the specified file") - if len(file_content) > 10485760: - gui.messageBox( - # Translators: error message when a file is too big - message=_("This file is too large. Only files smaller than 10 MB are supported."), - # Translators: error message caption - caption=_("Error"), - style=wx.ICON_ERROR) - return - result = gui.messageBox( - # Translators: question before sending a file - message=_("The session will be blocked until the transfer is complete. Are you sure you want to continue?"), - # Translators: question title - caption=_("Warning!"), - style=wx.YES | wx.NO | wx.ICON_WARNING) - if result == wx.YES: - file_content = base64.b64encode(file_content) - connector.send(type='file_transfer', name=filename, content=file_content.decode("utf-8")) - cues.clipboard_pushed() - # Translators: message spoken when the file has been sent successfully - ui.message(_("File sent")) - - @script( - # Translators: report number of connected computers gesture description - _("Reports number of computers connected to a session"), - **speakOnDemand) - def script_reportConnectedClients(self, gesture): - session = self.master_session or self.slave_session - if not session: - ui.message(_("Not connected.")) - return - # TRANSLATORS: message reported when get number of clients gesture is pressed - ui.message(ngettext("This is the only computer connected to this session", "There are {} computers connected to this session", session.client_count).format(session.client_count)) - - @script( - # Translators: send file gesture description - _("Sends the specified file to the remote machine"), - gesture="kb:control+shift+NVDA+f", - **speakOnDemand) - def script_send_file(self, gesture): - wx.CallAfter(self.on_send_file_item, None) - - @script( - # Translators: push clipboard gesture description - _("Sends the contents of the clipboard to the remote machine"), - gesture="kb:control+shift+NVDA+c", - **speakOnDemand) - def script_push_clipboard(self, gesture): - connector = self.slave_transport or self.master_transport - if not getattr(connector,'connected',False): - ui.message(_("Not connected.")) - return - try: - connector.send(type='set_clipboard_text', text=api.getClipData()) - cues.clipboard_pushed() - ui.message(_("Clipboard pushed")) - except (TypeError, OSError): - ui.message(_("Unable to push clipboard")) - - def on_copy_link_remote_item(self, evt): - session = self.master_session or self.slave_session - url = session.get_connection_info().get_url_to_connect(0) - api.copyToClip(str(url)) - - def on_copy_link_tele_item(self, evt): - session = self.master_session or self.slave_session - url = session.get_connection_info().get_url_to_connect(1) - api.copyToClip(str(url)) - - def on_options_item(self, evt): - wx.CallAfter(gui.mainFrame.popupSettingsDialog if hasattr(gui.mainFrame, "popupSettingsDialog") else gui.mainFrame._popupSettingsDialog, gui.NVDASettingsDialog, dialogs.OptionsDialog) - evt.Skip() - - def on_send_ctrl_alt_del(self, evt): - self.master_transport.send('send_SAS') - # Translators: message spoken when the Ctrl+Alt+Delete has been sent to the remote machine successfully - ui.message(_("Ctrl+Alt+Delete has been sent to the remote machine")) - - def disconnect(self): - if self.master_transport is None and self.slave_transport is None: - return - if self.server is not None: - self.server.close() - self.server = None - if self.master_transport is not None: - self.disconnect_as_master() - if self.slave_transport is not None: - self.disconnect_as_slave() - # Translators: Presented when disconnected from the remote computer. - ui.message(_("Disconnected!")) - cues.disconnected() - if self.menu.FindItemById(self.disconnect_item.Id): - self.menu.Remove(self.disconnect_item.Id) - if not self.menu.FindItemById(self.connect_item.Id): - self.menu.Insert(0, self.connect_item) - self.push_clipboard_item.Enable(False) - self.send_file_item.Enable(False) - self.copy_link_remote_item.Enable(False) - self.copy_link_tele_item.Enable(False) - - def disconnect_as_master(self): - self.master_transport.close() - self.master_transport = None - self.master_session = None - - def disconnecting_as_master(self): - if self.menu: - if not self.menu.FindItemById(self.connect_item.Id): - self.menu.Insert(0, self.connect_item) - if self.menu.FindItemById(self.disconnect_item.Id): - self.menu.Remove(self.disconnect_item.Id) - # Translators: Menu item in TeleNVDA submenu to mute speech and sounds from the remote computer. - self.mute_item.SetItemLabel(_("Mute remote")) - self.mute_item.Enable(False) - self.push_clipboard_item.Enable(False) - self.send_file_item.Enable(False) - self.copy_link_remote_item.Enable(False) - self.copy_link_tele_item.Enable(False) - self.send_ctrl_alt_del_item.Enable(False) - if self.local_machine: - self.local_machine.is_muted = False - self.sending_keys = False - self.muted = False - if buildVersion.version_year < 2025: - if self.hook_thread is not None: - ctypes.windll.user32.PostThreadMessageW(self.hook_thread.ident, WM_QUIT, 0, 0) - self.hook_thread.join() - self.hook_thread = None - self.key_modifiers = set() - - def disconnect_as_slave(self): - self.slave_transport.close() - self.slave_transport = None - self.slave_session = None - - def on_connected_as_master_failed(self): - if self.master_transport.successful_connects == 0: - self.disconnect_as_master() - # Translators: Title of the connection error dialog. - gui.messageBox(parent=gui.mainFrame, caption=_("Error Connecting"), - # Translators: Message shown when cannot connect to the remote computer. - message=_("Unable to connect to the remote computer"), style=wx.OK | wx.ICON_WARNING) - - def do_connect(self, evt): - if evt: - evt.Skip() - # Check if the connect dialog is already open - if getattr(self, 'is_connect_dialog_open', False): - return - # Set the flag to True, indicating that the connect dialog is open - setattr(self, 'is_connect_dialog_open', True) - last_cons = configuration.get_config()['connections']['last_connected'] - # Translators: Title of the connect dialog. - dlg = dialogs.DirectConnectDialog(parent=gui.mainFrame, id=wx.ID_ANY, title=_("Connect")) - dlg.panel.host.SetItems(list(reversed(last_cons))) - dlg.panel.host.SetSelection(0) - def handle_dlg_complete(dlg_result): - if dlg_result != wx.ID_OK: - # Reset the flag to False when the dialog is closed - setattr(self, 'is_connect_dialog_open', False) - return - if dlg.client_or_server.GetSelection() == 0: #client - host = dlg.panel.host.GetValue() - server_addr, port = address_to_hostport(host) - channel = dlg.panel.key.GetValue() - encryption_key = dlg.panel.encryption_key.GetValue() - if dlg.connection_type.GetSelection() == 0: - self.connect_as_master((server_addr, port), channel, encryption_key) - else: - self.connect_as_slave((server_addr, port), channel, encryption_key) - else: #We want a server - channel = dlg.panel.key.GetValue() - encryption_key = dlg.panel.encryption_key.GetValue() - self.start_control_server(int(dlg.panel.port.GetValue()), channel, useUPNP=bool(dlg.panel.useUPNP.GetValue())) - if dlg.connection_type.GetSelection() == 0: - self.connect_as_master(('127.0.0.1', int(dlg.panel.port.GetValue())), channel, insecure=True, encryption_key=encryption_key) - else: - self.connect_as_slave(('127.0.0.1', int(dlg.panel.port.GetValue())), channel, insecure=True, encryption_key=encryption_key) - # Reset the flag to False when the dialog is closed - setattr(self, 'is_connect_dialog_open', False) - gui.runScriptModalDialog(dlg, callback=handle_dlg_complete) - - def on_connected_as_master(self): - configuration.write_connection_to_config(self.master_transport.address) - if not self.menu.FindItemById(self.disconnect_item.Id): - self.menu.Insert(0, self.disconnect_item) - if self.menu.FindItemById(self.connect_item.Id): - self.menu.Remove(self.connect_item.Id) - self.mute_item.Enable(True) - self.push_clipboard_item.Enable(True) - if not globalVars.appArgs.secure: - self.send_file_item.Enable(True) - self.copy_link_remote_item.Enable(True) - self.copy_link_tele_item.Enable(True) - self.send_ctrl_alt_del_item.Enable(True) - if buildVersion.version_year < 2025: - # We might have already created a hook thread before if we're restoring an - # interrupted connection. We must not create another. - if not self.hook_thread: - self.hook_thread = threading.Thread(target=self.hook) - self.hook_thread.daemon = True - self.hook_thread.start() - # Translators: Presented when connected to the remote computer. - ui.message(_("Connected!")) - cues.connected() - if configuration.get_config()['ui']['mute_when_controlling_local_machine'] and not self.sending_keys: - self.local_machine.is_muted = True - - def on_disconnected_as_master(self): - # Translators: Presented when connection to a remote computer was interupted. - ui.message(_("Connection interrupted")) - - def connect_as_master(self, address, key, encryption_key, insecure=False): - transport = RelayTransport(address=address, serializer=serializer.JSONSerializer(), channel=key, connection_type='master', insecure=insecure, encryption_key=encryption_key) - self.master_session = MasterSession(transport=transport, local_machine=self.local_machine) - transport.callback_manager.register_callback(TransportEvents.CERTIFICATE_AUTHENTICATION_FAILED, self.on_certificate_as_master_failed) - transport.callback_manager.register_callback(TransportEvents.CONNECTED, self.on_connected_as_master) - transport.callback_manager.register_callback(TransportEvents.CONNECTION_FAILED, self.on_connected_as_master_failed) - transport.callback_manager.register_callback(TransportEvents.CLOSING, self.disconnecting_as_master) - transport.callback_manager.register_callback(TransportEvents.DISCONNECTED, self.on_disconnected_as_master) - self.master_transport = transport - self.master_transport.reconnector_thread.start() - - def connect_as_slave(self, address, key, encryption_key, insecure=False): - if not nvda_conf['keyboard']['handleInjectedKeys'] and gui.messageBox( - # Translators: A message to warn the user that handle keys from other applications should be on. - message=_("The option to handle keys from other applications is disabled in your NVDA keyboard settings. In order to allow the keyboard of this machine to be controlled, this option should be enabled. Would you like to do this now?"), - # Translators: The title of the warning dialog displayed when handle keys from other applications is disabled. - caption=_("Warning"),style=wx.YES|wx.NO|wx.ICON_WARNING)==wx.YES: - nvda_conf['keyboard']['handleInjectedKeys']=True - transport = RelayTransport(serializer=serializer.JSONSerializer(), address=address, channel=key, connection_type='slave', insecure=insecure, encryption_key=encryption_key) - self.slave_session = SlaveSession(transport=transport, local_machine=self.local_machine) - self.slave_transport = transport - transport.callback_manager.register_callback(TransportEvents.CERTIFICATE_AUTHENTICATION_FAILED, self.on_certificate_as_slave_failed) - self.slave_transport.callback_manager.register_callback(TransportEvents.CONNECTED, self.on_connected_as_slave) - self.slave_transport.reconnector_thread.start() - if not self.menu.FindItemById(self.disconnect_item.Id): - self.menu.Insert(0, self.disconnect_item) - if self.menu.FindItemById(self.connect_item.Id): - self.menu.Remove(self.connect_item.Id) - - def handle_certificate_failed(self, transport): - self.last_fail_address = transport.address - self.last_fail_key = transport.channel - self.disconnect() - try: - cert_hash = transport.last_fail_fingerprint - wnd = dialogs.CertificateUnauthorizedDialog(None, fingerprint=cert_hash) - a = wnd.ShowModal() - if a == wx.ID_YES: - config = configuration.get_config() - config['trusted_certs'][hostport_to_address(self.last_fail_address)]=cert_hash - config.write() - if a == wx.ID_YES or a == wx.ID_NO: return True - except Exception as ex: - log.error(ex) - return False - - def on_certificate_as_master_failed(self): - if self.handle_certificate_failed(self.master_transport): - self.connect_as_master(self.last_fail_address, self.last_fail_key, True) - - def on_certificate_as_slave_failed(self): - if self.handle_certificate_failed(self.slave_transport): - self.connect_as_slave(self.last_fail_address, self.last_fail_key, True) - - def on_connected_as_slave(self): - log.info("Control connector connected") - cues.control_server_connected() - # Translators: Presented in direct (client to server) remote connection when the controlled computer is ready. - speech.speakMessage(_("Connected to control server")) - self.push_clipboard_item.Enable(True) - if not globalVars.appArgs.secure: - self.send_file_item.Enable(True) - self.copy_link_remote_item.Enable(True) - self.copy_link_tele_item.Enable(True) - configuration.write_connection_to_config(self.slave_transport.address) - - def start_control_server(self, server_port, channel, useUPNP=False): - self.server = server.Server(server_port, channel, UPNP=useUPNP) - server_thread = threading.Thread(target=self.server.run) - server_thread.daemon = True - server_thread.start() - - def hook(self): - log.debug("Hook thread start") - keyhook = keyboard_hook.KeyboardHook() - keyhook.register_callback(self.hook_callback) - msg = ctypes.wintypes.MSG() - while ctypes.windll.user32.GetMessageW(ctypes.byref(msg), None, 0, 0): - pass - log.debug("Hook thread end") - keyhook.free() - - def hook_callback(self, **kwargs): - #Prevent disabling sending keys if another key is held down - if not self.sending_keys: - return False - keyCode = (kwargs['vk_code'], kwargs['extended']) - if not kwargs['pressed'] and keyCode in self.hostPendingModifiers: - self.hostPendingModifiers.discard(keyCode) - return False - gesture = KeyboardInputGesture(self.key_modifiers, keyCode[0], kwargs['scan_code'], keyCode[1]) - if gesture.isModifier: - if kwargs['pressed']: - self.key_modifiers.add(keyCode) - else: - self.key_modifiers.discard(keyCode) - elif kwargs['pressed']: - script = gesture.script - if self.ignoreGesture: - self.ignoreGesture = False - elif script in self.guestScripts: - wx.CallAfter(script, gesture) - return True - self.master_transport.send(type="key", **kwargs) - return True #Don't pass it on - - def set_receiving_braille(self, state): - if state and self.master_session.patch_callbacks_added and braille.handler.enabled: - self.master_session.patcher.patch_braille_input() - if buildVersion.version_year < 2023: - braille.handler.enabled = False - if braille.handler._cursorBlinkTimer: - braille.handler._cursorBlinkTimer.Stop() - braille.handler._cursorBlinkTimer=None - if braille.handler.buffer is braille.handler.messageBuffer: - braille.handler.buffer.clear() - braille.handler.buffer = braille.handler.mainBuffer - if braille.handler._messageCallLater: - braille.handler._messageCallLater.Stop() - braille.handler._messageCallLater = None - self.local_machine.receiving_braille=True - elif not state: - self.master_session.patcher.unpatch_braille_input() - if buildVersion.version_year < 2023: - braille.handler.enabled = bool(braille.handler.displaySize) - self.local_machine.receiving_braille=False - - def onSecureDesktopChange(self, isSecureDesktop: bool): - ''' - @param isSecureDesktop: True if the new desktop is the secure desktop. - ''' - if isSecureDesktop: - self.enter_secure_desktop() - else: - self.leave_secure_desktop() - - def event_gainFocus(self, obj, nextHandler): - if not hasattr(IAccessibleHandler, 'SecureDesktopNVDAObject'): - nextHandler() - return - if isinstance(obj, IAccessibleHandler.SecureDesktopNVDAObject): - self.sd_focused = True - self.enter_secure_desktop() - elif self.sd_focused and not isinstance(obj, IAccessibleHandler.SecureDesktopNVDAObject): - #event_leaveFocus won't work for some reason - self.sd_focused = False - self.leave_secure_desktop() - nextHandler() - - def enter_secure_desktop(self): - """function ran when entering a secure desktop.""" - if self.slave_transport is None: - return - if not os.path.exists(self.temp_location): - os.makedirs(self.temp_location) - channel = str(uuid.uuid4()) - self.sd_server = server.Server(port=0, password=channel, bind_host='127.0.0.1') - port = self.sd_server.server_socket.getsockname()[1] - server_thread = threading.Thread(target=self.sd_server.run) - server_thread.daemon = True - server_thread.start() - self.sd_relay = RelayTransport(address=('127.0.0.1', port), serializer=serializer.JSONSerializer(), channel=channel, insecure=True) - self.sd_relay.callback_manager.register_callback('msg_client_joined', self.on_master_display_change) - self.slave_transport.callback_manager.register_callback('msg_set_braille_info', self.on_master_display_change) - self.sd_bridge = bridge.BridgeTransport(self.slave_transport, self.sd_relay) - relay_thread = threading.Thread(target=self.sd_relay.run) - relay_thread.daemon = True - relay_thread.start() - data = [port, channel] - with open(self.ipc_file, 'w') as fp: - json.dump(data, fp) - - def leave_secure_desktop(self): - if self.sd_server is None: - return #Nothing to do - self.sd_bridge.disconnect() - self.sd_bridge = None - self.sd_server.close() - self.sd_server = None - self.sd_relay.close() - self.sd_relay = None - self.slave_transport.callback_manager.unregister_callback('msg_set_braille_info', self.on_master_display_change) - self.slave_session.set_display_size() - - def on_master_display_change(self, **kwargs): - self.sd_relay.send(type='set_display_size', sizes=self.slave_session.master_display_sizes) - - SD_CONNECT_BLOCK_TIMEOUT = 1 - def handle_secure_desktop(self): - try: - with open(self.ipc_file) as fp: - data = json.load(fp) - os.unlink(self.ipc_file) - port, channel = data - test_socket=socket.socket(socket.AF_INET, socket.SOCK_STREAM) - test_socket=wrap_socket(test_socket, ssl_version=ssl.PROTOCOL_TLS_CLIENT) - test_socket.connect(('127.0.0.1', port)) - test_socket.close() - self.connect_as_slave(('127.0.0.1', port), channel, insecure=True) - # So we don't miss the first output when switching to a secure desktop, - # block the main thread until the connection is established. We're - # connecting to localhost, so this should be pretty fast. Use a short - # timeout, though. - self.slave_transport.connected_event.wait(self.SD_CONNECT_BLOCK_TIMEOUT) - except: - pass - - def verify_connect(self, con_info): - if self.is_connected() or self.connecting: - gui.messageBox(_("TeleNVDA is already connected. Disconnect before opening a new connection."), _("TeleNVDA Already Connected"), wx.OK|wx.ICON_WARNING) - return - self.connecting = True - server_addr = con_info.get_address() - key = con_info.key - encryption_key = con_info.encryption_key - if con_info.mode == 'master': - message = _("Do you wish to control the machine on server {server} with key {key}?").format(server=server_addr, key=key) - elif con_info.mode == 'slave': - message = _("Do you wish to allow this machine to be controlled on server {server} with key {key}?").format(server=server_addr, key=key) - if gui.messageBox(message, _("TeleNVDA Connection Request"), wx.YES|wx.NO|wx.NO_DEFAULT|wx.ICON_WARNING) != wx.YES: - self.connecting = False - return - if con_info.mode == 'master': - self.connect_as_master((con_info.hostname, con_info.port), key=key, encryption_key=encryption_key) - elif con_info.mode == 'slave': - self.connect_as_slave((con_info.hostname, con_info.port), key=key, encryption_key=encryption_key) - self.connecting = False - - def is_connected(self): - connector = self.slave_transport or self.master_transport - if connector is not None: - return connector.connected - return False - - @script( - # Translators: Copy link compatible with NVDA Remote gesture description - description=_("Copies a link to the remote session to the clipboard compatible with both NVDA Remote and TeleNVDA"), - **speakOnDemand) - def script_copy_remote_link(self, gesture): - connector = self.slave_transport or self.master_transport - if not getattr(connector,'connected',False): - ui.message(_("Not connected.")) - return - self.on_copy_link_remote_item(None) - ui.message(_("Copied link")) - - @script( - # Translators: Copy link compatible with TeleNVDA gesture description - description=_("Copies a link to the remote session to the clipboard compatible only with TeleNVDA"), - **speakOnDemand) - def script_copy_tele_link(self, gesture): - connector = self.slave_transport or self.master_transport - if not getattr(connector,'connected',False): - ui.message(_("Not connected.")) - return - self.on_copy_link_tele_item(None) - ui.message(_("Copied link")) - - @script( - # Translators: description for the Connect gesture - _("""Opens a dialog to start a remote session"""), - gesture="kb:alt+NVDA+pageUp", - **speakOnDemand) - def script_connect(self, gesture): - if self.master_transport or self.slave_transport: - ui.message(_("TeleNVDA Already Connected")) - return - self.do_connect(None) - - @script( - # Translators: description for the Disconnect gesture - _("""Disconnect a remote session"""), - gesture="kb:alt+NVDA+pageDown", - **speakOnDemand) - def script_disconnect(self, gesture): - if self.master_transport is None and self.slave_transport is None: - ui.message(_("Not connected.")) - return - self.on_disconnect_item(None) - - @script( - # Translators: gesture description for the ignoreNextGesture script - _("""Set the host to ignore the next gesture completely, sending next gesture to the guest as is. Useful when you need to use the gesture asigned to toggle between guest and host, in the guest machine."""), - gesture = "kb:control+f11", - **speakOnDemand) - def script_ignoreNextGesture(self, gesture): - if not self.master_transport or not self.sending_keys: - return gesture.send() - self.ignoreGesture = True - # Translators: Report when the next gesture will be send to the guest ignoring everything else. - ui.message(_("Send next gesture to the guest")) - - @script( - # Translators: Documentation string for the script that toggles the control between guest and host machine. - description=_("Toggles the control between guest and host machine"), - gesture="kb:f11", - **speakOnDemand) - def script_sendKeys(self, gesture): - if not self.master_transport: - gesture.send() - return - self.sending_keys = not self.sending_keys - self.set_receiving_braille(self.sending_keys) - if self.sending_keys: - if buildVersion.version_year==2022 and buildVersion.version_major==4: - security.postSessionLockStateChanged.register(self.onSessionLockStateChange) - elif buildVersion.version_year>=2023: - security.post_sessionLockStateChanged.register(self.onSessionLockStateChange) - self.hostPendingModifiers = gesture.modifiers - # Translators: Presented when sending keyboard keys from the controlling computer to the controlled computer. - ui.message(_("Controlling remote machine.")) - if buildVersion.version_year >= 2025: - inputCore.decide_handleRawKey.register(self.handleRawKeys) - if configuration.get_config()['ui']['mute_when_controlling_local_machine'] and not self.muted: - # Only change this value if user didn't explicitly mute the remote machine - self.local_machine.is_muted = False - else: - # release all pressed keys in the guest. - for k in self.key_modifiers: - self.master_transport.send(type="key", vk_code=k[0], extended=k[1], pressed=False) - self.key_modifiers = set() - if buildVersion.version_year==2022 and buildVersion.version_major==4: - security.postSessionLockStateChanged.unregister(self.onSessionLockStateChange) - elif buildVersion.version_year>=2023: - security.post_sessionLockStateChanged.unregister(self.onSessionLockStateChange) - # Translators: Presented when keyboard control is back to the controlling computer. - ui.message(_("Controlling local machine.")) - if buildVersion.version_year >= 2025: - inputCore.decide_handleRawKey.unregister(self.handleRawKeys) - if configuration.get_config()['ui']['mute_when_controlling_local_machine'] and not self.muted: - self.local_machine.is_muted = True - - def handleRawKeys(self, vkCode, scanCode, extended, pressed): - keyCode = (vkCode, extended) - if not pressed and keyCode in self.hostPendingModifiers: - self.hostPendingModifiers.discard(keyCode) - return True - gesture = KeyboardInputGesture(self.key_modifiers, keyCode[0], scanCode, keyCode[1]) - if gesture.isModifier: - if pressed: - self.key_modifiers.add(keyCode) - else: - self.key_modifiers.discard(keyCode) - elif pressed: - script = gesture.script - if self.ignoreGesture: - self.ignoreGesture = False - elif script in self.guestScripts: - wx.CallAfter(script, gesture) - return False - self.master_transport.send(type="key", vk_code=vkCode, scan_code=scanCode, extended=extended, pressed=pressed) - return False - - def onSessionLockStateChange(self, isNowLocked): - if isNowLocked: - self.script_sendKeys(None) - - @script( - # Translators: gesture description for the toggle remote mute script - description=_("""Mute or unmute the speech coming from the remote computer"""), - **speakOnDemand) - def script_toggle_remote_mute(self, gesture): - if not self.is_connected() or self.connecting or self.slave_transport: return - self.on_mute_item(None) - - @script( - # Translators: send Ctrl+Alt+Delete gesture description - description=_("""Sends Ctrl+Alt+Delete to the remote machine"""), - **speakOnDemand) - def script_send_ctrl_alt_del(self, gesture): - if not self.is_connected() or self.connecting or self.slave_transport: return - self.on_send_ctrl_alt_del(None) - - @script( - # Translators: open addon settings gesture description - description=_("""Opens the addon settings panel inside NVDA settings dialog""")) - def script_options(self, gesture): - self.on_options_item(None) +import addonHandler +import api +import configobj +import core +import braille +import ctypes +import ctypes.wintypes +import globalVars +import gui +from gui import NVDASettingsDialog +import IAccessibleHandler +import json +import logging +import os +import queueHandler + +try: + from winAPI.secureDesktop import post_secureDesktopStateChange +except: + post_secureDesktopStateChange = None +try: + from utils import security +except: + pass +import buildVersion +import shlobj +import speech +import socket +import ssl +import sys +import threading +import ui +import uuid +import wx +import base64 +from config import conf as nvda_conf +from globalPluginHandler import GlobalPlugin as _GlobalPlugin +from keyboardHandler import KeyboardInputGesture +from logHandler import log +from scriptHandler import script +from winUser import WM_QUIT + +logger = logging.getLogger(__name__) + +from . import bridge +from . import configuration +from . import cues +from . import dialogs + +if buildVersion.version_year < 2025: + from . import keyboard_hook +else: + import inputCore +from . import local_machine +from . import serializer +from . import server +from . import url_handler +from .socket_utils import SERVER_PORT, address_to_hostport, hostport_to_address, wrap_socket +from .transport import RelayTransport, TransportEvents + +from .session import MasterSession, SlaveSession + +try: + addonHandler.initTranslation() +except addonHandler.AddonError: + log.warning( + "Unable to initialise translations. This may be because the addon is running from NVDA scratchpad.", + ) +speakOnDemand = {"speakOnDemand": True} if buildVersion.version_year >= 2024 else {} +if buildVersion.version_year < 2025: + logging.getLogger("keyboard_hook").addHandler(logging.StreamHandler(sys.stdout)) + +client = None + + +class GlobalPlugin(_GlobalPlugin): + # Translators: script category for add-on gestures + scriptCategory = _("TeleNVDA") + + def __init__(self, *args, **kwargs): + global client + super().__init__(*args, **kwargs) + for addon in addonHandler.getAvailableAddons(): + if addon.name == "remote" and not addon.isDisabled: + raise RuntimeError( + "TeleNVDA cannot be used while NVDA Remote is running. Please, disable NVDA Remote and restart NVDA." + ) + self.local_machine = local_machine.LocalMachine() + self.slave_session = None + self.master_session = None + self.create_menu() + NVDASettingsDialog.categoryClasses.append(dialogs.OptionsDialog) + self.connecting = False + self.muted = False # Used to know if mute remote was activated manually + self.url_handler_window = url_handler.URLHandlerWindow(callback=self.verify_connect) + url_handler.register_url_handler() + self.master_transport = None + self.slave_transport = None + self.server = None + self.hook_thread = None + self.sending_keys = False + self.key_modifiers = set() + self.hostPendingModifiers = set() + self.ignoreGesture = False + self.guestScripts = (self.script_sendKeys, self.script_ignoreNextGesture) + self.sd_server = None + self.sd_relay = None + self.sd_bridge = None + try: + configuration.get_config() + except configobj.ParseError: + os.remove( + os.path.abspath(os.path.join(globalVars.appArgs.configPath, configuration.CONFIG_FILE_NAME)) + ) + queueHandler.queueFunction( + queueHandler.eventQueue, + wx.CallAfter, + wx.MessageBox, + _("Your NVDA Remote configuration was corrupted and has been reset."), + _("NVDA Remote Configuration Error"), + wx.OK | wx.ICON_EXCLAMATION, + ) + if hasattr(shlobj, "SHGetKnownFolderPath"): + self.temp_location = os.path.join( + shlobj.SHGetKnownFolderPath(shlobj.FolderId.PROGRAM_DATA), "temp" + ) + else: + self.temp_location = os.path.join(shlobj.SHGetFolderPath(0, shlobj.CSIDL_COMMON_APPDATA), "temp") + self.ipc_file = os.path.join(self.temp_location, "remote.ipc") + self.sd_focused = False + if post_secureDesktopStateChange: + post_secureDesktopStateChange.register(self.onSecureDesktopChange) + if hasattr(globalVars, "teleNVDA"): + self.postStartupHandler() + core.postNvdaStartup.register(self.postStartupHandler) + globalVars.teleNVDA = None + client = self + + def postStartupHandler(self): + cs = configuration.get_config()["controlserver"] + if globalVars.appArgs.secure: + self.handle_secure_desktop() + if cs["autoconnect"] and not self.master_session and not self.slave_session: + wx.CallLater(50, self.perform_autoconnect) + + def perform_autoconnect(self): + cs = configuration.get_config()["controlserver"] + channel = cs["key"] + encryption_key = cs["encryption_key"] + if cs["self_hosted"]: + port = cs["port"] + address = ("localhost", port) + UPNP = cs["UPNP"] + self.start_control_server(port, channel, UPNP) + else: + address = address_to_hostport(cs["host"]) + if cs["connection_type"] == 0: + self.connect_as_slave(address, channel, encryption_key) + else: + self.connect_as_master(address, channel, encryption_key) + + def create_menu(self): + self.menu = wx.Menu() + tools_menu = gui.mainFrame.sysTrayIcon.toolsMenu + # Translators: Item in TeleNVDA submenu to connect to a remote computer. + self.connect_item = self.menu.Append( + wx.ID_ANY, + _("Connect..."), + _("Remotely connect to another computer running NVDA Remote Access or TeleNVDA"), + ) + gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.do_connect, self.connect_item) + # Translators: Item in TeleNVDA submenu to disconnect from a remote computer. + self.disconnect_item = self.menu.Append( + wx.ID_ANY, + _("Disconnect"), + _("Disconnect from another computer running NVDA Remote Access or TeleNVDA"), + ) + gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_disconnect_item, self.disconnect_item) + self.menu.Remove(self.disconnect_item.Id) + # Translators: Menu item in TeleNVDA submenu to mute speech and sounds from the remote computer. + self.mute_item = self.menu.Append( + wx.ID_ANY, _("Mute remote"), _("Mute speech and sounds from the remote computer") + ) + self.mute_item.Enable(False) + gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_mute_item, self.mute_item) + # Translators: Menu item in TeleNVDA submenu to push clipboard content to the remote computer. + self.push_clipboard_item = self.menu.Append( + wx.ID_ANY, _("&Push clipboard"), _("Push the clipboard to the other machine") + ) + self.push_clipboard_item.Enable(False) + gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_push_clipboard_item, self.push_clipboard_item) + # Translators: Menu item in TeleNVDA submenu to send a file to the remote computer. + self.send_file_item = self.menu.Append( + wx.ID_ANY, _("Send &file..."), _("Send a file to the other machine") + ) + self.send_file_item.Enable(False) + gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_send_file_item, self.send_file_item) + self.copyLinkMenu = wx.Menu() + # Translators: Menu item in TeleNVDA submenu to copy a link to the current session compatible with NVDA Remote. + self.copy_link_remote_item = self.copyLinkMenu.Append( + wx.ID_ANY, + _("NVDA &Remote protocol (recommended)"), + _("Copy a link to the remote session compatible with both NVDA Remote and TeleNVDA"), + ) + self.copy_link_remote_item.Enable(False) + gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_copy_link_remote_item, self.copy_link_remote_item) + # Translators: Menu item in TeleNVDA submenu to copy a link to the current session compatible with TeleNVDA. + self.copy_link_tele_item = self.copyLinkMenu.Append( + wx.ID_ANY, + _("&TeleNVDA protocol"), + _("Copy a link to the remote session compatible only with TeleNVDA"), + ) + self.copy_link_tele_item.Enable(False) + gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_copy_link_tele_item, self.copy_link_tele_item) + # Translators: Menu item in TeleNVDA submenu to copy a link to the current session. + self.copy_link_item = self.menu.AppendSubMenu( + self.copyLinkMenu, _("Copy &link"), _("Copy a link to the remote session") + ) + # Translators: Menu item in TeleNVDA submenu to open add-on options. + self.options_item = self.menu.Append(wx.ID_ANY, _("&Options..."), _("Options")) + gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_options_item, self.options_item) + # Translators: Menu item in TeleNVDA submenu to send Control+Alt+Delete to the remote computer. + self.send_ctrl_alt_del_item = self.menu.Append( + wx.ID_ANY, _("Send Ctrl+Alt+Del"), _("Send Ctrl+Alt+Del") + ) + gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.on_send_ctrl_alt_del, self.send_ctrl_alt_del_item) + self.send_ctrl_alt_del_item.Enable(False) + + # Translators: Label of menu in NVDA tools menu. + self.remote_item = tools_menu.AppendSubMenu(self.menu, _("R&emote"), _("TeleNVDA")) + + def terminate(self): + global client + if post_secureDesktopStateChange: + post_secureDesktopStateChange.unregister(self.onSecureDesktopChange) + self.disconnect() + self.local_machine.terminate() + self.local_machine = None + NVDASettingsDialog.categoryClasses.remove(dialogs.OptionsDialog) + self.copyLinkMenu.Remove(self.copy_link_remote_item.Id) + self.copy_link_remote_item.Destroy() + self.copy_link_remote_item = None + self.copyLinkMenu.Remove(self.copy_link_tele_item.Id) + self.copy_link_tele_item.Destroy() + self.copy_link_tele_item = None + try: + self.menu.Remove(self.connect_item.Id) + self.menu.Remove(self.disconnect_item.Id) + except: + pass + self.connect_item.Destroy() + self.connect_item = None + self.disconnect_item.Destroy() + self.disconnect_item = None + self.menu.Remove(self.mute_item.Id) + self.mute_item.Destroy() + self.mute_item = None + self.menu.Remove(self.push_clipboard_item.Id) + self.push_clipboard_item.Destroy() + self.push_clipboard_item = None + self.menu.Remove(self.send_file_item.Id) + self.send_file_item.Destroy() + self.send_file_item = None + self.menu.Remove(self.copy_link_item.Id) + self.copy_link_item.Destroy() + self.copy_link_item = None + self.menu.Remove(self.options_item.Id) + self.options_item.Destroy() + self.options_item = None + self.menu.Remove(self.send_ctrl_alt_del_item.Id) + self.send_ctrl_alt_del_item.Destroy() + self.send_ctrl_alt_del_item = None + tools_menu = gui.mainFrame.sysTrayIcon.toolsMenu + tools_menu.Remove(self.remote_item.Id) + self.remote_item.Destroy() + self.remote_item = None + try: + self.menu.Destroy() + self.copyLinkMenu.Destroy() + except (RuntimeError, AttributeError): + pass + try: + os.unlink(self.ipc_file) + except: + pass + self.menu = None + url_handler.unregister_url_handler() + self.url_handler_window.destroy() + self.url_handler_window = None + core.postNvdaStartup.unregister(self.postStartupHandler) + client = None + + def on_disconnect_item(self, evt): + if evt: + evt.Skip() + + def disconnect_as_slave_with_alert(): + if ( + self.slave_transport is not None + and configuration.get_config()["ui"]["alert_before_slave_disconnect"] + and not gui.message.isModalMessageBoxActive() + ): # Check if a modal message box is open + result = gui.messageBox( + # Translators: question before disconnecting + message=_("Are you sure you want to disconnect the controlled computer?"), + # Translators: question title + caption=_("Warning!"), + style=wx.YES | wx.NO | wx.ICON_WARNING, + ) + if result == wx.YES: + self.disconnect() + elif self.master_transport is not None or ( + self.slave_transport is not None + and not configuration.get_config()["ui"]["alert_before_slave_disconnect"] + ): + self.disconnect() + + wx.CallAfter(disconnect_as_slave_with_alert) + + def on_mute_item(self, evt): + if evt: + evt.Skip() + if not self.muted: + # Translators: Menu item in TeleNVDA submenu to unmute speech and sounds from the remote computer. + self.mute_item.SetItemLabel(_("Unmute remote")) + ui.message(_("Mute speech and sounds from the remote computer")) + if not configuration.get_config()["ui"]["mute_when_controlling_local_machine"]: + self.local_machine.is_muted = True + self.muted = True + else: + # Translators: Menu item in TeleNVDA submenu to mute speech and sounds from the remote computer. + self.mute_item.SetItemLabel(_("Mute remote")) + ui.message(_("Unmute speech and sounds from the remote computer")) + if not configuration.get_config()["ui"]["mute_when_controlling_local_machine"]: + self.local_machine.is_muted = False + self.muted = False + + def on_push_clipboard_item(self, evt): + connector = self.slave_transport or self.master_transport + try: + connector.send(type="set_clipboard_text", text=api.getClipData()) + cues.clipboard_pushed() + except TypeError: + log.exception("Unable to push clipboard") + + def on_send_file_item(self, evt): + connector = self.slave_transport or self.master_transport + if not getattr(connector, "connected", False): + ui.message(_("Not connected.")) + return + if globalVars.appArgs.secure: + return + # Check if a file dialog is already open + if getattr(self, "is_send_file_dialog_open", False): + return + # Set the flag to True, indicating that the file dialog is open + setattr(self, "is_send_file_dialog_open", True) + fd = wx.FileDialog( + gui.mainFrame, + # Translators: message displayed in transfer file dialog when sending a file + message=_("Choose the file you want to send to the remote computer"), + # Translators: supported file types when sending or receiving files + wildcard=_("All files (*.*)") + "|*.*", + defaultDir=os.environ["userprofile"], + style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_PREVIEW, + ) + if fd.ShowModal() != wx.ID_OK: + # Reset the flag to False after the file dialog is closed + setattr(self, "is_send_file_dialog_open", False) + return + # Reset the flag to False after the file dialog is closed + setattr(self, "is_send_file_dialog_open", False) + filename = os.path.basename(fd.GetPath()) + try: + f = open(fd.GetPath(), "rb") + file_content = f.read() + f.close() + except: + logger.exception("Unable to read the specified file") + if len(file_content) > 10485760: + gui.messageBox( + # Translators: error message when a file is too big + message=_("This file is too large. Only files smaller than 10 MB are supported."), + # Translators: error message caption + caption=_("Error"), + style=wx.ICON_ERROR, + ) + return + result = gui.messageBox( + # Translators: question before sending a file + message=_( + "The session will be blocked until the transfer is complete. Are you sure you want to continue?" + ), + # Translators: question title + caption=_("Warning!"), + style=wx.YES | wx.NO | wx.ICON_WARNING, + ) + if result == wx.YES: + file_content = base64.b64encode(file_content) + connector.send(type="file_transfer", name=filename, content=file_content.decode("utf-8")) + cues.clipboard_pushed() + # Translators: message spoken when the file has been sent successfully + ui.message(_("File sent")) + + @script( + # Translators: report number of connected computers gesture description + _("Reports number of computers connected to a session"), + **speakOnDemand, + ) + def script_reportConnectedClients(self, gesture): + session = self.master_session or self.slave_session + if not session: + ui.message(_("Not connected.")) + return + # TRANSLATORS: message reported when get number of clients gesture is pressed + ui.message( + ngettext( + "This is the only computer connected to this session", + "There are {} computers connected to this session", + session.client_count, + ).format(session.client_count) + ) + + @script( + # Translators: send file gesture description + _("Sends the specified file to the remote machine"), + gesture="kb:control+shift+NVDA+f", + **speakOnDemand, + ) + def script_send_file(self, gesture): + wx.CallAfter(self.on_send_file_item, None) + + @script( + # Translators: push clipboard gesture description + _("Sends the contents of the clipboard to the remote machine"), + gesture="kb:control+shift+NVDA+c", + **speakOnDemand, + ) + def script_push_clipboard(self, gesture): + connector = self.slave_transport or self.master_transport + if not getattr(connector, "connected", False): + ui.message(_("Not connected.")) + return + try: + connector.send(type="set_clipboard_text", text=api.getClipData()) + cues.clipboard_pushed() + ui.message(_("Clipboard pushed")) + except (TypeError, OSError): + ui.message(_("Unable to push clipboard")) + + def on_copy_link_remote_item(self, evt): + session = self.master_session or self.slave_session + url = session.get_connection_info().get_url_to_connect(0) + api.copyToClip(str(url)) + + def on_copy_link_tele_item(self, evt): + session = self.master_session or self.slave_session + url = session.get_connection_info().get_url_to_connect(1) + api.copyToClip(str(url)) + + def on_options_item(self, evt): + wx.CallAfter( + gui.mainFrame.popupSettingsDialog + if hasattr(gui.mainFrame, "popupSettingsDialog") + else gui.mainFrame._popupSettingsDialog, + gui.NVDASettingsDialog, + dialogs.OptionsDialog, + ) + evt.Skip() + + def on_send_ctrl_alt_del(self, evt): + self.master_transport.send("send_SAS") + # Translators: message spoken when the Ctrl+Alt+Delete has been sent to the remote machine successfully + ui.message(_("Ctrl+Alt+Delete has been sent to the remote machine")) + + def disconnect(self): + if self.master_transport is None and self.slave_transport is None: + return + if self.server is not None: + self.server.close() + self.server = None + if self.master_transport is not None: + self.disconnect_as_master() + if self.slave_transport is not None: + self.disconnect_as_slave() + # Translators: Presented when disconnected from the remote computer. + ui.message(_("Disconnected!")) + cues.disconnected() + if self.menu.FindItemById(self.disconnect_item.Id): + self.menu.Remove(self.disconnect_item.Id) + if not self.menu.FindItemById(self.connect_item.Id): + self.menu.Insert(0, self.connect_item) + self.push_clipboard_item.Enable(False) + self.send_file_item.Enable(False) + self.copy_link_remote_item.Enable(False) + self.copy_link_tele_item.Enable(False) + + def disconnect_as_master(self): + self.master_transport.close() + self.master_transport = None + self.master_session = None + + def disconnecting_as_master(self): + if self.menu: + if not self.menu.FindItemById(self.connect_item.Id): + self.menu.Insert(0, self.connect_item) + if self.menu.FindItemById(self.disconnect_item.Id): + self.menu.Remove(self.disconnect_item.Id) + # Translators: Menu item in TeleNVDA submenu to mute speech and sounds from the remote computer. + self.mute_item.SetItemLabel(_("Mute remote")) + self.mute_item.Enable(False) + self.push_clipboard_item.Enable(False) + self.send_file_item.Enable(False) + self.copy_link_remote_item.Enable(False) + self.copy_link_tele_item.Enable(False) + self.send_ctrl_alt_del_item.Enable(False) + if self.local_machine: + self.local_machine.is_muted = False + self.sending_keys = False + self.muted = False + if buildVersion.version_year < 2025: + if self.hook_thread is not None: + ctypes.windll.user32.PostThreadMessageW(self.hook_thread.ident, WM_QUIT, 0, 0) + self.hook_thread.join() + self.hook_thread = None + self.key_modifiers = set() + + def disconnect_as_slave(self): + self.slave_transport.close() + self.slave_transport = None + self.slave_session = None + + def on_connected_as_master_failed(self): + if self.master_transport.successful_connects == 0: + self.disconnect_as_master() + # Translators: Title of the connection error dialog. + gui.messageBox( + parent=gui.mainFrame, + caption=_("Error Connecting"), + # Translators: Message shown when cannot connect to the remote computer. + message=_("Unable to connect to the remote computer"), + style=wx.OK | wx.ICON_WARNING, + ) + + def do_connect(self, evt): + if evt: + evt.Skip() + # Check if the connect dialog is already open + if getattr(self, "is_connect_dialog_open", False): + return + # Set the flag to True, indicating that the connect dialog is open + setattr(self, "is_connect_dialog_open", True) + last_cons = configuration.get_config()["connections"]["last_connected"] + # Translators: Title of the connect dialog. + dlg = dialogs.DirectConnectDialog(parent=gui.mainFrame, id=wx.ID_ANY, title=_("Connect")) + dlg.panel.host.SetItems(list(reversed(last_cons))) + dlg.panel.host.SetSelection(0) + + def handle_dlg_complete(dlg_result): + if dlg_result != wx.ID_OK: + # Reset the flag to False when the dialog is closed + setattr(self, "is_connect_dialog_open", False) + return + if dlg.client_or_server.GetSelection() == 0: # client + host = dlg.panel.host.GetValue() + server_addr, port = address_to_hostport(host) + channel = dlg.panel.key.GetValue() + encryption_key = dlg.panel.encryption_key.GetValue() + if dlg.connection_type.GetSelection() == 0: + self.connect_as_master((server_addr, port), channel, encryption_key) + else: + self.connect_as_slave((server_addr, port), channel, encryption_key) + else: # We want a server + channel = dlg.panel.key.GetValue() + encryption_key = dlg.panel.encryption_key.GetValue() + self.start_control_server( + int(dlg.panel.port.GetValue()), channel, useUPNP=bool(dlg.panel.useUPNP.GetValue()) + ) + if dlg.connection_type.GetSelection() == 0: + self.connect_as_master( + ("127.0.0.1", int(dlg.panel.port.GetValue())), + channel, + insecure=True, + encryption_key=encryption_key, + ) + else: + self.connect_as_slave( + ("127.0.0.1", int(dlg.panel.port.GetValue())), + channel, + insecure=True, + encryption_key=encryption_key, + ) + # Reset the flag to False when the dialog is closed + setattr(self, "is_connect_dialog_open", False) + + gui.runScriptModalDialog(dlg, callback=handle_dlg_complete) + + def on_connected_as_master(self): + configuration.write_connection_to_config(self.master_transport.address) + if not self.menu.FindItemById(self.disconnect_item.Id): + self.menu.Insert(0, self.disconnect_item) + if self.menu.FindItemById(self.connect_item.Id): + self.menu.Remove(self.connect_item.Id) + self.mute_item.Enable(True) + self.push_clipboard_item.Enable(True) + if not globalVars.appArgs.secure: + self.send_file_item.Enable(True) + self.copy_link_remote_item.Enable(True) + self.copy_link_tele_item.Enable(True) + self.send_ctrl_alt_del_item.Enable(True) + if buildVersion.version_year < 2025: + # We might have already created a hook thread before if we're restoring an + # interrupted connection. We must not create another. + if not self.hook_thread: + self.hook_thread = threading.Thread(target=self.hook) + self.hook_thread.daemon = True + self.hook_thread.start() + # Translators: Presented when connected to the remote computer. + ui.message(_("Connected!")) + cues.connected() + if configuration.get_config()["ui"]["mute_when_controlling_local_machine"] and not self.sending_keys: + self.local_machine.is_muted = True + + def on_disconnected_as_master(self): + # Translators: Presented when connection to a remote computer was interupted. + ui.message(_("Connection interrupted")) + + def connect_as_master(self, address, key, encryption_key, insecure=False): + transport = RelayTransport( + address=address, + serializer=serializer.JSONSerializer(), + channel=key, + connection_type="master", + insecure=insecure, + encryption_key=encryption_key, + ) + self.master_session = MasterSession(transport=transport, local_machine=self.local_machine) + transport.callback_manager.register_callback( + TransportEvents.CERTIFICATE_AUTHENTICATION_FAILED, self.on_certificate_as_master_failed + ) + transport.callback_manager.register_callback(TransportEvents.CONNECTED, self.on_connected_as_master) + transport.callback_manager.register_callback( + TransportEvents.CONNECTION_FAILED, self.on_connected_as_master_failed + ) + transport.callback_manager.register_callback(TransportEvents.CLOSING, self.disconnecting_as_master) + transport.callback_manager.register_callback( + TransportEvents.DISCONNECTED, self.on_disconnected_as_master + ) + self.master_transport = transport + self.master_transport.reconnector_thread.start() + + def connect_as_slave(self, address, key, encryption_key, insecure=False): + if ( + not nvda_conf["keyboard"]["handleInjectedKeys"] + and gui.messageBox( + # Translators: A message to warn the user that handle keys from other applications should be on. + message=_( + "The option to handle keys from other applications is disabled in your NVDA keyboard settings. In order to allow the keyboard of this machine to be controlled, this option should be enabled. Would you like to do this now?" + ), + # Translators: The title of the warning dialog displayed when handle keys from other applications is disabled. + caption=_("Warning"), + style=wx.YES | wx.NO | wx.ICON_WARNING, + ) + == wx.YES + ): + nvda_conf["keyboard"]["handleInjectedKeys"] = True + transport = RelayTransport( + serializer=serializer.JSONSerializer(), + address=address, + channel=key, + connection_type="slave", + insecure=insecure, + encryption_key=encryption_key, + ) + self.slave_session = SlaveSession(transport=transport, local_machine=self.local_machine) + self.slave_transport = transport + transport.callback_manager.register_callback( + TransportEvents.CERTIFICATE_AUTHENTICATION_FAILED, self.on_certificate_as_slave_failed + ) + self.slave_transport.callback_manager.register_callback( + TransportEvents.CONNECTED, self.on_connected_as_slave + ) + self.slave_transport.reconnector_thread.start() + if not self.menu.FindItemById(self.disconnect_item.Id): + self.menu.Insert(0, self.disconnect_item) + if self.menu.FindItemById(self.connect_item.Id): + self.menu.Remove(self.connect_item.Id) + + def handle_certificate_failed(self, transport): + self.last_fail_address = transport.address + self.last_fail_key = transport.channel + self.disconnect() + try: + cert_hash = transport.last_fail_fingerprint + wnd = dialogs.CertificateUnauthorizedDialog(None, fingerprint=cert_hash) + a = wnd.ShowModal() + if a == wx.ID_YES: + config = configuration.get_config() + config["trusted_certs"][hostport_to_address(self.last_fail_address)] = cert_hash + config.write() + if a == wx.ID_YES or a == wx.ID_NO: + return True + except Exception as ex: + log.error(ex) + return False + + def on_certificate_as_master_failed(self): + if self.handle_certificate_failed(self.master_transport): + self.connect_as_master(self.last_fail_address, self.last_fail_key, True) + + def on_certificate_as_slave_failed(self): + if self.handle_certificate_failed(self.slave_transport): + self.connect_as_slave(self.last_fail_address, self.last_fail_key, True) + + def on_connected_as_slave(self): + log.info("Control connector connected") + cues.control_server_connected() + # Translators: Presented in direct (client to server) remote connection when the controlled computer is ready. + speech.speakMessage(_("Connected to control server")) + self.push_clipboard_item.Enable(True) + if not globalVars.appArgs.secure: + self.send_file_item.Enable(True) + self.copy_link_remote_item.Enable(True) + self.copy_link_tele_item.Enable(True) + configuration.write_connection_to_config(self.slave_transport.address) + + def start_control_server(self, server_port, channel, useUPNP=False): + self.server = server.Server(server_port, channel, UPNP=useUPNP) + server_thread = threading.Thread(target=self.server.run) + server_thread.daemon = True + server_thread.start() + + def hook(self): + log.debug("Hook thread start") + keyhook = keyboard_hook.KeyboardHook() + keyhook.register_callback(self.hook_callback) + msg = ctypes.wintypes.MSG() + while ctypes.windll.user32.GetMessageW(ctypes.byref(msg), None, 0, 0): + pass + log.debug("Hook thread end") + keyhook.free() + + def hook_callback(self, **kwargs): + # Prevent disabling sending keys if another key is held down + if not self.sending_keys: + return False + keyCode = (kwargs["vk_code"], kwargs["extended"]) + if not kwargs["pressed"] and keyCode in self.hostPendingModifiers: + self.hostPendingModifiers.discard(keyCode) + return False + gesture = KeyboardInputGesture(self.key_modifiers, keyCode[0], kwargs["scan_code"], keyCode[1]) + if gesture.isModifier: + if kwargs["pressed"]: + self.key_modifiers.add(keyCode) + else: + self.key_modifiers.discard(keyCode) + elif kwargs["pressed"]: + script = gesture.script + if self.ignoreGesture: + self.ignoreGesture = False + elif script in self.guestScripts: + wx.CallAfter(script, gesture) + return True + self.master_transport.send(type="key", **kwargs) + return True # Don't pass it on + + def set_receiving_braille(self, state): + if state and self.master_session.patch_callbacks_added and braille.handler.enabled: + self.master_session.patcher.patch_braille_input() + if buildVersion.version_year < 2023: + braille.handler.enabled = False + if braille.handler._cursorBlinkTimer: + braille.handler._cursorBlinkTimer.Stop() + braille.handler._cursorBlinkTimer = None + if braille.handler.buffer is braille.handler.messageBuffer: + braille.handler.buffer.clear() + braille.handler.buffer = braille.handler.mainBuffer + if braille.handler._messageCallLater: + braille.handler._messageCallLater.Stop() + braille.handler._messageCallLater = None + self.local_machine.receiving_braille = True + elif not state: + self.master_session.patcher.unpatch_braille_input() + if buildVersion.version_year < 2023: + braille.handler.enabled = bool(braille.handler.displaySize) + self.local_machine.receiving_braille = False + + def onSecureDesktopChange(self, isSecureDesktop: bool): + """ + @param isSecureDesktop: True if the new desktop is the secure desktop. + """ + if isSecureDesktop: + self.enter_secure_desktop() + else: + self.leave_secure_desktop() + + def event_gainFocus(self, obj, nextHandler): + if not hasattr(IAccessibleHandler, "SecureDesktopNVDAObject"): + nextHandler() + return + if isinstance(obj, IAccessibleHandler.SecureDesktopNVDAObject): + self.sd_focused = True + self.enter_secure_desktop() + elif self.sd_focused and not isinstance(obj, IAccessibleHandler.SecureDesktopNVDAObject): + # event_leaveFocus won't work for some reason + self.sd_focused = False + self.leave_secure_desktop() + nextHandler() + + def enter_secure_desktop(self): + """function ran when entering a secure desktop.""" + if self.slave_transport is None: + return + if not os.path.exists(self.temp_location): + os.makedirs(self.temp_location) + channel = str(uuid.uuid4()) + self.sd_server = server.Server(port=0, password=channel, bind_host="127.0.0.1") + port = self.sd_server.server_socket.getsockname()[1] + server_thread = threading.Thread(target=self.sd_server.run) + server_thread.daemon = True + server_thread.start() + self.sd_relay = RelayTransport( + address=("127.0.0.1", port), + serializer=serializer.JSONSerializer(), + channel=channel, + insecure=True, + ) + self.sd_relay.callback_manager.register_callback("msg_client_joined", self.on_master_display_change) + self.slave_transport.callback_manager.register_callback( + "msg_set_braille_info", self.on_master_display_change + ) + self.sd_bridge = bridge.BridgeTransport(self.slave_transport, self.sd_relay) + relay_thread = threading.Thread(target=self.sd_relay.run) + relay_thread.daemon = True + relay_thread.start() + data = [port, channel] + with open(self.ipc_file, "w") as fp: + json.dump(data, fp) + + def leave_secure_desktop(self): + if self.sd_server is None: + return # Nothing to do + self.sd_bridge.disconnect() + self.sd_bridge = None + self.sd_server.close() + self.sd_server = None + self.sd_relay.close() + self.sd_relay = None + self.slave_transport.callback_manager.unregister_callback( + "msg_set_braille_info", self.on_master_display_change + ) + self.slave_session.set_display_size() + + def on_master_display_change(self, **kwargs): + self.sd_relay.send(type="set_display_size", sizes=self.slave_session.master_display_sizes) + + SD_CONNECT_BLOCK_TIMEOUT = 1 + + def handle_secure_desktop(self): + try: + with open(self.ipc_file) as fp: + data = json.load(fp) + os.unlink(self.ipc_file) + port, channel = data + test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + test_socket = wrap_socket(test_socket, ssl_version=ssl.PROTOCOL_TLS_CLIENT) + test_socket.connect(("127.0.0.1", port)) + test_socket.close() + self.connect_as_slave(("127.0.0.1", port), channel, insecure=True) + # So we don't miss the first output when switching to a secure desktop, + # block the main thread until the connection is established. We're + # connecting to localhost, so this should be pretty fast. Use a short + # timeout, though. + self.slave_transport.connected_event.wait(self.SD_CONNECT_BLOCK_TIMEOUT) + except: + pass + + def verify_connect(self, con_info): + if self.is_connected() or self.connecting: + gui.messageBox( + _("TeleNVDA is already connected. Disconnect before opening a new connection."), + _("TeleNVDA Already Connected"), + wx.OK | wx.ICON_WARNING, + ) + return + self.connecting = True + server_addr = con_info.get_address() + key = con_info.key + encryption_key = con_info.encryption_key + if con_info.mode == "master": + message = _("Do you wish to control the machine on server {server} with key {key}?").format( + server=server_addr, key=key + ) + elif con_info.mode == "slave": + message = _( + "Do you wish to allow this machine to be controlled on server {server} with key {key}?" + ).format(server=server_addr, key=key) + if ( + gui.messageBox( + message, _("TeleNVDA Connection Request"), wx.YES | wx.NO | wx.NO_DEFAULT | wx.ICON_WARNING + ) + != wx.YES + ): + self.connecting = False + return + if con_info.mode == "master": + self.connect_as_master((con_info.hostname, con_info.port), key=key, encryption_key=encryption_key) + elif con_info.mode == "slave": + self.connect_as_slave((con_info.hostname, con_info.port), key=key, encryption_key=encryption_key) + self.connecting = False + + def is_connected(self): + connector = self.slave_transport or self.master_transport + if connector is not None: + return connector.connected + return False + + @script( + # Translators: Copy link compatible with NVDA Remote gesture description + description=_( + "Copies a link to the remote session to the clipboard compatible with both NVDA Remote and TeleNVDA" + ), + **speakOnDemand, + ) + def script_copy_remote_link(self, gesture): + connector = self.slave_transport or self.master_transport + if not getattr(connector, "connected", False): + ui.message(_("Not connected.")) + return + self.on_copy_link_remote_item(None) + ui.message(_("Copied link")) + + @script( + # Translators: Copy link compatible with TeleNVDA gesture description + description=_("Copies a link to the remote session to the clipboard compatible only with TeleNVDA"), + **speakOnDemand, + ) + def script_copy_tele_link(self, gesture): + connector = self.slave_transport or self.master_transport + if not getattr(connector, "connected", False): + ui.message(_("Not connected.")) + return + self.on_copy_link_tele_item(None) + ui.message(_("Copied link")) + + @script( + # Translators: description for the Connect gesture + _("""Opens a dialog to start a remote session"""), + gesture="kb:alt+NVDA+pageUp", + **speakOnDemand, + ) + def script_connect(self, gesture): + if self.master_transport or self.slave_transport: + ui.message(_("TeleNVDA Already Connected")) + return + self.do_connect(None) + + @script( + # Translators: description for the Disconnect gesture + _("""Disconnect a remote session"""), + gesture="kb:alt+NVDA+pageDown", + **speakOnDemand, + ) + def script_disconnect(self, gesture): + if self.master_transport is None and self.slave_transport is None: + ui.message(_("Not connected.")) + return + self.on_disconnect_item(None) + + @script( + # Translators: gesture description for the ignoreNextGesture script + _( + """Set the host to ignore the next gesture completely, sending next gesture to the guest as is. Useful when you need to use the gesture asigned to toggle between guest and host, in the guest machine.""" + ), + gesture="kb:control+f11", + **speakOnDemand, + ) + def script_ignoreNextGesture(self, gesture): + if not self.master_transport or not self.sending_keys: + return gesture.send() + self.ignoreGesture = True + # Translators: Report when the next gesture will be send to the guest ignoring everything else. + ui.message(_("Send next gesture to the guest")) + + @script( + # Translators: Documentation string for the script that toggles the control between guest and host machine. + description=_("Toggles the control between guest and host machine"), + gesture="kb:f11", + **speakOnDemand, + ) + def script_sendKeys(self, gesture): + if not self.master_transport: + gesture.send() + return + self.sending_keys = not self.sending_keys + self.set_receiving_braille(self.sending_keys) + if self.sending_keys: + if buildVersion.version_year == 2022 and buildVersion.version_major == 4: + security.postSessionLockStateChanged.register(self.onSessionLockStateChange) + elif buildVersion.version_year >= 2023: + security.post_sessionLockStateChanged.register(self.onSessionLockStateChange) + self.hostPendingModifiers = gesture.modifiers + # Translators: Presented when sending keyboard keys from the controlling computer to the controlled computer. + ui.message(_("Controlling remote machine.")) + if buildVersion.version_year >= 2025: + inputCore.decide_handleRawKey.register(self.handleRawKeys) + if configuration.get_config()["ui"]["mute_when_controlling_local_machine"] and not self.muted: + # Only change this value if user didn't explicitly mute the remote machine + self.local_machine.is_muted = False + else: + # release all pressed keys in the guest. + for k in self.key_modifiers: + self.master_transport.send(type="key", vk_code=k[0], extended=k[1], pressed=False) + self.key_modifiers = set() + if buildVersion.version_year == 2022 and buildVersion.version_major == 4: + security.postSessionLockStateChanged.unregister(self.onSessionLockStateChange) + elif buildVersion.version_year >= 2023: + security.post_sessionLockStateChanged.unregister(self.onSessionLockStateChange) + # Translators: Presented when keyboard control is back to the controlling computer. + ui.message(_("Controlling local machine.")) + if buildVersion.version_year >= 2025: + inputCore.decide_handleRawKey.unregister(self.handleRawKeys) + if configuration.get_config()["ui"]["mute_when_controlling_local_machine"] and not self.muted: + self.local_machine.is_muted = True + + def handleRawKeys(self, vkCode, scanCode, extended, pressed): + keyCode = (vkCode, extended) + if not pressed and keyCode in self.hostPendingModifiers: + self.hostPendingModifiers.discard(keyCode) + return True + gesture = KeyboardInputGesture(self.key_modifiers, keyCode[0], scanCode, keyCode[1]) + if gesture.isModifier: + if pressed: + self.key_modifiers.add(keyCode) + else: + self.key_modifiers.discard(keyCode) + elif pressed: + script = gesture.script + if self.ignoreGesture: + self.ignoreGesture = False + elif script in self.guestScripts: + wx.CallAfter(script, gesture) + return False + self.master_transport.send( + type="key", vk_code=vkCode, scan_code=scanCode, extended=extended, pressed=pressed + ) + return False + + def onSessionLockStateChange(self, isNowLocked): + if isNowLocked: + self.script_sendKeys(None) + + @script( + # Translators: gesture description for the toggle remote mute script + description=_("""Mute or unmute the speech coming from the remote computer"""), + **speakOnDemand, + ) + def script_toggle_remote_mute(self, gesture): + if not self.is_connected() or self.connecting or self.slave_transport: + return + self.on_mute_item(None) + + @script( + # Translators: send Ctrl+Alt+Delete gesture description + description=_("""Sends Ctrl+Alt+Delete to the remote machine"""), + **speakOnDemand, + ) + def script_send_ctrl_alt_del(self, gesture): + if not self.is_connected() or self.connecting or self.slave_transport: + return + self.on_send_ctrl_alt_del(None) + + @script( + # Translators: open addon settings gesture description + description=_("""Opens the addon settings panel inside NVDA settings dialog"""), + ) + def script_options(self, gesture): + self.on_options_item(None) diff --git a/addon/globalPlugins/remoteClient/configuration.py b/addon/globalPlugins/remoteClient/configuration.py index 3d731767..e21a2277 100644 --- a/addon/globalPlugins/remoteClient/configuration.py +++ b/addon/globalPlugins/remoteClient/configuration.py @@ -1,58 +1,64 @@ -from io import StringIO -import os -import configobj -from configobj import validate -import globalVars -from . import socket_utils -readonly = globalVars.appArgs.secure or globalVars.appArgs.launcher - -CONFIG_FILE_NAME = 'teleNVDA.ini' - -_config = None -configspec = StringIO(""" -[connections] - last_connected = list(default=list("remote.nvda.es")) -[controlserver] - autoconnect = boolean(default=False) - self_hosted = boolean(default=False) - UPNP = boolean(default=False) - connection_type = integer(default=0) - host = string(default="remote.nvda.es") - port = integer(default=6837) - key = string(default="") - encryption_key = string(default="") - -[seen_motds] - __many__ = string(default="") - -[trusted_certs] - __many__ = string(default="") - -[ui] - play_sounds = boolean(default=True) - alert_before_slave_disconnect = boolean(default=True) - mute_when_controlling_local_machine = boolean(default=False) - allow_speech_commands = boolean(default=True) - display_motd_once = boolean(default=False) - portcheck = string(default="https://nvda.es/portcheck.php?port={port}") -""") -def get_config(): - global _config - if not _config: - path = os.path.abspath(os.path.join(globalVars.appArgs.configPath, CONFIG_FILE_NAME)) - _config = configobj.ConfigObj(infile=path, configspec=configspec, default_encoding='utf8', create_empty=not readonly) - val = validate.Validator() - _config.validate(val, copy=True) - return _config - -def write_connection_to_config(address): - """Writes an address to the last connected section of the config. - If the address is already in the config, move it to the end.""" - conf = get_config() - last_cons = conf['connections']['last_connected'] - address = socket_utils.hostport_to_address(address) - if address in last_cons: - conf['connections']['last_connected'].remove(address) - conf['connections']['last_connected'].append(address) - if not readonly: - conf.write() +from io import StringIO +import os +import configobj +from configobj import validate +import globalVars +from . import socket_utils + +readonly = globalVars.appArgs.secure or globalVars.appArgs.launcher + +CONFIG_FILE_NAME = "teleNVDA.ini" + +_config = None +configspec = StringIO(""" +[connections] + last_connected = list(default=list("remote.nvda.es")) +[controlserver] + autoconnect = boolean(default=False) + self_hosted = boolean(default=False) + UPNP = boolean(default=False) + connection_type = integer(default=0) + host = string(default="remote.nvda.es") + port = integer(default=6837) + key = string(default="") + encryption_key = string(default="") + +[seen_motds] + __many__ = string(default="") + +[trusted_certs] + __many__ = string(default="") + +[ui] + play_sounds = boolean(default=True) + alert_before_slave_disconnect = boolean(default=True) + mute_when_controlling_local_machine = boolean(default=False) + allow_speech_commands = boolean(default=True) + display_motd_once = boolean(default=False) + portcheck = string(default="https://nvda.es/portcheck.php?port={port}") +""") + + +def get_config(): + global _config + if not _config: + path = os.path.abspath(os.path.join(globalVars.appArgs.configPath, CONFIG_FILE_NAME)) + _config = configobj.ConfigObj( + infile=path, configspec=configspec, default_encoding="utf8", create_empty=not readonly + ) + val = validate.Validator() + _config.validate(val, copy=True) + return _config + + +def write_connection_to_config(address): + """Writes an address to the last connected section of the config. + If the address is already in the config, move it to the end.""" + conf = get_config() + last_cons = conf["connections"]["last_connected"] + address = socket_utils.hostport_to_address(address) + if address in last_cons: + conf["connections"]["last_connected"].remove(address) + conf["connections"]["last_connected"].append(address) + if not readonly: + conf.write() diff --git a/addon/globalPlugins/remoteClient/connection_info.py b/addon/globalPlugins/remoteClient/connection_info.py index f0228ad2..d9c016ce 100644 --- a/addon/globalPlugins/remoteClient/connection_info.py +++ b/addon/globalPlugins/remoteClient/connection_info.py @@ -26,9 +26,9 @@ def from_url(cls, url): parsed_query = parse_qs(parsed_url.query) hostname = parsed_url.hostname port = parsed_url.port - key = parsed_query.get('key', [""])[0] - encryption_key = parsed_query.get('encryption_key', [""])[0] - mode = parsed_query.get('mode', [""])[0].lower() + key = parsed_query.get("key", [""])[0] + encryption_key = parsed_query.get("encryption_key", [""])[0] + mode = parsed_query.get("mode", [""])[0].lower() if not hostname: raise URLParsingError("No hostname provided") if not key: @@ -43,7 +43,14 @@ def from_url(cls, url): return cls(hostname=hostname, mode=mode, key=key, port=port) def __repr__(self): - return "{classname} (hostname={hostname}, port={port}, mode={mode}, key={key}, encryption_key={encryption_key})".format(classname=self.__class__.__name__, hostname=self.hostname, port=self.port, mode=self.mode, key=self.key, encryption_key=self.encryption_key) + return "{classname} (hostname={hostname}, port={port}, mode={mode}, key={key}, encryption_key={encryption_key})".format( + classname=self.__class__.__name__, + hostname=self.hostname, + port=self.port, + mode=self.mode, + key=self.key, + encryption_key=self.encryption_key, + ) def get_address(self): hostname = self.hostname if ":" not in self.hostname else "[" + self.hostname + "]" @@ -53,10 +60,10 @@ def get_url_to_connect(self, protocol): result = URL_PREFIX[protocol] + socket_utils.hostport_to_address((self.hostname, self.port)) result += "?" mode = self.mode - if mode == 'master': - mode = 'slave' - elif mode == 'slave': - mode = 'master' + if mode == "master": + mode = "slave" + elif mode == "slave": + mode = "master" if self.encryption_key: result += urlencode(dict(key=self.key, encryption_key=self.encryption_key, mode=mode)) else: diff --git a/addon/globalPlugins/remoteClient/dialogs.py b/addon/globalPlugins/remoteClient/dialogs.py index 553c46f3..ffd47a69 100644 --- a/addon/globalPlugins/remoteClient/dialogs.py +++ b/addon/globalPlugins/remoteClient/dialogs.py @@ -1,447 +1,528 @@ -import json -import random -import threading -from urllib import request -import wx -import gui -from gui.settingsDialogs import SettingsPanel -from . import serializer -from . import server -from . import transport -from . import socket_utils -from logHandler import log -import addonHandler -try: - addonHandler.initTranslation() -except addonHandler.AddonError: - log.warning( - "Unable to initialise translations. This may be because the addon is running from NVDA scratchpad." - ) -from . import configuration -import config as NVDAConfig -import os -import sys -sys.path.append(os.path.dirname(__file__)) -import miniupnpc -del sys.path[-1] - - -WX_VERSION = int(wx.version()[0]) -WX_CENTER = wx.Center if WX_VERSION>=4 else wx.CENTER_ON_SCREEN - -class ClientPanel(wx.Panel): - - def __init__(self, parent=None, id=wx.ID_ANY): - super().__init__(parent, id) - sizer = wx.BoxSizer(wx.HORIZONTAL) - # Translators: The label of an edit field in connect dialog to enter name or address of the remote computer. - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Host:"))) - self.host = wx.ComboBox(self, wx.ID_ANY) - sizer.Add(self.host) - # Translators: Label of the edit field to enter key (password) to secure the remote connection. - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Key:"))) - self.key = wx.TextCtrl(self, wx.ID_ANY) - sizer.Add(self.key) - # Translators: The button used to generate a random key/password. - self.generate_key = wx.Button(parent=self, label=_("&Generate Key")) - self.generate_key.Bind(wx.EVT_BUTTON, self.on_generate_key) - sizer.Add(self.generate_key) - # Translators: Label of an edit field to enter a second password to exchange encrypted data. - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("En&cryption password (optional):"))) - self.encryption_key = wx.TextCtrl(self, wx.ID_ANY) - sizer.Add(self.encryption_key) - self.SetSizerAndFit(sizer) - - def on_generate_key(self, evt): - if not self.host.GetValue(): - gui.messageBox(_("Host must be set."), _("Error"), wx.OK | wx.ICON_ERROR) - self.host.SetFocus() - else: - evt.Skip() - self.generate_key_command() - - def generate_key_command(self, insecure=False): - address = socket_utils.address_to_hostport(self.host.GetValue()) - self.key_connector = transport.RelayTransport(address=address, serializer=serializer.JSONSerializer(), insecure=insecure) - self.key_connector.callback_manager.register_callback('msg_generate_key', self.handle_key_generated) - self.key_connector.callback_manager.register_callback(transport.TransportEvents.CERTIFICATE_AUTHENTICATION_FAILED, self.handle_certificate_failed) - t = threading.Thread(target=self.key_connector.run) - t.start() - - def handle_key_generated(self, key=None): - self.key.SetValue(key) - self.key.SetFocus() - self.key_connector.close() - self.key_connector = None - - def handle_certificate_failed(self): - try: - cert_hash = self.key_connector.last_fail_fingerprint - - wnd = CertificateUnauthorizedDialog(None, fingerprint=cert_hash) - a = wnd.ShowModal() - if a == wx.ID_YES: - config = configuration.get_config() - config['trusted_certs'][self.host.GetValue()]=cert_hash - if not config.readonly: - config.write() - if a != wx.ID_YES and a != wx.ID_NO: return - except Exception as ex: - log.error(ex) - return - self.key_connector.close() - self.key_connector = None - self.generate_key_command(True) - -class ServerPanel(wx.Panel): - - def __init__(self, parent=None, id=wx.ID_ANY): - super().__init__(parent, id) - sizer = wx.BoxSizer(wx.HORIZONTAL) - # Translators: Used in server mode to obtain the external IP address for the server (controlled computer) for direct connection. - self.get_IP = wx.Button(parent=self, label=_("Get External &IP")) - self.get_IP.Bind(wx.EVT_BUTTON, self.on_get_IP) - sizer.Add(self.get_IP) - # Translators: Label of the field displaying the external IP address if using direct (client to server) connection. - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&External IP:"))) - self.external_IP = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_READONLY|wx.TE_MULTILINE) - sizer.Add(self.external_IP) - # Translators: The label of an edit field in connect dialog to enter the port the server will listen on. - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Port:"))) - self.port = wx.SpinCtrl(self, wx.ID_ANY, min=1, max=65535, value=str(socket_utils.SERVER_PORT)) - sizer.Add(self.port) - # Translators: label of a checkbox which allows forwarding a port using UPNP - self.useUPNP = wx.CheckBox(self, wx.ID_ANY, label=_("Use &UPNP to forward this port if possible")) - sizer.Add(self.useUPNP) - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Key:"))) - self.key = wx.TextCtrl(self, wx.ID_ANY) - sizer.Add(self.key) - self.generate_key = wx.Button(parent=self, label=_("&Generate Key")) - self.generate_key.Bind(wx.EVT_BUTTON, self.on_generate_key) - sizer.Add(self.generate_key) - # Translators: Label of an edit field to enter a second password to exchange encrypted data. - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("En&cryption password (optional):"))) - self.encryption_key = wx.TextCtrl(self, wx.ID_ANY) - sizer.Add(self.encryption_key) - self.SetSizerAndFit(sizer) - - def on_generate_key(self, evt): - evt.Skip() - res = str(random.randrange(1, 9)) - for n in range(6): - res += str(random.randrange(0, 9)) - self.key.SetValue(res) - self.key.SetFocus() - - def on_get_IP(self, evt): - evt.Skip() - self.get_IP.Enable(False) - result = gui.messageBox( - # Translators: message asking the user wether perform portcheck with UPNP or not - _("Would you like to use UPNP to forward the chosen port before detecting your IP address?"), - # Translators: title of the message asking the user to try portcheck with UPNP - _("Do you want to use UPNP?"), - wx.YES_NO|wx.ICON_QUESTION, self) - if result==wx.YES: - t = threading.Thread(target=self.do_portcheck, args=[int(self.port.GetValue()), True]) - else: - t = threading.Thread(target=self.do_portcheck, args=[int(self.port.GetValue())]) - t.daemon = True - t.start() - - def do_portcheck(self, port, UPNP=False): - config = configuration.get_config() - if UPNP: - try: - upnp = miniupnpc.UPnP() - upnp.discoverdelay = 200 - upnp.discover() - upnp.selectigd() - upnp.addportmapping(port, 'TCP', upnp.lanaddr, port, 'TeleNVDA', '', 60) - except Exception as e: - self.on_get_IP_fail(e) - self.get_IP.Enable(True) - raise - temp_server = server.Server(port=port, password=None) - try: - Headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' } - p = request.Request(config['ui']['portcheck'].format(port=port), headers=Headers, method="GET") - req = request.urlopen(p) - data = req.read() - result = json.loads(data) - wx.CallAfter(self.on_get_IP_success, result) - except Exception as e: - self.on_get_IP_fail(e) - raise - finally: - temp_server.close() - self.get_IP.Enable(True) - if UPNP: - upnp.deleteportmapping(port, 'TCP') - - def on_get_IP_success(self, data): - ip = data['host'] - port = data['port'] - is_open = data['open'] - if is_open: - gui.messageBox(message=_("Successfully retrieved IP address. Port {port} is open.").format(port=port), caption=_("Success"), style=wx.OK) - else: - gui.messageBox(message=_("Retrieved external IP, but port {port} is not currently forwarded.").format(port=port), caption=_("Warning"), style=wx.ICON_WARNING|wx.OK) - self.external_IP.SetValue(ip) - self.external_IP.SetSelection(0, len(ip)) - self.external_IP.SetFocus() - - - def on_get_IP_fail(self, exc): - gui.messageBox(message=_("Unable to contact portcheck server or UPNP device, please manually retrieve your IP address and forward ports if required. See the NVDA log for more details."), caption=_("Error"), style=wx.ICON_ERROR|wx.OK) - -class DirectConnectDialog(wx.Dialog): - - def __init__(self, parent, id, title): - super().__init__(parent, id, title=title) - main_sizer = self.main_sizer = wx.BoxSizer(wx.VERTICAL) - self.client_or_server = wx.RadioBox(self, wx.ID_ANY, choices=(_("Client"), _("Server")), style=wx.RA_VERTICAL) - self.client_or_server.Bind(wx.EVT_RADIOBOX, self.on_client_or_server) - self.client_or_server.SetSelection(0) - main_sizer.Add(self.client_or_server) - choices = [_("Control another machine"), _("Allow this machine to be controlled")] - self.connection_type = wx.RadioBox(self, wx.ID_ANY, choices=choices, style=wx.RA_VERTICAL) - self.connection_type.SetSelection(0) - main_sizer.Add(self.connection_type) - self.container = wx.Panel(parent=self) - self.panel = ClientPanel(parent=self.container) - main_sizer.Add(self.container) - buttons = self.CreateButtonSizer(wx.OK | wx.CANCEL) - main_sizer.Add(buttons, flag=wx.BOTTOM) - main_sizer.Fit(self) - self.SetSizer(main_sizer) - self.Center(wx.BOTH | WX_CENTER) - ok = wx.FindWindowById(wx.ID_OK, self) - ok.Bind(wx.EVT_BUTTON, self.on_ok) - self.client_or_server.SetFocus() - - def on_client_or_server(self, evt): - evt.Skip() - self.panel.Destroy() - if self.client_or_server.GetSelection() == 0: - self.panel = ClientPanel(parent=self.container) - else: - self.panel = ServerPanel(parent=self.container) - self.main_sizer.Fit(self) - - def on_ok(self, evt): - if self.client_or_server.GetSelection() == 0: - if not self.panel.host.GetValue() or not self.panel.key.GetValue(): - gui.messageBox(_("Both host and key must be set."), _("Error"), wx.OK | wx.ICON_ERROR) - self.panel.host.SetFocus() - return - elif len(self.panel.key.GetValue()) < 6: - gui.messageBox(_("The key must be longer than 6 characters."), _("Error"), wx.OK | wx.ICON_ERROR) - self.panel.key.SetFocus() - return - elif is_sequential(self.panel.key.GetValue()): - # Translators: error message for key/password being sequential, example 123456 - gui.messageBox(_("The key must not be sequential. Please, avoid keys such as 1234, 4321 or similar."), _("Error"), wx.OK | wx.ICON_ERROR) - self.panel.key.SetFocus() - return - elif self.client_or_server.GetSelection() == 1: - if not self.panel.port.GetValue() or not self.panel.key.GetValue(): - gui.messageBox(_("Both port and key must be set."), _("Error"), wx.OK | wx.ICON_ERROR) - self.panel.port.SetFocus() - return - elif len(self.panel.key.GetValue()) < 6: - gui.messageBox(_("The key must be longer than 6 characters."), _("Error"), wx.OK | wx.ICON_ERROR) - self.panel.key.SetFocus() - return - elif is_sequential(self.panel.key.GetValue()): - # Translators: error message for key/password being sequential, example 123456 - gui.messageBox(_("The key must not be sequential. Please, avoid keys such as 1234, 4321 or similar."), _("Error"), wx.OK | wx.ICON_ERROR) - self.panel.key.SetFocus() - return - evt.Skip() - -class OptionsDialog(SettingsPanel): - - # Translators: title for the TeleNVDA settings category in NVDA settings dialog - title = _("TeleNVDA") - - def makeSettings(self, sizer): - # Translators: A checkbox in add-on options dialog to set whether remote server is started when NVDA starts. - self.autoconnect = wx.CheckBox(self, wx.ID_ANY, label=_("Auto-connect to control server on startup")) - self.autoconnect.Bind(wx.EVT_CHECKBOX, self.on_autoconnect) - sizer.Add(self.autoconnect) - #Translators: Whether or not to use a relay server when autoconnecting - self.client_or_server = wx.RadioBox(self, wx.ID_ANY, choices=(_("Use Remote Control Server"), _("Host Control Server")), style=wx.RA_VERTICAL) - self.client_or_server.Bind(wx.EVT_RADIOBOX, self.on_client_or_server) - self.client_or_server.SetSelection(0) - self.client_or_server.Enable(False) - sizer.Add(self.client_or_server) - choices = [_("Allow this machine to be controlled"), _("Control another machine")] - self.connection_type = wx.RadioBox(self, wx.ID_ANY, choices=choices, style=wx.RA_VERTICAL) - self.connection_type.SetSelection(0) - self.connection_type.Enable(False) - sizer.Add(self.connection_type) - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Host:"))) - self.host = wx.TextCtrl(self, wx.ID_ANY) - self.host.Enable(False) - sizer.Add(self.host) - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Port:"))) - self.port = wx.SpinCtrl(self, wx.ID_ANY, min=1, max=65535) - self.port.Enable(False) - sizer.Add(self.port) - # Translators: label of a checkbox which allows forwarding a port using UPNP - self.useUPNP = wx.CheckBox(self, wx.ID_ANY, label=_("Use &UPNP to forward this port if possible")) - self.useUPNP.Enable(False) - sizer.Add(self.useUPNP) - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Key:"))) - self.key = wx.TextCtrl(self, wx.ID_ANY) - self.key.Enable(False) - sizer.Add(self.key) - # Translators: Label of an edit field to enter a second password to exchange encrypted data. - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("En&cryption password (optional):"))) - self.encryption_key = wx.TextCtrl(self, wx.ID_ANY) - self.encryption_key.Enable(False) - sizer.Add(self.encryption_key) - # Translators: A checkbox in add-on options dialog to set whether sounds play instead of beeps. - self.play_sounds = wx.CheckBox(self, wx.ID_ANY, label=_("Play sounds instead of beeps")) - sizer.Add(self.play_sounds) - # Translators: A checkbox in add-on options dialog to set whether to display an alert before the controlled computer disconnects. - self.alert_before_slave_disconnect = wx.CheckBox(self, wx.ID_ANY, label=_("Display an alert before the controlled computer disconnects")) - sizer.Add(self.alert_before_slave_disconnect) - # Translators: A checkbox in add-on options dialog to set whether to mute remote speech when controlling the local machine. - self.mute_when_controlling_local_machine = wx.CheckBox(self, wx.ID_ANY, label=_("Mute remote speech when controlling local machine")) - sizer.Add(self.mute_when_controlling_local_machine) - # Translators: A checkbox in add-on options dialog to set whether allow or block speech commands - self.speech_commands = wx.CheckBox(self, wx.ID_ANY, label=_("Process speech commands when controlling another computer")) - sizer.Add(self.speech_commands) - # Translators: A checkbox in add-on options dialog to set whether server welcome messages are displayed only once - self.motd_once = wx.CheckBox(self, wx.ID_ANY, label=_("Show server welcome messages only once")) - sizer.Add(self.motd_once) - # Translators: a text field in add-on options dialog to set the portcheck service URL - sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("Portcheck &service URL: "))) - self.portcheck = wx.TextCtrl(self, wx.ID_ANY) - sizer.Add(self.portcheck) - # Translators: A button in add-on options dialog to delete all fingerprints of unauthorized certificates. - self.delete_fingerprints = wx.Button(self, wx.ID_ANY, label=_("Delete all trusted fingerprints")) - self.delete_fingerprints.Bind(wx.EVT_BUTTON, self.on_delete_fingerprints) - sizer.Add(self.delete_fingerprints) - - def on_autoconnect(self, evt): - self.set_controls() - - def set_controls(self): - state = bool(self.autoconnect.GetValue()) - self.client_or_server.Enable(state) - self.connection_type.Enable(state) - self.key.Enable(state) - self.encryption_key.Enable(state) - self.host.Enable(not bool(self.client_or_server.GetSelection()) and state) - self.port.Enable(bool(self.client_or_server.GetSelection()) and state) - self.useUPNP.Enable(bool(self.client_or_server.GetSelection()) and state) - - def on_client_or_server(self, evt): - evt.Skip() - self.set_controls() - - def onPanelActivated(self): - config = configuration.get_config() - cs = config['controlserver'] - self_hosted = cs['self_hosted'] - connection_type = cs['connection_type'] - self.autoconnect.SetValue(cs['autoconnect']) - self.client_or_server.SetSelection(int(self_hosted)) - self.connection_type.SetSelection(connection_type) - self.host.SetValue(cs['host']) - self.port.SetValue(str(cs['port'])) - self.useUPNP.SetValue(cs['UPNP']) - self.key.SetValue(cs['key']) - self.encryption_key.SetValue(cs['encryption_key']) - self.set_controls() - self.play_sounds.SetValue(config['ui']['play_sounds']) - self.alert_before_slave_disconnect.SetValue(config['ui']['alert_before_slave_disconnect']) - self.mute_when_controlling_local_machine.SetValue(config['ui']['mute_when_controlling_local_machine']) - self.speech_commands.SetValue(config['ui']['allow_speech_commands']) - self.motd_once.SetValue(config['ui']['display_motd_once']) - self.portcheck.SetValue(config['ui']['portcheck']) - self.originalProfileName = NVDAConfig.conf.profiles[-1].name - NVDAConfig.conf.profiles[-1].name = None - self.Show() - - def on_delete_fingerprints(self, evt): - if gui.messageBox(_("When connecting to an unauthorized server, you will again be prompted to accepts its certificate."), _("Are you sure you want to delete all stored trusted fingerprints?"), wx.YES|wx.NO|wx.NO_DEFAULT|wx.ICON_WARNING) == wx.YES: - config = configuration.get_config() - config['trusted_certs'].clear() - if not configuration.readonly: - config.write() - evt.Skip() - - def onPanelDeactivated(self): - NVDAConfig.conf.profiles[-1].name = self.originalProfileName - self.Hide() - - def onDiscard(self): - NVDAConfig.conf.profiles[-1].name = self.originalProfileName - - def onSave(self): - if not "{port}" in self.portcheck.GetValue(): - # Translators: error message for invalid format on Portcheck service URL - gui.messageBox(_("Invalid format for portcheck service URL. You must include {port} somewhere."), _("Error"), wx.OK | wx.ICON_ERROR) - raise - if self.autoconnect.GetValue(): - if not self.client_or_server.GetSelection() and (not self.host.GetValue() or not self.key.GetValue()): - gui.messageBox(_("Both host and key must be set."), _("Error"), wx.OK | wx.ICON_ERROR) - raise - elif self.client_or_server.GetSelection() and not self.port.GetValue() or not self.key.GetValue(): - gui.messageBox(_("Both port and key must be set."), _("Error"), wx.OK | wx.ICON_ERROR) - raise - if len(self.key.GetValue()) < 6: - # Translators: error message for key/password length less than 6 characters - gui.messageBox(_("The key must be longer than 6 characters."), _("Error"), wx.OK | wx.ICON_ERROR) - self.key.SetFocus() - raise - elif is_sequential(self.key.GetValue()): - # Translators: error message for key/password being sequential, example 123456 - gui.messageBox(_("The key must not be sequential. Please, avoid keys such as 1234, 4321 or similar."), _("Error"), wx.OK | wx.ICON_ERROR) - self.key.SetFocus() - raise - NVDAConfig.conf.profiles[-1].name = self.originalProfileName - config = configuration.get_config() - cs = config['controlserver'] - cs['autoconnect'] = self.autoconnect.GetValue() - self_hosted = bool(self.client_or_server.GetSelection()) - connection_type = self.connection_type.GetSelection() - cs['self_hosted'] = self_hosted - cs['connection_type'] = connection_type - if not self_hosted: - cs['host'] = self.host.GetValue() - else: - cs['port'] = int(self.port.GetValue()) - cs['UPNP'] = bool(self.useUPNP.GetValue()) - cs['key'] = self.key.GetValue() - cs['encryption_key'] = self.encryption_key.GetValue() - config['ui']['play_sounds'] = self.play_sounds.GetValue() - config['ui']['alert_before_slave_disconnect'] = self.alert_before_slave_disconnect.GetValue() - config['ui']['mute_when_controlling_local_machine'] = self.mute_when_controlling_local_machine.GetValue() - config['ui']['allow_speech_commands'] = self.speech_commands.GetValue() - config['ui']['display_motd_once'] = self.motd_once.GetValue() - config['ui']['portcheck'] = self.portcheck.GetValue() - if not configuration.readonly: - config.write() - -class CertificateUnauthorizedDialog(wx.MessageDialog): - - def __init__(self, parent, fingerprint=None): - # Translators: A title bar of a window presented when an attempt has been made to connect with a server with unauthorized certificate. - title=_("TeleNVDA Connection Security Warning") - # Translators: A message of a window presented when an attempt has been made to connect with a server with unauthorized certificate. - message = _("Warning! The certificate of this server could not be verified.\nThis connection may not be secure. It is possible that someone is trying to overhear your communication.\nBefore continuing please make sure that the following server certificate fingerprint is a proper one.\nIf you have any questions, please contact the server administrator.\n\nServer SHA256 fingerprint: {fingerprint}\n\nDo you want to continue connecting?").format(fingerprint=fingerprint) - super().__init__(parent, caption=title, message=message, style=wx.YES_NO|wx.CANCEL|wx.CANCEL_DEFAULT|wx.CENTRE) - self.SetYesNoLabels(_("Connect and do not ask again for this server"), _("Connect")) - -def is_sequential(password): - if len(password) < 3: - return False - for i in range(len(password) - 2): - if ord(password[i]) == ord(password[i + 1]) - 1 == ord(password[i + 2]) - 2: - return True - return False +import json +import random +import threading +from urllib import request +import wx +import gui +from gui.settingsDialogs import SettingsPanel +from . import serializer +from . import server +from . import transport +from . import socket_utils +from logHandler import log +import addonHandler + +try: + addonHandler.initTranslation() +except addonHandler.AddonError: + log.warning( + "Unable to initialise translations. This may be because the addon is running from NVDA scratchpad.", + ) +from . import configuration +import config as NVDAConfig +import os +import sys + +sys.path.append(os.path.dirname(__file__)) +import miniupnpc + +del sys.path[-1] + + +WX_VERSION = int(wx.version()[0]) +WX_CENTER = wx.Center if WX_VERSION >= 4 else wx.CENTER_ON_SCREEN + + +class ClientPanel(wx.Panel): + def __init__(self, parent=None, id=wx.ID_ANY): + super().__init__(parent, id) + sizer = wx.BoxSizer(wx.HORIZONTAL) + # Translators: The label of an edit field in connect dialog to enter name or address of the remote computer. + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Host:"))) + self.host = wx.ComboBox(self, wx.ID_ANY) + sizer.Add(self.host) + # Translators: Label of the edit field to enter key (password) to secure the remote connection. + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Key:"))) + self.key = wx.TextCtrl(self, wx.ID_ANY) + sizer.Add(self.key) + # Translators: The button used to generate a random key/password. + self.generate_key = wx.Button(parent=self, label=_("&Generate Key")) + self.generate_key.Bind(wx.EVT_BUTTON, self.on_generate_key) + sizer.Add(self.generate_key) + # Translators: Label of an edit field to enter a second password to exchange encrypted data. + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("En&cryption password (optional):"))) + self.encryption_key = wx.TextCtrl(self, wx.ID_ANY) + sizer.Add(self.encryption_key) + self.SetSizerAndFit(sizer) + + def on_generate_key(self, evt): + if not self.host.GetValue(): + gui.messageBox(_("Host must be set."), _("Error"), wx.OK | wx.ICON_ERROR) + self.host.SetFocus() + else: + evt.Skip() + self.generate_key_command() + + def generate_key_command(self, insecure=False): + address = socket_utils.address_to_hostport(self.host.GetValue()) + self.key_connector = transport.RelayTransport( + address=address, serializer=serializer.JSONSerializer(), insecure=insecure + ) + self.key_connector.callback_manager.register_callback("msg_generate_key", self.handle_key_generated) + self.key_connector.callback_manager.register_callback( + transport.TransportEvents.CERTIFICATE_AUTHENTICATION_FAILED, self.handle_certificate_failed + ) + t = threading.Thread(target=self.key_connector.run) + t.start() + + def handle_key_generated(self, key=None): + self.key.SetValue(key) + self.key.SetFocus() + self.key_connector.close() + self.key_connector = None + + def handle_certificate_failed(self): + try: + cert_hash = self.key_connector.last_fail_fingerprint + + wnd = CertificateUnauthorizedDialog(None, fingerprint=cert_hash) + a = wnd.ShowModal() + if a == wx.ID_YES: + config = configuration.get_config() + config["trusted_certs"][self.host.GetValue()] = cert_hash + if not config.readonly: + config.write() + if a != wx.ID_YES and a != wx.ID_NO: + return + except Exception as ex: + log.error(ex) + return + self.key_connector.close() + self.key_connector = None + self.generate_key_command(True) + + +class ServerPanel(wx.Panel): + def __init__(self, parent=None, id=wx.ID_ANY): + super().__init__(parent, id) + sizer = wx.BoxSizer(wx.HORIZONTAL) + # Translators: Used in server mode to obtain the external IP address for the server (controlled computer) for direct connection. + self.get_IP = wx.Button(parent=self, label=_("Get External &IP")) + self.get_IP.Bind(wx.EVT_BUTTON, self.on_get_IP) + sizer.Add(self.get_IP) + # Translators: Label of the field displaying the external IP address if using direct (client to server) connection. + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&External IP:"))) + self.external_IP = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_READONLY | wx.TE_MULTILINE) + sizer.Add(self.external_IP) + # Translators: The label of an edit field in connect dialog to enter the port the server will listen on. + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Port:"))) + self.port = wx.SpinCtrl(self, wx.ID_ANY, min=1, max=65535, value=str(socket_utils.SERVER_PORT)) + sizer.Add(self.port) + # Translators: label of a checkbox which allows forwarding a port using UPNP + self.useUPNP = wx.CheckBox(self, wx.ID_ANY, label=_("Use &UPNP to forward this port if possible")) + sizer.Add(self.useUPNP) + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Key:"))) + self.key = wx.TextCtrl(self, wx.ID_ANY) + sizer.Add(self.key) + self.generate_key = wx.Button(parent=self, label=_("&Generate Key")) + self.generate_key.Bind(wx.EVT_BUTTON, self.on_generate_key) + sizer.Add(self.generate_key) + # Translators: Label of an edit field to enter a second password to exchange encrypted data. + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("En&cryption password (optional):"))) + self.encryption_key = wx.TextCtrl(self, wx.ID_ANY) + sizer.Add(self.encryption_key) + self.SetSizerAndFit(sizer) + + def on_generate_key(self, evt): + evt.Skip() + res = str(random.randrange(1, 9)) + for n in range(6): + res += str(random.randrange(0, 9)) + self.key.SetValue(res) + self.key.SetFocus() + + def on_get_IP(self, evt): + evt.Skip() + self.get_IP.Enable(False) + result = gui.messageBox( + # Translators: message asking the user wether perform portcheck with UPNP or not + _("Would you like to use UPNP to forward the chosen port before detecting your IP address?"), + # Translators: title of the message asking the user to try portcheck with UPNP + _("Do you want to use UPNP?"), + wx.YES_NO | wx.ICON_QUESTION, + self, + ) + if result == wx.YES: + t = threading.Thread(target=self.do_portcheck, args=[int(self.port.GetValue()), True]) + else: + t = threading.Thread(target=self.do_portcheck, args=[int(self.port.GetValue())]) + t.daemon = True + t.start() + + def do_portcheck(self, port, UPNP=False): + config = configuration.get_config() + if UPNP: + try: + upnp = miniupnpc.UPnP() + upnp.discoverdelay = 200 + upnp.discover() + upnp.selectigd() + upnp.addportmapping(port, "TCP", upnp.lanaddr, port, "TeleNVDA", "", 60) + except Exception as e: + self.on_get_IP_fail(e) + self.get_IP.Enable(True) + raise + temp_server = server.Server(port=port, password=None) + try: + Headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64)"} + p = request.Request(config["ui"]["portcheck"].format(port=port), headers=Headers, method="GET") + req = request.urlopen(p) + data = req.read() + result = json.loads(data) + wx.CallAfter(self.on_get_IP_success, result) + except Exception as e: + self.on_get_IP_fail(e) + raise + finally: + temp_server.close() + self.get_IP.Enable(True) + if UPNP: + upnp.deleteportmapping(port, "TCP") + + def on_get_IP_success(self, data): + ip = data["host"] + port = data["port"] + is_open = data["open"] + if is_open: + gui.messageBox( + message=_("Successfully retrieved IP address. Port {port} is open.").format(port=port), + caption=_("Success"), + style=wx.OK, + ) + else: + gui.messageBox( + message=_("Retrieved external IP, but port {port} is not currently forwarded.").format( + port=port + ), + caption=_("Warning"), + style=wx.ICON_WARNING | wx.OK, + ) + self.external_IP.SetValue(ip) + self.external_IP.SetSelection(0, len(ip)) + self.external_IP.SetFocus() + + def on_get_IP_fail(self, exc): + gui.messageBox( + message=_( + "Unable to contact portcheck server or UPNP device, please manually retrieve your IP address and forward ports if required. See the NVDA log for more details." + ), + caption=_("Error"), + style=wx.ICON_ERROR | wx.OK, + ) + + +class DirectConnectDialog(wx.Dialog): + def __init__(self, parent, id, title): + super().__init__(parent, id, title=title) + main_sizer = self.main_sizer = wx.BoxSizer(wx.VERTICAL) + self.client_or_server = wx.RadioBox( + self, wx.ID_ANY, choices=(_("Client"), _("Server")), style=wx.RA_VERTICAL + ) + self.client_or_server.Bind(wx.EVT_RADIOBOX, self.on_client_or_server) + self.client_or_server.SetSelection(0) + main_sizer.Add(self.client_or_server) + choices = [_("Control another machine"), _("Allow this machine to be controlled")] + self.connection_type = wx.RadioBox(self, wx.ID_ANY, choices=choices, style=wx.RA_VERTICAL) + self.connection_type.SetSelection(0) + main_sizer.Add(self.connection_type) + self.container = wx.Panel(parent=self) + self.panel = ClientPanel(parent=self.container) + main_sizer.Add(self.container) + buttons = self.CreateButtonSizer(wx.OK | wx.CANCEL) + main_sizer.Add(buttons, flag=wx.BOTTOM) + main_sizer.Fit(self) + self.SetSizer(main_sizer) + self.Center(wx.BOTH | WX_CENTER) + ok = wx.FindWindowById(wx.ID_OK, self) + ok.Bind(wx.EVT_BUTTON, self.on_ok) + self.client_or_server.SetFocus() + + def on_client_or_server(self, evt): + evt.Skip() + self.panel.Destroy() + if self.client_or_server.GetSelection() == 0: + self.panel = ClientPanel(parent=self.container) + else: + self.panel = ServerPanel(parent=self.container) + self.main_sizer.Fit(self) + + def on_ok(self, evt): + if self.client_or_server.GetSelection() == 0: + if not self.panel.host.GetValue() or not self.panel.key.GetValue(): + gui.messageBox(_("Both host and key must be set."), _("Error"), wx.OK | wx.ICON_ERROR) + self.panel.host.SetFocus() + return + elif len(self.panel.key.GetValue()) < 6: + gui.messageBox( + _("The key must be longer than 6 characters."), _("Error"), wx.OK | wx.ICON_ERROR + ) + self.panel.key.SetFocus() + return + elif is_sequential(self.panel.key.GetValue()): + # Translators: error message for key/password being sequential, example 123456 + gui.messageBox( + _("The key must not be sequential. Please, avoid keys such as 1234, 4321 or similar."), + _("Error"), + wx.OK | wx.ICON_ERROR, + ) + self.panel.key.SetFocus() + return + elif self.client_or_server.GetSelection() == 1: + if not self.panel.port.GetValue() or not self.panel.key.GetValue(): + gui.messageBox(_("Both port and key must be set."), _("Error"), wx.OK | wx.ICON_ERROR) + self.panel.port.SetFocus() + return + elif len(self.panel.key.GetValue()) < 6: + gui.messageBox( + _("The key must be longer than 6 characters."), _("Error"), wx.OK | wx.ICON_ERROR + ) + self.panel.key.SetFocus() + return + elif is_sequential(self.panel.key.GetValue()): + # Translators: error message for key/password being sequential, example 123456 + gui.messageBox( + _("The key must not be sequential. Please, avoid keys such as 1234, 4321 or similar."), + _("Error"), + wx.OK | wx.ICON_ERROR, + ) + self.panel.key.SetFocus() + return + evt.Skip() + + +class OptionsDialog(SettingsPanel): + # Translators: title for the TeleNVDA settings category in NVDA settings dialog + title = _("TeleNVDA") + + def makeSettings(self, sizer): + # Translators: A checkbox in add-on options dialog to set whether remote server is started when NVDA starts. + self.autoconnect = wx.CheckBox(self, wx.ID_ANY, label=_("Auto-connect to control server on startup")) + self.autoconnect.Bind(wx.EVT_CHECKBOX, self.on_autoconnect) + sizer.Add(self.autoconnect) + # Translators: Whether or not to use a relay server when autoconnecting + self.client_or_server = wx.RadioBox( + self, + wx.ID_ANY, + choices=(_("Use Remote Control Server"), _("Host Control Server")), + style=wx.RA_VERTICAL, + ) + self.client_or_server.Bind(wx.EVT_RADIOBOX, self.on_client_or_server) + self.client_or_server.SetSelection(0) + self.client_or_server.Enable(False) + sizer.Add(self.client_or_server) + choices = [_("Allow this machine to be controlled"), _("Control another machine")] + self.connection_type = wx.RadioBox(self, wx.ID_ANY, choices=choices, style=wx.RA_VERTICAL) + self.connection_type.SetSelection(0) + self.connection_type.Enable(False) + sizer.Add(self.connection_type) + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Host:"))) + self.host = wx.TextCtrl(self, wx.ID_ANY) + self.host.Enable(False) + sizer.Add(self.host) + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Port:"))) + self.port = wx.SpinCtrl(self, wx.ID_ANY, min=1, max=65535) + self.port.Enable(False) + sizer.Add(self.port) + # Translators: label of a checkbox which allows forwarding a port using UPNP + self.useUPNP = wx.CheckBox(self, wx.ID_ANY, label=_("Use &UPNP to forward this port if possible")) + self.useUPNP.Enable(False) + sizer.Add(self.useUPNP) + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("&Key:"))) + self.key = wx.TextCtrl(self, wx.ID_ANY) + self.key.Enable(False) + sizer.Add(self.key) + # Translators: Label of an edit field to enter a second password to exchange encrypted data. + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("En&cryption password (optional):"))) + self.encryption_key = wx.TextCtrl(self, wx.ID_ANY) + self.encryption_key.Enable(False) + sizer.Add(self.encryption_key) + # Translators: A checkbox in add-on options dialog to set whether sounds play instead of beeps. + self.play_sounds = wx.CheckBox(self, wx.ID_ANY, label=_("Play sounds instead of beeps")) + sizer.Add(self.play_sounds) + # Translators: A checkbox in add-on options dialog to set whether to display an alert before the controlled computer disconnects. + self.alert_before_slave_disconnect = wx.CheckBox( + self, wx.ID_ANY, label=_("Display an alert before the controlled computer disconnects") + ) + sizer.Add(self.alert_before_slave_disconnect) + # Translators: A checkbox in add-on options dialog to set whether to mute remote speech when controlling the local machine. + self.mute_when_controlling_local_machine = wx.CheckBox( + self, wx.ID_ANY, label=_("Mute remote speech when controlling local machine") + ) + sizer.Add(self.mute_when_controlling_local_machine) + # Translators: A checkbox in add-on options dialog to set whether allow or block speech commands + self.speech_commands = wx.CheckBox( + self, wx.ID_ANY, label=_("Process speech commands when controlling another computer") + ) + sizer.Add(self.speech_commands) + # Translators: A checkbox in add-on options dialog to set whether server welcome messages are displayed only once + self.motd_once = wx.CheckBox(self, wx.ID_ANY, label=_("Show server welcome messages only once")) + sizer.Add(self.motd_once) + # Translators: a text field in add-on options dialog to set the portcheck service URL + sizer.Add(wx.StaticText(self, wx.ID_ANY, label=_("Portcheck &service URL: "))) + self.portcheck = wx.TextCtrl(self, wx.ID_ANY) + sizer.Add(self.portcheck) + # Translators: A button in add-on options dialog to delete all fingerprints of unauthorized certificates. + self.delete_fingerprints = wx.Button(self, wx.ID_ANY, label=_("Delete all trusted fingerprints")) + self.delete_fingerprints.Bind(wx.EVT_BUTTON, self.on_delete_fingerprints) + sizer.Add(self.delete_fingerprints) + + def on_autoconnect(self, evt): + self.set_controls() + + def set_controls(self): + state = bool(self.autoconnect.GetValue()) + self.client_or_server.Enable(state) + self.connection_type.Enable(state) + self.key.Enable(state) + self.encryption_key.Enable(state) + self.host.Enable(not bool(self.client_or_server.GetSelection()) and state) + self.port.Enable(bool(self.client_or_server.GetSelection()) and state) + self.useUPNP.Enable(bool(self.client_or_server.GetSelection()) and state) + + def on_client_or_server(self, evt): + evt.Skip() + self.set_controls() + + def onPanelActivated(self): + config = configuration.get_config() + cs = config["controlserver"] + self_hosted = cs["self_hosted"] + connection_type = cs["connection_type"] + self.autoconnect.SetValue(cs["autoconnect"]) + self.client_or_server.SetSelection(int(self_hosted)) + self.connection_type.SetSelection(connection_type) + self.host.SetValue(cs["host"]) + self.port.SetValue(str(cs["port"])) + self.useUPNP.SetValue(cs["UPNP"]) + self.key.SetValue(cs["key"]) + self.encryption_key.SetValue(cs["encryption_key"]) + self.set_controls() + self.play_sounds.SetValue(config["ui"]["play_sounds"]) + self.alert_before_slave_disconnect.SetValue(config["ui"]["alert_before_slave_disconnect"]) + self.mute_when_controlling_local_machine.SetValue(config["ui"]["mute_when_controlling_local_machine"]) + self.speech_commands.SetValue(config["ui"]["allow_speech_commands"]) + self.motd_once.SetValue(config["ui"]["display_motd_once"]) + self.portcheck.SetValue(config["ui"]["portcheck"]) + self.originalProfileName = NVDAConfig.conf.profiles[-1].name + NVDAConfig.conf.profiles[-1].name = None + self.Show() + + def on_delete_fingerprints(self, evt): + if ( + gui.messageBox( + _( + "When connecting to an unauthorized server, you will again be prompted to accepts its certificate." + ), + _("Are you sure you want to delete all stored trusted fingerprints?"), + wx.YES | wx.NO | wx.NO_DEFAULT | wx.ICON_WARNING, + ) + == wx.YES + ): + config = configuration.get_config() + config["trusted_certs"].clear() + if not configuration.readonly: + config.write() + evt.Skip() + + def onPanelDeactivated(self): + NVDAConfig.conf.profiles[-1].name = self.originalProfileName + self.Hide() + + def onDiscard(self): + NVDAConfig.conf.profiles[-1].name = self.originalProfileName + + def onSave(self): + if "{port}" not in self.portcheck.GetValue(): + # Translators: error message for invalid format on Portcheck service URL + gui.messageBox( + _("Invalid format for portcheck service URL. You must include {port} somewhere."), + _("Error"), + wx.OK | wx.ICON_ERROR, + ) + raise + if self.autoconnect.GetValue(): + if not self.client_or_server.GetSelection() and ( + not self.host.GetValue() or not self.key.GetValue() + ): + gui.messageBox(_("Both host and key must be set."), _("Error"), wx.OK | wx.ICON_ERROR) + raise + elif self.client_or_server.GetSelection() and not self.port.GetValue() or not self.key.GetValue(): + gui.messageBox(_("Both port and key must be set."), _("Error"), wx.OK | wx.ICON_ERROR) + raise + if len(self.key.GetValue()) < 6: + # Translators: error message for key/password length less than 6 characters + gui.messageBox( + _("The key must be longer than 6 characters."), _("Error"), wx.OK | wx.ICON_ERROR + ) + self.key.SetFocus() + raise + elif is_sequential(self.key.GetValue()): + # Translators: error message for key/password being sequential, example 123456 + gui.messageBox( + _("The key must not be sequential. Please, avoid keys such as 1234, 4321 or similar."), + _("Error"), + wx.OK | wx.ICON_ERROR, + ) + self.key.SetFocus() + raise + NVDAConfig.conf.profiles[-1].name = self.originalProfileName + config = configuration.get_config() + cs = config["controlserver"] + cs["autoconnect"] = self.autoconnect.GetValue() + self_hosted = bool(self.client_or_server.GetSelection()) + connection_type = self.connection_type.GetSelection() + cs["self_hosted"] = self_hosted + cs["connection_type"] = connection_type + if not self_hosted: + cs["host"] = self.host.GetValue() + else: + cs["port"] = int(self.port.GetValue()) + cs["UPNP"] = bool(self.useUPNP.GetValue()) + cs["key"] = self.key.GetValue() + cs["encryption_key"] = self.encryption_key.GetValue() + config["ui"]["play_sounds"] = self.play_sounds.GetValue() + config["ui"]["alert_before_slave_disconnect"] = self.alert_before_slave_disconnect.GetValue() + config["ui"]["mute_when_controlling_local_machine"] = ( + self.mute_when_controlling_local_machine.GetValue() + ) + config["ui"]["allow_speech_commands"] = self.speech_commands.GetValue() + config["ui"]["display_motd_once"] = self.motd_once.GetValue() + config["ui"]["portcheck"] = self.portcheck.GetValue() + if not configuration.readonly: + config.write() + + +class CertificateUnauthorizedDialog(wx.MessageDialog): + def __init__(self, parent, fingerprint=None): + # Translators: A title bar of a window presented when an attempt has been made to connect with a server with unauthorized certificate. + title = _("TeleNVDA Connection Security Warning") + # Translators: A message of a window presented when an attempt has been made to connect with a server with unauthorized certificate. + message = _( + "Warning! The certificate of this server could not be verified.\nThis connection may not be secure. It is possible that someone is trying to overhear your communication.\nBefore continuing please make sure that the following server certificate fingerprint is a proper one.\nIf you have any questions, please contact the server administrator.\n\nServer SHA256 fingerprint: {fingerprint}\n\nDo you want to continue connecting?" + ).format(fingerprint=fingerprint) + super().__init__( + parent, + caption=title, + message=message, + style=wx.YES_NO | wx.CANCEL | wx.CANCEL_DEFAULT | wx.CENTRE, + ) + self.SetYesNoLabels(_("Connect and do not ask again for this server"), _("Connect")) + + +def is_sequential(password): + if len(password) < 3: + return False + for i in range(len(password) - 2): + if ord(password[i]) == ord(password[i + 1]) - 1 == ord(password[i + 2]) - 2: + return True + return False diff --git a/addon/globalPlugins/remoteClient/keyboard_hook.py b/addon/globalPlugins/remoteClient/keyboard_hook.py index 8710ab95..23405c06 100755 --- a/addon/globalPlugins/remoteClient/keyboard_hook.py +++ b/addon/globalPlugins/remoteClient/keyboard_hook.py @@ -39,7 +39,10 @@ def __init__(self): self.callbacks = list() self.proc = LowLevelKeyboardProc(self.keyboard_proc) self.handle = ctypes.windll.user32.SetWindowsHookExW( - WH_KEYBOARD_LL, self.proc, ctypes.windll.kernel32.GetModuleHandleW(None), 0 + WH_KEYBOARD_LL, + self.proc, + ctypes.windll.kernel32.GetModuleHandleW(None), + 0, ) def register_callback(self, callback): @@ -61,7 +64,10 @@ def keyboard_proc(self, code, wParam, lParam): for callback in self.callbacks: try: should_pass_on = not callback( - vk_code=vk_code, scan_code=scan_code, extended=extended, pressed=pressed + vk_code=vk_code, + scan_code=scan_code, + extended=extended, + pressed=pressed, ) except Exception: logger.exception("Error calling callback %r" % callback) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/AES.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/AES.py index 42f4bab1..82040057 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/AES.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/AES.py @@ -23,26 +23,30 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) from Cryptodome.Util import _cpu_features from Cryptodome.Random import get_random_bytes -MODE_ECB = 1 #: Electronic Code Book (:ref:`ecb_mode`) -MODE_CBC = 2 #: Cipher-Block Chaining (:ref:`cbc_mode`) -MODE_CFB = 3 #: Cipher Feedback (:ref:`cfb_mode`) -MODE_OFB = 5 #: Output Feedback (:ref:`ofb_mode`) -MODE_CTR = 6 #: Counter mode (:ref:`ctr_mode`) -MODE_OPENPGP = 7 #: OpenPGP mode (:ref:`openpgp_mode`) -MODE_CCM = 8 #: Counter with CBC-MAC (:ref:`ccm_mode`) -MODE_EAX = 9 #: :ref:`eax_mode` -MODE_SIV = 10 #: Synthetic Initialization Vector (:ref:`siv_mode`) -MODE_GCM = 11 #: Galois Counter Mode (:ref:`gcm_mode`) -MODE_OCB = 12 #: Offset Code Book (:ref:`ocb_mode`) -MODE_KW = 13 #: Key Wrap (:ref:`kw_mode`) -MODE_KWP = 14 #: Key Wrap with Padding (:ref:`kwp_mode`) +MODE_ECB = 1 #: Electronic Code Book (:ref:`ecb_mode`) +MODE_CBC = 2 #: Cipher-Block Chaining (:ref:`cbc_mode`) +MODE_CFB = 3 #: Cipher Feedback (:ref:`cfb_mode`) +MODE_OFB = 5 #: Output Feedback (:ref:`ofb_mode`) +MODE_CTR = 6 #: Counter mode (:ref:`ctr_mode`) +MODE_OPENPGP = 7 #: OpenPGP mode (:ref:`openpgp_mode`) +MODE_CCM = 8 #: Counter with CBC-MAC (:ref:`ccm_mode`) +MODE_EAX = 9 #: :ref:`eax_mode` +MODE_SIV = 10 #: Synthetic Initialization Vector (:ref:`siv_mode`) +MODE_GCM = 11 #: Galois Counter Mode (:ref:`gcm_mode`) +MODE_OCB = 12 #: Offset Code Book (:ref:`ocb_mode`) +MODE_KW = 13 #: Key Wrap (:ref:`kw_mode`) +MODE_KWP = 14 #: Key Wrap with Padding (:ref:`kwp_mode`) _cproto = """ int AES_start_operation(const uint8_t key[], @@ -61,172 +65,181 @@ # Load portable AES -_raw_aes_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_aes", - _cproto) +_raw_aes_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_aes", + _cproto, +) # Try to load AES with AES NI instructions try: - _raw_aesni_lib = None - if _cpu_features.have_aes_ni(): - _raw_aesni_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_aesni", - _cproto.replace("AES", - "AESNI")) + _raw_aesni_lib = None + if _cpu_features.have_aes_ni(): + _raw_aesni_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_aesni", + _cproto.replace( + "AES", + "AESNI", + ), + ) # _raw_aesni may not have been compiled in except OSError: - pass + pass def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" - - use_aesni = dict_parameters.pop("use_aesni", True) - - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - if len(key) not in key_size: - raise ValueError("Incorrect AES key length (%d bytes)" % len(key)) - - if use_aesni and _raw_aesni_lib: - start_operation = _raw_aesni_lib.AESNI_start_operation - stop_operation = _raw_aesni_lib.AESNI_stop_operation - else: - start_operation = _raw_aes_lib.AES_start_operation - stop_operation = _raw_aes_lib.AES_stop_operation - - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the AES cipher" - % result) - return SmartPointer(cipher.get(), stop_operation) + """This method instantiates and returns a handle to a low-level + base cipher. It will absorb named parameters in the process.""" + + use_aesni = dict_parameters.pop("use_aesni", True) + + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") + + if len(key) not in key_size: + raise ValueError("Incorrect AES key length (%d bytes)" % len(key)) + + if use_aesni and _raw_aesni_lib: + start_operation = _raw_aesni_lib.AESNI_start_operation + stop_operation = _raw_aesni_lib.AESNI_stop_operation + else: + start_operation = _raw_aes_lib.AES_start_operation + stop_operation = _raw_aes_lib.AES_stop_operation + + cipher = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the AES cipher" % result, + ) + return SmartPointer(cipher.get(), stop_operation) def _derive_Poly1305_key_pair(key, nonce): - """Derive a tuple (r, s, nonce) for a Poly1305 MAC. + """Derive a tuple (r, s, nonce) for a Poly1305 MAC. - If nonce is ``None``, a new 16-byte nonce is generated. - """ + If nonce is ``None``, a new 16-byte nonce is generated. + """ - if len(key) != 32: - raise ValueError("Poly1305 with AES requires a 32-byte key") + if len(key) != 32: + raise ValueError("Poly1305 with AES requires a 32-byte key") - if nonce is None: - nonce = get_random_bytes(16) - elif len(nonce) != 16: - raise ValueError("Poly1305 with AES requires a 16-byte nonce") + if nonce is None: + nonce = get_random_bytes(16) + elif len(nonce) != 16: + raise ValueError("Poly1305 with AES requires a 16-byte nonce") - s = new(key[:16], MODE_ECB).encrypt(nonce) - return key[16:], s, nonce + s = new(key[:16], MODE_ECB).encrypt(nonce) + return key[16:], s, nonce def new(key, mode, *args, **kwargs): - """Create a new AES cipher. + """Create a new AES cipher. - Args: - key(bytes/bytearray/memoryview): - The secret key to use in the symmetric cipher. + Args: + key(bytes/bytearray/memoryview): + The secret key to use in the symmetric cipher. - It must be 16 (*AES-128)*, 24 (*AES-192*) or 32 (*AES-256*) bytes long. + It must be 16 (*AES-128)*, 24 (*AES-192*) or 32 (*AES-256*) bytes long. - For ``MODE_SIV`` only, it doubles to 32, 48, or 64 bytes. - mode (a ``MODE_*`` constant): - The chaining mode to use for encryption or decryption. - If in doubt, use ``MODE_EAX``. + For ``MODE_SIV`` only, it doubles to 32, 48, or 64 bytes. + mode (a ``MODE_*`` constant): + The chaining mode to use for encryption or decryption. + If in doubt, use ``MODE_EAX``. - Keyword Args: - iv (bytes/bytearray/memoryview): - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + Keyword Args: + iv (bytes/bytearray/memoryview): + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 16 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 16 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 16 bytes long for encryption - and 18 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 16 bytes long for encryption + and 18 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - nonce (bytes/bytearray/memoryview): - (Only applicable for ``MODE_CCM``, ``MODE_EAX``, ``MODE_GCM``, - ``MODE_SIV``, ``MODE_OCB``, and ``MODE_CTR``). + nonce (bytes/bytearray/memoryview): + (Only applicable for ``MODE_CCM``, ``MODE_EAX``, ``MODE_GCM``, + ``MODE_SIV``, ``MODE_OCB``, and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key (except possibly for ``MODE_SIV``, see below). + A value that must never be reused for any other encryption done + with this key (except possibly for ``MODE_SIV``, see below). - For ``MODE_EAX``, ``MODE_GCM`` and ``MODE_SIV`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX``, ``MODE_GCM`` and ``MODE_SIV`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CCM``, its length must be in the range **[7..13]**. - Bear in mind that with CCM there is a trade-off between nonce - length and maximum message size. Recommendation: **11** bytes. + For ``MODE_CCM``, its length must be in the range **[7..13]**. + Bear in mind that with CCM there is a trade-off between nonce + length and maximum message size. Recommendation: **11** bytes. - For ``MODE_OCB``, its length must be in the range **[1..15]** - (recommended: **15**). + For ``MODE_OCB``, its length must be in the range **[1..15]** + (recommended: **15**). - For ``MODE_CTR``, its length must be in the range **[0..15]** - (recommended: **8**). + For ``MODE_CTR``, its length must be in the range **[0..15]** + (recommended: **8**). - For ``MODE_SIV``, the nonce is optional, if it is not specified, - then no nonce is being used, which renders the encryption - deterministic. + For ``MODE_SIV``, the nonce is optional, if it is not specified, + then no nonce is being used, which renders the encryption + deterministic. - If not provided, for modes other than ``MODE_SIV``, a random - byte string of the recommended length is used (you must then - read its value with the :attr:`nonce` attribute). + If not provided, for modes other than ``MODE_SIV``, a random + byte string of the recommended length is used (you must then + read its value with the :attr:`nonce` attribute). - segment_size (integer): - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + segment_size (integer): + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - mac_len (integer): - (Only ``MODE_EAX``, ``MODE_GCM``, ``MODE_OCB``, ``MODE_CCM``) - Length of the authentication tag, in bytes. + mac_len (integer): + (Only ``MODE_EAX``, ``MODE_GCM``, ``MODE_OCB``, ``MODE_CCM``) + Length of the authentication tag, in bytes. - It must be even and in the range **[4..16]**. - The recommended value (and the default, if not specified) is **16**. + It must be even and in the range **[4..16]**. + The recommended value (and the default, if not specified) is **16**. - msg_len (integer): - (Only ``MODE_CCM``). Length of the message to (de)cipher. - If not specified, ``encrypt`` must be called with the entire message. - Similarly, ``decrypt`` can only be called once. + msg_len (integer): + (Only ``MODE_CCM``). Length of the message to (de)cipher. + If not specified, ``encrypt`` must be called with the entire message. + Similarly, ``decrypt`` can only be called once. - assoc_len (integer): - (Only ``MODE_CCM``). Length of the associated data. - If not specified, all associated data is buffered internally, - which may represent a problem for very large messages. + assoc_len (integer): + (Only ``MODE_CCM``). Length of the associated data. + If not specified, all associated data is buffered internally, + which may represent a problem for very large messages. - initial_value (integer or bytes/bytearray/memoryview): - (Only ``MODE_CTR``). - The initial value for the counter. If not present, the cipher will - start counting from 0. The value is incremented by one for each block. - The counter number is encoded in big endian mode. + initial_value (integer or bytes/bytearray/memoryview): + (Only ``MODE_CTR``). + The initial value for the counter. If not present, the cipher will + start counting from 0. The value is incremented by one for each block. + The counter number is encoded in big endian mode. - counter (object): - (Only ``MODE_CTR``). - Instance of ``Cryptodome.Util.Counter``, which allows full customization - of the counter block. This parameter is incompatible to both ``nonce`` - and ``initial_value``. + counter (object): + (Only ``MODE_CTR``). + Instance of ``Cryptodome.Util.Counter``, which allows full customization + of the counter block. This parameter is incompatible to both ``nonce`` + and ``initial_value``. - use_aesni: (boolean): - Use Intel AES-NI hardware extensions (default: use if available). + use_aesni: (boolean): + Use Intel AES-NI hardware extensions (default: use if available). - Returns: - an AES object, of the applicable mode. - """ + Returns: + an AES object, of the applicable mode. + """ - kwargs["add_aes_modes"] = True - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) + kwargs["add_aes_modes"] = True + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) # Size of a data block (in bytes) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/AES.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/AES.pyi index 3f07b655..9cf4ff0e 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/AES.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/AES.pyi @@ -1,7 +1,7 @@ from typing import Dict, Optional, Tuple, Union, overload from typing_extensions import Literal -Buffer=bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -29,128 +29,79 @@ MODE_OCB: Literal[12] # MODE_ECB @overload -def new(key: Buffer, - mode: Literal[1], - use_aesni : bool = ...) -> \ - EcbMode: ... +def new(key: Buffer, mode: Literal[1], use_aesni: bool = ...) -> EcbMode: ... # MODE_CBC @overload -def new(key: Buffer, - mode: Literal[2], - iv : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - CbcMode: ... - +def new(key: Buffer, mode: Literal[2], iv: Optional[Buffer] = ..., use_aesni: bool = ...) -> CbcMode: ... @overload -def new(key: Buffer, - mode: Literal[2], - IV : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - CbcMode: ... +def new(key: Buffer, mode: Literal[2], IV: Optional[Buffer] = ..., use_aesni: bool = ...) -> CbcMode: ... # MODE_CFB @overload -def new(key: Buffer, - mode: Literal[3], - iv : Optional[Buffer] = ..., - segment_size : int = ..., - use_aesni : bool = ...) -> \ - CfbMode: ... - +def new( + key: Buffer, mode: Literal[3], iv: Optional[Buffer] = ..., segment_size: int = ..., use_aesni: bool = ... +) -> CfbMode: ... @overload -def new(key: Buffer, - mode: Literal[3], - IV : Optional[Buffer] = ..., - segment_size : int = ..., - use_aesni : bool = ...) -> \ - CfbMode: ... +def new( + key: Buffer, mode: Literal[3], IV: Optional[Buffer] = ..., segment_size: int = ..., use_aesni: bool = ... +) -> CfbMode: ... # MODE_OFB @overload -def new(key: Buffer, - mode: Literal[5], - iv : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - OfbMode: ... - +def new(key: Buffer, mode: Literal[5], iv: Optional[Buffer] = ..., use_aesni: bool = ...) -> OfbMode: ... @overload -def new(key: Buffer, - mode: Literal[5], - IV : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - OfbMode: ... +def new(key: Buffer, mode: Literal[5], IV: Optional[Buffer] = ..., use_aesni: bool = ...) -> OfbMode: ... # MODE_CTR @overload -def new(key: Buffer, - mode: Literal[6], - nonce : Optional[Buffer] = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ..., - use_aesni : bool = ...) -> \ - CtrMode: ... +def new( + key: Buffer, + mode: Literal[6], + nonce: Optional[Buffer] = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., + use_aesni: bool = ..., +) -> CtrMode: ... # MODE_OPENPGP @overload -def new(key: Buffer, - mode: Literal[7], - iv : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - OpenPgpMode: ... - +def new(key: Buffer, mode: Literal[7], iv: Optional[Buffer] = ..., use_aesni: bool = ...) -> OpenPgpMode: ... @overload -def new(key: Buffer, - mode: Literal[7], - IV : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - OpenPgpMode: ... +def new(key: Buffer, mode: Literal[7], IV: Optional[Buffer] = ..., use_aesni: bool = ...) -> OpenPgpMode: ... # MODE_CCM @overload -def new(key: Buffer, - mode: Literal[8], - nonce : Optional[Buffer] = ..., - mac_len : int = ..., - assoc_len : int = ..., - use_aesni : bool = ...) -> \ - CcmMode: ... +def new( + key: Buffer, + mode: Literal[8], + nonce: Optional[Buffer] = ..., + mac_len: int = ..., + assoc_len: int = ..., + use_aesni: bool = ..., +) -> CcmMode: ... # MODE_EAX @overload -def new(key: Buffer, - mode: Literal[9], - nonce : Optional[Buffer] = ..., - mac_len : int = ..., - use_aesni : bool = ...) -> \ - EaxMode: ... +def new( + key: Buffer, mode: Literal[9], nonce: Optional[Buffer] = ..., mac_len: int = ..., use_aesni: bool = ... +) -> EaxMode: ... # MODE_GCM @overload -def new(key: Buffer, - mode: Literal[10], - nonce : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - SivMode: ... +def new(key: Buffer, mode: Literal[10], nonce: Optional[Buffer] = ..., use_aesni: bool = ...) -> SivMode: ... # MODE_SIV @overload -def new(key: Buffer, - mode: Literal[11], - nonce : Optional[Buffer] = ..., - mac_len : int = ..., - use_aesni : bool = ...) -> \ - GcmMode: ... +def new( + key: Buffer, mode: Literal[11], nonce: Optional[Buffer] = ..., mac_len: int = ..., use_aesni: bool = ... +) -> GcmMode: ... # MODE_OCB @overload -def new(key: Buffer, - mode: Literal[12], - nonce : Optional[Buffer] = ..., - mac_len : int = ..., - use_aesni : bool = ...) -> \ - OcbMode: ... - +def new( + key: Buffer, mode: Literal[12], nonce: Optional[Buffer] = ..., mac_len: int = ..., use_aesni: bool = ... +) -> OcbMode: ... block_size: int key_size: Tuple[int, int, int] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC2.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC2.py index 4dc1bb88..766b8c65 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC2.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC2.py @@ -34,14 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util.py3compat import byte_string -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) _raw_arc2_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_arc2", - """ + "Cryptodome.Cipher._raw_arc2", + """ int ARC2_start_operation(const uint8_t key[], size_t key_len, size_t effective_key_len, @@ -55,111 +58,116 @@ uint8_t *out, size_t data_len); int ARC2_stop_operation(void *state); - """ - ) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" + """This method instantiates and returns a handle to a low-level + base cipher. It will absorb named parameters in the process.""" - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") - effective_keylen = dict_parameters.pop("effective_keylen", 1024) + effective_keylen = dict_parameters.pop("effective_keylen", 1024) - if len(key) not in key_size: - raise ValueError("Incorrect ARC2 key length (%d bytes)" % len(key)) + if len(key) not in key_size: + raise ValueError("Incorrect ARC2 key length (%d bytes)" % len(key)) - if not (40 <= effective_keylen <= 1024): - raise ValueError("'effective_key_len' must be at least 40 and no larger than 1024 " - "(not %d)" % effective_keylen) + if not (40 <= effective_keylen <= 1024): + raise ValueError( + "'effective_key_len' must be at least 40 and no larger than 1024 (not %d)" % effective_keylen, + ) - start_operation = _raw_arc2_lib.ARC2_start_operation - stop_operation = _raw_arc2_lib.ARC2_stop_operation + start_operation = _raw_arc2_lib.ARC2_start_operation + stop_operation = _raw_arc2_lib.ARC2_stop_operation - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - c_size_t(effective_keylen), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the ARC2 cipher" - % result) + cipher = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + c_size_t(effective_keylen), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the ARC2 cipher" % result, + ) - return SmartPointer(cipher.get(), stop_operation) + return SmartPointer(cipher.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new RC2 cipher. + """Create a new RC2 cipher. - :param key: - The secret key to use in the symmetric cipher. - Its length can vary from 5 to 128 bytes; the actual search space - (and the cipher strength) can be reduced with the ``effective_keylen`` parameter. - :type key: bytes, bytearray, memoryview + :param key: + The secret key to use in the symmetric cipher. + Its length can vary from 5 to 128 bytes; the actual search space + (and the cipher strength) can be reduced with the ``effective_keylen`` parameter. + :type key: bytes, bytearray, memoryview - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + :Keyword Arguments: + * **iv** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + * **nonce** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key. + A value that must never be reused for any other encryption done + with this key. - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CTR``, its length must be in the range **[0..7]**. + For ``MODE_CTR``, its length must be in the range **[0..7]**. - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - * **effective_keylen** (*integer*) -- - Optional. Maximum strength in bits of the actual key used by the ARC2 algorithm. - If the supplied ``key`` parameter is longer (in bits) of the value specified - here, it will be weakened to match it. - If not specified, no limitation is applied. + * **effective_keylen** (*integer*) -- + Optional. Maximum strength in bits of the actual key used by the ARC2 algorithm. + If the supplied ``key`` parameter is longer (in bits) of the value specified + here, it will be weakened to match it. + If not specified, no limitation is applied. - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - :Return: an ARC2 object, of the applicable mode. - """ + :Return: an ARC2 object, of the applicable mode. + """ + + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC2.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC2.pyi index a122a52d..9f307a80 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC2.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC2.pyi @@ -1,6 +1,6 @@ from typing import Union, Dict, Iterable, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode ARC2Mode = int @@ -20,16 +19,17 @@ MODE_CTR: ARC2Mode MODE_OPENPGP: ARC2Mode MODE_EAX: ARC2Mode -def new(key: Buffer, - mode: ARC2Mode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: ARC2Mode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC4.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC4.py index 543a3232..caf6ced3 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC4.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC4.py @@ -20,117 +20,134 @@ # SOFTWARE. # =================================================================== -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr) - - -_raw_arc4_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._ARC4", """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) + + +_raw_arc4_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._ARC4", + """ int ARC4_stream_encrypt(void *rc4State, const uint8_t in[], uint8_t out[], size_t len); int ARC4_stream_init(uint8_t *key, size_t keylen, void **pRc4State); int ARC4_stream_destroy(void *rc4State); - """) + """, +) class ARC4Cipher: - """ARC4 cipher object. Do not create it directly. Use - :func:`Cryptodome.Cipher.ARC4.new` instead. - """ - - def __init__(self, key, *args, **kwargs): - """Initialize an ARC4 cipher object - - See also `new()` at the module level.""" - - if len(args) > 0: - ndrop = args[0] - args = args[1:] - else: - ndrop = kwargs.pop('drop', 0) - - if len(key) not in key_size: - raise ValueError("Incorrect ARC4 key length (%d bytes)" % - len(key)) - - self._state = VoidPointer() - result = _raw_arc4_lib.ARC4_stream_init(c_uint8_ptr(key), - c_size_t(len(key)), - self._state.address_of()) - if result != 0: - raise ValueError("Error %d while creating the ARC4 cipher" - % result) - self._state = SmartPointer(self._state.get(), - _raw_arc4_lib.ARC4_stream_destroy) - - if ndrop > 0: - # This is OK even if the cipher is used for decryption, - # since encrypt and decrypt are actually the same thing - # with ARC4. - self.encrypt(b'\x00' * ndrop) - - self.block_size = 1 - self.key_size = len(key) - - def encrypt(self, plaintext): - """Encrypt a piece of data. - - :param plaintext: The data to encrypt, of any size. - :type plaintext: bytes, bytearray, memoryview - :returns: the encrypted byte string, of equal length as the - plaintext. - """ - - ciphertext = create_string_buffer(len(plaintext)) - result = _raw_arc4_lib.ARC4_stream_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - ciphertext, - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting with RC4" % result) - return get_raw_buffer(ciphertext) - - def decrypt(self, ciphertext): - """Decrypt a piece of data. - - :param ciphertext: The data to decrypt, of any size. - :type ciphertext: bytes, bytearray, memoryview - :returns: the decrypted byte string, of equal length as the - ciphertext. - """ - - try: - return self.encrypt(ciphertext) - except ValueError as e: - raise ValueError(str(e).replace("enc", "dec")) + """ARC4 cipher object. Do not create it directly. Use + :func:`Cryptodome.Cipher.ARC4.new` instead. + """ + + def __init__(self, key, *args, **kwargs): + """Initialize an ARC4 cipher object + + See also `new()` at the module level.""" + + if len(args) > 0: + ndrop = args[0] + args = args[1:] + else: + ndrop = kwargs.pop("drop", 0) + + if len(key) not in key_size: + raise ValueError( + "Incorrect ARC4 key length (%d bytes)" % len(key), + ) + + self._state = VoidPointer() + result = _raw_arc4_lib.ARC4_stream_init( + c_uint8_ptr(key), + c_size_t(len(key)), + self._state.address_of(), + ) + if result != 0: + raise ValueError( + "Error %d while creating the ARC4 cipher" % result, + ) + self._state = SmartPointer( + self._state.get(), + _raw_arc4_lib.ARC4_stream_destroy, + ) + + if ndrop > 0: + # This is OK even if the cipher is used for decryption, + # since encrypt and decrypt are actually the same thing + # with ARC4. + self.encrypt(b"\x00" * ndrop) + + self.block_size = 1 + self.key_size = len(key) + + def encrypt(self, plaintext): + """Encrypt a piece of data. + + :param plaintext: The data to encrypt, of any size. + :type plaintext: bytes, bytearray, memoryview + :returns: the encrypted byte string, of equal length as the + plaintext. + """ + + ciphertext = create_string_buffer(len(plaintext)) + result = _raw_arc4_lib.ARC4_stream_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + ciphertext, + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting with RC4" % result) + return get_raw_buffer(ciphertext) + + def decrypt(self, ciphertext): + """Decrypt a piece of data. + + :param ciphertext: The data to decrypt, of any size. + :type ciphertext: bytes, bytearray, memoryview + :returns: the decrypted byte string, of equal length as the + ciphertext. + """ + + try: + return self.encrypt(ciphertext) + except ValueError as e: + raise ValueError(str(e).replace("enc", "dec")) def new(key, *args, **kwargs): - """Create a new ARC4 cipher. + """Create a new ARC4 cipher. - :param key: - The secret key to use in the symmetric cipher. - Its length must be in the range ``[1..256]``. - The recommended length is 16 bytes. - :type key: bytes, bytearray, memoryview + :param key: + The secret key to use in the symmetric cipher. + Its length must be in the range ``[1..256]``. + The recommended length is 16 bytes. + :type key: bytes, bytearray, memoryview - :Keyword Arguments: - * *drop* (``integer``) -- - The amount of bytes to discard from the initial part of the keystream. - In fact, such part has been found to be distinguishable from random - data (while it shouldn't) and also correlated to key. + :Keyword Arguments: + * *drop* (``integer``) -- + The amount of bytes to discard from the initial part of the keystream. + In fact, such part has been found to be distinguishable from random + data (while it shouldn't) and also correlated to key. - The recommended value is 3072_ bytes. The default value is 0. + The recommended value is 3072_ bytes. The default value is 0. - :Return: an `ARC4Cipher` object + :Return: an `ARC4Cipher` object - .. _3072: http://eprint.iacr.org/2002/067.pdf - """ - return ARC4Cipher(key, *args, **kwargs) + .. _3072: http://eprint.iacr.org/2002/067.pdf + """ + return ARC4Cipher(key, *args, **kwargs) # Size of a data block (in bytes) block_size = 1 # Size of a key (in bytes) -key_size = range(1, 256+1) +key_size = range(1, 256 + 1) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC4.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC4.pyi index b0815859..c29f1b13 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC4.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ARC4.pyi @@ -1,16 +1,16 @@ -from typing import Any, Union, Iterable +from typing import Any, Iterable -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview class ARC4Cipher: - block_size: int - key_size: int + block_size: int + key_size: int - def __init__(self, key: Buffer, *args: Any, **kwargs: Any) -> None: ... - def encrypt(self, plaintext: Buffer) -> bytes: ... - def decrypt(self, ciphertext: Buffer) -> bytes: ... + def __init__(self, key: Buffer, *args: Any, **kwargs: Any) -> None: ... + def encrypt(self, plaintext: Buffer) -> bytes: ... + def decrypt(self, ciphertext: Buffer) -> bytes: ... -def new(key: Buffer, drop : int = ...) -> ARC4Cipher: ... +def new(key: Buffer, drop: int = ...) -> ARC4Cipher: ... block_size: int key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Blowfish.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Blowfish.py index 536cbc80..c9912618 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Blowfish.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Blowfish.py @@ -34,13 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) _raw_blowfish_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_blowfish", - """ + "Cryptodome.Cipher._raw_blowfish", + """ int Blowfish_start_operation(const uint8_t key[], size_t key_len, void **pResult); @@ -53,97 +57,101 @@ uint8_t *out, size_t data_len); int Blowfish_stop_operation(void *state); - """ - ) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a smart pointer to - a low-level base cipher. It will absorb named parameters in - the process.""" - - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - if len(key) not in key_size: - raise ValueError("Incorrect Blowfish key length (%d bytes)" % len(key)) - - start_operation = _raw_blowfish_lib.Blowfish_start_operation - stop_operation = _raw_blowfish_lib.Blowfish_stop_operation - - void_p = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - void_p.address_of()) - if result: - raise ValueError("Error %X while instantiating the Blowfish cipher" - % result) - return SmartPointer(void_p.get(), stop_operation) + """This method instantiates and returns a smart pointer to + a low-level base cipher. It will absorb named parameters in + the process.""" + + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") + + if len(key) not in key_size: + raise ValueError("Incorrect Blowfish key length (%d bytes)" % len(key)) + + start_operation = _raw_blowfish_lib.Blowfish_start_operation + stop_operation = _raw_blowfish_lib.Blowfish_stop_operation + + void_p = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + void_p.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the Blowfish cipher" % result, + ) + return SmartPointer(void_p.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new Blowfish cipher + """Create a new Blowfish cipher + + :param key: + The secret key to use in the symmetric cipher. + Its length can vary from 5 to 56 bytes. + :type key: bytes, bytearray, memoryview - :param key: - The secret key to use in the symmetric cipher. - Its length can vary from 5 to 56 bytes. - :type key: bytes, bytearray, memoryview + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :Keyword Arguments: + * **iv** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + The initialization vector to use for encryption or decryption. - The initialization vector to use for encryption or decryption. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + * **nonce** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + A value that must never be reused for any other encryption done + with this key. - A value that must never be reused for any other encryption done - with this key. + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_CTR``, its length must be in the range **[0..7]**. - For ``MODE_CTR``, its length must be in the range **[0..7]**. + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + :Return: a Blowfish object, of the applicable mode. + """ - :Return: a Blowfish object, of the applicable mode. - """ + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Blowfish.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Blowfish.pyi index b8b21c69..57ec3796 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Blowfish.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Blowfish.pyi @@ -1,6 +1,6 @@ from typing import Union, Dict, Iterable, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode BlowfishMode = int @@ -20,16 +19,17 @@ MODE_CTR: BlowfishMode MODE_OPENPGP: BlowfishMode MODE_EAX: BlowfishMode -def new(key: Buffer, - mode: BlowfishMode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: BlowfishMode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/CAST.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/CAST.py index 84eb88ed..a6290455 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/CAST.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/CAST.py @@ -34,14 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util.py3compat import byte_string -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) _raw_cast_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_cast", - """ + "Cryptodome.Cipher._raw_cast", + """ int CAST_start_operation(const uint8_t key[], size_t key_len, void **pResult); @@ -54,96 +57,101 @@ uint8_t *out, size_t data_len); int CAST_stop_operation(void *state); - """) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" + """This method instantiates and returns a handle to a low-level + base cipher. It will absorb named parameters in the process.""" - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") - if len(key) not in key_size: - raise ValueError("Incorrect CAST key length (%d bytes)" % len(key)) + if len(key) not in key_size: + raise ValueError("Incorrect CAST key length (%d bytes)" % len(key)) - start_operation = _raw_cast_lib.CAST_start_operation - stop_operation = _raw_cast_lib.CAST_stop_operation + start_operation = _raw_cast_lib.CAST_start_operation + stop_operation = _raw_cast_lib.CAST_stop_operation - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the CAST cipher" - % result) + cipher = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the CAST cipher" % result, + ) - return SmartPointer(cipher.get(), stop_operation) + return SmartPointer(cipher.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new CAST cipher + """Create a new CAST cipher - :param key: - The secret key to use in the symmetric cipher. - Its length can vary from 5 to 16 bytes. - :type key: bytes, bytearray, memoryview + :param key: + The secret key to use in the symmetric cipher. + Its length can vary from 5 to 16 bytes. + :type key: bytes, bytearray, memoryview - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + :Keyword Arguments: + * **iv** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + * **nonce** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key. + A value that must never be reused for any other encryption done + with this key. - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CTR``, its length must be in the range **[0..7]**. + For ``MODE_CTR``, its length must be in the range **[0..7]**. - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - :Return: a CAST object, of the applicable mode. - """ + :Return: a CAST object, of the applicable mode. + """ + + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/CAST.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/CAST.pyi index be01f09b..68b55e33 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/CAST.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/CAST.pyi @@ -1,6 +1,6 @@ from typing import Union, Dict, Iterable, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode CASTMode = int @@ -20,16 +19,17 @@ MODE_CTR: CASTMode MODE_OPENPGP: CASTMode MODE_EAX: CASTMode -def new(key: Buffer, - mode: CASTMode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: CASTMode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int -key_size : Iterable[int] +key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20.py index b2759b97..a4be6e5b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20.py @@ -31,15 +31,21 @@ from Cryptodome.Random import get_random_bytes from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, VoidPointer, - SmartPointer, c_size_t, - c_uint8_ptr, c_ulong, - is_writeable_buffer) - -_raw_chacha20_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._chacha20", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + create_string_buffer, + get_raw_buffer, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + c_ulong, + is_writeable_buffer, +) + +_raw_chacha20_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._chacha20", + """ int chacha20_init(void **pState, const uint8_t *key, size_t keySize, @@ -61,228 +67,240 @@ int hchacha20( const uint8_t key[32], const uint8_t nonce16[16], uint8_t subkey[32]); - """) + """, +) def _HChaCha20(key, nonce): + assert len(key) == 32 + assert len(nonce) == 16 - assert(len(key) == 32) - assert(len(nonce) == 16) + subkey = bytearray(32) + result = _raw_chacha20_lib.hchacha20( + c_uint8_ptr(key), + c_uint8_ptr(nonce), + c_uint8_ptr(subkey), + ) + if result: + raise ValueError("Error %d when deriving subkey with HChaCha20" % result) - subkey = bytearray(32) - result = _raw_chacha20_lib.hchacha20( - c_uint8_ptr(key), - c_uint8_ptr(nonce), - c_uint8_ptr(subkey)) - if result: - raise ValueError("Error %d when deriving subkey with HChaCha20" % result) - - return subkey + return subkey class ChaCha20Cipher(object): - """ChaCha20 (or XChaCha20) cipher object. - Do not create it directly. Use :py:func:`new` instead. - - :var nonce: The nonce with length 8, 12 or 24 bytes - :vartype nonce: bytes - """ - - block_size = 1 - - def __init__(self, key, nonce): - """Initialize a ChaCha20/XChaCha20 cipher object - - See also `new()` at the module level.""" - - self.nonce = _copy_bytes(None, None, nonce) - - # XChaCha20 requires a key derivation with HChaCha20 - # See 2.3 in https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - if len(nonce) == 24: - key = _HChaCha20(key, nonce[:16]) - nonce = b'\x00' * 4 + nonce[16:] - self._name = "XChaCha20" - else: - self._name = "ChaCha20" - nonce = self.nonce - - self._next = ("encrypt", "decrypt") - - self._state = VoidPointer() - result = _raw_chacha20_lib.chacha20_init( - self._state.address_of(), - c_uint8_ptr(key), - c_size_t(len(key)), - nonce, - c_size_t(len(nonce))) - if result: - raise ValueError("Error %d instantiating a %s cipher" % (result, - self._name)) - self._state = SmartPointer(self._state.get(), - _raw_chacha20_lib.chacha20_destroy) - - def encrypt(self, plaintext, output=None): - """Encrypt a piece of data. - - Args: - plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the ciphertext - is written to. If ``None``, the ciphertext is returned. - Returns: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "encrypt" not in self._next: - raise TypeError("Cipher object can only be used for decryption") - self._next = ("encrypt",) - return self._encrypt(plaintext, output) - - def _encrypt(self, plaintext, output): - """Encrypt without FSM checks""" - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = _raw_chacha20_lib.chacha20_encrypt( - self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting with %s" % (result, self._name)) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt a piece of data. - - Args: - ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the plaintext - is written to. If ``None``, the plaintext is returned. - Returns: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("Cipher object can only be used for encryption") - self._next = ("decrypt",) - - try: - return self._encrypt(ciphertext, output) - except ValueError as e: - raise ValueError(str(e).replace("enc", "dec")) - - def seek(self, position): - """Seek to a certain position in the key stream. - - If you want to seek to a certain block, - use ``seek(block_number * 64)``. - - Args: - position (integer): - The absolute position within the key stream, in bytes. - """ - - block_number, offset = divmod(position, 64) - block_low = block_number & 0xFFFFFFFF - block_high = block_number >> 32 - - result = _raw_chacha20_lib.chacha20_seek( - self._state.get(), - c_ulong(block_high), - c_ulong(block_low), - offset - ) - if result: - raise ValueError("Error %d while seeking with %s" % (result, self._name)) + """ChaCha20 (or XChaCha20) cipher object. + Do not create it directly. Use :py:func:`new` instead. + + :var nonce: The nonce with length 8, 12 or 24 bytes + :vartype nonce: bytes + """ + + block_size = 1 + + def __init__(self, key, nonce): + """Initialize a ChaCha20/XChaCha20 cipher object + + See also `new()` at the module level.""" + + self.nonce = _copy_bytes(None, None, nonce) + + # XChaCha20 requires a key derivation with HChaCha20 + # See 2.3 in https://tools.ietf.org/html/draft-arciszewski-xchacha-03 + if len(nonce) == 24: + key = _HChaCha20(key, nonce[:16]) + nonce = b"\x00" * 4 + nonce[16:] + self._name = "XChaCha20" + else: + self._name = "ChaCha20" + nonce = self.nonce + + self._next = ("encrypt", "decrypt") + + self._state = VoidPointer() + result = _raw_chacha20_lib.chacha20_init( + self._state.address_of(), + c_uint8_ptr(key), + c_size_t(len(key)), + nonce, + c_size_t(len(nonce)), + ) + if result: + raise ValueError( + "Error %d instantiating a %s cipher" + % ( + result, + self._name, + ), + ) + self._state = SmartPointer( + self._state.get(), + _raw_chacha20_lib.chacha20_destroy, + ) + + def encrypt(self, plaintext, output=None): + """Encrypt a piece of data. + + Args: + plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the ciphertext + is written to. If ``None``, the ciphertext is returned. + Returns: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "encrypt" not in self._next: + raise TypeError("Cipher object can only be used for decryption") + self._next = ("encrypt",) + return self._encrypt(plaintext, output) + + def _encrypt(self, plaintext, output): + """Encrypt without FSM checks""" + + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = _raw_chacha20_lib.chacha20_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting with %s" % (result, self._name)) + + if output is None: + return get_raw_buffer(ciphertext) + else: + return None + + def decrypt(self, ciphertext, output=None): + """Decrypt a piece of data. + + Args: + ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the plaintext + is written to. If ``None``, the plaintext is returned. + Returns: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError("Cipher object can only be used for encryption") + self._next = ("decrypt",) + + try: + return self._encrypt(ciphertext, output) + except ValueError as e: + raise ValueError(str(e).replace("enc", "dec")) + + def seek(self, position): + """Seek to a certain position in the key stream. + + If you want to seek to a certain block, + use ``seek(block_number * 64)``. + + Args: + position (integer): + The absolute position within the key stream, in bytes. + """ + + block_number, offset = divmod(position, 64) + block_low = block_number & 0xFFFFFFFF + block_high = block_number >> 32 + + result = _raw_chacha20_lib.chacha20_seek( + self._state.get(), + c_ulong(block_high), + c_ulong(block_low), + offset, + ) + if result: + raise ValueError("Error %d while seeking with %s" % (result, self._name)) def _derive_Poly1305_key_pair(key, nonce): - """Derive a tuple (r, s, nonce) for a Poly1305 MAC. - - If nonce is ``None``, a new 12-byte nonce is generated. - """ - - if len(key) != 32: - raise ValueError("Poly1305 with ChaCha20 requires a 32-byte key") - - if nonce is None: - padded_nonce = nonce = get_random_bytes(12) - elif len(nonce) == 8: - # See RFC7538, 2.6: [...] ChaCha20 as specified here requires a 96-bit - # nonce. So if the provided nonce is only 64-bit, then the first 32 - # bits of the nonce will be set to a constant number. - # This will usually be zero, but for protocols with multiple senders it may be - # different for each sender, but should be the same for all - # invocations of the function with the same key by a particular - # sender. - padded_nonce = b'\x00\x00\x00\x00' + nonce - elif len(nonce) == 12: - padded_nonce = nonce - else: - raise ValueError("Poly1305 with ChaCha20 requires an 8- or 12-byte nonce") - - rs = new(key=key, nonce=padded_nonce).encrypt(b'\x00' * 32) - return rs[:16], rs[16:], nonce + """Derive a tuple (r, s, nonce) for a Poly1305 MAC. + + If nonce is ``None``, a new 12-byte nonce is generated. + """ + + if len(key) != 32: + raise ValueError("Poly1305 with ChaCha20 requires a 32-byte key") + + if nonce is None: + padded_nonce = nonce = get_random_bytes(12) + elif len(nonce) == 8: + # See RFC7538, 2.6: [...] ChaCha20 as specified here requires a 96-bit + # nonce. So if the provided nonce is only 64-bit, then the first 32 + # bits of the nonce will be set to a constant number. + # This will usually be zero, but for protocols with multiple senders it may be + # different for each sender, but should be the same for all + # invocations of the function with the same key by a particular + # sender. + padded_nonce = b"\x00\x00\x00\x00" + nonce + elif len(nonce) == 12: + padded_nonce = nonce + else: + raise ValueError("Poly1305 with ChaCha20 requires an 8- or 12-byte nonce") + + rs = new(key=key, nonce=padded_nonce).encrypt(b"\x00" * 32) + return rs[:16], rs[16:], nonce def new(**kwargs): - """Create a new ChaCha20 or XChaCha20 cipher + """Create a new ChaCha20 or XChaCha20 cipher + + Keyword Args: + key (bytes/bytearray/memoryview): The secret key to use. + It must be 32 bytes long. + nonce (bytes/bytearray/memoryview): A mandatory value that + must never be reused for any other encryption + done with this key. - Keyword Args: - key (bytes/bytearray/memoryview): The secret key to use. - It must be 32 bytes long. - nonce (bytes/bytearray/memoryview): A mandatory value that - must never be reused for any other encryption - done with this key. + For ChaCha20, it must be 8 or 12 bytes long. - For ChaCha20, it must be 8 or 12 bytes long. + For XChaCha20, it must be 24 bytes long. - For XChaCha20, it must be 24 bytes long. + If not provided, 8 bytes will be randomly generated + (you can find them back in the ``nonce`` attribute). - If not provided, 8 bytes will be randomly generated - (you can find them back in the ``nonce`` attribute). + :Return: a :class:`Cryptodome.Cipher.ChaCha20.ChaCha20Cipher` object + """ - :Return: a :class:`Cryptodome.Cipher.ChaCha20.ChaCha20Cipher` object - """ + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter %s" % e) - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter %s" % e) + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(8) - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(8) + if len(key) != 32: + raise ValueError("ChaCha20/XChaCha20 key must be 32 bytes long") - if len(key) != 32: - raise ValueError("ChaCha20/XChaCha20 key must be 32 bytes long") + if len(nonce) not in (8, 12, 24): + raise ValueError("Nonce must be 8/12 bytes(ChaCha20) or 24 bytes (XChaCha20)") - if len(nonce) not in (8, 12, 24): - raise ValueError("Nonce must be 8/12 bytes(ChaCha20) or 24 bytes (XChaCha20)") + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) + return ChaCha20Cipher(key, nonce) - return ChaCha20Cipher(key, nonce) # Size of a data block (in bytes) block_size = 1 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20.pyi index f5001cdb..593029a1 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20.pyi @@ -1,23 +1,23 @@ from typing import Union, overload, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview def _HChaCha20(key: Buffer, nonce: Buffer) -> bytearray: ... class ChaCha20Cipher: - block_size: int - nonce: bytes + block_size: int + nonce: bytes - def __init__(self, key: Buffer, nonce: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - def seek(self, position: int) -> None: ... + def __init__(self, key: Buffer, nonce: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def seek(self, position: int) -> None: ... def new(key: Buffer, nonce: Optional[Buffer] = ...) -> ChaCha20Cipher: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20_Poly1305.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20_Poly1305.py index 6a89e2ad..32530a75 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20_Poly1305.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20_Poly1305.py @@ -42,292 +42,305 @@ def _enum(**enums): - return type('Enum', (), enums) + return type("Enum", (), enums) -_CipherStatus = _enum(PROCESSING_AUTH_DATA=1, - PROCESSING_CIPHERTEXT=2, - PROCESSING_DONE=3) +_CipherStatus = _enum( + PROCESSING_AUTH_DATA=1, + PROCESSING_CIPHERTEXT=2, + PROCESSING_DONE=3, +) class ChaCha20Poly1305Cipher(object): - """ChaCha20-Poly1305 and XChaCha20-Poly1305 cipher object. - Do not create it directly. Use :py:func:`new` instead. + """ChaCha20-Poly1305 and XChaCha20-Poly1305 cipher object. + Do not create it directly. Use :py:func:`new` instead. + + :var nonce: The nonce with length 8, 12 or 24 bytes + :vartype nonce: byte string + """ + + def __init__(self, key, nonce): + """Initialize a ChaCha20-Poly1305 AEAD cipher object + + See also `new()` at the module level.""" + + self._next = ( + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ) + + self._authenticator = Poly1305.new(key=key, nonce=nonce, cipher=ChaCha20) - :var nonce: The nonce with length 8, 12 or 24 bytes - :vartype nonce: byte string - """ + self._cipher = ChaCha20.new(key=key, nonce=nonce) + self._cipher.seek(64) # Block counter starts at 1 - def __init__(self, key, nonce): - """Initialize a ChaCha20-Poly1305 AEAD cipher object + self._len_aad = 0 + self._len_ct = 0 + self._mac_tag = None + self._status = _CipherStatus.PROCESSING_AUTH_DATA - See also `new()` at the module level.""" + def update(self, data): + """Protect the associated data. - self._next = ("update", "encrypt", "decrypt", "digest", - "verify") + Associated data (also known as *additional authenticated data* - AAD) + is the piece of the message that must stay in the clear, while + still allowing the receiver to verify its integrity. + An example is packet headers. - self._authenticator = Poly1305.new(key=key, nonce=nonce, cipher=ChaCha20) + The associated data (possibly split into multiple segments) is + fed into :meth:`update` before any call to :meth:`decrypt` or :meth:`encrypt`. + If there is no associated data, :meth:`update` is not called. - self._cipher = ChaCha20.new(key=key, nonce=nonce) - self._cipher.seek(64) # Block counter starts at 1 + :param bytes/bytearray/memoryview assoc_data: + A piece of associated data. There are no restrictions on its size. + """ - self._len_aad = 0 - self._len_ct = 0 - self._mac_tag = None - self._status = _CipherStatus.PROCESSING_AUTH_DATA + if "update" not in self._next: + raise TypeError("update() method cannot be called") - def update(self, data): - """Protect the associated data. + self._len_aad += len(data) + self._authenticator.update(data) - Associated data (also known as *additional authenticated data* - AAD) - is the piece of the message that must stay in the clear, while - still allowing the receiver to verify its integrity. - An example is packet headers. + def _pad_aad(self): + assert self._status == _CipherStatus.PROCESSING_AUTH_DATA + if self._len_aad & 0x0F: + self._authenticator.update(b"\x00" * (16 - (self._len_aad & 0x0F))) + self._status = _CipherStatus.PROCESSING_CIPHERTEXT - The associated data (possibly split into multiple segments) is - fed into :meth:`update` before any call to :meth:`decrypt` or :meth:`encrypt`. - If there is no associated data, :meth:`update` is not called. + def encrypt(self, plaintext, output=None): + """Encrypt a piece of data. - :param bytes/bytearray/memoryview assoc_data: - A piece of associated data. There are no restrictions on its size. - """ + Args: + plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the ciphertext + is written to. If ``None``, the ciphertext is returned. + Returns: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "update" not in self._next: - raise TypeError("update() method cannot be called") + if "encrypt" not in self._next: + raise TypeError("encrypt() method cannot be called") - self._len_aad += len(data) - self._authenticator.update(data) + if self._status == _CipherStatus.PROCESSING_AUTH_DATA: + self._pad_aad() - def _pad_aad(self): + self._next = ("encrypt", "digest") - assert(self._status == _CipherStatus.PROCESSING_AUTH_DATA) - if self._len_aad & 0x0F: - self._authenticator.update(b'\x00' * (16 - (self._len_aad & 0x0F))) - self._status = _CipherStatus.PROCESSING_CIPHERTEXT + result = self._cipher.encrypt(plaintext, output=output) + self._len_ct += len(plaintext) + if output is None: + self._authenticator.update(result) + else: + self._authenticator.update(output) + return result - def encrypt(self, plaintext, output=None): - """Encrypt a piece of data. + def decrypt(self, ciphertext, output=None): + """Decrypt a piece of data. - Args: - plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the ciphertext - is written to. If ``None``, the ciphertext is returned. - Returns: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ + Args: + ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the plaintext + is written to. If ``None``, the plaintext is returned. + Returns: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() method cannot be called") + if "decrypt" not in self._next: + raise TypeError("decrypt() method cannot be called") - if self._status == _CipherStatus.PROCESSING_AUTH_DATA: - self._pad_aad() + if self._status == _CipherStatus.PROCESSING_AUTH_DATA: + self._pad_aad() - self._next = ("encrypt", "digest") + self._next = ("decrypt", "verify") - result = self._cipher.encrypt(plaintext, output=output) - self._len_ct += len(plaintext) - if output is None: - self._authenticator.update(result) - else: - self._authenticator.update(output) - return result + self._len_ct += len(ciphertext) + self._authenticator.update(ciphertext) + return self._cipher.decrypt(ciphertext, output=output) - def decrypt(self, ciphertext, output=None): - """Decrypt a piece of data. + def _compute_mac(self): + """Finalize the cipher (if not done already) and return the MAC.""" - Args: - ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the plaintext - is written to. If ``None``, the plaintext is returned. - Returns: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ + if self._mac_tag: + assert self._status == _CipherStatus.PROCESSING_DONE + return self._mac_tag - if "decrypt" not in self._next: - raise TypeError("decrypt() method cannot be called") + assert self._status != _CipherStatus.PROCESSING_DONE - if self._status == _CipherStatus.PROCESSING_AUTH_DATA: - self._pad_aad() + if self._status == _CipherStatus.PROCESSING_AUTH_DATA: + self._pad_aad() - self._next = ("decrypt", "verify") + if self._len_ct & 0x0F: + self._authenticator.update(b"\x00" * (16 - (self._len_ct & 0x0F))) - self._len_ct += len(ciphertext) - self._authenticator.update(ciphertext) - return self._cipher.decrypt(ciphertext, output=output) + self._status = _CipherStatus.PROCESSING_DONE - def _compute_mac(self): - """Finalize the cipher (if not done already) and return the MAC.""" + self._authenticator.update(long_to_bytes(self._len_aad, 8)[::-1]) + self._authenticator.update(long_to_bytes(self._len_ct, 8)[::-1]) + self._mac_tag = self._authenticator.digest() + return self._mac_tag - if self._mac_tag: - assert(self._status == _CipherStatus.PROCESSING_DONE) - return self._mac_tag + def digest(self): + """Compute the *binary* authentication tag (MAC). - assert(self._status != _CipherStatus.PROCESSING_DONE) + :Return: the MAC tag, as 16 ``bytes``. + """ - if self._status == _CipherStatus.PROCESSING_AUTH_DATA: - self._pad_aad() + if "digest" not in self._next: + raise TypeError("digest() method cannot be called") + self._next = ("digest",) - if self._len_ct & 0x0F: - self._authenticator.update(b'\x00' * (16 - (self._len_ct & 0x0F))) + return self._compute_mac() - self._status = _CipherStatus.PROCESSING_DONE + def hexdigest(self): + """Compute the *printable* authentication tag (MAC). - self._authenticator.update(long_to_bytes(self._len_aad, 8)[::-1]) - self._authenticator.update(long_to_bytes(self._len_ct, 8)[::-1]) - self._mac_tag = self._authenticator.digest() - return self._mac_tag + This method is like :meth:`digest`. - def digest(self): - """Compute the *binary* authentication tag (MAC). + :Return: the MAC tag, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) - :Return: the MAC tag, as 16 ``bytes``. - """ + def verify(self, received_mac_tag): + """Validate the *binary* authentication tag (MAC). - if "digest" not in self._next: - raise TypeError("digest() method cannot be called") - self._next = ("digest",) + The receiver invokes this method at the very end, to + check if the associated data (if any) and the decrypted + messages are valid. - return self._compute_mac() + :param bytes/bytearray/memoryview received_mac_tag: + This is the 16-byte *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - def hexdigest(self): - """Compute the *printable* authentication tag (MAC). + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ("verify",) - This method is like :meth:`digest`. + secret = get_random_bytes(16) - :Return: the MAC tag, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) + self._compute_mac() - def verify(self, received_mac_tag): - """Validate the *binary* authentication tag (MAC). + mac1 = BLAKE2s.new( + digest_bits=160, + key=secret, + data=self._mac_tag, + ) + mac2 = BLAKE2s.new( + digest_bits=160, + key=secret, + data=received_mac_tag, + ) - The receiver invokes this method at the very end, to - check if the associated data (if any) and the decrypted - messages are valid. + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - :param bytes/bytearray/memoryview received_mac_tag: - This is the 16-byte *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + def hexverify(self, hex_mac_tag): + """Validate the *printable* authentication tag (MAC). - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ("verify",) + This method is like :meth:`verify`. - secret = get_random_bytes(16) + :param string hex_mac_tag: + This is the *printable* MAC. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - self._compute_mac() + self.verify(unhexlify(hex_mac_tag)) - mac1 = BLAKE2s.new(digest_bits=160, key=secret, - data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, - data=received_mac_tag) + def encrypt_and_digest(self, plaintext): + """Perform :meth:`encrypt` and :meth:`digest` in one step. - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + :param plaintext: The data to encrypt, of any size. + :type plaintext: bytes/bytearray/memoryview + :return: a tuple with two ``bytes`` objects: - def hexverify(self, hex_mac_tag): - """Validate the *printable* authentication tag (MAC). + - the ciphertext, of equal length as the plaintext + - the 16-byte MAC tag + """ - This method is like :meth:`verify`. + return self.encrypt(plaintext), self.digest() - :param string hex_mac_tag: - This is the *printable* MAC. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + def decrypt_and_verify(self, ciphertext, received_mac_tag): + """Perform :meth:`decrypt` and :meth:`verify` in one step. - self.verify(unhexlify(hex_mac_tag)) + :param ciphertext: The piece of data to decrypt. + :type ciphertext: bytes/bytearray/memoryview + :param bytes received_mac_tag: + This is the 16-byte *binary* MAC, as received from the sender. + :return: the decrypted data (as ``bytes``) + :raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - def encrypt_and_digest(self, plaintext): - """Perform :meth:`encrypt` and :meth:`digest` in one step. - - :param plaintext: The data to encrypt, of any size. - :type plaintext: bytes/bytearray/memoryview - :return: a tuple with two ``bytes`` objects: - - - the ciphertext, of equal length as the plaintext - - the 16-byte MAC tag - """ - - return self.encrypt(plaintext), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag): - """Perform :meth:`decrypt` and :meth:`verify` in one step. - - :param ciphertext: The piece of data to decrypt. - :type ciphertext: bytes/bytearray/memoryview - :param bytes received_mac_tag: - This is the 16-byte *binary* MAC, as received from the sender. - :return: the decrypted data (as ``bytes``) - :raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - plaintext = self.decrypt(ciphertext) - self.verify(received_mac_tag) - return plaintext + plaintext = self.decrypt(ciphertext) + self.verify(received_mac_tag) + return plaintext def new(**kwargs): - """Create a new ChaCha20-Poly1305 or XChaCha20-Poly1305 AEAD cipher. + """Create a new ChaCha20-Poly1305 or XChaCha20-Poly1305 AEAD cipher. - :keyword key: The secret key to use. It must be 32 bytes long. - :type key: byte string + :keyword key: The secret key to use. It must be 32 bytes long. + :type key: byte string - :keyword nonce: - A value that must never be reused for any other encryption - done with this key. + :keyword nonce: + A value that must never be reused for any other encryption + done with this key. - For ChaCha20-Poly1305, it must be 8 or 12 bytes long. + For ChaCha20-Poly1305, it must be 8 or 12 bytes long. - For XChaCha20-Poly1305, it must be 24 bytes long. + For XChaCha20-Poly1305, it must be 24 bytes long. - If not provided, 12 ``bytes`` will be generated randomly - (you can find them back in the ``nonce`` attribute). - :type nonce: bytes, bytearray, memoryview + If not provided, 12 ``bytes`` will be generated randomly + (you can find them back in the ``nonce`` attribute). + :type nonce: bytes, bytearray, memoryview - :Return: a :class:`Cryptodome.Cipher.ChaCha20.ChaCha20Poly1305Cipher` object - """ + :Return: a :class:`Cryptodome.Cipher.ChaCha20.ChaCha20Poly1305Cipher` object + """ - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter %s" % e) + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter %s" % e) - if len(key) != 32: - raise ValueError("Key must be 32 bytes long") + if len(key) != 32: + raise ValueError("Key must be 32 bytes long") - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(12) + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(12) - if len(nonce) in (8, 12): - chacha20_poly1305_nonce = nonce - elif len(nonce) == 24: - key = _HChaCha20(key, nonce[:16]) - chacha20_poly1305_nonce = b'\x00\x00\x00\x00' + nonce[16:] - else: - raise ValueError("Nonce must be 8, 12 or 24 bytes long") + if len(nonce) in (8, 12): + chacha20_poly1305_nonce = nonce + elif len(nonce) == 24: + key = _HChaCha20(key, nonce[:16]) + chacha20_poly1305_nonce = b"\x00\x00\x00\x00" + nonce[16:] + else: + raise ValueError("Nonce must be 8, 12 or 24 bytes long") - if not is_buffer(nonce): - raise TypeError("nonce must be bytes, bytearray or memoryview") + if not is_buffer(nonce): + raise TypeError("nonce must be bytes, bytearray or memoryview") - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) - cipher = ChaCha20Poly1305Cipher(key, chacha20_poly1305_nonce) - cipher.nonce = _copy_bytes(None, None, nonce) - return cipher + cipher = ChaCha20Poly1305Cipher(key, chacha20_poly1305_nonce) + cipher.nonce = _copy_bytes(None, None, nonce) + return cipher # Size of a key (in bytes) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20_Poly1305.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20_Poly1305.pyi index 109e8051..69186118 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20_Poly1305.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/ChaCha20_Poly1305.pyi @@ -1,26 +1,26 @@ from typing import Union, Tuple, overload, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview class ChaCha20Poly1305Cipher: - nonce: bytes + nonce: bytes - def __init__(self, key: Buffer, nonce: Buffer) -> None: ... - def update(self, data: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, received_mac_tag: str) -> None: ... - def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... - def decrypt_and_verify(self, ciphertext: Buffer, received_mac_tag: Buffer) -> bytes: ... + def __init__(self, key: Buffer, nonce: Buffer) -> None: ... + def update(self, data: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, received_mac_tag: str) -> None: ... + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + def decrypt_and_verify(self, ciphertext: Buffer, received_mac_tag: Buffer) -> bytes: ... def new(key: Buffer, nonce: Optional[Buffer] = ...) -> ChaCha20Poly1305Cipher: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES.py index 026b491d..be0fae87 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES.py @@ -34,14 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util.py3compat import byte_string -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) _raw_des_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_des", - """ + "Cryptodome.Cipher._raw_des", + """ int DES_start_operation(const uint8_t key[], size_t key_len, void **pResult); @@ -54,95 +57,100 @@ uint8_t *out, size_t data_len); int DES_stop_operation(void *state); - """) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" + """This method instantiates and returns a handle to a low-level + base cipher. It will absorb named parameters in the process.""" - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") - if len(key) != key_size: - raise ValueError("Incorrect DES key length (%d bytes)" % len(key)) + if len(key) != key_size: + raise ValueError("Incorrect DES key length (%d bytes)" % len(key)) - start_operation = _raw_des_lib.DES_start_operation - stop_operation = _raw_des_lib.DES_stop_operation + start_operation = _raw_des_lib.DES_start_operation + stop_operation = _raw_des_lib.DES_stop_operation - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the DES cipher" - % result) - return SmartPointer(cipher.get(), stop_operation) + cipher = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the DES cipher" % result, + ) + return SmartPointer(cipher.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new DES cipher. + """Create a new DES cipher. - :param key: - The secret key to use in the symmetric cipher. - It must be 8 byte long. The parity bits will be ignored. - :type key: bytes/bytearray/memoryview + :param key: + The secret key to use in the symmetric cipher. + It must be 8 byte long. The parity bits will be ignored. + :type key: bytes/bytearray/memoryview - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :Keyword Arguments: - * **iv** (*byte string*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + :Keyword Arguments: + * **iv** (*byte string*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - * **nonce** (*byte string*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + * **nonce** (*byte string*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key. + A value that must never be reused for any other encryption done + with this key. - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CTR``, its length must be in the range **[0..7]**. + For ``MODE_CTR``, its length must be in the range **[0..7]**. - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - :Return: a DES object, of the applicable mode. - """ + :Return: a DES object, of the applicable mode. + """ + + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES.pyi index 25a3b230..57ed526f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES.pyi @@ -1,6 +1,6 @@ -from typing import Union, Dict, Iterable, Optional +from typing import Union, Dict, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode DESMode = int @@ -20,16 +19,17 @@ MODE_CTR: DESMode MODE_OPENPGP: DESMode MODE_EAX: DESMode -def new(key: Buffer, - mode: DESMode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: DESMode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int key_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES3.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES3.py index 3b2828eb..59eeb8c6 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES3.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES3.py @@ -34,14 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util.py3compat import byte_string, bchr, bord, bstr -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t) +from Cryptodome.Util.py3compat import bchr, bord, bstr +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, +) _raw_des3_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_des3", - """ + "Cryptodome.Cipher._raw_des3", + """ int DES3_start_operation(const uint8_t key[], size_t key_len, void **pResult); @@ -54,124 +57,129 @@ uint8_t *out, size_t data_len); int DES3_stop_operation(void *state); - """) + """, +) def adjust_key_parity(key_in): - """Set the parity bits in a TDES key. + """Set the parity bits in a TDES key. - :param key_in: the TDES key whose bits need to be adjusted - :type key_in: byte string + :param key_in: the TDES key whose bits need to be adjusted + :type key_in: byte string - :returns: a copy of ``key_in``, with the parity bits correctly set - :rtype: byte string + :returns: a copy of ``key_in``, with the parity bits correctly set + :rtype: byte string - :raises ValueError: if the TDES key is not 16 or 24 bytes long - :raises ValueError: if the TDES key degenerates into Single DES - """ + :raises ValueError: if the TDES key is not 16 or 24 bytes long + :raises ValueError: if the TDES key degenerates into Single DES + """ - def parity_byte(key_byte): - parity = 1 - for i in range(1, 8): - parity ^= (key_byte >> i) & 1 - return (key_byte & 0xFE) | parity + def parity_byte(key_byte): + parity = 1 + for i in range(1, 8): + parity ^= (key_byte >> i) & 1 + return (key_byte & 0xFE) | parity - if len(key_in) not in key_size: - raise ValueError("Not a valid TDES key") + if len(key_in) not in key_size: + raise ValueError("Not a valid TDES key") - key_out = b"".join([ bchr(parity_byte(bord(x))) for x in key_in ]) + key_out = b"".join([bchr(parity_byte(bord(x))) for x in key_in]) - if key_out[:8] == key_out[8:16] or key_out[-16:-8] == key_out[-8:]: - raise ValueError("Triple DES key degenerates to single DES") + if key_out[:8] == key_out[8:16] or key_out[-16:-8] == key_out[-8:]: + raise ValueError("Triple DES key degenerates to single DES") - return key_out + return key_out def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level base cipher. - It will absorb named parameters in the process.""" + """This method instantiates and returns a handle to a low-level base cipher. + It will absorb named parameters in the process.""" - try: - key_in = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") + try: + key_in = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") - key = adjust_key_parity(bstr(key_in)) + key = adjust_key_parity(bstr(key_in)) - start_operation = _raw_des3_lib.DES3_start_operation - stop_operation = _raw_des3_lib.DES3_stop_operation + start_operation = _raw_des3_lib.DES3_start_operation + stop_operation = _raw_des3_lib.DES3_stop_operation - cipher = VoidPointer() - result = start_operation(key, - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the TDES cipher" - % result) - return SmartPointer(cipher.get(), stop_operation) + cipher = VoidPointer() + result = start_operation( + key, + c_size_t(len(key)), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the TDES cipher" % result, + ) + return SmartPointer(cipher.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new Triple DES cipher. + """Create a new Triple DES cipher. - :param key: - The secret key to use in the symmetric cipher. - It must be 16 or 24 byte long. The parity bits will be ignored. - :type key: bytes/bytearray/memoryview + :param key: + The secret key to use in the symmetric cipher. + It must be 16 or 24 byte long. The parity bits will be ignored. + :type key: bytes/bytearray/memoryview - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + :Keyword Arguments: + * **iv** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + * **nonce** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key. + A value that must never be reused for any other encryption done + with this key. - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CTR``, its length must be in the range **[0..7]**. + For ``MODE_CTR``, its length must be in the range **[0..7]**. - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - :Return: a Triple DES object, of the applicable mode. - """ + :Return: a Triple DES object, of the applicable mode. + """ + + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES3.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES3.pyi index 2c150f86..f247a74e 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES3.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/DES3.pyi @@ -1,6 +1,6 @@ from typing import Union, Dict, Tuple, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode def adjust_key_parity(key_in: bytes) -> bytes: ... @@ -22,16 +21,17 @@ MODE_CTR: DES3Mode MODE_OPENPGP: DES3Mode MODE_EAX: DES3Mode -def new(key: Buffer, - mode: DES3Mode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: DES3Mode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int key_size: Tuple[int, int] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_OAEP.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_OAEP.py index 08f9efe5..a7a41194 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_OAEP.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_OAEP.py @@ -32,200 +32,200 @@ class PKCS1OAEP_Cipher: - """Cipher object for PKCS#1 v1.5 OAEP. - Do not create directly: use :func:`new` instead.""" - - def __init__(self, key, hashAlgo, mgfunc, label, randfunc): - """Initialize this PKCS#1 OAEP cipher object. - - :Parameters: - key : an RSA key object - If a private half is given, both encryption and decryption are possible. - If a public half is given, only encryption is possible. - hashAlgo : hash object - The hash function to use. This can be a module under `Cryptodome.Hash` - or an existing hash object created from any of such modules. If not specified, - `Cryptodome.Hash.SHA1` is used. - mgfunc : callable - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice). - label : bytes/bytearray/memoryview - A label to apply to this particular encryption. If not specified, - an empty string is used. Specifying a label does not improve - security. - randfunc : callable - A function that returns random bytes. - - :attention: Modify the mask generation function only if you know what you are doing. - Sender and receiver must use the same one. - """ - self._key = key - - if hashAlgo: - self._hashObj = hashAlgo - else: - self._hashObj = Cryptodome.Hash.SHA1 - - if mgfunc: - self._mgf = mgfunc - else: - self._mgf = lambda x, y: MGF1(x, y, self._hashObj) - - self._label = _copy_bytes(None, None, label) - self._randfunc = randfunc - - def can_encrypt(self): - """Legacy function to check if you can call :meth:`encrypt`. - - .. deprecated:: 3.0""" - return self._key.can_encrypt() - - def can_decrypt(self): - """Legacy function to check if you can call :meth:`decrypt`. - - .. deprecated:: 3.0""" - return self._key.can_decrypt() - - def encrypt(self, message): - """Encrypt a message with PKCS#1 OAEP. - - :param message: - The message to encrypt, also known as plaintext. It can be of - variable length, but not longer than the RSA modulus (in bytes) - minus 2, minus twice the hash output size. - For instance, if you use RSA 2048 and SHA-256, the longest message - you can encrypt is 190 byte long. - :type message: bytes/bytearray/memoryview - - :returns: The ciphertext, as large as the RSA modulus. - :rtype: bytes - - :raises ValueError: - if the message is too long. - """ - - # See 7.1.1 in RFC3447 - modBits = Cryptodome.Util.number.size(self._key.n) - k = ceil_div(modBits, 8) # Convert from bits to bytes - hLen = self._hashObj.digest_size - mLen = len(message) - - # Step 1b - ps_len = k - mLen - 2 * hLen - 2 - if ps_len < 0: - raise ValueError("Plaintext is too long.") - # Step 2a - lHash = self._hashObj.new(self._label).digest() - # Step 2b - ps = b'\x00' * ps_len - # Step 2c - db = lHash + ps + b'\x01' + _copy_bytes(None, None, message) - # Step 2d - ros = self._randfunc(hLen) - # Step 2e - dbMask = self._mgf(ros, k-hLen-1) - # Step 2f - maskedDB = strxor(db, dbMask) - # Step 2g - seedMask = self._mgf(maskedDB, hLen) - # Step 2h - maskedSeed = strxor(ros, seedMask) - # Step 2i - em = b'\x00' + maskedSeed + maskedDB - # Step 3a (OS2IP) - em_int = bytes_to_long(em) - # Step 3b (RSAEP) - m_int = self._key._encrypt(em_int) - # Step 3c (I2OSP) - c = long_to_bytes(m_int, k) - return c - - def decrypt(self, ciphertext): - """Decrypt a message with PKCS#1 OAEP. - - :param ciphertext: The encrypted message. - :type ciphertext: bytes/bytearray/memoryview - - :returns: The original message (plaintext). - :rtype: bytes - - :raises ValueError: - if the ciphertext has the wrong length, or if decryption - fails the integrity check (in which case, the decryption - key is probably wrong). - :raises TypeError: - if the RSA key has no private half (i.e. you are trying - to decrypt using a public key). - """ - - # See 7.1.2 in RFC3447 - modBits = Cryptodome.Util.number.size(self._key.n) - k = ceil_div(modBits, 8) # Convert from bits to bytes - hLen = self._hashObj.digest_size - - # Step 1b and 1c - if len(ciphertext) != k or k < hLen+2: - raise ValueError("Ciphertext with incorrect length.") - # Step 2a (O2SIP) - ct_int = bytes_to_long(ciphertext) - # Step 2b (RSADP) and step 2c (I2OSP) - em = self._key._decrypt_to_bytes(ct_int) - # Step 3a - lHash = self._hashObj.new(self._label).digest() - # y must be 0, but we MUST NOT check it here in order not to - # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143) - maskedSeed = em[1:hLen+1] - maskedDB = em[hLen+1:] - # Step 3c - seedMask = self._mgf(maskedDB, hLen) - # Step 3d - seed = strxor(maskedSeed, seedMask) - # Step 3e - dbMask = self._mgf(seed, k-hLen-1) - # Step 3f - db = strxor(maskedDB, dbMask) - # Step 3b + 3g - res = oaep_decode(em, lHash, db) - if res <= 0: - raise ValueError("Incorrect decryption.") - # Step 4 - return db[res:] - - -def new(key, hashAlgo=None, mgfunc=None, label=b'', randfunc=None): - """Return a cipher object :class:`PKCS1OAEP_Cipher` - that can be used to perform PKCS#1 OAEP encryption or decryption. - - :param key: - The key object to use to encrypt or decrypt the message. - Decryption is only possible with a private RSA key. - :type key: RSA key object - - :param hashAlgo: - The hash function to use. This can be a module under `Cryptodome.Hash` - or an existing hash object created from any of such modules. - If not specified, `Cryptodome.Hash.SHA1` is used. - :type hashAlgo: hash object - - :param mgfunc: - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice). - :type mgfunc: callable - - :param label: - A label to apply to this particular encryption. If not specified, - an empty string is used. Specifying a label does not improve - security. - :type label: bytes/bytearray/memoryview - - :param randfunc: - A function that returns random bytes. - The default is `Random.get_random_bytes`. - :type randfunc: callable - """ - - if randfunc is None: - randfunc = Random.get_random_bytes - return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc) + """Cipher object for PKCS#1 v1.5 OAEP. + Do not create directly: use :func:`new` instead.""" + + def __init__(self, key, hashAlgo, mgfunc, label, randfunc): + """Initialize this PKCS#1 OAEP cipher object. + + :Parameters: + key : an RSA key object + If a private half is given, both encryption and decryption are possible. + If a public half is given, only encryption is possible. + hashAlgo : hash object + The hash function to use. This can be a module under `Cryptodome.Hash` + or an existing hash object created from any of such modules. If not specified, + `Cryptodome.Hash.SHA1` is used. + mgfunc : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice). + label : bytes/bytearray/memoryview + A label to apply to this particular encryption. If not specified, + an empty string is used. Specifying a label does not improve + security. + randfunc : callable + A function that returns random bytes. + + :attention: Modify the mask generation function only if you know what you are doing. + Sender and receiver must use the same one. + """ + self._key = key + + if hashAlgo: + self._hashObj = hashAlgo + else: + self._hashObj = Cryptodome.Hash.SHA1 + + if mgfunc: + self._mgf = mgfunc + else: + self._mgf = lambda x, y: MGF1(x, y, self._hashObj) + + self._label = _copy_bytes(None, None, label) + self._randfunc = randfunc + + def can_encrypt(self): + """Legacy function to check if you can call :meth:`encrypt`. + + .. deprecated:: 3.0""" + return self._key.can_encrypt() + + def can_decrypt(self): + """Legacy function to check if you can call :meth:`decrypt`. + + .. deprecated:: 3.0""" + return self._key.can_decrypt() + + def encrypt(self, message): + """Encrypt a message with PKCS#1 OAEP. + + :param message: + The message to encrypt, also known as plaintext. It can be of + variable length, but not longer than the RSA modulus (in bytes) + minus 2, minus twice the hash output size. + For instance, if you use RSA 2048 and SHA-256, the longest message + you can encrypt is 190 byte long. + :type message: bytes/bytearray/memoryview + + :returns: The ciphertext, as large as the RSA modulus. + :rtype: bytes + + :raises ValueError: + if the message is too long. + """ + + # See 7.1.1 in RFC3447 + modBits = Cryptodome.Util.number.size(self._key.n) + k = ceil_div(modBits, 8) # Convert from bits to bytes + hLen = self._hashObj.digest_size + mLen = len(message) + + # Step 1b + ps_len = k - mLen - 2 * hLen - 2 + if ps_len < 0: + raise ValueError("Plaintext is too long.") + # Step 2a + lHash = self._hashObj.new(self._label).digest() + # Step 2b + ps = b"\x00" * ps_len + # Step 2c + db = lHash + ps + b"\x01" + _copy_bytes(None, None, message) + # Step 2d + ros = self._randfunc(hLen) + # Step 2e + dbMask = self._mgf(ros, k - hLen - 1) + # Step 2f + maskedDB = strxor(db, dbMask) + # Step 2g + seedMask = self._mgf(maskedDB, hLen) + # Step 2h + maskedSeed = strxor(ros, seedMask) + # Step 2i + em = b"\x00" + maskedSeed + maskedDB + # Step 3a (OS2IP) + em_int = bytes_to_long(em) + # Step 3b (RSAEP) + m_int = self._key._encrypt(em_int) + # Step 3c (I2OSP) + c = long_to_bytes(m_int, k) + return c + + def decrypt(self, ciphertext): + """Decrypt a message with PKCS#1 OAEP. + + :param ciphertext: The encrypted message. + :type ciphertext: bytes/bytearray/memoryview + + :returns: The original message (plaintext). + :rtype: bytes + + :raises ValueError: + if the ciphertext has the wrong length, or if decryption + fails the integrity check (in which case, the decryption + key is probably wrong). + :raises TypeError: + if the RSA key has no private half (i.e. you are trying + to decrypt using a public key). + """ + + # See 7.1.2 in RFC3447 + modBits = Cryptodome.Util.number.size(self._key.n) + k = ceil_div(modBits, 8) # Convert from bits to bytes + hLen = self._hashObj.digest_size + + # Step 1b and 1c + if len(ciphertext) != k or k < hLen + 2: + raise ValueError("Ciphertext with incorrect length.") + # Step 2a (O2SIP) + ct_int = bytes_to_long(ciphertext) + # Step 2b (RSADP) and step 2c (I2OSP) + em = self._key._decrypt_to_bytes(ct_int) + # Step 3a + lHash = self._hashObj.new(self._label).digest() + # y must be 0, but we MUST NOT check it here in order not to + # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143) + maskedSeed = em[1 : hLen + 1] + maskedDB = em[hLen + 1 :] + # Step 3c + seedMask = self._mgf(maskedDB, hLen) + # Step 3d + seed = strxor(maskedSeed, seedMask) + # Step 3e + dbMask = self._mgf(seed, k - hLen - 1) + # Step 3f + db = strxor(maskedDB, dbMask) + # Step 3b + 3g + res = oaep_decode(em, lHash, db) + if res <= 0: + raise ValueError("Incorrect decryption.") + # Step 4 + return db[res:] + + +def new(key, hashAlgo=None, mgfunc=None, label=b"", randfunc=None): + """Return a cipher object :class:`PKCS1OAEP_Cipher` + that can be used to perform PKCS#1 OAEP encryption or decryption. + + :param key: + The key object to use to encrypt or decrypt the message. + Decryption is only possible with a private RSA key. + :type key: RSA key object + + :param hashAlgo: + The hash function to use. This can be a module under `Cryptodome.Hash` + or an existing hash object created from any of such modules. + If not specified, `Cryptodome.Hash.SHA1` is used. + :type hashAlgo: hash object + + :param mgfunc: + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice). + :type mgfunc: callable + + :param label: + A label to apply to this particular encryption. If not specified, + an empty string is used. Specifying a label does not improve + security. + :type label: bytes/bytearray/memoryview + + :param randfunc: + A function that returns random bytes. + The default is `Random.get_random_bytes`. + :type randfunc: callable + """ + + if randfunc is None: + randfunc = Random.get_random_bytes + return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_OAEP.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_OAEP.pyi index b54cd3f3..733d41da 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_OAEP.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_OAEP.pyi @@ -1,35 +1,39 @@ -from typing import Optional, Union, Callable, Any, overload +from typing import Optional, Union, Callable, Any from typing_extensions import Protocol from Cryptodome.PublicKey.RSA import RsaKey class HashLikeClass(Protocol): - digest_size : int - def new(self, data: Optional[bytes] = ...) -> Any: ... + digest_size: int + def new(self, data: Optional[bytes] = ...) -> Any: ... class HashLikeModule(Protocol): - digest_size : int - @staticmethod - def new(data: Optional[bytes] = ...) -> Any: ... + digest_size: int + @staticmethod + def new(data: Optional[bytes] = ...) -> Any: ... HashLike = Union[HashLikeClass, HashLikeModule] Buffer = Union[bytes, bytearray, memoryview] class PKCS1OAEP_Cipher: - def __init__(self, - key: RsaKey, - hashAlgo: HashLike, - mgfunc: Callable[[bytes, int], bytes], - label: Buffer, - randfunc: Callable[[int], bytes]) -> None: ... - def can_encrypt(self) -> bool: ... - def can_decrypt(self) -> bool: ... - def encrypt(self, message: Buffer) -> bytes: ... - def decrypt(self, ciphertext: Buffer) -> bytes: ... + def __init__( + self, + key: RsaKey, + hashAlgo: HashLike, + mgfunc: Callable[[bytes, int], bytes], + label: Buffer, + randfunc: Callable[[int], bytes], + ) -> None: ... + def can_encrypt(self) -> bool: ... + def can_decrypt(self) -> bool: ... + def encrypt(self, message: Buffer) -> bytes: ... + def decrypt(self, ciphertext: Buffer) -> bytes: ... -def new(key: RsaKey, - hashAlgo: Optional[HashLike] = ..., - mgfunc: Optional[Callable[[bytes, int], bytes]] = ..., - label: Optional[Buffer] = ..., - randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS1OAEP_Cipher: ... +def new( + key: RsaKey, + hashAlgo: Optional[HashLike] = ..., + mgfunc: Optional[Callable[[bytes, int], bytes]] = ..., + label: Optional[Buffer] = ..., + randfunc: Optional[Callable[[int], bytes]] = ..., +) -> PKCS1OAEP_Cipher: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_v1_5.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_v1_5.py index d7a9b793..82f7c59a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_v1_5.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_v1_5.py @@ -20,7 +20,7 @@ # SOFTWARE. # =================================================================== -__all__ = ['new', 'PKCS115_Cipher'] +__all__ = ["new", "PKCS115_Cipher"] from Cryptodome import Random from Cryptodome.Util.number import bytes_to_long, long_to_bytes @@ -29,161 +29,161 @@ class PKCS115_Cipher: - """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption. - Do not instantiate directly. Use :func:`Cryptodome.Cipher.PKCS1_v1_5.new` instead.""" - - def __init__(self, key, randfunc): - """Initialize this PKCS#1 v1.5 cipher object. - - :Parameters: - key : an RSA key object - If a private half is given, both encryption and decryption are possible. - If a public half is given, only encryption is possible. - randfunc : callable - Function that returns random bytes. - """ - - self._key = key - self._randfunc = randfunc - - def can_encrypt(self): - """Return True if this cipher object can be used for encryption.""" - return self._key.can_encrypt() - - def can_decrypt(self): - """Return True if this cipher object can be used for decryption.""" - return self._key.can_decrypt() - - def encrypt(self, message): - """Produce the PKCS#1 v1.5 encryption of a message. - - This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and it is specified in - `section 7.2.1 of RFC8017 - `_. - - :param message: - The message to encrypt, also known as plaintext. It can be of - variable length, but not longer than the RSA modulus (in bytes) minus 11. - :type message: bytes/bytearray/memoryview - - :Returns: A byte string, the ciphertext in which the message is encrypted. - It is as long as the RSA modulus (in bytes). - - :Raises ValueError: - If the RSA key length is not sufficiently long to deal with the given - message. - """ - - # See 7.2.1 in RFC8017 - k = self._key.size_in_bytes() - mLen = len(message) - - # Step 1 - if mLen > k - 11: - raise ValueError("Plaintext is too long.") - # Step 2a - ps = [] - while len(ps) != k - mLen - 3: - new_byte = self._randfunc(1) - if bord(new_byte[0]) == 0x00: - continue - ps.append(new_byte) - ps = b"".join(ps) - # Step 2b - em = b'\x00\x02' + ps + b'\x00' + _copy_bytes(None, None, message) - # Step 3a (OS2IP) - em_int = bytes_to_long(em) - # Step 3b (RSAEP) - m_int = self._key._encrypt(em_int) - # Step 3c (I2OSP) - c = long_to_bytes(m_int, k) - return c - - def decrypt(self, ciphertext, sentinel, expected_pt_len=0): - r"""Decrypt a PKCS#1 v1.5 ciphertext. - - This is the function ``RSAES-PKCS1-V1_5-DECRYPT`` specified in - `section 7.2.2 of RFC8017 - `_. - - Args: - ciphertext (bytes/bytearray/memoryview): - The ciphertext that contains the message to recover. - sentinel (any type): - The object to return whenever an error is detected. - expected_pt_len (integer): - The length the plaintext is known to have, or 0 if unknown. - - Returns (byte string): - It is either the original message or the ``sentinel`` (in case of an error). - - .. warning:: - PKCS#1 v1.5 decryption is intrinsically vulnerable to timing - attacks (see `Bleichenbacher's`__ attack). - **Use PKCS#1 OAEP instead**. - - This implementation attempts to mitigate the risk - with some constant-time constructs. - However, they are not sufficient by themselves: the type of protocol you - implement and the way you handle errors make a big difference. - - Specifically, you should make it very hard for the (malicious) - party that submitted the ciphertext to quickly understand if decryption - succeeded or not. - - To this end, it is recommended that your protocol only encrypts - plaintexts of fixed length (``expected_pt_len``), - that ``sentinel`` is a random byte string of the same length, - and that processing continues for as long - as possible even if ``sentinel`` is returned (i.e. in case of - incorrect decryption). - - .. __: https://dx.doi.org/10.1007/BFb0055716 - """ - - # See 7.2.2 in RFC8017 - k = self._key.size_in_bytes() - - # Step 1 - if len(ciphertext) != k: - raise ValueError("Ciphertext with incorrect length (not %d bytes)" % k) - - # Step 2a (O2SIP) - ct_int = bytes_to_long(ciphertext) - - # Step 2b (RSADP) and Step 2c (I2OSP) - em = self._key._decrypt_to_bytes(ct_int) - - # Step 3 (not constant time when the sentinel is not a byte string) - output = bytes(bytearray(k)) - if not is_bytes(sentinel) or len(sentinel) > k: - size = pkcs1_decode(em, b'', expected_pt_len, output) - if size < 0: - return sentinel - else: - return output[size:] - - # Step 3 (somewhat constant time) - size = pkcs1_decode(em, sentinel, expected_pt_len, output) - return output[size:] + """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption. + Do not instantiate directly. Use :func:`Cryptodome.Cipher.PKCS1_v1_5.new` instead.""" + + def __init__(self, key, randfunc): + """Initialize this PKCS#1 v1.5 cipher object. + + :Parameters: + key : an RSA key object + If a private half is given, both encryption and decryption are possible. + If a public half is given, only encryption is possible. + randfunc : callable + Function that returns random bytes. + """ + + self._key = key + self._randfunc = randfunc + + def can_encrypt(self): + """Return True if this cipher object can be used for encryption.""" + return self._key.can_encrypt() + + def can_decrypt(self): + """Return True if this cipher object can be used for decryption.""" + return self._key.can_decrypt() + + def encrypt(self, message): + """Produce the PKCS#1 v1.5 encryption of a message. + + This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and it is specified in + `section 7.2.1 of RFC8017 + `_. + + :param message: + The message to encrypt, also known as plaintext. It can be of + variable length, but not longer than the RSA modulus (in bytes) minus 11. + :type message: bytes/bytearray/memoryview + + :Returns: A byte string, the ciphertext in which the message is encrypted. + It is as long as the RSA modulus (in bytes). + + :Raises ValueError: + If the RSA key length is not sufficiently long to deal with the given + message. + """ + + # See 7.2.1 in RFC8017 + k = self._key.size_in_bytes() + mLen = len(message) + + # Step 1 + if mLen > k - 11: + raise ValueError("Plaintext is too long.") + # Step 2a + ps = [] + while len(ps) != k - mLen - 3: + new_byte = self._randfunc(1) + if bord(new_byte[0]) == 0x00: + continue + ps.append(new_byte) + ps = b"".join(ps) + # Step 2b + em = b"\x00\x02" + ps + b"\x00" + _copy_bytes(None, None, message) + # Step 3a (OS2IP) + em_int = bytes_to_long(em) + # Step 3b (RSAEP) + m_int = self._key._encrypt(em_int) + # Step 3c (I2OSP) + c = long_to_bytes(m_int, k) + return c + + def decrypt(self, ciphertext, sentinel, expected_pt_len=0): + r"""Decrypt a PKCS#1 v1.5 ciphertext. + + This is the function ``RSAES-PKCS1-V1_5-DECRYPT`` specified in + `section 7.2.2 of RFC8017 + `_. + + Args: + ciphertext (bytes/bytearray/memoryview): + The ciphertext that contains the message to recover. + sentinel (any type): + The object to return whenever an error is detected. + expected_pt_len (integer): + The length the plaintext is known to have, or 0 if unknown. + + Returns (byte string): + It is either the original message or the ``sentinel`` (in case of an error). + + .. warning:: + PKCS#1 v1.5 decryption is intrinsically vulnerable to timing + attacks (see `Bleichenbacher's`__ attack). + **Use PKCS#1 OAEP instead**. + + This implementation attempts to mitigate the risk + with some constant-time constructs. + However, they are not sufficient by themselves: the type of protocol you + implement and the way you handle errors make a big difference. + + Specifically, you should make it very hard for the (malicious) + party that submitted the ciphertext to quickly understand if decryption + succeeded or not. + + To this end, it is recommended that your protocol only encrypts + plaintexts of fixed length (``expected_pt_len``), + that ``sentinel`` is a random byte string of the same length, + and that processing continues for as long + as possible even if ``sentinel`` is returned (i.e. in case of + incorrect decryption). + + .. __: https://dx.doi.org/10.1007/BFb0055716 + """ + + # See 7.2.2 in RFC8017 + k = self._key.size_in_bytes() + + # Step 1 + if len(ciphertext) != k: + raise ValueError("Ciphertext with incorrect length (not %d bytes)" % k) + + # Step 2a (O2SIP) + ct_int = bytes_to_long(ciphertext) + + # Step 2b (RSADP) and Step 2c (I2OSP) + em = self._key._decrypt_to_bytes(ct_int) + + # Step 3 (not constant time when the sentinel is not a byte string) + output = bytes(bytearray(k)) + if not is_bytes(sentinel) or len(sentinel) > k: + size = pkcs1_decode(em, b"", expected_pt_len, output) + if size < 0: + return sentinel + else: + return output[size:] + + # Step 3 (somewhat constant time) + size = pkcs1_decode(em, sentinel, expected_pt_len, output) + return output[size:] def new(key, randfunc=None): - """Create a cipher for performing PKCS#1 v1.5 encryption or decryption. + """Create a cipher for performing PKCS#1 v1.5 encryption or decryption. - :param key: - The key to use to encrypt or decrypt the message. This is a `Cryptodome.PublicKey.RSA` object. - Decryption is only possible if *key* is a private RSA key. - :type key: RSA key object + :param key: + The key to use to encrypt or decrypt the message. This is a `Cryptodome.PublicKey.RSA` object. + Decryption is only possible if *key* is a private RSA key. + :type key: RSA key object - :param randfunc: - Function that return random bytes. - The default is :func:`Cryptodome.Random.get_random_bytes`. - :type randfunc: callable + :param randfunc: + Function that return random bytes. + The default is :func:`Cryptodome.Random.get_random_bytes`. + :type randfunc: callable - :returns: A cipher object `PKCS115_Cipher`. - """ + :returns: A cipher object `PKCS115_Cipher`. + """ - if randfunc is None: - randfunc = Random.get_random_bytes - return PKCS115_Cipher(key, randfunc) + if randfunc is None: + randfunc = Random.get_random_bytes + return PKCS115_Cipher(key, randfunc) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_v1_5.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_v1_5.pyi index b69f5095..e4ed0738 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_v1_5.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/PKCS1_v1_5.pyi @@ -1,20 +1,17 @@ -from typing import Callable, Union, Any, Optional, TypeVar +from typing import Callable, Union, Optional, TypeVar from Cryptodome.PublicKey.RSA import RsaKey Buffer = Union[bytes, bytearray, memoryview] -T = TypeVar('T') +T = TypeVar("T") class PKCS115_Cipher: - def __init__(self, - key: RsaKey, - randfunc: Callable[[int], bytes]) -> None: ... - def can_encrypt(self) -> bool: ... - def can_decrypt(self) -> bool: ... - def encrypt(self, message: Buffer) -> bytes: ... - def decrypt(self, ciphertext: Buffer, - sentinel: T, - expected_pt_len: Optional[int] = ...) -> Union[bytes, T]: ... + def __init__(self, key: RsaKey, randfunc: Callable[[int], bytes]) -> None: ... + def can_encrypt(self) -> bool: ... + def can_decrypt(self) -> bool: ... + def encrypt(self, message: Buffer) -> bytes: ... + def decrypt( + self, ciphertext: Buffer, sentinel: T, expected_pt_len: Optional[int] = ... + ) -> Union[bytes, T]: ... -def new(key: RsaKey, - randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS115_Cipher: ... +def new(key: RsaKey, randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS115_Cipher: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Salsa20.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Salsa20.py index 79e67017..22b4bfe2 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Salsa20.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Salsa20.py @@ -23,16 +23,22 @@ # =================================================================== from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, VoidPointer, - SmartPointer, c_size_t, - c_uint8_ptr, is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + create_string_buffer, + get_raw_buffer, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes -_raw_salsa20_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._Salsa20", - """ +_raw_salsa20_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._Salsa20", + """ int Salsa20_stream_init(uint8_t *key, size_t keylen, uint8_t *nonce, size_t nonce_len, void **pSalsaState); @@ -40,128 +46,135 @@ int Salsa20_stream_encrypt(void *salsaState, const uint8_t in[], uint8_t out[], size_t len); - """) + """, +) class Salsa20Cipher: - """Salsa20 cipher object. Do not create it directly. Use :py:func:`new` - instead. - - :var nonce: The nonce with length 8 - :vartype nonce: byte string - """ - - def __init__(self, key, nonce): - """Initialize a Salsa20 cipher object - - See also `new()` at the module level.""" - - if len(key) not in key_size: - raise ValueError("Incorrect key length for Salsa20 (%d bytes)" % len(key)) - - if len(nonce) != 8: - raise ValueError("Incorrect nonce length for Salsa20 (%d bytes)" % - len(nonce)) - - self.nonce = _copy_bytes(None, None, nonce) - - self._state = VoidPointer() - result = _raw_salsa20_lib.Salsa20_stream_init( - c_uint8_ptr(key), - c_size_t(len(key)), - c_uint8_ptr(nonce), - c_size_t(len(nonce)), - self._state.address_of()) - if result: - raise ValueError("Error %d instantiating a Salsa20 cipher") - self._state = SmartPointer(self._state.get(), - _raw_salsa20_lib.Salsa20_stream_destroy) - - self.block_size = 1 - self.key_size = len(key) - - def encrypt(self, plaintext, output=None): - """Encrypt a piece of data. - - Args: - plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the ciphertext - is written to. If ``None``, the ciphertext is returned. - Returns: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = _raw_salsa20_lib.Salsa20_stream_encrypt( - self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting with Salsa20" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt a piece of data. - - Args: - ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the plaintext - is written to. If ``None``, the plaintext is returned. - Returns: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - try: - return self.encrypt(ciphertext, output=output) - except ValueError as e: - raise ValueError(str(e).replace("enc", "dec")) + """Salsa20 cipher object. Do not create it directly. Use :py:func:`new` + instead. + + :var nonce: The nonce with length 8 + :vartype nonce: byte string + """ + + def __init__(self, key, nonce): + """Initialize a Salsa20 cipher object + + See also `new()` at the module level.""" + + if len(key) not in key_size: + raise ValueError("Incorrect key length for Salsa20 (%d bytes)" % len(key)) + + if len(nonce) != 8: + raise ValueError( + "Incorrect nonce length for Salsa20 (%d bytes)" % len(nonce), + ) + + self.nonce = _copy_bytes(None, None, nonce) + + self._state = VoidPointer() + result = _raw_salsa20_lib.Salsa20_stream_init( + c_uint8_ptr(key), + c_size_t(len(key)), + c_uint8_ptr(nonce), + c_size_t(len(nonce)), + self._state.address_of(), + ) + if result: + raise ValueError("Error %d instantiating a Salsa20 cipher") + self._state = SmartPointer( + self._state.get(), + _raw_salsa20_lib.Salsa20_stream_destroy, + ) + + self.block_size = 1 + self.key_size = len(key) + + def encrypt(self, plaintext, output=None): + """Encrypt a piece of data. + + Args: + plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the ciphertext + is written to. If ``None``, the ciphertext is returned. + Returns: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = _raw_salsa20_lib.Salsa20_stream_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting with Salsa20" % result) + + if output is None: + return get_raw_buffer(ciphertext) + else: + return None + + def decrypt(self, ciphertext, output=None): + """Decrypt a piece of data. + + Args: + ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the plaintext + is written to. If ``None``, the plaintext is returned. + Returns: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + try: + return self.encrypt(ciphertext, output=output) + except ValueError as e: + raise ValueError(str(e).replace("enc", "dec")) def new(key, nonce=None): - """Create a new Salsa20 cipher + """Create a new Salsa20 cipher - :keyword key: The secret key to use. It must be 16 or 32 bytes long. - :type key: bytes/bytearray/memoryview + :keyword key: The secret key to use. It must be 16 or 32 bytes long. + :type key: bytes/bytearray/memoryview - :keyword nonce: - A value that must never be reused for any other encryption - done with this key. It must be 8 bytes long. + :keyword nonce: + A value that must never be reused for any other encryption + done with this key. It must be 8 bytes long. - If not provided, a random byte string will be generated (you can read - it back via the ``nonce`` attribute of the returned object). - :type nonce: bytes/bytearray/memoryview + If not provided, a random byte string will be generated (you can read + it back via the ``nonce`` attribute of the returned object). + :type nonce: bytes/bytearray/memoryview - :Return: a :class:`Cryptodome.Cipher.Salsa20.Salsa20Cipher` object - """ + :Return: a :class:`Cryptodome.Cipher.Salsa20.Salsa20Cipher` object + """ - if nonce is None: - nonce = get_random_bytes(8) + if nonce is None: + nonce = get_random_bytes(8) + + return Salsa20Cipher(key, nonce) - return Salsa20Cipher(key, nonce) # Size of a data block (in bytes) block_size = 1 # Size of a key (in bytes) key_size = (16, 32) - diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Salsa20.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Salsa20.pyi index cf8690e2..1e1e60b4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Salsa20.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/Salsa20.pyi @@ -1,26 +1,23 @@ -from typing import Union, Tuple, Optional, overload, Optional +from typing import Union, Tuple, overload, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview class Salsa20Cipher: - nonce: bytes - block_size: int - key_size: int + nonce: bytes + block_size: int + key_size: int - def __init__(self, - key: Buffer, - nonce: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def __init__(self, key: Buffer, nonce: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... def new(key: Buffer, nonce: Optional[Buffer] = ...) -> Salsa20Cipher: ... block_size: int key_size: Tuple[int, int] - diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_EKSBlowfish.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_EKSBlowfish.py index c1c3249a..a13550cc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_EKSBlowfish.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_EKSBlowfish.py @@ -31,13 +31,18 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, c_size_t, - c_uint8_ptr, c_uint) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + c_uint, +) _raw_blowfish_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_eksblowfish", - """ + "Cryptodome.Cipher._raw_eksblowfish", + """ int EKSBlowfish_start_operation(const uint8_t key[], size_t key_len, const uint8_t salt[16], @@ -54,73 +59,76 @@ uint8_t *out, size_t data_len); int EKSBlowfish_stop_operation(void *state); - """ - ) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a smart pointer to - a low-level base cipher. It will absorb named parameters in - the process.""" - - try: - key = dict_parameters.pop("key") - salt = dict_parameters.pop("salt") - cost = dict_parameters.pop("cost") - except KeyError as e: - raise TypeError("Missing EKSBlowfish parameter: " + str(e)) - invert = dict_parameters.pop("invert", True) - - if len(key) not in key_size: - raise ValueError("Incorrect EKSBlowfish key length (%d bytes)" % len(key)) - - start_operation = _raw_blowfish_lib.EKSBlowfish_start_operation - stop_operation = _raw_blowfish_lib.EKSBlowfish_stop_operation - - void_p = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - c_uint8_ptr(salt), - c_size_t(len(salt)), - c_uint(cost), - c_uint(int(invert)), - void_p.address_of()) - if result: - raise ValueError("Error %X while instantiating the EKSBlowfish cipher" - % result) - return SmartPointer(void_p.get(), stop_operation) + """This method instantiates and returns a smart pointer to + a low-level base cipher. It will absorb named parameters in + the process.""" + + try: + key = dict_parameters.pop("key") + salt = dict_parameters.pop("salt") + cost = dict_parameters.pop("cost") + except KeyError as e: + raise TypeError("Missing EKSBlowfish parameter: " + str(e)) + invert = dict_parameters.pop("invert", True) + + if len(key) not in key_size: + raise ValueError("Incorrect EKSBlowfish key length (%d bytes)" % len(key)) + + start_operation = _raw_blowfish_lib.EKSBlowfish_start_operation + stop_operation = _raw_blowfish_lib.EKSBlowfish_stop_operation + + void_p = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + c_uint8_ptr(salt), + c_size_t(len(salt)), + c_uint(cost), + c_uint(int(invert)), + void_p.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the EKSBlowfish cipher" % result, + ) + return SmartPointer(void_p.get(), stop_operation) def new(key, mode, salt, cost, invert): - """Create a new EKSBlowfish cipher - - Args: + """Create a new EKSBlowfish cipher - key (bytes, bytearray, memoryview): - The secret key to use in the symmetric cipher. - Its length can vary from 0 to 72 bytes. + Args: - mode (one of the supported ``MODE_*`` constants): - The chaining mode to use for encryption or decryption. + key (bytes, bytearray, memoryview): + The secret key to use in the symmetric cipher. + Its length can vary from 0 to 72 bytes. - salt (bytes, bytearray, memoryview): - The salt that bcrypt uses to thwart rainbow table attacks + mode (one of the supported ``MODE_*`` constants): + The chaining mode to use for encryption or decryption. - cost (integer): - The complexity factor in bcrypt + salt (bytes, bytearray, memoryview): + The salt that bcrypt uses to thwart rainbow table attacks - invert (bool): - If ``False``, in the inner loop use ``ExpandKey`` first over the salt - and then over the key, as defined in - the `original bcrypt specification `_. - If ``True``, reverse the order, as in the first implementation of - `bcrypt` in OpenBSD. + cost (integer): + The complexity factor in bcrypt - :Return: an EKSBlowfish object - """ + invert (bool): + If ``False``, in the inner loop use ``ExpandKey`` first over the salt + and then over the key, as defined in + the `original bcrypt specification `_. + If ``True``, reverse the order, as in the first implementation of + `bcrypt` in OpenBSD. - kwargs = { 'salt':salt, 'cost':cost, 'invert':invert } - return _create_cipher(sys.modules[__name__], key, mode, **kwargs) + :Return: an EKSBlowfish object + """ + + kwargs = {"salt": salt, "cost": cost, "invert": invert} + return _create_cipher(sys.modules[__name__], key, mode, **kwargs) MODE_ECB = 1 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_EKSBlowfish.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_EKSBlowfish.pyi index 49c84489..812577c6 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_EKSBlowfish.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_EKSBlowfish.pyi @@ -6,10 +6,7 @@ MODE_ECB: int Buffer = Union[bytes, bytearray, memoryview] -def new(key: Buffer, - mode: int, - salt: Buffer, - cost: int) -> EcbMode: ... +def new(key: Buffer, mode: int, salt: Buffer, cost: int) -> EcbMode: ... block_size: int key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/__init__.py index 88237119..09630900 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/__init__.py @@ -22,70 +22,83 @@ # # where mode_state is a a pointer to base_cipher_state plus mode-specific data. + def _create_cipher(factory, key, mode, *args, **kwargs): + kwargs["key"] = key + + if args: + if mode in (8, 9, 10, 11, 12): + if len(args) > 1: + raise TypeError("Too many arguments for this mode") + kwargs["nonce"] = args[0] + elif mode in (2, 3, 5, 7): + if len(args) > 1: + raise TypeError("Too many arguments for this mode") + kwargs["IV"] = args[0] + elif mode == 6: + if len(args) > 0: + raise TypeError("Too many arguments for this mode") + elif mode == 1: + raise TypeError("IV is not meaningful for the ECB mode") + + res = None + extra_modes = kwargs.pop("add_aes_modes", False) + + if mode == 1: + from Cryptodome.Cipher._mode_ecb import _create_ecb_cipher + + res = _create_ecb_cipher(factory, **kwargs) + elif mode == 2: + from Cryptodome.Cipher._mode_cbc import _create_cbc_cipher + + res = _create_cbc_cipher(factory, **kwargs) + elif mode == 3: + from Cryptodome.Cipher._mode_cfb import _create_cfb_cipher + + res = _create_cfb_cipher(factory, **kwargs) + elif mode == 5: + from Cryptodome.Cipher._mode_ofb import _create_ofb_cipher + + res = _create_ofb_cipher(factory, **kwargs) + elif mode == 6: + from Cryptodome.Cipher._mode_ctr import _create_ctr_cipher + + res = _create_ctr_cipher(factory, **kwargs) + elif mode == 7: + from Cryptodome.Cipher._mode_openpgp import _create_openpgp_cipher + + res = _create_openpgp_cipher(factory, **kwargs) + elif mode == 9: + from Cryptodome.Cipher._mode_eax import _create_eax_cipher + + res = _create_eax_cipher(factory, **kwargs) + elif extra_modes: + if mode == 8: + from Cryptodome.Cipher._mode_ccm import _create_ccm_cipher + + res = _create_ccm_cipher(factory, **kwargs) + elif mode == 10: + from Cryptodome.Cipher._mode_siv import _create_siv_cipher + + res = _create_siv_cipher(factory, **kwargs) + elif mode == 11: + from Cryptodome.Cipher._mode_gcm import _create_gcm_cipher + + res = _create_gcm_cipher(factory, **kwargs) + elif mode == 12: + from Cryptodome.Cipher._mode_ocb import _create_ocb_cipher + + res = _create_ocb_cipher(factory, **kwargs) + elif mode == 13: + from Cryptodome.Cipher._mode_kw import _create_kw_cipher + + res = _create_kw_cipher(factory, **kwargs) + elif mode == 14: + from Cryptodome.Cipher._mode_kwp import _create_kwp_cipher + + res = _create_kwp_cipher(factory, **kwargs) + + if res is None: + raise ValueError("Mode not supported") - kwargs["key"] = key - - if args: - if mode in (8, 9, 10, 11, 12): - if len(args) > 1: - raise TypeError("Too many arguments for this mode") - kwargs["nonce"] = args[0] - elif mode in (2, 3, 5, 7): - if len(args) > 1: - raise TypeError("Too many arguments for this mode") - kwargs["IV"] = args[0] - elif mode == 6: - if len(args) > 0: - raise TypeError("Too many arguments for this mode") - elif mode == 1: - raise TypeError("IV is not meaningful for the ECB mode") - - res = None - extra_modes = kwargs.pop("add_aes_modes", False) - - if mode == 1: - from Cryptodome.Cipher._mode_ecb import _create_ecb_cipher - res = _create_ecb_cipher(factory, **kwargs) - elif mode == 2: - from Cryptodome.Cipher._mode_cbc import _create_cbc_cipher - res = _create_cbc_cipher(factory, **kwargs) - elif mode == 3: - from Cryptodome.Cipher._mode_cfb import _create_cfb_cipher - res = _create_cfb_cipher(factory, **kwargs) - elif mode == 5: - from Cryptodome.Cipher._mode_ofb import _create_ofb_cipher - res = _create_ofb_cipher(factory, **kwargs) - elif mode == 6: - from Cryptodome.Cipher._mode_ctr import _create_ctr_cipher - res = _create_ctr_cipher(factory, **kwargs) - elif mode == 7: - from Cryptodome.Cipher._mode_openpgp import _create_openpgp_cipher - res = _create_openpgp_cipher(factory, **kwargs) - elif mode == 9: - from Cryptodome.Cipher._mode_eax import _create_eax_cipher - res = _create_eax_cipher(factory, **kwargs) - elif extra_modes: - if mode == 8: - from Cryptodome.Cipher._mode_ccm import _create_ccm_cipher - res = _create_ccm_cipher(factory, **kwargs) - elif mode == 10: - from Cryptodome.Cipher._mode_siv import _create_siv_cipher - res = _create_siv_cipher(factory, **kwargs) - elif mode == 11: - from Cryptodome.Cipher._mode_gcm import _create_gcm_cipher - res = _create_gcm_cipher(factory, **kwargs) - elif mode == 12: - from Cryptodome.Cipher._mode_ocb import _create_ocb_cipher - res = _create_ocb_cipher(factory, **kwargs) - elif mode == 13: - from Cryptodome.Cipher._mode_kw import _create_kw_cipher - res = _create_kw_cipher(factory, **kwargs) - elif mode == 14: - from Cryptodome.Cipher._mode_kwp import _create_kwp_cipher - res = _create_kwp_cipher(factory, **kwargs) - - if res is None: - raise ValueError("Mode not supported") - - return res + return res diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cbc.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cbc.py index 94d02e70..b07772bc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cbc.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cbc.py @@ -32,17 +32,25 @@ Ciphertext Block Chaining (CBC) mode. """ -__all__ = ['CbcMode'] +__all__ = ["CbcMode"] from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes -raw_cbc_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_cbc", """ +raw_cbc_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_cbc", + """ int CBC_start_operation(void *cipher, const uint8_t iv[], size_t iv_len, @@ -56,238 +64,250 @@ uint8_t *out, size_t data_len); int CBC_stop_operation(void *state); - """ - ) + """, +) class CbcMode(object): - """*Cipher-Block Chaining (CBC)*. + """*Cipher-Block Chaining (CBC)*. - Each of the ciphertext blocks depends on the current - and all previous plaintext blocks. + Each of the ciphertext blocks depends on the current + and all previous plaintext blocks. - An Initialization Vector (*IV*) is required. + An Initialization Vector (*IV*) is required. - See `NIST SP800-38A`_ , Section 6.2 . + See `NIST SP800-38A`_ , Section 6.2 . - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, block_cipher, iv): - """Create a new block cipher, configured in CBC mode. + def __init__(self, block_cipher, iv): + """Create a new block cipher, configured in CBC mode. - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. - iv : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - It is as long as the cipher block. + iv : bytes/bytearray/memoryview + The initialization vector to use for encryption or decryption. + It is as long as the cipher block. - **The IV must be unpredictable**. Ideally it is picked randomly. + **The IV must be unpredictable**. Ideally it is picked randomly. - Reusing the *IV* for encryptions performed with the same key - compromises confidentiality. - """ + Reusing the *IV* for encryptions performed with the same key + compromises confidentiality. + """ - self._state = VoidPointer() - result = raw_cbc_lib.CBC_start_operation(block_cipher.get(), - c_uint8_ptr(iv), - c_size_t(len(iv)), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the CBC mode" - % result) + self._state = VoidPointer() + result = raw_cbc_lib.CBC_start_operation( + block_cipher.get(), + c_uint8_ptr(iv), + c_size_t(len(iv)), + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %d while instantiating the CBC mode" % result, + ) - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_cbc_lib.CBC_stop_operation) + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + raw_cbc_lib.CBC_stop_operation, + ) - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + block_cipher.release() - self.block_size = len(iv) - """The block size of the underlying cipher, in bytes.""" + self.block_size = len(iv) + """The block size of the underlying cipher, in bytes.""" - self.iv = _copy_bytes(None, None, iv) - """The Initialization Vector originally used to create the object. + self.iv = _copy_bytes(None, None, iv) + """The Initialization Vector originally used to create the object. The value does not change.""" - self.IV = self.iv - """Alias for `iv`""" + self.IV = self.iv + """Alias for `iv`""" - self._next = ["encrypt", "decrypt"] + self._next = ["encrypt", "decrypt"] - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.encrypt(a) + c.encrypt(b) + >>> c.encrypt(a) + c.encrypt(b) - is equivalent to: + is equivalent to: - >>> c.encrypt(a+b) + >>> c.encrypt(a+b) - That also means that you cannot reuse an object for encrypting - or decrypting other data with the same key. + That also means that you cannot reuse an object for encrypting + or decrypting other data with the same key. - This function does not add any padding to the plaintext. + This function does not add any padding to the plaintext. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - Its lenght must be multiple of the cipher block size. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + Its lenght must be multiple of the cipher block size. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = ["encrypt"] + if "encrypt" not in self._next: + raise TypeError("encrypt() cannot be called after decrypt()") + self._next = ["encrypt"] - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) - result = raw_cbc_lib.CBC_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - if result == 3: - raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) - raise ValueError("Error %d while encrypting in CBC mode" % result) + result = raw_cbc_lib.CBC_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + if result == 3: + raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) + raise ValueError("Error %d while encrypting in CBC mode" % result) - if output is None: - return get_raw_buffer(ciphertext) - else: - return None + if output is None: + return get_raw_buffer(ciphertext) + else: + return None - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.decrypt(a) + c.decrypt(b) + >>> c.decrypt(a) + c.decrypt(b) - is equivalent to: + is equivalent to: - >>> c.decrypt(a+b) + >>> c.decrypt(a+b) - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - Its length must be multiple of the cipher block size. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = ["decrypt"] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_cbc_lib.CBC_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - if result == 3: - raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) - raise ValueError("Error %d while decrypting in CBC mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + Its length must be multiple of the cipher block size. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError("decrypt() cannot be called after encrypt()") + self._next = ["decrypt"] + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_cbc_lib.CBC_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + if result == 3: + raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) + raise ValueError("Error %d while decrypting in CBC mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_cbc_cipher(factory, **kwargs): - """Instantiate a cipher object that performs CBC encryption/decryption. + """Instantiate a cipher object that performs CBC encryption/decryption. - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. - :Keywords: - iv : bytes/bytearray/memoryview - The IV to use for CBC. + :Keywords: + iv : bytes/bytearray/memoryview + The IV to use for CBC. - IV : bytes/bytearray/memoryview - Alias for ``iv``. + IV : bytes/bytearray/memoryview + Alias for ``iv``. - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ - cipher_state = factory._create_base_cipher(kwargs) - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) + cipher_state = factory._create_base_cipher(kwargs) + iv = kwargs.pop("IV", None) + IV = kwargs.pop("iv", None) - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV + if (None, None) == (iv, IV): + iv = get_random_bytes(factory.block_size) + if iv is not None: + if IV is not None: + raise TypeError("You must either use 'iv' or 'IV', not both") + else: + iv = IV - if len(iv) != factory.block_size: - raise ValueError("Incorrect IV length (it must be %d bytes long)" % - factory.block_size) + if len(iv) != factory.block_size: + raise ValueError( + "Incorrect IV length (it must be %d bytes long)" % factory.block_size, + ) - if kwargs: - raise TypeError("Unknown parameters for CBC: %s" % str(kwargs)) + if kwargs: + raise TypeError("Unknown parameters for CBC: %s" % str(kwargs)) - return CbcMode(cipher_state, iv) + return CbcMode(cipher_state, iv) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cbc.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cbc.pyi index 526632eb..779e8dee 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cbc.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cbc.pyi @@ -4,22 +4,19 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['CbcMode'] +__all__ = ["CbcMode"] class CbcMode(object): - block_size: int - iv: Buffer - IV: Buffer - - def __init__(self, - block_cipher: SmartPointer, - iv: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + block_size: int + iv: Buffer + IV: Buffer + def __init__(self, block_cipher: SmartPointer, iv: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ccm.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ccm.py index ac272217..1ca5cbad 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ccm.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ccm.py @@ -32,13 +32,15 @@ Counter with CBC-MAC (CCM) mode. """ -__all__ = ['CcmMode'] +__all__ = ["CcmMode"] import struct from binascii import unhexlify -from Cryptodome.Util.py3compat import (byte_string, bord, - _copy_bytes) +from Cryptodome.Util.py3compat import ( + bord, + _copy_bytes, +) from Cryptodome.Util._raw_api import is_writeable_buffer from Cryptodome.Util.strxor import strxor @@ -49,623 +51,663 @@ def enum(**enums): - return type('Enum', (), enums) + return type("Enum", (), enums) + MacStatus = enum(NOT_STARTED=0, PROCESSING_AUTH_DATA=1, PROCESSING_PLAINTEXT=2) class CCMMessageTooLongError(ValueError): - pass + pass class CcmMode(object): - """Counter with CBC-MAC (CCM). - - This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. - It provides both confidentiality and authenticity. - - The header of the message may be left in the clear, if needed, and it will - still be subject to authentication. The decryption step tells the receiver - if the message comes from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - including the - header - has been modified or corrupted. - - This mode requires a nonce. The nonce shall never repeat for two - different messages encrypted with the same key, but it does not need - to be random. - Note that there is a trade-off between the size of the nonce and the - maximum size of a single message you can encrypt. - - It is important to use a large nonce if the key is reused across several - messages and the nonce is chosen randomly. - - It is acceptable to us a short nonce if the key is only used a few times or - if the nonce is taken from a counter. - - The following table shows the trade-off when the nonce is chosen at - random. The column on the left shows how many messages it takes - for the keystream to repeat **on average**. In practice, you will want to - stop using the key way before that. - - +--------------------+---------------+-------------------+ - | Avg. # of messages | nonce | Max. message | - | before keystream | size | size | - | repeats | (bytes) | (bytes) | - +====================+===============+===================+ - | 2^52 | 13 | 64K | - +--------------------+---------------+-------------------+ - | 2^48 | 12 | 16M | - +--------------------+---------------+-------------------+ - | 2^44 | 11 | 4G | - +--------------------+---------------+-------------------+ - | 2^40 | 10 | 1T | - +--------------------+---------------+-------------------+ - | 2^36 | 9 | 64P | - +--------------------+---------------+-------------------+ - | 2^32 | 8 | 16E | - +--------------------+---------------+-------------------+ - - This mode is only available for ciphers that operate on 128 bits blocks - (e.g. AES but not TDES). - - See `NIST SP800-38C`_ or RFC3610_. - - .. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf - .. _RFC3610: https://tools.ietf.org/html/rfc3610 - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, mac_len, msg_len, assoc_len, - cipher_params): - - self.block_size = factory.block_size - """The block size of the underlying cipher, in bytes.""" - - self.nonce = _copy_bytes(None, None, nonce) - """The nonce used for this cipher instance""" - - self._factory = factory - self._key = _copy_bytes(None, None, key) - self._mac_len = mac_len - self._msg_len = msg_len - self._assoc_len = assoc_len - self._cipher_params = cipher_params - - self._mac_tag = None # Cache for MAC tag - - if self.block_size != 16: - raise ValueError("CCM mode is only available for ciphers" - " that operate on 128 bits blocks") - - # MAC tag length (Tlen) - if mac_len not in (4, 6, 8, 10, 12, 14, 16): - raise ValueError("Parameter 'mac_len' must be even" - " and in the range 4..16 (not %d)" % mac_len) - - # Nonce value - if not (7 <= len(nonce) <= 13): - raise ValueError("Length of parameter 'nonce' must be" - " in the range 7..13 bytes") - - # Message length (if known already) - q = 15 - len(nonce) # length of Q, the encoded message length - if msg_len and len(long_to_bytes(msg_len)) > q: - raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(nonce)) - - # Create MAC object (the tag will be the last block - # bytes worth of ciphertext) - self._mac = self._factory.new(key, - factory.MODE_CBC, - iv=b'\x00' * 16, - **cipher_params) - self._mac_status = MacStatus.NOT_STARTED - self._t = None - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - # Cumulative lengths - self._cumul_assoc_len = 0 - self._cumul_msg_len = 0 - - # Cache for unaligned associated data/plaintext. - # This is a list with byte strings, but when the MAC starts, - # it will become a binary string no longer than the block size. - self._cache = [] - - # Start CTR cipher, by formatting the counter (A.3) - self._cipher = self._factory.new(key, - self._factory.MODE_CTR, - nonce=struct.pack("B", q - 1) + self.nonce, - **cipher_params) - - # S_0, step 6 in 6.1 for j=0 - self._s_0 = self._cipher.encrypt(b'\x00' * 16) - - # Try to start the MAC - if None not in (assoc_len, msg_len): - self._start_mac() - - def _start_mac(self): - - assert(self._mac_status == MacStatus.NOT_STARTED) - assert(None not in (self._assoc_len, self._msg_len)) - assert(isinstance(self._cache, list)) - - # Formatting control information and nonce (A.2.1) - q = 15 - len(self.nonce) # length of Q, the encoded message length (2..8) - flags = (self._assoc_len > 0) << 6 - flags |= ((self._mac_len - 2) // 2) << 3 - flags |= q - 1 - b_0 = struct.pack("B", flags) + self.nonce + long_to_bytes(self._msg_len, q) - - # Formatting associated data (A.2.2) - # Encoded 'a' is concatenated with the associated data 'A' - assoc_len_encoded = b'' - if self._assoc_len > 0: - if self._assoc_len < (2 ** 16 - 2 ** 8): - enc_size = 2 - elif self._assoc_len < (2 ** 32): - assoc_len_encoded = b'\xFF\xFE' - enc_size = 4 - else: - assoc_len_encoded = b'\xFF\xFF' - enc_size = 8 - assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size) - - # b_0 and assoc_len_encoded must be processed first - self._cache.insert(0, b_0) - self._cache.insert(1, assoc_len_encoded) - - # Process all the data cached so far - first_data_to_mac = b"".join(self._cache) - self._cache = b"" - self._mac_status = MacStatus.PROCESSING_AUTH_DATA - self._update(first_data_to_mac) - - def _pad_cache_and_update(self): - - assert(self._mac_status != MacStatus.NOT_STARTED) - assert(len(self._cache) < self.block_size) - - # Associated data is concatenated with the least number - # of zero bytes (possibly none) to reach alignment to - # the 16 byte boundary (A.2.3) - len_cache = len(self._cache) - if len_cache > 0: - self._update(b'\x00' * (self.block_size - len_cache)) - - def update(self, assoc_data): - """Protect associated data - - If there is any associated data, the caller has to invoke - this function one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver is still able to detect any modification to it. - In CCM, the *associated data* is also called - *additional authenticated data* (AAD). - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. There are no restrictions on its size. - """ - - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - self._cumul_assoc_len += len(assoc_data) - if self._assoc_len is not None and \ - self._cumul_assoc_len > self._assoc_len: - raise ValueError("Associated data is too long") - - self._update(assoc_data) - return self - - def _update(self, assoc_data_pt=b""): - """Update the MAC with associated data or plaintext - (without FSM checks)""" - - # If MAC has not started yet, we just park the data into a list. - # If the data is mutable, we create a copy and store that instead. - if self._mac_status == MacStatus.NOT_STARTED: - if is_writeable_buffer(assoc_data_pt): - assoc_data_pt = _copy_bytes(None, None, assoc_data_pt) - self._cache.append(assoc_data_pt) - return - - assert(len(self._cache) < self.block_size) - - if len(self._cache) > 0: - filler = min(self.block_size - len(self._cache), - len(assoc_data_pt)) - self._cache += _copy_bytes(None, filler, assoc_data_pt) - assoc_data_pt = _copy_bytes(filler, None, assoc_data_pt) - - if len(self._cache) < self.block_size: - return - - # The cache is exactly one block - self._t = self._mac.encrypt(self._cache) - self._cache = b"" - - update_len = len(assoc_data_pt) // self.block_size * self.block_size - self._cache = _copy_bytes(update_len, None, assoc_data_pt) - if update_len > 0: - self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:] - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - This method can be called only **once** if ``msg_len`` was - not passed at initialization. - - If ``msg_len`` was given, the data to encrypt can be broken - up in two or more pieces and `encrypt` can be called - multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext as ``bytes``. - Otherwise, ``None``. - """ - - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - self._next = ["encrypt", "digest"] - - # No more associated data allowed from now - if self._assoc_len is None: - assert(isinstance(self._cache, list)) - self._assoc_len = sum([len(x) for x in self._cache]) - if self._msg_len is not None: - self._start_mac() - else: - if self._cumul_assoc_len < self._assoc_len: - raise ValueError("Associated data is too short") - - # Only once piece of plaintext accepted if message length was - # not declared in advance - if self._msg_len is None: - q = 15 - len(self.nonce) - if len(long_to_bytes(len(plaintext))) > q: - raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(self.nonce)) - - self._msg_len = len(plaintext) - self._start_mac() - self._next = ["digest"] - - self._cumul_msg_len += len(plaintext) - if self._cumul_msg_len > self._msg_len: - msg = "Message longer than declared for (%u bytes vs %u bytes" % \ - (self._cumul_msg_len, self._msg_len) - raise CCMMessageTooLongError(msg) - - if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: - # Associated data is concatenated with the least number - # of zero bytes (possibly none) to reach alignment to - # the 16 byte boundary (A.2.3) - self._pad_cache_and_update() - self._mac_status = MacStatus.PROCESSING_PLAINTEXT - - self._update(plaintext) - return self._cipher.encrypt(plaintext, output=output) - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - This method can be called only **once** if ``msg_len`` was - not passed at initialization. - - If ``msg_len`` was given, the data to decrypt can be - broken up in two or more pieces and `decrypt` can be - called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = ["decrypt", "verify"] - - # No more associated data allowed from now - if self._assoc_len is None: - assert(isinstance(self._cache, list)) - self._assoc_len = sum([len(x) for x in self._cache]) - if self._msg_len is not None: - self._start_mac() - else: - if self._cumul_assoc_len < self._assoc_len: - raise ValueError("Associated data is too short") - - # Only once piece of ciphertext accepted if message length was - # not declared in advance - if self._msg_len is None: - q = 15 - len(self.nonce) - if len(long_to_bytes(len(ciphertext))) > q: - raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(self.nonce)) - - self._msg_len = len(ciphertext) - self._start_mac() - self._next = ["verify"] - - self._cumul_msg_len += len(ciphertext) - if self._cumul_msg_len > self._msg_len: - msg = "Message longer than declared for (%u bytes vs %u bytes" % \ - (self._cumul_msg_len, self._msg_len) - raise CCMMessageTooLongError(msg) - - if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: - # Associated data is concatenated with the least number - # of zero bytes (possibly none) to reach alignment to - # the 16 byte boundary (A.2.3) - self._pad_cache_and_update() - self._mac_status = MacStatus.PROCESSING_PLAINTEXT - - # Encrypt is equivalent to decrypt with the CTR mode - plaintext = self._cipher.encrypt(ciphertext, output=output) - if output is None: - self._update(plaintext) - else: - self._update(output) - return plaintext - - def digest(self): - """Compute the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. - - :Return: the MAC, as a byte string. - """ - - if "digest" not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = ["digest"] - return self._digest() - - def _digest(self): - if self._mac_tag: - return self._mac_tag - - if self._assoc_len is None: - assert(isinstance(self._cache, list)) - self._assoc_len = sum([len(x) for x in self._cache]) - if self._msg_len is not None: - self._start_mac() - else: - if self._cumul_assoc_len < self._assoc_len: - raise ValueError("Associated data is too short") - - if self._msg_len is None: - self._msg_len = 0 - self._start_mac() - - if self._cumul_msg_len != self._msg_len: - raise ValueError("Message is too short") - - # Both associated data and payload are concatenated with the least - # number of zero bytes (possibly none) that align it to the - # 16 byte boundary (A.2.2 and A.2.3) - self._pad_cache_and_update() - - # Step 8 in 6.1 (T xor MSB_Tlen(S_0)) - self._mac_tag = strxor(self._t, self._s_0)[:self._mac_len] - - return self._mac_tag - - def hexdigest(self): - """Compute the *printable* MAC tag. - - This method is like `digest`. - - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. - - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ["verify"] - - self._digest() - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. - - This method is like `verify`. - - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: - - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` - - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ - - return self.encrypt(plaintext, output=output), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): - """Perform decrypt() and verify() in one step. + """Counter with CBC-MAC (CCM). + + This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. + It provides both confidentiality and authenticity. + + The header of the message may be left in the clear, if needed, and it will + still be subject to authentication. The decryption step tells the receiver + if the message comes from a source that really knowns the secret key. + Additionally, decryption detects if any part of the message - including the + header - has been modified or corrupted. + + This mode requires a nonce. The nonce shall never repeat for two + different messages encrypted with the same key, but it does not need + to be random. + Note that there is a trade-off between the size of the nonce and the + maximum size of a single message you can encrypt. + + It is important to use a large nonce if the key is reused across several + messages and the nonce is chosen randomly. + + It is acceptable to us a short nonce if the key is only used a few times or + if the nonce is taken from a counter. + + The following table shows the trade-off when the nonce is chosen at + random. The column on the left shows how many messages it takes + for the keystream to repeat **on average**. In practice, you will want to + stop using the key way before that. + + +--------------------+---------------+-------------------+ + | Avg. # of messages | nonce | Max. message | + | before keystream | size | size | + | repeats | (bytes) | (bytes) | + +====================+===============+===================+ + | 2^52 | 13 | 64K | + +--------------------+---------------+-------------------+ + | 2^48 | 12 | 16M | + +--------------------+---------------+-------------------+ + | 2^44 | 11 | 4G | + +--------------------+---------------+-------------------+ + | 2^40 | 10 | 1T | + +--------------------+---------------+-------------------+ + | 2^36 | 9 | 64P | + +--------------------+---------------+-------------------+ + | 2^32 | 8 | 16E | + +--------------------+---------------+-------------------+ + + This mode is only available for ciphers that operate on 128 bits blocks + (e.g. AES but not TDES). + + See `NIST SP800-38C`_ or RFC3610_. + + .. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf + .. _RFC3610: https://tools.ietf.org/html/rfc3610 + .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html + + :undocumented: __init__ + """ + + def __init__( + self, + factory, + key, + nonce, + mac_len, + msg_len, + assoc_len, + cipher_params, + ): + self.block_size = factory.block_size + """The block size of the underlying cipher, in bytes.""" + + self.nonce = _copy_bytes(None, None, nonce) + """The nonce used for this cipher instance""" + + self._factory = factory + self._key = _copy_bytes(None, None, key) + self._mac_len = mac_len + self._msg_len = msg_len + self._assoc_len = assoc_len + self._cipher_params = cipher_params + + self._mac_tag = None # Cache for MAC tag + + if self.block_size != 16: + raise ValueError( + "CCM mode is only available for ciphers that operate on 128 bits blocks", + ) + + # MAC tag length (Tlen) + if mac_len not in (4, 6, 8, 10, 12, 14, 16): + raise ValueError( + "Parameter 'mac_len' must be even and in the range 4..16 (not %d)" % mac_len, + ) + + # Nonce value + if not (7 <= len(nonce) <= 13): + raise ValueError( + "Length of parameter 'nonce' must be in the range 7..13 bytes", + ) + + # Message length (if known already) + q = 15 - len(nonce) # length of Q, the encoded message length + if msg_len and len(long_to_bytes(msg_len)) > q: + raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(nonce)) + + # Create MAC object (the tag will be the last block + # bytes worth of ciphertext) + self._mac = self._factory.new( + key, + factory.MODE_CBC, + iv=b"\x00" * 16, + **cipher_params, + ) + self._mac_status = MacStatus.NOT_STARTED + self._t = None + + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + # Cumulative lengths + self._cumul_assoc_len = 0 + self._cumul_msg_len = 0 + + # Cache for unaligned associated data/plaintext. + # This is a list with byte strings, but when the MAC starts, + # it will become a binary string no longer than the block size. + self._cache = [] + + # Start CTR cipher, by formatting the counter (A.3) + self._cipher = self._factory.new( + key, + self._factory.MODE_CTR, + nonce=struct.pack("B", q - 1) + self.nonce, + **cipher_params, + ) + + # S_0, step 6 in 6.1 for j=0 + self._s_0 = self._cipher.encrypt(b"\x00" * 16) + + # Try to start the MAC + if None not in (assoc_len, msg_len): + self._start_mac() + + def _start_mac(self): + assert self._mac_status == MacStatus.NOT_STARTED + assert None not in (self._assoc_len, self._msg_len) + assert isinstance(self._cache, list) + + # Formatting control information and nonce (A.2.1) + q = 15 - len(self.nonce) # length of Q, the encoded message length (2..8) + flags = (self._assoc_len > 0) << 6 + flags |= ((self._mac_len - 2) // 2) << 3 + flags |= q - 1 + b_0 = struct.pack("B", flags) + self.nonce + long_to_bytes(self._msg_len, q) + + # Formatting associated data (A.2.2) + # Encoded 'a' is concatenated with the associated data 'A' + assoc_len_encoded = b"" + if self._assoc_len > 0: + if self._assoc_len < (2**16 - 2**8): + enc_size = 2 + elif self._assoc_len < (2**32): + assoc_len_encoded = b"\xff\xfe" + enc_size = 4 + else: + assoc_len_encoded = b"\xff\xff" + enc_size = 8 + assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size) + + # b_0 and assoc_len_encoded must be processed first + self._cache.insert(0, b_0) + self._cache.insert(1, assoc_len_encoded) + + # Process all the data cached so far + first_data_to_mac = b"".join(self._cache) + self._cache = b"" + self._mac_status = MacStatus.PROCESSING_AUTH_DATA + self._update(first_data_to_mac) + + def _pad_cache_and_update(self): + assert self._mac_status != MacStatus.NOT_STARTED + assert len(self._cache) < self.block_size + + # Associated data is concatenated with the least number + # of zero bytes (possibly none) to reach alignment to + # the 16 byte boundary (A.2.3) + len_cache = len(self._cache) + if len_cache > 0: + self._update(b"\x00" * (self.block_size - len_cache)) + + def update(self, assoc_data): + """Protect associated data + + If there is any associated data, the caller has to invoke + this function one or more times, before using + ``decrypt`` or ``encrypt``. + + By *associated data* it is meant any data (e.g. packet headers) that + will not be encrypted and will be transmitted in the clear. + However, the receiver is still able to detect any modification to it. + In CCM, the *associated data* is also called + *additional authenticated data* (AAD). + + If there is no associated data, this method must not be called. + + The caller may split associated data in segments of any size, and + invoke this method multiple times, each time with the next segment. + + :Parameters: + assoc_data : bytes/bytearray/memoryview + A piece of associated data. There are no restrictions on its size. + """ + + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) + + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + self._cumul_assoc_len += len(assoc_data) + if self._assoc_len is not None and self._cumul_assoc_len > self._assoc_len: + raise ValueError("Associated data is too long") + + self._update(assoc_data) + return self + + def _update(self, assoc_data_pt=b""): + """Update the MAC with associated data or plaintext + (without FSM checks)""" + + # If MAC has not started yet, we just park the data into a list. + # If the data is mutable, we create a copy and store that instead. + if self._mac_status == MacStatus.NOT_STARTED: + if is_writeable_buffer(assoc_data_pt): + assoc_data_pt = _copy_bytes(None, None, assoc_data_pt) + self._cache.append(assoc_data_pt) + return + + assert len(self._cache) < self.block_size + + if len(self._cache) > 0: + filler = min( + self.block_size - len(self._cache), + len(assoc_data_pt), + ) + self._cache += _copy_bytes(None, filler, assoc_data_pt) + assoc_data_pt = _copy_bytes(filler, None, assoc_data_pt) + + if len(self._cache) < self.block_size: + return + + # The cache is exactly one block + self._t = self._mac.encrypt(self._cache) + self._cache = b"" + + update_len = len(assoc_data_pt) // self.block_size * self.block_size + self._cache = _copy_bytes(update_len, None, assoc_data_pt) + if update_len > 0: + self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:] + + def encrypt(self, plaintext, output=None): + """Encrypt data with the key set at initialization. + + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. + + This method can be called only **once** if ``msg_len`` was + not passed at initialization. + + If ``msg_len`` was given, the data to encrypt can be broken + up in two or more pieces and `encrypt` can be called + multiple times. + + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is equivalent to: + + >>> c.encrypt(a+b) + + This function does not add any padding to the plaintext. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext as ``bytes``. + Otherwise, ``None``. + """ + + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) + self._next = ["encrypt", "digest"] + + # No more associated data allowed from now + if self._assoc_len is None: + assert isinstance(self._cache, list) + self._assoc_len = sum([len(x) for x in self._cache]) + if self._msg_len is not None: + self._start_mac() + else: + if self._cumul_assoc_len < self._assoc_len: + raise ValueError("Associated data is too short") + + # Only once piece of plaintext accepted if message length was + # not declared in advance + if self._msg_len is None: + q = 15 - len(self.nonce) + if len(long_to_bytes(len(plaintext))) > q: + raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(self.nonce)) + + self._msg_len = len(plaintext) + self._start_mac() + self._next = ["digest"] + + self._cumul_msg_len += len(plaintext) + if self._cumul_msg_len > self._msg_len: + msg = "Message longer than declared for (%u bytes vs %u bytes" % ( + self._cumul_msg_len, + self._msg_len, + ) + raise CCMMessageTooLongError(msg) + + if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: + # Associated data is concatenated with the least number + # of zero bytes (possibly none) to reach alignment to + # the 16 byte boundary (A.2.3) + self._pad_cache_and_update() + self._mac_status = MacStatus.PROCESSING_PLAINTEXT + + self._update(plaintext) + return self._cipher.encrypt(plaintext, output=output) + + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key set at initialization. + + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. + + This method can be called only **once** if ``msg_len`` was + not passed at initialization. + + If ``msg_len`` was given, the data to decrypt can be + broken up in two or more pieces and `decrypt` can be + called multiple times. + + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is equivalent to: + + >>> c.decrypt(a+b) + + This function does not remove any padding from the plaintext. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + self._next = ["decrypt", "verify"] + + # No more associated data allowed from now + if self._assoc_len is None: + assert isinstance(self._cache, list) + self._assoc_len = sum([len(x) for x in self._cache]) + if self._msg_len is not None: + self._start_mac() + else: + if self._cumul_assoc_len < self._assoc_len: + raise ValueError("Associated data is too short") + + # Only once piece of ciphertext accepted if message length was + # not declared in advance + if self._msg_len is None: + q = 15 - len(self.nonce) + if len(long_to_bytes(len(ciphertext))) > q: + raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(self.nonce)) + + self._msg_len = len(ciphertext) + self._start_mac() + self._next = ["verify"] + + self._cumul_msg_len += len(ciphertext) + if self._cumul_msg_len > self._msg_len: + msg = "Message longer than declared for (%u bytes vs %u bytes" % ( + self._cumul_msg_len, + self._msg_len, + ) + raise CCMMessageTooLongError(msg) + + if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: + # Associated data is concatenated with the least number + # of zero bytes (possibly none) to reach alignment to + # the 16 byte boundary (A.2.3) + self._pad_cache_and_update() + self._mac_status = MacStatus.PROCESSING_PLAINTEXT + + # Encrypt is equivalent to decrypt with the CTR mode + plaintext = self._cipher.encrypt(ciphertext, output=output) + if output is None: + self._update(plaintext) + else: + self._update(output) + return plaintext + + def digest(self): + """Compute the *binary* MAC tag. + + The caller invokes this function at the very end. + + This method returns the MAC that shall be sent to the receiver, + together with the ciphertext. + + :Return: the MAC, as a byte string. + """ + + if "digest" not in self._next: + raise TypeError( + "digest() cannot be called when decrypting or validating a message", + ) + self._next = ["digest"] + return self._digest() + + def _digest(self): + if self._mac_tag: + return self._mac_tag + + if self._assoc_len is None: + assert isinstance(self._cache, list) + self._assoc_len = sum([len(x) for x in self._cache]) + if self._msg_len is not None: + self._start_mac() + else: + if self._cumul_assoc_len < self._assoc_len: + raise ValueError("Associated data is too short") + + if self._msg_len is None: + self._msg_len = 0 + self._start_mac() + + if self._cumul_msg_len != self._msg_len: + raise ValueError("Message is too short") + + # Both associated data and payload are concatenated with the least + # number of zero bytes (possibly none) that align it to the + # 16 byte boundary (A.2.2 and A.2.3) + self._pad_cache_and_update() + + # Step 8 in 6.1 (T xor MSB_Tlen(S_0)) + self._mac_tag = strxor(self._t, self._s_0)[: self._mac_len] + + return self._mac_tag + + def hexdigest(self): + """Compute the *printable* MAC tag. + + This method is like `digest`. + + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. + + The caller invokes this function at the very end. + + This method checks if the decrypted message is indeed valid + (that is, if the key is correct) and it has not been + tampered with while in transit. + + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ["verify"] + + self._digest() + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. + + This method is like `verify`. + + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + self.verify(unhexlify(hex_mac_tag)) + + def encrypt_and_digest(self, plaintext, output=None): + """Perform encrypt() and digest() in one step. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + a tuple with two items: + + - the ciphertext, as ``bytes`` + - the MAC tag, as ``bytes`` + + The first item becomes ``None`` when the ``output`` parameter + specified a location for the result. + """ + + return self.encrypt(plaintext, output=output), self.digest() + + def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): + """Perform decrypt() and verify() in one step. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` + parameter specified a location for the result. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - plaintext = self.decrypt(ciphertext, output=output) - self.verify(received_mac_tag) - return plaintext + plaintext = self.decrypt(ciphertext, output=output) + self.verify(received_mac_tag) + return plaintext def _create_ccm_cipher(factory, **kwargs): - """Create a new block cipher, configured in CCM mode. - - :Parameters: - factory : module - A symmetric cipher module from `Cryptodome.Cipher` (like - `Cryptodome.Cipher.AES`). - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - - Its length must be in the range ``[7..13]``. - 11 or 12 bytes are reasonable values in general. Bear in - mind that with CCM there is a trade-off between nonce length and - maximum message size. - - If not specified, a 11 byte long random string is used. - - mac_len : integer - Length of the MAC, in bytes. It must be even and in - the range ``[4..16]``. The default is 16. - - msg_len : integer - Length of the message to (de)cipher. - If not specified, ``encrypt`` or ``decrypt`` may only be called once. - - assoc_len : integer - Length of the associated data. - If not specified, all data is internally buffered. - """ - - try: - key = key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter: " + str(e)) - - nonce = kwargs.pop("nonce", None) # N - if nonce is None: - nonce = get_random_bytes(11) - mac_len = kwargs.pop("mac_len", factory.block_size) - msg_len = kwargs.pop("msg_len", None) # p - assoc_len = kwargs.pop("assoc_len", None) # a - cipher_params = dict(kwargs) - - return CcmMode(factory, key, nonce, mac_len, msg_len, - assoc_len, cipher_params) + """Create a new block cipher, configured in CCM mode. + + :Parameters: + factory : module + A symmetric cipher module from `Cryptodome.Cipher` (like + `Cryptodome.Cipher.AES`). + + :Keywords: + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. + + nonce : bytes/bytearray/memoryview + A value that must never be reused for any other encryption. + + Its length must be in the range ``[7..13]``. + 11 or 12 bytes are reasonable values in general. Bear in + mind that with CCM there is a trade-off between nonce length and + maximum message size. + + If not specified, a 11 byte long random string is used. + + mac_len : integer + Length of the MAC, in bytes. It must be even and in + the range ``[4..16]``. The default is 16. + + msg_len : integer + Length of the message to (de)cipher. + If not specified, ``encrypt`` or ``decrypt`` may only be called once. + + assoc_len : integer + Length of the associated data. + If not specified, all data is internally buffered. + """ + + try: + key = key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter: " + str(e)) + + nonce = kwargs.pop("nonce", None) # N + if nonce is None: + nonce = get_random_bytes(11) + mac_len = kwargs.pop("mac_len", factory.block_size) + msg_len = kwargs.pop("msg_len", None) # p + assoc_len = kwargs.pop("assoc_len", None) # a + cipher_params = dict(kwargs) + + return CcmMode( + factory, + key, + nonce, + mac_len, + msg_len, + assoc_len, + cipher_params, + ) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ccm.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ccm.pyi index 98af96a4..147fa6fd 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ccm.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ccm.pyi @@ -3,50 +3,45 @@ from typing import Union, overload, Dict, Tuple, Optional Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['CcmMode'] - +__all__ = ["CcmMode"] class CCMMessageTooLongError(ValueError): - pass - + pass class CcmMode(object): - block_size: int - nonce: bytes - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - mac_len: int, - msg_len: Optional[int], - assoc_len: Optional[int], - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> CcmMode: ... - - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... + block_size: int + nonce: bytes + + def __init__( + self, + factory: ModuleType, + key: Buffer, + nonce: Buffer, + mac_len: int, + msg_len: Optional[int], + assoc_len: Optional[int], + cipher_params: Dict, + ) -> None: ... + def update(self, assoc_data: Buffer) -> CcmMode: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer, output: Buffer) -> Tuple[None, bytes]: ... + def decrypt_and_verify( + self, + ciphertext: Buffer, + received_mac_tag: Buffer, + output: Optional[Union[bytearray, memoryview]] = ..., + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cfb.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cfb.py index 1b1b6c31..f1863cde 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cfb.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cfb.py @@ -24,17 +24,25 @@ Counter Feedback (CFB) mode. """ -__all__ = ['CfbMode'] +__all__ = ["CfbMode"] from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes -raw_cfb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_cfb",""" +raw_cfb_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_cfb", + """ int CFB_start_operation(void *cipher, const uint8_t iv[], size_t iv_len, @@ -48,246 +56,257 @@ const uint8_t *in, uint8_t *out, size_t data_len); - int CFB_stop_operation(void *state);""" - ) + int CFB_stop_operation(void *state);""", +) class CfbMode(object): - """*Cipher FeedBack (CFB)*. + """*Cipher FeedBack (CFB)*. - This mode is similar to CFB, but it transforms - the underlying block cipher into a stream cipher. + This mode is similar to CFB, but it transforms + the underlying block cipher into a stream cipher. - Plaintext and ciphertext are processed in *segments* - of **s** bits. The mode is therefore sometimes - labelled **s**-bit CFB. + Plaintext and ciphertext are processed in *segments* + of **s** bits. The mode is therefore sometimes + labelled **s**-bit CFB. - An Initialization Vector (*IV*) is required. + An Initialization Vector (*IV*) is required. - See `NIST SP800-38A`_ , Section 6.3. + See `NIST SP800-38A`_ , Section 6.3. - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, block_cipher, iv, segment_size): - """Create a new block cipher, configured in CFB mode. + def __init__(self, block_cipher, iv, segment_size): + """Create a new block cipher, configured in CFB mode. - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. - iv : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - It is as long as the cipher block. + iv : bytes/bytearray/memoryview + The initialization vector to use for encryption or decryption. + It is as long as the cipher block. - **The IV must be unpredictable**. Ideally it is picked randomly. + **The IV must be unpredictable**. Ideally it is picked randomly. - Reusing the *IV* for encryptions performed with the same key - compromises confidentiality. + Reusing the *IV* for encryptions performed with the same key + compromises confidentiality. - segment_size : integer - The number of bytes the plaintext and ciphertext are segmented in. - """ + segment_size : integer + The number of bytes the plaintext and ciphertext are segmented in. + """ - self._state = VoidPointer() - result = raw_cfb_lib.CFB_start_operation(block_cipher.get(), - c_uint8_ptr(iv), - c_size_t(len(iv)), - c_size_t(segment_size), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the CFB mode" % result) + self._state = VoidPointer() + result = raw_cfb_lib.CFB_start_operation( + block_cipher.get(), + c_uint8_ptr(iv), + c_size_t(len(iv)), + c_size_t(segment_size), + self._state.address_of(), + ) + if result: + raise ValueError("Error %d while instantiating the CFB mode" % result) - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_cfb_lib.CFB_stop_operation) + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + raw_cfb_lib.CFB_stop_operation, + ) - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + block_cipher.release() - self.block_size = len(iv) - """The block size of the underlying cipher, in bytes.""" + self.block_size = len(iv) + """The block size of the underlying cipher, in bytes.""" - self.iv = _copy_bytes(None, None, iv) - """The Initialization Vector originally used to create the object. + self.iv = _copy_bytes(None, None, iv) + """The Initialization Vector originally used to create the object. The value does not change.""" - self.IV = self.iv - """Alias for `iv`""" + self.IV = self.iv + """Alias for `iv`""" - self._next = ["encrypt", "decrypt"] + self._next = ["encrypt", "decrypt"] - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.encrypt(a) + c.encrypt(b) + >>> c.encrypt(a) + c.encrypt(b) - is equivalent to: + is equivalent to: - >>> c.encrypt(a+b) + >>> c.encrypt(a+b) - This function does not add any padding to the plaintext. + This function does not add any padding to the plaintext. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = ["encrypt"] + if "encrypt" not in self._next: + raise TypeError("encrypt() cannot be called after decrypt()") + self._next = ["encrypt"] - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) - result = raw_cfb_lib.CFB_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting in CFB mode" % result) + result = raw_cfb_lib.CFB_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting in CFB mode" % result) - if output is None: - return get_raw_buffer(ciphertext) - else: - return None + if output is None: + return get_raw_buffer(ciphertext) + else: + return None - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.decrypt(a) + c.decrypt(b) + >>> c.decrypt(a) + c.decrypt(b) - is equivalent to: + is equivalent to: - >>> c.decrypt(a+b) + >>> c.decrypt(a+b) - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "decrypt" not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = ["decrypt"] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_cfb_lib.CFB_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - raise ValueError("Error %d while decrypting in CFB mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + if "decrypt" not in self._next: + raise TypeError("decrypt() cannot be called after encrypt()") + self._next = ["decrypt"] + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_cfb_lib.CFB_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + raise ValueError("Error %d while decrypting in CFB mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_cfb_cipher(factory, **kwargs): - """Instantiate a cipher object that performs CFB encryption/decryption. + """Instantiate a cipher object that performs CFB encryption/decryption. - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. - :Keywords: - iv : bytes/bytearray/memoryview - The IV to use for CFB. + :Keywords: + iv : bytes/bytearray/memoryview + The IV to use for CFB. - IV : bytes/bytearray/memoryview - Alias for ``iv``. + IV : bytes/bytearray/memoryview + Alias for ``iv``. - segment_size : integer - The number of bit the plaintext and ciphertext are segmented in. - If not present, the default is 8. + segment_size : integer + The number of bit the plaintext and ciphertext are segmented in. + If not present, the default is 8. - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ - cipher_state = factory._create_base_cipher(kwargs) + cipher_state = factory._create_base_cipher(kwargs) - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) + iv = kwargs.pop("IV", None) + IV = kwargs.pop("iv", None) - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV + if (None, None) == (iv, IV): + iv = get_random_bytes(factory.block_size) + if iv is not None: + if IV is not None: + raise TypeError("You must either use 'iv' or 'IV', not both") + else: + iv = IV - if len(iv) != factory.block_size: - raise ValueError("Incorrect IV length (it must be %d bytes long)" % - factory.block_size) + if len(iv) != factory.block_size: + raise ValueError( + "Incorrect IV length (it must be %d bytes long)" % factory.block_size, + ) - segment_size_bytes, rem = divmod(kwargs.pop("segment_size", 8), 8) - if segment_size_bytes == 0 or rem != 0: - raise ValueError("'segment_size' must be positive and multiple of 8 bits") + segment_size_bytes, rem = divmod(kwargs.pop("segment_size", 8), 8) + if segment_size_bytes == 0 or rem != 0: + raise ValueError("'segment_size' must be positive and multiple of 8 bits") - if kwargs: - raise TypeError("Unknown parameters for CFB: %s" % str(kwargs)) - return CfbMode(cipher_state, iv, segment_size_bytes) + if kwargs: + raise TypeError("Unknown parameters for CFB: %s" % str(kwargs)) + return CfbMode(cipher_state, iv, segment_size_bytes) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cfb.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cfb.pyi index 228e4645..623ea4c5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cfb.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_cfb.pyi @@ -4,23 +4,19 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['CfbMode'] - +__all__ = ["CfbMode"] class CfbMode(object): - block_size: int - iv: Buffer - IV: Buffer - - def __init__(self, - block_cipher: SmartPointer, - iv: Buffer, - segment_size: int) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + block_size: int + iv: Buffer + IV: Buffer + + def __init__(self, block_cipher: SmartPointer, iv: Buffer, segment_size: int) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ctr.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ctr.py index 9ce357fc..20c64b5c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ctr.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ctr.py @@ -24,20 +24,28 @@ Counter (CTR) mode. """ -__all__ = ['CtrMode'] +__all__ = ["CtrMode"] import struct -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes from Cryptodome.Util.py3compat import _copy_bytes, is_native_int from Cryptodome.Util.number import long_to_bytes -raw_ctr_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ctr", """ +raw_ctr_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_ctr", + """ int CTR_start_operation(void *cipher, uint8_t initialCounterBlock[], size_t initialCounterBlock_len, @@ -53,341 +61,377 @@ const uint8_t *in, uint8_t *out, size_t data_len); - int CTR_stop_operation(void *ctrState);""" - ) + int CTR_stop_operation(void *ctrState);""", +) class CtrMode(object): - """*CounTeR (CTR)* mode. + """*CounTeR (CTR)* mode. + + This mode is very similar to ECB, in that + encryption of one block is done independently of all other blocks. + + Unlike ECB, the block *position* contributes to the encryption + and no information leaks about symbol frequency. + + Each message block is associated to a *counter* which + must be unique across all messages that get encrypted + with the same key (not just within the same message). + The counter is as big as the block size. + + Counters can be generated in several ways. The most + straightword one is to choose an *initial counter block* + (which can be made public, similarly to the *IV* for the + other modes) and increment its lowest **m** bits by one + (modulo *2^m*) for each block. In most cases, **m** is + chosen to be half the block size. + + See `NIST SP800-38A`_, Section 6.5 (for the mode) and + Appendix B (for how to manage the *initial counter block*). - This mode is very similar to ECB, in that - encryption of one block is done independently of all other blocks. - - Unlike ECB, the block *position* contributes to the encryption - and no information leaks about symbol frequency. - - Each message block is associated to a *counter* which - must be unique across all messages that get encrypted - with the same key (not just within the same message). - The counter is as big as the block size. - - Counters can be generated in several ways. The most - straightword one is to choose an *initial counter block* - (which can be made public, similarly to the *IV* for the - other modes) and increment its lowest **m** bits by one - (modulo *2^m*) for each block. In most cases, **m** is - chosen to be half the block size. - - See `NIST SP800-38A`_, Section 6.5 (for the mode) and - Appendix B (for how to manage the *initial counter block*). - - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - :undocumented: __init__ - """ - - def __init__(self, block_cipher, initial_counter_block, - prefix_len, counter_len, little_endian): - """Create a new block cipher, configured in CTR mode. - - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. - - initial_counter_block : bytes/bytearray/memoryview - The initial plaintext to use to generate the key stream. - - It is as large as the cipher block, and it embeds - the initial value of the counter. - - This value must not be reused. - It shall contain a nonce or a random component. - Reusing the *initial counter block* for encryptions - performed with the same key compromises confidentiality. - - prefix_len : integer - The amount of bytes at the beginning of the counter block - that never change. - - counter_len : integer - The length in bytes of the counter embedded in the counter - block. - - little_endian : boolean - True if the counter in the counter block is an integer encoded - in little endian mode. If False, it is big endian. - """ - - if len(initial_counter_block) == prefix_len + counter_len: - self.nonce = _copy_bytes(None, prefix_len, initial_counter_block) - """Nonce; not available if there is a fixed suffix""" - - self._state = VoidPointer() - result = raw_ctr_lib.CTR_start_operation(block_cipher.get(), - c_uint8_ptr(initial_counter_block), - c_size_t(len(initial_counter_block)), - c_size_t(prefix_len), - counter_len, - little_endian, - self._state.address_of()) - if result: - raise ValueError("Error %X while instantiating the CTR mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_ctr_lib.CTR_stop_operation) - - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() - - self.block_size = len(initial_counter_block) - """The block size of the underlying cipher, in bytes.""" - - self._next = ["encrypt", "decrypt"] - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "encrypt" not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = ["encrypt"] - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ctr_lib.CTR_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - if result == 0x60002: - raise OverflowError("The counter has wrapped around in" - " CTR mode") - raise ValueError("Error %X while encrypting in CTR mode" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = ["decrypt"] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ctr_lib.CTR_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - if result == 0x60002: - raise OverflowError("The counter has wrapped around in" - " CTR mode") - raise ValueError("Error %X while decrypting in CTR mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + + :undocumented: __init__ + """ + + def __init__( + self, + block_cipher, + initial_counter_block, + prefix_len, + counter_len, + little_endian, + ): + """Create a new block cipher, configured in CTR mode. + + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. + + initial_counter_block : bytes/bytearray/memoryview + The initial plaintext to use to generate the key stream. + + It is as large as the cipher block, and it embeds + the initial value of the counter. + + This value must not be reused. + It shall contain a nonce or a random component. + Reusing the *initial counter block* for encryptions + performed with the same key compromises confidentiality. + + prefix_len : integer + The amount of bytes at the beginning of the counter block + that never change. + + counter_len : integer + The length in bytes of the counter embedded in the counter + block. + + little_endian : boolean + True if the counter in the counter block is an integer encoded + in little endian mode. If False, it is big endian. + """ + + if len(initial_counter_block) == prefix_len + counter_len: + self.nonce = _copy_bytes(None, prefix_len, initial_counter_block) + """Nonce; not available if there is a fixed suffix""" + + self._state = VoidPointer() + result = raw_ctr_lib.CTR_start_operation( + block_cipher.get(), + c_uint8_ptr(initial_counter_block), + c_size_t(len(initial_counter_block)), + c_size_t(prefix_len), + counter_len, + little_endian, + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the CTR mode" % result, + ) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + raw_ctr_lib.CTR_stop_operation, + ) + + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + block_cipher.release() + + self.block_size = len(initial_counter_block) + """The block size of the underlying cipher, in bytes.""" + + self._next = ["encrypt", "decrypt"] + + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. + + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. + + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is equivalent to: + + >>> c.encrypt(a+b) + + This function does not add any padding to the plaintext. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "encrypt" not in self._next: + raise TypeError("encrypt() cannot be called after decrypt()") + self._next = ["encrypt"] + + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ctr_lib.CTR_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + if result == 0x60002: + raise OverflowError( + "The counter has wrapped around in CTR mode", + ) + raise ValueError("Error %X while encrypting in CTR mode" % result) + + if output is None: + return get_raw_buffer(ciphertext) + else: + return None + + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. + + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. + + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is equivalent to: + + >>> c.decrypt(a+b) + + This function does not remove any padding from the plaintext. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError("decrypt() cannot be called after encrypt()") + self._next = ["decrypt"] + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ctr_lib.CTR_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + if result == 0x60002: + raise OverflowError( + "The counter has wrapped around in CTR mode", + ) + raise ValueError("Error %X while decrypting in CTR mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_ctr_cipher(factory, **kwargs): - """Instantiate a cipher object that performs CTR encryption/decryption. - - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. - - :Keywords: - nonce : bytes/bytearray/memoryview - The fixed part at the beginning of the counter block - the rest is - the counter number that gets increased when processing the next block. - The nonce must be such that no two messages are encrypted under the - same key and the same nonce. - - The nonce must be shorter than the block size (it can have - zero length; the counter is then as long as the block). - - If this parameter is not present, a random nonce will be created with - length equal to half the block size. No random nonce shorter than - 64 bits will be created though - you must really think through all - security consequences of using such a short block size. - - initial_value : posive integer or bytes/bytearray/memoryview - The initial value for the counter. If not present, the cipher will - start counting from 0. The value is incremented by one for each block. - The counter number is encoded in big endian mode. - - counter : object - Instance of ``Cryptodome.Util.Counter``, which allows full customization - of the counter block. This parameter is incompatible to both ``nonce`` - and ``initial_value``. - - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ - - cipher_state = factory._create_base_cipher(kwargs) - - counter = kwargs.pop("counter", None) - nonce = kwargs.pop("nonce", None) - initial_value = kwargs.pop("initial_value", None) - if kwargs: - raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs)) - - if counter is not None and (nonce, initial_value) != (None, None): - raise TypeError("'counter' and 'nonce'/'initial_value'" - " are mutually exclusive") - - if counter is None: - # Cryptodome.Util.Counter is not used - if nonce is None: - if factory.block_size < 16: - raise TypeError("Impossible to create a safe nonce for short" - " block sizes") - nonce = get_random_bytes(factory.block_size // 2) - else: - if len(nonce) >= factory.block_size: - raise ValueError("Nonce is too long") - - # What is not nonce is counter - counter_len = factory.block_size - len(nonce) - - if initial_value is None: - initial_value = 0 - - if is_native_int(initial_value): - if (1 << (counter_len * 8)) - 1 < initial_value: - raise ValueError("Initial counter value is too large") - initial_counter_block = nonce + long_to_bytes(initial_value, counter_len) - else: - if len(initial_value) != counter_len: - raise ValueError("Incorrect length for counter byte string (%d bytes, expected %d)" % - (len(initial_value), counter_len)) - initial_counter_block = nonce + initial_value - - return CtrMode(cipher_state, - initial_counter_block, - len(nonce), # prefix - counter_len, - False) # little_endian - - # Cryptodome.Util.Counter is used - - # 'counter' used to be a callable object, but now it is - # just a dictionary for backward compatibility. - _counter = dict(counter) - try: - counter_len = _counter.pop("counter_len") - prefix = _counter.pop("prefix") - suffix = _counter.pop("suffix") - initial_value = _counter.pop("initial_value") - little_endian = _counter.pop("little_endian") - except KeyError: - raise TypeError("Incorrect counter object" - " (use Cryptodome.Util.Counter.new)") - - # Compute initial counter block - words = [] - while initial_value > 0: - words.append(struct.pack('B', initial_value & 255)) - initial_value >>= 8 - words += [b'\x00'] * max(0, counter_len - len(words)) - if not little_endian: - words.reverse() - initial_counter_block = prefix + b"".join(words) + suffix - - if len(initial_counter_block) != factory.block_size: - raise ValueError("Size of the counter block (%d bytes) must match" - " block size (%d)" % (len(initial_counter_block), - factory.block_size)) - - return CtrMode(cipher_state, initial_counter_block, - len(prefix), counter_len, little_endian) + """Instantiate a cipher object that performs CTR encryption/decryption. + + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. + + :Keywords: + nonce : bytes/bytearray/memoryview + The fixed part at the beginning of the counter block - the rest is + the counter number that gets increased when processing the next block. + The nonce must be such that no two messages are encrypted under the + same key and the same nonce. + + The nonce must be shorter than the block size (it can have + zero length; the counter is then as long as the block). + + If this parameter is not present, a random nonce will be created with + length equal to half the block size. No random nonce shorter than + 64 bits will be created though - you must really think through all + security consequences of using such a short block size. + + initial_value : posive integer or bytes/bytearray/memoryview + The initial value for the counter. If not present, the cipher will + start counting from 0. The value is incremented by one for each block. + The counter number is encoded in big endian mode. + + counter : object + Instance of ``Cryptodome.Util.Counter``, which allows full customization + of the counter block. This parameter is incompatible to both ``nonce`` + and ``initial_value``. + + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ + + cipher_state = factory._create_base_cipher(kwargs) + + counter = kwargs.pop("counter", None) + nonce = kwargs.pop("nonce", None) + initial_value = kwargs.pop("initial_value", None) + if kwargs: + raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs)) + + if counter is not None and (nonce, initial_value) != (None, None): + raise TypeError( + "'counter' and 'nonce'/'initial_value' are mutually exclusive", + ) + + if counter is None: + # Cryptodome.Util.Counter is not used + if nonce is None: + if factory.block_size < 16: + raise TypeError( + "Impossible to create a safe nonce for short block sizes", + ) + nonce = get_random_bytes(factory.block_size // 2) + else: + if len(nonce) >= factory.block_size: + raise ValueError("Nonce is too long") + + # What is not nonce is counter + counter_len = factory.block_size - len(nonce) + + if initial_value is None: + initial_value = 0 + + if is_native_int(initial_value): + if (1 << (counter_len * 8)) - 1 < initial_value: + raise ValueError("Initial counter value is too large") + initial_counter_block = nonce + long_to_bytes(initial_value, counter_len) + else: + if len(initial_value) != counter_len: + raise ValueError( + "Incorrect length for counter byte string (%d bytes, expected %d)" + % (len(initial_value), counter_len), + ) + initial_counter_block = nonce + initial_value + + return CtrMode( + cipher_state, + initial_counter_block, + len(nonce), # prefix + counter_len, + False, + ) # little_endian + + # Cryptodome.Util.Counter is used + + # 'counter' used to be a callable object, but now it is + # just a dictionary for backward compatibility. + _counter = dict(counter) + try: + counter_len = _counter.pop("counter_len") + prefix = _counter.pop("prefix") + suffix = _counter.pop("suffix") + initial_value = _counter.pop("initial_value") + little_endian = _counter.pop("little_endian") + except KeyError: + raise TypeError( + "Incorrect counter object (use Cryptodome.Util.Counter.new)", + ) + + # Compute initial counter block + words = [] + while initial_value > 0: + words.append(struct.pack("B", initial_value & 255)) + initial_value >>= 8 + words += [b"\x00"] * max(0, counter_len - len(words)) + if not little_endian: + words.reverse() + initial_counter_block = prefix + b"".join(words) + suffix + + if len(initial_counter_block) != factory.block_size: + raise ValueError( + "Size of the counter block (%d bytes) must match" + " block size (%d)" + % ( + len(initial_counter_block), + factory.block_size, + ), + ) + + return CtrMode( + cipher_state, + initial_counter_block, + len(prefix), + counter_len, + little_endian, + ) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ctr.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ctr.pyi index a68a8909..e5270bce 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ctr.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ctr.pyi @@ -4,24 +4,25 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['CtrMode'] +__all__ = ["CtrMode"] class CtrMode(object): - block_size: int - nonce: bytes - - def __init__(self, - block_cipher: SmartPointer, - initial_counter_block: Buffer, - prefix_len: int, - counter_len: int, - little_endian: bool) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + block_size: int + nonce: bytes + def __init__( + self, + block_cipher: SmartPointer, + initial_counter_block: Buffer, + prefix_len: int, + counter_len: int, + little_endian: bool, + ) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_eax.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_eax.py index 44ef21f5..8126cc3f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_eax.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_eax.py @@ -32,377 +32,397 @@ EAX mode. """ -__all__ = ['EaxMode'] +__all__ = ["EaxMode"] import struct from binascii import unhexlify -from Cryptodome.Util.py3compat import byte_string, bord, _copy_bytes +from Cryptodome.Util.py3compat import bord, _copy_bytes from Cryptodome.Util._raw_api import is_buffer from Cryptodome.Util.strxor import strxor -from Cryptodome.Util.number import long_to_bytes, bytes_to_long +from Cryptodome.Util.number import bytes_to_long from Cryptodome.Hash import CMAC, BLAKE2s from Cryptodome.Random import get_random_bytes class EaxMode(object): - """*EAX* mode. + """*EAX* mode. + + This is an Authenticated Encryption with Associated Data + (`AEAD`_) mode. It provides both confidentiality and authenticity. + + The header of the message may be left in the clear, if needed, + and it will still be subject to authentication. + + The decryption step tells the receiver if the message comes + from a source that really knowns the secret key. + Additionally, decryption detects if any part of the message - + including the header - has been modified or corrupted. + + This mode requires a *nonce*. + + This mode is only available for ciphers that operate on 64 or + 128 bits blocks. + + There are no official standards defining EAX. + The implementation is based on `a proposal`__ that + was presented to NIST. + + .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html + .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf + + :undocumented: __init__ + """ + + def __init__(self, factory, key, nonce, mac_len, cipher_params): + """EAX cipher mode""" + + self.block_size = factory.block_size + """The block size of the underlying cipher, in bytes.""" + + self.nonce = _copy_bytes(None, None, nonce) + """The nonce originally used to create the object.""" + + self._mac_len = mac_len + self._mac_tag = None # Cache for MAC tag - This is an Authenticated Encryption with Associated Data - (`AEAD`_) mode. It provides both confidentiality and authenticity. + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + # MAC tag length + if not (2 <= self._mac_len <= self.block_size): + raise ValueError( + "'mac_len' must be at least 2 and not larger than %d" % self.block_size, + ) + + # Nonce cannot be empty and must be a byte string + if len(self.nonce) == 0: + raise ValueError("Nonce cannot be empty in EAX mode") + if not is_buffer(nonce): + raise TypeError("nonce must be bytes, bytearray or memoryview") + + self._omac = [ + CMAC.new( + key, + b"\x00" * (self.block_size - 1) + struct.pack("B", i), + ciphermod=factory, + cipher_params=cipher_params, + ) + for i in range(0, 3) + ] + + # Compute MAC of nonce + self._omac[0].update(self.nonce) + self._signer = self._omac[1] + + # MAC of the nonce is also the initial counter for CTR encryption + counter_int = bytes_to_long(self._omac[0].digest()) + self._cipher = factory.new( + key, + factory.MODE_CTR, + initial_value=counter_int, + nonce=b"", + **cipher_params, + ) + + def update(self, assoc_data): + """Protect associated data + + If there is any associated data, the caller has to invoke + this function one or more times, before using + ``decrypt`` or ``encrypt``. + + By *associated data* it is meant any data (e.g. packet headers) that + will not be encrypted and will be transmitted in the clear. + However, the receiver is still able to detect any modification to it. + + If there is no associated data, this method must not be called. + + The caller may split associated data in segments of any size, and + invoke this method multiple times, each time with the next segment. + + :Parameters: + assoc_data : bytes/bytearray/memoryview + A piece of associated data. There are no restrictions on its size. + """ + + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) + + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + self._signer.update(assoc_data) + return self + + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. + + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. + + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is equivalent to: + + >>> c.encrypt(a+b) + + This function does not add any padding to the plaintext. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext as ``bytes``. + Otherwise, ``None``. + """ + + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) + self._next = ["encrypt", "digest"] + ct = self._cipher.encrypt(plaintext, output=output) + if output is None: + self._omac[2].update(ct) + else: + self._omac[2].update(output) + return ct + + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. + + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. + + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is equivalent to: - The header of the message may be left in the clear, if needed, - and it will still be subject to authentication. + >>> c.decrypt(a+b) - The decryption step tells the receiver if the message comes - from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - - including the header - has been modified or corrupted. + This function does not remove any padding from the plaintext. - This mode requires a *nonce*. + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + self._next = ["decrypt", "verify"] + self._omac[2].update(ciphertext) + return self._cipher.decrypt(ciphertext, output=output) + + def digest(self): + """Compute the *binary* MAC tag. + + The caller invokes this function at the very end. + + This method returns the MAC that shall be sent to the receiver, + together with the ciphertext. - This mode is only available for ciphers that operate on 64 or - 128 bits blocks. + :Return: the MAC, as a byte string. + """ - There are no official standards defining EAX. - The implementation is based on `a proposal`__ that - was presented to NIST. + if "digest" not in self._next: + raise TypeError( + "digest() cannot be called when decrypting or validating a message", + ) + self._next = ["digest"] + + if not self._mac_tag: + tag = b"\x00" * self.block_size + for i in range(3): + tag = strxor(tag, self._omac[i].digest()) + self._mac_tag = tag[: self._mac_len] + + return self._mac_tag + + def hexdigest(self): + """Compute the *printable* MAC tag. + + This method is like `digest`. + + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. + + The caller invokes this function at the very end. + + This method checks if the decrypted message is indeed valid + (that is, if the key is correct) and it has not been + tampered with while in transit. + + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises MacMismatchError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ["verify"] + + if not self._mac_tag: + tag = b"\x00" * self.block_size + for i in range(3): + tag = strxor(tag, self._omac[i].digest()) + self._mac_tag = tag[: self._mac_len] + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. + + This method is like `verify`. + + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises MacMismatchError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + self.verify(unhexlify(hex_mac_tag)) + + def encrypt_and_digest(self, plaintext, output=None): + """Perform encrypt() and digest() in one step. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + a tuple with two items: - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf + - the ciphertext, as ``bytes`` + - the MAC tag, as ``bytes`` - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, mac_len, cipher_params): - """EAX cipher mode""" - - self.block_size = factory.block_size - """The block size of the underlying cipher, in bytes.""" - - self.nonce = _copy_bytes(None, None, nonce) - """The nonce originally used to create the object.""" - - self._mac_len = mac_len - self._mac_tag = None # Cache for MAC tag - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - # MAC tag length - if not (2 <= self._mac_len <= self.block_size): - raise ValueError("'mac_len' must be at least 2 and not larger than %d" - % self.block_size) - - # Nonce cannot be empty and must be a byte string - if len(self.nonce) == 0: - raise ValueError("Nonce cannot be empty in EAX mode") - if not is_buffer(nonce): - raise TypeError("nonce must be bytes, bytearray or memoryview") - - self._omac = [ - CMAC.new(key, - b'\x00' * (self.block_size - 1) + struct.pack('B', i), - ciphermod=factory, - cipher_params=cipher_params) - for i in range(0, 3) - ] - - # Compute MAC of nonce - self._omac[0].update(self.nonce) - self._signer = self._omac[1] - - # MAC of the nonce is also the initial counter for CTR encryption - counter_int = bytes_to_long(self._omac[0].digest()) - self._cipher = factory.new(key, - factory.MODE_CTR, - initial_value=counter_int, - nonce=b"", - **cipher_params) - - def update(self, assoc_data): - """Protect associated data - - If there is any associated data, the caller has to invoke - this function one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver is still able to detect any modification to it. - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. There are no restrictions on its size. - """ - - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - self._signer.update(assoc_data) - return self - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext as ``bytes``. - Otherwise, ``None``. - """ - - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - self._next = ["encrypt", "digest"] - ct = self._cipher.encrypt(plaintext, output=output) - if output is None: - self._omac[2].update(ct) - else: - self._omac[2].update(output) - return ct - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = ["decrypt", "verify"] - self._omac[2].update(ciphertext) - return self._cipher.decrypt(ciphertext, output=output) - - def digest(self): - """Compute the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. - - :Return: the MAC, as a byte string. - """ - - if "digest" not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = ["digest"] - - if not self._mac_tag: - tag = b'\x00' * self.block_size - for i in range(3): - tag = strxor(tag, self._omac[i].digest()) - self._mac_tag = tag[:self._mac_len] - - return self._mac_tag - - def hexdigest(self): - """Compute the *printable* MAC tag. - - This method is like `digest`. - - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. - - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises MacMismatchError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ["verify"] - - if not self._mac_tag: - tag = b'\x00' * self.block_size - for i in range(3): - tag = strxor(tag, self._omac[i].digest()) - self._mac_tag = tag[:self._mac_len] - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. - - This method is like `verify`. - - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises MacMismatchError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: - - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` - - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ - - return self.encrypt(plaintext, output=output), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): - """Perform decrypt() and verify() in one step. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises MacMismatchError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - pt = self.decrypt(ciphertext, output=output) - self.verify(received_mac_tag) - return pt + The first item becomes ``None`` when the ``output`` parameter + specified a location for the result. + """ + + return self.encrypt(plaintext, output=output), self.digest() + + def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): + """Perform decrypt() and verify() in one step. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` + parameter specified a location for the result. + :Raises MacMismatchError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + pt = self.decrypt(ciphertext, output=output) + self.verify(received_mac_tag) + return pt def _create_eax_cipher(factory, **kwargs): - """Create a new block cipher, configured in EAX mode. - - :Parameters: - factory : module - A symmetric cipher module from `Cryptodome.Cipher` (like - `Cryptodome.Cipher.AES`). - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - There are no restrictions on its length, but it is recommended to use - at least 16 bytes. - - The nonce shall never repeat for two different messages encrypted with - the same key, but it does not need to be random. - - If not specified, a 16 byte long random string is used. - - mac_len : integer - Length of the MAC, in bytes. It must be no larger than the cipher - block bytes (which is the default). - """ - - try: - key = kwargs.pop("key") - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(16) - mac_len = kwargs.pop("mac_len", factory.block_size) - except KeyError as e: - raise TypeError("Missing parameter: " + str(e)) - - return EaxMode(factory, key, nonce, mac_len, kwargs) + """Create a new block cipher, configured in EAX mode. + + :Parameters: + factory : module + A symmetric cipher module from `Cryptodome.Cipher` (like + `Cryptodome.Cipher.AES`). + + :Keywords: + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. + + nonce : bytes/bytearray/memoryview + A value that must never be reused for any other encryption. + There are no restrictions on its length, but it is recommended to use + at least 16 bytes. + + The nonce shall never repeat for two different messages encrypted with + the same key, but it does not need to be random. + + If not specified, a 16 byte long random string is used. + + mac_len : integer + Length of the MAC, in bytes. It must be no larger than the cipher + block bytes (which is the default). + """ + + try: + key = kwargs.pop("key") + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(16) + mac_len = kwargs.pop("mac_len", factory.block_size) + except KeyError as e: + raise TypeError("Missing parameter: " + str(e)) + + return EaxMode(factory, key, nonce, mac_len, kwargs) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_eax.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_eax.pyi index cbfa467e..b5129fa9 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_eax.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_eax.pyi @@ -1,45 +1,37 @@ from types import ModuleType -from typing import Any, Union, Tuple, Dict, overload, Optional +from typing import Union, Tuple, Dict, overload, Optional Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['EaxMode'] +__all__ = ["EaxMode"] class EaxMode(object): - block_size: int - nonce: bytes - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - mac_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> EaxMode: ... + block_size: int + nonce: bytes - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... + def __init__( + self, factory: ModuleType, key: Buffer, nonce: Buffer, mac_len: int, cipher_params: Dict + ) -> None: ... + def update(self, assoc_data: Buffer) -> EaxMode: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer, output: Buffer) -> Tuple[None, bytes]: ... + def decrypt_and_verify( + self, + ciphertext: Buffer, + received_mac_tag: Buffer, + output: Optional[Union[bytearray, memoryview]] = ..., + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ecb.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ecb.py index a01a16fe..bf32c165 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ecb.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ecb.py @@ -24,15 +24,22 @@ Electronic Code Book (ECB) mode. """ -__all__ = [ 'EcbMode' ] - -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, create_string_buffer, - get_raw_buffer, SmartPointer, - c_size_t, c_uint8_ptr, - is_writeable_buffer) - -raw_ecb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ecb", """ +__all__ = ["EcbMode"] + +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) + +raw_ecb_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_ecb", + """ int ECB_start_operation(void *cipher, void **pResult); int ECB_encrypt(void *ecbState, @@ -44,177 +51,188 @@ uint8_t *out, size_t data_len); int ECB_stop_operation(void *state); - """ - ) + """, +) class EcbMode(object): - """*Electronic Code Book (ECB)*. - - This is the simplest encryption mode. Each of the plaintext blocks - is directly encrypted into a ciphertext block, independently of - any other block. - - This mode is dangerous because it exposes frequency of symbols - in your plaintext. Other modes (e.g. *CBC*) should be used instead. - - See `NIST SP800-38A`_ , Section 6.1. + """*Electronic Code Book (ECB)*. + + This is the simplest encryption mode. Each of the plaintext blocks + is directly encrypted into a ciphertext block, independently of + any other block. + + This mode is dangerous because it exposes frequency of symbols + in your plaintext. Other modes (e.g. *CBC*) should be used instead. + + See `NIST SP800-38A`_ , Section 6.1. + + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + + :undocumented: __init__ + """ + + def __init__(self, block_cipher): + """Create a new block cipher, configured in ECB mode. - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. + """ + self.block_size = block_cipher.block_size - :undocumented: __init__ - """ - - def __init__(self, block_cipher): - """Create a new block cipher, configured in ECB mode. - - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. - """ - self.block_size = block_cipher.block_size - - self._state = VoidPointer() - result = raw_ecb_lib.ECB_start_operation(block_cipher.get(), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the ECB mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher - # mode - self._state = SmartPointer(self._state.get(), - raw_ecb_lib.ECB_stop_operation) - - # Memory allocated for the underlying block cipher is now owned - # by the cipher mode - block_cipher.release() - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key set at initialization. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - The length must be multiple of the cipher block length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ecb_lib.ECB_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - if result == 3: - raise ValueError("Data must be aligned to block boundary in ECB mode") - raise ValueError("Error %d while encrypting in ECB mode" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key set at initialization. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - The length must be multiple of the cipher block length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ecb_lib.ECB_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - if result == 3: - raise ValueError("Data must be aligned to block boundary in ECB mode") - raise ValueError("Error %d while decrypting in ECB mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + self._state = VoidPointer() + result = raw_ecb_lib.ECB_start_operation( + block_cipher.get(), + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %d while instantiating the ECB mode" % result, + ) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher + # mode + self._state = SmartPointer( + self._state.get(), + raw_ecb_lib.ECB_stop_operation, + ) + + # Memory allocated for the underlying block cipher is now owned + # by the cipher mode + block_cipher.release() + + def encrypt(self, plaintext, output=None): + """Encrypt data with the key set at initialization. + + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. + + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is equivalent to: + + >>> c.encrypt(a+b) + + This function does not add any padding to the plaintext. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + The length must be multiple of the cipher block length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ecb_lib.ECB_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + if result == 3: + raise ValueError("Data must be aligned to block boundary in ECB mode") + raise ValueError("Error %d while encrypting in ECB mode" % result) + + if output is None: + return get_raw_buffer(ciphertext) + else: + return None + + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key set at initialization. + + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. + + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is equivalent to: + + >>> c.decrypt(a+b) + + This function does not remove any padding from the plaintext. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + The length must be multiple of the cipher block length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ecb_lib.ECB_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + if result == 3: + raise ValueError("Data must be aligned to block boundary in ECB mode") + raise ValueError("Error %d while decrypting in ECB mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_ecb_cipher(factory, **kwargs): - """Instantiate a cipher object that performs ECB encryption/decryption. + """Instantiate a cipher object that performs ECB encryption/decryption. - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. - All keywords are passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present""" + All keywords are passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present""" - cipher_state = factory._create_base_cipher(kwargs) - cipher_state.block_size = factory.block_size - if kwargs: - raise TypeError("Unknown parameters for ECB: %s" % str(kwargs)) - return EcbMode(cipher_state) + cipher_state = factory._create_base_cipher(kwargs) + cipher_state.block_size = factory.block_size + if kwargs: + raise TypeError("Unknown parameters for ECB: %s" % str(kwargs)) + return EcbMode(cipher_state) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ecb.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ecb.pyi index 936195f9..474ccd6f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ecb.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ecb.pyi @@ -4,16 +4,15 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = [ 'EcbMode' ] +__all__ = ["EcbMode"] class EcbMode(object): - def __init__(self, block_cipher: SmartPointer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - + def __init__(self, block_cipher: SmartPointer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_gcm.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_gcm.py index 99144006..42ce3084 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_gcm.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_gcm.py @@ -32,7 +32,7 @@ Galois/Counter Mode (GCM). """ -__all__ = ['GcmMode'] +__all__ = ["GcmMode"] from binascii import unhexlify @@ -44,9 +44,15 @@ from Cryptodome.Hash import BLAKE2s from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) from Cryptodome.Util import _cpu_features @@ -63,558 +69,592 @@ int ghash_destroy_%imp%(void *ghash_tables); """ + def _build_impl(lib, postfix): - from collections import namedtuple + from collections import namedtuple - funcs = ( "ghash", "ghash_expand", "ghash_destroy" ) - GHASH_Imp = namedtuple('_GHash_Imp', funcs) - try: - imp_funcs = [ getattr(lib, x + "_" + postfix) for x in funcs ] - except AttributeError: # Make sphinx stop complaining with its mocklib - imp_funcs = [ None ] * 3 - params = dict(zip(funcs, imp_funcs)) - return GHASH_Imp(**params) + funcs = ("ghash", "ghash_expand", "ghash_destroy") + GHASH_Imp = namedtuple("_GHash_Imp", funcs) + try: + imp_funcs = [getattr(lib, x + "_" + postfix) for x in funcs] + except AttributeError: # Make sphinx stop complaining with its mocklib + imp_funcs = [None] * 3 + params = dict(zip(funcs, imp_funcs)) + return GHASH_Imp(**params) def _get_ghash_portable(): - api = _ghash_api_template.replace("%imp%", "portable") - lib = load_pycryptodome_raw_lib("Cryptodome.Hash._ghash_portable", api) - result = _build_impl(lib, "portable") - return result + api = _ghash_api_template.replace("%imp%", "portable") + lib = load_pycryptodome_raw_lib("Cryptodome.Hash._ghash_portable", api) + result = _build_impl(lib, "portable") + return result + + _ghash_portable = _get_ghash_portable() def _get_ghash_clmul(): - """Return None if CLMUL implementation is not available""" - - if not _cpu_features.have_clmul(): - return None - try: - api = _ghash_api_template.replace("%imp%", "clmul") - lib = load_pycryptodome_raw_lib("Cryptodome.Hash._ghash_clmul", api) - result = _build_impl(lib, "clmul") - except OSError: - result = None - return result + """Return None if CLMUL implementation is not available""" + + if not _cpu_features.have_clmul(): + return None + try: + api = _ghash_api_template.replace("%imp%", "clmul") + lib = load_pycryptodome_raw_lib("Cryptodome.Hash._ghash_clmul", api) + result = _build_impl(lib, "clmul") + except OSError: + result = None + return result + + _ghash_clmul = _get_ghash_clmul() class _GHASH(object): - """GHASH function defined in NIST SP 800-38D, Algorithm 2. + """GHASH function defined in NIST SP 800-38D, Algorithm 2. - If X_1, X_2, .. X_m are the blocks of input data, the function - computes: + If X_1, X_2, .. X_m are the blocks of input data, the function + computes: - X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H + X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H - in the Galois field GF(2^256) using the reducing polynomial - (x^128 + x^7 + x^2 + x + 1). - """ + in the Galois field GF(2^256) using the reducing polynomial + (x^128 + x^7 + x^2 + x + 1). + """ - def __init__(self, subkey, ghash_c): - assert len(subkey) == 16 + def __init__(self, subkey, ghash_c): + assert len(subkey) == 16 - self.ghash_c = ghash_c + self.ghash_c = ghash_c - self._exp_key = VoidPointer() - result = ghash_c.ghash_expand(c_uint8_ptr(subkey), - self._exp_key.address_of()) - if result: - raise ValueError("Error %d while expanding the GHASH key" % result) + self._exp_key = VoidPointer() + result = ghash_c.ghash_expand( + c_uint8_ptr(subkey), + self._exp_key.address_of(), + ) + if result: + raise ValueError("Error %d while expanding the GHASH key" % result) - self._exp_key = SmartPointer(self._exp_key.get(), - ghash_c.ghash_destroy) + self._exp_key = SmartPointer( + self._exp_key.get(), + ghash_c.ghash_destroy, + ) - # create_string_buffer always returns a string of zeroes - self._last_y = create_string_buffer(16) + # create_string_buffer always returns a string of zeroes + self._last_y = create_string_buffer(16) - def update(self, block_data): - assert len(block_data) % 16 == 0 + def update(self, block_data): + assert len(block_data) % 16 == 0 - result = self.ghash_c.ghash(self._last_y, - c_uint8_ptr(block_data), - c_size_t(len(block_data)), - self._last_y, - self._exp_key.get()) - if result: - raise ValueError("Error %d while updating GHASH" % result) + result = self.ghash_c.ghash( + self._last_y, + c_uint8_ptr(block_data), + c_size_t(len(block_data)), + self._last_y, + self._exp_key.get(), + ) + if result: + raise ValueError("Error %d while updating GHASH" % result) - return self + return self - def digest(self): - return get_raw_buffer(self._last_y) + def digest(self): + return get_raw_buffer(self._last_y) def enum(**enums): - return type('Enum', (), enums) + return type("Enum", (), enums) MacStatus = enum(PROCESSING_AUTH_DATA=1, PROCESSING_CIPHERTEXT=2) class GcmMode(object): - """Galois Counter Mode (GCM). - - This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. - It provides both confidentiality and authenticity. - - The header of the message may be left in the clear, if needed, and it will - still be subject to authentication. The decryption step tells the receiver - if the message comes from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - including the - header - has been modified or corrupted. - - This mode requires a *nonce*. - - This mode is only available for ciphers that operate on 128 bits blocks - (e.g. AES but not TDES). - - See `NIST SP800-38D`_. - - .. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, mac_len, cipher_params, ghash_c): - - self.block_size = factory.block_size - if self.block_size != 16: - raise ValueError("GCM mode is only available for ciphers" - " that operate on 128 bits blocks") - - if len(nonce) == 0: - raise ValueError("Nonce cannot be empty") - - if not is_buffer(nonce): - raise TypeError("Nonce must be bytes, bytearray or memoryview") - - # See NIST SP 800 38D, 5.2.1.1 - if len(nonce) > 2**64 - 1: - raise ValueError("Nonce exceeds maximum length") - - - self.nonce = _copy_bytes(None, None, nonce) - """Nonce""" - - self._factory = factory - self._key = _copy_bytes(None, None, key) - self._tag = None # Cache for MAC tag - - self._mac_len = mac_len - if not (4 <= mac_len <= 16): - raise ValueError("Parameter 'mac_len' must be in the range 4..16") - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - self._no_more_assoc_data = False - - # Length of associated data - self._auth_len = 0 - - # Length of the ciphertext or plaintext - self._msg_len = 0 - - # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H - # See also Algorithm 5 (decryption) - hash_subkey = factory.new(key, - self._factory.MODE_ECB, - **cipher_params - ).encrypt(b'\x00' * 16) - - # Step 2 - Compute J0 - if len(self.nonce) == 12: - j0 = self.nonce + b"\x00\x00\x00\x01" - else: - fill = (16 - (len(self.nonce) % 16)) % 16 + 8 - ghash_in = (self.nonce + - b'\x00' * fill + - long_to_bytes(8 * len(self.nonce), 8)) - j0 = _GHASH(hash_subkey, ghash_c).update(ghash_in).digest() - - # Step 3 - Prepare GCTR cipher for encryption/decryption - nonce_ctr = j0[:12] - iv_ctr = (bytes_to_long(j0) + 1) & 0xFFFFFFFF - self._cipher = factory.new(key, - self._factory.MODE_CTR, - initial_value=iv_ctr, - nonce=nonce_ctr, - **cipher_params) - - # Step 5 - Bootstrat GHASH - self._signer = _GHASH(hash_subkey, ghash_c) - - # Step 6 - Prepare GCTR cipher for GMAC - self._tag_cipher = factory.new(key, - self._factory.MODE_CTR, - initial_value=j0, - nonce=b"", - **cipher_params) - - # Cache for data to authenticate - self._cache = b"" - - self._status = MacStatus.PROCESSING_AUTH_DATA - - def update(self, assoc_data): - """Protect associated data - - If there is any associated data, the caller has to invoke - this function one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver is still able to detect any modification to it. - In GCM, the *associated data* is also called - *additional authenticated data* (AAD). - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. There are no restrictions on its size. - """ - - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - self._update(assoc_data) - self._auth_len += len(assoc_data) - - # See NIST SP 800 38D, 5.2.1.1 - if self._auth_len > 2**64 - 1: - raise ValueError("Additional Authenticated Data exceeds maximum length") - - return self - - def _update(self, data): - assert(len(self._cache) < 16) - - if len(self._cache) > 0: - filler = min(16 - len(self._cache), len(data)) - self._cache += _copy_bytes(None, filler, data) - data = data[filler:] - - if len(self._cache) < 16: - return - - # The cache is exactly one block - self._signer.update(self._cache) - self._cache = b"" - - update_len = len(data) // 16 * 16 - self._cache = _copy_bytes(update_len, None, data) - if update_len > 0: - self._signer.update(data[:update_len]) - - def _pad_cache_and_update(self): - assert(len(self._cache) < 16) - - # The authenticated data A is concatenated to the minimum - # number of zero bytes (possibly none) such that the - # - ciphertext C is aligned to the 16 byte boundary. - # See step 5 in section 7.1 - # - ciphertext C is aligned to the 16 byte boundary. - # See step 6 in section 7.2 - len_cache = len(self._cache) - if len_cache > 0: - self._update(b'\x00' * (16 - len_cache)) - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) + """Galois Counter Mode (GCM). + + This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. + It provides both confidentiality and authenticity. + + The header of the message may be left in the clear, if needed, and it will + still be subject to authentication. The decryption step tells the receiver + if the message comes from a source that really knowns the secret key. + Additionally, decryption detects if any part of the message - including the + header - has been modified or corrupted. + + This mode requires a *nonce*. + + This mode is only available for ciphers that operate on 128 bits blocks + (e.g. AES but not TDES). + + See `NIST SP800-38D`_. + + .. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html + + :undocumented: __init__ + """ + + def __init__(self, factory, key, nonce, mac_len, cipher_params, ghash_c): + self.block_size = factory.block_size + if self.block_size != 16: + raise ValueError( + "GCM mode is only available for ciphers that operate on 128 bits blocks", + ) + + if len(nonce) == 0: + raise ValueError("Nonce cannot be empty") + + if not is_buffer(nonce): + raise TypeError("Nonce must be bytes, bytearray or memoryview") + + # See NIST SP 800 38D, 5.2.1.1 + if len(nonce) > 2**64 - 1: + raise ValueError("Nonce exceeds maximum length") + + self.nonce = _copy_bytes(None, None, nonce) + """Nonce""" + + self._factory = factory + self._key = _copy_bytes(None, None, key) + self._tag = None # Cache for MAC tag + + self._mac_len = mac_len + if not (4 <= mac_len <= 16): + raise ValueError("Parameter 'mac_len' must be in the range 4..16") + + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + self._no_more_assoc_data = False + + # Length of associated data + self._auth_len = 0 + + # Length of the ciphertext or plaintext + self._msg_len = 0 + + # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H + # See also Algorithm 5 (decryption) + hash_subkey = factory.new( + key, + self._factory.MODE_ECB, + **cipher_params, + ).encrypt(b"\x00" * 16) + + # Step 2 - Compute J0 + if len(self.nonce) == 12: + j0 = self.nonce + b"\x00\x00\x00\x01" + else: + fill = (16 - (len(self.nonce) % 16)) % 16 + 8 + ghash_in = self.nonce + b"\x00" * fill + long_to_bytes(8 * len(self.nonce), 8) + j0 = _GHASH(hash_subkey, ghash_c).update(ghash_in).digest() + + # Step 3 - Prepare GCTR cipher for encryption/decryption + nonce_ctr = j0[:12] + iv_ctr = (bytes_to_long(j0) + 1) & 0xFFFFFFFF + self._cipher = factory.new( + key, + self._factory.MODE_CTR, + initial_value=iv_ctr, + nonce=nonce_ctr, + **cipher_params, + ) + + # Step 5 - Bootstrat GHASH + self._signer = _GHASH(hash_subkey, ghash_c) + + # Step 6 - Prepare GCTR cipher for GMAC + self._tag_cipher = factory.new( + key, + self._factory.MODE_CTR, + initial_value=j0, + nonce=b"", + **cipher_params, + ) + + # Cache for data to authenticate + self._cache = b"" - This function does not add any padding to the plaintext. + self._status = MacStatus.PROCESSING_AUTH_DATA + + def update(self, assoc_data): + """Protect associated data + + If there is any associated data, the caller has to invoke + this function one or more times, before using + ``decrypt`` or ``encrypt``. + + By *associated data* it is meant any data (e.g. packet headers) that + will not be encrypted and will be transmitted in the clear. + However, the receiver is still able to detect any modification to it. + In GCM, the *associated data* is also called + *additional authenticated data* (AAD). + + If there is no associated data, this method must not be called. + + The caller may split associated data in segments of any size, and + invoke this method multiple times, each time with the next segment. + + :Parameters: + assoc_data : bytes/bytearray/memoryview + A piece of associated data. There are no restrictions on its size. + """ + + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) + + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + self._update(assoc_data) + self._auth_len += len(assoc_data) + + # See NIST SP 800 38D, 5.2.1.1 + if self._auth_len > 2**64 - 1: + raise ValueError("Additional Authenticated Data exceeds maximum length") + + return self + + def _update(self, data): + assert len(self._cache) < 16 - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext as ``bytes``. - Otherwise, ``None``. - """ + if len(self._cache) > 0: + filler = min(16 - len(self._cache), len(data)) + self._cache += _copy_bytes(None, filler, data) + data = data[filler:] - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - self._next = ["encrypt", "digest"] + if len(self._cache) < 16: + return + + # The cache is exactly one block + self._signer.update(self._cache) + self._cache = b"" + + update_len = len(data) // 16 * 16 + self._cache = _copy_bytes(update_len, None, data) + if update_len > 0: + self._signer.update(data[:update_len]) + + def _pad_cache_and_update(self): + assert len(self._cache) < 16 + + # The authenticated data A is concatenated to the minimum + # number of zero bytes (possibly none) such that the + # - ciphertext C is aligned to the 16 byte boundary. + # See step 5 in section 7.1 + # - ciphertext C is aligned to the 16 byte boundary. + # See step 6 in section 7.2 + len_cache = len(self._cache) + if len_cache > 0: + self._update(b"\x00" * (16 - len_cache)) - ciphertext = self._cipher.encrypt(plaintext, output=output) + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. - if self._status == MacStatus.PROCESSING_AUTH_DATA: - self._pad_cache_and_update() - self._status = MacStatus.PROCESSING_CIPHERTEXT + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - self._update(ciphertext if output is None else output) - self._msg_len += len(plaintext) + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - # See NIST SP 800 38D, 5.2.1.1 - if self._msg_len > 2**39 - 256: - raise ValueError("Plaintext exceeds maximum length") + That is, the statement: - return ciphertext + >>> c.encrypt(a) + c.encrypt(b) - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. + is equivalent to: - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + >>> c.encrypt(a+b) - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + This function does not add any padding to the plaintext. - That is, the statement: + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext as ``bytes``. + Otherwise, ``None``. + """ - >>> c.decrypt(a) + c.decrypt(b) + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) + self._next = ["encrypt", "digest"] - is equivalent to: + ciphertext = self._cipher.encrypt(plaintext, output=output) - >>> c.decrypt(a+b) + if self._status == MacStatus.PROCESSING_AUTH_DATA: + self._pad_cache_and_update() + self._status = MacStatus.PROCESSING_CIPHERTEXT - This function does not remove any padding from the plaintext. + self._update(ciphertext if output is None else output) + self._msg_len += len(plaintext) - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext as ``bytes``. - Otherwise, ``None``. - """ + # See NIST SP 800 38D, 5.2.1.1 + if self._msg_len > 2**39 - 256: + raise ValueError("Plaintext exceeds maximum length") - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = ["decrypt", "verify"] + return ciphertext - if self._status == MacStatus.PROCESSING_AUTH_DATA: - self._pad_cache_and_update() - self._status = MacStatus.PROCESSING_CIPHERTEXT + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. - self._update(ciphertext) - self._msg_len += len(ciphertext) + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - return self._cipher.decrypt(ciphertext, output=output) + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - def digest(self): - """Compute the *binary* MAC tag in an AEAD mode. + That is, the statement: - The caller invokes this function at the very end. + >>> c.decrypt(a) + c.decrypt(b) - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. + is equivalent to: - :Return: the MAC, as a byte string. - """ + >>> c.decrypt(a+b) - if "digest" not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = ["digest"] + This function does not remove any padding from the plaintext. - return self._compute_mac() + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext as ``bytes``. + Otherwise, ``None``. + """ - def _compute_mac(self): - """Compute MAC without any FSM checks.""" + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + self._next = ["decrypt", "verify"] - if self._tag: - return self._tag + if self._status == MacStatus.PROCESSING_AUTH_DATA: + self._pad_cache_and_update() + self._status = MacStatus.PROCESSING_CIPHERTEXT - # Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S - self._pad_cache_and_update() - self._update(long_to_bytes(8 * self._auth_len, 8)) - self._update(long_to_bytes(8 * self._msg_len, 8)) - s_tag = self._signer.digest() + self._update(ciphertext) + self._msg_len += len(ciphertext) - # Step 6 - Compute T - self._tag = self._tag_cipher.encrypt(s_tag)[:self._mac_len] + return self._cipher.decrypt(ciphertext, output=output) - return self._tag + def digest(self): + """Compute the *binary* MAC tag in an AEAD mode. - def hexdigest(self): - """Compute the *printable* MAC tag. + The caller invokes this function at the very end. - This method is like `digest`. + This method returns the MAC that shall be sent to the receiver, + together with the ciphertext. - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) + :Return: the MAC, as a byte string. + """ - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. + if "digest" not in self._next: + raise TypeError( + "digest() cannot be called when decrypting or validating a message", + ) + self._next = ["digest"] - The caller invokes this function at the very end. + return self._compute_mac() - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. + def _compute_mac(self): + """Compute MAC without any FSM checks.""" - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + if self._tag: + return self._tag - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ["verify"] + # Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S + self._pad_cache_and_update() + self._update(long_to_bytes(8 * self._auth_len, 8)) + self._update(long_to_bytes(8 * self._msg_len, 8)) + s_tag = self._signer.digest() - secret = get_random_bytes(16) + # Step 6 - Compute T + self._tag = self._tag_cipher.encrypt(s_tag)[: self._mac_len] - mac1 = BLAKE2s.new(digest_bits=160, key=secret, - data=self._compute_mac()) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, - data=received_mac_tag) + return self._tag - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + def hexdigest(self): + """Compute the *printable* MAC tag. - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. + This method is like `digest`. - This method is like `verify`. + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. - self.verify(unhexlify(hex_mac_tag)) + The caller invokes this function at the very end. - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. + This method checks if the decrypted message is indeed valid + (that is, if the key is correct) and it has not been + tampered with while in transit. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ["verify"] + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new( + digest_bits=160, + key=secret, + data=self._compute_mac(), + ) + mac2 = BLAKE2s.new( + digest_bits=160, + key=secret, + data=received_mac_tag, + ) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. - return self.encrypt(plaintext, output=output), self.digest() + This method is like `verify`. - def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): - """Perform decrypt() and verify() in one step. + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - received_mac_tag : byte string - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + self.verify(unhexlify(hex_mac_tag)) - plaintext = self.decrypt(ciphertext, output=output) - self.verify(received_mac_tag) - return plaintext + def encrypt_and_digest(self, plaintext, output=None): + """Perform encrypt() and digest() in one step. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + a tuple with two items: + + - the ciphertext, as ``bytes`` + - the MAC tag, as ``bytes`` + + The first item becomes ``None`` when the ``output`` parameter + specified a location for the result. + """ + + return self.encrypt(plaintext, output=output), self.digest() + + def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): + """Perform decrypt() and verify() in one step. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + received_mac_tag : byte string + This is the *binary* MAC, as received from the sender. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` + parameter specified a location for the result. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + plaintext = self.decrypt(ciphertext, output=output) + self.verify(received_mac_tag) + return plaintext def _create_gcm_cipher(factory, **kwargs): - """Create a new block cipher, configured in Galois Counter Mode (GCM). - - :Parameters: - factory : module - A block cipher module, taken from `Cryptodome.Cipher`. - The cipher must have block length of 16 bytes. - GCM has been only defined for `Cryptodome.Cipher.AES`. - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - It must be 16 (e.g. *AES-128*), 24 (e.g. *AES-192*) - or 32 (e.g. *AES-256*) bytes long. - - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - - There are no restrictions on its length, - but it is recommended to use at least 16 bytes. - - The nonce shall never repeat for two - different messages encrypted with the same key, - but it does not need to be random. - - If not provided, a 16 byte nonce will be randomly created. - - mac_len : integer - Length of the MAC, in bytes. - It must be no larger than 16 bytes (which is the default). - """ - - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter:" + str(e)) - - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(16) - mac_len = kwargs.pop("mac_len", 16) - - # Not documented - only used for testing - use_clmul = kwargs.pop("use_clmul", True) - if use_clmul and _ghash_clmul: - ghash_c = _ghash_clmul - else: - ghash_c = _ghash_portable - - return GcmMode(factory, key, nonce, mac_len, kwargs, ghash_c) + """Create a new block cipher, configured in Galois Counter Mode (GCM). + + :Parameters: + factory : module + A block cipher module, taken from `Cryptodome.Cipher`. + The cipher must have block length of 16 bytes. + GCM has been only defined for `Cryptodome.Cipher.AES`. + + :Keywords: + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. + It must be 16 (e.g. *AES-128*), 24 (e.g. *AES-192*) + or 32 (e.g. *AES-256*) bytes long. + + nonce : bytes/bytearray/memoryview + A value that must never be reused for any other encryption. + + There are no restrictions on its length, + but it is recommended to use at least 16 bytes. + + The nonce shall never repeat for two + different messages encrypted with the same key, + but it does not need to be random. + + If not provided, a 16 byte nonce will be randomly created. + + mac_len : integer + Length of the MAC, in bytes. + It must be no larger than 16 bytes (which is the default). + """ + + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter:" + str(e)) + + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(16) + mac_len = kwargs.pop("mac_len", 16) + + # Not documented - only used for testing + use_clmul = kwargs.pop("use_clmul", True) + if use_clmul and _ghash_clmul: + ghash_c = _ghash_clmul + else: + ghash_c = _ghash_portable + + return GcmMode(factory, key, nonce, mac_len, kwargs, ghash_c) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_gcm.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_gcm.pyi index 8912955f..ff0382bd 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_gcm.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_gcm.pyi @@ -1,45 +1,37 @@ from types import ModuleType from typing import Union, Tuple, Dict, overload, Optional -__all__ = ['GcmMode'] +__all__ = ["GcmMode"] Buffer = Union[bytes, bytearray, memoryview] class GcmMode(object): - block_size: int - nonce: Buffer - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - mac_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> GcmMode: ... + block_size: int + nonce: Buffer - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... + def __init__( + self, factory: ModuleType, key: Buffer, nonce: Buffer, mac_len: int, cipher_params: Dict + ) -> None: ... + def update(self, assoc_data: Buffer) -> GcmMode: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer, output: Buffer) -> Tuple[None, bytes]: ... + def decrypt_and_verify( + self, + ciphertext: Buffer, + received_mac_tag: Buffer, + output: Optional[Union[bytearray, memoryview]] = ..., + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_kw.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_kw.py index 41c09ef7..f5de3357 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_kw.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_kw.py @@ -7,152 +7,158 @@ from Cryptodome.Util.strxor import strxor -def W(cipher: ModuleType, - plaintext: Union[bytes, bytearray]) -> bytes: - - S = [plaintext[i:i+8] for i in range(0, len(plaintext), 8)] - n = len(S) - s = 6 * (n - 1) - A = S[0] - R = deque(S[1:]) - - for t in range(1, s + 1): - t_64 = struct.pack('>Q', t) - ct = cipher.encrypt(A + R.popleft()) - A = strxor(ct[:8], t_64) - R.append(ct[8:]) - - return A + b''.join(R) - - -def W_inverse(cipher: ModuleType, - ciphertext: Union[bytes, bytearray]) -> bytes: - - C = [ciphertext[i:i+8] for i in range(0, len(ciphertext), 8)] - n = len(C) - s = 6 * (n - 1) - A = C[0] - R = deque(C[1:]) - - for t in range(s, 0, -1): - t_64 = struct.pack('>Q', t) - pt = cipher.decrypt(strxor(A, t_64) + R.pop()) - A = pt[:8] - R.appendleft(pt[8:]) - - return A + b''.join(R) +def W( + cipher: ModuleType, + plaintext: Union[bytes, bytearray], +) -> bytes: + S = [plaintext[i : i + 8] for i in range(0, len(plaintext), 8)] + n = len(S) + s = 6 * (n - 1) + A = S[0] + R = deque(S[1:]) + + for t in range(1, s + 1): + t_64 = struct.pack(">Q", t) + ct = cipher.encrypt(A + R.popleft()) + A = strxor(ct[:8], t_64) + R.append(ct[8:]) + + return A + b"".join(R) + + +def W_inverse( + cipher: ModuleType, + ciphertext: Union[bytes, bytearray], +) -> bytes: + C = [ciphertext[i : i + 8] for i in range(0, len(ciphertext), 8)] + n = len(C) + s = 6 * (n - 1) + A = C[0] + R = deque(C[1:]) + + for t in range(s, 0, -1): + t_64 = struct.pack(">Q", t) + pt = cipher.decrypt(strxor(A, t_64) + R.pop()) + A = pt[:8] + R.appendleft(pt[8:]) + + return A + b"".join(R) class KWMode(object): - """Key Wrap (KW) mode. - - This is a deterministic Authenticated Encryption (AE) mode - for protecting cryptographic keys. See `NIST SP800-38F`_. + """Key Wrap (KW) mode. - It provides both confidentiality and authenticity, and it designed - so that any bit of the ciphertext depends on all bits of the plaintext. + This is a deterministic Authenticated Encryption (AE) mode + for protecting cryptographic keys. See `NIST SP800-38F`_. - This mode is only available for ciphers that operate on 128 bits blocks - (e.g., AES). + It provides both confidentiality and authenticity, and it designed + so that any bit of the ciphertext depends on all bits of the plaintext. - .. _`NIST SP800-38F`: http://csrc.nist.gov/publications/nistpubs/800-38F/SP-800-38F.pdf + This mode is only available for ciphers that operate on 128 bits blocks + (e.g., AES). - :undocumented: __init__ - """ + .. _`NIST SP800-38F`: http://csrc.nist.gov/publications/nistpubs/800-38F/SP-800-38F.pdf - def __init__(self, - factory: ModuleType, - key: Union[bytes, bytearray]): + :undocumented: __init__ + """ - self.block_size = factory.block_size - if self.block_size != 16: - raise ValueError("Key Wrap mode is only available for ciphers" - " that operate on 128 bits blocks") + def __init__( + self, + factory: ModuleType, + key: Union[bytes, bytearray], + ): + self.block_size = factory.block_size + if self.block_size != 16: + raise ValueError( + "Key Wrap mode is only available for ciphers that operate on 128 bits blocks", + ) - self._factory = factory - self._cipher = factory.new(key, factory.MODE_ECB) - self._done = False + self._factory = factory + self._cipher = factory.new(key, factory.MODE_ECB) + self._done = False - def seal(self, plaintext: Union[bytes, bytearray]) -> bytes: - """Encrypt and authenticate (wrap) a cryptographic key. + def seal(self, plaintext: Union[bytes, bytearray]) -> bytes: + """Encrypt and authenticate (wrap) a cryptographic key. - Args: - plaintext: - The cryptographic key to wrap. - It must be at least 16 bytes long, and its length - must be a multiple of 8. + Args: + plaintext: + The cryptographic key to wrap. + It must be at least 16 bytes long, and its length + must be a multiple of 8. - Returns: - The wrapped key. - """ + Returns: + The wrapped key. + """ - if self._done: - raise ValueError("The cipher cannot be used more than once") + if self._done: + raise ValueError("The cipher cannot be used more than once") - if len(plaintext) % 8: - raise ValueError("The plaintext must have length multiple of 8 bytes") + if len(plaintext) % 8: + raise ValueError("The plaintext must have length multiple of 8 bytes") - if len(plaintext) < 16: - raise ValueError("The plaintext must be at least 16 bytes long") + if len(plaintext) < 16: + raise ValueError("The plaintext must be at least 16 bytes long") - if len(plaintext) >= 2**32: - raise ValueError("The plaintext is too long") + if len(plaintext) >= 2**32: + raise ValueError("The plaintext is too long") - res = W(self._cipher, b'\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6' + plaintext) - self._done = True - return res + res = W(self._cipher, b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" + plaintext) + self._done = True + return res - def unseal(self, ciphertext: Union[bytes, bytearray]) -> bytes: - """Decrypt and authenticate (unwrap) a cryptographic key. + def unseal(self, ciphertext: Union[bytes, bytearray]) -> bytes: + """Decrypt and authenticate (unwrap) a cryptographic key. - Args: - ciphertext: - The cryptographic key to unwrap. - It must be at least 24 bytes long, and its length - must be a multiple of 8. + Args: + ciphertext: + The cryptographic key to unwrap. + It must be at least 24 bytes long, and its length + must be a multiple of 8. - Returns: - The original key. + Returns: + The original key. - Raises: ValueError - If the ciphertext or the key are not valid. - """ + Raises: ValueError + If the ciphertext or the key are not valid. + """ - if self._done: - raise ValueError("The cipher cannot be used more than once") + if self._done: + raise ValueError("The cipher cannot be used more than once") - if len(ciphertext) % 8: - raise ValueError("The ciphertext must have length multiple of 8 bytes") + if len(ciphertext) % 8: + raise ValueError("The ciphertext must have length multiple of 8 bytes") - if len(ciphertext) < 24: - raise ValueError("The ciphertext must be at least 24 bytes long") + if len(ciphertext) < 24: + raise ValueError("The ciphertext must be at least 24 bytes long") - pt = W_inverse(self._cipher, ciphertext) + pt = W_inverse(self._cipher, ciphertext) - if pt[:8] != b'\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6': - raise ValueError("Incorrect integrity check value") - self._done = True + if pt[:8] != b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6": + raise ValueError("Incorrect integrity check value") + self._done = True - return pt[8:] + return pt[8:] -def _create_kw_cipher(factory: ModuleType, - **kwargs: Union[bytes, bytearray]) -> KWMode: - """Create a new block cipher in Key Wrap mode. +def _create_kw_cipher( + factory: ModuleType, + **kwargs: Union[bytes, bytearray], +) -> KWMode: + """Create a new block cipher in Key Wrap mode. - Args: - factory: - A block cipher module, taken from `Cryptodome.Cipher`. - The cipher must have block length of 16 bytes, such as AES. + Args: + factory: + A block cipher module, taken from `Cryptodome.Cipher`. + The cipher must have block length of 16 bytes, such as AES. - Keywords: - key: - The secret key to use to seal or unseal. - """ + Keywords: + key: + The secret key to use to seal or unseal. + """ - try: - key = kwargs["key"] - except KeyError as e: - raise TypeError("Missing parameter:" + str(e)) + try: + key = kwargs["key"] + except KeyError as e: + raise TypeError("Missing parameter:" + str(e)) - return KWMode(factory, key) + return KWMode(factory, key) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_kwp.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_kwp.py index 08684431..56679d4a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_kwp.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_kwp.py @@ -7,129 +7,133 @@ class KWPMode(object): - """Key Wrap with Padding (KWP) mode. + """Key Wrap with Padding (KWP) mode. - This is a deterministic Authenticated Encryption (AE) mode - for protecting cryptographic keys. See `NIST SP800-38F`_. + This is a deterministic Authenticated Encryption (AE) mode + for protecting cryptographic keys. See `NIST SP800-38F`_. - It provides both confidentiality and authenticity, and it designed - so that any bit of the ciphertext depends on all bits of the plaintext. + It provides both confidentiality and authenticity, and it designed + so that any bit of the ciphertext depends on all bits of the plaintext. - This mode is only available for ciphers that operate on 128 bits blocks - (e.g., AES). + This mode is only available for ciphers that operate on 128 bits blocks + (e.g., AES). - .. _`NIST SP800-38F`: http://csrc.nist.gov/publications/nistpubs/800-38F/SP-800-38F.pdf + .. _`NIST SP800-38F`: http://csrc.nist.gov/publications/nistpubs/800-38F/SP-800-38F.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, - factory: ModuleType, - key: Union[bytes, bytearray]): + def __init__( + self, + factory: ModuleType, + key: Union[bytes, bytearray], + ): + self.block_size = factory.block_size + if self.block_size != 16: + raise ValueError( + "Key Wrap with Padding mode is only available for ciphers that operate on 128 bits blocks", + ) - self.block_size = factory.block_size - if self.block_size != 16: - raise ValueError("Key Wrap with Padding mode is only available for ciphers" - " that operate on 128 bits blocks") + self._factory = factory + self._cipher = factory.new(key, factory.MODE_ECB) + self._done = False - self._factory = factory - self._cipher = factory.new(key, factory.MODE_ECB) - self._done = False + def seal(self, plaintext: Union[bytes, bytearray]) -> bytes: + """Encrypt and authenticate (wrap) a cryptographic key. - def seal(self, plaintext: Union[bytes, bytearray]) -> bytes: - """Encrypt and authenticate (wrap) a cryptographic key. + Args: + plaintext: + The cryptographic key to wrap. - Args: - plaintext: - The cryptographic key to wrap. + Returns: + The wrapped key. + """ - Returns: - The wrapped key. - """ + if self._done: + raise ValueError("The cipher cannot be used more than once") - if self._done: - raise ValueError("The cipher cannot be used more than once") + if len(plaintext) == 0: + raise ValueError("The plaintext must be at least 1 byte") - if len(plaintext) == 0: - raise ValueError("The plaintext must be at least 1 byte") + if len(plaintext) >= 2**32: + raise ValueError("The plaintext is too long") - if len(plaintext) >= 2 ** 32: - raise ValueError("The plaintext is too long") + padlen = (8 - len(plaintext)) % 8 + padded = plaintext + b"\x00" * padlen - padlen = (8 - len(plaintext)) % 8 - padded = plaintext + b'\x00' * padlen + AIV = b"\xa6\x59\x59\xa6" + struct.pack(">I", len(plaintext)) - AIV = b'\xA6\x59\x59\xA6' + struct.pack('>I', len(plaintext)) + if len(padded) == 8: + res = self._cipher.encrypt(AIV + padded) + else: + res = W(self._cipher, AIV + padded) - if len(padded) == 8: - res = self._cipher.encrypt(AIV + padded) - else: - res = W(self._cipher, AIV + padded) + return res - return res + def unseal(self, ciphertext: Union[bytes, bytearray]) -> bytes: + """Decrypt and authenticate (unwrap) a cryptographic key. - def unseal(self, ciphertext: Union[bytes, bytearray]) -> bytes: - """Decrypt and authenticate (unwrap) a cryptographic key. + Args: + ciphertext: + The cryptographic key to unwrap. + It must be at least 16 bytes long, and its length + must be a multiple of 8. - Args: - ciphertext: - The cryptographic key to unwrap. - It must be at least 16 bytes long, and its length - must be a multiple of 8. + Returns: + The original key. - Returns: - The original key. + Raises: ValueError + If the ciphertext or the key are not valid. + """ - Raises: ValueError - If the ciphertext or the key are not valid. - """ + if self._done: + raise ValueError("The cipher cannot be used more than once") - if self._done: - raise ValueError("The cipher cannot be used more than once") + if len(ciphertext) % 8: + raise ValueError("The ciphertext must have length multiple of 8 bytes") - if len(ciphertext) % 8: - raise ValueError("The ciphertext must have length multiple of 8 bytes") + if len(ciphertext) < 16: + raise ValueError("The ciphertext must be at least 24 bytes long") - if len(ciphertext) < 16: - raise ValueError("The ciphertext must be at least 24 bytes long") + if len(ciphertext) == 16: + S = self._cipher.decrypt(ciphertext) + else: + S = W_inverse(self._cipher, ciphertext) - if len(ciphertext) == 16: - S = self._cipher.decrypt(ciphertext) - else: - S = W_inverse(self._cipher, ciphertext) + if S[:4] != b"\xa6\x59\x59\xa6": + raise ValueError("Incorrect decryption") - if S[:4] != b'\xA6\x59\x59\xA6': - raise ValueError("Incorrect decryption") + Plen = struct.unpack(">I", S[4:8])[0] - Plen = struct.unpack('>I', S[4:8])[0] + padlen = len(S) - 8 - Plen + if padlen < 0 or padlen > 7: + raise ValueError("Incorrect decryption") - padlen = len(S) - 8 - Plen - if padlen < 0 or padlen > 7: - raise ValueError("Incorrect decryption") + if S[len(S) - padlen :] != b"\x00" * padlen: + raise ValueError("Incorrect decryption") - if S[len(S) - padlen:] != b'\x00' * padlen: - raise ValueError("Incorrect decryption") + return S[8 : len(S) - padlen] - return S[8:len(S) - padlen] +def _create_kwp_cipher( + factory: ModuleType, + **kwargs: Union[bytes, bytearray], +) -> KWPMode: + """Create a new block cipher in Key Wrap with Padding mode. -def _create_kwp_cipher(factory: ModuleType, - **kwargs: Union[bytes, bytearray]) -> KWPMode: - """Create a new block cipher in Key Wrap with Padding mode. + Args: + factory: + A block cipher module, taken from `Cryptodome.Cipher`. + The cipher must have block length of 16 bytes, such as AES. - Args: - factory: - A block cipher module, taken from `Cryptodome.Cipher`. - The cipher must have block length of 16 bytes, such as AES. + Keywords: + key: + The secret key to use to seal or unseal. + """ - Keywords: - key: - The secret key to use to seal or unseal. - """ + try: + key = kwargs["key"] + except KeyError as e: + raise TypeError("Missing parameter:" + str(e)) - try: - key = kwargs["key"] - except KeyError as e: - raise TypeError("Missing parameter:" + str(e)) - - return KWPMode(factory, key) + return KWPMode(factory, key) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ocb.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ocb.py index 1295e61a..e7c648fc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ocb.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ocb.py @@ -78,12 +78,20 @@ from Cryptodome.Hash import BLAKE2s from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_buffer) - -_raw_ocb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ocb", """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_buffer, +) + +_raw_ocb_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_ocb", + """ int OCB_start_operation(void *cipher, const uint8_t *offset_0, size_t offset_0_len, @@ -103,430 +111,471 @@ uint8_t *tag, size_t tag_len); int OCB_stop_operation(void *state); - """) + """, +) class OcbMode(object): - """Offset Codebook (OCB) mode. - - :undocumented: __init__ - """ - - def __init__(self, factory, nonce, mac_len, cipher_params): - - if factory.block_size != 16: - raise ValueError("OCB mode is only available for ciphers" - " that operate on 128 bits blocks") - - self.block_size = 16 - """The block size of the underlying cipher, in bytes.""" - - self.nonce = _copy_bytes(None, None, nonce) - """Nonce used for this session.""" - if len(nonce) not in range(1, 16): - raise ValueError("Nonce must be at most 15 bytes long") - if not is_buffer(nonce): - raise TypeError("Nonce must be bytes, bytearray or memoryview") - - self._mac_len = mac_len - if not 8 <= mac_len <= 16: - raise ValueError("MAC tag must be between 8 and 16 bytes long") - - # Cache for MAC tag - self._mac_tag = None - - # Cache for unaligned associated data - self._cache_A = b"" - - # Cache for unaligned ciphertext/plaintext - self._cache_P = b"" - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - # Compute Offset_0 - params_without_key = dict(cipher_params) - key = params_without_key.pop("key") - - taglen_mod128 = (self._mac_len * 8) % 128 - if len(self.nonce) < 15: - nonce = bchr(taglen_mod128 << 1) +\ - b'\x00' * (14 - len(nonce)) +\ - b'\x01' +\ - self.nonce - else: - nonce = bchr((taglen_mod128 << 1) | 0x01) +\ - self.nonce - - bottom_bits = bord(nonce[15]) & 0x3F # 6 bits, 0..63 - top_bits = bord(nonce[15]) & 0xC0 # 2 bits - - ktop_cipher = factory.new(key, - factory.MODE_ECB, - **params_without_key) - ktop = ktop_cipher.encrypt(struct.pack('15sB', - nonce[:15], - top_bits)) - - stretch = ktop + strxor(ktop[:8], ktop[1:9]) # 192 bits - offset_0 = long_to_bytes(bytes_to_long(stretch) >> - (64 - bottom_bits), 24)[8:] - - # Create low-level cipher instance - raw_cipher = factory._create_base_cipher(cipher_params) - if cipher_params: - raise TypeError("Unknown keywords: " + str(cipher_params)) - - self._state = VoidPointer() - result = _raw_ocb_lib.OCB_start_operation(raw_cipher.get(), - offset_0, - c_size_t(len(offset_0)), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the OCB mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - _raw_ocb_lib.OCB_stop_operation) - - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - raw_cipher.release() - - def _update(self, assoc_data, assoc_data_len): - result = _raw_ocb_lib.OCB_update(self._state.get(), - c_uint8_ptr(assoc_data), - c_size_t(assoc_data_len)) - if result: - raise ValueError("Error %d while computing MAC in OCB mode" % result) - - def update(self, assoc_data): - """Process the associated data. - - If there is any associated data, the caller has to invoke - this method one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver shall still able to detect modifications. - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. - """ - - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = ["encrypt", "decrypt", "digest", - "verify", "update"] - - if len(self._cache_A) > 0: - filler = min(16 - len(self._cache_A), len(assoc_data)) - self._cache_A += _copy_bytes(None, filler, assoc_data) - assoc_data = assoc_data[filler:] - - if len(self._cache_A) < 16: - return self - - # Clear the cache, and proceeding with any other aligned data - self._cache_A, seg = b"", self._cache_A - self.update(seg) - - update_len = len(assoc_data) // 16 * 16 - self._cache_A = _copy_bytes(update_len, None, assoc_data) - self._update(assoc_data, update_len) - return self - - def _transcrypt_aligned(self, in_data, in_data_len, - trans_func, trans_desc): - - out_data = create_string_buffer(in_data_len) - result = trans_func(self._state.get(), - in_data, - out_data, - c_size_t(in_data_len)) - if result: - raise ValueError("Error %d while %sing in OCB mode" - % (result, trans_desc)) - return get_raw_buffer(out_data) - - def _transcrypt(self, in_data, trans_func, trans_desc): - # Last piece to encrypt/decrypt - if in_data is None: - out_data = self._transcrypt_aligned(self._cache_P, - len(self._cache_P), - trans_func, - trans_desc) - self._cache_P = b"" - return out_data - - # Try to fill up the cache, if it already contains something - prefix = b"" - if len(self._cache_P) > 0: - filler = min(16 - len(self._cache_P), len(in_data)) - self._cache_P += _copy_bytes(None, filler, in_data) - in_data = in_data[filler:] - - if len(self._cache_P) < 16: - # We could not manage to fill the cache, so there is certainly - # no output yet. - return b"" - - # Clear the cache, and proceeding with any other aligned data - prefix = self._transcrypt_aligned(self._cache_P, - len(self._cache_P), - trans_func, - trans_desc) - self._cache_P = b"" - - # Process data in multiples of the block size - trans_len = len(in_data) // 16 * 16 - result = self._transcrypt_aligned(c_uint8_ptr(in_data), - trans_len, - trans_func, - trans_desc) - if prefix: - result = prefix + result - - # Left-over - self._cache_P = _copy_bytes(trans_len, None, in_data) - - return result - - def encrypt(self, plaintext=None): - """Encrypt the next piece of plaintext. - - After the entire plaintext has been passed (but before `digest`), - you **must** call this method one last time with no arguments to collect - the final piece of ciphertext. - - If possible, use the method `encrypt_and_digest` instead. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The next piece of data to encrypt or ``None`` to signify - that encryption has finished and that any remaining ciphertext - has to be produced. - :Return: - the ciphertext, as a byte string. - Its length may not match the length of the *plaintext*. - """ - - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - - if plaintext is None: - self._next = ["digest"] - else: - self._next = ["encrypt"] - return self._transcrypt(plaintext, _raw_ocb_lib.OCB_encrypt, "encrypt") - - def decrypt(self, ciphertext=None): - """Decrypt the next piece of ciphertext. - - After the entire ciphertext has been passed (but before `verify`), - you **must** call this method one last time with no arguments to collect - the remaining piece of plaintext. - - If possible, use the method `decrypt_and_verify` instead. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The next piece of data to decrypt or ``None`` to signify - that decryption has finished and that any remaining plaintext - has to be produced. - :Return: - the plaintext, as a byte string. - Its length may not match the length of the *ciphertext*. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called after" - " initialization or an update()") - - if ciphertext is None: - self._next = ["verify"] - else: - self._next = ["decrypt"] - return self._transcrypt(ciphertext, - _raw_ocb_lib.OCB_decrypt, - "decrypt") - - def _compute_mac_tag(self): - - if self._mac_tag is not None: - return - - if self._cache_A: - self._update(self._cache_A, len(self._cache_A)) - self._cache_A = b"" - - mac_tag = create_string_buffer(16) - result = _raw_ocb_lib.OCB_digest(self._state.get(), - mac_tag, - c_size_t(len(mac_tag)) - ) - if result: - raise ValueError("Error %d while computing digest in OCB mode" - % result) - self._mac_tag = get_raw_buffer(mac_tag)[:self._mac_len] - - def digest(self): - """Compute the *binary* MAC tag. - - Call this method after the final `encrypt` (the one with no arguments) - to obtain the MAC tag. - - The MAC tag is needed by the receiver to determine authenticity - of the message. - - :Return: the MAC, as a byte string. - """ - - if "digest" not in self._next: - raise TypeError("digest() cannot be called now for this cipher") + """Offset Codebook (OCB) mode. + + :undocumented: __init__ + """ + + def __init__(self, factory, nonce, mac_len, cipher_params): + if factory.block_size != 16: + raise ValueError( + "OCB mode is only available for ciphers that operate on 128 bits blocks", + ) + + self.block_size = 16 + """The block size of the underlying cipher, in bytes.""" + + self.nonce = _copy_bytes(None, None, nonce) + """Nonce used for this session.""" + if len(nonce) not in range(1, 16): + raise ValueError("Nonce must be at most 15 bytes long") + if not is_buffer(nonce): + raise TypeError("Nonce must be bytes, bytearray or memoryview") + + self._mac_len = mac_len + if not 8 <= mac_len <= 16: + raise ValueError("MAC tag must be between 8 and 16 bytes long") + + # Cache for MAC tag + self._mac_tag = None + + # Cache for unaligned associated data + self._cache_A = b"" + + # Cache for unaligned ciphertext/plaintext + self._cache_P = b"" + + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + # Compute Offset_0 + params_without_key = dict(cipher_params) + key = params_without_key.pop("key") + + taglen_mod128 = (self._mac_len * 8) % 128 + if len(self.nonce) < 15: + nonce = bchr(taglen_mod128 << 1) + b"\x00" * (14 - len(nonce)) + b"\x01" + self.nonce + else: + nonce = bchr((taglen_mod128 << 1) | 0x01) + self.nonce + + bottom_bits = bord(nonce[15]) & 0x3F # 6 bits, 0..63 + top_bits = bord(nonce[15]) & 0xC0 # 2 bits + + ktop_cipher = factory.new( + key, + factory.MODE_ECB, + **params_without_key, + ) + ktop = ktop_cipher.encrypt( + struct.pack( + "15sB", + nonce[:15], + top_bits, + ), + ) + + stretch = ktop + strxor(ktop[:8], ktop[1:9]) # 192 bits + offset_0 = long_to_bytes( + bytes_to_long(stretch) >> (64 - bottom_bits), + 24, + )[8:] + + # Create low-level cipher instance + raw_cipher = factory._create_base_cipher(cipher_params) + if cipher_params: + raise TypeError("Unknown keywords: " + str(cipher_params)) + + self._state = VoidPointer() + result = _raw_ocb_lib.OCB_start_operation( + raw_cipher.get(), + offset_0, + c_size_t(len(offset_0)), + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %d while instantiating the OCB mode" % result, + ) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + _raw_ocb_lib.OCB_stop_operation, + ) + + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + raw_cipher.release() + + def _update(self, assoc_data, assoc_data_len): + result = _raw_ocb_lib.OCB_update( + self._state.get(), + c_uint8_ptr(assoc_data), + c_size_t(assoc_data_len), + ) + if result: + raise ValueError("Error %d while computing MAC in OCB mode" % result) + + def update(self, assoc_data): + """Process the associated data. + + If there is any associated data, the caller has to invoke + this method one or more times, before using + ``decrypt`` or ``encrypt``. + + By *associated data* it is meant any data (e.g. packet headers) that + will not be encrypted and will be transmitted in the clear. + However, the receiver shall still able to detect modifications. + + If there is no associated data, this method must not be called. + + The caller may split associated data in segments of any size, and + invoke this method multiple times, each time with the next segment. + + :Parameters: + assoc_data : bytes/bytearray/memoryview + A piece of associated data. + """ + + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) + + self._next = [ + "encrypt", + "decrypt", + "digest", + "verify", + "update", + ] + + if len(self._cache_A) > 0: + filler = min(16 - len(self._cache_A), len(assoc_data)) + self._cache_A += _copy_bytes(None, filler, assoc_data) + assoc_data = assoc_data[filler:] + + if len(self._cache_A) < 16: + return self + + # Clear the cache, and proceeding with any other aligned data + self._cache_A, seg = b"", self._cache_A + self.update(seg) + + update_len = len(assoc_data) // 16 * 16 + self._cache_A = _copy_bytes(update_len, None, assoc_data) + self._update(assoc_data, update_len) + return self + + def _transcrypt_aligned( + self, + in_data, + in_data_len, + trans_func, + trans_desc, + ): + out_data = create_string_buffer(in_data_len) + result = trans_func( + self._state.get(), + in_data, + out_data, + c_size_t(in_data_len), + ) + if result: + raise ValueError( + "Error %d while %sing in OCB mode" % (result, trans_desc), + ) + return get_raw_buffer(out_data) + + def _transcrypt(self, in_data, trans_func, trans_desc): + # Last piece to encrypt/decrypt + if in_data is None: + out_data = self._transcrypt_aligned( + self._cache_P, + len(self._cache_P), + trans_func, + trans_desc, + ) + self._cache_P = b"" + return out_data + + # Try to fill up the cache, if it already contains something + prefix = b"" + if len(self._cache_P) > 0: + filler = min(16 - len(self._cache_P), len(in_data)) + self._cache_P += _copy_bytes(None, filler, in_data) + in_data = in_data[filler:] + + if len(self._cache_P) < 16: + # We could not manage to fill the cache, so there is certainly + # no output yet. + return b"" + + # Clear the cache, and proceeding with any other aligned data + prefix = self._transcrypt_aligned( + self._cache_P, + len(self._cache_P), + trans_func, + trans_desc, + ) + self._cache_P = b"" + + # Process data in multiples of the block size + trans_len = len(in_data) // 16 * 16 + result = self._transcrypt_aligned( + c_uint8_ptr(in_data), + trans_len, + trans_func, + trans_desc, + ) + if prefix: + result = prefix + result + + # Left-over + self._cache_P = _copy_bytes(trans_len, None, in_data) + + return result + + def encrypt(self, plaintext=None): + """Encrypt the next piece of plaintext. + + After the entire plaintext has been passed (but before `digest`), + you **must** call this method one last time with no arguments to collect + the final piece of ciphertext. + + If possible, use the method `encrypt_and_digest` instead. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The next piece of data to encrypt or ``None`` to signify + that encryption has finished and that any remaining ciphertext + has to be produced. + :Return: + the ciphertext, as a byte string. + Its length may not match the length of the *plaintext*. + """ + + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) + + if plaintext is None: + self._next = ["digest"] + else: + self._next = ["encrypt"] + return self._transcrypt(plaintext, _raw_ocb_lib.OCB_encrypt, "encrypt") + + def decrypt(self, ciphertext=None): + """Decrypt the next piece of ciphertext. + + After the entire ciphertext has been passed (but before `verify`), + you **must** call this method one last time with no arguments to collect + the remaining piece of plaintext. + + If possible, use the method `decrypt_and_verify` instead. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The next piece of data to decrypt or ``None`` to signify + that decryption has finished and that any remaining plaintext + has to be produced. + :Return: + the plaintext, as a byte string. + Its length may not match the length of the *ciphertext*. + """ + + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + + if ciphertext is None: + self._next = ["verify"] + else: + self._next = ["decrypt"] + return self._transcrypt( + ciphertext, + _raw_ocb_lib.OCB_decrypt, + "decrypt", + ) + + def _compute_mac_tag(self): + if self._mac_tag is not None: + return + + if self._cache_A: + self._update(self._cache_A, len(self._cache_A)) + self._cache_A = b"" + + mac_tag = create_string_buffer(16) + result = _raw_ocb_lib.OCB_digest( + self._state.get(), + mac_tag, + c_size_t(len(mac_tag)), + ) + if result: + raise ValueError( + "Error %d while computing digest in OCB mode" % result, + ) + self._mac_tag = get_raw_buffer(mac_tag)[: self._mac_len] + + def digest(self): + """Compute the *binary* MAC tag. + + Call this method after the final `encrypt` (the one with no arguments) + to obtain the MAC tag. + + The MAC tag is needed by the receiver to determine authenticity + of the message. - assert(len(self._cache_P) == 0) + :Return: the MAC, as a byte string. + """ + + if "digest" not in self._next: + raise TypeError("digest() cannot be called now for this cipher") - self._next = ["digest"] + assert len(self._cache_P) == 0 - if self._mac_tag is None: - self._compute_mac_tag() + self._next = ["digest"] - return self._mac_tag + if self._mac_tag is None: + self._compute_mac_tag() - def hexdigest(self): - """Compute the *printable* MAC tag. + return self._mac_tag - This method is like `digest`. + def hexdigest(self): + """Compute the *printable* MAC tag. + + This method is like `digest`. - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. - Call this method after the final `decrypt` (the one with no arguments) - to check if the message is authentic and valid. + Call this method after the final `decrypt` (the one with no arguments) + to check if the message is authentic and valid. - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - if "verify" not in self._next: - raise TypeError("verify() cannot be called now for this cipher") + if "verify" not in self._next: + raise TypeError("verify() cannot be called now for this cipher") - assert(len(self._cache_P) == 0) + assert len(self._cache_P) == 0 - self._next = ["verify"] + self._next = ["verify"] - if self._mac_tag is None: - self._compute_mac_tag() + if self._mac_tag is None: + self._compute_mac_tag() - secret = get_random_bytes(16) - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + secret = get_random_bytes(16) + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. - This method is like `verify`. + This method is like `verify`. - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - self.verify(unhexlify(hex_mac_tag)) + self.verify(unhexlify(hex_mac_tag)) - def encrypt_and_digest(self, plaintext): - """Encrypt the message and create the MAC tag in one step. + def encrypt_and_digest(self, plaintext): + """Encrypt the message and create the MAC tag in one step. - :Parameters: - plaintext : bytes/bytearray/memoryview - The entire message to encrypt. - :Return: - a tuple with two byte strings: + :Parameters: + plaintext : bytes/bytearray/memoryview + The entire message to encrypt. + :Return: + a tuple with two byte strings: - - the encrypted data - - the MAC - """ + - the encrypted data + - the MAC + """ - return self.encrypt(plaintext) + self.encrypt(), self.digest() + return self.encrypt(plaintext) + self.encrypt(), self.digest() - def decrypt_and_verify(self, ciphertext, received_mac_tag): - """Decrypted the message and verify its authenticity in one step. + def decrypt_and_verify(self, ciphertext, received_mac_tag): + """Decrypted the message and verify its authenticity in one step. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The entire message to decrypt. - received_mac_tag : byte string - This is the *binary* MAC, as received from the sender. + :Parameters: + ciphertext : bytes/bytearray/memoryview + The entire message to decrypt. + received_mac_tag : byte string + This is the *binary* MAC, as received from the sender. - :Return: the decrypted data (byte string). - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Return: the decrypted data (byte string). + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - plaintext = self.decrypt(ciphertext) + self.decrypt() - self.verify(received_mac_tag) - return plaintext + plaintext = self.decrypt(ciphertext) + self.decrypt() + self.verify(received_mac_tag) + return plaintext def _create_ocb_cipher(factory, **kwargs): - """Create a new block cipher, configured in OCB mode. - - :Parameters: - factory : module - A symmetric cipher module from `Cryptodome.Cipher` - (like `Cryptodome.Cipher.AES`). - - :Keywords: - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - Its length can vary from 1 to 15 bytes. - If not specified, a random 15 bytes long nonce is generated. - - mac_len : integer - Length of the MAC, in bytes. - It must be in the range ``[8..16]``. - The default is 16 (128 bits). - - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ - - try: - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(15) - mac_len = kwargs.pop("mac_len", 16) - except KeyError as e: - raise TypeError("Keyword missing: " + str(e)) - - return OcbMode(factory, nonce, mac_len, kwargs) + """Create a new block cipher, configured in OCB mode. + + :Parameters: + factory : module + A symmetric cipher module from `Cryptodome.Cipher` + (like `Cryptodome.Cipher.AES`). + + :Keywords: + nonce : bytes/bytearray/memoryview + A value that must never be reused for any other encryption. + Its length can vary from 1 to 15 bytes. + If not specified, a random 15 bytes long nonce is generated. + + mac_len : integer + Length of the MAC, in bytes. + It must be in the range ``[8..16]``. + The default is 16 (128 bits). + + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ + + try: + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(15) + mac_len = kwargs.pop("mac_len", 16) + except KeyError as e: + raise TypeError("Keyword missing: " + str(e)) + + return OcbMode(factory, nonce, mac_len, kwargs) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ocb.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ocb.pyi index a1909fc3..eae2f343 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ocb.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ocb.pyi @@ -1,36 +1,25 @@ from types import ModuleType -from typing import Union, Any, Optional, Tuple, Dict, overload +from typing import Union, Tuple, Dict, overload Buffer = Union[bytes, bytearray, memoryview] class OcbMode(object): - block_size: int - nonce: Buffer + block_size: int + nonce: Buffer - def __init__(self, - factory: ModuleType, - nonce: Buffer, - mac_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> OcbMode: ... - - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer) -> bytes: ... + def __init__(self, factory: ModuleType, nonce: Buffer, mac_len: int, cipher_params: Dict) -> None: ... + def update(self, assoc_data: Buffer) -> OcbMode: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + def decrypt_and_verify(self, ciphertext: Buffer, received_mac_tag: Buffer) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ofb.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ofb.py index 8c0ccf63..97c0ed8e 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ofb.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ofb.py @@ -24,17 +24,25 @@ Output Feedback (CFB) mode. """ -__all__ = ['OfbMode'] +__all__ = ["OfbMode"] from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes -raw_ofb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ofb", """ +raw_ofb_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_ofb", + """ int OFB_start_operation(void *cipher, const uint8_t iv[], size_t iv_len, @@ -48,235 +56,247 @@ uint8_t *out, size_t data_len); int OFB_stop_operation(void *state); - """ - ) + """, +) class OfbMode(object): - """*Output FeedBack (OFB)*. + """*Output FeedBack (OFB)*. - This mode is very similar to CBC, but it - transforms the underlying block cipher into a stream cipher. + This mode is very similar to CBC, but it + transforms the underlying block cipher into a stream cipher. - The keystream is the iterated block encryption of the - previous ciphertext block. + The keystream is the iterated block encryption of the + previous ciphertext block. - An Initialization Vector (*IV*) is required. + An Initialization Vector (*IV*) is required. - See `NIST SP800-38A`_ , Section 6.4. + See `NIST SP800-38A`_ , Section 6.4. - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, block_cipher, iv): - """Create a new block cipher, configured in OFB mode. + def __init__(self, block_cipher, iv): + """Create a new block cipher, configured in OFB mode. - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. - iv : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - It is as long as the cipher block. + iv : bytes/bytearray/memoryview + The initialization vector to use for encryption or decryption. + It is as long as the cipher block. - **The IV must be a nonce, to to be reused for any other - message**. It shall be a nonce or a random value. + **The IV must be a nonce, to to be reused for any other + message**. It shall be a nonce or a random value. - Reusing the *IV* for encryptions performed with the same key - compromises confidentiality. - """ + Reusing the *IV* for encryptions performed with the same key + compromises confidentiality. + """ - self._state = VoidPointer() - result = raw_ofb_lib.OFB_start_operation(block_cipher.get(), - c_uint8_ptr(iv), - c_size_t(len(iv)), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the OFB mode" - % result) + self._state = VoidPointer() + result = raw_ofb_lib.OFB_start_operation( + block_cipher.get(), + c_uint8_ptr(iv), + c_size_t(len(iv)), + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %d while instantiating the OFB mode" % result, + ) - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_ofb_lib.OFB_stop_operation) + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + raw_ofb_lib.OFB_stop_operation, + ) - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + block_cipher.release() - self.block_size = len(iv) - """The block size of the underlying cipher, in bytes.""" + self.block_size = len(iv) + """The block size of the underlying cipher, in bytes.""" - self.iv = _copy_bytes(None, None, iv) - """The Initialization Vector originally used to create the object. + self.iv = _copy_bytes(None, None, iv) + """The Initialization Vector originally used to create the object. The value does not change.""" - self.IV = self.iv - """Alias for `iv`""" + self.IV = self.iv + """Alias for `iv`""" - self._next = ["encrypt", "decrypt"] + self._next = ["encrypt", "decrypt"] - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.encrypt(a) + c.encrypt(b) + >>> c.encrypt(a) + c.encrypt(b) - is equivalent to: + is equivalent to: - >>> c.encrypt(a+b) + >>> c.encrypt(a+b) - This function does not add any padding to the plaintext. + This function does not add any padding to the plaintext. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = ["encrypt"] + if "encrypt" not in self._next: + raise TypeError("encrypt() cannot be called after decrypt()") + self._next = ["encrypt"] - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) - result = raw_ofb_lib.OFB_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting in OFB mode" % result) + result = raw_ofb_lib.OFB_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting in OFB mode" % result) - if output is None: - return get_raw_buffer(ciphertext) - else: - return None + if output is None: + return get_raw_buffer(ciphertext) + else: + return None - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.decrypt(a) + c.decrypt(b) + >>> c.decrypt(a) + c.decrypt(b) - is equivalent to: + is equivalent to: - >>> c.decrypt(a+b) + >>> c.decrypt(a+b) - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext is written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext is written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "decrypt" not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = ["decrypt"] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ofb_lib.OFB_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - raise ValueError("Error %d while decrypting in OFB mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + if "decrypt" not in self._next: + raise TypeError("decrypt() cannot be called after encrypt()") + self._next = ["decrypt"] + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ofb_lib.OFB_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + raise ValueError("Error %d while decrypting in OFB mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_ofb_cipher(factory, **kwargs): - """Instantiate a cipher object that performs OFB encryption/decryption. + """Instantiate a cipher object that performs OFB encryption/decryption. - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. - :Keywords: - iv : bytes/bytearray/memoryview - The IV to use for OFB. + :Keywords: + iv : bytes/bytearray/memoryview + The IV to use for OFB. - IV : bytes/bytearray/memoryview - Alias for ``iv``. + IV : bytes/bytearray/memoryview + Alias for ``iv``. - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ - cipher_state = factory._create_base_cipher(kwargs) - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) + cipher_state = factory._create_base_cipher(kwargs) + iv = kwargs.pop("IV", None) + IV = kwargs.pop("iv", None) - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV + if (None, None) == (iv, IV): + iv = get_random_bytes(factory.block_size) + if iv is not None: + if IV is not None: + raise TypeError("You must either use 'iv' or 'IV', not both") + else: + iv = IV - if len(iv) != factory.block_size: - raise ValueError("Incorrect IV length (it must be %d bytes long)" % - factory.block_size) + if len(iv) != factory.block_size: + raise ValueError( + "Incorrect IV length (it must be %d bytes long)" % factory.block_size, + ) - if kwargs: - raise TypeError("Unknown parameters for OFB: %s" % str(kwargs)) + if kwargs: + raise TypeError("Unknown parameters for OFB: %s" % str(kwargs)) - return OfbMode(cipher_state, iv) + return OfbMode(cipher_state, iv) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ofb.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ofb.pyi index d28608ec..2988e240 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ofb.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_ofb.pyi @@ -4,22 +4,19 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['OfbMode'] +__all__ = ["OfbMode"] class OfbMode(object): - block_size: int - iv: Buffer - IV: Buffer - - def __init__(self, - block_cipher: SmartPointer, - iv: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + block_size: int + iv: Buffer + IV: Buffer + def __init__(self, block_cipher: SmartPointer, iv: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_openpgp.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_openpgp.py index d86ed19a..f55a3821 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_openpgp.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_openpgp.py @@ -32,175 +32,178 @@ OpenPGP mode. """ -__all__ = ['OpenPgpMode'] +__all__ = ["OpenPgpMode"] from Cryptodome.Util.py3compat import _copy_bytes from Cryptodome.Random import get_random_bytes -class OpenPgpMode(object): - """OpenPGP mode. - This mode is a variant of CFB, and it is only used in PGP and - OpenPGP_ applications. If in doubt, use another mode. +class OpenPgpMode(object): + """OpenPGP mode. - An Initialization Vector (*IV*) is required. + This mode is a variant of CFB, and it is only used in PGP and + OpenPGP_ applications. If in doubt, use another mode. - Unlike CFB, the *encrypted* IV (not the IV itself) is - transmitted to the receiver. + An Initialization Vector (*IV*) is required. - The IV is a random data block. For legacy reasons, two of its bytes are - duplicated to act as a checksum for the correctness of the key, which is now - known to be insecure and is ignored. The encrypted IV is therefore 2 bytes - longer than the clean IV. + Unlike CFB, the *encrypted* IV (not the IV itself) is + transmitted to the receiver. - .. _OpenPGP: http://tools.ietf.org/html/rfc4880 + The IV is a random data block. For legacy reasons, two of its bytes are + duplicated to act as a checksum for the correctness of the key, which is now + known to be insecure and is ignored. The encrypted IV is therefore 2 bytes + longer than the clean IV. - :undocumented: __init__ - """ + .. _OpenPGP: http://tools.ietf.org/html/rfc4880 - def __init__(self, factory, key, iv, cipher_params): + :undocumented: __init__ + """ - #: The block size of the underlying cipher, in bytes. - self.block_size = factory.block_size + def __init__(self, factory, key, iv, cipher_params): + #: The block size of the underlying cipher, in bytes. + self.block_size = factory.block_size - self._done_first_block = False # True after the first encryption + self._done_first_block = False # True after the first encryption - # Instantiate a temporary cipher to process the IV - IV_cipher = factory.new( - key, - factory.MODE_CFB, - IV=b'\x00' * self.block_size, - segment_size=self.block_size * 8, - **cipher_params) + # Instantiate a temporary cipher to process the IV + IV_cipher = factory.new( + key, + factory.MODE_CFB, + IV=b"\x00" * self.block_size, + segment_size=self.block_size * 8, + **cipher_params, + ) - iv = _copy_bytes(None, None, iv) + iv = _copy_bytes(None, None, iv) - # The cipher will be used for... - if len(iv) == self.block_size: - # ... encryption - self._encrypted_IV = IV_cipher.encrypt(iv + iv[-2:]) - elif len(iv) == self.block_size + 2: - # ... decryption - self._encrypted_IV = iv - # Last two bytes are for a deprecated "quick check" feature that - # should not be used. (https://eprint.iacr.org/2005/033) - iv = IV_cipher.decrypt(iv)[:-2] - else: - raise ValueError("Length of IV must be %d or %d bytes" - " for MODE_OPENPGP" - % (self.block_size, self.block_size + 2)) + # The cipher will be used for... + if len(iv) == self.block_size: + # ... encryption + self._encrypted_IV = IV_cipher.encrypt(iv + iv[-2:]) + elif len(iv) == self.block_size + 2: + # ... decryption + self._encrypted_IV = iv + # Last two bytes are for a deprecated "quick check" feature that + # should not be used. (https://eprint.iacr.org/2005/033) + iv = IV_cipher.decrypt(iv)[:-2] + else: + raise ValueError( + "Length of IV must be %d or %d bytes" + " for MODE_OPENPGP" % (self.block_size, self.block_size + 2), + ) - self.iv = self.IV = iv + self.iv = self.IV = iv - # Instantiate the cipher for the real PGP data - self._cipher = factory.new( - key, - factory.MODE_CFB, - IV=self._encrypted_IV[-self.block_size:], - segment_size=self.block_size * 8, - **cipher_params) + # Instantiate the cipher for the real PGP data + self._cipher = factory.new( + key, + factory.MODE_CFB, + IV=self._encrypted_IV[-self.block_size :], + segment_size=self.block_size * 8, + **cipher_params, + ) - def encrypt(self, plaintext): - """Encrypt data with the key and the parameters set at initialization. + def encrypt(self, plaintext): + """Encrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.encrypt(a) + c.encrypt(b) + >>> c.encrypt(a) + c.encrypt(b) - is equivalent to: + is equivalent to: - >>> c.encrypt(a+b) + >>> c.encrypt(a+b) - This function does not add any padding to the plaintext. + This function does not add any padding to the plaintext. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. - :Return: - the encrypted data, as a byte string. - It is as long as *plaintext* with one exception: - when encrypting the first message chunk, - the encypted IV is prepended to the returned ciphertext. - """ + :Return: + the encrypted data, as a byte string. + It is as long as *plaintext* with one exception: + when encrypting the first message chunk, + the encypted IV is prepended to the returned ciphertext. + """ - res = self._cipher.encrypt(plaintext) - if not self._done_first_block: - res = self._encrypted_IV + res - self._done_first_block = True - return res + res = self._cipher.encrypt(plaintext) + if not self._done_first_block: + res = self._encrypted_IV + res + self._done_first_block = True + return res - def decrypt(self, ciphertext): - """Decrypt data with the key and the parameters set at initialization. + def decrypt(self, ciphertext): + """Decrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.decrypt(a) + c.decrypt(b) + >>> c.decrypt(a) + c.decrypt(b) - is equivalent to: + is equivalent to: - >>> c.decrypt(a+b) + >>> c.decrypt(a+b) - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. - :Return: the decrypted data (byte string). - """ + :Return: the decrypted data (byte string). + """ - return self._cipher.decrypt(ciphertext) + return self._cipher.decrypt(ciphertext) def _create_openpgp_cipher(factory, **kwargs): - """Create a new block cipher, configured in OpenPGP mode. + """Create a new block cipher, configured in OpenPGP mode. - :Parameters: - factory : module - The module. + :Parameters: + factory : module + The module. - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. + :Keywords: + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. - IV : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. + IV : bytes/bytearray/memoryview + The initialization vector to use for encryption or decryption. - For encryption, the IV must be as long as the cipher block size. + For encryption, the IV must be as long as the cipher block size. - For decryption, it must be 2 bytes longer (it is actually the - *encrypted* IV which was prefixed to the ciphertext). - """ + For decryption, it must be 2 bytes longer (it is actually the + *encrypted* IV which was prefixed to the ciphertext). + """ - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) + iv = kwargs.pop("IV", None) + IV = kwargs.pop("iv", None) - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV + if (None, None) == (iv, IV): + iv = get_random_bytes(factory.block_size) + if iv is not None: + if IV is not None: + raise TypeError("You must either use 'iv' or 'IV', not both") + else: + iv = IV - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing component: " + str(e)) + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing component: " + str(e)) - return OpenPgpMode(factory, key, iv, kwargs) + return OpenPgpMode(factory, key, iv, kwargs) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_openpgp.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_openpgp.pyi index 14b81058..79b85e05 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_openpgp.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_openpgp.pyi @@ -3,18 +3,13 @@ from typing import Union, Dict Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['OpenPgpMode'] +__all__ = ["OpenPgpMode"] class OpenPgpMode(object): - block_size: int - iv: Union[bytes, bytearray, memoryview] - IV: Union[bytes, bytearray, memoryview] - - def __init__(self, - factory: ModuleType, - key: Buffer, - iv: Buffer, - cipher_params: Dict) -> None: ... - def encrypt(self, plaintext: Buffer) -> bytes: ... - def decrypt(self, plaintext: Buffer) -> bytes: ... + block_size: int + iv: Union[bytes, bytearray, memoryview] + IV: Union[bytes, bytearray, memoryview] + def __init__(self, factory: ModuleType, key: Buffer, iv: Buffer, cipher_params: Dict) -> None: ... + def encrypt(self, plaintext: Buffer) -> bytes: ... + def decrypt(self, plaintext: Buffer) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_siv.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_siv.py index 4a76ad6d..b5a3aba5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_siv.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_siv.py @@ -32,361 +32,380 @@ Synthetic Initialization Vector (SIV) mode. """ -__all__ = ['SivMode'] +__all__ = ["SivMode"] -from binascii import hexlify, unhexlify +from binascii import unhexlify from Cryptodome.Util.py3compat import bord, _copy_bytes from Cryptodome.Util._raw_api import is_buffer -from Cryptodome.Util.number import long_to_bytes, bytes_to_long +from Cryptodome.Util.number import bytes_to_long from Cryptodome.Protocol.KDF import _S2V from Cryptodome.Hash import BLAKE2s from Cryptodome.Random import get_random_bytes class SivMode(object): - """Synthetic Initialization Vector (SIV). + """Synthetic Initialization Vector (SIV). - This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. - It provides both confidentiality and authenticity. + This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. + It provides both confidentiality and authenticity. - The header of the message may be left in the clear, if needed, and it will - still be subject to authentication. The decryption step tells the receiver - if the message comes from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - including the - header - has been modified or corrupted. + The header of the message may be left in the clear, if needed, and it will + still be subject to authentication. The decryption step tells the receiver + if the message comes from a source that really knowns the secret key. + Additionally, decryption detects if any part of the message - including the + header - has been modified or corrupted. - Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a - nonce is not catastrophic for the confidentiality of the message. The only - effect is that an attacker can tell when the same plaintext (and same - associated data) is protected with the same key. + Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a + nonce is not catastrophic for the confidentiality of the message. The only + effect is that an attacker can tell when the same plaintext (and same + associated data) is protected with the same key. - The length of the MAC is fixed to the block size of the underlying cipher. - The key size is twice the length of the key of the underlying cipher. + The length of the MAC is fixed to the block size of the underlying cipher. + The key size is twice the length of the key of the underlying cipher. - This mode is only available for AES ciphers. + This mode is only available for AES ciphers. - +--------------------+---------------+-------------------+ - | Cipher | SIV MAC size | SIV key length | - | | (bytes) | (bytes) | - +====================+===============+===================+ - | AES-128 | 16 | 32 | - +--------------------+---------------+-------------------+ - | AES-192 | 16 | 48 | - +--------------------+---------------+-------------------+ - | AES-256 | 16 | 64 | - +--------------------+---------------+-------------------+ + +--------------------+---------------+-------------------+ + | Cipher | SIV MAC size | SIV key length | + | | (bytes) | (bytes) | + +====================+===============+===================+ + | AES-128 | 16 | 32 | + +--------------------+---------------+-------------------+ + | AES-192 | 16 | 48 | + +--------------------+---------------+-------------------+ + | AES-256 | 16 | 64 | + +--------------------+---------------+-------------------+ - See `RFC5297`_ and the `original paper`__. + See `RFC5297`_ and the `original paper`__. - .. _RFC5297: https://tools.ietf.org/html/rfc5297 - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf + .. _RFC5297: https://tools.ietf.org/html/rfc5297 + .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html + .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, factory, key, nonce, kwargs): + def __init__(self, factory, key, nonce, kwargs): + self.block_size = factory.block_size + """The block size of the underlying cipher, in bytes.""" - self.block_size = factory.block_size - """The block size of the underlying cipher, in bytes.""" + self._factory = factory - self._factory = factory + self._cipher_params = kwargs - self._cipher_params = kwargs + if len(key) not in (32, 48, 64): + raise ValueError("Incorrect key length (%d bytes)" % len(key)) - if len(key) not in (32, 48, 64): - raise ValueError("Incorrect key length (%d bytes)" % len(key)) + if nonce is not None: + if not is_buffer(nonce): + raise TypeError("When provided, the nonce must be bytes, bytearray or memoryview") - if nonce is not None: - if not is_buffer(nonce): - raise TypeError("When provided, the nonce must be bytes, bytearray or memoryview") + if len(nonce) == 0: + raise ValueError("When provided, the nonce must be non-empty") - if len(nonce) == 0: - raise ValueError("When provided, the nonce must be non-empty") - - self.nonce = _copy_bytes(None, None, nonce) - """Public attribute is only available in case of non-deterministic + self.nonce = _copy_bytes(None, None, nonce) + """Public attribute is only available in case of non-deterministic encryption.""" - subkey_size = len(key) // 2 - - self._mac_tag = None # Cache for MAC tag - self._kdf = _S2V(key[:subkey_size], - ciphermod=factory, - cipher_params=self._cipher_params) - self._subkey_cipher = key[subkey_size:] - - # Purely for the purpose of verifying that cipher_params are OK - factory.new(key[:subkey_size], factory.MODE_ECB, **kwargs) - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - def _create_ctr_cipher(self, v): - """Create a new CTR cipher from V in SIV mode""" - - v_int = bytes_to_long(v) - q = v_int & 0xFFFFFFFFFFFFFFFF7FFFFFFF7FFFFFFF - return self._factory.new( - self._subkey_cipher, - self._factory.MODE_CTR, - initial_value=q, - nonce=b"", - **self._cipher_params) - - def update(self, component): - """Protect one associated data component + subkey_size = len(key) // 2 - For SIV, the associated data is a sequence (*vector*) of non-empty - byte strings (*components*). + self._mac_tag = None # Cache for MAC tag + self._kdf = _S2V( + key[:subkey_size], + ciphermod=factory, + cipher_params=self._cipher_params, + ) + self._subkey_cipher = key[subkey_size:] - This method consumes the next component. It must be called - once for each of the components that constitue the associated data. + # Purely for the purpose of verifying that cipher_params are OK + factory.new(key[:subkey_size], factory.MODE_ECB, **kwargs) - Note that the components have clear boundaries, so that: + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] - >>> cipher.update(b"builtin") - >>> cipher.update(b"securely") + def _create_ctr_cipher(self, v): + """Create a new CTR cipher from V in SIV mode""" - is not equivalent to: + v_int = bytes_to_long(v) + q = v_int & 0xFFFFFFFFFFFFFFFF7FFFFFFF7FFFFFFF + return self._factory.new( + self._subkey_cipher, + self._factory.MODE_CTR, + initial_value=q, + nonce=b"", + **self._cipher_params, + ) - >>> cipher.update(b"built") - >>> cipher.update(b"insecurely") + def update(self, component): + """Protect one associated data component - If there is no associated data, this method must not be called. + For SIV, the associated data is a sequence (*vector*) of non-empty + byte strings (*components*). - :Parameters: - component : bytes/bytearray/memoryview - The next associated data component. - """ + This method consumes the next component. It must be called + once for each of the components that constitue the associated data. - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") + Note that the components have clear boundaries, so that: - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] + >>> cipher.update(b"builtin") + >>> cipher.update(b"securely") - return self._kdf.update(component) + is not equivalent to: + + >>> cipher.update(b"built") + >>> cipher.update(b"insecurely") - def encrypt(self, plaintext): - """ - For SIV, encryption and MAC authentication must take place at the same - point. This method shall not be used. + If there is no associated data, this method must not be called. - Use `encrypt_and_digest` instead. - """ + :Parameters: + component : bytes/bytearray/memoryview + The next associated data component. + """ - raise TypeError("encrypt() not allowed for SIV mode." - " Use encrypt_and_digest() instead.") + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) - def decrypt(self, ciphertext): - """ - For SIV, decryption and verification must take place at the same - point. This method shall not be used. + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] - Use `decrypt_and_verify` instead. - """ + return self._kdf.update(component) - raise TypeError("decrypt() not allowed for SIV mode." - " Use decrypt_and_verify() instead.") + def encrypt(self, plaintext): + """ + For SIV, encryption and MAC authentication must take place at the same + point. This method shall not be used. - def digest(self): - """Compute the *binary* MAC tag. + Use `encrypt_and_digest` instead. + """ - The caller invokes this function at the very end. + raise TypeError( + "encrypt() not allowed for SIV mode. Use encrypt_and_digest() instead.", + ) - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. + def decrypt(self, ciphertext): + """ + For SIV, decryption and verification must take place at the same + point. This method shall not be used. - :Return: the MAC, as a byte string. - """ + Use `decrypt_and_verify` instead. + """ - if "digest" not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = ["digest"] - if self._mac_tag is None: - self._mac_tag = self._kdf.derive() - return self._mac_tag + raise TypeError( + "decrypt() not allowed for SIV mode. Use decrypt_and_verify() instead.", + ) - def hexdigest(self): - """Compute the *printable* MAC tag. + def digest(self): + """Compute the *binary* MAC tag. + + The caller invokes this function at the very end. - This method is like `digest`. + This method returns the MAC that shall be sent to the receiver, + together with the ciphertext. - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) + :Return: the MAC, as a byte string. + """ - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. + if "digest" not in self._next: + raise TypeError( + "digest() cannot be called when decrypting or validating a message", + ) + self._next = ["digest"] + if self._mac_tag is None: + self._mac_tag = self._kdf.derive() + return self._mac_tag - The caller invokes this function at the very end. + def hexdigest(self): + """Compute the *printable* MAC tag. - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. + This method is like `digest`. - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ["verify"] + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. - if self._mac_tag is None: - self._mac_tag = self._kdf.derive() + The caller invokes this function at the very end. - secret = get_random_bytes(16) + This method checks if the decrypted message is indeed valid + (that is, if the key is correct) and it has not been + tampered with while in transit. - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ["verify"] + + if self._mac_tag is None: + self._mac_tag = self._kdf.derive() + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. - This method is like `verify`. + This method is like `verify`. - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - self.verify(unhexlify(hex_mac_tag)) + self.verify(unhexlify(hex_mac_tag)) - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. + def encrypt_and_digest(self, plaintext, output=None): + """Perform encrypt() and digest() in one step. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + a tuple with two items: - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` + - the ciphertext, as ``bytes`` + - the MAC tag, as ``bytes`` - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ + The first item becomes ``None`` when the ``output`` parameter + specified a location for the result. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) - self._next = ["digest"] + self._next = ["digest"] - # Compute V (MAC) - if hasattr(self, 'nonce'): - self._kdf.update(self.nonce) - self._kdf.update(plaintext) - self._mac_tag = self._kdf.derive() + # Compute V (MAC) + if hasattr(self, "nonce"): + self._kdf.update(self.nonce) + self._kdf.update(plaintext) + self._mac_tag = self._kdf.derive() - cipher = self._create_ctr_cipher(self._mac_tag) + cipher = self._create_ctr_cipher(self._mac_tag) - return cipher.encrypt(plaintext, output=output), self._mac_tag + return cipher.encrypt(plaintext, output=output), self._mac_tag - def decrypt_and_verify(self, ciphertext, mac_tag, output=None): - """Perform decryption and verification in one step. + def decrypt_and_verify(self, ciphertext, mac_tag, output=None): + """Perform decryption and verification in one step. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - You cannot reuse an object for encrypting - or decrypting other data with the same key. + You cannot reuse an object for encrypting + or decrypting other data with the same key. - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` + parameter specified a location for the result. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = ["verify"] + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + self._next = ["verify"] - # Take the MAC and start the cipher for decryption - self._cipher = self._create_ctr_cipher(mac_tag) + # Take the MAC and start the cipher for decryption + self._cipher = self._create_ctr_cipher(mac_tag) - plaintext = self._cipher.decrypt(ciphertext, output=output) + plaintext = self._cipher.decrypt(ciphertext, output=output) - if hasattr(self, 'nonce'): - self._kdf.update(self.nonce) - self._kdf.update(plaintext if output is None else output) - self.verify(mac_tag) + if hasattr(self, "nonce"): + self._kdf.update(self.nonce) + self._kdf.update(plaintext if output is None else output) + self.verify(mac_tag) - return plaintext + return plaintext def _create_siv_cipher(factory, **kwargs): - """Create a new block cipher, configured in - Synthetic Initializaton Vector (SIV) mode. + """Create a new block cipher, configured in + Synthetic Initializaton Vector (SIV) mode. - :Parameters: + :Parameters: - factory : object - A symmetric cipher module from `Cryptodome.Cipher` - (like `Cryptodome.Cipher.AES`). + factory : object + A symmetric cipher module from `Cryptodome.Cipher` + (like `Cryptodome.Cipher.AES`). - :Keywords: + :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - It must be 32, 48 or 64 bytes long. - If AES is the chosen cipher, the variants *AES-128*, - *AES-192* and or *AES-256* will be used internally. + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. + It must be 32, 48 or 64 bytes long. + If AES is the chosen cipher, the variants *AES-128*, + *AES-192* and or *AES-256* will be used internally. - nonce : bytes/bytearray/memoryview - For deterministic encryption, it is not present. + nonce : bytes/bytearray/memoryview + For deterministic encryption, it is not present. - Otherwise, it is a value that must never be reused - for encrypting message under this key. + Otherwise, it is a value that must never be reused + for encrypting message under this key. - There are no restrictions on its length, - but it is recommended to use at least 16 bytes. - """ + There are no restrictions on its length, + but it is recommended to use at least 16 bytes. + """ - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter: " + str(e)) + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter: " + str(e)) - nonce = kwargs.pop("nonce", None) + nonce = kwargs.pop("nonce", None) - return SivMode(factory, key, nonce, kwargs) + return SivMode(factory, key, nonce, kwargs) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_siv.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_siv.pyi index 2934f23d..afaf9cc4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_siv.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_mode_siv.pyi @@ -3,36 +3,27 @@ from typing import Union, Tuple, Dict, Optional, overload Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['SivMode'] +__all__ = ["SivMode"] class SivMode(object): - block_size: int - nonce: bytes - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - kwargs: Dict) -> None: ... - - def update(self, component: Buffer) -> SivMode: ... + block_size: int + nonce: bytes - def encrypt(self, plaintext: Buffer) -> bytes: ... - def decrypt(self, plaintext: Buffer) -> bytes: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... + def __init__(self, factory: ModuleType, key: Buffer, nonce: Buffer, kwargs: Dict) -> None: ... + def update(self, component: Buffer) -> SivMode: ... + def encrypt(self, plaintext: Buffer) -> bytes: ... + def decrypt(self, plaintext: Buffer) -> bytes: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer, output: Buffer) -> Tuple[None, bytes]: ... + def decrypt_and_verify( + self, + ciphertext: Buffer, + received_mac_tag: Buffer, + output: Optional[Union[bytearray, memoryview]] = ..., + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_pkcs1_oaep_decode.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_pkcs1_oaep_decode.py index 82bdaa74..25747893 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_pkcs1_oaep_decode.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Cipher/_pkcs1_oaep_decode.py @@ -1,9 +1,13 @@ -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + c_size_t, + c_uint8_ptr, +) -_raw_pkcs1_decode = load_pycryptodome_raw_lib("Cryptodome.Cipher._pkcs1_decode", - """ +_raw_pkcs1_decode = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._pkcs1_decode", + """ int pkcs1_decode(const uint8_t *em, size_t len_em, const uint8_t *sentinel, size_t len_sentinel, size_t expected_pt_len, @@ -15,27 +19,32 @@ size_t hLen, const uint8_t *db, size_t db_len); - """) + """, +) def pkcs1_decode(em, sentinel, expected_pt_len, output): - if len(em) != len(output): - raise ValueError("Incorrect output length") + if len(em) != len(output): + raise ValueError("Incorrect output length") - ret = _raw_pkcs1_decode.pkcs1_decode(c_uint8_ptr(em), - c_size_t(len(em)), - c_uint8_ptr(sentinel), - c_size_t(len(sentinel)), - c_size_t(expected_pt_len), - c_uint8_ptr(output)) - return ret + ret = _raw_pkcs1_decode.pkcs1_decode( + c_uint8_ptr(em), + c_size_t(len(em)), + c_uint8_ptr(sentinel), + c_size_t(len(sentinel)), + c_size_t(expected_pt_len), + c_uint8_ptr(output), + ) + return ret def oaep_decode(em, lHash, db): - ret = _raw_pkcs1_decode.oaep_decode(c_uint8_ptr(em), - c_size_t(len(em)), - c_uint8_ptr(lHash), - c_size_t(len(lHash)), - c_uint8_ptr(db), - c_size_t(len(db))) - return ret + ret = _raw_pkcs1_decode.oaep_decode( + c_uint8_ptr(em), + c_size_t(len(em)), + c_uint8_ptr(lHash), + c_size_t(len(lHash)), + c_uint8_ptr(db), + c_size_t(len(db)), + ) + return ret diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2b.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2b.py index 85da8877..d0347cb1 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2b.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2b.py @@ -33,14 +33,19 @@ from Cryptodome.Util.py3compat import bord, tobytes from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_blake2b_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._BLAKE2b", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_blake2b_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._BLAKE2b", + """ int blake2b_init(void **state, const uint8_t *key, size_t key_size, @@ -52,196 +57,198 @@ int blake2b_digest(const void *state, uint8_t digest[64]); int blake2b_copy(const void *src, void *dst); - """) + """, +) class BLAKE2b_Hash(object): - """A BLAKE2b hash object. - Do not instantiate directly. Use the :func:`new` function. + """A BLAKE2b hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The internal block size of the hash algorithm in bytes. + block_size = 64 + + def __init__(self, data, key, digest_bytes, update_after_digest): + # The size of the resulting hash in bytes. + self.digest_size = digest_bytes + + self._update_after_digest = update_after_digest + self._digest_done = False + + # See https://tools.ietf.org/html/rfc7693 + if digest_bytes in (20, 32, 48, 64) and not key: + self.oid = "1.3.6.1.4.1.1722.12.2.1." + str(digest_bytes) + + state = VoidPointer() + result = _raw_blake2b_lib.blake2b_init( + state.address_of(), + c_uint8_ptr(key), + c_size_t(len(key)), + c_size_t(digest_bytes), + ) + if result: + raise ValueError("Error %d while instantiating BLAKE2b" % result) + self._state = SmartPointer( + state.get(), + _raw_blake2b_lib.blake2b_destroy, + ) + if data: + self.update(data) - :ivar oid: ASN.1 Object ID - :vartype oid: string + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer + Args: + data (bytes/bytearray/memoryview): The next chunk of the message being hashed. + """ - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - # The internal block size of the hash algorithm in bytes. - block_size = 64 + result = _raw_blake2b_lib.blake2b_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError("Error %d while hashing BLAKE2b data" % result) + return self - def __init__(self, data, key, digest_bytes, update_after_digest): + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. - # The size of the resulting hash in bytes. - self.digest_size = digest_bytes + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ - self._update_after_digest = update_after_digest - self._digest_done = False + bfr = create_string_buffer(64) + result = _raw_blake2b_lib.blake2b_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError("Error %d while creating BLAKE2b digest" % result) - # See https://tools.ietf.org/html/rfc7693 - if digest_bytes in (20, 32, 48, 64) and not key: - self.oid = "1.3.6.1.4.1.1722.12.2.1." + str(digest_bytes) + self._digest_done = True - state = VoidPointer() - result = _raw_blake2b_lib.blake2b_init(state.address_of(), - c_uint8_ptr(key), - c_size_t(len(key)), - c_size_t(digest_bytes) - ) - if result: - raise ValueError("Error %d while instantiating BLAKE2b" % result) - self._state = SmartPointer(state.get(), - _raw_blake2b_lib.blake2b_destroy) - if data: - self.update(data) + return get_raw_buffer(bfr)[: self.digest_size] + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ - Args: - data (bytes/bytearray/memoryview): The next chunk of the message being hashed. - """ + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. - result = _raw_blake2b_lib.blake2b_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing BLAKE2b data" % result) - return self + Args: + mac_tag (bytes/bytearray/memoryview): the expected MAC of the message. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. + secret = get_random_bytes(16) - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ + mac1 = new(digest_bits=160, key=secret, data=mac_tag) + mac2 = new(digest_bits=160, key=secret, data=self.digest()) - bfr = create_string_buffer(64) - result = _raw_blake2b_lib.blake2b_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while creating BLAKE2b digest" % result) + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - self._digest_done = True + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. - return get_raw_buffer(bfr)[:self.digest_size] + Args: + hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. + self.verify(unhexlify(tobytes(hex_mac_tag))) - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ + def new(self, **kwargs): + """Return a new instance of a BLAKE2b hash object. + See :func:`new`. + """ - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: + kwargs["digest_bytes"] = self.digest_size - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (bytes/bytearray/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = new(digest_bits=160, key=secret, data=mac_tag) - mac2 = new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - - def new(self, **kwargs): - """Return a new instance of a BLAKE2b hash object. - See :func:`new`. - """ - - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) + return new(**kwargs) def new(**kwargs): - """Create a new hash object. - - Args: - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`BLAKE2b_Hash.update`. - digest_bytes (integer): - Optional. The size of the digest, in bytes (1 to 64). Default is 64. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (8 to 512, in steps of 8). - Default is 512. - key (bytes/bytearray/memoryview): - Optional. The key to use to compute the MAC (1 to 64 bytes). - If not specified, no key will be used. - update_after_digest (boolean): - Optional. By default, a hash object cannot be updated anymore after - the digest is computed. When this flag is ``True``, such check - is no longer enforced. - - Returns: - A :class:`BLAKE2b_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 64 - if digest_bytes is not None: - if not (1 <= digest_bytes <= 64): - raise ValueError("'digest_bytes' not in range 1..64") - else: - if not (8 <= digest_bits <= 512) or (digest_bits % 8): - raise ValueError("'digest_bits' not in range 8..512, " - "with steps of 8") - digest_bytes = digest_bits // 8 - - key = kwargs.pop("key", b"") - if len(key) > 64: - raise ValueError("BLAKE2b key cannot exceed 64 bytes") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest) + """Create a new hash object. + + Args: + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`BLAKE2b_Hash.update`. + digest_bytes (integer): + Optional. The size of the digest, in bytes (1 to 64). Default is 64. + digest_bits (integer): + Optional and alternative to ``digest_bytes``. + The size of the digest, in bits (8 to 512, in steps of 8). + Default is 512. + key (bytes/bytearray/memoryview): + Optional. The key to use to compute the MAC (1 to 64 bytes). + If not specified, no key will be used. + update_after_digest (boolean): + Optional. By default, a hash object cannot be updated anymore after + the digest is computed. When this flag is ``True``, such check + is no longer enforced. + + Returns: + A :class:`BLAKE2b_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + digest_bytes = 64 + if digest_bytes is not None: + if not (1 <= digest_bytes <= 64): + raise ValueError("'digest_bytes' not in range 1..64") + else: + if not (8 <= digest_bits <= 512) or (digest_bits % 8): + raise ValueError( + "'digest_bits' not in range 8..512, with steps of 8", + ) + digest_bytes = digest_bits // 8 + + key = kwargs.pop("key", b"") + if len(key) > 64: + raise ValueError("BLAKE2b key cannot exceed 64 bytes") + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2b.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2b.pyi index d37c3749..9fde522a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2b.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2b.pyi @@ -1,32 +1,31 @@ -from typing import Any, Union -from types import ModuleType +from typing import Union Buffer = Union[bytes, bytearray, memoryview] class BLAKE2b_Hash(object): - block_size: int - digest_size: int - oid: str + block_size: int + digest_size: int + oid: str - def __init__(self, - data: Buffer, - key: Buffer, - digest_bytes: bytes, - update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> BLAKE2b_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - def new(self, - data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - key: Buffer = ..., - update_after_digest: bool = ...) -> BLAKE2b_Hash: ... + def __init__(self, data: Buffer, key: Buffer, digest_bytes: bytes, update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> BLAKE2b_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + def new( + self, + data: Buffer = ..., + digest_bytes: int = ..., + digest_bits: int = ..., + key: Buffer = ..., + update_after_digest: bool = ..., + ) -> BLAKE2b_Hash: ... -def new(data: Buffer = ..., +def new( + data: Buffer = ..., digest_bytes: int = ..., digest_bits: int = ..., key: Buffer = ..., - update_after_digest: bool = ...) -> BLAKE2b_Hash: ... + update_after_digest: bool = ..., +) -> BLAKE2b_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2s.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2s.py index 43be5c43..575f82a5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2s.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2s.py @@ -33,14 +33,19 @@ from Cryptodome.Util.py3compat import bord, tobytes from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_blake2s_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._BLAKE2s", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_blake2s_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._BLAKE2s", + """ int blake2s_init(void **state, const uint8_t *key, size_t key_size, @@ -52,196 +57,198 @@ int blake2s_digest(const void *state, uint8_t digest[32]); int blake2s_copy(const void *src, void *dst); - """) + """, +) class BLAKE2s_Hash(object): - """A BLAKE2s hash object. - Do not instantiate directly. Use the :func:`new` function. + """A BLAKE2s hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The internal block size of the hash algorithm in bytes. + block_size = 32 + + def __init__(self, data, key, digest_bytes, update_after_digest): + # The size of the resulting hash in bytes. + self.digest_size = digest_bytes + + self._update_after_digest = update_after_digest + self._digest_done = False + + # See https://tools.ietf.org/html/rfc7693 + if digest_bytes in (16, 20, 28, 32) and not key: + self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes) + + state = VoidPointer() + result = _raw_blake2s_lib.blake2s_init( + state.address_of(), + c_uint8_ptr(key), + c_size_t(len(key)), + c_size_t(digest_bytes), + ) + if result: + raise ValueError("Error %d while instantiating BLAKE2s" % result) + self._state = SmartPointer( + state.get(), + _raw_blake2s_lib.blake2s_destroy, + ) + if data: + self.update(data) - :ivar oid: ASN.1 Object ID - :vartype oid: string + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - # The internal block size of the hash algorithm in bytes. - block_size = 32 + result = _raw_blake2s_lib.blake2s_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError("Error %d while hashing BLAKE2s data" % result) + return self - def __init__(self, data, key, digest_bytes, update_after_digest): + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. - # The size of the resulting hash in bytes. - self.digest_size = digest_bytes + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ - self._update_after_digest = update_after_digest - self._digest_done = False + bfr = create_string_buffer(32) + result = _raw_blake2s_lib.blake2s_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError("Error %d while creating BLAKE2s digest" % result) - # See https://tools.ietf.org/html/rfc7693 - if digest_bytes in (16, 20, 28, 32) and not key: - self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes) + self._digest_done = True - state = VoidPointer() - result = _raw_blake2s_lib.blake2s_init(state.address_of(), - c_uint8_ptr(key), - c_size_t(len(key)), - c_size_t(digest_bytes) - ) - if result: - raise ValueError("Error %d while instantiating BLAKE2s" % result) - self._state = SmartPointer(state.get(), - _raw_blake2s_lib.blake2s_destroy) - if data: - self.update(data) + return get_raw_buffer(bfr)[: self.digest_size] + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. - result = _raw_blake2s_lib.blake2s_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing BLAKE2s data" % result) - return self + Args: + mac_tag (byte string/byte array/memoryview): the expected MAC of the message. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. + secret = get_random_bytes(16) - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ + mac1 = new(digest_bits=160, key=secret, data=mac_tag) + mac2 = new(digest_bits=160, key=secret, data=self.digest()) - bfr = create_string_buffer(32) - result = _raw_blake2s_lib.blake2s_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while creating BLAKE2s digest" % result) + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - self._digest_done = True + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. - return get_raw_buffer(bfr)[:self.digest_size] + Args: + hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. + self.verify(unhexlify(tobytes(hex_mac_tag))) - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ + def new(self, **kwargs): + """Return a new instance of a BLAKE2s hash object. + See :func:`new`. + """ - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: + kwargs["digest_bytes"] = self.digest_size - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte array/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = new(digest_bits=160, key=secret, data=mac_tag) - mac2 = new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - - def new(self, **kwargs): - """Return a new instance of a BLAKE2s hash object. - See :func:`new`. - """ - - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) + return new(**kwargs) def new(**kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`BLAKE2s_Hash.update`. - digest_bytes (integer): - Optional. The size of the digest, in bytes (1 to 32). Default is 32. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (8 to 256, in steps of 8). - Default is 256. - key (byte string): - Optional. The key to use to compute the MAC (1 to 64 bytes). - If not specified, no key will be used. - update_after_digest (boolean): - Optional. By default, a hash object cannot be updated anymore after - the digest is computed. When this flag is ``True``, such check - is no longer enforced. - - Returns: - A :class:`BLAKE2s_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 32 - if digest_bytes is not None: - if not (1 <= digest_bytes <= 32): - raise ValueError("'digest_bytes' not in range 1..32") - else: - if not (8 <= digest_bits <= 256) or (digest_bits % 8): - raise ValueError("'digest_bits' not in range 8..256, " - "with steps of 8") - digest_bytes = digest_bits // 8 - - key = kwargs.pop("key", b"") - if len(key) > 32: - raise ValueError("BLAKE2s key cannot exceed 32 bytes") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return BLAKE2s_Hash(data, key, digest_bytes, update_after_digest) + """Create a new hash object. + + Args: + data (byte string/byte array/memoryview): + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`BLAKE2s_Hash.update`. + digest_bytes (integer): + Optional. The size of the digest, in bytes (1 to 32). Default is 32. + digest_bits (integer): + Optional and alternative to ``digest_bytes``. + The size of the digest, in bits (8 to 256, in steps of 8). + Default is 256. + key (byte string): + Optional. The key to use to compute the MAC (1 to 64 bytes). + If not specified, no key will be used. + update_after_digest (boolean): + Optional. By default, a hash object cannot be updated anymore after + the digest is computed. When this flag is ``True``, such check + is no longer enforced. + + Returns: + A :class:`BLAKE2s_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + digest_bytes = 32 + if digest_bytes is not None: + if not (1 <= digest_bytes <= 32): + raise ValueError("'digest_bytes' not in range 1..32") + else: + if not (8 <= digest_bits <= 256) or (digest_bits % 8): + raise ValueError( + "'digest_bits' not in range 8..256, with steps of 8", + ) + digest_bytes = digest_bits // 8 + + key = kwargs.pop("key", b"") + if len(key) > 32: + raise ValueError("BLAKE2s key cannot exceed 32 bytes") + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return BLAKE2s_Hash(data, key, digest_bytes, update_after_digest) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2s.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2s.pyi index 374b3a43..47a970ab 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2s.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/BLAKE2s.pyi @@ -3,24 +3,22 @@ from typing import Any, Union Buffer = Union[bytes, bytearray, memoryview] class BLAKE2s_Hash(object): - block_size: int - digest_size: int - oid: str + block_size: int + digest_size: int + oid: str - def __init__(self, - data: Buffer, - key: Buffer, - digest_bytes: bytes, - update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> BLAKE2s_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - def new(self, **kwargs: Any) -> BLAKE2s_Hash: ... + def __init__(self, data: Buffer, key: Buffer, digest_bytes: bytes, update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> BLAKE2s_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + def new(self, **kwargs: Any) -> BLAKE2s_Hash: ... -def new(data: Buffer = ..., +def new( + data: Buffer = ..., digest_bytes: int = ..., digest_bits: int = ..., key: Buffer = ..., - update_after_digest: bool = ...) -> BLAKE2s_Hash: ... + update_after_digest: bool = ..., +) -> BLAKE2s_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/CMAC.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/CMAC.py index 8feb79fd..935cb1d8 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/CMAC.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/CMAC.py @@ -34,273 +34,299 @@ def _shift_bytes(bs, xor_lsb=0): - num = (bytes_to_long(bs) << 1) ^ xor_lsb - return long_to_bytes(num, len(bs))[-len(bs):] + num = (bytes_to_long(bs) << 1) ^ xor_lsb + return long_to_bytes(num, len(bs))[-len(bs) :] class CMAC(object): - """A CMAC hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting MAC tag - :vartype digest_size: integer - """ - - digest_size = None - - def __init__(self, key, msg, ciphermod, cipher_params, mac_len, - update_after_digest): - - self.digest_size = mac_len - - self._key = _copy_bytes(None, None, key) - self._factory = ciphermod - self._cipher_params = cipher_params - self._block_size = bs = ciphermod.block_size - self._mac_tag = None - self._update_after_digest = update_after_digest - - # Section 5.3 of NIST SP 800 38B and Appendix B - if bs == 8: - const_Rb = 0x1B - self._max_size = 8 * (2 ** 21) - elif bs == 16: - const_Rb = 0x87 - self._max_size = 16 * (2 ** 48) - else: - raise TypeError("CMAC requires a cipher with a block size" - " of 8 or 16 bytes, not %d" % bs) - - # Compute sub-keys - zero_block = b'\x00' * bs - self._ecb = ciphermod.new(key, - ciphermod.MODE_ECB, - **self._cipher_params) - L = self._ecb.encrypt(zero_block) - if bord(L[0]) & 0x80: - self._k1 = _shift_bytes(L, const_Rb) - else: - self._k1 = _shift_bytes(L) - if bord(self._k1[0]) & 0x80: - self._k2 = _shift_bytes(self._k1, const_Rb) - else: - self._k2 = _shift_bytes(self._k1) - - # Initialize CBC cipher with zero IV - self._cbc = ciphermod.new(key, - ciphermod.MODE_CBC, - zero_block, - **self._cipher_params) - - # Cache for outstanding data to authenticate - self._cache = bytearray(bs) - self._cache_n = 0 - - # Last piece of ciphertext produced - self._last_ct = zero_block - - # Last block that was encrypted with AES - self._last_pt = None - - # Counter for total message size - self._data_size = 0 - - if msg: - self.update(msg) - - def update(self, msg): - """Authenticate the next chunk of message. - - Args: - data (byte string/byte array/memoryview): The next chunk of data - """ - - if self._mac_tag is not None and not self._update_after_digest: - raise TypeError("update() cannot be called after digest() or verify()") - - self._data_size += len(msg) - bs = self._block_size - - if self._cache_n > 0: - filler = min(bs - self._cache_n, len(msg)) - self._cache[self._cache_n:self._cache_n+filler] = msg[:filler] - self._cache_n += filler - - if self._cache_n < bs: - return self - - msg = memoryview(msg)[filler:] - self._update(self._cache) - self._cache_n = 0 - - remain = len(msg) % bs - if remain > 0: - self._update(msg[:-remain]) - self._cache[:remain] = msg[-remain:] - else: - self._update(msg) - self._cache_n = remain - return self - - def _update(self, data_block): - """Update a block aligned to the block boundary""" - - bs = self._block_size - assert len(data_block) % bs == 0 - - if len(data_block) == 0: - return - - ct = self._cbc.encrypt(data_block) - if len(data_block) == bs: - second_last = self._last_ct - else: - second_last = ct[-bs*2:-bs] - self._last_ct = ct[-bs:] - self._last_pt = strxor(second_last, data_block[-bs:]) - - def copy(self): - """Return a copy ("clone") of the CMAC object. - - The copy will have the same internal state as the original CMAC - object. - This can be used to efficiently compute the MAC tag of byte - strings that share a common initial substring. - - :return: An :class:`CMAC` - """ - - obj = self.__new__(CMAC) - obj.__dict__ = self.__dict__.copy() - obj._cbc = self._factory.new(self._key, - self._factory.MODE_CBC, - self._last_ct, - **self._cipher_params) - obj._cache = self._cache[:] - obj._last_ct = self._last_ct[:] - return obj - - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message - that has been authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bs = self._block_size - - if self._mac_tag is not None and not self._update_after_digest: - return self._mac_tag - - if self._data_size > self._max_size: - raise ValueError("MAC is unsafe for this message") - - if self._cache_n == 0 and self._data_size > 0: - # Last block was full - pt = strxor(self._last_pt, self._k1) - else: - # Last block is partial (or message length is zero) - partial = self._cache[:] - partial[self._cache_n:] = b'\x80' + b'\x00' * (bs - self._cache_n - 1) - pt = strxor(strxor(self._last_ct, partial), self._k2) - - self._mac_tag = self._ecb.encrypt(pt)[:self.digest_size] - - return self._mac_tag - - def hexdigest(self): - """Return the **printable** MAC tag of the message authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) - for x in tuple(self.digest())]) - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte array/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - -def new(key, msg=None, ciphermod=None, cipher_params=None, mac_len=None, - update_after_digest=False): - """Create a new MAC object. - - Args: - key (byte string/byte array/memoryview): - key for the CMAC object. - The key must be valid for the underlying cipher algorithm. - For instance, it must be 16 bytes long for AES-128. - ciphermod (module): - A cipher module from :mod:`Cryptodome.Cipher`. - The cipher's block size has to be 128 bits, - like :mod:`Cryptodome.Cipher.AES`, to reduce the probability - of collisions. - msg (byte string/byte array/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to `CMAC.update`. Optional. - cipher_params (dict): - Optional. A set of parameters to use when instantiating a cipher - object. - mac_len (integer): - Length of the MAC, in bytes. - It must be at least 4 bytes long. - The default (and recommended) length matches the size of a cipher block. - update_after_digest (boolean): - Optional. By default, a hash object cannot be updated anymore after - the digest is computed. When this flag is ``True``, such check - is no longer enforced. - Returns: - A :class:`CMAC` object - """ - - if ciphermod is None: - raise TypeError("ciphermod must be specified (try AES)") - - cipher_params = {} if cipher_params is None else dict(cipher_params) - - if mac_len is None: - mac_len = ciphermod.block_size - - if mac_len < 4: - raise ValueError("MAC tag length must be at least 4 bytes long") - - if mac_len > ciphermod.block_size: - raise ValueError("MAC tag length cannot be larger than a cipher block (%d) bytes" % ciphermod.block_size) - - return CMAC(key, msg, ciphermod, cipher_params, mac_len, - update_after_digest) + """A CMAC hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar digest_size: the size in bytes of the resulting MAC tag + :vartype digest_size: integer + """ + + digest_size = None + + def __init__( + self, + key, + msg, + ciphermod, + cipher_params, + mac_len, + update_after_digest, + ): + self.digest_size = mac_len + + self._key = _copy_bytes(None, None, key) + self._factory = ciphermod + self._cipher_params = cipher_params + self._block_size = bs = ciphermod.block_size + self._mac_tag = None + self._update_after_digest = update_after_digest + + # Section 5.3 of NIST SP 800 38B and Appendix B + if bs == 8: + const_Rb = 0x1B + self._max_size = 8 * (2**21) + elif bs == 16: + const_Rb = 0x87 + self._max_size = 16 * (2**48) + else: + raise TypeError( + "CMAC requires a cipher with a block size of 8 or 16 bytes, not %d" % bs, + ) + + # Compute sub-keys + zero_block = b"\x00" * bs + self._ecb = ciphermod.new( + key, + ciphermod.MODE_ECB, + **self._cipher_params, + ) + L = self._ecb.encrypt(zero_block) + if bord(L[0]) & 0x80: + self._k1 = _shift_bytes(L, const_Rb) + else: + self._k1 = _shift_bytes(L) + if bord(self._k1[0]) & 0x80: + self._k2 = _shift_bytes(self._k1, const_Rb) + else: + self._k2 = _shift_bytes(self._k1) + + # Initialize CBC cipher with zero IV + self._cbc = ciphermod.new( + key, + ciphermod.MODE_CBC, + zero_block, + **self._cipher_params, + ) + + # Cache for outstanding data to authenticate + self._cache = bytearray(bs) + self._cache_n = 0 + + # Last piece of ciphertext produced + self._last_ct = zero_block + + # Last block that was encrypted with AES + self._last_pt = None + + # Counter for total message size + self._data_size = 0 + + if msg: + self.update(msg) + + def update(self, msg): + """Authenticate the next chunk of message. + + Args: + data (byte string/byte array/memoryview): The next chunk of data + """ + + if self._mac_tag is not None and not self._update_after_digest: + raise TypeError("update() cannot be called after digest() or verify()") + + self._data_size += len(msg) + bs = self._block_size + + if self._cache_n > 0: + filler = min(bs - self._cache_n, len(msg)) + self._cache[self._cache_n : self._cache_n + filler] = msg[:filler] + self._cache_n += filler + + if self._cache_n < bs: + return self + + msg = memoryview(msg)[filler:] + self._update(self._cache) + self._cache_n = 0 + + remain = len(msg) % bs + if remain > 0: + self._update(msg[:-remain]) + self._cache[:remain] = msg[-remain:] + else: + self._update(msg) + self._cache_n = remain + return self + + def _update(self, data_block): + """Update a block aligned to the block boundary""" + + bs = self._block_size + assert len(data_block) % bs == 0 + + if len(data_block) == 0: + return + + ct = self._cbc.encrypt(data_block) + if len(data_block) == bs: + second_last = self._last_ct + else: + second_last = ct[-bs * 2 : -bs] + self._last_ct = ct[-bs:] + self._last_pt = strxor(second_last, data_block[-bs:]) + + def copy(self): + """Return a copy ("clone") of the CMAC object. + + The copy will have the same internal state as the original CMAC + object. + This can be used to efficiently compute the MAC tag of byte + strings that share a common initial substring. + + :return: An :class:`CMAC` + """ + + obj = self.__new__(CMAC) + obj.__dict__ = self.__dict__.copy() + obj._cbc = self._factory.new( + self._key, + self._factory.MODE_CBC, + self._last_ct, + **self._cipher_params, + ) + obj._cache = self._cache[:] + obj._last_ct = self._last_ct[:] + return obj + + def digest(self): + """Return the **binary** (non-printable) MAC tag of the message + that has been authenticated so far. + + :return: The MAC tag, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bs = self._block_size + + if self._mac_tag is not None and not self._update_after_digest: + return self._mac_tag + + if self._data_size > self._max_size: + raise ValueError("MAC is unsafe for this message") + + if self._cache_n == 0 and self._data_size > 0: + # Last block was full + pt = strxor(self._last_pt, self._k1) + else: + # Last block is partial (or message length is zero) + partial = self._cache[:] + partial[self._cache_n :] = b"\x80" + b"\x00" * (bs - self._cache_n - 1) + pt = strxor(strxor(self._last_ct, partial), self._k2) + + self._mac_tag = self._ecb.encrypt(pt)[: self.digest_size] + + return self._mac_tag + + def hexdigest(self): + """Return the **printable** MAC tag of the message authenticated so far. + + :return: The MAC tag, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. + + Args: + mac_tag (byte string/byte array/memoryview): the expected MAC of the message. + + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. + + Args: + hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. + + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + self.verify(unhexlify(tobytes(hex_mac_tag))) + + +def new( + key, + msg=None, + ciphermod=None, + cipher_params=None, + mac_len=None, + update_after_digest=False, +): + """Create a new MAC object. + + Args: + key (byte string/byte array/memoryview): + key for the CMAC object. + The key must be valid for the underlying cipher algorithm. + For instance, it must be 16 bytes long for AES-128. + ciphermod (module): + A cipher module from :mod:`Cryptodome.Cipher`. + The cipher's block size has to be 128 bits, + like :mod:`Cryptodome.Cipher.AES`, to reduce the probability + of collisions. + msg (byte string/byte array/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to `CMAC.update`. Optional. + cipher_params (dict): + Optional. A set of parameters to use when instantiating a cipher + object. + mac_len (integer): + Length of the MAC, in bytes. + It must be at least 4 bytes long. + The default (and recommended) length matches the size of a cipher block. + update_after_digest (boolean): + Optional. By default, a hash object cannot be updated anymore after + the digest is computed. When this flag is ``True``, such check + is no longer enforced. + Returns: + A :class:`CMAC` object + """ + + if ciphermod is None: + raise TypeError("ciphermod must be specified (try AES)") + + cipher_params = {} if cipher_params is None else dict(cipher_params) + + if mac_len is None: + mac_len = ciphermod.block_size + + if mac_len < 4: + raise ValueError("MAC tag length must be at least 4 bytes long") + + if mac_len > ciphermod.block_size: + raise ValueError( + "MAC tag length cannot be larger than a cipher block (%d) bytes" % ciphermod.block_size + ) + + return CMAC( + key, + msg, + ciphermod, + cipher_params, + mac_len, + update_after_digest, + ) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/CMAC.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/CMAC.pyi index acdf0553..10cd2afc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/CMAC.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/CMAC.pyi @@ -6,25 +6,29 @@ Buffer = Union[bytes, bytearray, memoryview] digest_size: int class CMAC(object): - digest_size: int + digest_size: int - def __init__(self, - key: Buffer, - msg: Buffer, - ciphermod: ModuleType, - cipher_params: Dict[str, Any], - mac_len: int, update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> CMAC: ... - def copy(self) -> CMAC: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... + def __init__( + self, + key: Buffer, + msg: Buffer, + ciphermod: ModuleType, + cipher_params: Dict[str, Any], + mac_len: int, + update_after_digest: bool, + ) -> None: ... + def update(self, data: Buffer) -> CMAC: ... + def copy(self) -> CMAC: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... - -def new(key: Buffer, - msg: Buffer = ..., +def new( + key: Buffer, + msg: Buffer = ..., ciphermod: ModuleType = ..., cipher_params: Dict[str, Any] = ..., mac_len: int = ..., - update_after_digest: bool = ...) -> CMAC: ... + update_after_digest: bool = ..., +) -> CMAC: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/HMAC.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/HMAC.py index 615056a8..13aa2089 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/HMAC.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/HMAC.py @@ -39,200 +39,200 @@ from Cryptodome.Util.strxor import strxor from Cryptodome.Random import get_random_bytes -__all__ = ['new', 'HMAC'] +__all__ = ["new", "HMAC"] _hash2hmac_oid = { - '1.3.14.3.2.26': '1.2.840.113549.2.7', # SHA-1 - '2.16.840.1.101.3.4.2.4': '1.2.840.113549.2.8', # SHA-224 - '2.16.840.1.101.3.4.2.1': '1.2.840.113549.2.9', # SHA-256 - '2.16.840.1.101.3.4.2.2': '1.2.840.113549.2.10', # SHA-384 - '2.16.840.1.101.3.4.2.3': '1.2.840.113549.2.11', # SHA-512 - '2.16.840.1.101.3.4.2.5': '1.2.840.113549.2.12', # SHA-512_224 - '2.16.840.1.101.3.4.2.6': '1.2.840.113549.2.13', # SHA-512_256 - '2.16.840.1.101.3.4.2.7': '2.16.840.1.101.3.4.2.13', # SHA-3 224 - '2.16.840.1.101.3.4.2.8': '2.16.840.1.101.3.4.2.14', # SHA-3 256 - '2.16.840.1.101.3.4.2.9': '2.16.840.1.101.3.4.2.15', # SHA-3 384 - '2.16.840.1.101.3.4.2.10': '2.16.840.1.101.3.4.2.16', # SHA-3 512 + "1.3.14.3.2.26": "1.2.840.113549.2.7", # SHA-1 + "2.16.840.1.101.3.4.2.4": "1.2.840.113549.2.8", # SHA-224 + "2.16.840.1.101.3.4.2.1": "1.2.840.113549.2.9", # SHA-256 + "2.16.840.1.101.3.4.2.2": "1.2.840.113549.2.10", # SHA-384 + "2.16.840.1.101.3.4.2.3": "1.2.840.113549.2.11", # SHA-512 + "2.16.840.1.101.3.4.2.5": "1.2.840.113549.2.12", # SHA-512_224 + "2.16.840.1.101.3.4.2.6": "1.2.840.113549.2.13", # SHA-512_256 + "2.16.840.1.101.3.4.2.7": "2.16.840.1.101.3.4.2.13", # SHA-3 224 + "2.16.840.1.101.3.4.2.8": "2.16.840.1.101.3.4.2.14", # SHA-3 256 + "2.16.840.1.101.3.4.2.9": "2.16.840.1.101.3.4.2.15", # SHA-3 384 + "2.16.840.1.101.3.4.2.10": "2.16.840.1.101.3.4.2.16", # SHA-3 512 } _hmac2hash_oid = {v: k for k, v in _hash2hmac_oid.items()} class HMAC(object): - """An HMAC hash object. - Do not instantiate directly. Use the :func:`new` function. + """An HMAC hash object. + Do not instantiate directly. Use the :func:`new` function. - :ivar digest_size: the size in bytes of the resulting MAC tag - :vartype digest_size: integer + :ivar digest_size: the size in bytes of the resulting MAC tag + :vartype digest_size: integer - :ivar oid: the ASN.1 object ID of the HMAC algorithm. - Only present if the algorithm was officially assigned one. - """ + :ivar oid: the ASN.1 object ID of the HMAC algorithm. + Only present if the algorithm was officially assigned one. + """ - def __init__(self, key, msg=b"", digestmod=None): + def __init__(self, key, msg=b"", digestmod=None): + if digestmod is None: + from Cryptodome.Hash import MD5 - if digestmod is None: - from Cryptodome.Hash import MD5 - digestmod = MD5 + digestmod = MD5 - if msg is None: - msg = b"" + if msg is None: + msg = b"" - # Size of the MAC tag - self.digest_size = digestmod.digest_size + # Size of the MAC tag + self.digest_size = digestmod.digest_size - self._digestmod = digestmod + self._digestmod = digestmod - # Hash OID --> HMAC OID - try: - self.oid = _hash2hmac_oid[digestmod.oid] - except (KeyError, AttributeError): - pass + # Hash OID --> HMAC OID + try: + self.oid = _hash2hmac_oid[digestmod.oid] + except (KeyError, AttributeError): + pass - if isinstance(key, memoryview): - key = key.tobytes() + if isinstance(key, memoryview): + key = key.tobytes() - try: - if len(key) <= digestmod.block_size: - # Step 1 or 2 - key_0 = key + b"\x00" * (digestmod.block_size - len(key)) - else: - # Step 3 - hash_k = digestmod.new(key).digest() - key_0 = hash_k + b"\x00" * (digestmod.block_size - len(hash_k)) - except AttributeError: - # Not all hash types have "block_size" - raise ValueError("Hash type incompatible to HMAC") + try: + if len(key) <= digestmod.block_size: + # Step 1 or 2 + key_0 = key + b"\x00" * (digestmod.block_size - len(key)) + else: + # Step 3 + hash_k = digestmod.new(key).digest() + key_0 = hash_k + b"\x00" * (digestmod.block_size - len(hash_k)) + except AttributeError: + # Not all hash types have "block_size" + raise ValueError("Hash type incompatible to HMAC") - # Step 4 - key_0_ipad = strxor(key_0, b"\x36" * len(key_0)) + # Step 4 + key_0_ipad = strxor(key_0, b"\x36" * len(key_0)) - # Start step 5 and 6 - self._inner = digestmod.new(key_0_ipad) - self._inner.update(msg) + # Start step 5 and 6 + self._inner = digestmod.new(key_0_ipad) + self._inner.update(msg) - # Step 7 - key_0_opad = strxor(key_0, b"\x5c" * len(key_0)) + # Step 7 + key_0_opad = strxor(key_0, b"\x5c" * len(key_0)) - # Start step 8 and 9 - self._outer = digestmod.new(key_0_opad) + # Start step 8 and 9 + self._outer = digestmod.new(key_0_opad) - def update(self, msg): - """Authenticate the next chunk of message. + def update(self, msg): + """Authenticate the next chunk of message. - Args: - data (byte string/byte array/memoryview): The next chunk of data - """ + Args: + data (byte string/byte array/memoryview): The next chunk of data + """ - self._inner.update(msg) - return self + self._inner.update(msg) + return self - def _pbkdf2_hmac_assist(self, first_digest, iterations): - """Carry out the expensive inner loop for PBKDF2-HMAC""" + def _pbkdf2_hmac_assist(self, first_digest, iterations): + """Carry out the expensive inner loop for PBKDF2-HMAC""" - result = self._digestmod._pbkdf2_hmac_assist( - self._inner, - self._outer, - first_digest, - iterations) - return result + result = self._digestmod._pbkdf2_hmac_assist( + self._inner, + self._outer, + first_digest, + iterations, + ) + return result - def copy(self): - """Return a copy ("clone") of the HMAC object. + def copy(self): + """Return a copy ("clone") of the HMAC object. - The copy will have the same internal state as the original HMAC - object. - This can be used to efficiently compute the MAC tag of byte - strings that share a common initial substring. + The copy will have the same internal state as the original HMAC + object. + This can be used to efficiently compute the MAC tag of byte + strings that share a common initial substring. - :return: An :class:`HMAC` - """ + :return: An :class:`HMAC` + """ - new_hmac = HMAC(b"fake key", digestmod=self._digestmod) + new_hmac = HMAC(b"fake key", digestmod=self._digestmod) - # Syncronize the state - new_hmac._inner = self._inner.copy() - new_hmac._outer = self._outer.copy() + # Syncronize the state + new_hmac._inner = self._inner.copy() + new_hmac._outer = self._outer.copy() - return new_hmac + return new_hmac - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message - authenticated so far. + def digest(self): + """Return the **binary** (non-printable) MAC tag of the message + authenticated so far. - :return: The MAC tag digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ + :return: The MAC tag digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ - frozen_outer_hash = self._outer.copy() - frozen_outer_hash.update(self._inner.digest()) - return frozen_outer_hash.digest() + frozen_outer_hash = self._outer.copy() + frozen_outer_hash.update(self._inner.digest()) + return frozen_outer_hash.digest() - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. - Args: - mac_tag (byte string/byte string/memoryview): the expected MAC of the message. + Args: + mac_tag (byte string/byte string/memoryview): the expected MAC of the message. - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - secret = get_random_bytes(16) + secret = get_random_bytes(16) - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - def hexdigest(self): - """Return the **printable** MAC tag of the message authenticated so far. + def hexdigest(self): + """Return the **printable** MAC tag of the message authenticated so far. - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ + :return: The MAC tag, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ - return "".join(["%02x" % bord(x) - for x in tuple(self.digest())]) + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. - Args: - hex_mac_tag (string): the expected MAC of the message, - as a hexadecimal string. + Args: + hex_mac_tag (string): the expected MAC of the message, + as a hexadecimal string. - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - self.verify(unhexlify(tobytes(hex_mac_tag))) + self.verify(unhexlify(tobytes(hex_mac_tag))) def new(key, msg=b"", digestmod=None): - """Create a new MAC object. - - Args: - key (bytes/bytearray/memoryview): - key for the MAC object. - It must be long enough to match the expected security level of the - MAC. - msg (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to :meth:`HMAC.update`. - digestmod (module): - The hash to use to implement the HMAC. - Default is :mod:`Cryptodome.Hash.MD5`. - - Returns: - An :class:`HMAC` object - """ - - return HMAC(key, msg, digestmod) + """Create a new MAC object. + + Args: + key (bytes/bytearray/memoryview): + key for the MAC object. + It must be long enough to match the expected security level of the + MAC. + msg (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to :meth:`HMAC.update`. + digestmod (module): + The hash to use to implement the HMAC. + Default is :mod:`Cryptodome.Hash.MD5`. + + Returns: + An :class:`HMAC` object + """ + + return HMAC(key, msg, digestmod) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/HMAC.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/HMAC.pyi index b577230f..8d3b7c52 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/HMAC.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/HMAC.pyi @@ -1,25 +1,19 @@ from types import ModuleType -from typing import Union, Dict +from typing import Union Buffer = Union[bytes, bytearray, memoryview] digest_size: int class HMAC(object): - digest_size: int + digest_size: int - def __init__(self, - key: Buffer, - msg: Buffer, - digestmod: ModuleType) -> None: ... - def update(self, msg: Buffer) -> HMAC: ... - def copy(self) -> HMAC: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... + def __init__(self, key: Buffer, msg: Buffer, digestmod: ModuleType) -> None: ... + def update(self, msg: Buffer) -> HMAC: ... + def copy(self) -> HMAC: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... - -def new(key: Buffer, - msg: Buffer = ..., - digestmod: ModuleType = ...) -> HMAC: ... +def new(key: Buffer, msg: Buffer = ..., digestmod: ModuleType = ...) -> HMAC: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC128.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC128.py index afd91c46..bf284faa 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC128.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC128.py @@ -38,142 +38,149 @@ class KMAC_Hash(object): - """A KMAC hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ + """A KMAC hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ - def __init__(self, data, key, mac_len, custom, - oid_variant, cshake, rate): + def __init__( + self, + data, + key, + mac_len, + custom, + oid_variant, + cshake, + rate, + ): + # See https://tools.ietf.org/html/rfc8702 + self.oid = "2.16.840.1.101.3.4.2." + oid_variant + self.digest_size = mac_len - # See https://tools.ietf.org/html/rfc8702 - self.oid = "2.16.840.1.101.3.4.2." + oid_variant - self.digest_size = mac_len + self._mac = None - self._mac = None + partial_newX = _bytepad(_encode_str(tobytes(key)), rate) + self._cshake = cshake._new(partial_newX, custom, b"KMAC") - partial_newX = _bytepad(_encode_str(tobytes(key)), rate) - self._cshake = cshake._new(partial_newX, custom, b"KMAC") + if data: + self._cshake.update(data) - if data: - self._cshake.update(data) + def update(self, data): + """Authenticate the next chunk of message. - def update(self, data): - """Authenticate the next chunk of message. + Args: + data (bytes/bytearray/memoryview): The next chunk of the message to + authenticate. + """ - Args: - data (bytes/bytearray/memoryview): The next chunk of the message to - authenticate. - """ + if self._mac: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - if self._mac: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + self._cshake.update(data) + return self - self._cshake.update(data) - return self + def digest(self): + """Return the **binary** (non-printable) MAC tag of the message. - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message. + :return: The MAC tag. Binary form. + :rtype: byte string + """ - :return: The MAC tag. Binary form. - :rtype: byte string - """ + if not self._mac: + self._cshake.update(_right_encode(self.digest_size * 8)) + self._mac = self._cshake.read(self.digest_size) - if not self._mac: - self._cshake.update(_right_encode(self.digest_size * 8)) - self._mac = self._cshake.read(self.digest_size) + return self._mac - return self._mac + def hexdigest(self): + """Return the **printable** MAC tag of the message. - def hexdigest(self): - """Return the **printable** MAC tag of the message. + :return: The MAC tag. Hexadecimal encoded. + :rtype: string + """ - :return: The MAC tag. Hexadecimal encoded. - :rtype: string - """ + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. + Args: + mac_tag (bytes/bytearray/memoryview): the expected MAC of the message. - Args: - mac_tag (bytes/bytearray/memoryview): the expected MAC of the message. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ + secret = get_random_bytes(16) - secret = get_random_bytes(16) + mac1 = SHA3_256.new(secret + mac_tag) + mac2 = SHA3_256.new(secret + self.digest()) - mac1 = SHA3_256.new(secret + mac_tag) - mac2 = SHA3_256.new(secret + self.digest()) + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. + Args: + hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ + self.verify(unhexlify(tobytes(hex_mac_tag))) - self.verify(unhexlify(tobytes(hex_mac_tag))) + def new(self, **kwargs): + """Return a new instance of a KMAC hash object. + See :func:`new`. + """ - def new(self, **kwargs): - """Return a new instance of a KMAC hash object. - See :func:`new`. - """ + if "mac_len" not in kwargs: + kwargs["mac_len"] = self.digest_size - if "mac_len" not in kwargs: - kwargs["mac_len"] = self.digest_size - - return new(**kwargs) + return new(**kwargs) def new(**kwargs): - """Create a new KMAC128 object. - - Args: - key (bytes/bytearray/memoryview): - The key to use to compute the MAC. - It must be at least 128 bits long (16 bytes). - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to :meth:`KMAC_Hash.update`. - mac_len (integer): - Optional. The size of the authentication tag, in bytes. - Default is 64. Minimum is 8. - custom (bytes/bytearray/memoryview): - Optional. A customization byte string (``S`` in SP 800-185). - - Returns: - A :class:`KMAC_Hash` hash object - """ - - key = kwargs.pop("key", None) - if not is_bytes(key): - raise TypeError("You must pass a key to KMAC128") - if len(key) < 16: - raise ValueError("The key must be at least 128 bits long (16 bytes)") - - data = kwargs.pop("data", None) - - mac_len = kwargs.pop("mac_len", 64) - if mac_len < 8: - raise ValueError("'mac_len' must be 8 bytes or more") - - custom = kwargs.pop("custom", b"") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return KMAC_Hash(data, key, mac_len, custom, "19", cSHAKE128, 168) + """Create a new KMAC128 object. + + Args: + key (bytes/bytearray/memoryview): + The key to use to compute the MAC. + It must be at least 128 bits long (16 bytes). + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to :meth:`KMAC_Hash.update`. + mac_len (integer): + Optional. The size of the authentication tag, in bytes. + Default is 64. Minimum is 8. + custom (bytes/bytearray/memoryview): + Optional. A customization byte string (``S`` in SP 800-185). + + Returns: + A :class:`KMAC_Hash` hash object + """ + + key = kwargs.pop("key", None) + if not is_bytes(key): + raise TypeError("You must pass a key to KMAC128") + if len(key) < 16: + raise ValueError("The key must be at least 128 bits long (16 bytes)") + + data = kwargs.pop("data", None) + + mac_len = kwargs.pop("mac_len", 64) + if mac_len < 8: + raise ValueError("'mac_len' must be 8 bytes or more") + + custom = kwargs.pop("custom", b"") + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return KMAC_Hash(data, key, mac_len, custom, "19", cSHAKE128, 168) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC128.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC128.pyi index 8947dabc..23223322 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC128.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC128.pyi @@ -4,30 +4,23 @@ from types import ModuleType Buffer = Union[bytes, bytearray, memoryview] class KMAC_Hash(object): + def __init__( + self, + data: Buffer, + key: Buffer, + mac_len: int, + custom: Buffer, + oid_variant: str, + cshake: ModuleType, + rate: int, + ) -> None: ... + def update(self, data: Buffer) -> KMAC_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + def new( + self, data: Buffer = ..., mac_len: int = ..., key: Buffer = ..., custom: Buffer = ... + ) -> KMAC_Hash: ... - def __init__(self, - data: Buffer, - key: Buffer, - mac_len: int, - custom: Buffer, - oid_variant: str, - cshake: ModuleType, - rate: int) -> None: ... - - def update(self, data: Buffer) -> KMAC_Hash: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - def new(self, - data: Buffer = ..., - mac_len: int = ..., - key: Buffer = ..., - custom: Buffer = ...) -> KMAC_Hash: ... - - -def new(key: Buffer, - data: Buffer = ..., - mac_len: int = ..., - custom: Buffer = ...) -> KMAC_Hash: ... +def new(key: Buffer, data: Buffer = ..., mac_len: int = ..., custom: Buffer = ...) -> KMAC_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC256.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC256.py index 82da0626..2d957b1b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC256.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC256.py @@ -35,40 +35,40 @@ def new(**kwargs): - """Create a new KMAC256 object. + """Create a new KMAC256 object. - Args: - key (bytes/bytearray/memoryview): - The key to use to compute the MAC. - It must be at least 256 bits long (32 bytes). - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to :meth:`KMAC_Hash.update`. - mac_len (integer): - Optional. The size of the authentication tag, in bytes. - Default is 64. Minimum is 8. - custom (bytes/bytearray/memoryview): - Optional. A customization byte string (``S`` in SP 800-185). + Args: + key (bytes/bytearray/memoryview): + The key to use to compute the MAC. + It must be at least 256 bits long (32 bytes). + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to :meth:`KMAC_Hash.update`. + mac_len (integer): + Optional. The size of the authentication tag, in bytes. + Default is 64. Minimum is 8. + custom (bytes/bytearray/memoryview): + Optional. A customization byte string (``S`` in SP 800-185). - Returns: - A :class:`KMAC_Hash` hash object - """ + Returns: + A :class:`KMAC_Hash` hash object + """ - key = kwargs.pop("key", None) - if not is_bytes(key): - raise TypeError("You must pass a key to KMAC256") - if len(key) < 32: - raise ValueError("The key must be at least 256 bits long (32 bytes)") + key = kwargs.pop("key", None) + if not is_bytes(key): + raise TypeError("You must pass a key to KMAC256") + if len(key) < 32: + raise ValueError("The key must be at least 256 bits long (32 bytes)") - data = kwargs.pop("data", None) + data = kwargs.pop("data", None) - mac_len = kwargs.pop("mac_len", 64) - if mac_len < 8: - raise ValueError("'mac_len' must be 8 bytes or more") + mac_len = kwargs.pop("mac_len", 64) + if mac_len < 8: + raise ValueError("'mac_len' must be 8 bytes or more") - custom = kwargs.pop("custom", b"") + custom = kwargs.pop("custom", b"") - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) - return KMAC_Hash(data, key, mac_len, custom, "20", cSHAKE256, 136) + return KMAC_Hash(data, key, mac_len, custom, "20", cSHAKE256, 136) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC256.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC256.pyi index 86cc5000..a2f684b4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC256.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KMAC256.pyi @@ -4,7 +4,4 @@ from .KMAC128 import KMAC_Hash Buffer = Union[bytes, bytearray, memoryview] -def new(key: Buffer, - data: Buffer = ..., - mac_len: int = ..., - custom: Buffer = ...) -> KMAC_Hash: ... +def new(key: Buffer, data: Buffer = ..., mac_len: int = ..., custom: Buffer = ...) -> KMAC_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KangarooTwelve.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KangarooTwelve.py index 60ced572..3155ea5c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KangarooTwelve.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KangarooTwelve.py @@ -33,190 +33,189 @@ from . import TurboSHAKE128 + def _length_encode(x): - if x == 0: - return b'\x00' + if x == 0: + return b"\x00" - S = long_to_bytes(x) - return S + bchr(len(S)) + S = long_to_bytes(x) + return S + bchr(len(S)) # Possible states for a KangarooTwelve instance, which depend on the amount of data processed so far. -SHORT_MSG = 1 # Still within the first 8192 bytes, but it is not certain we will exceed them. -LONG_MSG_S0 = 2 # Still within the first 8192 bytes, and it is certain we will exceed them. -LONG_MSG_SX = 3 # Beyond the first 8192 bytes. -SQUEEZING = 4 # No more data to process. +SHORT_MSG = 1 # Still within the first 8192 bytes, but it is not certain we will exceed them. +LONG_MSG_S0 = 2 # Still within the first 8192 bytes, and it is certain we will exceed them. +LONG_MSG_SX = 3 # Beyond the first 8192 bytes. +SQUEEZING = 4 # No more data to process. class K12_XOF(object): - """A KangarooTwelve hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ - - def __init__(self, data, custom): - - if custom == None: - custom = b'' - - self._custom = custom + _length_encode(len(custom)) - self._state = SHORT_MSG - self._padding = None # Final padding is only decided in read() - - # Internal hash that consumes FinalNode - # The real domain separation byte will be known before squeezing - self._hash1 = TurboSHAKE128.new(domain=1) - self._length1 = 0 - - # Internal hash that produces CV_i (reset each time) - self._hash2 = None - self._length2 = 0 - - # Incremented by one for each 8192-byte block - self._ctr = 0 - - if data: - self.update(data) - - def update(self, data): - """Hash the next piece of data. - - .. note:: - For better performance, submit chunks with a length multiple of 8192 bytes. - - Args: - data (byte string/byte array/memoryview): The next chunk of the - message to hash. - """ - - if self._state == SQUEEZING: - raise TypeError("You cannot call 'update' after the first 'read'") - - if self._state == SHORT_MSG: - next_length = self._length1 + len(data) - - if next_length + len(self._custom) <= 8192: - self._length1 = next_length - self._hash1.update(data) - return self + """A KangarooTwelve hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ + + def __init__(self, data, custom): + if custom == None: + custom = b"" + + self._custom = custom + _length_encode(len(custom)) + self._state = SHORT_MSG + self._padding = None # Final padding is only decided in read() + + # Internal hash that consumes FinalNode + # The real domain separation byte will be known before squeezing + self._hash1 = TurboSHAKE128.new(domain=1) + self._length1 = 0 - # Switch to tree hashing - self._state = LONG_MSG_S0 + # Internal hash that produces CV_i (reset each time) + self._hash2 = None + self._length2 = 0 - if self._state == LONG_MSG_S0: - data_mem = memoryview(data) - assert(self._length1 < 8192) - dtc = min(len(data), 8192 - self._length1) - self._hash1.update(data_mem[:dtc]) - self._length1 += dtc + # Incremented by one for each 8192-byte block + self._ctr = 0 + + if data: + self.update(data) + + def update(self, data): + """Hash the next piece of data. - if self._length1 < 8192: - return self + .. note:: + For better performance, submit chunks with a length multiple of 8192 bytes. + + Args: + data (byte string/byte array/memoryview): The next chunk of the + message to hash. + """ + + if self._state == SQUEEZING: + raise TypeError("You cannot call 'update' after the first 'read'") + + if self._state == SHORT_MSG: + next_length = self._length1 + len(data) + + if next_length + len(self._custom) <= 8192: + self._length1 = next_length + self._hash1.update(data) + return self + + # Switch to tree hashing + self._state = LONG_MSG_S0 - # Finish hashing S_0 and start S_1 - assert(self._length1 == 8192) + if self._state == LONG_MSG_S0: + data_mem = memoryview(data) + assert self._length1 < 8192 + dtc = min(len(data), 8192 - self._length1) + self._hash1.update(data_mem[:dtc]) + self._length1 += dtc - divider = b'\x03' + b'\x00' * 7 - self._hash1.update(divider) - self._length1 += 8 + if self._length1 < 8192: + return self - self._hash2 = TurboSHAKE128.new(domain=0x0B) - self._length2 = 0 - self._ctr = 1 + # Finish hashing S_0 and start S_1 + assert self._length1 == 8192 - self._state = LONG_MSG_SX - return self.update(data_mem[dtc:]) + divider = b"\x03" + b"\x00" * 7 + self._hash1.update(divider) + self._length1 += 8 - # LONG_MSG_SX - assert(self._state == LONG_MSG_SX) - index = 0 - len_data = len(data) + self._hash2 = TurboSHAKE128.new(domain=0x0B) + self._length2 = 0 + self._ctr = 1 - # All iteractions could actually run in parallel - data_mem = memoryview(data) - while index < len_data: + self._state = LONG_MSG_SX + return self.update(data_mem[dtc:]) - new_index = min(index + 8192 - self._length2, len_data) - self._hash2.update(data_mem[index:new_index]) - self._length2 += new_index - index - index = new_index + # LONG_MSG_SX + assert self._state == LONG_MSG_SX + index = 0 + len_data = len(data) - if self._length2 == 8192: - cv_i = self._hash2.read(32) - self._hash1.update(cv_i) - self._length1 += 32 - self._hash2._reset() - self._length2 = 0 - self._ctr += 1 + # All iteractions could actually run in parallel + data_mem = memoryview(data) + while index < len_data: + new_index = min(index + 8192 - self._length2, len_data) + self._hash2.update(data_mem[index:new_index]) + self._length2 += new_index - index + index = new_index - return self + if self._length2 == 8192: + cv_i = self._hash2.read(32) + self._hash1.update(cv_i) + self._length1 += 32 + self._hash2._reset() + self._length2 = 0 + self._ctr += 1 - def read(self, length): - """ - Produce more bytes of the digest. + return self - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. + def read(self, length): + """ + Produce more bytes of the digest. - Args: - length (integer): the amount of bytes this method must return + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ + Args: + length (integer): the amount of bytes this method must return - custom_was_consumed = False + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ - if self._state == SHORT_MSG: - self._hash1.update(self._custom) - self._padding = 0x07 - self._state = SQUEEZING + custom_was_consumed = False - if self._state == LONG_MSG_S0: - self.update(self._custom) - custom_was_consumed = True - assert(self._state == LONG_MSG_SX) + if self._state == SHORT_MSG: + self._hash1.update(self._custom) + self._padding = 0x07 + self._state = SQUEEZING - if self._state == LONG_MSG_SX: - if not custom_was_consumed: - self.update(self._custom) + if self._state == LONG_MSG_S0: + self.update(self._custom) + custom_was_consumed = True + assert self._state == LONG_MSG_SX - # Is there still some leftover data in hash2? - if self._length2 > 0: - cv_i = self._hash2.read(32) - self._hash1.update(cv_i) - self._length1 += 32 - self._hash2._reset() - self._length2 = 0 - self._ctr += 1 + if self._state == LONG_MSG_SX: + if not custom_was_consumed: + self.update(self._custom) - trailer = _length_encode(self._ctr - 1) + b'\xFF\xFF' - self._hash1.update(trailer) + # Is there still some leftover data in hash2? + if self._length2 > 0: + cv_i = self._hash2.read(32) + self._hash1.update(cv_i) + self._length1 += 32 + self._hash2._reset() + self._length2 = 0 + self._ctr += 1 - self._padding = 0x06 - self._state = SQUEEZING + trailer = _length_encode(self._ctr - 1) + b"\xff\xff" + self._hash1.update(trailer) - self._hash1._domain = self._padding - return self._hash1.read(length) + self._padding = 0x06 + self._state = SQUEEZING + + self._hash1._domain = self._padding + return self._hash1.read(length) - def new(self, data=None, custom=b''): - return type(self)(data, custom) + def new(self, data=None, custom=b""): + return type(self)(data, custom) def new(data=None, custom=None): - """Return a fresh instance of a KangarooTwelve object. + """Return a fresh instance of a KangarooTwelve object. - Args: - data (bytes/bytearray/memoryview): - Optional. - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - custom (bytes): - Optional. - A customization byte string. + Args: + data (bytes/bytearray/memoryview): + Optional. + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + custom (bytes): + Optional. + A customization byte string. - :Return: A :class:`K12_XOF` object - """ + :Return: A :class:`K12_XOF` object + """ - return K12_XOF(data, custom) + return K12_XOF(data, custom) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KangarooTwelve.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KangarooTwelve.pyi index 8b3fd74f..acf09644 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KangarooTwelve.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/KangarooTwelve.pyi @@ -3,14 +3,9 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class K12_XOF(object): - def __init__(self, - data: Optional[Buffer] = ..., - custom: Optional[bytes] = ...) -> None: ... - def update(self, data: Buffer) -> K12_XOF: ... - def read(self, length: int) -> bytes: ... - def new(self, - data: Optional[Buffer] = ..., - custom: Optional[bytes] = ...) -> None: ... + def __init__(self, data: Optional[Buffer] = ..., custom: Optional[bytes] = ...) -> None: ... + def update(self, data: Buffer) -> K12_XOF: ... + def read(self, length: int) -> bytes: ... + def new(self, data: Optional[Buffer] = ..., custom: Optional[bytes] = ...) -> None: ... -def new(data: Optional[Buffer] = ..., - custom: Optional[Buffer] = ...) -> K12_XOF: ... +def new(data: Optional[Buffer] = ..., custom: Optional[Buffer] = ...) -> K12_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD2.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD2.py index 47ecc05f..9792e682 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD2.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD2.py @@ -30,15 +30,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) _raw_md2_lib = load_pycryptodome_raw_lib( - "Cryptodome.Hash._MD2", - """ + "Cryptodome.Hash._MD2", + """ int md2_init(void **shaState); int md2_destroy(void *shaState); int md2_update(void *hs, @@ -47,117 +51,130 @@ int md2_digest(const void *shaState, uint8_t digest[20]); int md2_copy(const void *src, void *dst); - """) + """, +) class MD2Hash(object): - """An MD2 hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 16 - # The internal block size of the hash algorithm in bytes. - block_size = 16 - # ASN.1 Object ID - oid = "1.2.840.113549.2.2" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_md2_lib.md2_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating MD2" - % result) - self._state = SmartPointer(state.get(), - _raw_md2_lib.md2_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_md2_lib.md2_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating MD2" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_md2_lib.md2_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating MD2" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = MD2Hash() - result = _raw_md2_lib.md2_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying MD2" % result) - return clone - - def new(self, data=None): - return MD2Hash(data) + """An MD2 hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 16 + # The internal block size of the hash algorithm in bytes. + block_size = 16 + # ASN.1 Object ID + oid = "1.2.840.113549.2.2" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_md2_lib.md2_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating MD2" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_md2_lib.md2_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_md2_lib.md2_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating MD2" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_md2_lib.md2_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating MD2" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = MD2Hash() + result = _raw_md2_lib.md2_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying MD2" % result) + return clone + + def new(self, data=None): + return MD2Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`MD2Hash.update`. - :type data: bytes/bytearray/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`MD2Hash.update`. + :type data: bytes/bytearray/memoryview - :Return: A :class:`MD2Hash` hash object - """ + :Return: A :class:`MD2Hash` hash object + """ + + return MD2Hash().new(data) - return MD2Hash().new(data) # The size of the resulting hash in bytes. digest_size = MD2Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD2.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD2.pyi index 95a97a9e..8b1425f0 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD2.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD2.pyi @@ -3,17 +3,18 @@ from typing import Union Buffer = Union[bytes, bytearray, memoryview] class MD4Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Buffer = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> MD4Hash: ... - def new(self, data: Buffer = ...) -> MD4Hash: ... + def __init__(self, data: Buffer = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> MD4Hash: ... + def new(self, data: Buffer = ...) -> MD4Hash: ... def new(data: Buffer = ...) -> MD4Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD4.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD4.py index 668fa653..ce7224c4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD4.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD4.py @@ -45,15 +45,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) _raw_md4_lib = load_pycryptodome_raw_lib( - "Cryptodome.Hash._MD4", - """ + "Cryptodome.Hash._MD4", + """ int md4_init(void **shaState); int md4_destroy(void *shaState); int md4_update(void *hs, @@ -62,121 +66,133 @@ int md4_digest(const void *shaState, uint8_t digest[20]); int md4_copy(const void *src, void *dst); - """) + """, +) class MD4Hash(object): - """Class that implements an MD4 hash - """ - - #: The size of the resulting hash in bytes. - digest_size = 16 - #: The internal block size of the hash algorithm in bytes. - block_size = 64 - #: ASN.1 Object ID - oid = "1.2.840.113549.2.4" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_md4_lib.md4_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating MD4" - % result) - self._state = SmartPointer(state.get(), - _raw_md4_lib.md4_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Repeated calls are equivalent to a single call with the concatenation - of all the arguments. In other words: - - >>> m.update(a); m.update(b) - - is equivalent to: - - >>> m.update(a+b) - - :Parameters: - data : byte string/byte array/memoryview - The next chunk of the message being hashed. - """ - - result = _raw_md4_lib.md4_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating MD4" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that - has been hashed so far. - - This method does not change the state of the hash object. - You can continue updating the object after calling this function. - - :Return: A byte string of `digest_size` bytes. It may contain non-ASCII - characters, including null bytes. - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_md4_lib.md4_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating MD4" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been - hashed so far. - - This method does not change the state of the hash object. - - :Return: A string of 2* `digest_size` characters. It contains only - hexadecimal ASCII digits. - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :Return: A hash object of the same type - """ - - clone = MD4Hash() - result = _raw_md4_lib.md4_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying MD4" % result) - return clone - - def new(self, data=None): - return MD4Hash(data) + """Class that implements an MD4 hash""" + + #: The size of the resulting hash in bytes. + digest_size = 16 + #: The internal block size of the hash algorithm in bytes. + block_size = 64 + #: ASN.1 Object ID + oid = "1.2.840.113549.2.4" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_md4_lib.md4_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating MD4" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_md4_lib.md4_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Repeated calls are equivalent to a single call with the concatenation + of all the arguments. In other words: + + >>> m.update(a); m.update(b) + + is equivalent to: + + >>> m.update(a+b) + + :Parameters: + data : byte string/byte array/memoryview + The next chunk of the message being hashed. + """ + + result = _raw_md4_lib.md4_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating MD4" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that + has been hashed so far. + + This method does not change the state of the hash object. + You can continue updating the object after calling this function. + + :Return: A byte string of `digest_size` bytes. It may contain non-ASCII + characters, including null bytes. + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_md4_lib.md4_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating MD4" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been + hashed so far. + + This method does not change the state of the hash object. + + :Return: A string of 2* `digest_size` characters. It contains only + hexadecimal ASCII digits. + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :Return: A hash object of the same type + """ + + clone = MD4Hash() + result = _raw_md4_lib.md4_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying MD4" % result) + return clone + + def new(self, data=None): + return MD4Hash(data) def new(data=None): - """Return a fresh instance of the hash object. + """Return a fresh instance of the hash object. + + :Parameters: + data : byte string/byte array/memoryview + The very first chunk of the message to hash. + It is equivalent to an early call to `MD4Hash.update()`. + Optional. - :Parameters: - data : byte string/byte array/memoryview - The very first chunk of the message to hash. - It is equivalent to an early call to `MD4Hash.update()`. - Optional. + :Return: A `MD4Hash` object + """ + return MD4Hash().new(data) - :Return: A `MD4Hash` object - """ - return MD4Hash().new(data) #: The size of the resulting hash in bytes. digest_size = MD4Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD4.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD4.pyi index a9a72953..9f79ebde 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD4.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD4.pyi @@ -3,17 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class MD4Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> MD4Hash: ... - def new(self, data: Optional[Buffer] = ...) -> MD4Hash: ... + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> MD4Hash: ... + def new(self, data: Optional[Buffer] = ...) -> MD4Hash: ... def new(data: Optional[Buffer] = ...) -> MD4Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD5.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD5.py index 8f573a9b..d02a162f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD5.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD5.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import * -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_md5_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._MD5", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_md5_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._MD5", + """ #define MD5_DIGEST_SIZE 16 int MD5_init(void **shaState); @@ -44,118 +49,132 @@ const uint8_t first_digest[MD5_DIGEST_SIZE], uint8_t final_digest[MD5_DIGEST_SIZE], size_t iterations); - """) + """, +) + class MD5Hash(object): - """A MD5 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 16 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "1.2.840.113549.2.5" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_md5_lib.MD5_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating MD5" - % result) - self._state = SmartPointer(state.get(), - _raw_md5_lib.MD5_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_md5_lib.MD5_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating MD5" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_md5_lib.MD5_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating MD5" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = MD5Hash() - result = _raw_md5_lib.MD5_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying MD5" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-1 hash object.""" - - return MD5Hash(data) + """A MD5 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 16 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "1.2.840.113549.2.5" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_md5_lib.MD5_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating MD5" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_md5_lib.MD5_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_md5_lib.MD5_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating MD5" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_md5_lib.MD5_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating MD5" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = MD5Hash() + result = _raw_md5_lib.MD5_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying MD5" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-1 hash object.""" + + return MD5Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. + + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`MD5Hash.update`. + :type data: byte string/byte array/memoryview - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`MD5Hash.update`. - :type data: byte string/byte array/memoryview + :Return: A :class:`MD5Hash` hash object + """ + return MD5Hash().new(data) - :Return: A :class:`MD5Hash` hash object - """ - return MD5Hash().new(data) # The size of the resulting hash in bytes. digest_size = 16 @@ -165,20 +184,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert len(first_digest) == digest_size - assert iterations > 0 + assert len(first_digest) == digest_size + assert iterations > 0 - bfr = create_string_buffer(digest_size); - result = _raw_md5_lib.MD5_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations)) + bfr = create_string_buffer(digest_size) + result = _raw_md5_lib.MD5_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assis for MD5" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assis for MD5" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD5.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD5.pyi index d8195562..a8b7e084 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD5.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/MD5.pyi @@ -3,17 +3,18 @@ from typing import Union Buffer = Union[bytes, bytearray, memoryview] class MD5Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Buffer = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> MD5Hash: ... - def new(self, data: Buffer = ...) -> MD5Hash: ... + def __init__(self, data: Buffer = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> MD5Hash: ... + def new(self, data: Buffer = ...) -> MD5Hash: ... def new(data: Buffer = ...) -> MD5Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/Poly1305.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/Poly1305.py index c03f5229..993bfda1 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/Poly1305.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/Poly1305.py @@ -26,15 +26,20 @@ from Cryptodome.Hash import BLAKE2s from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - - -_raw_poly1305 = load_pycryptodome_raw_lib("Cryptodome.Hash._poly1305", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + + +_raw_poly1305 = load_pycryptodome_raw_lib( + "Cryptodome.Hash._poly1305", + """ int poly1305_init(void **state, const uint8_t *r, size_t r_len, @@ -47,171 +52,176 @@ int poly1305_digest(const void *state, uint8_t *digest, size_t len); - """) + """, +) class Poly1305_MAC(object): - """An Poly1305 MAC object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting MAC tag - :vartype digest_size: integer - """ - - digest_size = 16 - - def __init__(self, r, s, data): - - if len(r) != 16: - raise ValueError("Parameter r is not 16 bytes long") - if len(s) != 16: - raise ValueError("Parameter s is not 16 bytes long") - - self._mac_tag = None - - state = VoidPointer() - result = _raw_poly1305.poly1305_init(state.address_of(), - c_uint8_ptr(r), - c_size_t(len(r)), - c_uint8_ptr(s), - c_size_t(len(s)) - ) - if result: - raise ValueError("Error %d while instantiating Poly1305" % result) - self._state = SmartPointer(state.get(), - _raw_poly1305.poly1305_destroy) - if data: - self.update(data) - - def update(self, data): - """Authenticate the next chunk of message. - - Args: - data (byte string/byte array/memoryview): The next chunk of data - """ - - if self._mac_tag: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_poly1305.poly1305_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing Poly1305 data" % result) - return self - - def copy(self): - raise NotImplementedError() - - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message - authenticated so far. - - :return: The MAC tag digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - if self._mac_tag: - return self._mac_tag - - bfr = create_string_buffer(16) - result = _raw_poly1305.poly1305_digest(self._state.get(), - bfr, - c_size_t(len(bfr))) - if result: - raise ValueError("Error %d while creating Poly1305 digest" % result) - - self._mac_tag = get_raw_buffer(bfr) - return self._mac_tag - - def hexdigest(self): - """Return the **printable** MAC tag of the message authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) - for x in tuple(self.digest())]) - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte string/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, - as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - + """An Poly1305 MAC object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar digest_size: the size in bytes of the resulting MAC tag + :vartype digest_size: integer + """ + + digest_size = 16 + + def __init__(self, r, s, data): + if len(r) != 16: + raise ValueError("Parameter r is not 16 bytes long") + if len(s) != 16: + raise ValueError("Parameter s is not 16 bytes long") + + self._mac_tag = None + + state = VoidPointer() + result = _raw_poly1305.poly1305_init( + state.address_of(), + c_uint8_ptr(r), + c_size_t(len(r)), + c_uint8_ptr(s), + c_size_t(len(s)), + ) + if result: + raise ValueError("Error %d while instantiating Poly1305" % result) + self._state = SmartPointer( + state.get(), + _raw_poly1305.poly1305_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Authenticate the next chunk of message. + + Args: + data (byte string/byte array/memoryview): The next chunk of data + """ + + if self._mac_tag: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_poly1305.poly1305_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError("Error %d while hashing Poly1305 data" % result) + return self + + def copy(self): + raise NotImplementedError() + + def digest(self): + """Return the **binary** (non-printable) MAC tag of the message + authenticated so far. + + :return: The MAC tag digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + if self._mac_tag: + return self._mac_tag + + bfr = create_string_buffer(16) + result = _raw_poly1305.poly1305_digest( + self._state.get(), + bfr, + c_size_t(len(bfr)), + ) + if result: + raise ValueError("Error %d while creating Poly1305 digest" % result) + + self._mac_tag = get_raw_buffer(bfr) + return self._mac_tag + + def hexdigest(self): + """Return the **printable** MAC tag of the message authenticated so far. + + :return: The MAC tag, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. + + Args: + mac_tag (byte string/byte string/memoryview): the expected MAC of the message. + + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. + + Args: + hex_mac_tag (string): the expected MAC of the message, + as a hexadecimal string. + + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + self.verify(unhexlify(tobytes(hex_mac_tag))) def new(**kwargs): - """Create a new Poly1305 MAC object. - - Args: - key (bytes/bytearray/memoryview): - The 32-byte key for the Poly1305 object. - cipher (module from ``Cryptodome.Cipher``): - The cipher algorithm to use for deriving the Poly1305 - key pair *(r, s)*. - It can only be ``Cryptodome.Cipher.AES`` or ``Cryptodome.Cipher.ChaCha20``. - nonce (bytes/bytearray/memoryview): - Optional. The non-repeatable value to use for the MAC of this message. - It must be 16 bytes long for ``AES`` and 8 or 12 bytes for ``ChaCha20``. - If not passed, a random nonce is created; you will find it in the - ``nonce`` attribute of the new object. - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to ``update()``. - - Returns: - A :class:`Poly1305_MAC` object - """ - - cipher = kwargs.pop("cipher", None) - if not hasattr(cipher, '_derive_Poly1305_key_pair'): - raise ValueError("Parameter 'cipher' must be AES or ChaCha20") - - cipher_key = kwargs.pop("key", None) - if cipher_key is None: - raise TypeError("You must pass a parameter 'key'") - - nonce = kwargs.pop("nonce", None) - data = kwargs.pop("data", None) - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - r, s, nonce = cipher._derive_Poly1305_key_pair(cipher_key, nonce) - - new_mac = Poly1305_MAC(r, s, data) - new_mac.nonce = _copy_bytes(None, None, nonce) # nonce may still be just a memoryview - return new_mac + """Create a new Poly1305 MAC object. + + Args: + key (bytes/bytearray/memoryview): + The 32-byte key for the Poly1305 object. + cipher (module from ``Cryptodome.Cipher``): + The cipher algorithm to use for deriving the Poly1305 + key pair *(r, s)*. + It can only be ``Cryptodome.Cipher.AES`` or ``Cryptodome.Cipher.ChaCha20``. + nonce (bytes/bytearray/memoryview): + Optional. The non-repeatable value to use for the MAC of this message. + It must be 16 bytes long for ``AES`` and 8 or 12 bytes for ``ChaCha20``. + If not passed, a random nonce is created; you will find it in the + ``nonce`` attribute of the new object. + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to ``update()``. + + Returns: + A :class:`Poly1305_MAC` object + """ + + cipher = kwargs.pop("cipher", None) + if not hasattr(cipher, "_derive_Poly1305_key_pair"): + raise ValueError("Parameter 'cipher' must be AES or ChaCha20") + + cipher_key = kwargs.pop("key", None) + if cipher_key is None: + raise TypeError("You must pass a parameter 'key'") + + nonce = kwargs.pop("nonce", None) + data = kwargs.pop("data", None) + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + r, s, nonce = cipher._derive_Poly1305_key_pair(cipher_key, nonce) + + new_mac = Poly1305_MAC(r, s, data) + new_mac.nonce = _copy_bytes(None, None, nonce) # nonce may still be just a memoryview + return new_mac diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/Poly1305.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/Poly1305.pyi index f97a14a0..362f500a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/Poly1305.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/Poly1305.pyi @@ -4,21 +4,15 @@ from typing import Union Buffer = Union[bytes, bytearray, memoryview] class Poly1305_MAC(object): - block_size: int - digest_size: int - oid: str + block_size: int + digest_size: int + oid: str - def __init__(self, - r : int, - s : int, - data : Buffer) -> None: ... - def update(self, data: Buffer) -> Poly1305_MAC: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... + def __init__(self, r: int, s: int, data: Buffer) -> None: ... + def update(self, data: Buffer) -> Poly1305_MAC: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... -def new(key: Buffer, - cipher: ModuleType, - nonce: Buffer = ..., - data: Buffer = ...) -> Poly1305_MAC: ... +def new(key: Buffer, cipher: ModuleType, nonce: Buffer = ..., data: Buffer = ...) -> Poly1305_MAC: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD.py index 35ad576c..03717ec6 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD.py @@ -22,5 +22,3 @@ # Cryptodome.Hash.RIPEMD """Deprecated alias for `Cryptodome.Hash.RIPEMD160`""" - -from Cryptodome.Hash.RIPEMD160 import new, block_size, digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD160.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD160.py index f9590275..1487646c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD160.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD160.py @@ -30,15 +30,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) _raw_ripemd160_lib = load_pycryptodome_raw_lib( - "Cryptodome.Hash._RIPEMD160", - """ + "Cryptodome.Hash._RIPEMD160", + """ int ripemd160_init(void **shaState); int ripemd160_destroy(void *shaState); int ripemd160_update(void *hs, @@ -47,120 +51,133 @@ int ripemd160_digest(const void *shaState, uint8_t digest[20]); int ripemd160_copy(const void *src, void *dst); - """) + """, +) class RIPEMD160Hash(object): - """A RIPEMD-160 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 20 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "1.3.36.3.2.1" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_ripemd160_lib.ripemd160_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating RIPEMD160" - % result) - self._state = SmartPointer(state.get(), - _raw_ripemd160_lib.ripemd160_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_ripemd160_lib.ripemd160_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating ripemd160" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_ripemd160_lib.ripemd160_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating ripemd160" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = RIPEMD160Hash() - result = _raw_ripemd160_lib.ripemd160_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying ripemd160" % result) - return clone - - def new(self, data=None): - """Create a fresh RIPEMD-160 hash object.""" - - return RIPEMD160Hash(data) + """A RIPEMD-160 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 20 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "1.3.36.3.2.1" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_ripemd160_lib.ripemd160_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating RIPEMD160" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_ripemd160_lib.ripemd160_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_ripemd160_lib.ripemd160_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating ripemd160" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_ripemd160_lib.ripemd160_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating ripemd160" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = RIPEMD160Hash() + result = _raw_ripemd160_lib.ripemd160_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying ripemd160" % result) + return clone + + def new(self, data=None): + """Create a fresh RIPEMD-160 hash object.""" + + return RIPEMD160Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`RIPEMD160Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`RIPEMD160Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`RIPEMD160Hash` hash object - """ + :Return: A :class:`RIPEMD160Hash` hash object + """ + + return RIPEMD160Hash().new(data) - return RIPEMD160Hash().new(data) # The size of the resulting hash in bytes. digest_size = RIPEMD160Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD160.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD160.pyi index b6194737..9022e49a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD160.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/RIPEMD160.pyi @@ -3,17 +3,18 @@ from typing import Union Buffer = Union[bytes, bytearray, memoryview] class RIPEMD160Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Buffer = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> RIPEMD160Hash: ... - def new(self, data: Buffer = ...) -> RIPEMD160Hash: ... + def __init__(self, data: Buffer = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> RIPEMD160Hash: ... + def new(self, data: Buffer = ...) -> RIPEMD160Hash: ... def new(data: Buffer = ...) -> RIPEMD160Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA.py index 95f8745b..0fd021ea 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA.py @@ -21,4 +21,3 @@ # This file exists for backward compatibility with old code that refers to # Cryptodome.Hash.SHA -from Cryptodome.Hash.SHA1 import __doc__, new, block_size, digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA.pyi index 7d01a5f9..cfb22524 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA.pyi @@ -1,4 +1,3 @@ # This file exists for backward compatibility with old code that refers to # Cryptodome.Hash.SHA -from Cryptodome.Hash.SHA1 import __doc__, new, block_size, digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA1.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA1.py index dea51bce..add3b6e0 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA1.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA1.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import * -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha1_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA1", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha1_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA1", + """ #define SHA1_DIGEST_SIZE 20 int SHA1_init(void **shaState); @@ -44,118 +49,131 @@ const uint8_t first_digest[SHA1_DIGEST_SIZE], uint8_t final_digest[SHA1_DIGEST_SIZE], size_t iterations); - """) + """, +) + class SHA1Hash(object): - """A SHA-1 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 20 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "1.3.14.3.2.26" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha1_lib.SHA1_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA1" - % result) - self._state = SmartPointer(state.get(), - _raw_sha1_lib.SHA1_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha1_lib.SHA1_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating SHA1" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha1_lib.SHA1_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating SHA1" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA1Hash() - result = _raw_sha1_lib.SHA1_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA1" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-1 hash object.""" - - return SHA1Hash(data) + """A SHA-1 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 20 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "1.3.14.3.2.26" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_sha1_lib.SHA1_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating SHA1" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha1_lib.SHA1_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha1_lib.SHA1_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA1" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha1_lib.SHA1_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating SHA1" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA1Hash() + result = _raw_sha1_lib.SHA1_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA1" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-1 hash object.""" + + return SHA1Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA1Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA1Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`SHA1Hash` hash object - """ - return SHA1Hash().new(data) + :Return: A :class:`SHA1Hash` hash object + """ + return SHA1Hash().new(data) # The size of the resulting hash in bytes. @@ -166,20 +184,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert len(first_digest) == digest_size - assert iterations > 0 + assert len(first_digest) == digest_size + assert iterations > 0 - bfr = create_string_buffer(digest_size); - result = _raw_sha1_lib.SHA1_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations)) + bfr = create_string_buffer(digest_size) + result = _raw_sha1_lib.SHA1_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assis for SHA1" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assis for SHA1" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA1.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA1.pyi index d6c8e25e..6b05ebc4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA1.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA1.pyi @@ -3,17 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA1Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA1Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA1Hash: ... + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA1Hash: ... + def new(self, data: Optional[Buffer] = ...) -> SHA1Hash: ... def new(data: Optional[Buffer] = ...) -> SHA1Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA224.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA224.py index fca7622e..04a1c505 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA224.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA224.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha224_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA224", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha224_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA224", + """ int SHA224_init(void **shaState); int SHA224_destroy(void *shaState); int SHA224_update(void *hs, @@ -44,119 +49,132 @@ uint8_t *final_digest, size_t iterations, size_t digest_size); - """) + """, +) + class SHA224Hash(object): - """A SHA-224 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 28 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = '2.16.840.1.101.3.4.2.4' - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha224_lib.SHA224_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA224" - % result) - self._state = SmartPointer(state.get(), - _raw_sha224_lib.SHA224_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha224_lib.SHA224_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA224" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha224_lib.SHA224_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA224 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA224Hash() - result = _raw_sha224_lib.SHA224_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA224" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-224 hash object.""" - - return SHA224Hash(data) + """A SHA-224 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 28 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.4" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_sha224_lib.SHA224_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating SHA224" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha224_lib.SHA224_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha224_lib.SHA224_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while hashing data with SHA224" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha224_lib.SHA224_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while making SHA224 digest" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA224Hash() + result = _raw_sha224_lib.SHA224_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA224" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-224 hash object.""" + + return SHA224Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA224Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA224Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`SHA224Hash` hash object - """ - return SHA224Hash().new(data) + :Return: A :class:`SHA224Hash` hash object + """ + return SHA224Hash().new(data) # The size of the resulting hash in bytes. @@ -167,20 +185,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert iterations > 0 + assert iterations > 0 - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha224_lib.SHA224_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) + bfr = create_string_buffer(len(first_digest)) + result = _raw_sha224_lib.SHA224_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + c_size_t(len(first_digest)), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA224" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assist for SHA224" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA224.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA224.pyi index 613a7f9a..65d18ed1 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA224.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA224.pyi @@ -3,17 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA224Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA224Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA224Hash: ... + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA224Hash: ... + def new(self, data: Optional[Buffer] = ...) -> SHA224Hash: ... def new(data: Optional[Buffer] = ...) -> SHA224Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA256.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA256.py index c1a81b1d..a538ef34 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA256.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA256.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha256_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA256", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha256_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA256", + """ int SHA256_init(void **shaState); int SHA256_destroy(void *shaState); int SHA256_update(void *hs, @@ -44,118 +49,132 @@ uint8_t *final_digest, size_t iterations, size_t digest_size); - """) + """, +) + class SHA256Hash(object): - """A SHA-256 hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 32 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.1" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha256_lib.SHA256_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA256" - % result) - self._state = SmartPointer(state.get(), - _raw_sha256_lib.SHA256_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha256_lib.SHA256_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA256" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha256_lib.SHA256_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA256 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA256Hash() - result = _raw_sha256_lib.SHA256_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA256" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-256 hash object.""" - - return SHA256Hash(data) + """A SHA-256 hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 32 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.1" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_sha256_lib.SHA256_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating SHA256" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha256_lib.SHA256_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha256_lib.SHA256_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while hashing data with SHA256" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha256_lib.SHA256_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while making SHA256 digest" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA256Hash() + result = _raw_sha256_lib.SHA256_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA256" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-256 hash object.""" + + return SHA256Hash(data) + def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA256Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA256Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`SHA256Hash` hash object - """ + :Return: A :class:`SHA256Hash` hash object + """ - return SHA256Hash().new(data) + return SHA256Hash().new(data) # The size of the resulting hash in bytes. @@ -166,20 +185,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert iterations > 0 + assert iterations > 0 - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha256_lib.SHA256_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) + bfr = create_string_buffer(len(first_digest)) + result = _raw_sha256_lib.SHA256_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + c_size_t(len(first_digest)), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA256" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assist for SHA256" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA256.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA256.pyi index cbf21bfb..3521cff9 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA256.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA256.pyi @@ -1,18 +1,17 @@ from typing import Union, Optional - class SHA256Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> None: ... - def update(self, data: Union[bytes, bytearray, memoryview]) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA256Hash: ... - def new(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Union[bytes, bytearray, memoryview]] = None) -> None: ... + def update(self, data: Union[bytes, bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA256Hash: ... + def new(self, data: Optional[Union[bytes, bytearray, memoryview]] = None) -> SHA256Hash: ... -def new(data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ... +def new(data: Optional[Union[bytes, bytearray, memoryview]] = None) -> SHA256Hash: ... digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA384.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA384.py index 711aa73c..4c15f7ae 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA384.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA384.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha384_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA384", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha384_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA384", + """ int SHA384_init(void **shaState); int SHA384_destroy(void *shaState); int SHA384_update(void *hs, @@ -44,119 +49,132 @@ uint8_t *final_digest, size_t iterations, size_t digest_size); - """) + """, +) + class SHA384Hash(object): - """A SHA-384 hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 48 - # The internal block size of the hash algorithm in bytes. - block_size = 128 - # ASN.1 Object ID - oid = '2.16.840.1.101.3.4.2.2' - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha384_lib.SHA384_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA384" - % result) - self._state = SmartPointer(state.get(), - _raw_sha384_lib.SHA384_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha384_lib.SHA384_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA384" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha384_lib.SHA384_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA384 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA384Hash() - result = _raw_sha384_lib.SHA384_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA384" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-384 hash object.""" - - return SHA384Hash(data) + """A SHA-384 hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 48 + # The internal block size of the hash algorithm in bytes. + block_size = 128 + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.2" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_sha384_lib.SHA384_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating SHA384" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha384_lib.SHA384_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha384_lib.SHA384_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while hashing data with SHA384" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha384_lib.SHA384_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while making SHA384 digest" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA384Hash() + result = _raw_sha384_lib.SHA384_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA384" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-384 hash object.""" + + return SHA384Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA384Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA384Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`SHA384Hash` hash object - """ + :Return: A :class:`SHA384Hash` hash object + """ - return SHA384Hash().new(data) + return SHA384Hash().new(data) # The size of the resulting hash in bytes. @@ -167,20 +185,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert iterations > 0 + assert iterations > 0 - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha384_lib.SHA384_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) + bfr = create_string_buffer(len(first_digest)) + result = _raw_sha384_lib.SHA384_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + c_size_t(len(first_digest)), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA384" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assist for SHA384" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA384.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA384.pyi index c2aab9e0..249a6855 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA384.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA384.pyi @@ -3,17 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA384Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA384Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA384Hash: ... + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA384Hash: ... + def new(self, data: Optional[Buffer] = ...) -> SHA384Hash: ... def new(data: Optional[Buffer] = ...) -> SHA384Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_224.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_224.py index 34888c56..bcac372c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_224.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_224.py @@ -20,152 +20,170 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib -class SHA3_224_Hash(object): - """A SHA3-224 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 28 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.7" - - # Input block size for HMAC - block_size = 144 - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x06 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHA-3/224" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data)) - ) - if result: - raise ValueError("Error %d while updating SHA-3/224" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while instantiating SHA-3/224" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA3-224" % result) - return clone - def new(self, data=None): - """Create a fresh SHA3-224 hash object.""" - - return type(self)(data, self._update_after_digest) +class SHA3_224_Hash(object): + """A SHA3-224 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 28 + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.7" + + # Input block size for HMAC + block_size = 144 + + def __init__(self, data, update_after_digest): + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x06 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/224" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHA-3/224" % result, + ) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/224" % result, + ) + + self._digest_value = get_raw_buffer(bfr) + return self._digest_value + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA3-224" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA3-224 hash object.""" + + return type(self)(data, self._update_after_digest) def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_224_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_224_Hash(data, update_after_digest) + """Create a new hash object. + + Args: + data (byte string/byte array/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + update_after_digest (boolean): + Whether :meth:`digest` can be followed by another :meth:`update` + (default: ``False``). + + :Return: A :class:`SHA3_224_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + if len(args) == 1: + if data: + raise ValueError("Initial data for hash specified twice") + data = args[0] + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return SHA3_224_Hash(data, update_after_digest) + # The size of the resulting hash in bytes. digest_size = SHA3_224_Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_224.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_224.pyi index 21808219..3f3896ea 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_224.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_224.pyi @@ -3,15 +3,15 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA3_224_Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_224_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA3_224_Hash: ... - def new(self, data: Optional[Buffer]) -> SHA3_224_Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> SHA3_224_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA3_224_Hash: ... + def new(self, data: Optional[Buffer]) -> SHA3_224_Hash: ... def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_224_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_256.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_256.py index 024962fa..a0b99c01 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_256.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_256.py @@ -20,152 +20,170 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib -class SHA3_256_Hash(object): - """A SHA3-256 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 32 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.8" - - # Input block size for HMAC - block_size = 136 - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x06 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHA-3/256" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data)) - ) - if result: - raise ValueError("Error %d while updating SHA-3/256" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while instantiating SHA-3/256" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA3-256" % result) - return clone - def new(self, data=None): - """Create a fresh SHA3-256 hash object.""" - - return type(self)(data, self._update_after_digest) +class SHA3_256_Hash(object): + """A SHA3-256 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 32 + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.8" + + # Input block size for HMAC + block_size = 136 + + def __init__(self, data, update_after_digest): + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x06 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/256" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHA-3/256" % result, + ) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/256" % result, + ) + + self._digest_value = get_raw_buffer(bfr) + return self._digest_value + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA3-256" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA3-256 hash object.""" + + return type(self)(data, self._update_after_digest) def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_256_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_256_Hash(data, update_after_digest) + """Create a new hash object. + + Args: + data (byte string/byte array/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + update_after_digest (boolean): + Whether :meth:`digest` can be followed by another :meth:`update` + (default: ``False``). + + :Return: A :class:`SHA3_256_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + if len(args) == 1: + if data: + raise ValueError("Initial data for hash specified twice") + data = args[0] + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return SHA3_256_Hash(data, update_after_digest) + # The size of the resulting hash in bytes. digest_size = SHA3_256_Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_256.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_256.pyi index 88436bd8..731c6229 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_256.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_256.pyi @@ -3,15 +3,15 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA3_256_Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_256_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA3_256_Hash: ... - def new(self, data: Optional[Buffer]) -> SHA3_256_Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> SHA3_256_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA3_256_Hash: ... + def new(self, data: Optional[Buffer]) -> SHA3_256_Hash: ... def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_256_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_384.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_384.py index 26eeb791..227fd234 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_384.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_384.py @@ -20,157 +20,175 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib -class SHA3_384_Hash(object): - """A SHA3-384 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 48 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.9" - - # Input block size for HMAC - block_size = 104 - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x06 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHA-3/384" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHA-3/384" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while instantiating SHA-3/384" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ +class SHA3_384_Hash(object): + """A SHA3-384 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 48 + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.9" + + # Input block size for HMAC + block_size = 104 + + def __init__(self, data, update_after_digest): + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x06 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/384" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHA-3/384" % result, + ) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/384" % result, + ) + + self._digest_value = get_raw_buffer(bfr) + return self._digest_value + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA3-384" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA3-256 hash object.""" + + return type(self)(data, self._update_after_digest) + + def new(self, data=None): + """Create a fresh SHA3-384 hash object.""" + + return type(self)(data, self._update_after_digest) - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA3-384" % result) - return clone - def new(self, data=None): - """Create a fresh SHA3-256 hash object.""" +def new(*args, **kwargs): + """Create a new hash object. - return type(self)(data, self._update_after_digest) + Args: + data (byte string/byte array/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + update_after_digest (boolean): + Whether :meth:`digest` can be followed by another :meth:`update` + (default: ``False``). + :Return: A :class:`SHA3_384_Hash` hash object + """ - def new(self, data=None): - """Create a fresh SHA3-384 hash object.""" + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + if len(args) == 1: + if data: + raise ValueError("Initial data for hash specified twice") + data = args[0] - return type(self)(data, self._update_after_digest) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + return SHA3_384_Hash(data, update_after_digest) -def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_384_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_384_Hash(data, update_after_digest) # The size of the resulting hash in bytes. digest_size = SHA3_384_Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_384.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_384.pyi index 98d00c6c..2f35bde4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_384.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_384.pyi @@ -3,15 +3,15 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA3_384_Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_384_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA3_384_Hash: ... - def new(self, data: Optional[Buffer]) -> SHA3_384_Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> SHA3_384_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA3_384_Hash: ... + def new(self, data: Optional[Buffer]) -> SHA3_384_Hash: ... def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_384_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_512.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_512.py index 99b1c37a..23e0c45c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_512.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_512.py @@ -20,152 +20,170 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib -class SHA3_512_Hash(object): - """A SHA3-512 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 64 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.10" - - # Input block size for HMAC - block_size = 72 - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x06 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHA-3/512" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHA-3/512" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while instantiating SHA-3/512" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) +class SHA3_512_Hash(object): + """A SHA3-512 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 64 + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.10" + + # Input block size for HMAC + block_size = 72 + + def __init__(self, data, update_after_digest): + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x06 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/512" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHA-3/512" % result, + ) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/512" % result, + ) + + self._digest_value = get_raw_buffer(bfr) + return self._digest_value + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA3-512" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA3-521 hash object.""" + + return type(self)(data, self._update_after_digest) - def copy(self): - """Return a copy ("clone") of the hash object. - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. +def new(*args, **kwargs): + """Create a new hash object. - :return: A hash object of the same type - """ + Args: + data (byte string/byte array/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + update_after_digest (boolean): + Whether :meth:`digest` can be followed by another :meth:`update` + (default: ``False``). - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA3-512" % result) - return clone + :Return: A :class:`SHA3_512_Hash` hash object + """ - def new(self, data=None): - """Create a fresh SHA3-521 hash object.""" + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + if len(args) == 1: + if data: + raise ValueError("Initial data for hash specified twice") + data = args[0] - return type(self)(data, self._update_after_digest) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + return SHA3_512_Hash(data, update_after_digest) -def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_512_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_512_Hash(data, update_after_digest) # The size of the resulting hash in bytes. digest_size = SHA3_512_Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_512.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_512.pyi index cdeec165..79ff19fc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_512.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA3_512.pyi @@ -3,15 +3,15 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA3_512_Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_512_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA3_512_Hash: ... - def new(self, data: Optional[Buffer]) -> SHA3_512_Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> SHA3_512_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA3_512_Hash: ... + def new(self, data: Optional[Buffer]) -> SHA3_512_Hash: ... def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_512_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA512.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA512.py index 5066197a..e9bb53a9 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA512.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA512.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha512_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA512", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha512_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA512", + """ int SHA512_init(void **shaState, size_t digest_size); int SHA512_destroy(void *shaState); @@ -45,136 +50,151 @@ uint8_t *final_digest, size_t iterations, size_t digest_size); - """) + """, +) + class SHA512Hash(object): - """A SHA-512 hash object (possibly in its truncated version SHA-512/224 or - SHA-512/256. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The internal block size of the hash algorithm in bytes. - block_size = 128 - - def __init__(self, data, truncate): - self._truncate = truncate - - if truncate is None: - self.oid = "2.16.840.1.101.3.4.2.3" - self.digest_size = 64 - elif truncate == "224": - self.oid = "2.16.840.1.101.3.4.2.5" - self.digest_size = 28 - elif truncate == "256": - self.oid = "2.16.840.1.101.3.4.2.6" - self.digest_size = 32 - else: - raise ValueError("Incorrect truncation length. It must be '224' or '256'.") - - state = VoidPointer() - result = _raw_sha512_lib.SHA512_init(state.address_of(), - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while instantiating SHA-512" - % result) - self._state = SmartPointer(state.get(), - _raw_sha512_lib.SHA512_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha512_lib.SHA512_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA512" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha512_lib.SHA512_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA512 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA512Hash(None, self._truncate) - result = _raw_sha512_lib.SHA512_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA512" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-512 hash object.""" - - return SHA512Hash(data, self._truncate) + """A SHA-512 hash object (possibly in its truncated version SHA-512/224 or + SHA-512/256. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The internal block size of the hash algorithm in bytes. + block_size = 128 + + def __init__(self, data, truncate): + self._truncate = truncate + + if truncate is None: + self.oid = "2.16.840.1.101.3.4.2.3" + self.digest_size = 64 + elif truncate == "224": + self.oid = "2.16.840.1.101.3.4.2.5" + self.digest_size = 28 + elif truncate == "256": + self.oid = "2.16.840.1.101.3.4.2.6" + self.digest_size = 32 + else: + raise ValueError("Incorrect truncation length. It must be '224' or '256'.") + + state = VoidPointer() + result = _raw_sha512_lib.SHA512_init( + state.address_of(), + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-512" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha512_lib.SHA512_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha512_lib.SHA512_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while hashing data with SHA512" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha512_lib.SHA512_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while making SHA512 digest" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA512Hash(None, self._truncate) + result = _raw_sha512_lib.SHA512_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA512" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-512 hash object.""" + + return SHA512Hash(data, self._truncate) def new(data=None, truncate=None): - """Create a new hash object. + """Create a new hash object. - Args: - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA512Hash.update`. - truncate (string): - Optional. The desired length of the digest. It can be either "224" or - "256". If not present, the digest is 512 bits long. - Passing this parameter is **not** equivalent to simply truncating - the output digest. + Args: + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA512Hash.update`. + truncate (string): + Optional. The desired length of the digest. It can be either "224" or + "256". If not present, the digest is 512 bits long. + Passing this parameter is **not** equivalent to simply truncating + the output digest. - :Return: A :class:`SHA512Hash` hash object - """ + :Return: A :class:`SHA512Hash` hash object + """ - return SHA512Hash(data, truncate) + return SHA512Hash(data, truncate) # The size of the full SHA-512 hash in bytes. @@ -185,20 +205,21 @@ def new(data=None, truncate=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert iterations > 0 + assert iterations > 0 - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha512_lib.SHA512_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) + bfr = create_string_buffer(len(first_digest)) + result = _raw_sha512_lib.SHA512_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + c_size_t(len(first_digest)), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA512" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assist for SHA512" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA512.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA512.pyi index f219ee94..7b7f7c29 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA512.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHA512.pyi @@ -3,20 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA512Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, - data: Optional[Buffer], - truncate: Optional[str]) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA512Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA512Hash: ... + def __init__(self, data: Optional[Buffer], truncate: Optional[str]) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA512Hash: ... + def new(self, data: Optional[Buffer] = ...) -> SHA512Hash: ... + +def new(data: Optional[Buffer] = ..., truncate: Optional[str] = ...) -> SHA512Hash: ... -def new(data: Optional[Buffer] = ..., - truncate: Optional[str] = ...) -> SHA512Hash: ... digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE128.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE128.py index 847b5141..6e9dbb06 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE128.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE128.py @@ -28,118 +28,135 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib + class SHAKE128_XOF(object): - """A SHAKE128 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - """ - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.11" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(32), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHAKE128" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - self._is_squeezing = False - self._padding = 0x1F - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHAKE128 state" - % result) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while extracting from SHAKE128" - % result) - - return get_raw_buffer(bfr) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - - :return: A hash object of the same type - """ - - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHAKE128" % result) - return clone - - def new(self, data=None): - return type(self)(data=data) + """A SHAKE128 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + """ + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.11" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(32), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHAKE128" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + self._is_squeezing = False + self._padding = 0x1F + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._is_squeezing: + raise TypeError("You cannot call 'update' after the first 'read'") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHAKE128 state" % result, + ) + return self + + def read(self, length): + """ + Compute the next piece of XOF output. + + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. + + Args: + length (integer): the amount of bytes this method must return + + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ + + self._is_squeezing = True + bfr = create_string_buffer(length) + result = _raw_keccak_lib.keccak_squeeze( + self._state.get(), + bfr, + c_size_t(length), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while extracting from SHAKE128" % result, + ) + + return get_raw_buffer(bfr) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHAKE128" % result) + return clone + + def new(self, data=None): + return type(self)(data=data) def new(data=None): - """Return a fresh instance of a SHAKE128 object. + """Return a fresh instance of a SHAKE128 object. - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - Optional. + Args: + data (bytes/bytearray/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + Optional. - :Return: A :class:`SHAKE128_XOF` object - """ + :Return: A :class:`SHAKE128_XOF` object + """ - return SHAKE128_XOF(data=data) + return SHAKE128_XOF(data=data) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE128.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE128.pyi index de51d8ea..c585628f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE128.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE128.pyi @@ -3,12 +3,11 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHAKE128_XOF(object): - oid: str - def __init__(self, - data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> SHAKE128_XOF: ... - def read(self, length: int) -> bytes: ... - def copy(self) -> SHAKE128_XOF: ... - def new(self, data: Optional[Buffer] = ...) -> SHAKE128_XOF: ... + oid: str + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> SHAKE128_XOF: ... + def read(self, length: int) -> bytes: ... + def copy(self) -> SHAKE128_XOF: ... + def new(self, data: Optional[Buffer] = ...) -> SHAKE128_XOF: ... def new(data: Optional[Buffer] = ...) -> SHAKE128_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE256.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE256.py index 637044eb..2623852f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE256.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE256.py @@ -28,119 +28,136 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib + class SHAKE256_XOF(object): - """A SHAKE256 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - """ - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.12" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(64), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHAKE256" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - self._is_squeezing = False - self._padding = 0x1F - - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHAKE256 state" - % result) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while extracting from SHAKE256" - % result) - - return get_raw_buffer(bfr) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - - :return: A hash object of the same type - """ - - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHAKE256" % result) - return clone - - def new(self, data=None): - return type(self)(data=data) + """A SHAKE256 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + """ + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.12" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(64), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHAKE256" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + self._is_squeezing = False + self._padding = 0x1F + + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._is_squeezing: + raise TypeError("You cannot call 'update' after the first 'read'") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHAKE256 state" % result, + ) + return self + + def read(self, length): + """ + Compute the next piece of XOF output. + + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. + + Args: + length (integer): the amount of bytes this method must return + + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ + + self._is_squeezing = True + bfr = create_string_buffer(length) + result = _raw_keccak_lib.keccak_squeeze( + self._state.get(), + bfr, + c_size_t(length), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while extracting from SHAKE256" % result, + ) + + return get_raw_buffer(bfr) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHAKE256" % result) + return clone + + def new(self, data=None): + return type(self)(data=data) def new(data=None): - """Return a fresh instance of a SHAKE256 object. + """Return a fresh instance of a SHAKE256 object. - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - Optional. + Args: + data (bytes/bytearray/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + Optional. - :Return: A :class:`SHAKE256_XOF` object - """ + :Return: A :class:`SHAKE256_XOF` object + """ - return SHAKE256_XOF(data=data) + return SHAKE256_XOF(data=data) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE256.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE256.pyi index 72eb8985..3660833d 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE256.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/SHAKE256.pyi @@ -3,12 +3,11 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHAKE256_XOF(object): - oid: str - def __init__(self, - data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> SHAKE256_XOF: ... - def read(self, length: int) -> bytes: ... - def copy(self) -> SHAKE256_XOF: ... - def new(self, data: Optional[Buffer] = ...) -> SHAKE256_XOF: ... + oid: str + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> SHAKE256_XOF: ... + def read(self, length: int) -> bytes: ... + def copy(self) -> SHAKE256_XOF: ... + def new(self, data: Optional[Buffer] = ...) -> SHAKE256_XOF: ... def new(data: Optional[Buffer] = ...) -> SHAKE256_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash128.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash128.py index 49aeccc5..a5677c14 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash128.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash128.py @@ -28,109 +28,109 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util.py3compat import bord, is_bytes, tobytes +from Cryptodome.Util.py3compat import bord, is_bytes from . import cSHAKE128 from .cSHAKE128 import _encode_str, _right_encode class TupleHash(object): - """A Tuple hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ + """A Tuple hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ - def __init__(self, custom, cshake, digest_size): + def __init__(self, custom, cshake, digest_size): + self.digest_size = digest_size - self.digest_size = digest_size + self._cshake = cshake._new(b"", custom, b"TupleHash") + self._digest = None - self._cshake = cshake._new(b'', custom, b'TupleHash') - self._digest = None + def update(self, *data): + """Authenticate the next tuple of byte strings. + TupleHash guarantees the logical separation between each byte string. - def update(self, *data): - """Authenticate the next tuple of byte strings. - TupleHash guarantees the logical separation between each byte string. + Args: + data (bytes/bytearray/memoryview): One or more items to hash. + """ - Args: - data (bytes/bytearray/memoryview): One or more items to hash. - """ + if self._digest is not None: + raise TypeError("You cannot call 'update' after 'digest' or 'hexdigest'") - if self._digest is not None: - raise TypeError("You cannot call 'update' after 'digest' or 'hexdigest'") + for item in data: + if not is_bytes(item): + raise TypeError("You can only call 'update' on bytes") + self._cshake.update(_encode_str(item)) - for item in data: - if not is_bytes(item): - raise TypeError("You can only call 'update' on bytes" ) - self._cshake.update(_encode_str(item)) + return self - return self + def digest(self): + """Return the **binary** (non-printable) digest of the tuple of byte strings. - def digest(self): - """Return the **binary** (non-printable) digest of the tuple of byte strings. + :return: The hash digest. Binary form. + :rtype: byte string + """ - :return: The hash digest. Binary form. - :rtype: byte string - """ + if self._digest is None: + self._cshake.update(_right_encode(self.digest_size * 8)) + self._digest = self._cshake.read(self.digest_size) - if self._digest is None: - self._cshake.update(_right_encode(self.digest_size * 8)) - self._digest = self._cshake.read(self.digest_size) + return self._digest - return self._digest + def hexdigest(self): + """Return the **printable** digest of the tuple of byte strings. - def hexdigest(self): - """Return the **printable** digest of the tuple of byte strings. + :return: The hash digest. Hexadecimal encoded. + :rtype: string + """ - :return: The hash digest. Hexadecimal encoded. - :rtype: string - """ + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + def new(self, **kwargs): + """Return a new instance of a TupleHash object. + See :func:`new`. + """ - def new(self, **kwargs): - """Return a new instance of a TupleHash object. - See :func:`new`. - """ + if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: + kwargs["digest_bytes"] = self.digest_size - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) + return new(**kwargs) def new(**kwargs): - """Create a new TupleHash128 object. - - Args: - digest_bytes (integer): - Optional. The size of the digest, in bytes. - Default is 64. Minimum is 8. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (and in steps of 8). - Default is 512. Minimum is 64. - custom (bytes): - Optional. - A customization bytestring (``S`` in SP 800-185). - - :Return: A :class:`TupleHash` object - """ - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 64 - if digest_bytes is not None: - if digest_bytes < 8: - raise ValueError("'digest_bytes' must be at least 8") - else: - if digest_bits < 64 or digest_bits % 8: - raise ValueError("'digest_bytes' must be at least 64 " - "in steps of 8") - digest_bytes = digest_bits // 8 - - custom = kwargs.pop("custom", b'') - - return TupleHash(custom, cSHAKE128, digest_bytes) + """Create a new TupleHash128 object. + + Args: + digest_bytes (integer): + Optional. The size of the digest, in bytes. + Default is 64. Minimum is 8. + digest_bits (integer): + Optional and alternative to ``digest_bytes``. + The size of the digest, in bits (and in steps of 8). + Default is 512. Minimum is 64. + custom (bytes): + Optional. + A customization bytestring (``S`` in SP 800-185). + + :Return: A :class:`TupleHash` object + """ + + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + digest_bytes = 64 + if digest_bytes is not None: + if digest_bytes < 8: + raise ValueError("'digest_bytes' must be at least 8") + else: + if digest_bits < 64 or digest_bits % 8: + raise ValueError( + "'digest_bytes' must be at least 64 in steps of 8", + ) + digest_bytes = digest_bits // 8 + + custom = kwargs.pop("custom", b"") + + return TupleHash(custom, cSHAKE128, digest_bytes) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash128.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash128.pyi index 2e0ea833..3ef55a2d 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash128.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash128.pyi @@ -1,22 +1,14 @@ -from typing import Any, Union, List, Tuple +from typing import Union from types import ModuleType Buffer = Union[bytes, bytearray, memoryview] class TupleHash(object): - digest_size: int - def __init__(self, - custom: bytes, - cshake: ModuleType, - digest_size: int) -> None: ... - def update(self, *data: Buffer) -> TupleHash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def new(self, - digest_bytes: int = ..., - digest_bits: int = ..., - custom: int = ...) -> TupleHash: ... + digest_size: int + def __init__(self, custom: bytes, cshake: ModuleType, digest_size: int) -> None: ... + def update(self, *data: Buffer) -> TupleHash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def new(self, digest_bytes: int = ..., digest_bits: int = ..., custom: int = ...) -> TupleHash: ... -def new(digest_bytes: int = ..., - digest_bits: int = ..., - custom: int = ...) -> TupleHash: ... +def new(digest_bytes: int = ..., digest_bits: int = ..., custom: int = ...) -> TupleHash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash256.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash256.py index 40a824a9..d6a925b8 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash256.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash256.py @@ -33,38 +33,39 @@ def new(**kwargs): - """Create a new TupleHash256 object. + """Create a new TupleHash256 object. - Args: - digest_bytes (integer): - Optional. The size of the digest, in bytes. - Default is 64. Minimum is 8. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (and in steps of 8). - Default is 512. Minimum is 64. - custom (bytes): - Optional. - A customization bytestring (``S`` in SP 800-185). + Args: + digest_bytes (integer): + Optional. The size of the digest, in bytes. + Default is 64. Minimum is 8. + digest_bits (integer): + Optional and alternative to ``digest_bytes``. + The size of the digest, in bits (and in steps of 8). + Default is 512. Minimum is 64. + custom (bytes): + Optional. + A customization bytestring (``S`` in SP 800-185). - :Return: A :class:`TupleHash` object - """ + :Return: A :class:`TupleHash` object + """ - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 64 - if digest_bytes is not None: - if digest_bytes < 8: - raise ValueError("'digest_bytes' must be at least 8") - else: - if digest_bits < 64 or digest_bits % 8: - raise ValueError("'digest_bytes' must be at least 64 " - "in steps of 8") - digest_bytes = digest_bits // 8 + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + digest_bytes = 64 + if digest_bytes is not None: + if digest_bytes < 8: + raise ValueError("'digest_bytes' must be at least 8") + else: + if digest_bits < 64 or digest_bits % 8: + raise ValueError( + "'digest_bytes' must be at least 64 in steps of 8", + ) + digest_bytes = digest_bits // 8 - custom = kwargs.pop("custom", b'') + custom = kwargs.pop("custom", b"") - return TupleHash(custom, cSHAKE256, digest_bytes) + return TupleHash(custom, cSHAKE256, digest_bytes) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash256.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash256.pyi index 82d943f0..e6dfc87a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash256.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TupleHash256.pyi @@ -1,5 +1,3 @@ from .TupleHash128 import TupleHash -def new(digest_bytes: int = ..., - digest_bits: int = ..., - custom: int = ...) -> TupleHash: ... +def new(digest_bytes: int = ..., digest_bits: int = ..., custom: int = ...) -> TupleHash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE128.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE128.py index 92ac59e4..8cda579d 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE128.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE128.py @@ -1,112 +1,124 @@ -from Cryptodome.Util._raw_api import (VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) -from Cryptodome.Util.number import long_to_bytes -from Cryptodome.Util.py3compat import bchr from .keccak import _raw_keccak_lib class TurboSHAKE(object): - """A TurboSHAKE hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ - - def __init__(self, capacity, domain_separation, data): - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(capacity), - c_ubyte(12)) # Reduced number of rounds - if result: - raise ValueError("Error %d while instantiating TurboSHAKE" - % result) - self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy) - - self._is_squeezing = False - self._capacity = capacity - self._domain = domain_separation - - if data: - self.update(data) - - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating TurboSHAKE state" - % result) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length), - c_ubyte(self._domain)) - if result: - raise ValueError("Error %d while extracting from TurboSHAKE" - % result) - - return get_raw_buffer(bfr) - - def new(self, data=None): - return type(self)(self._capacity, self._domain, data) - - def _reset(self): - result = _raw_keccak_lib.keccak_reset(self._state.get()) - if result: - raise ValueError("Error %d while resetting TurboSHAKE state" - % result) - self._is_squeezing = False + """A TurboSHAKE hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ + + def __init__(self, capacity, domain_separation, data): + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(capacity), + c_ubyte(12), + ) # Reduced number of rounds + if result: + raise ValueError( + "Error %d while instantiating TurboSHAKE" % result, + ) + self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy) + + self._is_squeezing = False + self._capacity = capacity + self._domain = domain_separation + + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._is_squeezing: + raise TypeError("You cannot call 'update' after the first 'read'") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating TurboSHAKE state" % result, + ) + return self + + def read(self, length): + """ + Compute the next piece of XOF output. + + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. + + Args: + length (integer): the amount of bytes this method must return + + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ + + self._is_squeezing = True + bfr = create_string_buffer(length) + result = _raw_keccak_lib.keccak_squeeze( + self._state.get(), + bfr, + c_size_t(length), + c_ubyte(self._domain), + ) + if result: + raise ValueError( + "Error %d while extracting from TurboSHAKE" % result, + ) + + return get_raw_buffer(bfr) + + def new(self, data=None): + return type(self)(self._capacity, self._domain, data) + + def _reset(self): + result = _raw_keccak_lib.keccak_reset(self._state.get()) + if result: + raise ValueError( + "Error %d while resetting TurboSHAKE state" % result, + ) + self._is_squeezing = False def new(**kwargs): - """Create a new TurboSHAKE128 object. - - Args: - domain (integer): - Optional - A domain separation byte, between 0x01 and 0x7F. - The default value is 0x1F. - data (bytes/bytearray/memoryview): - Optional - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - - :Return: A :class:`TurboSHAKE` object - """ - - domain_separation = kwargs.get('domain', 0x1F) - if not (0x01 <= domain_separation <= 0x7F): - raise ValueError("Incorrect domain separation value (%d)" % - domain_separation) - data = kwargs.get('data') - return TurboSHAKE(32, domain_separation, data=data) + """Create a new TurboSHAKE128 object. + + Args: + domain (integer): + Optional - A domain separation byte, between 0x01 and 0x7F. + The default value is 0x1F. + data (bytes/bytearray/memoryview): + Optional - The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + + :Return: A :class:`TurboSHAKE` object + """ + + domain_separation = kwargs.get("domain", 0x1F) + if not (0x01 <= domain_separation <= 0x7F): + raise ValueError( + "Incorrect domain separation value (%d)" % domain_separation, + ) + data = kwargs.get("data") + return TurboSHAKE(32, domain_separation, data=data) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE128.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE128.pyi index d74c9c08..83b573a9 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE128.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE128.pyi @@ -4,14 +4,13 @@ from typing_extensions import TypedDict, Unpack, NotRequired Buffer = Union[bytes, bytearray, memoryview] class TurboSHAKE(object): - - def __init__(self, capacity: int, domain_separation: int, data: Union[Buffer, None]) -> None: ... - def update(self, data: Buffer) -> TurboSHAKE : ... - def read(self, length: int) -> bytes: ... - def new(self, data: Optional[Buffer]=None) -> TurboSHAKE: ... + def __init__(self, capacity: int, domain_separation: int, data: Union[Buffer, None]) -> None: ... + def update(self, data: Buffer) -> TurboSHAKE: ... + def read(self, length: int) -> bytes: ... + def new(self, data: Optional[Buffer] = None) -> TurboSHAKE: ... class Args(TypedDict): - domain: NotRequired[int] - data: NotRequired[Buffer] + domain: NotRequired[int] + data: NotRequired[Buffer] def new(**kwargs: Unpack[Args]) -> TurboSHAKE: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE256.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE256.py index ce27a485..d8acf75c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE256.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE256.py @@ -1,22 +1,24 @@ from .TurboSHAKE128 import TurboSHAKE + def new(**kwargs): - """Create a new TurboSHAKE256 object. + """Create a new TurboSHAKE256 object. - Args: - domain (integer): - Optional - A domain separation byte, between 0x01 and 0x7F. - The default value is 0x1F. - data (bytes/bytearray/memoryview): - Optional - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. + Args: + domain (integer): + Optional - A domain separation byte, between 0x01 and 0x7F. + The default value is 0x1F. + data (bytes/bytearray/memoryview): + Optional - The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. - :Return: A :class:`TurboSHAKE` object - """ + :Return: A :class:`TurboSHAKE` object + """ - domain_separation = kwargs.get('domain', 0x1F) - if not (0x01 <= domain_separation <= 0x7F): - raise ValueError("Incorrect domain separation value (%d)" % - domain_separation) - data = kwargs.get('data') - return TurboSHAKE(64, domain_separation, data=data) + domain_separation = kwargs.get("domain", 0x1F) + if not (0x01 <= domain_separation <= 0x7F): + raise ValueError( + "Incorrect domain separation value (%d)" % domain_separation, + ) + data = kwargs.get("data") + return TurboSHAKE(64, domain_separation, data=data) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE256.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE256.pyi index 561e946c..3d3b8604 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE256.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/TurboSHAKE256.pyi @@ -6,7 +6,7 @@ from .TurboSHAKE128 import TurboSHAKE Buffer = Union[bytes, bytearray, memoryview] class Args(TypedDict): - domain: NotRequired[int] - data: NotRequired[Buffer] + domain: NotRequired[int] + data: NotRequired[Buffer] def new(**kwargs: Unpack[Args]) -> TurboSHAKE: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/__init__.py index 80446e4f..38f8cc8f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/__init__.py @@ -18,52 +18,83 @@ # SOFTWARE. # =================================================================== -__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1', - 'SHA224', 'SHA256', 'SHA384', 'SHA512', - 'SHA3_224', 'SHA3_256', 'SHA3_384', 'SHA3_512', - 'CMAC', 'Poly1305', - 'cSHAKE128', 'cSHAKE256', 'KMAC128', 'KMAC256', - 'TupleHash128', 'TupleHash256', 'KangarooTwelve', - 'TurboSHAKE128', 'TurboSHAKE256'] +__all__ = [ + "HMAC", + "MD2", + "MD4", + "MD5", + "RIPEMD160", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA3_224", + "SHA3_256", + "SHA3_384", + "SHA3_512", + "CMAC", + "Poly1305", + "cSHAKE128", + "cSHAKE256", + "KMAC128", + "KMAC256", + "TupleHash128", + "TupleHash256", + "KangarooTwelve", + "TurboSHAKE128", + "TurboSHAKE256", +] + def new(name): - """Return a new hash instance, based on its name or - on its ASN.1 Object ID""" + """Return a new hash instance, based on its name or + on its ASN.1 Object ID""" + + name = name.upper() + if name in ("1.3.14.3.2.26", "SHA1", "SHA-1"): + from . import SHA1 + + return SHA1.new() + if name in ("2.16.840.1.101.3.4.2.4", "SHA224", "SHA-224"): + from . import SHA224 + + return SHA224.new() + if name in ("2.16.840.1.101.3.4.2.1", "SHA256", "SHA-256"): + from . import SHA256 + + return SHA256.new() + if name in ("2.16.840.1.101.3.4.2.2", "SHA384", "SHA-384"): + from . import SHA384 + + return SHA384.new() + if name in ("2.16.840.1.101.3.4.2.3", "SHA512", "SHA-512"): + from . import SHA512 + + return SHA512.new() + if name in ("2.16.840.1.101.3.4.2.5", "SHA512-224", "SHA-512-224"): + from . import SHA512 + + return SHA512.new(truncate="224") + if name in ("2.16.840.1.101.3.4.2.6", "SHA512-256", "SHA-512-256"): + from . import SHA512 + + return SHA512.new(truncate="256") + if name in ("2.16.840.1.101.3.4.2.7", "SHA3-224", "SHA-3-224"): + from . import SHA3_224 + + return SHA3_224.new() + if name in ("2.16.840.1.101.3.4.2.8", "SHA3-256", "SHA-3-256"): + from . import SHA3_256 + + return SHA3_256.new() + if name in ("2.16.840.1.101.3.4.2.9", "SHA3-384", "SHA-3-384"): + from . import SHA3_384 - name = name.upper() - if name in ("1.3.14.3.2.26", "SHA1", "SHA-1"): - from . import SHA1 - return SHA1.new() - if name in ("2.16.840.1.101.3.4.2.4", "SHA224", "SHA-224"): - from . import SHA224 - return SHA224.new() - if name in ("2.16.840.1.101.3.4.2.1", "SHA256", "SHA-256"): - from . import SHA256 - return SHA256.new() - if name in ("2.16.840.1.101.3.4.2.2", "SHA384", "SHA-384"): - from . import SHA384 - return SHA384.new() - if name in ("2.16.840.1.101.3.4.2.3", "SHA512", "SHA-512"): - from . import SHA512 - return SHA512.new() - if name in ("2.16.840.1.101.3.4.2.5", "SHA512-224", "SHA-512-224"): - from . import SHA512 - return SHA512.new(truncate='224') - if name in ("2.16.840.1.101.3.4.2.6", "SHA512-256", "SHA-512-256"): - from . import SHA512 - return SHA512.new(truncate='256') - if name in ("2.16.840.1.101.3.4.2.7", "SHA3-224", "SHA-3-224"): - from . import SHA3_224 - return SHA3_224.new() - if name in ("2.16.840.1.101.3.4.2.8", "SHA3-256", "SHA-3-256"): - from . import SHA3_256 - return SHA3_256.new() - if name in ("2.16.840.1.101.3.4.2.9", "SHA3-384", "SHA-3-384"): - from . import SHA3_384 - return SHA3_384.new() - if name in ("2.16.840.1.101.3.4.2.10", "SHA3-512", "SHA-3-512"): - from . import SHA3_512 - return SHA3_512.new() - else: - raise ValueError("Unknown hash %s" % str(name)) + return SHA3_384.new() + if name in ("2.16.840.1.101.3.4.2.10", "SHA3-512", "SHA-3-512"): + from . import SHA3_512 + return SHA3_512.new() + else: + raise ValueError("Unknown hash %s" % str(name)) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE128.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE128.py index 064b3d67..ac6373cc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE128.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE128.py @@ -30,10 +30,15 @@ from Cryptodome.Util.py3compat import bchr, concat_buffers -from Cryptodome.Util._raw_api import (VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Util.number import long_to_bytes @@ -41,147 +46,158 @@ def _left_encode(x): - """Left encode function as defined in NIST SP 800-185""" + """Left encode function as defined in NIST SP 800-185""" - assert (x < (1 << 2040) and x >= 0) + assert x < (1 << 2040) and x >= 0 - # Get number of bytes needed to represent this integer. - num = 1 if x == 0 else (x.bit_length() + 7) // 8 + # Get number of bytes needed to represent this integer. + num = 1 if x == 0 else (x.bit_length() + 7) // 8 - return bchr(num) + long_to_bytes(x) + return bchr(num) + long_to_bytes(x) def _right_encode(x): - """Right encode function as defined in NIST SP 800-185""" + """Right encode function as defined in NIST SP 800-185""" - assert (x < (1 << 2040) and x >= 0) + assert x < (1 << 2040) and x >= 0 - # Get number of bytes needed to represent this integer. - num = 1 if x == 0 else (x.bit_length() + 7) // 8 + # Get number of bytes needed to represent this integer. + num = 1 if x == 0 else (x.bit_length() + 7) // 8 - return long_to_bytes(x) + bchr(num) + return long_to_bytes(x) + bchr(num) def _encode_str(x): - """Encode string function as defined in NIST SP 800-185""" + """Encode string function as defined in NIST SP 800-185""" - bitlen = len(x) * 8 - if bitlen >= (1 << 2040): - raise ValueError("String too large to encode in cSHAKE") + bitlen = len(x) * 8 + if bitlen >= (1 << 2040): + raise ValueError("String too large to encode in cSHAKE") - return concat_buffers(_left_encode(bitlen), x) + return concat_buffers(_left_encode(bitlen), x) def _bytepad(x, length): - """Zero pad byte string as defined in NIST SP 800-185""" + """Zero pad byte string as defined in NIST SP 800-185""" - to_pad = concat_buffers(_left_encode(length), x) + to_pad = concat_buffers(_left_encode(length), x) - # Note: this implementation works with byte aligned strings, - # hence no additional bit padding is needed at this point. - npad = (length - len(to_pad) % length) % length + # Note: this implementation works with byte aligned strings, + # hence no additional bit padding is needed at this point. + npad = (length - len(to_pad) % length) % length - return to_pad + b'\x00' * npad + return to_pad + b"\x00" * npad class cSHAKE_XOF(object): - """A cSHAKE hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ - - def __init__(self, data, custom, capacity, function): - state = VoidPointer() - - if custom or function: - prefix_unpad = _encode_str(function) + _encode_str(custom) - prefix = _bytepad(prefix_unpad, (1600 - capacity)//8) - self._padding = 0x04 - else: - prefix = None - self._padding = 0x1F # for SHAKE - - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(capacity//8), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating cSHAKE" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - self._is_squeezing = False - - if prefix: - self.update(prefix) - - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating %s state" - % (result, self.name)) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while extracting from %s" - % (result, self.name)) - - return get_raw_buffer(bfr) + """A cSHAKE hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ + + def __init__(self, data, custom, capacity, function): + state = VoidPointer() + + if custom or function: + prefix_unpad = _encode_str(function) + _encode_str(custom) + prefix = _bytepad(prefix_unpad, (1600 - capacity) // 8) + self._padding = 0x04 + else: + prefix = None + self._padding = 0x1F # for SHAKE + + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(capacity // 8), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating cSHAKE" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + self._is_squeezing = False + + if prefix: + self.update(prefix) + + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._is_squeezing: + raise TypeError("You cannot call 'update' after the first 'read'") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating %s state" % (result, self.name), + ) + return self + + def read(self, length): + """ + Compute the next piece of XOF output. + + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. + + Args: + length (integer): the amount of bytes this method must return + + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ + + self._is_squeezing = True + bfr = create_string_buffer(length) + result = _raw_keccak_lib.keccak_squeeze( + self._state.get(), + bfr, + c_size_t(length), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while extracting from %s" % (result, self.name), + ) + + return get_raw_buffer(bfr) def _new(data, custom, function): - # Use Keccak[256] - return cSHAKE_XOF(data, custom, 256, function) + # Use Keccak[256] + return cSHAKE_XOF(data, custom, 256, function) def new(data=None, custom=None): - """Return a fresh instance of a cSHAKE128 object. - - Args: - data (bytes/bytearray/memoryview): - Optional. - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - custom (bytes): - Optional. - A customization bytestring (``S`` in SP 800-185). - - :Return: A :class:`cSHAKE_XOF` object - """ - - # Use Keccak[256] - return cSHAKE_XOF(data, custom, 256, b'') + """Return a fresh instance of a cSHAKE128 object. + + Args: + data (bytes/bytearray/memoryview): + Optional. + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + custom (bytes): + Optional. + A customization bytestring (``S`` in SP 800-185). + + :Return: A :class:`cSHAKE_XOF` object + """ + + # Use Keccak[256] + return cSHAKE_XOF(data, custom, 256, b"") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE128.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE128.pyi index 1452feaf..6e6225b1 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE128.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE128.pyi @@ -3,12 +3,10 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class cSHAKE_XOF(object): - def __init__(self, - data: Optional[Buffer] = ..., - function: Optional[bytes] = ..., - custom: Optional[bytes] = ...) -> None: ... - def update(self, data: Buffer) -> cSHAKE_XOF: ... - def read(self, length: int) -> bytes: ... + def __init__( + self, data: Optional[Buffer] = ..., function: Optional[bytes] = ..., custom: Optional[bytes] = ... + ) -> None: ... + def update(self, data: Buffer) -> cSHAKE_XOF: ... + def read(self, length: int) -> bytes: ... -def new(data: Optional[Buffer] = ..., - custom: Optional[Buffer] = ...) -> cSHAKE_XOF: ... +def new(data: Optional[Buffer] = ..., custom: Optional[Buffer] = ...) -> cSHAKE_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE256.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE256.py index a5b87012..4906ed00 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE256.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE256.py @@ -28,29 +28,28 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util._raw_api import c_size_t from Cryptodome.Hash.cSHAKE128 import cSHAKE_XOF def _new(data, custom, function): - # Use Keccak[512] - return cSHAKE_XOF(data, custom, 512, function) + # Use Keccak[512] + return cSHAKE_XOF(data, custom, 512, function) def new(data=None, custom=None): - """Return a fresh instance of a cSHAKE256 object. - - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - Optional. - custom (bytes): - Optional. - A customization bytestring (``S`` in SP 800-185). - - :Return: A :class:`cSHAKE_XOF` object - """ - - # Use Keccak[512] - return cSHAKE_XOF(data, custom, 512, b'') + """Return a fresh instance of a cSHAKE256 object. + + Args: + data (bytes/bytearray/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + Optional. + custom (bytes): + Optional. + A customization bytestring (``S`` in SP 800-185). + + :Return: A :class:`cSHAKE_XOF` object + """ + + # Use Keccak[512] + return cSHAKE_XOF(data, custom, 512, b"") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE256.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE256.pyi index b910bb6f..955c4c35 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE256.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/cSHAKE256.pyi @@ -4,5 +4,4 @@ from Cryptodome.Hash.cSHAKE128 import cSHAKE_XOF Buffer = Union[bytes, bytearray, memoryview] -def new(data: Optional[Buffer] = ..., - custom: Optional[Buffer] = ...) -> cSHAKE_XOF: ... +def new(data: Optional[Buffer] = ..., custom: Optional[Buffer] = ...) -> cSHAKE_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/keccak.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/keccak.py index f2af2024..3f9780e7 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/keccak.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/keccak.py @@ -30,14 +30,20 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) - -_raw_keccak_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._keccak", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) + +_raw_keccak_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._keccak", + """ int keccak_init(void **state, size_t capacity_bytes, uint8_t rounds); @@ -55,127 +61,137 @@ uint8_t padding); int keccak_copy(const void *src, void *dst); int keccak_reset(void *state); - """) + """, +) -class Keccak_Hash(object): - """A Keccak hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - def __init__(self, data, digest_bytes, update_after_digest): - # The size of the resulting hash in bytes. - self.digest_size = digest_bytes - - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x01 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating keccak" % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating keccak" % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while squeezing keccak" % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def new(self, **kwargs): - """Create a fresh Keccak hash object.""" - - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) +class Keccak_Hash(object): + """A Keccak hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + def __init__(self, data, digest_bytes, update_after_digest): + # The size of the resulting hash in bytes. + self.digest_size = digest_bytes + + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x01 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError("Error %d while instantiating keccak" % result) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError("Error %d while updating keccak" % result) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError("Error %d while squeezing keccak" % result) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def new(self, **kwargs): + """Create a fresh Keccak hash object.""" + + if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: + kwargs["digest_bytes"] = self.digest_size + + return new(**kwargs) def new(**kwargs): - """Create a new hash object. - - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`Keccak_Hash.update`. - digest_bytes (integer): - The size of the digest, in bytes (28, 32, 48, 64). - digest_bits (integer): - The size of the digest, in bits (224, 256, 384, 512). - update_after_digest (boolean): - Whether :meth:`Keccak.digest` can be followed by another - :meth:`Keccak.update` (default: ``False``). - - :Return: A :class:`Keccak_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - raise TypeError("Digest size (bits, bytes) not provided") - if digest_bytes is not None: - if digest_bytes not in (28, 32, 48, 64): - raise ValueError("'digest_bytes' must be: 28, 32, 48 or 64") - else: - if digest_bits not in (224, 256, 384, 512): - raise ValueError("'digest_bytes' must be: 224, 256, 384 or 512") - digest_bytes = digest_bits // 8 - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return Keccak_Hash(data, digest_bytes, update_after_digest) + """Create a new hash object. + + Args: + data (bytes/bytearray/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`Keccak_Hash.update`. + digest_bytes (integer): + The size of the digest, in bytes (28, 32, 48, 64). + digest_bits (integer): + The size of the digest, in bits (224, 256, 384, 512). + update_after_digest (boolean): + Whether :meth:`Keccak.digest` can be followed by another + :meth:`Keccak.update` (default: ``False``). + + :Return: A :class:`Keccak_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + raise TypeError("Digest size (bits, bytes) not provided") + if digest_bytes is not None: + if digest_bytes not in (28, 32, 48, 64): + raise ValueError("'digest_bytes' must be: 28, 32, 48 or 64") + else: + if digest_bits not in (224, 256, 384, 512): + raise ValueError("'digest_bytes' must be: 224, 256, 384 or 512") + digest_bytes = digest_bits // 8 + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return Keccak_Hash(data, digest_bytes, update_after_digest) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/keccak.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/keccak.pyi index 844d2565..f620ffc0 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/keccak.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Hash/keccak.pyi @@ -1,23 +1,21 @@ -from typing import Union, Any +from typing import Union Buffer = Union[bytes, bytearray, memoryview] class Keccak_Hash(object): - digest_size: int - def __init__(self, - data: Buffer, - digest_bytes: int, - update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> Keccak_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def new(self, - data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - update_after_digest: bool = ...) -> Keccak_Hash: ... + digest_size: int + def __init__(self, data: Buffer, digest_bytes: int, update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> Keccak_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def new( + self, + data: Buffer = ..., + digest_bytes: int = ..., + digest_bits: int = ..., + update_after_digest: bool = ..., + ) -> Keccak_Hash: ... -def new(data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - update_after_digest: bool = ...) -> Keccak_Hash: ... +def new( + data: Buffer = ..., digest_bytes: int = ..., digest_bits: int = ..., update_after_digest: bool = ... +) -> Keccak_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PEM.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PEM.py index 61fe920f..f0a37e5d 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PEM.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PEM.py @@ -31,7 +31,7 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = ['encode', 'decode'] +__all__ = ["encode", "decode"] import re from binascii import a2b_base64, b2a_base64, hexlify, unhexlify @@ -45,147 +45,145 @@ def encode(data, marker, passphrase=None, randfunc=None): - """Encode a piece of binary data into PEM format. - - Args: - data (byte string): - The piece of binary data to encode. - marker (string): - The marker for the PEM block (e.g. "PUBLIC KEY"). - Note that there is no official master list for all allowed markers. - Still, you can refer to the OpenSSL_ source code. - passphrase (byte string): - If given, the PEM block will be encrypted. The key is derived from - the passphrase. - randfunc (callable): - Random number generation function; it accepts an integer N and returns - a byte string of random data, N bytes long. If not given, a new one is - instantiated. - - Returns: - The PEM block, as a string. - - .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h - """ - - if randfunc is None: - randfunc = get_random_bytes - - out = "-----BEGIN %s-----\n" % marker - if passphrase: - # We only support 3DES for encryption - salt = randfunc(8) - key = PBKDF1(passphrase, salt, 16, 1, MD5) - key += PBKDF1(key + passphrase, salt, 8, 1, MD5) - objenc = DES3.new(key, DES3.MODE_CBC, salt) - out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" %\ - tostr(hexlify(salt).upper()) - # Encrypt with PKCS#7 padding - data = objenc.encrypt(pad(data, objenc.block_size)) - elif passphrase is not None: - raise ValueError("Empty password") - - # Each BASE64 line can take up to 64 characters (=48 bytes of data) - # b2a_base64 adds a new line character! - chunks = [tostr(b2a_base64(data[i:i + 48])) - for i in range(0, len(data), 48)] - out += "".join(chunks) - out += "-----END %s-----" % marker - return out + """Encode a piece of binary data into PEM format. + + Args: + data (byte string): + The piece of binary data to encode. + marker (string): + The marker for the PEM block (e.g. "PUBLIC KEY"). + Note that there is no official master list for all allowed markers. + Still, you can refer to the OpenSSL_ source code. + passphrase (byte string): + If given, the PEM block will be encrypted. The key is derived from + the passphrase. + randfunc (callable): + Random number generation function; it accepts an integer N and returns + a byte string of random data, N bytes long. If not given, a new one is + instantiated. + + Returns: + The PEM block, as a string. + + .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h + """ + + if randfunc is None: + randfunc = get_random_bytes + + out = "-----BEGIN %s-----\n" % marker + if passphrase: + # We only support 3DES for encryption + salt = randfunc(8) + key = PBKDF1(passphrase, salt, 16, 1, MD5) + key += PBKDF1(key + passphrase, salt, 8, 1, MD5) + objenc = DES3.new(key, DES3.MODE_CBC, salt) + out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" % tostr(hexlify(salt).upper()) + # Encrypt with PKCS#7 padding + data = objenc.encrypt(pad(data, objenc.block_size)) + elif passphrase is not None: + raise ValueError("Empty password") + + # Each BASE64 line can take up to 64 characters (=48 bytes of data) + # b2a_base64 adds a new line character! + chunks = [tostr(b2a_base64(data[i : i + 48])) for i in range(0, len(data), 48)] + out += "".join(chunks) + out += "-----END %s-----" % marker + return out def _EVP_BytesToKey(data, salt, key_len): - d = [ b'' ] - m = (key_len + 15 ) // 16 - for _ in range(m): - nd = MD5.new(d[-1] + data + salt).digest() - d.append(nd) - return b"".join(d)[:key_len] + d = [b""] + m = (key_len + 15) // 16 + for _ in range(m): + nd = MD5.new(d[-1] + data + salt).digest() + d.append(nd) + return b"".join(d)[:key_len] def decode(pem_data, passphrase=None): - """Decode a PEM block into binary. - - Args: - pem_data (string): - The PEM block. - passphrase (byte string): - If given and the PEM block is encrypted, - the key will be derived from the passphrase. - - Returns: - A tuple with the binary data, the marker string, and a boolean to - indicate if decryption was performed. - - Raises: - ValueError: if decoding fails, if the PEM file is encrypted and no passphrase has - been provided or if the passphrase is incorrect. - """ - - # Verify Pre-Encapsulation Boundary - r = re.compile(r"\s*-----BEGIN (.*)-----\s+") - m = r.match(pem_data) - if not m: - raise ValueError("Not a valid PEM pre boundary") - marker = m.group(1) - - # Verify Post-Encapsulation Boundary - r = re.compile(r"-----END (.*)-----\s*$") - m = r.search(pem_data) - if not m or m.group(1) != marker: - raise ValueError("Not a valid PEM post boundary") - - # Removes spaces and slit on lines - lines = pem_data.replace(" ", '').split() - if len(lines) < 3: - raise ValueError("A PEM file must have at least 3 lines") - - # Decrypts, if necessary - if lines[1].startswith('Proc-Type:4,ENCRYPTED'): - if not passphrase: - raise ValueError("PEM is encrypted, but no passphrase available") - DEK = lines[2].split(':') - if len(DEK) != 2 or DEK[0] != 'DEK-Info': - raise ValueError("PEM encryption format not supported.") - algo, salt = DEK[1].split(',') - salt = unhexlify(tobytes(salt)) - - padding = True - - if algo == "DES-CBC": - key = _EVP_BytesToKey(passphrase, salt, 8) - objdec = DES.new(key, DES.MODE_CBC, salt) - elif algo == "DES-EDE3-CBC": - key = _EVP_BytesToKey(passphrase, salt, 24) - objdec = DES3.new(key, DES3.MODE_CBC, salt) - elif algo == "AES-128-CBC": - key = _EVP_BytesToKey(passphrase, salt[:8], 16) - objdec = AES.new(key, AES.MODE_CBC, salt) - elif algo == "AES-192-CBC": - key = _EVP_BytesToKey(passphrase, salt[:8], 24) - objdec = AES.new(key, AES.MODE_CBC, salt) - elif algo == "AES-256-CBC": - key = _EVP_BytesToKey(passphrase, salt[:8], 32) - objdec = AES.new(key, AES.MODE_CBC, salt) - elif algo.lower() == "id-aes256-gcm": - key = _EVP_BytesToKey(passphrase, salt[:8], 32) - objdec = AES.new(key, AES.MODE_GCM, nonce=salt) - padding = False - else: - raise ValueError("Unsupport PEM encryption algorithm (%s)." % algo) - lines = lines[2:] - else: - objdec = None - - # Decode body - data = a2b_base64(''.join(lines[1:-1])) - enc_flag = False - if objdec: - if padding: - data = unpad(objdec.decrypt(data), objdec.block_size) - else: - # There is no tag, so we don't use decrypt_and_verify - data = objdec.decrypt(data) - enc_flag = True - - return (data, marker, enc_flag) + """Decode a PEM block into binary. + + Args: + pem_data (string): + The PEM block. + passphrase (byte string): + If given and the PEM block is encrypted, + the key will be derived from the passphrase. + + Returns: + A tuple with the binary data, the marker string, and a boolean to + indicate if decryption was performed. + + Raises: + ValueError: if decoding fails, if the PEM file is encrypted and no passphrase has + been provided or if the passphrase is incorrect. + """ + + # Verify Pre-Encapsulation Boundary + r = re.compile(r"\s*-----BEGIN (.*)-----\s+") + m = r.match(pem_data) + if not m: + raise ValueError("Not a valid PEM pre boundary") + marker = m.group(1) + + # Verify Post-Encapsulation Boundary + r = re.compile(r"-----END (.*)-----\s*$") + m = r.search(pem_data) + if not m or m.group(1) != marker: + raise ValueError("Not a valid PEM post boundary") + + # Removes spaces and slit on lines + lines = pem_data.replace(" ", "").split() + if len(lines) < 3: + raise ValueError("A PEM file must have at least 3 lines") + + # Decrypts, if necessary + if lines[1].startswith("Proc-Type:4,ENCRYPTED"): + if not passphrase: + raise ValueError("PEM is encrypted, but no passphrase available") + DEK = lines[2].split(":") + if len(DEK) != 2 or DEK[0] != "DEK-Info": + raise ValueError("PEM encryption format not supported.") + algo, salt = DEK[1].split(",") + salt = unhexlify(tobytes(salt)) + + padding = True + + if algo == "DES-CBC": + key = _EVP_BytesToKey(passphrase, salt, 8) + objdec = DES.new(key, DES.MODE_CBC, salt) + elif algo == "DES-EDE3-CBC": + key = _EVP_BytesToKey(passphrase, salt, 24) + objdec = DES3.new(key, DES3.MODE_CBC, salt) + elif algo == "AES-128-CBC": + key = _EVP_BytesToKey(passphrase, salt[:8], 16) + objdec = AES.new(key, AES.MODE_CBC, salt) + elif algo == "AES-192-CBC": + key = _EVP_BytesToKey(passphrase, salt[:8], 24) + objdec = AES.new(key, AES.MODE_CBC, salt) + elif algo == "AES-256-CBC": + key = _EVP_BytesToKey(passphrase, salt[:8], 32) + objdec = AES.new(key, AES.MODE_CBC, salt) + elif algo.lower() == "id-aes256-gcm": + key = _EVP_BytesToKey(passphrase, salt[:8], 32) + objdec = AES.new(key, AES.MODE_GCM, nonce=salt) + padding = False + else: + raise ValueError("Unsupport PEM encryption algorithm (%s)." % algo) + lines = lines[2:] + else: + objdec = None + + # Decode body + data = a2b_base64("".join(lines[1:-1])) + enc_flag = False + if objdec: + if padding: + data = unpad(objdec.decrypt(data), objdec.block_size) + else: + # There is no tag, so we don't use decrypt_and_verify + data = objdec.decrypt(data) + enc_flag = True + + return (data, marker, enc_flag) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PEM.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PEM.pyi index 2e324c45..0d1500bf 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PEM.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PEM.pyi @@ -1,10 +1,9 @@ from typing import Tuple, Optional, Callable -def encode(data: bytes, - marke: str, - passphrase: Optional[bytes] = ..., - randfunc: Optional[Callable[[int],bytes]] = ...) -> str: ... - - -def decode(pem_data: str, - passphrase: Optional[bytes] = ...) -> Tuple[bytes, str, bool]: ... +def encode( + data: bytes, + marke: str, + passphrase: Optional[bytes] = ..., + randfunc: Optional[Callable[[int], bytes]] = ..., +) -> str: ... +def decode(pem_data: str, passphrase: Optional[bytes] = ...) -> Tuple[bytes, str, bool]: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PKCS8.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PKCS8.py index e7701993..9c000a1f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PKCS8.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PKCS8.py @@ -35,192 +35,207 @@ from Cryptodome.Util.py3compat import * from Cryptodome.Util.asn1 import ( - DerNull, - DerSequence, - DerObjectId, - DerOctetString, - ) + DerNull, + DerSequence, + DerObjectId, + DerOctetString, +) from Cryptodome.IO._PBES import PBES1, PBES2, PbesError -__all__ = ['wrap', 'unwrap'] - - -def wrap(private_key, key_oid, passphrase=None, protection=None, - prot_params=None, key_params=DerNull(), randfunc=None): - """Wrap a private key into a PKCS#8 blob (clear or encrypted). - - Args: - - private_key (bytes): - The private key encoded in binary form. The actual encoding is - algorithm specific. In most cases, it is DER. - - key_oid (string): - The object identifier (OID) of the private key to wrap. - It is a dotted string, like ``'1.2.840.113549.1.1.1'`` (for RSA keys) - or ``'1.2.840.10045.2.1'`` (for ECC keys). - - Keyword Args: - - passphrase (bytes or string): - The secret passphrase from which the wrapping key is derived. - Set it only if encryption is required. - - protection (string): - The identifier of the algorithm to use for securely wrapping the key. - Refer to :ref:`the encryption parameters` . - The default value is ``'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'``. - - prot_params (dictionary): - Parameters for the key derivation function (KDF). - Refer to :ref:`the encryption parameters` . - - key_params (DER object or None): - The ``parameters`` field to use in the ``AlgorithmIdentifier`` - SEQUENCE. If ``None``, no ``parameters`` field will be added. - By default, the ASN.1 type ``NULL`` is used. - - randfunc (callable): - Random number generation function; it should accept a single integer - N and return a string of random data, N bytes long. - If not specified, a new RNG will be instantiated - from :mod:`Cryptodome.Random`. - - Returns: - bytes: The PKCS#8-wrapped private key (possibly encrypted). - """ - - # - # PrivateKeyInfo ::= SEQUENCE { - # version Version, - # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - # privateKey PrivateKey, - # attributes [0] IMPLICIT Attributes OPTIONAL - # } - # - if key_params is None: - algorithm = DerSequence([DerObjectId(key_oid)]) - else: - algorithm = DerSequence([DerObjectId(key_oid), key_params]) - - pk_info = DerSequence([ - 0, - algorithm, - DerOctetString(private_key) - ]) - pk_info_der = pk_info.encode() - - if passphrase is None: - return pk_info_der - - if not passphrase: - raise ValueError("Empty passphrase") - - # Encryption with PBES2 - passphrase = tobytes(passphrase) - if protection is None: - protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' - return PBES2.encrypt(pk_info_der, passphrase, - protection, prot_params, randfunc) +__all__ = ["wrap", "unwrap"] + + +def wrap( + private_key, + key_oid, + passphrase=None, + protection=None, + prot_params=None, + key_params=DerNull(), + randfunc=None, +): + """Wrap a private key into a PKCS#8 blob (clear or encrypted). + + Args: + + private_key (bytes): + The private key encoded in binary form. The actual encoding is + algorithm specific. In most cases, it is DER. + + key_oid (string): + The object identifier (OID) of the private key to wrap. + It is a dotted string, like ``'1.2.840.113549.1.1.1'`` (for RSA keys) + or ``'1.2.840.10045.2.1'`` (for ECC keys). + + Keyword Args: + + passphrase (bytes or string): + The secret passphrase from which the wrapping key is derived. + Set it only if encryption is required. + + protection (string): + The identifier of the algorithm to use for securely wrapping the key. + Refer to :ref:`the encryption parameters` . + The default value is ``'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'``. + + prot_params (dictionary): + Parameters for the key derivation function (KDF). + Refer to :ref:`the encryption parameters` . + + key_params (DER object or None): + The ``parameters`` field to use in the ``AlgorithmIdentifier`` + SEQUENCE. If ``None``, no ``parameters`` field will be added. + By default, the ASN.1 type ``NULL`` is used. + + randfunc (callable): + Random number generation function; it should accept a single integer + N and return a string of random data, N bytes long. + If not specified, a new RNG will be instantiated + from :mod:`Cryptodome.Random`. + + Returns: + bytes: The PKCS#8-wrapped private key (possibly encrypted). + """ + + # + # PrivateKeyInfo ::= SEQUENCE { + # version Version, + # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + # privateKey PrivateKey, + # attributes [0] IMPLICIT Attributes OPTIONAL + # } + # + if key_params is None: + algorithm = DerSequence([DerObjectId(key_oid)]) + else: + algorithm = DerSequence([DerObjectId(key_oid), key_params]) + + pk_info = DerSequence( + [ + 0, + algorithm, + DerOctetString(private_key), + ] + ) + pk_info_der = pk_info.encode() + + if passphrase is None: + return pk_info_der + + if not passphrase: + raise ValueError("Empty passphrase") + + # Encryption with PBES2 + passphrase = tobytes(passphrase) + if protection is None: + protection = "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC" + return PBES2.encrypt( + pk_info_der, + passphrase, + protection, + prot_params, + randfunc, + ) def unwrap(p8_private_key, passphrase=None): - """Unwrap a private key from a PKCS#8 blob (clear or encrypted). - - Args: - p8_private_key (bytes): - The private key wrapped into a PKCS#8 container, DER encoded. - - Keyword Args: - passphrase (byte string or string): - The passphrase to use to decrypt the blob (if it is encrypted). - - Return: - A tuple containing - - #. the algorithm identifier of the wrapped key (OID, dotted string) - #. the private key (bytes, DER encoded) - #. the associated parameters (bytes, DER encoded) or ``None`` - - Raises: - ValueError : if decoding fails - """ - - if passphrase is not None: - passphrase = tobytes(passphrase) - - found = False - try: - p8_private_key = PBES1.decrypt(p8_private_key, passphrase) - found = True - except PbesError as e: - error_str = "PBES1[%s]" % str(e) - except ValueError: - error_str = "PBES1[Invalid]" - - if not found: - try: - p8_private_key = PBES2.decrypt(p8_private_key, passphrase) - found = True - except PbesError as e: - error_str += ",PBES2[%s]" % str(e) - except ValueError: - error_str += ",PBES2[Invalid]" - - if not found: - raise ValueError("Error decoding PKCS#8 (%s)" % error_str) - - pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4, 5)) - if len(pk_info) == 2 and not passphrase: - raise ValueError("Not a valid clear PKCS#8 structure " - "(maybe it is encrypted?)") - - # RFC5208, PKCS#8, version is v1(0) - # - # PrivateKeyInfo ::= SEQUENCE { - # version Version, - # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - # privateKey PrivateKey, - # attributes [0] IMPLICIT Attributes OPTIONAL - # } - # - # RFC5915, Asymmetric Key Package, version is v2(1) - # - # OneAsymmetricKey ::= SEQUENCE { - # version Version, - # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - # privateKey PrivateKey, - # attributes [0] Attributes OPTIONAL, - # ..., - # [[2: publicKey [1] PublicKey OPTIONAL ]], - # ... - # } - - if pk_info[0] == 0: - if len(pk_info) not in (3, 4): - raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") - elif pk_info[0] == 1: - if len(pk_info) not in (3, 4, 5): - raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") - else: - raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") - - algo = DerSequence().decode(pk_info[1], nr_elements=(1, 2)) - algo_oid = DerObjectId().decode(algo[0]).value - if len(algo) == 1: - algo_params = None - else: - try: - DerNull().decode(algo[1]) - algo_params = None - except: - algo_params = algo[1] - - # PrivateKey ::= OCTET STRING - private_key = DerOctetString().decode(pk_info[2]).payload - - # We ignore attributes and (for v2 only) publickey - - return (algo_oid, private_key, algo_params) + """Unwrap a private key from a PKCS#8 blob (clear or encrypted). + + Args: + p8_private_key (bytes): + The private key wrapped into a PKCS#8 container, DER encoded. + + Keyword Args: + passphrase (byte string or string): + The passphrase to use to decrypt the blob (if it is encrypted). + + Return: + A tuple containing + + #. the algorithm identifier of the wrapped key (OID, dotted string) + #. the private key (bytes, DER encoded) + #. the associated parameters (bytes, DER encoded) or ``None`` + + Raises: + ValueError : if decoding fails + """ + + if passphrase is not None: + passphrase = tobytes(passphrase) + + found = False + try: + p8_private_key = PBES1.decrypt(p8_private_key, passphrase) + found = True + except PbesError as e: + error_str = "PBES1[%s]" % str(e) + except ValueError: + error_str = "PBES1[Invalid]" + + if not found: + try: + p8_private_key = PBES2.decrypt(p8_private_key, passphrase) + found = True + except PbesError as e: + error_str += ",PBES2[%s]" % str(e) + except ValueError: + error_str += ",PBES2[Invalid]" + + if not found: + raise ValueError("Error decoding PKCS#8 (%s)" % error_str) + + pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4, 5)) + if len(pk_info) == 2 and not passphrase: + raise ValueError( + "Not a valid clear PKCS#8 structure (maybe it is encrypted?)", + ) + + # RFC5208, PKCS#8, version is v1(0) + # + # PrivateKeyInfo ::= SEQUENCE { + # version Version, + # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + # privateKey PrivateKey, + # attributes [0] IMPLICIT Attributes OPTIONAL + # } + # + # RFC5915, Asymmetric Key Package, version is v2(1) + # + # OneAsymmetricKey ::= SEQUENCE { + # version Version, + # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + # privateKey PrivateKey, + # attributes [0] Attributes OPTIONAL, + # ..., + # [[2: publicKey [1] PublicKey OPTIONAL ]], + # ... + # } + + if pk_info[0] == 0: + if len(pk_info) not in (3, 4): + raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") + elif pk_info[0] == 1: + if len(pk_info) not in (3, 4, 5): + raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") + else: + raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") + + algo = DerSequence().decode(pk_info[1], nr_elements=(1, 2)) + algo_oid = DerObjectId().decode(algo[0]).value + if len(algo) == 1: + algo_params = None + else: + try: + DerNull().decode(algo[1]) + algo_params = None + except: + algo_params = algo[1] + + # PrivateKey ::= OCTET STRING + private_key = DerOctetString().decode(pk_info[2]).payload + + # We ignore attributes and (for v2 only) publickey + + return (algo_oid, private_key, algo_params) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PKCS8.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PKCS8.pyi index c8d0c104..00bc6be9 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PKCS8.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/PKCS8.pyi @@ -1,17 +1,17 @@ from typing import Tuple, Optional, Union, Callable -from typing_extensions import NotRequired from Cryptodome.Util.asn1 import DerObject from Cryptodome.IO._PBES import ProtParams - -def wrap(private_key: bytes, - key_oid: str, - passphrase: Union[bytes, str] = ..., - protection: str = ..., - prot_params: Optional[ProtParams] = ..., - key_params: Optional[DerObject] = ..., - randfunc: Optional[Callable[[int], str]] = ...) -> bytes: ... - - -def unwrap(p8_private_key: bytes, passphrase: Optional[Union[bytes, str]] = ...) -> Tuple[str, bytes, Optional[bytes]]: ... +def wrap( + private_key: bytes, + key_oid: str, + passphrase: Union[bytes, str] = ..., + protection: str = ..., + prot_params: Optional[ProtParams] = ..., + key_params: Optional[DerObject] = ..., + randfunc: Optional[Callable[[int], str]] = ..., +) -> bytes: ... +def unwrap( + p8_private_key: bytes, passphrase: Optional[Union[bytes, str]] = ... +) -> Tuple[str, bytes, Optional[bytes]]: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/_PBES.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/_PBES.py index 75d8cdeb..da44d726 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/_PBES.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/_PBES.py @@ -36,9 +36,11 @@ from Cryptodome import Hash from Cryptodome import Random from Cryptodome.Util.asn1 import ( - DerSequence, DerOctetString, - DerObjectId, DerInteger, - ) + DerSequence, + DerOctetString, + DerObjectId, + DerInteger, +) from Cryptodome.Cipher import AES from Cryptodome.Util.Padding import pad, unpad @@ -64,8 +66,10 @@ _OID_AES192_GCM = "2.16.840.1.101.3.4.1.26" _OID_AES256_GCM = "2.16.840.1.101.3.4.1.46" + class PbesError(ValueError): - pass + pass + # These are the ASN.1 definitions used by the PBES1/2 logic: # @@ -123,424 +127,462 @@ class PbesError(ValueError): class PBES1(object): - """Deprecated encryption scheme with password-based key derivation - (originally defined in PKCS#5 v1.5, but still present in `v2.0`__). - - .. __: http://www.ietf.org/rfc/rfc2898.txt - """ - - @staticmethod - def decrypt(data, passphrase): - """Decrypt a piece of data using a passphrase and *PBES1*. - - The algorithm to use is automatically detected. - - :Parameters: - data : byte string - The piece of data to decrypt. - passphrase : byte string - The passphrase to use for decrypting the data. - :Returns: - The decrypted data, as a binary string. - """ - - enc_private_key_info = DerSequence().decode(data) - encrypted_algorithm = DerSequence().decode(enc_private_key_info[0]) - encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload - - pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value - cipher_params = {} - if pbe_oid == _OID_PBE_WITH_MD5_AND_DES_CBC: - # PBE_MD5_DES_CBC - from Cryptodome.Hash import MD5 - from Cryptodome.Cipher import DES - hashmod = MD5 - module = DES - elif pbe_oid == _OID_PBE_WITH_MD5_AND_RC2_CBC: - # PBE_MD5_RC2_CBC - from Cryptodome.Hash import MD5 - from Cryptodome.Cipher import ARC2 - hashmod = MD5 - module = ARC2 - cipher_params['effective_keylen'] = 64 - elif pbe_oid == _OID_PBE_WITH_SHA1_AND_DES_CBC: - # PBE_SHA1_DES_CBC - from Cryptodome.Hash import SHA1 - from Cryptodome.Cipher import DES - hashmod = SHA1 - module = DES - elif pbe_oid == _OID_PBE_WITH_SHA1_AND_RC2_CBC: - # PBE_SHA1_RC2_CBC - from Cryptodome.Hash import SHA1 - from Cryptodome.Cipher import ARC2 - hashmod = SHA1 - module = ARC2 - cipher_params['effective_keylen'] = 64 - else: - raise PbesError("Unknown OID for PBES1") - - pbe_params = DerSequence().decode(encrypted_algorithm[1], nr_elements=2) - salt = DerOctetString().decode(pbe_params[0]).payload - iterations = pbe_params[1] - - key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod) - key, iv = key_iv[:8], key_iv[8:] - - cipher = module.new(key, module.MODE_CBC, iv, **cipher_params) - pt = cipher.decrypt(encrypted_data) - return unpad(pt, cipher.block_size) + """Deprecated encryption scheme with password-based key derivation + (originally defined in PKCS#5 v1.5, but still present in `v2.0`__). + + .. __: http://www.ietf.org/rfc/rfc2898.txt + """ + + @staticmethod + def decrypt(data, passphrase): + """Decrypt a piece of data using a passphrase and *PBES1*. + + The algorithm to use is automatically detected. + + :Parameters: + data : byte string + The piece of data to decrypt. + passphrase : byte string + The passphrase to use for decrypting the data. + :Returns: + The decrypted data, as a binary string. + """ + + enc_private_key_info = DerSequence().decode(data) + encrypted_algorithm = DerSequence().decode(enc_private_key_info[0]) + encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload + + pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value + cipher_params = {} + if pbe_oid == _OID_PBE_WITH_MD5_AND_DES_CBC: + # PBE_MD5_DES_CBC + from Cryptodome.Hash import MD5 + from Cryptodome.Cipher import DES + + hashmod = MD5 + module = DES + elif pbe_oid == _OID_PBE_WITH_MD5_AND_RC2_CBC: + # PBE_MD5_RC2_CBC + from Cryptodome.Hash import MD5 + from Cryptodome.Cipher import ARC2 + + hashmod = MD5 + module = ARC2 + cipher_params["effective_keylen"] = 64 + elif pbe_oid == _OID_PBE_WITH_SHA1_AND_DES_CBC: + # PBE_SHA1_DES_CBC + from Cryptodome.Hash import SHA1 + from Cryptodome.Cipher import DES + + hashmod = SHA1 + module = DES + elif pbe_oid == _OID_PBE_WITH_SHA1_AND_RC2_CBC: + # PBE_SHA1_RC2_CBC + from Cryptodome.Hash import SHA1 + from Cryptodome.Cipher import ARC2 + + hashmod = SHA1 + module = ARC2 + cipher_params["effective_keylen"] = 64 + else: + raise PbesError("Unknown OID for PBES1") + + pbe_params = DerSequence().decode(encrypted_algorithm[1], nr_elements=2) + salt = DerOctetString().decode(pbe_params[0]).payload + iterations = pbe_params[1] + + key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod) + key, iv = key_iv[:8], key_iv[8:] + + cipher = module.new(key, module.MODE_CBC, iv, **cipher_params) + pt = cipher.decrypt(encrypted_data) + return unpad(pt, cipher.block_size) class PBES2(object): - """Encryption scheme with password-based key derivation - (defined in `PKCS#5 v2.0`__). - - .. __: http://www.ietf.org/rfc/rfc2898.txt.""" - - @staticmethod - def encrypt(data, passphrase, protection, prot_params=None, randfunc=None): - """Encrypt a piece of data using a passphrase and *PBES2*. - - :Parameters: - data : byte string - The piece of data to encrypt. - passphrase : byte string - The passphrase to use for encrypting the data. - protection : string - The identifier of the encryption algorithm to use. - The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'. - prot_params : dictionary - Parameters of the protection algorithm. - - +------------------+-----------------------------------------------+ - | Key | Description | - +==================+===============================================+ - | iteration_count | The KDF algorithm is repeated several times to| - | | slow down brute force attacks on passwords | - | | (called *N* or CPU/memory cost in scrypt). | - | | | - | | The default value for PBKDF2 is 1 000. | - | | The default value for scrypt is 16 384. | - +------------------+-----------------------------------------------+ - | salt_size | Salt is used to thwart dictionary and rainbow | - | | attacks on passwords. The default value is 8 | - | | bytes. | - +------------------+-----------------------------------------------+ - | block_size | *(scrypt only)* Memory-cost (r). The default | - | | value is 8. | - +------------------+-----------------------------------------------+ - | parallelization | *(scrypt only)* CPU-cost (p). The default | - | | value is 1. | - +------------------+-----------------------------------------------+ - - - randfunc : callable - Random number generation function; it should accept - a single integer N and return a string of random data, - N bytes long. If not specified, a new RNG will be - instantiated from ``Cryptodome.Random``. - - :Returns: - The encrypted data, as a binary string. - """ - - if prot_params is None: - prot_params = {} - - if randfunc is None: - randfunc = Random.new().read - - pattern = re.compile(r'^(PBKDF2WithHMAC-([0-9A-Z-]+)|scrypt)And([0-9A-Z-]+)$') - res = pattern.match(protection) - if res is None: - raise ValueError("Unknown protection %s" % protection) - - if protection.startswith("PBKDF"): - pbkdf = "pbkdf2" - pbkdf2_hmac_algo = res.group(2) - enc_algo = res.group(3) - else: - pbkdf = "scrypt" - enc_algo = res.group(3) - - aead = False - if enc_algo == 'DES-EDE3-CBC': - from Cryptodome.Cipher import DES3 - key_size = 24 - module = DES3 - cipher_mode = DES3.MODE_CBC - enc_oid = _OID_DES_EDE3_CBC - enc_param = {'iv': randfunc(8)} - elif enc_algo == 'AES128-CBC': - key_size = 16 - module = AES - cipher_mode = AES.MODE_CBC - enc_oid = _OID_AES128_CBC - enc_param = {'iv': randfunc(16)} - elif enc_algo == 'AES192-CBC': - key_size = 24 - module = AES - cipher_mode = AES.MODE_CBC - enc_oid = _OID_AES192_CBC - enc_param = {'iv': randfunc(16)} - elif enc_algo == 'AES256-CBC': - key_size = 32 - module = AES - cipher_mode = AES.MODE_CBC - enc_oid = _OID_AES256_CBC - enc_param = {'iv': randfunc(16)} - elif enc_algo == 'AES128-GCM': - key_size = 16 - module = AES - cipher_mode = AES.MODE_GCM - enc_oid = _OID_AES128_GCM - enc_param = {'nonce': randfunc(12)} - aead = True - elif enc_algo == 'AES192-GCM': - key_size = 24 - module = AES - cipher_mode = AES.MODE_GCM - enc_oid = _OID_AES192_GCM - enc_param = {'nonce': randfunc(12)} - aead = True - elif enc_algo == 'AES256-GCM': - key_size = 32 - module = AES - cipher_mode = AES.MODE_GCM - enc_oid = _OID_AES256_GCM - enc_param = {'nonce': randfunc(12)} - aead = True - else: - raise ValueError("Unknown encryption mode '%s'" % enc_algo) - - iv_nonce = list(enc_param.values())[0] - salt = randfunc(prot_params.get("salt_size", 8)) - - # Derive key from password - if pbkdf == 'pbkdf2': - - count = prot_params.get("iteration_count", 1000) - digestmod = Hash.new(pbkdf2_hmac_algo) - - key = PBKDF2(passphrase, - salt, - key_size, - count, - hmac_hash_module=digestmod) - - pbkdf2_params = DerSequence([ - DerOctetString(salt), - DerInteger(count) - ]) - - if pbkdf2_hmac_algo != 'SHA1': - try: - hmac_oid = Hash.HMAC.new(b'', digestmod=digestmod).oid - except KeyError: - raise ValueError("No OID for HMAC hash algorithm") - pbkdf2_params.append(DerSequence([DerObjectId(hmac_oid)])) - - kdf_info = DerSequence([ - DerObjectId(_OID_PBKDF2), # PBKDF2 - pbkdf2_params - ]) - - elif pbkdf == 'scrypt': - - count = prot_params.get("iteration_count", 16384) - scrypt_r = prot_params.get('block_size', 8) - scrypt_p = prot_params.get('parallelization', 1) - key = scrypt(passphrase, salt, key_size, - count, scrypt_r, scrypt_p) - kdf_info = DerSequence([ - DerObjectId(_OID_SCRYPT), # scrypt - DerSequence([ - DerOctetString(salt), - DerInteger(count), - DerInteger(scrypt_r), - DerInteger(scrypt_p) - ]) - ]) - - else: - raise ValueError("Unknown KDF " + res.group(1)) - - # Create cipher and use it - cipher = module.new(key, cipher_mode, **enc_param) - if aead: - ct, tag = cipher.encrypt_and_digest(data) - encrypted_data = ct + tag - else: - encrypted_data = cipher.encrypt(pad(data, cipher.block_size)) - enc_info = DerSequence([ - DerObjectId(enc_oid), - DerOctetString(iv_nonce) - ]) - - # Result - enc_private_key_info = DerSequence([ - # encryptionAlgorithm - DerSequence([ - DerObjectId(_OID_PBES2), - DerSequence([ - kdf_info, - enc_info - ]), - ]), - DerOctetString(encrypted_data) - ]) - return enc_private_key_info.encode() - - @staticmethod - def decrypt(data, passphrase): - """Decrypt a piece of data using a passphrase and *PBES2*. - - The algorithm to use is automatically detected. - - :Parameters: - data : byte string - The piece of data to decrypt. - passphrase : byte string - The passphrase to use for decrypting the data. - :Returns: - The decrypted data, as a binary string. - """ - - enc_private_key_info = DerSequence().decode(data, nr_elements=2) - enc_algo = DerSequence().decode(enc_private_key_info[0]) - encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload - - pbe_oid = DerObjectId().decode(enc_algo[0]).value - if pbe_oid != _OID_PBES2: - raise PbesError("Not a PBES2 object") - - pbes2_params = DerSequence().decode(enc_algo[1], nr_elements=2) - - # Key Derivation Function selection - kdf_info = DerSequence().decode(pbes2_params[0], nr_elements=2) - kdf_oid = DerObjectId().decode(kdf_info[0]).value - - kdf_key_length = None - - # We only support PBKDF2 or scrypt - if kdf_oid == _OID_PBKDF2: - - pbkdf2_params = DerSequence().decode(kdf_info[1], nr_elements=(2, 3, 4)) - salt = DerOctetString().decode(pbkdf2_params[0]).payload - iteration_count = pbkdf2_params[1] - - left = len(pbkdf2_params) - 2 - idx = 2 - - if left > 0: - try: - # Check if it's an INTEGER - kdf_key_length = pbkdf2_params[idx] - 0 - left -= 1 - idx += 1 - except TypeError: - # keyLength is not present - pass - - # Default is HMAC-SHA1 - pbkdf2_prf_oid = _OID_HMAC_SHA1 - if left > 0: - pbkdf2_prf_algo_id = DerSequence().decode(pbkdf2_params[idx]) - pbkdf2_prf_oid = DerObjectId().decode(pbkdf2_prf_algo_id[0]).value - - elif kdf_oid == _OID_SCRYPT: - - scrypt_params = DerSequence().decode(kdf_info[1], nr_elements=(4, 5)) - salt = DerOctetString().decode(scrypt_params[0]).payload - iteration_count, scrypt_r, scrypt_p = [scrypt_params[x] - for x in (1, 2, 3)] - if len(scrypt_params) > 4: - kdf_key_length = scrypt_params[4] - else: - kdf_key_length = None - else: - raise PbesError("Unsupported PBES2 KDF") - - # Cipher selection - enc_info = DerSequence().decode(pbes2_params[1]) - enc_oid = DerObjectId().decode(enc_info[0]).value - - aead = False - if enc_oid == _OID_DES_EDE3_CBC: - # DES_EDE3_CBC - from Cryptodome.Cipher import DES3 - module = DES3 - cipher_mode = DES3.MODE_CBC - key_size = 24 - cipher_param = 'iv' - elif enc_oid == _OID_AES128_CBC: - module = AES - cipher_mode = AES.MODE_CBC - key_size = 16 - cipher_param = 'iv' - elif enc_oid == _OID_AES192_CBC: - module = AES - cipher_mode = AES.MODE_CBC - key_size = 24 - cipher_param = 'iv' - elif enc_oid == _OID_AES256_CBC: - module = AES - cipher_mode = AES.MODE_CBC - key_size = 32 - cipher_param = 'iv' - elif enc_oid == _OID_AES128_GCM: - module = AES - cipher_mode = AES.MODE_GCM - key_size = 16 - cipher_param = 'nonce' - aead = True - elif enc_oid == _OID_AES192_GCM: - module = AES - cipher_mode = AES.MODE_GCM - key_size = 24 - cipher_param = 'nonce' - aead = True - elif enc_oid == _OID_AES256_GCM: - module = AES - cipher_mode = AES.MODE_GCM - key_size = 32 - cipher_param = 'nonce' - aead = True - else: - raise PbesError("Unsupported PBES2 cipher " + enc_algo) - - if kdf_key_length and kdf_key_length != key_size: - raise PbesError("Mismatch between PBES2 KDF parameters" - " and selected cipher") - - iv_nonce = DerOctetString().decode(enc_info[1]).payload - - # Create cipher - if kdf_oid == _OID_PBKDF2: - - try: - hmac_hash_module_oid = Hash.HMAC._hmac2hash_oid[pbkdf2_prf_oid] - except KeyError: - raise PbesError("Unsupported HMAC %s" % pbkdf2_prf_oid) - hmac_hash_module = Hash.new(hmac_hash_module_oid) - - key = PBKDF2(passphrase, salt, key_size, iteration_count, - hmac_hash_module=hmac_hash_module) - else: - key = scrypt(passphrase, salt, key_size, iteration_count, - scrypt_r, scrypt_p) - cipher = module.new(key, cipher_mode, **{cipher_param:iv_nonce}) - - # Decrypt data - if len(encrypted_data) < cipher.block_size: - raise ValueError("Too little data to decrypt") - - if aead: - tag_len = cipher.block_size - pt = cipher.decrypt_and_verify(encrypted_data[:-tag_len], - encrypted_data[-tag_len:]) - else: - pt_padded = cipher.decrypt(encrypted_data) - pt = unpad(pt_padded, cipher.block_size) - - return pt + """Encryption scheme with password-based key derivation + (defined in `PKCS#5 v2.0`__). + + .. __: http://www.ietf.org/rfc/rfc2898.txt.""" + + @staticmethod + def encrypt(data, passphrase, protection, prot_params=None, randfunc=None): + """Encrypt a piece of data using a passphrase and *PBES2*. + + :Parameters: + data : byte string + The piece of data to encrypt. + passphrase : byte string + The passphrase to use for encrypting the data. + protection : string + The identifier of the encryption algorithm to use. + The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'. + prot_params : dictionary + Parameters of the protection algorithm. + + +------------------+-----------------------------------------------+ + | Key | Description | + +==================+===============================================+ + | iteration_count | The KDF algorithm is repeated several times to| + | | slow down brute force attacks on passwords | + | | (called *N* or CPU/memory cost in scrypt). | + | | | + | | The default value for PBKDF2 is 1 000. | + | | The default value for scrypt is 16 384. | + +------------------+-----------------------------------------------+ + | salt_size | Salt is used to thwart dictionary and rainbow | + | | attacks on passwords. The default value is 8 | + | | bytes. | + +------------------+-----------------------------------------------+ + | block_size | *(scrypt only)* Memory-cost (r). The default | + | | value is 8. | + +------------------+-----------------------------------------------+ + | parallelization | *(scrypt only)* CPU-cost (p). The default | + | | value is 1. | + +------------------+-----------------------------------------------+ + + + randfunc : callable + Random number generation function; it should accept + a single integer N and return a string of random data, + N bytes long. If not specified, a new RNG will be + instantiated from ``Cryptodome.Random``. + + :Returns: + The encrypted data, as a binary string. + """ + + if prot_params is None: + prot_params = {} + + if randfunc is None: + randfunc = Random.new().read + + pattern = re.compile(r"^(PBKDF2WithHMAC-([0-9A-Z-]+)|scrypt)And([0-9A-Z-]+)$") + res = pattern.match(protection) + if res is None: + raise ValueError("Unknown protection %s" % protection) + + if protection.startswith("PBKDF"): + pbkdf = "pbkdf2" + pbkdf2_hmac_algo = res.group(2) + enc_algo = res.group(3) + else: + pbkdf = "scrypt" + enc_algo = res.group(3) + + aead = False + if enc_algo == "DES-EDE3-CBC": + from Cryptodome.Cipher import DES3 + + key_size = 24 + module = DES3 + cipher_mode = DES3.MODE_CBC + enc_oid = _OID_DES_EDE3_CBC + enc_param = {"iv": randfunc(8)} + elif enc_algo == "AES128-CBC": + key_size = 16 + module = AES + cipher_mode = AES.MODE_CBC + enc_oid = _OID_AES128_CBC + enc_param = {"iv": randfunc(16)} + elif enc_algo == "AES192-CBC": + key_size = 24 + module = AES + cipher_mode = AES.MODE_CBC + enc_oid = _OID_AES192_CBC + enc_param = {"iv": randfunc(16)} + elif enc_algo == "AES256-CBC": + key_size = 32 + module = AES + cipher_mode = AES.MODE_CBC + enc_oid = _OID_AES256_CBC + enc_param = {"iv": randfunc(16)} + elif enc_algo == "AES128-GCM": + key_size = 16 + module = AES + cipher_mode = AES.MODE_GCM + enc_oid = _OID_AES128_GCM + enc_param = {"nonce": randfunc(12)} + aead = True + elif enc_algo == "AES192-GCM": + key_size = 24 + module = AES + cipher_mode = AES.MODE_GCM + enc_oid = _OID_AES192_GCM + enc_param = {"nonce": randfunc(12)} + aead = True + elif enc_algo == "AES256-GCM": + key_size = 32 + module = AES + cipher_mode = AES.MODE_GCM + enc_oid = _OID_AES256_GCM + enc_param = {"nonce": randfunc(12)} + aead = True + else: + raise ValueError("Unknown encryption mode '%s'" % enc_algo) + + iv_nonce = list(enc_param.values())[0] + salt = randfunc(prot_params.get("salt_size", 8)) + + # Derive key from password + if pbkdf == "pbkdf2": + count = prot_params.get("iteration_count", 1000) + digestmod = Hash.new(pbkdf2_hmac_algo) + + key = PBKDF2( + passphrase, + salt, + key_size, + count, + hmac_hash_module=digestmod, + ) + + pbkdf2_params = DerSequence( + [ + DerOctetString(salt), + DerInteger(count), + ] + ) + + if pbkdf2_hmac_algo != "SHA1": + try: + hmac_oid = Hash.HMAC.new(b"", digestmod=digestmod).oid + except KeyError: + raise ValueError("No OID for HMAC hash algorithm") + pbkdf2_params.append(DerSequence([DerObjectId(hmac_oid)])) + + kdf_info = DerSequence( + [ + DerObjectId(_OID_PBKDF2), # PBKDF2 + pbkdf2_params, + ] + ) + + elif pbkdf == "scrypt": + count = prot_params.get("iteration_count", 16384) + scrypt_r = prot_params.get("block_size", 8) + scrypt_p = prot_params.get("parallelization", 1) + key = scrypt( + passphrase, + salt, + key_size, + count, + scrypt_r, + scrypt_p, + ) + kdf_info = DerSequence( + [ + DerObjectId(_OID_SCRYPT), # scrypt + DerSequence( + [ + DerOctetString(salt), + DerInteger(count), + DerInteger(scrypt_r), + DerInteger(scrypt_p), + ] + ), + ] + ) + + else: + raise ValueError("Unknown KDF " + res.group(1)) + + # Create cipher and use it + cipher = module.new(key, cipher_mode, **enc_param) + if aead: + ct, tag = cipher.encrypt_and_digest(data) + encrypted_data = ct + tag + else: + encrypted_data = cipher.encrypt(pad(data, cipher.block_size)) + enc_info = DerSequence( + [ + DerObjectId(enc_oid), + DerOctetString(iv_nonce), + ] + ) + + # Result + enc_private_key_info = DerSequence( + [ + # encryptionAlgorithm + DerSequence( + [ + DerObjectId(_OID_PBES2), + DerSequence( + [ + kdf_info, + enc_info, + ] + ), + ] + ), + DerOctetString(encrypted_data), + ] + ) + return enc_private_key_info.encode() + + @staticmethod + def decrypt(data, passphrase): + """Decrypt a piece of data using a passphrase and *PBES2*. + + The algorithm to use is automatically detected. + + :Parameters: + data : byte string + The piece of data to decrypt. + passphrase : byte string + The passphrase to use for decrypting the data. + :Returns: + The decrypted data, as a binary string. + """ + + enc_private_key_info = DerSequence().decode(data, nr_elements=2) + enc_algo = DerSequence().decode(enc_private_key_info[0]) + encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload + + pbe_oid = DerObjectId().decode(enc_algo[0]).value + if pbe_oid != _OID_PBES2: + raise PbesError("Not a PBES2 object") + + pbes2_params = DerSequence().decode(enc_algo[1], nr_elements=2) + + # Key Derivation Function selection + kdf_info = DerSequence().decode(pbes2_params[0], nr_elements=2) + kdf_oid = DerObjectId().decode(kdf_info[0]).value + + kdf_key_length = None + + # We only support PBKDF2 or scrypt + if kdf_oid == _OID_PBKDF2: + pbkdf2_params = DerSequence().decode(kdf_info[1], nr_elements=(2, 3, 4)) + salt = DerOctetString().decode(pbkdf2_params[0]).payload + iteration_count = pbkdf2_params[1] + + left = len(pbkdf2_params) - 2 + idx = 2 + + if left > 0: + try: + # Check if it's an INTEGER + kdf_key_length = pbkdf2_params[idx] - 0 + left -= 1 + idx += 1 + except TypeError: + # keyLength is not present + pass + + # Default is HMAC-SHA1 + pbkdf2_prf_oid = _OID_HMAC_SHA1 + if left > 0: + pbkdf2_prf_algo_id = DerSequence().decode(pbkdf2_params[idx]) + pbkdf2_prf_oid = DerObjectId().decode(pbkdf2_prf_algo_id[0]).value + + elif kdf_oid == _OID_SCRYPT: + scrypt_params = DerSequence().decode(kdf_info[1], nr_elements=(4, 5)) + salt = DerOctetString().decode(scrypt_params[0]).payload + iteration_count, scrypt_r, scrypt_p = [scrypt_params[x] for x in (1, 2, 3)] + if len(scrypt_params) > 4: + kdf_key_length = scrypt_params[4] + else: + kdf_key_length = None + else: + raise PbesError("Unsupported PBES2 KDF") + + # Cipher selection + enc_info = DerSequence().decode(pbes2_params[1]) + enc_oid = DerObjectId().decode(enc_info[0]).value + + aead = False + if enc_oid == _OID_DES_EDE3_CBC: + # DES_EDE3_CBC + from Cryptodome.Cipher import DES3 + + module = DES3 + cipher_mode = DES3.MODE_CBC + key_size = 24 + cipher_param = "iv" + elif enc_oid == _OID_AES128_CBC: + module = AES + cipher_mode = AES.MODE_CBC + key_size = 16 + cipher_param = "iv" + elif enc_oid == _OID_AES192_CBC: + module = AES + cipher_mode = AES.MODE_CBC + key_size = 24 + cipher_param = "iv" + elif enc_oid == _OID_AES256_CBC: + module = AES + cipher_mode = AES.MODE_CBC + key_size = 32 + cipher_param = "iv" + elif enc_oid == _OID_AES128_GCM: + module = AES + cipher_mode = AES.MODE_GCM + key_size = 16 + cipher_param = "nonce" + aead = True + elif enc_oid == _OID_AES192_GCM: + module = AES + cipher_mode = AES.MODE_GCM + key_size = 24 + cipher_param = "nonce" + aead = True + elif enc_oid == _OID_AES256_GCM: + module = AES + cipher_mode = AES.MODE_GCM + key_size = 32 + cipher_param = "nonce" + aead = True + else: + raise PbesError("Unsupported PBES2 cipher " + enc_algo) + + if kdf_key_length and kdf_key_length != key_size: + raise PbesError( + "Mismatch between PBES2 KDF parameters and selected cipher", + ) + + iv_nonce = DerOctetString().decode(enc_info[1]).payload + + # Create cipher + if kdf_oid == _OID_PBKDF2: + try: + hmac_hash_module_oid = Hash.HMAC._hmac2hash_oid[pbkdf2_prf_oid] + except KeyError: + raise PbesError("Unsupported HMAC %s" % pbkdf2_prf_oid) + hmac_hash_module = Hash.new(hmac_hash_module_oid) + + key = PBKDF2( + passphrase, + salt, + key_size, + iteration_count, + hmac_hash_module=hmac_hash_module, + ) + else: + key = scrypt( + passphrase, + salt, + key_size, + iteration_count, + scrypt_r, + scrypt_p, + ) + cipher = module.new(key, cipher_mode, **{cipher_param: iv_nonce}) + + # Decrypt data + if len(encrypted_data) < cipher.block_size: + raise ValueError("Too little data to decrypt") + + if aead: + tag_len = cipher.block_size + pt = cipher.decrypt_and_verify( + encrypted_data[:-tag_len], + encrypted_data[-tag_len:], + ) + else: + pt_padded = cipher.decrypt(encrypted_data) + pt = unpad(pt_padded, cipher.block_size) + + return pt diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/_PBES.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/_PBES.pyi index 06733640..ca27e7fd 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/_PBES.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/_PBES.pyi @@ -1,26 +1,26 @@ from typing import Optional, Callable, TypedDict from typing_extensions import NotRequired -class PbesError(ValueError): - ... +class PbesError(ValueError): ... class PBES1(object): - @staticmethod - def decrypt(data: bytes, passphrase: bytes) -> bytes: ... + @staticmethod + def decrypt(data: bytes, passphrase: bytes) -> bytes: ... class ProtParams(TypedDict): - iteration_count: NotRequired[int] - salt_size: NotRequired[int] - block_size: NotRequired[int] - parallelization: NotRequired[int] + iteration_count: NotRequired[int] + salt_size: NotRequired[int] + block_size: NotRequired[int] + parallelization: NotRequired[int] class PBES2(object): - @staticmethod - def encrypt(data: bytes, - passphrase: bytes, - protection: str, - prot_params: Optional[ProtParams] = ..., - randfunc: Optional[Callable[[int],bytes]] = ...) -> bytes: ... - - @staticmethod - def decrypt(data:bytes, passphrase: bytes) -> bytes: ... + @staticmethod + def encrypt( + data: bytes, + passphrase: bytes, + protection: str, + prot_params: Optional[ProtParams] = ..., + randfunc: Optional[Callable[[int], bytes]] = ..., + ) -> bytes: ... + @staticmethod + def decrypt(data: bytes, passphrase: bytes) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/__init__.py index 85a0d0b1..794fb76e 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/IO/__init__.py @@ -28,4 +28,4 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = ['PEM', 'PKCS8'] +__all__ = ["PEM", "PKCS8"] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Numbers.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Numbers.py index 9e96686b..0724e9f0 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Numbers.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Numbers.py @@ -33,15 +33,16 @@ import os try: - if os.getenv("PYCRYPTODOME_DISABLE_GMP"): - raise ImportError() + if os.getenv("PYCRYPTODOME_DISABLE_GMP"): + raise ImportError() - from Cryptodome.Math._IntegerGMP import IntegerGMP as Integer - from Cryptodome.Math._IntegerGMP import implementation as _implementation + from Cryptodome.Math._IntegerGMP import IntegerGMP as Integer + from Cryptodome.Math._IntegerGMP import implementation as _implementation except (ImportError, OSError, AttributeError): - try: - from Cryptodome.Math._IntegerCustom import IntegerCustom as Integer - from Cryptodome.Math._IntegerCustom import implementation as _implementation - except (ImportError, OSError): - from Cryptodome.Math._IntegerNative import IntegerNative as Integer - _implementation = {} + try: + from Cryptodome.Math._IntegerCustom import IntegerCustom as Integer + from Cryptodome.Math._IntegerCustom import implementation as _implementation + except (ImportError, OSError): + from Cryptodome.Math._IntegerNative import IntegerNative as Integer + + _implementation = {} diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Numbers.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Numbers.pyi index b0206ca4..4cb0a758 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Numbers.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Numbers.pyi @@ -1,2 +1,3 @@ from Cryptodome.Math._IntegerBase import IntegerBase as Integer -__all__ = ['Integer'] + +__all__ = ["Integer"] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Primality.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Primality.py index 33814fa8..ae81b658 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Primality.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Primality.py @@ -43,327 +43,353 @@ def miller_rabin_test(candidate, iterations, randfunc=None): - """Perform a Miller-Rabin primality test on an integer. - - The test is specified in Section C.3.1 of `FIPS PUB 186-4`__. - - :Parameters: - candidate : integer - The number to test for primality. - iterations : integer - The maximum number of iterations to perform before - declaring a candidate a probable prime. - randfunc : callable - An RNG function where bases are taken from. - - :Returns: - ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. - - .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if not isinstance(candidate, Integer): - candidate = Integer(candidate) - - if candidate in (1, 2, 3, 5): - return PROBABLY_PRIME - - if candidate.is_even(): - return COMPOSITE - - one = Integer(1) - minus_one = Integer(candidate - 1) - - if randfunc is None: - randfunc = Random.new().read - - # Step 1 and 2 - m = Integer(minus_one) - a = 0 - while m.is_even(): - m >>= 1 - a += 1 - - # Skip step 3 - - # Step 4 - for i in iter_range(iterations): - - # Step 4.1-2 - base = 1 - while base in (one, minus_one): - base = Integer.random_range(min_inclusive=2, - max_inclusive=candidate - 2, - randfunc=randfunc) - assert(2 <= base <= candidate - 2) - - # Step 4.3-4.4 - z = pow(base, m, candidate) - if z in (one, minus_one): - continue - - # Step 4.5 - for j in iter_range(1, a): - z = pow(z, 2, candidate) - if z == minus_one: - break - if z == one: - return COMPOSITE - else: - return COMPOSITE - - # Step 5 - return PROBABLY_PRIME + """Perform a Miller-Rabin primality test on an integer. + + The test is specified in Section C.3.1 of `FIPS PUB 186-4`__. + + :Parameters: + candidate : integer + The number to test for primality. + iterations : integer + The maximum number of iterations to perform before + declaring a candidate a probable prime. + randfunc : callable + An RNG function where bases are taken from. + + :Returns: + ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. + + .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ + + if not isinstance(candidate, Integer): + candidate = Integer(candidate) + + if candidate in (1, 2, 3, 5): + return PROBABLY_PRIME + + if candidate.is_even(): + return COMPOSITE + + one = Integer(1) + minus_one = Integer(candidate - 1) + + if randfunc is None: + randfunc = Random.new().read + + # Step 1 and 2 + m = Integer(minus_one) + a = 0 + while m.is_even(): + m >>= 1 + a += 1 + + # Skip step 3 + + # Step 4 + for i in iter_range(iterations): + # Step 4.1-2 + base = 1 + while base in (one, minus_one): + base = Integer.random_range( + min_inclusive=2, + max_inclusive=candidate - 2, + randfunc=randfunc, + ) + assert 2 <= base <= candidate - 2 + + # Step 4.3-4.4 + z = pow(base, m, candidate) + if z in (one, minus_one): + continue + + # Step 4.5 + for j in iter_range(1, a): + z = pow(z, 2, candidate) + if z == minus_one: + break + if z == one: + return COMPOSITE + else: + return COMPOSITE + + # Step 5 + return PROBABLY_PRIME def lucas_test(candidate): - """Perform a Lucas primality test on an integer. - - The test is specified in Section C.3.3 of `FIPS PUB 186-4`__. - - :Parameters: - candidate : integer - The number to test for primality. - - :Returns: - ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. - - .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if not isinstance(candidate, Integer): - candidate = Integer(candidate) - - # Step 1 - if candidate in (1, 2, 3, 5): - return PROBABLY_PRIME - if candidate.is_even() or candidate.is_perfect_square(): - return COMPOSITE - - # Step 2 - def alternate(): - value = 5 - while True: - yield value - if value > 0: - value += 2 - else: - value -= 2 - value = -value - - for D in alternate(): - if candidate in (D, -D): - continue - js = Integer.jacobi_symbol(D, candidate) - if js == 0: - return COMPOSITE - if js == -1: - break - # Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer) - - # Step 3 - # This is \delta(n) = n - jacobi(D/n) - K = candidate + 1 - # Step 4 - r = K.size_in_bits() - 1 - # Step 5 - # U_1=1 and V_1=P - U_i = Integer(1) - V_i = Integer(1) - U_temp = Integer(0) - V_temp = Integer(0) - # Step 6 - for i in iter_range(r - 1, -1, -1): - # Square - # U_temp = U_i * V_i % candidate - U_temp.set(U_i) - U_temp *= V_i - U_temp %= candidate - # V_temp = (((V_i ** 2 + (U_i ** 2 * D)) * K) >> 1) % candidate - V_temp.set(U_i) - V_temp *= U_i - V_temp *= D - V_temp.multiply_accumulate(V_i, V_i) - if V_temp.is_odd(): - V_temp += candidate - V_temp >>= 1 - V_temp %= candidate - # Multiply - if K.get_bit(i): - # U_i = (((U_temp + V_temp) * K) >> 1) % candidate - U_i.set(U_temp) - U_i += V_temp - if U_i.is_odd(): - U_i += candidate - U_i >>= 1 - U_i %= candidate - # V_i = (((V_temp + U_temp * D) * K) >> 1) % candidate - V_i.set(V_temp) - V_i.multiply_accumulate(U_temp, D) - if V_i.is_odd(): - V_i += candidate - V_i >>= 1 - V_i %= candidate - else: - U_i.set(U_temp) - V_i.set(V_temp) - # Step 7 - if U_i == 0: - return PROBABLY_PRIME - return COMPOSITE + """Perform a Lucas primality test on an integer. + + The test is specified in Section C.3.3 of `FIPS PUB 186-4`__. + + :Parameters: + candidate : integer + The number to test for primality. + + :Returns: + ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. + + .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ + + if not isinstance(candidate, Integer): + candidate = Integer(candidate) + + # Step 1 + if candidate in (1, 2, 3, 5): + return PROBABLY_PRIME + if candidate.is_even() or candidate.is_perfect_square(): + return COMPOSITE + + # Step 2 + def alternate(): + value = 5 + while True: + yield value + if value > 0: + value += 2 + else: + value -= 2 + value = -value + + for D in alternate(): + if candidate in (D, -D): + continue + js = Integer.jacobi_symbol(D, candidate) + if js == 0: + return COMPOSITE + if js == -1: + break + # Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer) + + # Step 3 + # This is \delta(n) = n - jacobi(D/n) + K = candidate + 1 + # Step 4 + r = K.size_in_bits() - 1 + # Step 5 + # U_1=1 and V_1=P + U_i = Integer(1) + V_i = Integer(1) + U_temp = Integer(0) + V_temp = Integer(0) + # Step 6 + for i in iter_range(r - 1, -1, -1): + # Square + # U_temp = U_i * V_i % candidate + U_temp.set(U_i) + U_temp *= V_i + U_temp %= candidate + # V_temp = (((V_i ** 2 + (U_i ** 2 * D)) * K) >> 1) % candidate + V_temp.set(U_i) + V_temp *= U_i + V_temp *= D + V_temp.multiply_accumulate(V_i, V_i) + if V_temp.is_odd(): + V_temp += candidate + V_temp >>= 1 + V_temp %= candidate + # Multiply + if K.get_bit(i): + # U_i = (((U_temp + V_temp) * K) >> 1) % candidate + U_i.set(U_temp) + U_i += V_temp + if U_i.is_odd(): + U_i += candidate + U_i >>= 1 + U_i %= candidate + # V_i = (((V_temp + U_temp * D) * K) >> 1) % candidate + V_i.set(V_temp) + V_i.multiply_accumulate(U_temp, D) + if V_i.is_odd(): + V_i += candidate + V_i >>= 1 + V_i %= candidate + else: + U_i.set(U_temp) + V_i.set(V_temp) + # Step 7 + if U_i == 0: + return PROBABLY_PRIME + return COMPOSITE from Cryptodome.Util.number import sieve_base as _sieve_base_large + ## The optimal number of small primes to use for the sieve ## is probably dependent on the platform and the candidate size _sieve_base = set(_sieve_base_large[:100]) def test_probable_prime(candidate, randfunc=None): - """Test if a number is prime. - - A number is qualified as prime if it passes a certain - number of Miller-Rabin tests (dependent on the size - of the number, but such that probability of a false - positive is less than 10^-30) and a single Lucas test. - - For instance, a 1024-bit candidate will need to pass - 4 Miller-Rabin tests. - - :Parameters: - candidate : integer - The number to test for primality. - randfunc : callable - The routine to draw random bytes from to select Miller-Rabin bases. - :Returns: - ``PROBABLE_PRIME`` if the number if prime with very high probability. - ``COMPOSITE`` if the number is a composite. - For efficiency reasons, ``COMPOSITE`` is also returned for small primes. - """ - - if randfunc is None: - randfunc = Random.new().read - - if not isinstance(candidate, Integer): - candidate = Integer(candidate) - - # First, check trial division by the smallest primes - if int(candidate) in _sieve_base: - return PROBABLY_PRIME - try: - map(candidate.fail_if_divisible_by, _sieve_base) - except ValueError: - return COMPOSITE - - # These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30, - # with p(k, t) being the probability that a randomly chosen k-bit number - # is composite but still survives t MR iterations. - mr_ranges = ((220, 30), (280, 20), (390, 15), (512, 10), - (620, 7), (740, 6), (890, 5), (1200, 4), - (1700, 3), (3700, 2)) - - bit_size = candidate.size_in_bits() - try: - mr_iterations = list(filter(lambda x: bit_size < x[0], - mr_ranges))[0][1] - except IndexError: - mr_iterations = 1 - - if miller_rabin_test(candidate, mr_iterations, - randfunc=randfunc) == COMPOSITE: - return COMPOSITE - if lucas_test(candidate) == COMPOSITE: - return COMPOSITE - return PROBABLY_PRIME + """Test if a number is prime. + + A number is qualified as prime if it passes a certain + number of Miller-Rabin tests (dependent on the size + of the number, but such that probability of a false + positive is less than 10^-30) and a single Lucas test. + + For instance, a 1024-bit candidate will need to pass + 4 Miller-Rabin tests. + + :Parameters: + candidate : integer + The number to test for primality. + randfunc : callable + The routine to draw random bytes from to select Miller-Rabin bases. + :Returns: + ``PROBABLE_PRIME`` if the number if prime with very high probability. + ``COMPOSITE`` if the number is a composite. + For efficiency reasons, ``COMPOSITE`` is also returned for small primes. + """ + + if randfunc is None: + randfunc = Random.new().read + + if not isinstance(candidate, Integer): + candidate = Integer(candidate) + + # First, check trial division by the smallest primes + if int(candidate) in _sieve_base: + return PROBABLY_PRIME + try: + map(candidate.fail_if_divisible_by, _sieve_base) + except ValueError: + return COMPOSITE + + # These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30, + # with p(k, t) being the probability that a randomly chosen k-bit number + # is composite but still survives t MR iterations. + mr_ranges = ( + (220, 30), + (280, 20), + (390, 15), + (512, 10), + (620, 7), + (740, 6), + (890, 5), + (1200, 4), + (1700, 3), + (3700, 2), + ) + + bit_size = candidate.size_in_bits() + try: + mr_iterations = list( + filter( + lambda x: bit_size < x[0], + mr_ranges, + ), + )[0][1] + except IndexError: + mr_iterations = 1 + + if ( + miller_rabin_test( + candidate, + mr_iterations, + randfunc=randfunc, + ) + == COMPOSITE + ): + return COMPOSITE + if lucas_test(candidate) == COMPOSITE: + return COMPOSITE + return PROBABLY_PRIME def generate_probable_prime(**kwargs): - """Generate a random probable prime. - - The prime will not have any specific properties - (e.g. it will not be a *strong* prime). - - Random numbers are evaluated for primality until one - passes all tests, consisting of a certain number of - Miller-Rabin tests with random bases followed by - a single Lucas test. - - The number of Miller-Rabin iterations is chosen such that - the probability that the output number is a non-prime is - less than 1E-30 (roughly 2^{-100}). - - This approach is compliant to `FIPS PUB 186-4`__. - - :Keywords: - exact_bits : integer - The desired size in bits of the probable prime. - It must be at least 160. - randfunc : callable - An RNG function where candidate primes are taken from. - prime_filter : callable - A function that takes an Integer as parameter and returns - True if the number can be passed to further primality tests, - False if it should be immediately discarded. - - :Return: - A probable prime in the range 2^exact_bits > p > 2^(exact_bits-1). - - .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - exact_bits = kwargs.pop("exact_bits", None) - randfunc = kwargs.pop("randfunc", None) - prime_filter = kwargs.pop("prime_filter", lambda x: True) - if kwargs: - raise ValueError("Unknown parameters: " + kwargs.keys()) - - if exact_bits is None: - raise ValueError("Missing exact_bits parameter") - if exact_bits < 160: - raise ValueError("Prime number is not big enough.") - - if randfunc is None: - randfunc = Random.new().read - - result = COMPOSITE - while result == COMPOSITE: - candidate = Integer.random(exact_bits=exact_bits, - randfunc=randfunc) | 1 - if not prime_filter(candidate): - continue - result = test_probable_prime(candidate, randfunc) - return candidate + """Generate a random probable prime. + + The prime will not have any specific properties + (e.g. it will not be a *strong* prime). + + Random numbers are evaluated for primality until one + passes all tests, consisting of a certain number of + Miller-Rabin tests with random bases followed by + a single Lucas test. + + The number of Miller-Rabin iterations is chosen such that + the probability that the output number is a non-prime is + less than 1E-30 (roughly 2^{-100}). + + This approach is compliant to `FIPS PUB 186-4`__. + + :Keywords: + exact_bits : integer + The desired size in bits of the probable prime. + It must be at least 160. + randfunc : callable + An RNG function where candidate primes are taken from. + prime_filter : callable + A function that takes an Integer as parameter and returns + True if the number can be passed to further primality tests, + False if it should be immediately discarded. + + :Return: + A probable prime in the range 2^exact_bits > p > 2^(exact_bits-1). + + .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ + + exact_bits = kwargs.pop("exact_bits", None) + randfunc = kwargs.pop("randfunc", None) + prime_filter = kwargs.pop("prime_filter", lambda x: True) + if kwargs: + raise ValueError("Unknown parameters: " + kwargs.keys()) + + if exact_bits is None: + raise ValueError("Missing exact_bits parameter") + if exact_bits < 160: + raise ValueError("Prime number is not big enough.") + + if randfunc is None: + randfunc = Random.new().read + + result = COMPOSITE + while result == COMPOSITE: + candidate = ( + Integer.random( + exact_bits=exact_bits, + randfunc=randfunc, + ) + | 1 + ) + if not prime_filter(candidate): + continue + result = test_probable_prime(candidate, randfunc) + return candidate def generate_probable_safe_prime(**kwargs): - """Generate a random, probable safe prime. - - Note this operation is much slower than generating a simple prime. - - :Keywords: - exact_bits : integer - The desired size in bits of the probable safe prime. - randfunc : callable - An RNG function where candidate primes are taken from. - - :Return: - A probable safe prime in the range - 2^exact_bits > p > 2^(exact_bits-1). - """ - - exact_bits = kwargs.pop("exact_bits", None) - randfunc = kwargs.pop("randfunc", None) - if kwargs: - raise ValueError("Unknown parameters: " + kwargs.keys()) - - if randfunc is None: - randfunc = Random.new().read - - result = COMPOSITE - while result == COMPOSITE: - q = generate_probable_prime(exact_bits=exact_bits - 1, randfunc=randfunc) - candidate = q * 2 + 1 - if candidate.size_in_bits() != exact_bits: - continue - result = test_probable_prime(candidate, randfunc=randfunc) - return candidate + """Generate a random, probable safe prime. + + Note this operation is much slower than generating a simple prime. + + :Keywords: + exact_bits : integer + The desired size in bits of the probable safe prime. + randfunc : callable + An RNG function where candidate primes are taken from. + + :Return: + A probable safe prime in the range + 2^exact_bits > p > 2^(exact_bits-1). + """ + + exact_bits = kwargs.pop("exact_bits", None) + randfunc = kwargs.pop("randfunc", None) + if kwargs: + raise ValueError("Unknown parameters: " + kwargs.keys()) + + if randfunc is None: + randfunc = Random.new().read + + result = COMPOSITE + while result == COMPOSITE: + q = generate_probable_prime(exact_bits=exact_bits - 1, randfunc=randfunc) + candidate = q * 2 + 1 + if candidate.size_in_bits() != exact_bits: + continue + result = test_probable_prime(candidate, randfunc=randfunc) + return candidate diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Primality.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Primality.pyi index 78134830..efa634d3 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Primality.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/Primality.pyi @@ -1,18 +1,22 @@ -from typing import Callable, Optional, Union, Set +from typing import Callable, Optional, Set PrimeResult = int COMPOSITE: PrimeResult PROBABLY_PRIME: PrimeResult -def miller_rabin_test(candidate: int, iterations: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ... +def miller_rabin_test( + candidate: int, iterations: int, randfunc: Optional[Callable[[int], bytes]] = None +) -> PrimeResult: ... def lucas_test(candidate: int) -> PrimeResult: ... + _sieve_base: Set[int] -def test_probable_prime(candidate: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ... -def generate_probable_prime(*, - exact_bits: int = ..., - randfunc: Callable[[int],bytes] = ..., - prime_filter: Callable[[int],bool] = ...) -> int: ... -def generate_probable_safe_prime(*, - exact_bits: int = ..., - randfunc: Callable[[int],bytes] = ...) -> int: ... + +def test_probable_prime(candidate: int, randfunc: Optional[Callable[[int], bytes]] = None) -> PrimeResult: ... +def generate_probable_prime( + *, + exact_bits: int = ..., + randfunc: Callable[[int], bytes] = ..., + prime_filter: Callable[[int], bool] = ..., +) -> int: ... +def generate_probable_safe_prime(*, exact_bits: int = ..., randfunc: Callable[[int], bytes] = ...) -> int: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerBase.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerBase.py index 03dd5916..7898b142 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerBase.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerBase.py @@ -36,377 +36,378 @@ class IntegerBase(ABC): + # Conversions + @abc.abstractmethod + def __int__(self): + pass + + @abc.abstractmethod + def __str__(self): + pass + + @abc.abstractmethod + def __repr__(self): + pass + + @abc.abstractmethod + def to_bytes(self, block_size=0, byteorder="big"): + pass + + @staticmethod + @abc.abstractmethod + def from_bytes(byte_string, byteorder="big"): + pass + + # Relations + @abc.abstractmethod + def __eq__(self, term): + pass - # Conversions - @abc.abstractmethod - def __int__(self): - pass + @abc.abstractmethod + def __ne__(self, term): + pass - @abc.abstractmethod - def __str__(self): - pass + @abc.abstractmethod + def __lt__(self, term): + pass - @abc.abstractmethod - def __repr__(self): - pass - - @abc.abstractmethod - def to_bytes(self, block_size=0, byteorder='big'): - pass - - @staticmethod - @abc.abstractmethod - def from_bytes(byte_string, byteorder='big'): - pass + @abc.abstractmethod + def __le__(self, term): + pass - # Relations - @abc.abstractmethod - def __eq__(self, term): - pass - - @abc.abstractmethod - def __ne__(self, term): - pass - - @abc.abstractmethod - def __lt__(self, term): - pass - - @abc.abstractmethod - def __le__(self, term): - pass - - @abc.abstractmethod - def __gt__(self, term): - pass - - @abc.abstractmethod - def __ge__(self, term): - pass - - @abc.abstractmethod - def __nonzero__(self): - pass - __bool__ = __nonzero__ - - @abc.abstractmethod - def is_negative(self): - pass - - # Arithmetic operations - @abc.abstractmethod - def __add__(self, term): - pass - - @abc.abstractmethod - def __sub__(self, term): - pass - - @abc.abstractmethod - def __mul__(self, factor): - pass - - @abc.abstractmethod - def __floordiv__(self, divisor): - pass - - @abc.abstractmethod - def __mod__(self, divisor): - pass - - @abc.abstractmethod - def inplace_pow(self, exponent, modulus=None): - pass - - @abc.abstractmethod - def __pow__(self, exponent, modulus=None): - pass - - @abc.abstractmethod - def __abs__(self): - pass - - @abc.abstractmethod - def sqrt(self, modulus=None): - pass - - @abc.abstractmethod - def __iadd__(self, term): - pass - - @abc.abstractmethod - def __isub__(self, term): - pass - - @abc.abstractmethod - def __imul__(self, term): - pass - - @abc.abstractmethod - def __imod__(self, term): - pass + @abc.abstractmethod + def __gt__(self, term): + pass + + @abc.abstractmethod + def __ge__(self, term): + pass + + @abc.abstractmethod + def __nonzero__(self): + pass + + __bool__ = __nonzero__ + + @abc.abstractmethod + def is_negative(self): + pass + + # Arithmetic operations + @abc.abstractmethod + def __add__(self, term): + pass + + @abc.abstractmethod + def __sub__(self, term): + pass + + @abc.abstractmethod + def __mul__(self, factor): + pass + + @abc.abstractmethod + def __floordiv__(self, divisor): + pass + + @abc.abstractmethod + def __mod__(self, divisor): + pass + + @abc.abstractmethod + def inplace_pow(self, exponent, modulus=None): + pass + + @abc.abstractmethod + def __pow__(self, exponent, modulus=None): + pass + + @abc.abstractmethod + def __abs__(self): + pass + + @abc.abstractmethod + def sqrt(self, modulus=None): + pass + + @abc.abstractmethod + def __iadd__(self, term): + pass + + @abc.abstractmethod + def __isub__(self, term): + pass + + @abc.abstractmethod + def __imul__(self, term): + pass + + @abc.abstractmethod + def __imod__(self, term): + pass - # Boolean/bit operations - @abc.abstractmethod - def __and__(self, term): - pass - - @abc.abstractmethod - def __or__(self, term): - pass - - @abc.abstractmethod - def __rshift__(self, pos): - pass - - @abc.abstractmethod - def __irshift__(self, pos): - pass - - @abc.abstractmethod - def __lshift__(self, pos): - pass - - @abc.abstractmethod - def __ilshift__(self, pos): - pass - - @abc.abstractmethod - def get_bit(self, n): - pass - - # Extra - @abc.abstractmethod - def is_odd(self): - pass - - @abc.abstractmethod - def is_even(self): - pass - - @abc.abstractmethod - def size_in_bits(self): - pass - - @abc.abstractmethod - def size_in_bytes(self): - pass - - @abc.abstractmethod - def is_perfect_square(self): - pass - - @abc.abstractmethod - def fail_if_divisible_by(self, small_prime): - pass - - @abc.abstractmethod - def multiply_accumulate(self, a, b): - pass - - @abc.abstractmethod - def set(self, source): - pass - - @abc.abstractmethod - def inplace_inverse(self, modulus): - pass - - @abc.abstractmethod - def inverse(self, modulus): - pass - - @abc.abstractmethod - def gcd(self, term): - pass - - @abc.abstractmethod - def lcm(self, term): - pass - - @staticmethod - @abc.abstractmethod - def jacobi_symbol(a, n): - pass - - @staticmethod - def _tonelli_shanks(n, p): - """Tonelli-shanks algorithm for computing the square root - of n modulo a prime p. - - n must be in the range [0..p-1]. - p must be at least even. - - The return value r is the square root of modulo p. If non-zero, - another solution will also exist (p-r). - - Note we cannot assume that p is really a prime: if it's not, - we can either raise an exception or return the correct value. - """ - - # See https://rosettacode.org/wiki/Tonelli-Shanks_algorithm - - if n in (0, 1): - return n - - if p % 4 == 3: - root = pow(n, (p + 1) // 4, p) - if pow(root, 2, p) != n: - raise ValueError("Cannot compute square root") - return root - - s = 1 - q = (p - 1) // 2 - while not (q & 1): - s += 1 - q >>= 1 - - z = n.__class__(2) - while True: - euler = pow(z, (p - 1) // 2, p) - if euler == 1: - z += 1 - continue - if euler == p - 1: - break - # Most probably p is not a prime - raise ValueError("Cannot compute square root") - - m = s - c = pow(z, q, p) - t = pow(n, q, p) - r = pow(n, (q + 1) // 2, p) - - while t != 1: - for i in iter_range(0, m): - if pow(t, 2**i, p) == 1: - break - if i == m: - raise ValueError("Cannot compute square root of %d mod %d" % (n, p)) - b = pow(c, 2**(m - i - 1), p) - m = i - c = b**2 % p - t = (t * b**2) % p - r = (r * b) % p - - if pow(r, 2, p) != n: - raise ValueError("Cannot compute square root") - - return r - - @classmethod - def random(cls, **kwargs): - """Generate a random natural integer of a certain size. - - :Keywords: - exact_bits : positive integer - The length in bits of the resulting random Integer number. - The number is guaranteed to fulfil the relation: - - 2^bits > result >= 2^(bits - 1) - - max_bits : positive integer - The maximum length in bits of the resulting random Integer number. - The number is guaranteed to fulfil the relation: - - 2^bits > result >=0 - - randfunc : callable - A function that returns a random byte string. The length of the - byte string is passed as parameter. Optional. - If not provided (or ``None``), randomness is read from the system RNG. - - :Return: a Integer object - """ - - exact_bits = kwargs.pop("exact_bits", None) - max_bits = kwargs.pop("max_bits", None) - randfunc = kwargs.pop("randfunc", None) - - if randfunc is None: - randfunc = Random.new().read - - if exact_bits is None and max_bits is None: - raise ValueError("Either 'exact_bits' or 'max_bits' must be specified") - - if exact_bits is not None and max_bits is not None: - raise ValueError("'exact_bits' and 'max_bits' are mutually exclusive") - - bits = exact_bits or max_bits - bytes_needed = ((bits - 1) // 8) + 1 - significant_bits_msb = 8 - (bytes_needed * 8 - bits) - msb = bord(randfunc(1)[0]) - if exact_bits is not None: - msb |= 1 << (significant_bits_msb - 1) - msb &= (1 << significant_bits_msb) - 1 - - return cls.from_bytes(bchr(msb) + randfunc(bytes_needed - 1)) - - @classmethod - def random_range(cls, **kwargs): - """Generate a random integer within a given internal. - - :Keywords: - min_inclusive : integer - The lower end of the interval (inclusive). - max_inclusive : integer - The higher end of the interval (inclusive). - max_exclusive : integer - The higher end of the interval (exclusive). - randfunc : callable - A function that returns a random byte string. The length of the - byte string is passed as parameter. Optional. - If not provided (or ``None``), randomness is read from the system RNG. - :Returns: - An Integer randomly taken in the given interval. - """ - - min_inclusive = kwargs.pop("min_inclusive", None) - max_inclusive = kwargs.pop("max_inclusive", None) - max_exclusive = kwargs.pop("max_exclusive", None) - randfunc = kwargs.pop("randfunc", None) - - if kwargs: - raise ValueError("Unknown keywords: " + str(kwargs.keys)) - if None not in (max_inclusive, max_exclusive): - raise ValueError("max_inclusive and max_exclusive cannot be both" - " specified") - if max_exclusive is not None: - max_inclusive = max_exclusive - 1 - if None in (min_inclusive, max_inclusive): - raise ValueError("Missing keyword to identify the interval") - - if randfunc is None: - randfunc = Random.new().read - - norm_maximum = max_inclusive - min_inclusive - bits_needed = cls(norm_maximum).size_in_bits() - - norm_candidate = -1 - while not 0 <= norm_candidate <= norm_maximum: - norm_candidate = cls.random( - max_bits=bits_needed, - randfunc=randfunc - ) - return norm_candidate + min_inclusive - - @staticmethod - @abc.abstractmethod - def _mult_modulo_bytes(term1, term2, modulus): - """Multiply two integers, take the modulo, and encode as big endian. - This specialized method is used for RSA decryption. - - Args: - term1 : integer - The first term of the multiplication, non-negative. - term2 : integer - The second term of the multiplication, non-negative. - modulus: integer - The modulus, a positive odd number. - :Returns: - A byte string, with the result of the modular multiplication - encoded in big endian mode. - It is as long as the modulus would be, with zero padding - on the left if needed. - """ - pass + # Boolean/bit operations + @abc.abstractmethod + def __and__(self, term): + pass + + @abc.abstractmethod + def __or__(self, term): + pass + + @abc.abstractmethod + def __rshift__(self, pos): + pass + + @abc.abstractmethod + def __irshift__(self, pos): + pass + + @abc.abstractmethod + def __lshift__(self, pos): + pass + + @abc.abstractmethod + def __ilshift__(self, pos): + pass + + @abc.abstractmethod + def get_bit(self, n): + pass + + # Extra + @abc.abstractmethod + def is_odd(self): + pass + + @abc.abstractmethod + def is_even(self): + pass + + @abc.abstractmethod + def size_in_bits(self): + pass + + @abc.abstractmethod + def size_in_bytes(self): + pass + + @abc.abstractmethod + def is_perfect_square(self): + pass + + @abc.abstractmethod + def fail_if_divisible_by(self, small_prime): + pass + + @abc.abstractmethod + def multiply_accumulate(self, a, b): + pass + + @abc.abstractmethod + def set(self, source): + pass + + @abc.abstractmethod + def inplace_inverse(self, modulus): + pass + + @abc.abstractmethod + def inverse(self, modulus): + pass + + @abc.abstractmethod + def gcd(self, term): + pass + + @abc.abstractmethod + def lcm(self, term): + pass + + @staticmethod + @abc.abstractmethod + def jacobi_symbol(a, n): + pass + + @staticmethod + def _tonelli_shanks(n, p): + """Tonelli-shanks algorithm for computing the square root + of n modulo a prime p. + + n must be in the range [0..p-1]. + p must be at least even. + + The return value r is the square root of modulo p. If non-zero, + another solution will also exist (p-r). + + Note we cannot assume that p is really a prime: if it's not, + we can either raise an exception or return the correct value. + """ + + # See https://rosettacode.org/wiki/Tonelli-Shanks_algorithm + + if n in (0, 1): + return n + + if p % 4 == 3: + root = pow(n, (p + 1) // 4, p) + if pow(root, 2, p) != n: + raise ValueError("Cannot compute square root") + return root + + s = 1 + q = (p - 1) // 2 + while not (q & 1): + s += 1 + q >>= 1 + + z = n.__class__(2) + while True: + euler = pow(z, (p - 1) // 2, p) + if euler == 1: + z += 1 + continue + if euler == p - 1: + break + # Most probably p is not a prime + raise ValueError("Cannot compute square root") + + m = s + c = pow(z, q, p) + t = pow(n, q, p) + r = pow(n, (q + 1) // 2, p) + + while t != 1: + for i in iter_range(0, m): + if pow(t, 2**i, p) == 1: + break + if i == m: + raise ValueError("Cannot compute square root of %d mod %d" % (n, p)) + b = pow(c, 2 ** (m - i - 1), p) + m = i + c = b**2 % p + t = (t * b**2) % p + r = (r * b) % p + + if pow(r, 2, p) != n: + raise ValueError("Cannot compute square root") + + return r + + @classmethod + def random(cls, **kwargs): + """Generate a random natural integer of a certain size. + + :Keywords: + exact_bits : positive integer + The length in bits of the resulting random Integer number. + The number is guaranteed to fulfil the relation: + + 2^bits > result >= 2^(bits - 1) + + max_bits : positive integer + The maximum length in bits of the resulting random Integer number. + The number is guaranteed to fulfil the relation: + + 2^bits > result >=0 + + randfunc : callable + A function that returns a random byte string. The length of the + byte string is passed as parameter. Optional. + If not provided (or ``None``), randomness is read from the system RNG. + + :Return: a Integer object + """ + + exact_bits = kwargs.pop("exact_bits", None) + max_bits = kwargs.pop("max_bits", None) + randfunc = kwargs.pop("randfunc", None) + + if randfunc is None: + randfunc = Random.new().read + + if exact_bits is None and max_bits is None: + raise ValueError("Either 'exact_bits' or 'max_bits' must be specified") + + if exact_bits is not None and max_bits is not None: + raise ValueError("'exact_bits' and 'max_bits' are mutually exclusive") + + bits = exact_bits or max_bits + bytes_needed = ((bits - 1) // 8) + 1 + significant_bits_msb = 8 - (bytes_needed * 8 - bits) + msb = bord(randfunc(1)[0]) + if exact_bits is not None: + msb |= 1 << (significant_bits_msb - 1) + msb &= (1 << significant_bits_msb) - 1 + + return cls.from_bytes(bchr(msb) + randfunc(bytes_needed - 1)) + + @classmethod + def random_range(cls, **kwargs): + """Generate a random integer within a given internal. + + :Keywords: + min_inclusive : integer + The lower end of the interval (inclusive). + max_inclusive : integer + The higher end of the interval (inclusive). + max_exclusive : integer + The higher end of the interval (exclusive). + randfunc : callable + A function that returns a random byte string. The length of the + byte string is passed as parameter. Optional. + If not provided (or ``None``), randomness is read from the system RNG. + :Returns: + An Integer randomly taken in the given interval. + """ + + min_inclusive = kwargs.pop("min_inclusive", None) + max_inclusive = kwargs.pop("max_inclusive", None) + max_exclusive = kwargs.pop("max_exclusive", None) + randfunc = kwargs.pop("randfunc", None) + + if kwargs: + raise ValueError("Unknown keywords: " + str(kwargs.keys)) + if None not in (max_inclusive, max_exclusive): + raise ValueError( + "max_inclusive and max_exclusive cannot be both specified", + ) + if max_exclusive is not None: + max_inclusive = max_exclusive - 1 + if None in (min_inclusive, max_inclusive): + raise ValueError("Missing keyword to identify the interval") + + if randfunc is None: + randfunc = Random.new().read + + norm_maximum = max_inclusive - min_inclusive + bits_needed = cls(norm_maximum).size_in_bits() + + norm_candidate = -1 + while not 0 <= norm_candidate <= norm_maximum: + norm_candidate = cls.random( + max_bits=bits_needed, + randfunc=randfunc, + ) + return norm_candidate + min_inclusive + + @staticmethod + @abc.abstractmethod + def _mult_modulo_bytes(term1, term2, modulus): + """Multiply two integers, take the modulo, and encode as big endian. + This specialized method is used for RSA decryption. + + Args: + term1 : integer + The first term of the multiplication, non-negative. + term2 : integer + The second term of the multiplication, non-negative. + modulus: integer + The modulus, a positive odd number. + :Returns: + A byte string, with the result of the modular multiplication + encoded in big endian mode. + It is as long as the modulus would be, with zero padding + on the left if needed. + """ + pass diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerBase.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerBase.pyi index ea235326..6a8baf03 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerBase.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerBase.pyi @@ -1,67 +1,66 @@ from typing import Optional, Union, Callable -RandFunc = Callable[[int],int] +RandFunc = Callable[[int], int] class IntegerBase: - - def __init__(self, value: Union[IntegerBase, int]): ... - - def __int__(self) -> int: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... - def to_bytes(self, block_size: Optional[int]=0, byteorder: str= ...) -> bytes: ... - @staticmethod - def from_bytes(byte_string: bytes, byteorder: Optional[str] = ...) -> IntegerBase: ... - def __eq__(self, term: object) -> bool: ... - def __ne__(self, term: object) -> bool: ... - def __lt__(self, term: Union[IntegerBase, int]) -> bool: ... - def __le__(self, term: Union[IntegerBase, int]) -> bool: ... - def __gt__(self, term: Union[IntegerBase, int]) -> bool: ... - def __ge__(self, term: Union[IntegerBase, int]) -> bool: ... - def __nonzero__(self) -> bool: ... - def is_negative(self) -> bool: ... - def __add__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __sub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __mul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __floordiv__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... - def __mod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... - def inplace_pow(self, exponent: int, modulus: Optional[Union[IntegerBase, int]]=None) -> IntegerBase: ... - def __pow__(self, exponent: int, modulus: Optional[int]) -> IntegerBase: ... - def __abs__(self) -> IntegerBase: ... - def sqrt(self, modulus: Optional[int]) -> IntegerBase: ... - def __iadd__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __isub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __imul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __imod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... - def __and__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __or__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __rshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def __irshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def __lshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def __ilshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def get_bit(self, n: int) -> bool: ... - def is_odd(self) -> bool: ... - def is_even(self) -> bool: ... - def size_in_bits(self) -> int: ... - def size_in_bytes(self) -> int: ... - def is_perfect_square(self) -> bool: ... - def fail_if_divisible_by(self, small_prime: Union[IntegerBase, int]) -> None: ... - def multiply_accumulate(self, a: Union[IntegerBase, int], b: Union[IntegerBase, int]) -> IntegerBase: ... - def set(self, source: Union[IntegerBase, int]) -> IntegerBase: ... - def inplace_inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... - def inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... - def gcd(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def lcm(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - @staticmethod - def jacobi_symbol(a: Union[IntegerBase, int], n: Union[IntegerBase, int]) -> IntegerBase: ... - @staticmethod - def _tonelli_shanks(n: Union[IntegerBase, int], p: Union[IntegerBase, int]) -> IntegerBase : ... - @classmethod - def random(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ... - @classmethod - def random_range(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ... - @staticmethod - def _mult_modulo_bytes(term1: Union[IntegerBase, int], - term2: Union[IntegerBase, int], - modulus: Union[IntegerBase, int]) -> bytes: ... - + def __init__(self, value: Union[IntegerBase, int]): ... + def __int__(self) -> int: ... + def __str__(self) -> str: ... + def __repr__(self) -> str: ... + def to_bytes(self, block_size: Optional[int] = 0, byteorder: str = ...) -> bytes: ... + @staticmethod + def from_bytes(byte_string: bytes, byteorder: Optional[str] = ...) -> IntegerBase: ... + def __eq__(self, term: object) -> bool: ... + def __ne__(self, term: object) -> bool: ... + def __lt__(self, term: Union[IntegerBase, int]) -> bool: ... + def __le__(self, term: Union[IntegerBase, int]) -> bool: ... + def __gt__(self, term: Union[IntegerBase, int]) -> bool: ... + def __ge__(self, term: Union[IntegerBase, int]) -> bool: ... + def __nonzero__(self) -> bool: ... + def is_negative(self) -> bool: ... + def __add__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __sub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __mul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __floordiv__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... + def __mod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... + def inplace_pow( + self, exponent: int, modulus: Optional[Union[IntegerBase, int]] = None + ) -> IntegerBase: ... + def __pow__(self, exponent: int, modulus: Optional[int]) -> IntegerBase: ... + def __abs__(self) -> IntegerBase: ... + def sqrt(self, modulus: Optional[int]) -> IntegerBase: ... + def __iadd__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __isub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __imul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __imod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... + def __and__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __or__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __rshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... + def __irshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... + def __lshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... + def __ilshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... + def get_bit(self, n: int) -> bool: ... + def is_odd(self) -> bool: ... + def is_even(self) -> bool: ... + def size_in_bits(self) -> int: ... + def size_in_bytes(self) -> int: ... + def is_perfect_square(self) -> bool: ... + def fail_if_divisible_by(self, small_prime: Union[IntegerBase, int]) -> None: ... + def multiply_accumulate(self, a: Union[IntegerBase, int], b: Union[IntegerBase, int]) -> IntegerBase: ... + def set(self, source: Union[IntegerBase, int]) -> IntegerBase: ... + def inplace_inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... + def inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... + def gcd(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def lcm(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + @staticmethod + def jacobi_symbol(a: Union[IntegerBase, int], n: Union[IntegerBase, int]) -> IntegerBase: ... + @staticmethod + def _tonelli_shanks(n: Union[IntegerBase, int], p: Union[IntegerBase, int]) -> IntegerBase: ... + @classmethod + def random(cls, **kwargs: Union[int, RandFunc]) -> IntegerBase: ... + @classmethod + def random_range(cls, **kwargs: Union[int, RandFunc]) -> IntegerBase: ... + @staticmethod + def _mult_modulo_bytes( + term1: Union[IntegerBase, int], term2: Union[IntegerBase, int], modulus: Union[IntegerBase, int] + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerCustom.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerCustom.py index 20eadcad..592b7d3a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerCustom.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerCustom.py @@ -32,10 +32,14 @@ from Cryptodome.Util.number import long_to_bytes, bytes_to_long -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, backend, - c_size_t, c_ulonglong) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + create_string_buffer, + get_raw_buffer, + backend, + c_size_t, + c_ulonglong, +) from Cryptodome.Random.random import getrandbits @@ -61,102 +65,100 @@ class IntegerCustom(IntegerNative): - - @staticmethod - def from_bytes(byte_string, byteorder='big'): - if byteorder == 'big': - pass - elif byteorder == 'little': - byte_string = bytearray(byte_string) - byte_string.reverse() - else: - raise ValueError("Incorrect byteorder") - return IntegerCustom(bytes_to_long(byte_string)) - - def inplace_pow(self, exponent, modulus=None): - exp_value = int(exponent) - if exp_value < 0: - raise ValueError("Exponent must not be negative") - - # No modular reduction - if modulus is None: - self._value = pow(self._value, exp_value) - return self - - # With modular reduction - mod_value = int(modulus) - if mod_value < 0: - raise ValueError("Modulus must be positive") - if mod_value == 0: - raise ZeroDivisionError("Modulus cannot be zero") - - # C extension only works with odd moduli - if (mod_value & 1) == 0: - self._value = pow(self._value, exp_value, mod_value) - return self - - # C extension only works with bases smaller than modulus - if self._value >= mod_value: - self._value %= mod_value - - max_len = len(long_to_bytes(max(self._value, exp_value, mod_value))) - - base_b = long_to_bytes(self._value, max_len) - exp_b = long_to_bytes(exp_value, max_len) - modulus_b = long_to_bytes(mod_value, max_len) - - out = create_string_buffer(max_len) - - error = _raw_montgomery.monty_pow( - out, - base_b, - exp_b, - modulus_b, - c_size_t(max_len), - c_ulonglong(getrandbits(64)) - ) - - if error: - raise ValueError("monty_pow failed with error: %d" % error) - - result = bytes_to_long(get_raw_buffer(out)) - self._value = result - return self - - @staticmethod - def _mult_modulo_bytes(term1, term2, modulus): - - # With modular reduction - mod_value = int(modulus) - if mod_value < 0: - raise ValueError("Modulus must be positive") - if mod_value == 0: - raise ZeroDivisionError("Modulus cannot be zero") - - # C extension only works with odd moduli - if (mod_value & 1) == 0: - raise ValueError("Odd modulus is required") - - # C extension only works with non-negative terms smaller than modulus - if term1 >= mod_value or term1 < 0: - term1 %= mod_value - if term2 >= mod_value or term2 < 0: - term2 %= mod_value - - modulus_b = long_to_bytes(mod_value) - numbers_len = len(modulus_b) - term1_b = long_to_bytes(term1, numbers_len) - term2_b = long_to_bytes(term2, numbers_len) - out = create_string_buffer(numbers_len) - - error = _raw_montgomery.monty_multiply( - out, - term1_b, - term2_b, - modulus_b, - c_size_t(numbers_len) - ) - if error: - raise ValueError("monty_multiply failed with error: %d" % error) - - return get_raw_buffer(out) + @staticmethod + def from_bytes(byte_string, byteorder="big"): + if byteorder == "big": + pass + elif byteorder == "little": + byte_string = bytearray(byte_string) + byte_string.reverse() + else: + raise ValueError("Incorrect byteorder") + return IntegerCustom(bytes_to_long(byte_string)) + + def inplace_pow(self, exponent, modulus=None): + exp_value = int(exponent) + if exp_value < 0: + raise ValueError("Exponent must not be negative") + + # No modular reduction + if modulus is None: + self._value = pow(self._value, exp_value) + return self + + # With modular reduction + mod_value = int(modulus) + if mod_value < 0: + raise ValueError("Modulus must be positive") + if mod_value == 0: + raise ZeroDivisionError("Modulus cannot be zero") + + # C extension only works with odd moduli + if (mod_value & 1) == 0: + self._value = pow(self._value, exp_value, mod_value) + return self + + # C extension only works with bases smaller than modulus + if self._value >= mod_value: + self._value %= mod_value + + max_len = len(long_to_bytes(max(self._value, exp_value, mod_value))) + + base_b = long_to_bytes(self._value, max_len) + exp_b = long_to_bytes(exp_value, max_len) + modulus_b = long_to_bytes(mod_value, max_len) + + out = create_string_buffer(max_len) + + error = _raw_montgomery.monty_pow( + out, + base_b, + exp_b, + modulus_b, + c_size_t(max_len), + c_ulonglong(getrandbits(64)), + ) + + if error: + raise ValueError("monty_pow failed with error: %d" % error) + + result = bytes_to_long(get_raw_buffer(out)) + self._value = result + return self + + @staticmethod + def _mult_modulo_bytes(term1, term2, modulus): + # With modular reduction + mod_value = int(modulus) + if mod_value < 0: + raise ValueError("Modulus must be positive") + if mod_value == 0: + raise ZeroDivisionError("Modulus cannot be zero") + + # C extension only works with odd moduli + if (mod_value & 1) == 0: + raise ValueError("Odd modulus is required") + + # C extension only works with non-negative terms smaller than modulus + if term1 >= mod_value or term1 < 0: + term1 %= mod_value + if term2 >= mod_value or term2 < 0: + term2 %= mod_value + + modulus_b = long_to_bytes(mod_value) + numbers_len = len(modulus_b) + term1_b = long_to_bytes(term1, numbers_len) + term2_b = long_to_bytes(term2, numbers_len) + out = create_string_buffer(numbers_len) + + error = _raw_montgomery.monty_multiply( + out, + term1_b, + term2_b, + modulus_b, + c_size_t(numbers_len), + ) + if error: + raise ValueError("monty_multiply failed with error: %d" % error) + + return get_raw_buffer(out) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerCustom.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerCustom.pyi index 2dd75c74..16a2bead 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerCustom.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerCustom.pyi @@ -5,4 +5,4 @@ from ._IntegerNative import IntegerNative _raw_montgomery = Any class IntegerCustom(IntegerNative): - pass + pass diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerGMP.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerGMP.py index be773722..b7a2423c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerGMP.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerGMP.py @@ -33,8 +33,13 @@ from Cryptodome.Util.py3compat import is_native_int -from Cryptodome.Util._raw_api import (backend, load_lib, - c_ulong, c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + backend, + load_lib, + c_ulong, + c_size_t, + c_uint8_ptr, +) from ._IntegerBase import IntegerBase @@ -97,28 +102,27 @@ """ if sys.platform == "win32": - raise ImportError("Not using GMP on Windows") + raise ImportError("Not using GMP on Windows") lib = load_lib("gmp", gmp_defs) implementation = {"library": "gmp", "api": backend} if hasattr(lib, "__mpir_version"): - raise ImportError("MPIR library detected") + raise ImportError("MPIR library detected") # Lazy creation of GMP methods class _GMP(object): - - def __getattr__(self, name): - if name.startswith("mpz_"): - func_name = "__gmpz_" + name[4:] - elif name.startswith("gmp_"): - func_name = "__gmp_" + name[4:] - else: - raise AttributeError("Attribute %s is invalid" % name) - func = getattr(lib, func_name) - setattr(self, name, func) - return func + def __getattr__(self, name): + if name.startswith("mpz_"): + func_name = "__gmpz_" + name[4:] + elif name.startswith("gmp_"): + func_name = "__gmp_" + name[4:] + else: + raise AttributeError("Attribute %s is invalid" % name) + func = getattr(lib, func_name) + setattr(self, name, func) + return func _gmp = _GMP() @@ -128,24 +132,26 @@ def __getattr__(self, name): # a new MPZ structure, we need to break the abstraction # and know exactly what ffi backend we have if implementation["api"] == "ctypes": - from ctypes import Structure, c_int, c_void_p, byref + from ctypes import Structure, c_int, c_void_p, byref - class _MPZ(Structure): - _fields_ = [('_mp_alloc', c_int), - ('_mp_size', c_int), - ('_mp_d', c_void_p)] + class _MPZ(Structure): + _fields_ = [ + ("_mp_alloc", c_int), + ("_mp_size", c_int), + ("_mp_d", c_void_p), + ] - def new_mpz(): - return byref(_MPZ()) + def new_mpz(): + return byref(_MPZ()) - _gmp.mpz_getlimbn.restype = c_ulong + _gmp.mpz_getlimbn.restype = c_ulong else: - # We are using CFFI - from Cryptodome.Util._raw_api import ffi + # We are using CFFI + from Cryptodome.Util._raw_api import ffi - def new_mpz(): - return ffi.new("MPZ*") + def new_mpz(): + return ffi.new("MPZ*") # Size of a native word @@ -153,647 +159,730 @@ def new_mpz(): class IntegerGMP(IntegerBase): - """A fast, arbitrary precision integer""" - - _zero_mpz_p = new_mpz() - _gmp.mpz_init_set_ui(_zero_mpz_p, c_ulong(0)) - - def __init__(self, value): - """Initialize the integer to the given value.""" - - self._mpz_p = new_mpz() - self._initialized = False - - if isinstance(value, float): - raise ValueError("A floating point type is not a natural number") - - if is_native_int(value): - _gmp.mpz_init(self._mpz_p) - self._initialized = True - if value == 0: - return - - tmp = new_mpz() - _gmp.mpz_init(tmp) - - try: - positive = value >= 0 - reduce = abs(value) - slots = (reduce.bit_length() - 1) // 32 + 1 - - while slots > 0: - slots = slots - 1 - _gmp.mpz_set_ui(tmp, - c_ulong(0xFFFFFFFF & (reduce >> (slots * 32)))) - _gmp.mpz_mul_2exp(tmp, tmp, c_ulong(slots * 32)) - _gmp.mpz_add(self._mpz_p, self._mpz_p, tmp) - finally: - _gmp.mpz_clear(tmp) - - if not positive: - _gmp.mpz_neg(self._mpz_p, self._mpz_p) - - elif isinstance(value, IntegerGMP): - _gmp.mpz_init_set(self._mpz_p, value._mpz_p) - self._initialized = True - else: - raise NotImplementedError - - # Conversions - def __int__(self): - tmp = new_mpz() - _gmp.mpz_init_set(tmp, self._mpz_p) - - try: - value = 0 - slot = 0 - while _gmp.mpz_cmp(tmp, self._zero_mpz_p) != 0: - lsb = _gmp.mpz_get_ui(tmp) & 0xFFFFFFFF - value |= lsb << (slot * 32) - _gmp.mpz_tdiv_q_2exp(tmp, tmp, c_ulong(32)) - slot = slot + 1 - finally: - _gmp.mpz_clear(tmp) - - if self < 0: - value = -value - return int(value) - - def __str__(self): - return str(int(self)) - - def __repr__(self): - return "Integer(%s)" % str(self) - - # Only Python 2.x - def __hex__(self): - return hex(int(self)) - - # Only Python 3.x - def __index__(self): - return int(self) - - def to_bytes(self, block_size=0, byteorder='big'): - """Convert the number into a byte string. - - This method encodes the number in network order and prepends - as many zero bytes as required. It only works for non-negative - values. - - :Parameters: - block_size : integer - The exact size the output byte string must have. - If zero, the string has the minimal length. - byteorder : string - 'big' for big-endian integers (default), 'little' for litte-endian. - :Returns: - A byte string. - :Raise ValueError: - If the value is negative or if ``block_size`` is - provided and the length of the byte string would exceed it. - """ - - if self < 0: - raise ValueError("Conversion only valid for non-negative numbers") - - num_limbs = _gmp.mpz_size(self._mpz_p) - if _sys_bits == 32: - spchar = "L" - num_limbs = max(1, num_limbs, (block_size + 3) // 4) - elif _sys_bits == 64: - spchar = "Q" - num_limbs = max(1, num_limbs, (block_size + 7) // 8) - else: - raise ValueError("Unknown limb size") - - # mpz_getlimbn returns 0 if i is larger than the number of actual limbs - limbs = [_gmp.mpz_getlimbn(self._mpz_p, num_limbs - i - 1) for i in range(num_limbs)] - - result = struct.pack(">" + spchar * num_limbs, *limbs) - cutoff_len = len(result) - block_size - if block_size == 0: - result = result.lstrip(b'\x00') - elif cutoff_len > 0: - if result[:cutoff_len] != b'\x00' * (cutoff_len): - raise ValueError("Number is too big to convert to " - "byte string of prescribed length") - result = result[cutoff_len:] - elif cutoff_len < 0: - result = b'\x00' * (-cutoff_len) + result - - if byteorder == 'little': - result = result[::-1] - elif byteorder == 'big': - pass - else: - raise ValueError("Incorrect byteorder") - - if len(result) == 0: - result = b'\x00' - - return result - - @staticmethod - def from_bytes(byte_string, byteorder='big'): - """Convert a byte string into a number. - - :Parameters: - byte_string : byte string - The input number, encoded in network order. - It can only be non-negative. - byteorder : string - 'big' for big-endian integers (default), 'little' for litte-endian. - - :Return: - The ``Integer`` object carrying the same value as the input. - """ - result = IntegerGMP(0) - if byteorder == 'big': - pass - elif byteorder == 'little': - byte_string = bytearray(byte_string) - byte_string.reverse() - else: - raise ValueError("Incorrect byteorder") - _gmp.mpz_import( - result._mpz_p, - c_size_t(len(byte_string)), # Amount of words to read - 1, # Big endian - c_size_t(1), # Each word is 1 byte long - 0, # Endianess within a word - not relevant - c_size_t(0), # No nails - c_uint8_ptr(byte_string)) - return result - - # Relations - def _apply_and_return(self, func, term): - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - return func(self._mpz_p, term._mpz_p) - - def __eq__(self, term): - if not (isinstance(term, IntegerGMP) or is_native_int(term)): - return False - return self._apply_and_return(_gmp.mpz_cmp, term) == 0 - - def __ne__(self, term): - if not (isinstance(term, IntegerGMP) or is_native_int(term)): - return True - return self._apply_and_return(_gmp.mpz_cmp, term) != 0 - - def __lt__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) < 0 - - def __le__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) <= 0 - - def __gt__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) > 0 - - def __ge__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) >= 0 - - def __nonzero__(self): - return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) != 0 - __bool__ = __nonzero__ - - def is_negative(self): - return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) < 0 - - # Arithmetic operations - def __add__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - try: - term = IntegerGMP(term) - except NotImplementedError: - return NotImplemented - _gmp.mpz_add(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __sub__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - try: - term = IntegerGMP(term) - except NotImplementedError: - return NotImplemented - _gmp.mpz_sub(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __mul__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - try: - term = IntegerGMP(term) - except NotImplementedError: - return NotImplemented - _gmp.mpz_mul(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __floordiv__(self, divisor): - if not isinstance(divisor, IntegerGMP): - divisor = IntegerGMP(divisor) - if _gmp.mpz_cmp(divisor._mpz_p, - self._zero_mpz_p) == 0: - raise ZeroDivisionError("Division by zero") - result = IntegerGMP(0) - _gmp.mpz_fdiv_q(result._mpz_p, - self._mpz_p, - divisor._mpz_p) - return result - - def __mod__(self, divisor): - if not isinstance(divisor, IntegerGMP): - divisor = IntegerGMP(divisor) - comp = _gmp.mpz_cmp(divisor._mpz_p, - self._zero_mpz_p) - if comp == 0: - raise ZeroDivisionError("Division by zero") - if comp < 0: - raise ValueError("Modulus must be positive") - result = IntegerGMP(0) - _gmp.mpz_mod(result._mpz_p, - self._mpz_p, - divisor._mpz_p) - return result - - def inplace_pow(self, exponent, modulus=None): - - if modulus is None: - if exponent < 0: - raise ValueError("Exponent must not be negative") - - # Normal exponentiation - if exponent > 256: - raise ValueError("Exponent is too big") - _gmp.mpz_pow_ui(self._mpz_p, - self._mpz_p, # Base - c_ulong(int(exponent)) - ) - else: - # Modular exponentiation - if not isinstance(modulus, IntegerGMP): - modulus = IntegerGMP(modulus) - if not modulus: - raise ZeroDivisionError("Division by zero") - if modulus.is_negative(): - raise ValueError("Modulus must be positive") - if is_native_int(exponent): - if exponent < 0: - raise ValueError("Exponent must not be negative") - if exponent < 65536: - _gmp.mpz_powm_ui(self._mpz_p, - self._mpz_p, - c_ulong(exponent), - modulus._mpz_p) - return self - exponent = IntegerGMP(exponent) - elif exponent.is_negative(): - raise ValueError("Exponent must not be negative") - _gmp.mpz_powm(self._mpz_p, - self._mpz_p, - exponent._mpz_p, - modulus._mpz_p) - return self - - def __pow__(self, exponent, modulus=None): - result = IntegerGMP(self) - return result.inplace_pow(exponent, modulus) - - def __abs__(self): - result = IntegerGMP(0) - _gmp.mpz_abs(result._mpz_p, self._mpz_p) - return result - - def sqrt(self, modulus=None): - """Return the largest Integer that does not - exceed the square root""" - - if modulus is None: - if self < 0: - raise ValueError("Square root of negative value") - result = IntegerGMP(0) - _gmp.mpz_sqrt(result._mpz_p, - self._mpz_p) - else: - if modulus <= 0: - raise ValueError("Modulus must be positive") - modulus = int(modulus) - result = IntegerGMP(self._tonelli_shanks(int(self) % modulus, modulus)) - - return result - - def __iadd__(self, term): - if is_native_int(term): - if 0 <= term < 65536: - _gmp.mpz_add_ui(self._mpz_p, - self._mpz_p, - c_ulong(term)) - return self - if -65535 < term < 0: - _gmp.mpz_sub_ui(self._mpz_p, - self._mpz_p, - c_ulong(-term)) - return self - term = IntegerGMP(term) - _gmp.mpz_add(self._mpz_p, - self._mpz_p, - term._mpz_p) - return self - - def __isub__(self, term): - if is_native_int(term): - if 0 <= term < 65536: - _gmp.mpz_sub_ui(self._mpz_p, - self._mpz_p, - c_ulong(term)) - return self - if -65535 < term < 0: - _gmp.mpz_add_ui(self._mpz_p, - self._mpz_p, - c_ulong(-term)) - return self - term = IntegerGMP(term) - _gmp.mpz_sub(self._mpz_p, - self._mpz_p, - term._mpz_p) - return self - - def __imul__(self, term): - if is_native_int(term): - if 0 <= term < 65536: - _gmp.mpz_mul_ui(self._mpz_p, - self._mpz_p, - c_ulong(term)) - return self - if -65535 < term < 0: - _gmp.mpz_mul_ui(self._mpz_p, - self._mpz_p, - c_ulong(-term)) - _gmp.mpz_neg(self._mpz_p, self._mpz_p) - return self - term = IntegerGMP(term) - _gmp.mpz_mul(self._mpz_p, - self._mpz_p, - term._mpz_p) - return self - - def __imod__(self, divisor): - if not isinstance(divisor, IntegerGMP): - divisor = IntegerGMP(divisor) - comp = _gmp.mpz_cmp(divisor._mpz_p, - divisor._zero_mpz_p) - if comp == 0: - raise ZeroDivisionError("Division by zero") - if comp < 0: - raise ValueError("Modulus must be positive") - _gmp.mpz_mod(self._mpz_p, - self._mpz_p, - divisor._mpz_p) - return self - - # Boolean/bit operations - def __and__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - _gmp.mpz_and(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __or__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - _gmp.mpz_ior(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __rshift__(self, pos): - result = IntegerGMP(0) - if pos < 0: - raise ValueError("negative shift count") - if pos > 65536: - if self < 0: - return -1 - else: - return 0 - _gmp.mpz_tdiv_q_2exp(result._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return result - - def __irshift__(self, pos): - if pos < 0: - raise ValueError("negative shift count") - if pos > 65536: - if self < 0: - return -1 - else: - return 0 - _gmp.mpz_tdiv_q_2exp(self._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return self - - def __lshift__(self, pos): - result = IntegerGMP(0) - if not 0 <= pos < 65536: - raise ValueError("Incorrect shift count") - _gmp.mpz_mul_2exp(result._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return result - - def __ilshift__(self, pos): - if not 0 <= pos < 65536: - raise ValueError("Incorrect shift count") - _gmp.mpz_mul_2exp(self._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return self - - def get_bit(self, n): - """Return True if the n-th bit is set to 1. - Bit 0 is the least significant.""" - - if self < 0: - raise ValueError("no bit representation for negative values") - if n < 0: - raise ValueError("negative bit count") - if n > 65536: - return 0 - return bool(_gmp.mpz_tstbit(self._mpz_p, - c_ulong(int(n)))) - - # Extra - def is_odd(self): - return _gmp.mpz_tstbit(self._mpz_p, 0) == 1 - - def is_even(self): - return _gmp.mpz_tstbit(self._mpz_p, 0) == 0 - - def size_in_bits(self): - """Return the minimum number of bits that can encode the number.""" - - if self < 0: - raise ValueError("Conversion only valid for non-negative numbers") - return _gmp.mpz_sizeinbase(self._mpz_p, 2) - - def size_in_bytes(self): - """Return the minimum number of bytes that can encode the number.""" - return (self.size_in_bits() - 1) // 8 + 1 - - def is_perfect_square(self): - return _gmp.mpz_perfect_square_p(self._mpz_p) != 0 - - def fail_if_divisible_by(self, small_prime): - """Raise an exception if the small prime is a divisor.""" - - if is_native_int(small_prime): - if 0 < small_prime < 65536: - if _gmp.mpz_divisible_ui_p(self._mpz_p, - c_ulong(small_prime)): - raise ValueError("The value is composite") - return - small_prime = IntegerGMP(small_prime) - if _gmp.mpz_divisible_p(self._mpz_p, - small_prime._mpz_p): - raise ValueError("The value is composite") - - def multiply_accumulate(self, a, b): - """Increment the number by the product of a and b.""" - - if not isinstance(a, IntegerGMP): - a = IntegerGMP(a) - if is_native_int(b): - if 0 < b < 65536: - _gmp.mpz_addmul_ui(self._mpz_p, - a._mpz_p, - c_ulong(b)) - return self - if -65535 < b < 0: - _gmp.mpz_submul_ui(self._mpz_p, - a._mpz_p, - c_ulong(-b)) - return self - b = IntegerGMP(b) - _gmp.mpz_addmul(self._mpz_p, - a._mpz_p, - b._mpz_p) - return self - - def set(self, source): - """Set the Integer to have the given value""" - - if not isinstance(source, IntegerGMP): - source = IntegerGMP(source) - _gmp.mpz_set(self._mpz_p, - source._mpz_p) - return self - - def inplace_inverse(self, modulus): - """Compute the inverse of this number in the ring of - modulo integers. - - Raise an exception if no inverse exists. - """ - - if not isinstance(modulus, IntegerGMP): - modulus = IntegerGMP(modulus) - - comp = _gmp.mpz_cmp(modulus._mpz_p, - self._zero_mpz_p) - if comp == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if comp < 0: - raise ValueError("Modulus must be positive") - - result = _gmp.mpz_invert(self._mpz_p, - self._mpz_p, - modulus._mpz_p) - if not result: - raise ValueError("No inverse value can be computed") - return self - - def inverse(self, modulus): - result = IntegerGMP(self) - result.inplace_inverse(modulus) - return result - - def gcd(self, term): - """Compute the greatest common denominator between this - number and another term.""" - - result = IntegerGMP(0) - if is_native_int(term): - if 0 < term < 65535: - _gmp.mpz_gcd_ui(result._mpz_p, - self._mpz_p, - c_ulong(term)) - return result - term = IntegerGMP(term) - _gmp.mpz_gcd(result._mpz_p, self._mpz_p, term._mpz_p) - return result - - def lcm(self, term): - """Compute the least common multiplier between this - number and another term.""" - - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - _gmp.mpz_lcm(result._mpz_p, self._mpz_p, term._mpz_p) - return result - - @staticmethod - def jacobi_symbol(a, n): - """Compute the Jacobi symbol""" - - if not isinstance(a, IntegerGMP): - a = IntegerGMP(a) - if not isinstance(n, IntegerGMP): - n = IntegerGMP(n) - if n <= 0 or n.is_even(): - raise ValueError("n must be positive odd for the Jacobi symbol") - return _gmp.mpz_jacobi(a._mpz_p, n._mpz_p) - - @staticmethod - def _mult_modulo_bytes(term1, term2, modulus): - if not isinstance(term1, IntegerGMP): - term1 = IntegerGMP(term1) - if not isinstance(term2, IntegerGMP): - term2 = IntegerGMP(term2) - if not isinstance(modulus, IntegerGMP): - modulus = IntegerGMP(modulus) - - if modulus < 0: - raise ValueError("Modulus must be positive") - if modulus == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if (modulus & 1) == 0: - raise ValueError("Odd modulus is required") - - product = (term1 * term2) % modulus - return product.to_bytes(modulus.size_in_bytes()) - - # Clean-up - def __del__(self): - - try: - if self._mpz_p is not None: - if self._initialized: - _gmp.mpz_clear(self._mpz_p) - - self._mpz_p = None - except AttributeError: - pass + """A fast, arbitrary precision integer""" + + _zero_mpz_p = new_mpz() + _gmp.mpz_init_set_ui(_zero_mpz_p, c_ulong(0)) + + def __init__(self, value): + """Initialize the integer to the given value.""" + + self._mpz_p = new_mpz() + self._initialized = False + + if isinstance(value, float): + raise ValueError("A floating point type is not a natural number") + + if is_native_int(value): + _gmp.mpz_init(self._mpz_p) + self._initialized = True + if value == 0: + return + + tmp = new_mpz() + _gmp.mpz_init(tmp) + + try: + positive = value >= 0 + reduce = abs(value) + slots = (reduce.bit_length() - 1) // 32 + 1 + + while slots > 0: + slots = slots - 1 + _gmp.mpz_set_ui( + tmp, + c_ulong(0xFFFFFFFF & (reduce >> (slots * 32))), + ) + _gmp.mpz_mul_2exp(tmp, tmp, c_ulong(slots * 32)) + _gmp.mpz_add(self._mpz_p, self._mpz_p, tmp) + finally: + _gmp.mpz_clear(tmp) + + if not positive: + _gmp.mpz_neg(self._mpz_p, self._mpz_p) + + elif isinstance(value, IntegerGMP): + _gmp.mpz_init_set(self._mpz_p, value._mpz_p) + self._initialized = True + else: + raise NotImplementedError + + # Conversions + def __int__(self): + tmp = new_mpz() + _gmp.mpz_init_set(tmp, self._mpz_p) + + try: + value = 0 + slot = 0 + while _gmp.mpz_cmp(tmp, self._zero_mpz_p) != 0: + lsb = _gmp.mpz_get_ui(tmp) & 0xFFFFFFFF + value |= lsb << (slot * 32) + _gmp.mpz_tdiv_q_2exp(tmp, tmp, c_ulong(32)) + slot = slot + 1 + finally: + _gmp.mpz_clear(tmp) + + if self < 0: + value = -value + return int(value) + + def __str__(self): + return str(int(self)) + + def __repr__(self): + return "Integer(%s)" % str(self) + + # Only Python 2.x + def __hex__(self): + return hex(int(self)) + + # Only Python 3.x + def __index__(self): + return int(self) + + def to_bytes(self, block_size=0, byteorder="big"): + """Convert the number into a byte string. + + This method encodes the number in network order and prepends + as many zero bytes as required. It only works for non-negative + values. + + :Parameters: + block_size : integer + The exact size the output byte string must have. + If zero, the string has the minimal length. + byteorder : string + 'big' for big-endian integers (default), 'little' for litte-endian. + :Returns: + A byte string. + :Raise ValueError: + If the value is negative or if ``block_size`` is + provided and the length of the byte string would exceed it. + """ + + if self < 0: + raise ValueError("Conversion only valid for non-negative numbers") + + num_limbs = _gmp.mpz_size(self._mpz_p) + if _sys_bits == 32: + spchar = "L" + num_limbs = max(1, num_limbs, (block_size + 3) // 4) + elif _sys_bits == 64: + spchar = "Q" + num_limbs = max(1, num_limbs, (block_size + 7) // 8) + else: + raise ValueError("Unknown limb size") + + # mpz_getlimbn returns 0 if i is larger than the number of actual limbs + limbs = [_gmp.mpz_getlimbn(self._mpz_p, num_limbs - i - 1) for i in range(num_limbs)] + + result = struct.pack(">" + spchar * num_limbs, *limbs) + cutoff_len = len(result) - block_size + if block_size == 0: + result = result.lstrip(b"\x00") + elif cutoff_len > 0: + if result[:cutoff_len] != b"\x00" * (cutoff_len): + raise ValueError( + "Number is too big to convert to byte string of prescribed length", + ) + result = result[cutoff_len:] + elif cutoff_len < 0: + result = b"\x00" * (-cutoff_len) + result + + if byteorder == "little": + result = result[::-1] + elif byteorder == "big": + pass + else: + raise ValueError("Incorrect byteorder") + + if len(result) == 0: + result = b"\x00" + + return result + + @staticmethod + def from_bytes(byte_string, byteorder="big"): + """Convert a byte string into a number. + + :Parameters: + byte_string : byte string + The input number, encoded in network order. + It can only be non-negative. + byteorder : string + 'big' for big-endian integers (default), 'little' for litte-endian. + + :Return: + The ``Integer`` object carrying the same value as the input. + """ + result = IntegerGMP(0) + if byteorder == "big": + pass + elif byteorder == "little": + byte_string = bytearray(byte_string) + byte_string.reverse() + else: + raise ValueError("Incorrect byteorder") + _gmp.mpz_import( + result._mpz_p, + c_size_t(len(byte_string)), # Amount of words to read + 1, # Big endian + c_size_t(1), # Each word is 1 byte long + 0, # Endianess within a word - not relevant + c_size_t(0), # No nails + c_uint8_ptr(byte_string), + ) + return result + + # Relations + def _apply_and_return(self, func, term): + if not isinstance(term, IntegerGMP): + term = IntegerGMP(term) + return func(self._mpz_p, term._mpz_p) + + def __eq__(self, term): + if not (isinstance(term, IntegerGMP) or is_native_int(term)): + return False + return self._apply_and_return(_gmp.mpz_cmp, term) == 0 + + def __ne__(self, term): + if not (isinstance(term, IntegerGMP) or is_native_int(term)): + return True + return self._apply_and_return(_gmp.mpz_cmp, term) != 0 + + def __lt__(self, term): + return self._apply_and_return(_gmp.mpz_cmp, term) < 0 + + def __le__(self, term): + return self._apply_and_return(_gmp.mpz_cmp, term) <= 0 + + def __gt__(self, term): + return self._apply_and_return(_gmp.mpz_cmp, term) > 0 + + def __ge__(self, term): + return self._apply_and_return(_gmp.mpz_cmp, term) >= 0 + + def __nonzero__(self): + return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) != 0 + + __bool__ = __nonzero__ + + def is_negative(self): + return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) < 0 + + # Arithmetic operations + def __add__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + try: + term = IntegerGMP(term) + except NotImplementedError: + return NotImplemented + _gmp.mpz_add( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __sub__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + try: + term = IntegerGMP(term) + except NotImplementedError: + return NotImplemented + _gmp.mpz_sub( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __mul__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + try: + term = IntegerGMP(term) + except NotImplementedError: + return NotImplemented + _gmp.mpz_mul( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __floordiv__(self, divisor): + if not isinstance(divisor, IntegerGMP): + divisor = IntegerGMP(divisor) + if ( + _gmp.mpz_cmp( + divisor._mpz_p, + self._zero_mpz_p, + ) + == 0 + ): + raise ZeroDivisionError("Division by zero") + result = IntegerGMP(0) + _gmp.mpz_fdiv_q( + result._mpz_p, + self._mpz_p, + divisor._mpz_p, + ) + return result + + def __mod__(self, divisor): + if not isinstance(divisor, IntegerGMP): + divisor = IntegerGMP(divisor) + comp = _gmp.mpz_cmp( + divisor._mpz_p, + self._zero_mpz_p, + ) + if comp == 0: + raise ZeroDivisionError("Division by zero") + if comp < 0: + raise ValueError("Modulus must be positive") + result = IntegerGMP(0) + _gmp.mpz_mod( + result._mpz_p, + self._mpz_p, + divisor._mpz_p, + ) + return result + + def inplace_pow(self, exponent, modulus=None): + if modulus is None: + if exponent < 0: + raise ValueError("Exponent must not be negative") + + # Normal exponentiation + if exponent > 256: + raise ValueError("Exponent is too big") + _gmp.mpz_pow_ui( + self._mpz_p, + self._mpz_p, # Base + c_ulong(int(exponent)), + ) + else: + # Modular exponentiation + if not isinstance(modulus, IntegerGMP): + modulus = IntegerGMP(modulus) + if not modulus: + raise ZeroDivisionError("Division by zero") + if modulus.is_negative(): + raise ValueError("Modulus must be positive") + if is_native_int(exponent): + if exponent < 0: + raise ValueError("Exponent must not be negative") + if exponent < 65536: + _gmp.mpz_powm_ui( + self._mpz_p, + self._mpz_p, + c_ulong(exponent), + modulus._mpz_p, + ) + return self + exponent = IntegerGMP(exponent) + elif exponent.is_negative(): + raise ValueError("Exponent must not be negative") + _gmp.mpz_powm( + self._mpz_p, + self._mpz_p, + exponent._mpz_p, + modulus._mpz_p, + ) + return self + + def __pow__(self, exponent, modulus=None): + result = IntegerGMP(self) + return result.inplace_pow(exponent, modulus) + + def __abs__(self): + result = IntegerGMP(0) + _gmp.mpz_abs(result._mpz_p, self._mpz_p) + return result + + def sqrt(self, modulus=None): + """Return the largest Integer that does not + exceed the square root""" + + if modulus is None: + if self < 0: + raise ValueError("Square root of negative value") + result = IntegerGMP(0) + _gmp.mpz_sqrt( + result._mpz_p, + self._mpz_p, + ) + else: + if modulus <= 0: + raise ValueError("Modulus must be positive") + modulus = int(modulus) + result = IntegerGMP(self._tonelli_shanks(int(self) % modulus, modulus)) + + return result + + def __iadd__(self, term): + if is_native_int(term): + if 0 <= term < 65536: + _gmp.mpz_add_ui( + self._mpz_p, + self._mpz_p, + c_ulong(term), + ) + return self + if -65535 < term < 0: + _gmp.mpz_sub_ui( + self._mpz_p, + self._mpz_p, + c_ulong(-term), + ) + return self + term = IntegerGMP(term) + _gmp.mpz_add( + self._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return self + + def __isub__(self, term): + if is_native_int(term): + if 0 <= term < 65536: + _gmp.mpz_sub_ui( + self._mpz_p, + self._mpz_p, + c_ulong(term), + ) + return self + if -65535 < term < 0: + _gmp.mpz_add_ui( + self._mpz_p, + self._mpz_p, + c_ulong(-term), + ) + return self + term = IntegerGMP(term) + _gmp.mpz_sub( + self._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return self + + def __imul__(self, term): + if is_native_int(term): + if 0 <= term < 65536: + _gmp.mpz_mul_ui( + self._mpz_p, + self._mpz_p, + c_ulong(term), + ) + return self + if -65535 < term < 0: + _gmp.mpz_mul_ui( + self._mpz_p, + self._mpz_p, + c_ulong(-term), + ) + _gmp.mpz_neg(self._mpz_p, self._mpz_p) + return self + term = IntegerGMP(term) + _gmp.mpz_mul( + self._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return self + + def __imod__(self, divisor): + if not isinstance(divisor, IntegerGMP): + divisor = IntegerGMP(divisor) + comp = _gmp.mpz_cmp( + divisor._mpz_p, + divisor._zero_mpz_p, + ) + if comp == 0: + raise ZeroDivisionError("Division by zero") + if comp < 0: + raise ValueError("Modulus must be positive") + _gmp.mpz_mod( + self._mpz_p, + self._mpz_p, + divisor._mpz_p, + ) + return self + + # Boolean/bit operations + def __and__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + term = IntegerGMP(term) + _gmp.mpz_and( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __or__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + term = IntegerGMP(term) + _gmp.mpz_ior( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __rshift__(self, pos): + result = IntegerGMP(0) + if pos < 0: + raise ValueError("negative shift count") + if pos > 65536: + if self < 0: + return -1 + else: + return 0 + _gmp.mpz_tdiv_q_2exp( + result._mpz_p, + self._mpz_p, + c_ulong(int(pos)), + ) + return result + + def __irshift__(self, pos): + if pos < 0: + raise ValueError("negative shift count") + if pos > 65536: + if self < 0: + return -1 + else: + return 0 + _gmp.mpz_tdiv_q_2exp( + self._mpz_p, + self._mpz_p, + c_ulong(int(pos)), + ) + return self + + def __lshift__(self, pos): + result = IntegerGMP(0) + if not 0 <= pos < 65536: + raise ValueError("Incorrect shift count") + _gmp.mpz_mul_2exp( + result._mpz_p, + self._mpz_p, + c_ulong(int(pos)), + ) + return result + + def __ilshift__(self, pos): + if not 0 <= pos < 65536: + raise ValueError("Incorrect shift count") + _gmp.mpz_mul_2exp( + self._mpz_p, + self._mpz_p, + c_ulong(int(pos)), + ) + return self + + def get_bit(self, n): + """Return True if the n-th bit is set to 1. + Bit 0 is the least significant.""" + + if self < 0: + raise ValueError("no bit representation for negative values") + if n < 0: + raise ValueError("negative bit count") + if n > 65536: + return 0 + return bool( + _gmp.mpz_tstbit( + self._mpz_p, + c_ulong(int(n)), + ), + ) + + # Extra + def is_odd(self): + return _gmp.mpz_tstbit(self._mpz_p, 0) == 1 + + def is_even(self): + return _gmp.mpz_tstbit(self._mpz_p, 0) == 0 + + def size_in_bits(self): + """Return the minimum number of bits that can encode the number.""" + + if self < 0: + raise ValueError("Conversion only valid for non-negative numbers") + return _gmp.mpz_sizeinbase(self._mpz_p, 2) + + def size_in_bytes(self): + """Return the minimum number of bytes that can encode the number.""" + return (self.size_in_bits() - 1) // 8 + 1 + + def is_perfect_square(self): + return _gmp.mpz_perfect_square_p(self._mpz_p) != 0 + + def fail_if_divisible_by(self, small_prime): + """Raise an exception if the small prime is a divisor.""" + + if is_native_int(small_prime): + if 0 < small_prime < 65536: + if _gmp.mpz_divisible_ui_p( + self._mpz_p, + c_ulong(small_prime), + ): + raise ValueError("The value is composite") + return + small_prime = IntegerGMP(small_prime) + if _gmp.mpz_divisible_p( + self._mpz_p, + small_prime._mpz_p, + ): + raise ValueError("The value is composite") + + def multiply_accumulate(self, a, b): + """Increment the number by the product of a and b.""" + + if not isinstance(a, IntegerGMP): + a = IntegerGMP(a) + if is_native_int(b): + if 0 < b < 65536: + _gmp.mpz_addmul_ui( + self._mpz_p, + a._mpz_p, + c_ulong(b), + ) + return self + if -65535 < b < 0: + _gmp.mpz_submul_ui( + self._mpz_p, + a._mpz_p, + c_ulong(-b), + ) + return self + b = IntegerGMP(b) + _gmp.mpz_addmul( + self._mpz_p, + a._mpz_p, + b._mpz_p, + ) + return self + + def set(self, source): + """Set the Integer to have the given value""" + + if not isinstance(source, IntegerGMP): + source = IntegerGMP(source) + _gmp.mpz_set( + self._mpz_p, + source._mpz_p, + ) + return self + + def inplace_inverse(self, modulus): + """Compute the inverse of this number in the ring of + modulo integers. + + Raise an exception if no inverse exists. + """ + + if not isinstance(modulus, IntegerGMP): + modulus = IntegerGMP(modulus) + + comp = _gmp.mpz_cmp( + modulus._mpz_p, + self._zero_mpz_p, + ) + if comp == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if comp < 0: + raise ValueError("Modulus must be positive") + + result = _gmp.mpz_invert( + self._mpz_p, + self._mpz_p, + modulus._mpz_p, + ) + if not result: + raise ValueError("No inverse value can be computed") + return self + + def inverse(self, modulus): + result = IntegerGMP(self) + result.inplace_inverse(modulus) + return result + + def gcd(self, term): + """Compute the greatest common denominator between this + number and another term.""" + + result = IntegerGMP(0) + if is_native_int(term): + if 0 < term < 65535: + _gmp.mpz_gcd_ui( + result._mpz_p, + self._mpz_p, + c_ulong(term), + ) + return result + term = IntegerGMP(term) + _gmp.mpz_gcd(result._mpz_p, self._mpz_p, term._mpz_p) + return result + + def lcm(self, term): + """Compute the least common multiplier between this + number and another term.""" + + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + term = IntegerGMP(term) + _gmp.mpz_lcm(result._mpz_p, self._mpz_p, term._mpz_p) + return result + + @staticmethod + def jacobi_symbol(a, n): + """Compute the Jacobi symbol""" + + if not isinstance(a, IntegerGMP): + a = IntegerGMP(a) + if not isinstance(n, IntegerGMP): + n = IntegerGMP(n) + if n <= 0 or n.is_even(): + raise ValueError("n must be positive odd for the Jacobi symbol") + return _gmp.mpz_jacobi(a._mpz_p, n._mpz_p) + + @staticmethod + def _mult_modulo_bytes(term1, term2, modulus): + if not isinstance(term1, IntegerGMP): + term1 = IntegerGMP(term1) + if not isinstance(term2, IntegerGMP): + term2 = IntegerGMP(term2) + if not isinstance(modulus, IntegerGMP): + modulus = IntegerGMP(modulus) + + if modulus < 0: + raise ValueError("Modulus must be positive") + if modulus == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if (modulus & 1) == 0: + raise ValueError("Odd modulus is required") + + product = (term1 * term2) % modulus + return product.to_bytes(modulus.size_in_bytes()) + + # Clean-up + def __del__(self): + try: + if self._mpz_p is not None: + if self._initialized: + _gmp.mpz_clear(self._mpz_p) + + self._mpz_p = None + except AttributeError: + pass diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerGMP.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerGMP.pyi index 2181b470..9775fa59 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerGMP.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerGMP.pyi @@ -1,3 +1,4 @@ from ._IntegerBase import IntegerBase + class IntegerGMP(IntegerBase): - pass + pass diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerNative.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerNative.py index 5f768e26..bfaded4c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerNative.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerNative.py @@ -34,349 +34,348 @@ class IntegerNative(IntegerBase): - """A class to model a natural integer (including zero)""" - - def __init__(self, value): - if isinstance(value, float): - raise ValueError("A floating point type is not a natural number") - try: - self._value = value._value - except AttributeError: - self._value = value - - # Conversions - def __int__(self): - return self._value - - def __str__(self): - return str(int(self)) - - def __repr__(self): - return "Integer(%s)" % str(self) - - # Only Python 2.x - def __hex__(self): - return hex(self._value) - - # Only Python 3.x - def __index__(self): - return int(self._value) - - def to_bytes(self, block_size=0, byteorder='big'): - if self._value < 0: - raise ValueError("Conversion only valid for non-negative numbers") - result = long_to_bytes(self._value, block_size) - if len(result) > block_size > 0: - raise ValueError("Value too large to encode") - if byteorder == 'big': - pass - elif byteorder == 'little': - result = bytearray(result) - result.reverse() - result = bytes(result) - else: - raise ValueError("Incorrect byteorder") - return result - - @classmethod - def from_bytes(cls, byte_string, byteorder='big'): - if byteorder == 'big': - pass - elif byteorder == 'little': - byte_string = bytearray(byte_string) - byte_string.reverse() - else: - raise ValueError("Incorrect byteorder") - return cls(bytes_to_long(byte_string)) - - # Relations - def __eq__(self, term): - if term is None: - return False - return self._value == int(term) - - def __ne__(self, term): - return not self.__eq__(term) - - def __lt__(self, term): - return self._value < int(term) - - def __le__(self, term): - return self.__lt__(term) or self.__eq__(term) - - def __gt__(self, term): - return not self.__le__(term) - - def __ge__(self, term): - return not self.__lt__(term) - - def __nonzero__(self): - return self._value != 0 - __bool__ = __nonzero__ - - def is_negative(self): - return self._value < 0 - - # Arithmetic operations - def __add__(self, term): - try: - return self.__class__(self._value + int(term)) - except (ValueError, AttributeError, TypeError): - return NotImplemented - - def __sub__(self, term): - try: - return self.__class__(self._value - int(term)) - except (ValueError, AttributeError, TypeError): - return NotImplemented - - def __mul__(self, factor): - try: - return self.__class__(self._value * int(factor)) - except (ValueError, AttributeError, TypeError): - return NotImplemented - - def __floordiv__(self, divisor): - return self.__class__(self._value // int(divisor)) - - def __mod__(self, divisor): - divisor_value = int(divisor) - if divisor_value < 0: - raise ValueError("Modulus must be positive") - return self.__class__(self._value % divisor_value) - - def inplace_pow(self, exponent, modulus=None): - exp_value = int(exponent) - if exp_value < 0: - raise ValueError("Exponent must not be negative") - - if modulus is not None: - mod_value = int(modulus) - if mod_value < 0: - raise ValueError("Modulus must be positive") - if mod_value == 0: - raise ZeroDivisionError("Modulus cannot be zero") - else: - mod_value = None - self._value = pow(self._value, exp_value, mod_value) - return self - - def __pow__(self, exponent, modulus=None): - result = self.__class__(self) - return result.inplace_pow(exponent, modulus) - - def __abs__(self): - return abs(self._value) - - def sqrt(self, modulus=None): - - value = self._value - if modulus is None: - if value < 0: - raise ValueError("Square root of negative value") - # http://stackoverflow.com/questions/15390807/integer-square-root-in-python - - x = value - y = (x + 1) // 2 - while y < x: - x = y - y = (x + value // x) // 2 - result = x - else: - if modulus <= 0: - raise ValueError("Modulus must be positive") - result = self._tonelli_shanks(self % modulus, modulus) - - return self.__class__(result) - - def __iadd__(self, term): - self._value += int(term) - return self - - def __isub__(self, term): - self._value -= int(term) - return self - - def __imul__(self, term): - self._value *= int(term) - return self - - def __imod__(self, term): - modulus = int(term) - if modulus == 0: - raise ZeroDivisionError("Division by zero") - if modulus < 0: - raise ValueError("Modulus must be positive") - self._value %= modulus - return self - - # Boolean/bit operations - def __and__(self, term): - return self.__class__(self._value & int(term)) - - def __or__(self, term): - return self.__class__(self._value | int(term)) - - def __rshift__(self, pos): - try: - return self.__class__(self._value >> int(pos)) - except OverflowError: - if self._value >= 0: - return 0 - else: - return -1 - - def __irshift__(self, pos): - try: - self._value >>= int(pos) - except OverflowError: - if self._value >= 0: - return 0 - else: - return -1 - return self - - def __lshift__(self, pos): - try: - return self.__class__(self._value << int(pos)) - except OverflowError: - raise ValueError("Incorrect shift count") - - def __ilshift__(self, pos): - try: - self._value <<= int(pos) - except OverflowError: - raise ValueError("Incorrect shift count") - return self - - def get_bit(self, n): - if self._value < 0: - raise ValueError("no bit representation for negative values") - try: - try: - result = (self._value >> n._value) & 1 - if n._value < 0: - raise ValueError("negative bit count") - except AttributeError: - result = (self._value >> n) & 1 - if n < 0: - raise ValueError("negative bit count") - except OverflowError: - result = 0 - return result - - # Extra - def is_odd(self): - return (self._value & 1) == 1 - - def is_even(self): - return (self._value & 1) == 0 - - def size_in_bits(self): - - if self._value < 0: - raise ValueError("Conversion only valid for non-negative numbers") - - if self._value == 0: - return 1 - - return self._value.bit_length() - - def size_in_bytes(self): - return (self.size_in_bits() - 1) // 8 + 1 - - def is_perfect_square(self): - if self._value < 0: - return False - if self._value in (0, 1): - return True - - x = self._value // 2 - square_x = x ** 2 - - while square_x > self._value: - x = (square_x + self._value) // (2 * x) - square_x = x ** 2 - - return self._value == x ** 2 - - def fail_if_divisible_by(self, small_prime): - if (self._value % int(small_prime)) == 0: - raise ValueError("Value is composite") - - def multiply_accumulate(self, a, b): - self._value += int(a) * int(b) - return self - - def set(self, source): - self._value = int(source) - - def inplace_inverse(self, modulus): - self._value = inverse(self._value, int(modulus)) - return self - - def inverse(self, modulus): - result = self.__class__(self) - result.inplace_inverse(modulus) - return result - - def gcd(self, term): - return self.__class__(GCD(abs(self._value), abs(int(term)))) - - def lcm(self, term): - term = int(term) - if self._value == 0 or term == 0: - return self.__class__(0) - return self.__class__(abs((self._value * term) // self.gcd(term)._value)) - - @staticmethod - def jacobi_symbol(a, n): - a = int(a) - n = int(n) - - if n <= 0: - raise ValueError("n must be a positive integer") - - if (n & 1) == 0: - raise ValueError("n must be odd for the Jacobi symbol") - - # Step 1 - a = a % n - # Step 2 - if a == 1 or n == 1: - return 1 - # Step 3 - if a == 0: - return 0 - # Step 4 - e = 0 - a1 = a - while (a1 & 1) == 0: - a1 >>= 1 - e += 1 - # Step 5 - if (e & 1) == 0: - s = 1 - elif n % 8 in (1, 7): - s = 1 - else: - s = -1 - # Step 6 - if n % 4 == 3 and a1 % 4 == 3: - s = -s - # Step 7 - n1 = n % a1 - # Step 8 - return s * IntegerNative.jacobi_symbol(n1, a1) - - @staticmethod - def _mult_modulo_bytes(term1, term2, modulus): - if modulus < 0: - raise ValueError("Modulus must be positive") - if modulus == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if (modulus & 1) == 0: - raise ValueError("Odd modulus is required") - - number_len = len(long_to_bytes(modulus)) - return long_to_bytes((term1 * term2) % modulus, number_len) + """A class to model a natural integer (including zero)""" + + def __init__(self, value): + if isinstance(value, float): + raise ValueError("A floating point type is not a natural number") + try: + self._value = value._value + except AttributeError: + self._value = value + + # Conversions + def __int__(self): + return self._value + + def __str__(self): + return str(int(self)) + + def __repr__(self): + return "Integer(%s)" % str(self) + + # Only Python 2.x + def __hex__(self): + return hex(self._value) + + # Only Python 3.x + def __index__(self): + return int(self._value) + + def to_bytes(self, block_size=0, byteorder="big"): + if self._value < 0: + raise ValueError("Conversion only valid for non-negative numbers") + result = long_to_bytes(self._value, block_size) + if len(result) > block_size > 0: + raise ValueError("Value too large to encode") + if byteorder == "big": + pass + elif byteorder == "little": + result = bytearray(result) + result.reverse() + result = bytes(result) + else: + raise ValueError("Incorrect byteorder") + return result + + @classmethod + def from_bytes(cls, byte_string, byteorder="big"): + if byteorder == "big": + pass + elif byteorder == "little": + byte_string = bytearray(byte_string) + byte_string.reverse() + else: + raise ValueError("Incorrect byteorder") + return cls(bytes_to_long(byte_string)) + + # Relations + def __eq__(self, term): + if term is None: + return False + return self._value == int(term) + + def __ne__(self, term): + return not self.__eq__(term) + + def __lt__(self, term): + return self._value < int(term) + + def __le__(self, term): + return self.__lt__(term) or self.__eq__(term) + + def __gt__(self, term): + return not self.__le__(term) + + def __ge__(self, term): + return not self.__lt__(term) + + def __nonzero__(self): + return self._value != 0 + + __bool__ = __nonzero__ + + def is_negative(self): + return self._value < 0 + + # Arithmetic operations + def __add__(self, term): + try: + return self.__class__(self._value + int(term)) + except (ValueError, AttributeError, TypeError): + return NotImplemented + + def __sub__(self, term): + try: + return self.__class__(self._value - int(term)) + except (ValueError, AttributeError, TypeError): + return NotImplemented + + def __mul__(self, factor): + try: + return self.__class__(self._value * int(factor)) + except (ValueError, AttributeError, TypeError): + return NotImplemented + + def __floordiv__(self, divisor): + return self.__class__(self._value // int(divisor)) + + def __mod__(self, divisor): + divisor_value = int(divisor) + if divisor_value < 0: + raise ValueError("Modulus must be positive") + return self.__class__(self._value % divisor_value) + + def inplace_pow(self, exponent, modulus=None): + exp_value = int(exponent) + if exp_value < 0: + raise ValueError("Exponent must not be negative") + + if modulus is not None: + mod_value = int(modulus) + if mod_value < 0: + raise ValueError("Modulus must be positive") + if mod_value == 0: + raise ZeroDivisionError("Modulus cannot be zero") + else: + mod_value = None + self._value = pow(self._value, exp_value, mod_value) + return self + + def __pow__(self, exponent, modulus=None): + result = self.__class__(self) + return result.inplace_pow(exponent, modulus) + + def __abs__(self): + return abs(self._value) + + def sqrt(self, modulus=None): + value = self._value + if modulus is None: + if value < 0: + raise ValueError("Square root of negative value") + # http://stackoverflow.com/questions/15390807/integer-square-root-in-python + + x = value + y = (x + 1) // 2 + while y < x: + x = y + y = (x + value // x) // 2 + result = x + else: + if modulus <= 0: + raise ValueError("Modulus must be positive") + result = self._tonelli_shanks(self % modulus, modulus) + + return self.__class__(result) + + def __iadd__(self, term): + self._value += int(term) + return self + + def __isub__(self, term): + self._value -= int(term) + return self + + def __imul__(self, term): + self._value *= int(term) + return self + + def __imod__(self, term): + modulus = int(term) + if modulus == 0: + raise ZeroDivisionError("Division by zero") + if modulus < 0: + raise ValueError("Modulus must be positive") + self._value %= modulus + return self + + # Boolean/bit operations + def __and__(self, term): + return self.__class__(self._value & int(term)) + + def __or__(self, term): + return self.__class__(self._value | int(term)) + + def __rshift__(self, pos): + try: + return self.__class__(self._value >> int(pos)) + except OverflowError: + if self._value >= 0: + return 0 + else: + return -1 + + def __irshift__(self, pos): + try: + self._value >>= int(pos) + except OverflowError: + if self._value >= 0: + return 0 + else: + return -1 + return self + + def __lshift__(self, pos): + try: + return self.__class__(self._value << int(pos)) + except OverflowError: + raise ValueError("Incorrect shift count") + + def __ilshift__(self, pos): + try: + self._value <<= int(pos) + except OverflowError: + raise ValueError("Incorrect shift count") + return self + + def get_bit(self, n): + if self._value < 0: + raise ValueError("no bit representation for negative values") + try: + try: + result = (self._value >> n._value) & 1 + if n._value < 0: + raise ValueError("negative bit count") + except AttributeError: + result = (self._value >> n) & 1 + if n < 0: + raise ValueError("negative bit count") + except OverflowError: + result = 0 + return result + + # Extra + def is_odd(self): + return (self._value & 1) == 1 + + def is_even(self): + return (self._value & 1) == 0 + + def size_in_bits(self): + if self._value < 0: + raise ValueError("Conversion only valid for non-negative numbers") + + if self._value == 0: + return 1 + + return self._value.bit_length() + + def size_in_bytes(self): + return (self.size_in_bits() - 1) // 8 + 1 + + def is_perfect_square(self): + if self._value < 0: + return False + if self._value in (0, 1): + return True + + x = self._value // 2 + square_x = x**2 + + while square_x > self._value: + x = (square_x + self._value) // (2 * x) + square_x = x**2 + + return self._value == x**2 + + def fail_if_divisible_by(self, small_prime): + if (self._value % int(small_prime)) == 0: + raise ValueError("Value is composite") + + def multiply_accumulate(self, a, b): + self._value += int(a) * int(b) + return self + + def set(self, source): + self._value = int(source) + + def inplace_inverse(self, modulus): + self._value = inverse(self._value, int(modulus)) + return self + + def inverse(self, modulus): + result = self.__class__(self) + result.inplace_inverse(modulus) + return result + + def gcd(self, term): + return self.__class__(GCD(abs(self._value), abs(int(term)))) + + def lcm(self, term): + term = int(term) + if self._value == 0 or term == 0: + return self.__class__(0) + return self.__class__(abs((self._value * term) // self.gcd(term)._value)) + + @staticmethod + def jacobi_symbol(a, n): + a = int(a) + n = int(n) + + if n <= 0: + raise ValueError("n must be a positive integer") + + if (n & 1) == 0: + raise ValueError("n must be odd for the Jacobi symbol") + + # Step 1 + a = a % n + # Step 2 + if a == 1 or n == 1: + return 1 + # Step 3 + if a == 0: + return 0 + # Step 4 + e = 0 + a1 = a + while (a1 & 1) == 0: + a1 >>= 1 + e += 1 + # Step 5 + if (e & 1) == 0: + s = 1 + elif n % 8 in (1, 7): + s = 1 + else: + s = -1 + # Step 6 + if n % 4 == 3 and a1 % 4 == 3: + s = -s + # Step 7 + n1 = n % a1 + # Step 8 + return s * IntegerNative.jacobi_symbol(n1, a1) + + @staticmethod + def _mult_modulo_bytes(term1, term2, modulus): + if modulus < 0: + raise ValueError("Modulus must be positive") + if modulus == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if (modulus & 1) == 0: + raise ValueError("Odd modulus is required") + + number_len = len(long_to_bytes(modulus)) + return long_to_bytes((term1 * term2) % modulus, number_len) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerNative.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerNative.pyi index 3f65a39e..b8bbecb5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerNative.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Math/_IntegerNative.pyi @@ -1,3 +1,4 @@ from ._IntegerBase import IntegerBase + class IntegerNative(IntegerBase): - pass + pass diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/DH.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/DH.py index 41793c1f..b95d7b38 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/DH.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/DH.py @@ -1,192 +1,194 @@ from Cryptodome.Util.number import long_to_bytes -from Cryptodome.PublicKey.ECC import (EccKey, - construct, - _import_curve25519_public_key, - _import_curve448_public_key) +from Cryptodome.PublicKey.ECC import ( + EccKey, + construct, + _import_curve25519_public_key, + _import_curve448_public_key, +) def _compute_ecdh(key_priv, key_pub): - pointP = key_pub.pointQ * key_priv.d - if pointP.is_point_at_infinity(): - raise ValueError("Invalid ECDH point") + pointP = key_pub.pointQ * key_priv.d + if pointP.is_point_at_infinity(): + raise ValueError("Invalid ECDH point") - if key_priv.curve == "Curve25519": - z = bytearray(pointP.x.to_bytes(32, byteorder='little')) - elif key_priv.curve == "Curve448": - z = bytearray(pointP.x.to_bytes(56, byteorder='little')) - else: - # See Section 5.7.1.2 in NIST SP 800-56Ar3 - z = long_to_bytes(pointP.x, pointP.size_in_bytes()) - return z + if key_priv.curve == "Curve25519": + z = bytearray(pointP.x.to_bytes(32, byteorder="little")) + elif key_priv.curve == "Curve448": + z = bytearray(pointP.x.to_bytes(56, byteorder="little")) + else: + # See Section 5.7.1.2 in NIST SP 800-56Ar3 + z = long_to_bytes(pointP.x, pointP.size_in_bytes()) + return z def import_x25519_public_key(encoded): - """Create a new X25519 public key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC7748. + """Create a new X25519 public key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC7748. - Args: - encoded (bytes): - The x25519 public key to import. - It must be 32 bytes. + Args: + encoded (bytes): + The x25519 public key to import. + It must be 32 bytes. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - x = _import_curve25519_public_key(encoded) - return construct(curve='Curve25519', point_x=x) + x = _import_curve25519_public_key(encoded) + return construct(curve="Curve25519", point_x=x) def import_x25519_private_key(encoded): - """Create a new X25519 private key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC7748. + """Create a new X25519 private key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC7748. - Args: - encoded (bytes): - The X25519 private key to import. - It must be 32 bytes. + Args: + encoded (bytes): + The X25519 private key to import. + It must be 32 bytes. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - return construct(seed=encoded, curve="Curve25519") + return construct(seed=encoded, curve="Curve25519") def import_x448_public_key(encoded): - """Create a new X448 public key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC7748. + """Create a new X448 public key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC7748. - Args: - encoded (bytes): - The x448 public key to import. - It must be 56 bytes. + Args: + encoded (bytes): + The x448 public key to import. + It must be 56 bytes. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - x = _import_curve448_public_key(encoded) - return construct(curve='Curve448', point_x=x) + x = _import_curve448_public_key(encoded) + return construct(curve="Curve448", point_x=x) def import_x448_private_key(encoded): - """Create a new X448 private key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC7748. + """Create a new X448 private key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC7748. - Args: - encoded (bytes): - The X448 private key to import. - It must be 56 bytes. + Args: + encoded (bytes): + The X448 private key to import. + It must be 56 bytes. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - return construct(seed=encoded, curve="Curve448") + return construct(seed=encoded, curve="Curve448") def key_agreement(**kwargs): - """Perform a Diffie-Hellman key agreement. - - Keywords: - kdf (callable): - A key derivation function that accepts ``bytes`` as input and returns - ``bytes``. - static_priv (EccKey): - The local static private key. Optional. - static_pub (EccKey): - The static public key that belongs to the peer. Optional. - eph_priv (EccKey): - The local ephemeral private key, generated for this session. Optional. - eph_pub (EccKey): - The ephemeral public key, received from the peer for this session. Optional. - - At least two keys must be passed, of which one is a private key and one - a public key. - - Returns (bytes): - The derived secret key material. - """ - - static_priv = kwargs.get('static_priv', None) - static_pub = kwargs.get('static_pub', None) - eph_priv = kwargs.get('eph_priv', None) - eph_pub = kwargs.get('eph_pub', None) - kdf = kwargs.get('kdf', None) - - if kdf is None: - raise ValueError("'kdf' is mandatory") - - count_priv = 0 - count_pub = 0 - curve = None - - def check_curve(curve, key, name, private): - if not isinstance(key, EccKey): - raise TypeError("'%s' must be an ECC key" % name) - if private and not key.has_private(): - raise TypeError("'%s' must be a private ECC key" % name) - if curve is None: - curve = key.curve - elif curve != key.curve: - raise TypeError("'%s' is defined on an incompatible curve" % name) - return curve - - if static_priv is not None: - curve = check_curve(curve, static_priv, 'static_priv', True) - count_priv += 1 - - if static_pub is not None: - curve = check_curve(curve, static_pub, 'static_pub', False) - count_pub += 1 - - if eph_priv is not None: - curve = check_curve(curve, eph_priv, 'eph_priv', True) - count_priv += 1 - - if eph_pub is not None: - curve = check_curve(curve, eph_pub, 'eph_pub', False) - count_pub += 1 - - if (count_priv + count_pub) < 2 or count_priv == 0 or count_pub == 0: - raise ValueError("Too few keys for the ECDH key agreement") - - Zs = b'' - Ze = b'' - - if static_priv and static_pub: - # C(*, 2s) - Zs = _compute_ecdh(static_priv, static_pub) - - if eph_priv and eph_pub: - # C(2e, 0s) or C(2e, 2s) - if bool(static_priv) != bool(static_pub): - raise ValueError("DH mode C(2e, 1s) is not supported") - Ze = _compute_ecdh(eph_priv, eph_pub) - elif eph_priv and static_pub: - # C(1e, 2s) or C(1e, 1s) - Ze = _compute_ecdh(eph_priv, static_pub) - elif eph_pub and static_priv: - # C(1e, 2s) or C(1e, 1s) - Ze = _compute_ecdh(static_priv, eph_pub) - - Z = Ze + Zs - - return kdf(Z) + """Perform a Diffie-Hellman key agreement. + + Keywords: + kdf (callable): + A key derivation function that accepts ``bytes`` as input and returns + ``bytes``. + static_priv (EccKey): + The local static private key. Optional. + static_pub (EccKey): + The static public key that belongs to the peer. Optional. + eph_priv (EccKey): + The local ephemeral private key, generated for this session. Optional. + eph_pub (EccKey): + The ephemeral public key, received from the peer for this session. Optional. + + At least two keys must be passed, of which one is a private key and one + a public key. + + Returns (bytes): + The derived secret key material. + """ + + static_priv = kwargs.get("static_priv", None) + static_pub = kwargs.get("static_pub", None) + eph_priv = kwargs.get("eph_priv", None) + eph_pub = kwargs.get("eph_pub", None) + kdf = kwargs.get("kdf", None) + + if kdf is None: + raise ValueError("'kdf' is mandatory") + + count_priv = 0 + count_pub = 0 + curve = None + + def check_curve(curve, key, name, private): + if not isinstance(key, EccKey): + raise TypeError("'%s' must be an ECC key" % name) + if private and not key.has_private(): + raise TypeError("'%s' must be a private ECC key" % name) + if curve is None: + curve = key.curve + elif curve != key.curve: + raise TypeError("'%s' is defined on an incompatible curve" % name) + return curve + + if static_priv is not None: + curve = check_curve(curve, static_priv, "static_priv", True) + count_priv += 1 + + if static_pub is not None: + curve = check_curve(curve, static_pub, "static_pub", False) + count_pub += 1 + + if eph_priv is not None: + curve = check_curve(curve, eph_priv, "eph_priv", True) + count_priv += 1 + + if eph_pub is not None: + curve = check_curve(curve, eph_pub, "eph_pub", False) + count_pub += 1 + + if (count_priv + count_pub) < 2 or count_priv == 0 or count_pub == 0: + raise ValueError("Too few keys for the ECDH key agreement") + + Zs = b"" + Ze = b"" + + if static_priv and static_pub: + # C(*, 2s) + Zs = _compute_ecdh(static_priv, static_pub) + + if eph_priv and eph_pub: + # C(2e, 0s) or C(2e, 2s) + if bool(static_priv) != bool(static_pub): + raise ValueError("DH mode C(2e, 1s) is not supported") + Ze = _compute_ecdh(eph_priv, eph_pub) + elif eph_priv and static_pub: + # C(1e, 2s) or C(1e, 1s) + Ze = _compute_ecdh(eph_priv, static_pub) + elif eph_pub and static_priv: + # C(1e, 2s) or C(1e, 1s) + Ze = _compute_ecdh(static_priv, eph_pub) + + Z = Ze + Zs + + return kdf(Z) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/DH.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/DH.pyi index 017d8637..d495ccae 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/DH.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/DH.pyi @@ -3,14 +3,14 @@ from typing_extensions import Unpack, NotRequired from Cryptodome.PublicKey.ECC import EccKey -T = TypeVar('T') +T = TypeVar("T") class RequestParams(TypedDict, Generic[T]): - kdf: Callable[[bytes|bytearray|memoryview], T] - static_priv: NotRequired[EccKey] - static_pub: NotRequired[EccKey] - eph_priv: NotRequired[EccKey] - eph_pub: NotRequired[EccKey] + kdf: Callable[[bytes | bytearray | memoryview], T] + static_priv: NotRequired[EccKey] + static_pub: NotRequired[EccKey] + eph_priv: NotRequired[EccKey] + eph_pub: NotRequired[EccKey] def import_x25519_public_key(encoded: bytes) -> EccKey: ... def import_x25519_private_key(encoded: bytes) -> EccKey: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/HPKE.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/HPKE.py index 13823ec6..ed77f338 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/HPKE.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/HPKE.py @@ -14,470 +14,522 @@ class MODE(IntEnum): - """HPKE modes""" - BASE = 0x00 - PSK = 0x01 - AUTH = 0x02 - AUTH_PSK = 0x03 + """HPKE modes""" + + BASE = 0x00 + PSK = 0x01 + AUTH = 0x02 + AUTH_PSK = 0x03 class AEAD(IntEnum): - """Authenticated Encryption with Associated Data (AEAD) Functions""" - AES128_GCM = 0x0001 - AES256_GCM = 0x0002 - CHACHA20_POLY1305 = 0x0003 + """Authenticated Encryption with Associated Data (AEAD) Functions""" + + AES128_GCM = 0x0001 + AES256_GCM = 0x0002 + CHACHA20_POLY1305 = 0x0003 class DeserializeError(ValueError): - pass + pass + class MessageLimitReachedError(ValueError): - pass + pass + # CURVE to (KEM ID, KDF ID, HASH) _Curve_Config = { - "NIST P-256": (0x0010, 0x0001, SHA256), - "NIST P-384": (0x0011, 0x0002, SHA384), - "NIST P-521": (0x0012, 0x0003, SHA512), - "Curve25519": (0x0020, 0x0001, SHA256), - "Curve448": (0x0021, 0x0003, SHA512), + "NIST P-256": (0x0010, 0x0001, SHA256), + "NIST P-384": (0x0011, 0x0002, SHA384), + "NIST P-521": (0x0012, 0x0003, SHA512), + "Curve25519": (0x0020, 0x0001, SHA256), + "Curve448": (0x0021, 0x0003, SHA512), } -def _labeled_extract(salt: bytes, - label: bytes, - ikm: bytes, - suite_id: bytes, - hashmod: ModuleType): - labeled_ikm = b"HPKE-v1" + suite_id + label + ikm - return _HKDF_extract(salt, labeled_ikm, hashmod) - - -def _labeled_expand(prk: bytes, - label: bytes, - info: bytes, - L: int, - suite_id: bytes, - hashmod: ModuleType): - labeled_info = struct.pack('>H', L) + b"HPKE-v1" + suite_id + \ - label + info - return _HKDF_expand(prk, labeled_info, L, hashmod) - - -def _extract_and_expand(dh: bytes, - kem_context: bytes, - suite_id: bytes, - hashmod: ModuleType): - Nsecret = hashmod.digest_size - - eae_prk = _labeled_extract(b"", - b"eae_prk", - dh, - suite_id, - hashmod) - - shared_secret = _labeled_expand(eae_prk, - b"shared_secret", - kem_context, - Nsecret, - suite_id, - hashmod) - return shared_secret +def _labeled_extract( + salt: bytes, + label: bytes, + ikm: bytes, + suite_id: bytes, + hashmod: ModuleType, +): + labeled_ikm = b"HPKE-v1" + suite_id + label + ikm + return _HKDF_extract(salt, labeled_ikm, hashmod) + + +def _labeled_expand( + prk: bytes, + label: bytes, + info: bytes, + L: int, + suite_id: bytes, + hashmod: ModuleType, +): + labeled_info = struct.pack(">H", L) + b"HPKE-v1" + suite_id + label + info + return _HKDF_expand(prk, labeled_info, L, hashmod) + + +def _extract_and_expand( + dh: bytes, + kem_context: bytes, + suite_id: bytes, + hashmod: ModuleType, +): + Nsecret = hashmod.digest_size + + eae_prk = _labeled_extract( + b"", + b"eae_prk", + dh, + suite_id, + hashmod, + ) + + shared_secret = _labeled_expand( + eae_prk, + b"shared_secret", + kem_context, + Nsecret, + suite_id, + hashmod, + ) + return shared_secret class HPKE_Cipher: - - def __init__(self, - receiver_key: EccKey, - enc: Optional[bytes], - sender_key: Optional[EccKey], - psk_pair: tuple[bytes, bytes], - info: bytes, - aead_id: AEAD, - mode: MODE): - - self.enc: bytes = b'' if enc is None else enc - """The encapsulated session key.""" - - self._verify_psk_inputs(mode, psk_pair) - - self._curve = receiver_key.curve - self._aead_id = aead_id - self._mode = mode - - try: - self._kem_id, \ - self._kdf_id, \ - self._hashmod = _Curve_Config[self._curve] - except KeyError as ke: - raise ValueError("Curve {} is not supported by HPKE".format(self._curve)) from ke - - self._Nk = 16 if self._aead_id == AEAD.AES128_GCM else 32 - self._Nn = 12 - self._Nt = 16 - self._Nh = self._hashmod.digest_size - - self._encrypt = not receiver_key.has_private() - - if self._encrypt: - # SetupBaseS (encryption) - if enc is not None: - raise ValueError("Parameter 'enc' cannot be an input when sealing") - shared_secret, self.enc = self._encap(receiver_key, - self._kem_id, - self._hashmod, - sender_key) - else: - # SetupBaseR (decryption) - if enc is None: - raise ValueError("Parameter 'enc' required when unsealing") - shared_secret = self._decap(enc, - receiver_key, - self._kem_id, - self._hashmod, - sender_key) - - self._sequence = 0 - self._max_sequence = (1 << (8 * self._Nn)) - 1 - - self._key, \ - self._base_nonce, \ - self._export_secret = self._key_schedule(shared_secret, - info, - *psk_pair) - - @staticmethod - def _encap(receiver_key: EccKey, - kem_id: int, - hashmod: ModuleType, - sender_key: Optional[EccKey] = None, - eph_key: Optional[EccKey] = None): - - assert (sender_key is None) or sender_key.has_private() - assert (eph_key is None) or eph_key.has_private() - - if eph_key is None: - eph_key = ECC.generate(curve=receiver_key.curve) - enc = eph_key.public_key().export_key(format='raw') - - pkRm = receiver_key.public_key().export_key(format='raw') - kem_context = enc + pkRm - extra_param = {} - if sender_key: - kem_context += sender_key.public_key().export_key(format='raw') - extra_param = {'static_priv': sender_key} - - suite_id = b"KEM" + struct.pack('>H', kem_id) - - def kdf(dh, - kem_context=kem_context, - suite_id=suite_id, - hashmod=hashmod): - return _extract_and_expand(dh, kem_context, suite_id, hashmod) - - shared_secret = key_agreement(eph_priv=eph_key, - static_pub=receiver_key, - kdf=kdf, - **extra_param) - return shared_secret, enc - - @staticmethod - def _decap(enc: bytes, - receiver_key: EccKey, - kem_id: int, - hashmod: ModuleType, - sender_key: Optional[EccKey] = None): - - assert receiver_key.has_private() - - try: - if receiver_key.curve == 'Curve25519': - pkE = import_x25519_public_key(enc) - elif receiver_key.curve == 'Curve448': - pkE = import_x448_public_key(enc) - else: - pkE = ECC.import_key(enc, curve_name=receiver_key.curve) - except ValueError as ve: - raise DeserializeError("'enc' is not a valid encapsulated HPKE key") from ve - - pkRm = receiver_key.public_key().export_key(format='raw') - kem_context = enc + pkRm - extra_param = {} - if sender_key: - kem_context += sender_key.public_key().export_key(format='raw') - extra_param = {'static_pub': sender_key} - - suite_id = b"KEM" + struct.pack('>H', kem_id) - - def kdf(dh, - kem_context=kem_context, - suite_id=suite_id, - hashmod=hashmod): - return _extract_and_expand(dh, kem_context, suite_id, hashmod) - - shared_secret = key_agreement(eph_pub=pkE, - static_priv=receiver_key, - kdf=kdf, - **extra_param) - return shared_secret - - @staticmethod - def _verify_psk_inputs(mode: MODE, psk_pair: tuple[bytes, bytes]): - psk_id, psk = psk_pair - - if (psk == b'') ^ (psk_id == b''): - raise ValueError("Inconsistent PSK inputs") - - if (psk == b''): - if mode in (MODE.PSK, MODE.AUTH_PSK): - raise ValueError(f"PSK is required with mode {mode.name}") - else: - if len(psk) < 32: - raise ValueError("PSK must be at least 32 byte long") - if mode in (MODE.BASE, MODE.AUTH): - raise ValueError("PSK is not compatible with this mode") - - def _key_schedule(self, - shared_secret: bytes, - info: bytes, - psk_id: bytes, - psk: bytes): - - suite_id = b"HPKE" + struct.pack('>HHH', - self._kem_id, - self._kdf_id, - self._aead_id) - - psk_id_hash = _labeled_extract(b'', - b'psk_id_hash', - psk_id, - suite_id, - self._hashmod) - - info_hash = _labeled_extract(b'', - b'info_hash', - info, - suite_id, - self._hashmod) - - key_schedule_context = self._mode.to_bytes(1, 'big') + psk_id_hash + info_hash - - secret = _labeled_extract(shared_secret, - b'secret', - psk, - suite_id, - self._hashmod) - - key = _labeled_expand(secret, - b'key', - key_schedule_context, - self._Nk, - suite_id, - self._hashmod) - - base_nonce = _labeled_expand(secret, - b'base_nonce', - key_schedule_context, - self._Nn, - suite_id, - self._hashmod) - - exporter_secret = _labeled_expand(secret, - b'exp', - key_schedule_context, - self._Nh, - suite_id, - self._hashmod) - - return key, base_nonce, exporter_secret - - def _new_cipher(self): - nonce = strxor(self._base_nonce, self._sequence.to_bytes(self._Nn, 'big')) - if self._aead_id in (AEAD.AES128_GCM, AEAD.AES256_GCM): - cipher = AES.new(self._key, AES.MODE_GCM, nonce=nonce, mac_len=self._Nt) - elif self._aead_id == AEAD.CHACHA20_POLY1305: - cipher = ChaCha20_Poly1305.new(key=self._key, nonce=nonce) - else: - raise ValueError(f"Unknown AEAD cipher ID {self._aead_id:#x}") - if self._sequence >= self._max_sequence: - raise MessageLimitReachedError() - self._sequence += 1 - return cipher - - def seal(self, plaintext: bytes, auth_data: Optional[bytes] = None): - """Encrypt and authenticate a message. - - This method can be invoked multiple times - to seal an ordered sequence of messages. - - Arguments: - plaintext: bytes - The message to seal. - auth_data: bytes - Optional. Additional Authenticated data (AAD) that is not encrypted - but that will be also covered by the authentication tag. - - Returns: - The ciphertext concatenated with the authentication tag. - """ - - if not self._encrypt: - raise ValueError("This cipher can only be used to seal") - cipher = self._new_cipher() - if auth_data: - cipher.update(auth_data) - ct, tag = cipher.encrypt_and_digest(plaintext) - return ct + tag - - def unseal(self, ciphertext: bytes, auth_data: Optional[bytes] = None): - """Decrypt a message and validate its authenticity. - - This method can be invoked multiple times - to unseal an ordered sequence of messages. - - Arguments: - cipertext: bytes - The message to unseal. - auth_data: bytes - Optional. Additional Authenticated data (AAD) that - was also covered by the authentication tag. - - Returns: - The original plaintext. - - Raises: ValueError - If the ciphertext (in combination with the AAD) is not valid. - - But if it is the first time you call ``unseal()`` this - exception may also mean that any of the parameters or keys - used to establish the session is wrong or that one is missing. - """ - - if self._encrypt: - raise ValueError("This cipher can only be used to unseal") - if len(ciphertext) < self._Nt: - raise ValueError("Ciphertext is too small") - cipher = self._new_cipher() - if auth_data: - cipher.update(auth_data) - - try: - pt = cipher.decrypt_and_verify(ciphertext[:-self._Nt], - ciphertext[-self._Nt:]) - except ValueError: - if self._sequence == 1: - raise ValueError("Incorrect HPKE keys/parameters or invalid message (wrong MAC tag)") - raise ValueError("Invalid message (wrong MAC tag)") - return pt - - -def new(*, receiver_key: EccKey, - aead_id: AEAD, - enc: Optional[bytes] = None, - sender_key: Optional[EccKey] = None, - psk: Optional[tuple[bytes, bytes]] = None, - info: Optional[bytes] = None) -> HPKE_Cipher: - """Create an HPKE context which can be used: - - - by the sender to seal (encrypt) a message or - - by the receiver to unseal (decrypt) it. - - As a minimum, the two parties agree on the receiver's asymmetric key - (of which the sender will only know the public half). - - Additionally, for authentication purposes, they may also agree on: - - * the sender's asymmetric key (of which the receiver will only know the public half) - - * a shared secret (e.g., a symmetric key derived from a password) - - Args: - receiver_key: - The ECC key of the receiver. - It must be on one of the following curves: ``NIST P-256``, - ``NIST P-384``, ``NIST P-521``, ``X25519`` or ``X448``. - - If this is a **public** key, the HPKE context can only be used to - **seal** (**encrypt**). - - If this is a **private** key, the HPKE context can only be used to - **unseal** (**decrypt**). - - aead_id: - The HPKE identifier of the symmetric cipher. - The possible values are: - - * ``HPKE.AEAD.AES128_GCM`` - * ``HPKE.AEAD.AES256_GCM`` - * ``HPKE.AEAD.CHACHA20_POLY1305`` - - enc: - The encapsulated session key (i.e., the KEM shared secret). - - The receiver must always specify this parameter. - - The sender must always omit this parameter. - - sender_key: - The ECC key of the sender. - It must be on the same curve as the ``receiver_key``. - If the ``receiver_key`` is a public key, ``sender_key`` must be a - private key, and vice versa. - - psk: - A Pre-Shared Key (PSK) as a 2-tuple of non-empty - byte strings: the identifier and the actual secret value. - Sender and receiver must use the same PSK (or none). - - The secret value must be at least 32 bytes long, - but it must not be a low-entropy password - (use a KDF like PBKDF2 or scrypt to derive a secret - from a password). - - info: - A non-secret parameter that contributes - to the generation of all session keys. - Sender and receive must use the same **info** parameter (or none). - - Returns: - An object that can be used for - sealing (if ``receiver_key`` is a public key) or - unsealing (if ``receiver_key`` is a private key). - In the latter case, - correctness of all the keys and parameters will only - be assessed with the first call to ``unseal()``. - """ - - if aead_id not in AEAD: - raise ValueError(f"Unknown AEAD cipher ID {aead_id:#x}") - - curve = receiver_key.curve - if curve not in ('NIST P-256', 'NIST P-384', 'NIST P-521', - 'Curve25519', 'Curve448'): - raise ValueError(f"Unsupported curve {curve}") - - if sender_key: - count_private_keys = int(receiver_key.has_private()) + \ - int(sender_key.has_private()) - if count_private_keys != 1: - raise ValueError("Exactly 1 private key required") - if sender_key.curve != curve: - raise ValueError("Sender key uses {} but recipient key {}". - format(sender_key.curve, curve)) - mode = MODE.AUTH if psk is None else MODE.AUTH_PSK - else: - mode = MODE.BASE if psk is None else MODE.PSK - - if psk is None: - psk = b'', b'' - - if info is None: - info = b'' - - return HPKE_Cipher(receiver_key, - enc, - sender_key, - psk, - info, - aead_id, - mode) + def __init__( + self, + receiver_key: EccKey, + enc: Optional[bytes], + sender_key: Optional[EccKey], + psk_pair: tuple[bytes, bytes], + info: bytes, + aead_id: AEAD, + mode: MODE, + ): + self.enc: bytes = b"" if enc is None else enc + """The encapsulated session key.""" + + self._verify_psk_inputs(mode, psk_pair) + + self._curve = receiver_key.curve + self._aead_id = aead_id + self._mode = mode + + try: + self._kem_id, self._kdf_id, self._hashmod = _Curve_Config[self._curve] + except KeyError as ke: + raise ValueError("Curve {} is not supported by HPKE".format(self._curve)) from ke + + self._Nk = 16 if self._aead_id == AEAD.AES128_GCM else 32 + self._Nn = 12 + self._Nt = 16 + self._Nh = self._hashmod.digest_size + + self._encrypt = not receiver_key.has_private() + + if self._encrypt: + # SetupBaseS (encryption) + if enc is not None: + raise ValueError("Parameter 'enc' cannot be an input when sealing") + shared_secret, self.enc = self._encap( + receiver_key, + self._kem_id, + self._hashmod, + sender_key, + ) + else: + # SetupBaseR (decryption) + if enc is None: + raise ValueError("Parameter 'enc' required when unsealing") + shared_secret = self._decap( + enc, + receiver_key, + self._kem_id, + self._hashmod, + sender_key, + ) + + self._sequence = 0 + self._max_sequence = (1 << (8 * self._Nn)) - 1 + + self._key, self._base_nonce, self._export_secret = self._key_schedule( + shared_secret, + info, + *psk_pair, + ) + + @staticmethod + def _encap( + receiver_key: EccKey, + kem_id: int, + hashmod: ModuleType, + sender_key: Optional[EccKey] = None, + eph_key: Optional[EccKey] = None, + ): + assert (sender_key is None) or sender_key.has_private() + assert (eph_key is None) or eph_key.has_private() + + if eph_key is None: + eph_key = ECC.generate(curve=receiver_key.curve) + enc = eph_key.public_key().export_key(format="raw") + + pkRm = receiver_key.public_key().export_key(format="raw") + kem_context = enc + pkRm + extra_param = {} + if sender_key: + kem_context += sender_key.public_key().export_key(format="raw") + extra_param = {"static_priv": sender_key} + + suite_id = b"KEM" + struct.pack(">H", kem_id) + + def kdf( + dh, + kem_context=kem_context, + suite_id=suite_id, + hashmod=hashmod, + ): + return _extract_and_expand(dh, kem_context, suite_id, hashmod) + + shared_secret = key_agreement( + eph_priv=eph_key, + static_pub=receiver_key, + kdf=kdf, + **extra_param, + ) + return shared_secret, enc + + @staticmethod + def _decap( + enc: bytes, + receiver_key: EccKey, + kem_id: int, + hashmod: ModuleType, + sender_key: Optional[EccKey] = None, + ): + assert receiver_key.has_private() + + try: + if receiver_key.curve == "Curve25519": + pkE = import_x25519_public_key(enc) + elif receiver_key.curve == "Curve448": + pkE = import_x448_public_key(enc) + else: + pkE = ECC.import_key(enc, curve_name=receiver_key.curve) + except ValueError as ve: + raise DeserializeError("'enc' is not a valid encapsulated HPKE key") from ve + + pkRm = receiver_key.public_key().export_key(format="raw") + kem_context = enc + pkRm + extra_param = {} + if sender_key: + kem_context += sender_key.public_key().export_key(format="raw") + extra_param = {"static_pub": sender_key} + + suite_id = b"KEM" + struct.pack(">H", kem_id) + + def kdf( + dh, + kem_context=kem_context, + suite_id=suite_id, + hashmod=hashmod, + ): + return _extract_and_expand(dh, kem_context, suite_id, hashmod) + + shared_secret = key_agreement( + eph_pub=pkE, + static_priv=receiver_key, + kdf=kdf, + **extra_param, + ) + return shared_secret + + @staticmethod + def _verify_psk_inputs(mode: MODE, psk_pair: tuple[bytes, bytes]): + psk_id, psk = psk_pair + + if (psk == b"") ^ (psk_id == b""): + raise ValueError("Inconsistent PSK inputs") + + if psk == b"": + if mode in (MODE.PSK, MODE.AUTH_PSK): + raise ValueError(f"PSK is required with mode {mode.name}") + else: + if len(psk) < 32: + raise ValueError("PSK must be at least 32 byte long") + if mode in (MODE.BASE, MODE.AUTH): + raise ValueError("PSK is not compatible with this mode") + + def _key_schedule( + self, + shared_secret: bytes, + info: bytes, + psk_id: bytes, + psk: bytes, + ): + suite_id = b"HPKE" + struct.pack( + ">HHH", + self._kem_id, + self._kdf_id, + self._aead_id, + ) + + psk_id_hash = _labeled_extract( + b"", + b"psk_id_hash", + psk_id, + suite_id, + self._hashmod, + ) + + info_hash = _labeled_extract( + b"", + b"info_hash", + info, + suite_id, + self._hashmod, + ) + + key_schedule_context = self._mode.to_bytes(1, "big") + psk_id_hash + info_hash + + secret = _labeled_extract( + shared_secret, + b"secret", + psk, + suite_id, + self._hashmod, + ) + + key = _labeled_expand( + secret, + b"key", + key_schedule_context, + self._Nk, + suite_id, + self._hashmod, + ) + + base_nonce = _labeled_expand( + secret, + b"base_nonce", + key_schedule_context, + self._Nn, + suite_id, + self._hashmod, + ) + + exporter_secret = _labeled_expand( + secret, + b"exp", + key_schedule_context, + self._Nh, + suite_id, + self._hashmod, + ) + + return key, base_nonce, exporter_secret + + def _new_cipher(self): + nonce = strxor(self._base_nonce, self._sequence.to_bytes(self._Nn, "big")) + if self._aead_id in (AEAD.AES128_GCM, AEAD.AES256_GCM): + cipher = AES.new(self._key, AES.MODE_GCM, nonce=nonce, mac_len=self._Nt) + elif self._aead_id == AEAD.CHACHA20_POLY1305: + cipher = ChaCha20_Poly1305.new(key=self._key, nonce=nonce) + else: + raise ValueError(f"Unknown AEAD cipher ID {self._aead_id:#x}") + if self._sequence >= self._max_sequence: + raise MessageLimitReachedError() + self._sequence += 1 + return cipher + + def seal(self, plaintext: bytes, auth_data: Optional[bytes] = None): + """Encrypt and authenticate a message. + + This method can be invoked multiple times + to seal an ordered sequence of messages. + + Arguments: + plaintext: bytes + The message to seal. + auth_data: bytes + Optional. Additional Authenticated data (AAD) that is not encrypted + but that will be also covered by the authentication tag. + + Returns: + The ciphertext concatenated with the authentication tag. + """ + + if not self._encrypt: + raise ValueError("This cipher can only be used to seal") + cipher = self._new_cipher() + if auth_data: + cipher.update(auth_data) + ct, tag = cipher.encrypt_and_digest(plaintext) + return ct + tag + + def unseal(self, ciphertext: bytes, auth_data: Optional[bytes] = None): + """Decrypt a message and validate its authenticity. + + This method can be invoked multiple times + to unseal an ordered sequence of messages. + + Arguments: + cipertext: bytes + The message to unseal. + auth_data: bytes + Optional. Additional Authenticated data (AAD) that + was also covered by the authentication tag. + + Returns: + The original plaintext. + + Raises: ValueError + If the ciphertext (in combination with the AAD) is not valid. + + But if it is the first time you call ``unseal()`` this + exception may also mean that any of the parameters or keys + used to establish the session is wrong or that one is missing. + """ + + if self._encrypt: + raise ValueError("This cipher can only be used to unseal") + if len(ciphertext) < self._Nt: + raise ValueError("Ciphertext is too small") + cipher = self._new_cipher() + if auth_data: + cipher.update(auth_data) + + try: + pt = cipher.decrypt_and_verify( + ciphertext[: -self._Nt], + ciphertext[-self._Nt :], + ) + except ValueError: + if self._sequence == 1: + raise ValueError("Incorrect HPKE keys/parameters or invalid message (wrong MAC tag)") + raise ValueError("Invalid message (wrong MAC tag)") + return pt + + +def new( + *, + receiver_key: EccKey, + aead_id: AEAD, + enc: Optional[bytes] = None, + sender_key: Optional[EccKey] = None, + psk: Optional[tuple[bytes, bytes]] = None, + info: Optional[bytes] = None, +) -> HPKE_Cipher: + """Create an HPKE context which can be used: + + - by the sender to seal (encrypt) a message or + - by the receiver to unseal (decrypt) it. + + As a minimum, the two parties agree on the receiver's asymmetric key + (of which the sender will only know the public half). + + Additionally, for authentication purposes, they may also agree on: + + * the sender's asymmetric key (of which the receiver will only know the public half) + + * a shared secret (e.g., a symmetric key derived from a password) + + Args: + receiver_key: + The ECC key of the receiver. + It must be on one of the following curves: ``NIST P-256``, + ``NIST P-384``, ``NIST P-521``, ``X25519`` or ``X448``. + + If this is a **public** key, the HPKE context can only be used to + **seal** (**encrypt**). + + If this is a **private** key, the HPKE context can only be used to + **unseal** (**decrypt**). + + aead_id: + The HPKE identifier of the symmetric cipher. + The possible values are: + + * ``HPKE.AEAD.AES128_GCM`` + * ``HPKE.AEAD.AES256_GCM`` + * ``HPKE.AEAD.CHACHA20_POLY1305`` + + enc: + The encapsulated session key (i.e., the KEM shared secret). + + The receiver must always specify this parameter. + + The sender must always omit this parameter. + + sender_key: + The ECC key of the sender. + It must be on the same curve as the ``receiver_key``. + If the ``receiver_key`` is a public key, ``sender_key`` must be a + private key, and vice versa. + + psk: + A Pre-Shared Key (PSK) as a 2-tuple of non-empty + byte strings: the identifier and the actual secret value. + Sender and receiver must use the same PSK (or none). + + The secret value must be at least 32 bytes long, + but it must not be a low-entropy password + (use a KDF like PBKDF2 or scrypt to derive a secret + from a password). + + info: + A non-secret parameter that contributes + to the generation of all session keys. + Sender and receive must use the same **info** parameter (or none). + + Returns: + An object that can be used for + sealing (if ``receiver_key`` is a public key) or + unsealing (if ``receiver_key`` is a private key). + In the latter case, + correctness of all the keys and parameters will only + be assessed with the first call to ``unseal()``. + """ + + if aead_id not in AEAD: + raise ValueError(f"Unknown AEAD cipher ID {aead_id:#x}") + + curve = receiver_key.curve + if curve not in ( + "NIST P-256", + "NIST P-384", + "NIST P-521", + "Curve25519", + "Curve448", + ): + raise ValueError(f"Unsupported curve {curve}") + + if sender_key: + count_private_keys = int(receiver_key.has_private()) + int(sender_key.has_private()) + if count_private_keys != 1: + raise ValueError("Exactly 1 private key required") + if sender_key.curve != curve: + raise ValueError( + "Sender key uses {} but recipient key {}".format(sender_key.curve, curve), + ) + mode = MODE.AUTH if psk is None else MODE.AUTH_PSK + else: + mode = MODE.BASE if psk is None else MODE.PSK + + if psk is None: + psk = b"", b"" + + if info is None: + info = b"" + + return HPKE_Cipher( + receiver_key, + enc, + sender_key, + psk, + info, + aead_id, + mode, + ) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/KDF.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/KDF.py index 5f8170a0..c67f071c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/KDF.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/KDF.py @@ -26,622 +26,640 @@ import struct from functools import reduce -from Cryptodome.Util.py3compat import (tobytes, bord, _copy_bytes, iter_range, - tostr, bchr, bstr) +from Cryptodome.Util.py3compat import ( + tobytes, + bord, + _copy_bytes, + iter_range, + tostr, + bchr, + bstr, +) from Cryptodome.Hash import SHA1, SHA256, HMAC, CMAC, BLAKE2s from Cryptodome.Util.strxor import strxor from Cryptodome.Random import get_random_bytes from Cryptodome.Util.number import size as bit_size, long_to_bytes, bytes_to_long -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, c_size_t) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + create_string_buffer, + get_raw_buffer, + c_size_t, +) _raw_salsa20_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._Salsa20", - """ + "Cryptodome.Cipher._Salsa20", + """ int Salsa20_8_core(const uint8_t *x, const uint8_t *y, uint8_t *out); - """) + """, +) _raw_scrypt_lib = load_pycryptodome_raw_lib( - "Cryptodome.Protocol._scrypt", - """ + "Cryptodome.Protocol._scrypt", + """ typedef int (core_t)(const uint8_t [64], const uint8_t [64], uint8_t [64]); int scryptROMix(const uint8_t *data_in, uint8_t *data_out, size_t data_len, unsigned N, core_t *core); - """) + """, +) def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None): - """Derive one key from a password (or passphrase). - - This function performs key derivation according to an old version of - the PKCS#5 standard (v1.5) or `RFC2898 - `_. - - Args: - password (string): - The secret password to generate the key from. - salt (byte string): - An 8 byte string to use for better protection from dictionary attacks. - This value does not need to be kept secret, but it should be randomly - chosen for each derivation. - dkLen (integer): - The length of the desired key. The default is 16 bytes, suitable for - instance for :mod:`Cryptodome.Cipher.AES`. - count (integer): - The number of iterations to carry out. The recommendation is 1000 or - more. - hashAlgo (module): - The hash algorithm to use, as a module or an object from the :mod:`Cryptodome.Hash` package. - The digest length must be no shorter than ``dkLen``. - The default algorithm is :mod:`Cryptodome.Hash.SHA1`. - - Return: - A byte string of length ``dkLen`` that can be used as key. - """ - - if not hashAlgo: - hashAlgo = SHA1 - password = tobytes(password) - pHash = hashAlgo.new(password+salt) - digest = pHash.digest_size - if dkLen > digest: - raise TypeError("Selected hash algorithm has a too short digest (%d bytes)." % digest) - if len(salt) != 8: - raise ValueError("Salt is not 8 bytes long (%d bytes instead)." % len(salt)) - for i in iter_range(count-1): - pHash = pHash.new(pHash.digest()) - return pHash.digest()[:dkLen] + """Derive one key from a password (or passphrase). + + This function performs key derivation according to an old version of + the PKCS#5 standard (v1.5) or `RFC2898 + `_. + + Args: + password (string): + The secret password to generate the key from. + salt (byte string): + An 8 byte string to use for better protection from dictionary attacks. + This value does not need to be kept secret, but it should be randomly + chosen for each derivation. + dkLen (integer): + The length of the desired key. The default is 16 bytes, suitable for + instance for :mod:`Cryptodome.Cipher.AES`. + count (integer): + The number of iterations to carry out. The recommendation is 1000 or + more. + hashAlgo (module): + The hash algorithm to use, as a module or an object from the :mod:`Cryptodome.Hash` package. + The digest length must be no shorter than ``dkLen``. + The default algorithm is :mod:`Cryptodome.Hash.SHA1`. + + Return: + A byte string of length ``dkLen`` that can be used as key. + """ + + if not hashAlgo: + hashAlgo = SHA1 + password = tobytes(password) + pHash = hashAlgo.new(password + salt) + digest = pHash.digest_size + if dkLen > digest: + raise TypeError("Selected hash algorithm has a too short digest (%d bytes)." % digest) + if len(salt) != 8: + raise ValueError("Salt is not 8 bytes long (%d bytes instead)." % len(salt)) + for i in iter_range(count - 1): + pHash = pHash.new(pHash.digest()) + return pHash.digest()[:dkLen] def PBKDF2(password, salt, dkLen=16, count=1000, prf=None, hmac_hash_module=None): - """Derive one or more keys from a password (or passphrase). - - This function performs key derivation according to the PKCS#5 standard (v2.0). - - Args: - password (string or byte string): - The secret password to generate the key from. - - Strings will be encoded as ISO 8859-1 (also known as Latin-1), - which does not allow any characters with codepoints > 255. - salt (string or byte string): - A (byte) string to use for better protection from dictionary attacks. - This value does not need to be kept secret, but it should be randomly - chosen for each derivation. It is recommended to use at least 16 bytes. - - Strings will be encoded as ISO 8859-1 (also known as Latin-1), - which does not allow any characters with codepoints > 255. - dkLen (integer): - The cumulative length of the keys to produce. - - Due to a flaw in the PBKDF2 design, you should not request more bytes - than the ``prf`` can output. For instance, ``dkLen`` should not exceed - 20 bytes in combination with ``HMAC-SHA1``. - count (integer): - The number of iterations to carry out. The higher the value, the slower - and the more secure the function becomes. - - You should find the maximum number of iterations that keeps the - key derivation still acceptable on the slowest hardware you must support. - - Although the default value is 1000, **it is recommended to use at least - 1000000 (1 million) iterations**. - prf (callable): - A pseudorandom function. It must be a function that returns a - pseudorandom byte string from two parameters: a secret and a salt. - The slower the algorithm, the more secure the derivation function. - If not specified, **HMAC-SHA1** is used. - hmac_hash_module (module): - A module from ``Cryptodome.Hash`` implementing a Merkle-Damgard cryptographic - hash, which PBKDF2 must use in combination with HMAC. - This parameter is mutually exclusive with ``prf``. - - Return: - A byte string of length ``dkLen`` that can be used as key material. - If you want multiple keys, just break up this string into segments of the desired length. - """ - - password = tobytes(password) - salt = tobytes(salt) - - if prf and hmac_hash_module: - raise ValueError("'prf' and 'hmac_hash_module' are mutually exlusive") - - if prf is None and hmac_hash_module is None: - hmac_hash_module = SHA1 - - if prf or not hasattr(hmac_hash_module, "_pbkdf2_hmac_assist"): - # Generic (and slow) implementation - - if prf is None: - prf = lambda p, s: HMAC.new(p, s, hmac_hash_module).digest() - - def link(s): - s[0], s[1] = s[1], prf(password, s[1]) - return s[0] - - key = b'' - i = 1 - while len(key) < dkLen: - s = [prf(password, salt + struct.pack(">I", i))] * 2 - key += reduce(strxor, (link(s) for j in range(count))) - i += 1 - - else: - # Optimized implementation - key = b'' - i = 1 - while len(key) < dkLen: - base = HMAC.new(password, b"", hmac_hash_module) - first_digest = base.copy().update(salt + struct.pack(">I", i)).digest() - key += base._pbkdf2_hmac_assist(first_digest, count) - i += 1 - - return key[:dkLen] + """Derive one or more keys from a password (or passphrase). + + This function performs key derivation according to the PKCS#5 standard (v2.0). + + Args: + password (string or byte string): + The secret password to generate the key from. + + Strings will be encoded as ISO 8859-1 (also known as Latin-1), + which does not allow any characters with codepoints > 255. + salt (string or byte string): + A (byte) string to use for better protection from dictionary attacks. + This value does not need to be kept secret, but it should be randomly + chosen for each derivation. It is recommended to use at least 16 bytes. + + Strings will be encoded as ISO 8859-1 (also known as Latin-1), + which does not allow any characters with codepoints > 255. + dkLen (integer): + The cumulative length of the keys to produce. + + Due to a flaw in the PBKDF2 design, you should not request more bytes + than the ``prf`` can output. For instance, ``dkLen`` should not exceed + 20 bytes in combination with ``HMAC-SHA1``. + count (integer): + The number of iterations to carry out. The higher the value, the slower + and the more secure the function becomes. + + You should find the maximum number of iterations that keeps the + key derivation still acceptable on the slowest hardware you must support. + + Although the default value is 1000, **it is recommended to use at least + 1000000 (1 million) iterations**. + prf (callable): + A pseudorandom function. It must be a function that returns a + pseudorandom byte string from two parameters: a secret and a salt. + The slower the algorithm, the more secure the derivation function. + If not specified, **HMAC-SHA1** is used. + hmac_hash_module (module): + A module from ``Cryptodome.Hash`` implementing a Merkle-Damgard cryptographic + hash, which PBKDF2 must use in combination with HMAC. + This parameter is mutually exclusive with ``prf``. + + Return: + A byte string of length ``dkLen`` that can be used as key material. + If you want multiple keys, just break up this string into segments of the desired length. + """ + + password = tobytes(password) + salt = tobytes(salt) + + if prf and hmac_hash_module: + raise ValueError("'prf' and 'hmac_hash_module' are mutually exlusive") + + if prf is None and hmac_hash_module is None: + hmac_hash_module = SHA1 + + if prf or not hasattr(hmac_hash_module, "_pbkdf2_hmac_assist"): + # Generic (and slow) implementation + + if prf is None: + prf = lambda p, s: HMAC.new(p, s, hmac_hash_module).digest() + + def link(s): + s[0], s[1] = s[1], prf(password, s[1]) + return s[0] + + key = b"" + i = 1 + while len(key) < dkLen: + s = [prf(password, salt + struct.pack(">I", i))] * 2 + key += reduce(strxor, (link(s) for j in range(count))) + i += 1 + + else: + # Optimized implementation + key = b"" + i = 1 + while len(key) < dkLen: + base = HMAC.new(password, b"", hmac_hash_module) + first_digest = base.copy().update(salt + struct.pack(">I", i)).digest() + key += base._pbkdf2_hmac_assist(first_digest, count) + i += 1 + + return key[:dkLen] class _S2V(object): - """String-to-vector PRF as defined in `RFC5297`_. - - This class implements a pseudorandom function family - based on CMAC that takes as input a vector of strings. - - .. _RFC5297: http://tools.ietf.org/html/rfc5297 - """ - - def __init__(self, key, ciphermod, cipher_params=None): - """Initialize the S2V PRF. - - :Parameters: - key : byte string - A secret that can be used as key for CMACs - based on ciphers from ``ciphermod``. - ciphermod : module - A block cipher module from `Cryptodome.Cipher`. - cipher_params : dictionary - A set of extra parameters to use to create a cipher instance. - """ - - self._key = _copy_bytes(None, None, key) - self._ciphermod = ciphermod - self._last_string = self._cache = b'\x00' * ciphermod.block_size - - # Max number of update() call we can process - self._n_updates = ciphermod.block_size * 8 - 1 - - if cipher_params is None: - self._cipher_params = {} - else: - self._cipher_params = dict(cipher_params) - - @staticmethod - def new(key, ciphermod): - """Create a new S2V PRF. - - :Parameters: - key : byte string - A secret that can be used as key for CMACs - based on ciphers from ``ciphermod``. - ciphermod : module - A block cipher module from `Cryptodome.Cipher`. - """ - return _S2V(key, ciphermod) - - def _double(self, bs): - doubled = bytes_to_long(bs) << 1 - if bord(bs[0]) & 0x80: - doubled ^= 0x87 - return long_to_bytes(doubled, len(bs))[-len(bs):] - - def update(self, item): - """Pass the next component of the vector. - - The maximum number of components you can pass is equal to the block - length of the cipher (in bits) minus 1. - - :Parameters: - item : byte string - The next component of the vector. - :Raise TypeError: when the limit on the number of components has been reached. - """ - - if self._n_updates == 0: - raise TypeError("Too many components passed to S2V") - self._n_updates -= 1 - - mac = CMAC.new(self._key, - msg=self._last_string, - ciphermod=self._ciphermod, - cipher_params=self._cipher_params) - self._cache = strxor(self._double(self._cache), mac.digest()) - self._last_string = _copy_bytes(None, None, item) - - def derive(self): - """"Derive a secret from the vector of components. - - :Return: a byte string, as long as the block length of the cipher. - """ - - if len(self._last_string) >= 16: - # xorend - final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache) - else: - # zero-pad & xor - padded = (self._last_string + b'\x80' + b'\x00' * 15)[:16] - final = strxor(padded, self._double(self._cache)) - mac = CMAC.new(self._key, - msg=final, - ciphermod=self._ciphermod, - cipher_params=self._cipher_params) - return mac.digest() + """String-to-vector PRF as defined in `RFC5297`_. + + This class implements a pseudorandom function family + based on CMAC that takes as input a vector of strings. + + .. _RFC5297: http://tools.ietf.org/html/rfc5297 + """ + + def __init__(self, key, ciphermod, cipher_params=None): + """Initialize the S2V PRF. + + :Parameters: + key : byte string + A secret that can be used as key for CMACs + based on ciphers from ``ciphermod``. + ciphermod : module + A block cipher module from `Cryptodome.Cipher`. + cipher_params : dictionary + A set of extra parameters to use to create a cipher instance. + """ + + self._key = _copy_bytes(None, None, key) + self._ciphermod = ciphermod + self._last_string = self._cache = b"\x00" * ciphermod.block_size + + # Max number of update() call we can process + self._n_updates = ciphermod.block_size * 8 - 1 + + if cipher_params is None: + self._cipher_params = {} + else: + self._cipher_params = dict(cipher_params) + + @staticmethod + def new(key, ciphermod): + """Create a new S2V PRF. + + :Parameters: + key : byte string + A secret that can be used as key for CMACs + based on ciphers from ``ciphermod``. + ciphermod : module + A block cipher module from `Cryptodome.Cipher`. + """ + return _S2V(key, ciphermod) + + def _double(self, bs): + doubled = bytes_to_long(bs) << 1 + if bord(bs[0]) & 0x80: + doubled ^= 0x87 + return long_to_bytes(doubled, len(bs))[-len(bs) :] + + def update(self, item): + """Pass the next component of the vector. + + The maximum number of components you can pass is equal to the block + length of the cipher (in bits) minus 1. + + :Parameters: + item : byte string + The next component of the vector. + :Raise TypeError: when the limit on the number of components has been reached. + """ + + if self._n_updates == 0: + raise TypeError("Too many components passed to S2V") + self._n_updates -= 1 + + mac = CMAC.new( + self._key, + msg=self._last_string, + ciphermod=self._ciphermod, + cipher_params=self._cipher_params, + ) + self._cache = strxor(self._double(self._cache), mac.digest()) + self._last_string = _copy_bytes(None, None, item) + + def derive(self): + """ "Derive a secret from the vector of components. + + :Return: a byte string, as long as the block length of the cipher. + """ + + if len(self._last_string) >= 16: + # xorend + final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache) + else: + # zero-pad & xor + padded = (self._last_string + b"\x80" + b"\x00" * 15)[:16] + final = strxor(padded, self._double(self._cache)) + mac = CMAC.new( + self._key, + msg=final, + ciphermod=self._ciphermod, + cipher_params=self._cipher_params, + ) + return mac.digest() def _HKDF_extract(salt, ikm, hashmod): - prk = HMAC.new(salt, ikm, digestmod=hashmod).digest() - return prk + prk = HMAC.new(salt, ikm, digestmod=hashmod).digest() + return prk def _HKDF_expand(prk, info, L, hashmod): - t = [b""] - n = 1 - tlen = 0 - while tlen < L: - hmac = HMAC.new(prk, t[-1] + info + struct.pack('B', n), digestmod=hashmod) - t.append(hmac.digest()) - tlen += hashmod.digest_size - n += 1 - okm = b"".join(t) - return okm[:L] + t = [b""] + n = 1 + tlen = 0 + while tlen < L: + hmac = HMAC.new(prk, t[-1] + info + struct.pack("B", n), digestmod=hashmod) + t.append(hmac.digest()) + tlen += hashmod.digest_size + n += 1 + okm = b"".join(t) + return okm[:L] def HKDF(master, key_len, salt, hashmod, num_keys=1, context=None): - """Derive one or more keys from a master secret using - the HMAC-based KDF defined in RFC5869_. - - Args: - master (byte string): - The unguessable value used by the KDF to generate the other keys. - It must be a high-entropy secret, though not necessarily uniform. - It must not be a password. - key_len (integer): - The length in bytes of every derived key. - salt (byte string): - A non-secret, reusable value that strengthens the randomness - extraction step. - Ideally, it is as long as the digest size of the chosen hash. - If empty, a string of zeroes in used. - hashmod (module): - A cryptographic hash algorithm from :mod:`Cryptodome.Hash`. - :mod:`Cryptodome.Hash.SHA512` is a good choice. - num_keys (integer): - The number of keys to derive. Every key is :data:`key_len` bytes long. - The maximum cumulative length of all keys is - 255 times the digest size. - context (byte string): - Optional identifier describing what the keys are used for. - - Return: - A byte string or a tuple of byte strings. - - .. _RFC5869: http://tools.ietf.org/html/rfc5869 - """ - - output_len = key_len * num_keys - if output_len > (255 * hashmod.digest_size): - raise ValueError("Too much secret data to derive") - if not salt: - salt = b'\x00' * hashmod.digest_size - if context is None: - context = b"" - - prk = _HKDF_extract(salt, master, hashmod) - okm = _HKDF_expand(prk, context, output_len, hashmod) - - if num_keys == 1: - return okm[:key_len] - kol = [okm[idx:idx + key_len] - for idx in iter_range(0, output_len, key_len)] - return list(kol[:num_keys]) + """Derive one or more keys from a master secret using + the HMAC-based KDF defined in RFC5869_. + + Args: + master (byte string): + The unguessable value used by the KDF to generate the other keys. + It must be a high-entropy secret, though not necessarily uniform. + It must not be a password. + key_len (integer): + The length in bytes of every derived key. + salt (byte string): + A non-secret, reusable value that strengthens the randomness + extraction step. + Ideally, it is as long as the digest size of the chosen hash. + If empty, a string of zeroes in used. + hashmod (module): + A cryptographic hash algorithm from :mod:`Cryptodome.Hash`. + :mod:`Cryptodome.Hash.SHA512` is a good choice. + num_keys (integer): + The number of keys to derive. Every key is :data:`key_len` bytes long. + The maximum cumulative length of all keys is + 255 times the digest size. + context (byte string): + Optional identifier describing what the keys are used for. + + Return: + A byte string or a tuple of byte strings. + + .. _RFC5869: http://tools.ietf.org/html/rfc5869 + """ + + output_len = key_len * num_keys + if output_len > (255 * hashmod.digest_size): + raise ValueError("Too much secret data to derive") + if not salt: + salt = b"\x00" * hashmod.digest_size + if context is None: + context = b"" + + prk = _HKDF_extract(salt, master, hashmod) + okm = _HKDF_expand(prk, context, output_len, hashmod) + + if num_keys == 1: + return okm[:key_len] + kol = [okm[idx : idx + key_len] for idx in iter_range(0, output_len, key_len)] + return list(kol[:num_keys]) def scrypt(password, salt, key_len, N, r, p, num_keys=1): - """Derive one or more keys from a passphrase. - - Args: - password (string): - The secret pass phrase to generate the keys from. - salt (string): - A string to use for better protection from dictionary attacks. - This value does not need to be kept secret, - but it should be randomly chosen for each derivation. - It is recommended to be at least 16 bytes long. - key_len (integer): - The length in bytes of each derived key. - N (integer): - CPU/Memory cost parameter. It must be a power of 2 and less - than :math:`2^{32}`. - r (integer): - Block size parameter. - p (integer): - Parallelization parameter. - It must be no greater than :math:`(2^{32}-1)/(4r)`. - num_keys (integer): - The number of keys to derive. Every key is :data:`key_len` bytes long. - By default, only 1 key is generated. - The maximum cumulative length of all keys is :math:`(2^{32}-1)*32` - (that is, 128TB). - - A good choice of parameters *(N, r , p)* was suggested - by Colin Percival in his `presentation in 2009`__: - - - *( 2¹⁴, 8, 1 )* for interactive logins (≤100ms) - - *( 2²⁰, 8, 1 )* for file encryption (≤5s) - - Return: - A byte string or a tuple of byte strings. - - .. __: http://www.tarsnap.com/scrypt/scrypt-slides.pdf - """ - - if 2 ** (bit_size(N) - 1) != N: - raise ValueError("N must be a power of 2") - if N >= 2 ** 32: - raise ValueError("N is too big") - if p > ((2 ** 32 - 1) * 32) // (128 * r): - raise ValueError("p or r are too big") - - prf_hmac_sha256 = lambda p, s: HMAC.new(p, s, SHA256).digest() - - stage_1 = PBKDF2(password, salt, p * 128 * r, 1, prf=prf_hmac_sha256) - - scryptROMix = _raw_scrypt_lib.scryptROMix - core = _raw_salsa20_lib.Salsa20_8_core - - # Parallelize into p flows - data_out = [] - for flow in iter_range(p): - idx = flow * 128 * r - buffer_out = create_string_buffer(128 * r) - result = scryptROMix(stage_1[idx: idx + 128 * r], - buffer_out, - c_size_t(128 * r), - N, - core) - if result: - raise ValueError("Error %X while running scrypt" % result) - data_out += [get_raw_buffer(buffer_out)] - - dk = PBKDF2(password, - b"".join(data_out), - key_len * num_keys, 1, - prf=prf_hmac_sha256) - - if num_keys == 1: - return dk - - kol = [dk[idx:idx + key_len] - for idx in iter_range(0, key_len * num_keys, key_len)] - return kol + """Derive one or more keys from a passphrase. + + Args: + password (string): + The secret pass phrase to generate the keys from. + salt (string): + A string to use for better protection from dictionary attacks. + This value does not need to be kept secret, + but it should be randomly chosen for each derivation. + It is recommended to be at least 16 bytes long. + key_len (integer): + The length in bytes of each derived key. + N (integer): + CPU/Memory cost parameter. It must be a power of 2 and less + than :math:`2^{32}`. + r (integer): + Block size parameter. + p (integer): + Parallelization parameter. + It must be no greater than :math:`(2^{32}-1)/(4r)`. + num_keys (integer): + The number of keys to derive. Every key is :data:`key_len` bytes long. + By default, only 1 key is generated. + The maximum cumulative length of all keys is :math:`(2^{32}-1)*32` + (that is, 128TB). + + A good choice of parameters *(N, r , p)* was suggested + by Colin Percival in his `presentation in 2009`__: + + - *( 2¹⁴, 8, 1 )* for interactive logins (≤100ms) + - *( 2²⁰, 8, 1 )* for file encryption (≤5s) + + Return: + A byte string or a tuple of byte strings. + + .. __: http://www.tarsnap.com/scrypt/scrypt-slides.pdf + """ + + if 2 ** (bit_size(N) - 1) != N: + raise ValueError("N must be a power of 2") + if N >= 2**32: + raise ValueError("N is too big") + if p > ((2**32 - 1) * 32) // (128 * r): + raise ValueError("p or r are too big") + + prf_hmac_sha256 = lambda p, s: HMAC.new(p, s, SHA256).digest() + + stage_1 = PBKDF2(password, salt, p * 128 * r, 1, prf=prf_hmac_sha256) + + scryptROMix = _raw_scrypt_lib.scryptROMix + core = _raw_salsa20_lib.Salsa20_8_core + + # Parallelize into p flows + data_out = [] + for flow in iter_range(p): + idx = flow * 128 * r + buffer_out = create_string_buffer(128 * r) + result = scryptROMix( + stage_1[idx : idx + 128 * r], + buffer_out, + c_size_t(128 * r), + N, + core, + ) + if result: + raise ValueError("Error %X while running scrypt" % result) + data_out += [get_raw_buffer(buffer_out)] + + dk = PBKDF2( + password, + b"".join(data_out), + key_len * num_keys, + 1, + prf=prf_hmac_sha256, + ) + + if num_keys == 1: + return dk + + kol = [dk[idx : idx + key_len] for idx in iter_range(0, key_len * num_keys, key_len)] + return kol def _bcrypt_encode(data): - s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - bits = [] - for c in data: - bits_c = bin(bord(c))[2:].zfill(8) - bits.append(bstr(bits_c)) - bits = b"".join(bits) + bits = [] + for c in data: + bits_c = bin(bord(c))[2:].zfill(8) + bits.append(bstr(bits_c)) + bits = b"".join(bits) - bits6 = [bits[idx:idx+6] for idx in range(0, len(bits), 6)] + bits6 = [bits[idx : idx + 6] for idx in range(0, len(bits), 6)] - result = [] - for g in bits6[:-1]: - idx = int(g, 2) - result.append(s[idx]) + result = [] + for g in bits6[:-1]: + idx = int(g, 2) + result.append(s[idx]) - g = bits6[-1] - idx = int(g, 2) << (6 - len(g)) - result.append(s[idx]) - result = "".join(result) + g = bits6[-1] + idx = int(g, 2) << (6 - len(g)) + result.append(s[idx]) + result = "".join(result) - return tobytes(result) + return tobytes(result) def _bcrypt_decode(data): - s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - bits = [] - for c in tostr(data): - idx = s.find(c) - bits6 = bin(idx)[2:].zfill(6) - bits.append(bits6) - bits = "".join(bits) + bits = [] + for c in tostr(data): + idx = s.find(c) + bits6 = bin(idx)[2:].zfill(6) + bits.append(bits6) + bits = "".join(bits) - modulo4 = len(data) % 4 - if modulo4 == 1: - raise ValueError("Incorrect length") - elif modulo4 == 2: - bits = bits[:-4] - elif modulo4 == 3: - bits = bits[:-2] + modulo4 = len(data) % 4 + if modulo4 == 1: + raise ValueError("Incorrect length") + elif modulo4 == 2: + bits = bits[:-4] + elif modulo4 == 3: + bits = bits[:-2] - bits8 = [bits[idx:idx+8] for idx in range(0, len(bits), 8)] + bits8 = [bits[idx : idx + 8] for idx in range(0, len(bits), 8)] - result = [] - for g in bits8: - result.append(bchr(int(g, 2))) - result = b"".join(result) + result = [] + for g in bits8: + result.append(bchr(int(g, 2))) + result = b"".join(result) - return result + return result def _bcrypt_hash(password, cost, salt, constant, invert): - from Cryptodome.Cipher import _EKSBlowfish + from Cryptodome.Cipher import _EKSBlowfish - if len(password) > 72: - raise ValueError("The password is too long. It must be 72 bytes at most.") + if len(password) > 72: + raise ValueError("The password is too long. It must be 72 bytes at most.") - if not (4 <= cost <= 31): - raise ValueError("bcrypt cost factor must be in the range 4..31") + if not (4 <= cost <= 31): + raise ValueError("bcrypt cost factor must be in the range 4..31") - cipher = _EKSBlowfish.new(password, _EKSBlowfish.MODE_ECB, salt, cost, invert) - ctext = constant - for _ in range(64): - ctext = cipher.encrypt(ctext) - return ctext + cipher = _EKSBlowfish.new(password, _EKSBlowfish.MODE_ECB, salt, cost, invert) + ctext = constant + for _ in range(64): + ctext = cipher.encrypt(ctext) + return ctext def bcrypt(password, cost, salt=None): - """Hash a password into a key, using the OpenBSD bcrypt protocol. + """Hash a password into a key, using the OpenBSD bcrypt protocol. - Args: - password (byte string or string): - The secret password or pass phrase. - It must be at most 72 bytes long. - It must not contain the zero byte. - Unicode strings will be encoded as UTF-8. - cost (integer): - The exponential factor that makes it slower to compute the hash. - It must be in the range 4 to 31. - A value of at least 12 is recommended. - salt (byte string): - Optional. Random byte string to thwarts dictionary and rainbow table - attacks. It must be 16 bytes long. - If not passed, a random value is generated. + Args: + password (byte string or string): + The secret password or pass phrase. + It must be at most 72 bytes long. + It must not contain the zero byte. + Unicode strings will be encoded as UTF-8. + cost (integer): + The exponential factor that makes it slower to compute the hash. + It must be in the range 4 to 31. + A value of at least 12 is recommended. + salt (byte string): + Optional. Random byte string to thwarts dictionary and rainbow table + attacks. It must be 16 bytes long. + If not passed, a random value is generated. - Return (byte string): - The bcrypt hash + Return (byte string): + The bcrypt hash - Raises: - ValueError: if password is longer than 72 bytes or if it contains the zero byte + Raises: + ValueError: if password is longer than 72 bytes or if it contains the zero byte - """ + """ - password = tobytes(password, "utf-8") + password = tobytes(password, "utf-8") - if password.find(bchr(0)[0]) != -1: - raise ValueError("The password contains the zero byte") + if password.find(bchr(0)[0]) != -1: + raise ValueError("The password contains the zero byte") - if len(password) < 72: - password += b"\x00" + if len(password) < 72: + password += b"\x00" - if salt is None: - salt = get_random_bytes(16) - if len(salt) != 16: - raise ValueError("bcrypt salt must be 16 bytes long") + if salt is None: + salt = get_random_bytes(16) + if len(salt) != 16: + raise ValueError("bcrypt salt must be 16 bytes long") - ctext = _bcrypt_hash(password, cost, salt, b"OrpheanBeholderScryDoubt", True) + ctext = _bcrypt_hash(password, cost, salt, b"OrpheanBeholderScryDoubt", True) - cost_enc = b"$" + bstr(str(cost).zfill(2)) - salt_enc = b"$" + _bcrypt_encode(salt) - hash_enc = _bcrypt_encode(ctext[:-1]) # only use 23 bytes, not 24 - return b"$2a" + cost_enc + salt_enc + hash_enc + cost_enc = b"$" + bstr(str(cost).zfill(2)) + salt_enc = b"$" + _bcrypt_encode(salt) + hash_enc = _bcrypt_encode(ctext[:-1]) # only use 23 bytes, not 24 + return b"$2a" + cost_enc + salt_enc + hash_enc def bcrypt_check(password, bcrypt_hash): - """Verify if the provided password matches the given bcrypt hash. - - Args: - password (byte string or string): - The secret password or pass phrase to test. - It must be at most 72 bytes long. - It must not contain the zero byte. - Unicode strings will be encoded as UTF-8. - bcrypt_hash (byte string, bytearray): - The reference bcrypt hash the password needs to be checked against. - - Raises: - ValueError: if the password does not match - """ - - bcrypt_hash = tobytes(bcrypt_hash) - - if len(bcrypt_hash) != 60: - raise ValueError("Incorrect length of the bcrypt hash: %d bytes instead of 60" % len(bcrypt_hash)) - - if bcrypt_hash[:4] != b'$2a$': - raise ValueError("Unsupported prefix") - - p = re.compile(br'\$2a\$([0-9][0-9])\$([A-Za-z0-9./]{22,22})([A-Za-z0-9./]{31,31})') - r = p.match(bcrypt_hash) - if not r: - raise ValueError("Incorrect bcrypt hash format") - - cost = int(r.group(1)) - if not (4 <= cost <= 31): - raise ValueError("Incorrect cost") - - salt = _bcrypt_decode(r.group(2)) - - bcrypt_hash2 = bcrypt(password, cost, salt) - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash).digest() - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash2).digest() - if mac1 != mac2: - raise ValueError("Incorrect bcrypt hash") - - -def SP800_108_Counter(master, key_len, prf, num_keys=None, label=b'', context=b''): - """Derive one or more keys from a master secret using - a pseudorandom function in Counter Mode, as specified in - `NIST SP 800-108r1 `_. - - Args: - master (byte string): - The secret value used by the KDF to derive the other keys. - It must not be a password. - The length on the secret must be consistent with the input expected by - the :data:`prf` function. - key_len (integer): - The length in bytes of each derived key. - prf (function): - A pseudorandom function that takes two byte strings as parameters: - the secret and an input. It returns another byte string. - num_keys (integer): - The number of keys to derive. Every key is :data:`key_len` bytes long. - By default, only 1 key is derived. - label (byte string): - Optional description of the purpose of the derived keys. - It must not contain zero bytes. - context (byte string): - Optional information pertaining to - the protocol that uses the keys, such as the identity of the - participants, nonces, session IDs, etc. - It must not contain zero bytes. - - Return: - - a byte string (if ``num_keys`` is not specified), or - - a tuple of byte strings (if ``num_key`` is specified). - """ - - if num_keys is None: - num_keys = 1 - - if context.find(b'\x00') != -1: - raise ValueError("Null byte found in context") - - key_len_enc = long_to_bytes(key_len * num_keys * 8, 4) - output_len = key_len * num_keys - - i = 1 - dk = b"" - while len(dk) < output_len: - info = long_to_bytes(i, 4) + label + b'\x00' + context + key_len_enc - dk += prf(master, info) - i += 1 - if i > 0xFFFFFFFF: - raise ValueError("Overflow in SP800 108 counter") - - if num_keys == 1: - return dk[:key_len] - else: - kol = [dk[idx:idx + key_len] - for idx in iter_range(0, output_len, key_len)] - return kol + """Verify if the provided password matches the given bcrypt hash. + + Args: + password (byte string or string): + The secret password or pass phrase to test. + It must be at most 72 bytes long. + It must not contain the zero byte. + Unicode strings will be encoded as UTF-8. + bcrypt_hash (byte string, bytearray): + The reference bcrypt hash the password needs to be checked against. + + Raises: + ValueError: if the password does not match + """ + + bcrypt_hash = tobytes(bcrypt_hash) + + if len(bcrypt_hash) != 60: + raise ValueError("Incorrect length of the bcrypt hash: %d bytes instead of 60" % len(bcrypt_hash)) + + if bcrypt_hash[:4] != b"$2a$": + raise ValueError("Unsupported prefix") + + p = re.compile(rb"\$2a\$([0-9][0-9])\$([A-Za-z0-9./]{22,22})([A-Za-z0-9./]{31,31})") + r = p.match(bcrypt_hash) + if not r: + raise ValueError("Incorrect bcrypt hash format") + + cost = int(r.group(1)) + if not (4 <= cost <= 31): + raise ValueError("Incorrect cost") + + salt = _bcrypt_decode(r.group(2)) + + bcrypt_hash2 = bcrypt(password, cost, salt) + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash).digest() + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash2).digest() + if mac1 != mac2: + raise ValueError("Incorrect bcrypt hash") + + +def SP800_108_Counter(master, key_len, prf, num_keys=None, label=b"", context=b""): + """Derive one or more keys from a master secret using + a pseudorandom function in Counter Mode, as specified in + `NIST SP 800-108r1 `_. + + Args: + master (byte string): + The secret value used by the KDF to derive the other keys. + It must not be a password. + The length on the secret must be consistent with the input expected by + the :data:`prf` function. + key_len (integer): + The length in bytes of each derived key. + prf (function): + A pseudorandom function that takes two byte strings as parameters: + the secret and an input. It returns another byte string. + num_keys (integer): + The number of keys to derive. Every key is :data:`key_len` bytes long. + By default, only 1 key is derived. + label (byte string): + Optional description of the purpose of the derived keys. + It must not contain zero bytes. + context (byte string): + Optional information pertaining to + the protocol that uses the keys, such as the identity of the + participants, nonces, session IDs, etc. + It must not contain zero bytes. + + Return: + - a byte string (if ``num_keys`` is not specified), or + - a tuple of byte strings (if ``num_key`` is specified). + """ + + if num_keys is None: + num_keys = 1 + + if context.find(b"\x00") != -1: + raise ValueError("Null byte found in context") + + key_len_enc = long_to_bytes(key_len * num_keys * 8, 4) + output_len = key_len * num_keys + + i = 1 + dk = b"" + while len(dk) < output_len: + info = long_to_bytes(i, 4) + label + b"\x00" + context + key_len_enc + dk += prf(master, info) + i += 1 + if i > 0xFFFFFFFF: + raise ValueError("Overflow in SP800 108 counter") + + if num_keys == 1: + return dk[:key_len] + else: + kol = [dk[idx : idx + key_len] for idx in iter_range(0, output_len, key_len)] + return kol diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/KDF.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/KDF.pyi index 80691e0f..21289389 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/KDF.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/KDF.pyi @@ -2,43 +2,59 @@ from types import ModuleType from typing import Optional, Callable, Tuple, Union, Dict, Any, overload from typing_extensions import Literal -Buffer=bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview RNG = Callable[[int], bytes] PRF = Callable[[bytes, bytes], bytes] -def PBKDF1(password: str, salt: bytes, dkLen: int, count: Optional[int]=1000, hashAlgo: Optional[ModuleType]=None) -> bytes: ... -def PBKDF2(password: str, salt: bytes, dkLen: Optional[int]=16, count: Optional[int]=1000, prf: Optional[RNG]=None, hmac_hash_module: Optional[ModuleType]=None) -> bytes: ... +def PBKDF1( + password: str, salt: bytes, dkLen: int, count: Optional[int] = 1000, hashAlgo: Optional[ModuleType] = None +) -> bytes: ... +def PBKDF2( + password: str, + salt: bytes, + dkLen: Optional[int] = 16, + count: Optional[int] = 1000, + prf: Optional[RNG] = None, + hmac_hash_module: Optional[ModuleType] = None, +) -> bytes: ... class _S2V(object): - def __init__(self, key: bytes, ciphermod: ModuleType, cipher_params: Optional[Dict[Any, Any]]=None) -> None: ... - - @staticmethod - def new(key: bytes, ciphermod: ModuleType) -> None: ... - def update(self, item: bytes) -> None: ... - def derive(self) -> bytes: ... + def __init__( + self, key: bytes, ciphermod: ModuleType, cipher_params: Optional[Dict[Any, Any]] = None + ) -> None: ... + @staticmethod + def new(key: bytes, ciphermod: ModuleType) -> None: ... + def update(self, item: bytes) -> None: ... + def derive(self) -> bytes: ... def _HKDF_extract(salt: Buffer, ikm: Buffer, hashmod: ModuleType) -> bytes: ... -def _HKDF_expand(prk: Buffer, info: Buffer, L: int, hashmod) -> bytes : ... -def HKDF(master: bytes, key_len: int, salt: bytes, hashmod: ModuleType, num_keys: Optional[int]=1, context: Optional[bytes]=None) -> Union[bytes, Tuple[bytes, ...]]: ... - -def scrypt(password: str, salt: str, key_len: int, N: int, r: int, p: int, num_keys: Optional[int]=1) -> Union[bytes, Tuple[bytes, ...]]: ... - +def _HKDF_expand(prk: Buffer, info: Buffer, L: int, hashmod) -> bytes: ... +def HKDF( + master: bytes, + key_len: int, + salt: bytes, + hashmod: ModuleType, + num_keys: Optional[int] = 1, + context: Optional[bytes] = None, +) -> Union[bytes, Tuple[bytes, ...]]: ... +def scrypt( + password: str, salt: str, key_len: int, N: int, r: int, p: int, num_keys: Optional[int] = 1 +) -> Union[bytes, Tuple[bytes, ...]]: ... def _bcrypt_decode(data: bytes) -> bytes: ... -def _bcrypt_hash(password:bytes , cost: int, salt: bytes, constant:bytes, invert:bool) -> bytes: ... -def bcrypt(password: Union[bytes, str], cost: int, salt: Optional[bytes]=None) -> bytes: ... +def _bcrypt_hash(password: bytes, cost: int, salt: bytes, constant: bytes, invert: bool) -> bytes: ... +def bcrypt(password: Union[bytes, str], cost: int, salt: Optional[bytes] = None) -> bytes: ... def bcrypt_check(password: Union[bytes, str], bcrypt_hash: Union[bytes, bytearray, str]) -> None: ... - @overload -def SP800_108_Counter(master: Buffer, - key_len: int, - prf: PRF, - num_keys: Literal[None] = None, - label: Buffer = b'', context: Buffer = b'') -> bytes: ... - +def SP800_108_Counter( + master: Buffer, + key_len: int, + prf: PRF, + num_keys: Literal[None] = None, + label: Buffer = b"", + context: Buffer = b"", +) -> bytes: ... @overload -def SP800_108_Counter(master: Buffer, - key_len: int, - prf: PRF, - num_keys: int, - label: Buffer = b'', context: Buffer = b'') -> Tuple[bytes]: ... +def SP800_108_Counter( + master: Buffer, key_len: int, prf: PRF, num_keys: int, label: Buffer = b"", context: Buffer = b"" +) -> Tuple[bytes]: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/SecretSharing.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/SecretSharing.py index 1034909f..2d07c5f1 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/SecretSharing.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/SecretSharing.py @@ -38,260 +38,259 @@ def _mult_gf2(f1, f2): - """Multiply two polynomials in GF(2)""" + """Multiply two polynomials in GF(2)""" - # Ensure f2 is the smallest - if f2 > f1: - f1, f2 = f2, f1 - z = 0 - while f2: - if f2 & 1: - z ^= f1 - f1 <<= 1 - f2 >>= 1 - return z + # Ensure f2 is the smallest + if f2 > f1: + f1, f2 = f2, f1 + z = 0 + while f2: + if f2 & 1: + z ^= f1 + f1 <<= 1 + f2 >>= 1 + return z def _div_gf2(a, b): - """ - Compute division of polynomials over GF(2). - Given a and b, it finds two polynomials q and r such that: + """ + Compute division of polynomials over GF(2). + Given a and b, it finds two polynomials q and r such that: - a = b*q + r with deg(r)= d: - s = 1 << (deg(r) - d) - q ^= s - r ^= _mult_gf2(b, s) - return (q, r) + deg = number.size + q = 0 + r = a + d = deg(b) + while deg(r) >= d: + s = 1 << (deg(r) - d) + q ^= s + r ^= _mult_gf2(b, s) + return (q, r) class _Element(object): - """Element of GF(2^128) field""" - - # The irreducible polynomial defining - # this field is 1 + x + x^2 + x^7 + x^128 - irr_poly = 1 + 2 + 4 + 128 + 2 ** 128 - - def __init__(self, encoded_value): - """Initialize the element to a certain value. - - The value passed as parameter is internally encoded as - a 128-bit integer, where each bit represents a polynomial - coefficient. The LSB is the constant coefficient. - """ - - if is_native_int(encoded_value): - self._value = encoded_value - elif len(encoded_value) == 16: - self._value = bytes_to_long(encoded_value) - else: - raise ValueError("The encoded value must be an integer or a 16 byte string") - - def __eq__(self, other): - return self._value == other._value - - def __int__(self): - """Return the field element, encoded as a 128-bit integer.""" - return self._value - - def encode(self): - """Return the field element, encoded as a 16 byte string.""" - return long_to_bytes(self._value, 16) - - def __mul__(self, factor): - - f1 = self._value - f2 = factor._value - - # Make sure that f2 is the smallest, to speed up the loop - if f2 > f1: - f1, f2 = f2, f1 - - if self.irr_poly in (f1, f2): - return _Element(0) - - mask1 = 2 ** 128 - v, z = f1, 0 - while f2: - # if f2 ^ 1: z ^= v - mask2 = int(bin(f2 & 1)[2:] * 128, base=2) - z = (mask2 & (z ^ v)) | ((mask1 - mask2 - 1) & z) - v <<= 1 - # if v & mask1: v ^= self.irr_poly - mask3 = int(bin((v >> 128) & 1)[2:] * 128, base=2) - v = (mask3 & (v ^ self.irr_poly)) | ((mask1 - mask3 - 1) & v) - f2 >>= 1 - return _Element(z) - - def __add__(self, term): - return _Element(self._value ^ term._value) - - def inverse(self): - """Return the inverse of this element in GF(2^128).""" - - # We use the Extended GCD algorithm - # http://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor - - if self._value == 0: - raise ValueError("Inversion of zero") - - r0, r1 = self._value, self.irr_poly - s0, s1 = 1, 0 - while r1 > 0: - q = _div_gf2(r0, r1)[0] - r0, r1 = r1, r0 ^ _mult_gf2(q, r1) - s0, s1 = s1, s0 ^ _mult_gf2(q, s1) - return _Element(s0) - - def __pow__(self, exponent): - result = _Element(self._value) - for _ in range(exponent - 1): - result = result * self - return result + """Element of GF(2^128) field""" + + # The irreducible polynomial defining + # this field is 1 + x + x^2 + x^7 + x^128 + irr_poly = 1 + 2 + 4 + 128 + 2**128 + + def __init__(self, encoded_value): + """Initialize the element to a certain value. + + The value passed as parameter is internally encoded as + a 128-bit integer, where each bit represents a polynomial + coefficient. The LSB is the constant coefficient. + """ + + if is_native_int(encoded_value): + self._value = encoded_value + elif len(encoded_value) == 16: + self._value = bytes_to_long(encoded_value) + else: + raise ValueError("The encoded value must be an integer or a 16 byte string") + + def __eq__(self, other): + return self._value == other._value + + def __int__(self): + """Return the field element, encoded as a 128-bit integer.""" + return self._value + + def encode(self): + """Return the field element, encoded as a 16 byte string.""" + return long_to_bytes(self._value, 16) + + def __mul__(self, factor): + f1 = self._value + f2 = factor._value + + # Make sure that f2 is the smallest, to speed up the loop + if f2 > f1: + f1, f2 = f2, f1 + + if self.irr_poly in (f1, f2): + return _Element(0) + + mask1 = 2**128 + v, z = f1, 0 + while f2: + # if f2 ^ 1: z ^= v + mask2 = int(bin(f2 & 1)[2:] * 128, base=2) + z = (mask2 & (z ^ v)) | ((mask1 - mask2 - 1) & z) + v <<= 1 + # if v & mask1: v ^= self.irr_poly + mask3 = int(bin((v >> 128) & 1)[2:] * 128, base=2) + v = (mask3 & (v ^ self.irr_poly)) | ((mask1 - mask3 - 1) & v) + f2 >>= 1 + return _Element(z) + + def __add__(self, term): + return _Element(self._value ^ term._value) + + def inverse(self): + """Return the inverse of this element in GF(2^128).""" + + # We use the Extended GCD algorithm + # http://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor + + if self._value == 0: + raise ValueError("Inversion of zero") + + r0, r1 = self._value, self.irr_poly + s0, s1 = 1, 0 + while r1 > 0: + q = _div_gf2(r0, r1)[0] + r0, r1 = r1, r0 ^ _mult_gf2(q, r1) + s0, s1 = s1, s0 ^ _mult_gf2(q, s1) + return _Element(s0) + + def __pow__(self, exponent): + result = _Element(self._value) + for _ in range(exponent - 1): + result = result * self + return result class Shamir(object): - """Shamir's secret sharing scheme. - - A secret is split into ``n`` shares, and it is sufficient to collect - ``k`` of them to reconstruct the secret. - """ - - @staticmethod - def split(k, n, secret, ssss=False): - """Split a secret into ``n`` shares. - - The secret can be reconstructed later using just ``k`` shares - out of the original ``n``. - Each share must be kept confidential to the person it was - assigned to. - - Each share is associated to an index (starting from 1). - - Args: - k (integer): - The number of shares needed to reconstruct the secret. - n (integer): - The number of shares to create (at least ``k``). - secret (byte string): - A byte string of 16 bytes (e.g. an AES 128 key). - ssss (bool): - If ``True``, the shares can be used with the ``ssss`` utility - (without using the "diffusion layer"). - Default: ``False``. - - Return (tuples): - ``n`` tuples, one per participant. - A tuple contains two items: - - 1. the unique index (an integer) - 2. the share (16 bytes) - """ - - # - # We create a polynomial with random coefficients in GF(2^128): - # - # p(x) = c_0 + \sum_{i=1}^{k-1} c_i * x^i - # - # c_0 is the secret. - # - - coeffs = [_Element(rng(16)) for i in range(k - 1)] - coeffs.append(_Element(secret)) - - # Each share is y_i = p(x_i) where x_i - # is the index assigned to the share. - - def make_share(user, coeffs, ssss): - idx = _Element(user) - - # Horner's method - share = _Element(0) - for coeff in coeffs: - share = idx * share + coeff - - # The ssss utility actually uses: - # - # p(x) = c_0 + \sum_{i=1}^{k-1} c_i * x^i + x^k - # - if ssss: - share += _Element(user) ** len(coeffs) - - return share.encode() - - return [(i, make_share(i, coeffs, ssss)) for i in range(1, n + 1)] - - @staticmethod - def combine(shares, ssss=False): - """Recombine a secret, if enough shares are presented. - - Args: - shares (tuples): - The *k* tuples, each containing the index (an integer) and - the share (a byte string, 16 bytes long) that were assigned to - a participant. - - .. note:: - - Pass exactly as many share as they are required, - and no more. - - ssss (bool): - If ``True``, the shares were produced by the ``ssss`` utility - (without using the "diffusion layer"). - Default: ``False``. - - Return: - The original secret, as a byte string (16 bytes long). - """ - - # - # Given k points (x,y), the interpolation polynomial of degree k-1 is: - # - # L(x) = \sum_{j=0}^{k-1} y_i * l_j(x) - # - # where: - # - # l_j(x) = \prod_{ \overset{0 \le m \le k-1}{m \ne j} } - # \frac{x - x_m}{x_j - x_m} - # - # However, in this case we are purely interested in the constant - # coefficient of L(x). - # - - k = len(shares) - - gf_shares = [] - for x in shares: - idx = _Element(x[0]) - value = _Element(x[1]) - if any(y[0] == idx for y in gf_shares): - raise ValueError("Duplicate share") - if ssss: - value += idx ** k - gf_shares.append((idx, value)) - - result = _Element(0) - for j in range(k): - x_j, y_j = gf_shares[j] - - numerator = _Element(1) - denominator = _Element(1) - - for m in range(k): - x_m = gf_shares[m][0] - if m != j: - numerator *= x_m - denominator *= x_j + x_m - result += y_j * numerator * denominator.inverse() - - return result.encode() + """Shamir's secret sharing scheme. + + A secret is split into ``n`` shares, and it is sufficient to collect + ``k`` of them to reconstruct the secret. + """ + + @staticmethod + def split(k, n, secret, ssss=False): + """Split a secret into ``n`` shares. + + The secret can be reconstructed later using just ``k`` shares + out of the original ``n``. + Each share must be kept confidential to the person it was + assigned to. + + Each share is associated to an index (starting from 1). + + Args: + k (integer): + The number of shares needed to reconstruct the secret. + n (integer): + The number of shares to create (at least ``k``). + secret (byte string): + A byte string of 16 bytes (e.g. an AES 128 key). + ssss (bool): + If ``True``, the shares can be used with the ``ssss`` utility + (without using the "diffusion layer"). + Default: ``False``. + + Return (tuples): + ``n`` tuples, one per participant. + A tuple contains two items: + + 1. the unique index (an integer) + 2. the share (16 bytes) + """ + + # + # We create a polynomial with random coefficients in GF(2^128): + # + # p(x) = c_0 + \sum_{i=1}^{k-1} c_i * x^i + # + # c_0 is the secret. + # + + coeffs = [_Element(rng(16)) for i in range(k - 1)] + coeffs.append(_Element(secret)) + + # Each share is y_i = p(x_i) where x_i + # is the index assigned to the share. + + def make_share(user, coeffs, ssss): + idx = _Element(user) + + # Horner's method + share = _Element(0) + for coeff in coeffs: + share = idx * share + coeff + + # The ssss utility actually uses: + # + # p(x) = c_0 + \sum_{i=1}^{k-1} c_i * x^i + x^k + # + if ssss: + share += _Element(user) ** len(coeffs) + + return share.encode() + + return [(i, make_share(i, coeffs, ssss)) for i in range(1, n + 1)] + + @staticmethod + def combine(shares, ssss=False): + """Recombine a secret, if enough shares are presented. + + Args: + shares (tuples): + The *k* tuples, each containing the index (an integer) and + the share (a byte string, 16 bytes long) that were assigned to + a participant. + + .. note:: + + Pass exactly as many share as they are required, + and no more. + + ssss (bool): + If ``True``, the shares were produced by the ``ssss`` utility + (without using the "diffusion layer"). + Default: ``False``. + + Return: + The original secret, as a byte string (16 bytes long). + """ + + # + # Given k points (x,y), the interpolation polynomial of degree k-1 is: + # + # L(x) = \sum_{j=0}^{k-1} y_i * l_j(x) + # + # where: + # + # l_j(x) = \prod_{ \overset{0 \le m \le k-1}{m \ne j} } + # \frac{x - x_m}{x_j - x_m} + # + # However, in this case we are purely interested in the constant + # coefficient of L(x). + # + + k = len(shares) + + gf_shares = [] + for x in shares: + idx = _Element(x[0]) + value = _Element(x[1]) + if any(y[0] == idx for y in gf_shares): + raise ValueError("Duplicate share") + if ssss: + value += idx**k + gf_shares.append((idx, value)) + + result = _Element(0) + for j in range(k): + x_j, y_j = gf_shares[j] + + numerator = _Element(1) + denominator = _Element(1) + + for m in range(k): + x_m = gf_shares[m][0] + if m != j: + numerator *= x_m + denominator *= x_j + x_m + result += y_j * numerator * denominator.inverse() + + return result.encode() diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/SecretSharing.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/SecretSharing.pyi index 5952c993..ff200854 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/SecretSharing.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/SecretSharing.pyi @@ -1,22 +1,21 @@ from typing import Union, List, Tuple, Optional -def _mult_gf2(f1: int, f2: int) -> int : ... -def _div_gf2(a: int, b: int) -> int : ... +def _mult_gf2(f1: int, f2: int) -> int: ... +def _div_gf2(a: int, b: int) -> int: ... class _Element(object): - irr_poly: int - def __init__(self, encoded_value: Union[int, bytes]) -> None: ... - def __eq__(self, other) -> bool: ... - def __int__(self) -> int: ... - def encode(self) -> bytes: ... - def __mul__(self, factor: int) -> _Element: ... - def __add__(self, term: _Element) -> _Element: ... - def inverse(self) -> _Element: ... - def __pow__(self, exponent) -> _Element: ... + irr_poly: int + def __init__(self, encoded_value: Union[int, bytes]) -> None: ... + def __eq__(self, other) -> bool: ... + def __int__(self) -> int: ... + def encode(self) -> bytes: ... + def __mul__(self, factor: int) -> _Element: ... + def __add__(self, term: _Element) -> _Element: ... + def inverse(self) -> _Element: ... + def __pow__(self, exponent) -> _Element: ... class Shamir(object): - @staticmethod - def split(k: int, n: int, secret: bytes, ssss: Optional[bool]) -> List[Tuple[int, bytes]]: ... - @staticmethod - def combine(shares: List[Tuple[int, bytes]], ssss: Optional[bool]) -> bytes: ... - + @staticmethod + def split(k: int, n: int, secret: bytes, ssss: Optional[bool]) -> List[Tuple[int, bytes]]: ... + @staticmethod + def combine(shares: List[Tuple[int, bytes]], ssss: Optional[bool]) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/__init__.py index 76e22bf6..7d0721dc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/__init__.py @@ -28,4 +28,4 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = ['KDF', 'SecretSharing', 'DH'] +__all__ = ["KDF", "SecretSharing", "DH"] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/__init__.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/__init__.pyi index 377ed901..4e66b321 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/__init__.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Protocol/__init__.pyi @@ -1 +1 @@ -__all__ = ['KDF.pyi', 'SecretSharing.pyi'] +__all__ = ["KDF.pyi", "SecretSharing.pyi"] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/DSA.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/DSA.py index dddd304b..d0994e48 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/DSA.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/DSA.py @@ -22,7 +22,7 @@ # SOFTWARE. # =================================================================== -__all__ = ['generate', 'construct', 'DsaKey', 'import_key' ] +__all__ = ["generate", "construct", "DsaKey", "import_key"] import binascii import struct @@ -34,18 +34,22 @@ from Cryptodome.IO import PKCS8, PEM from Cryptodome.Hash import SHA256 from Cryptodome.Util.asn1 import ( - DerObject, DerSequence, - DerInteger, DerObjectId, - DerBitString, - ) + DerSequence, + DerInteger, +) from Cryptodome.Math.Numbers import Integer -from Cryptodome.Math.Primality import (test_probable_prime, COMPOSITE, - PROBABLY_PRIME) - -from Cryptodome.PublicKey import (_expand_subject_public_key_info, - _create_subject_public_key_info, - _extract_subject_public_key_info) +from Cryptodome.Math.Primality import ( + test_probable_prime, + COMPOSITE, + PROBABLY_PRIME, +) + +from Cryptodome.PublicKey import ( + _expand_subject_public_key_info, + _create_subject_public_key_info, + _extract_subject_public_key_info, +) # ; The following ASN.1 types are relevant for DSA # @@ -75,464 +79,489 @@ # } # + class DsaKey(object): - r"""Class defining an actual DSA key. - Do not instantiate directly. - Use :func:`generate`, :func:`construct` or :func:`import_key` instead. - - :ivar p: DSA modulus - :vartype p: integer + r"""Class defining an actual DSA key. + Do not instantiate directly. + Use :func:`generate`, :func:`construct` or :func:`import_key` instead. + + :ivar p: DSA modulus + :vartype p: integer + + :ivar q: Order of the subgroup + :vartype q: integer - :ivar q: Order of the subgroup - :vartype q: integer + :ivar g: Generator + :vartype g: integer + + :ivar y: Public key + :vartype y: integer - :ivar g: Generator - :vartype g: integer + :ivar x: Private key + :vartype x: integer - :ivar y: Public key - :vartype y: integer - - :ivar x: Private key - :vartype x: integer - - :undocumented: exportKey, publickey - """ - - _keydata = ['y', 'g', 'p', 'q', 'x'] - - def __init__(self, key_dict): - input_set = set(key_dict.keys()) - public_set = set(('y' , 'g', 'p', 'q')) - if not public_set.issubset(input_set): - raise ValueError("Some DSA components are missing = %s" % - str(public_set - input_set)) - extra_set = input_set - public_set - if extra_set and extra_set != set(('x',)): - raise ValueError("Unknown DSA components = %s" % - str(extra_set - set(('x',)))) - self._key = dict(key_dict) - - def _sign(self, m, k): - if not self.has_private(): - raise TypeError("DSA public key cannot be used for signing") - if not (1 < k < self.q): - raise ValueError("k is not between 2 and q-1") - - x, q, p, g = [self._key[comp] for comp in ['x', 'q', 'p', 'g']] - - blind_factor = Integer.random_range(min_inclusive=1, - max_exclusive=q) - inv_blind_k = (blind_factor * k).inverse(q) - blind_x = x * blind_factor - - r = pow(g, k, p) % q # r = (g**k mod p) mod q - s = (inv_blind_k * (blind_factor * m + blind_x * r)) % q - return map(int, (r, s)) - - def _verify(self, m, sig): - r, s = sig - y, q, p, g = [self._key[comp] for comp in ['y', 'q', 'p', 'g']] - if not (0 < r < q) or not (0 < s < q): - return False - w = Integer(s).inverse(q) - u1 = (w * m) % q - u2 = (w * r) % q - v = (pow(g, u1, p) * pow(y, u2, p) % p) % q - return v == r - - def has_private(self): - """Whether this is a DSA private key""" - - return 'x' in self._key - - def can_encrypt(self): # legacy - return False - - def can_sign(self): # legacy - return True - - def public_key(self): - """A matching DSA public key. - - Returns: - a new :class:`DsaKey` object - """ - - public_components = dict((k, self._key[k]) for k in ('y', 'g', 'p', 'q')) - return DsaKey(public_components) - - def __eq__(self, other): - if bool(self.has_private()) != bool(other.has_private()): - return False - - result = True - for comp in self._keydata: - result = result and (getattr(self._key, comp, None) == - getattr(other._key, comp, None)) - return result - - def __ne__(self, other): - return not self.__eq__(other) - - def __getstate__(self): - # DSA key is not pickable - from pickle import PicklingError - raise PicklingError - - def domain(self): - """The DSA domain parameters. - - Returns - tuple : (p,q,g) - """ - - return [int(self._key[comp]) for comp in ('p', 'q', 'g')] - - def __repr__(self): - attrs = [] - for k in self._keydata: - if k == 'p': - bits = Integer(self.p).size_in_bits() - attrs.append("p(%d)" % (bits,)) - elif hasattr(self, k): - attrs.append(k) - if self.has_private(): - attrs.append("private") - # PY3K: This is meant to be text, do not change to bytes (data) - return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs)) - - def __getattr__(self, item): - try: - return int(self._key[item]) - except KeyError: - raise AttributeError(item) - - def export_key(self, format='PEM', pkcs8=None, passphrase=None, - protection=None, randfunc=None): - """Export this DSA key. - - Args: - format (string): - The encoding for the output: - - - *'PEM'* (default). ASCII as per `RFC1421`_/ `RFC1423`_. - - *'DER'*. Binary ASN.1 encoding. - - *'OpenSSH'*. ASCII one-liner as per `RFC4253`_. - Only suitable for public keys, not for private keys. - - passphrase (string): - *Private keys only*. The pass phrase to protect the output. - - pkcs8 (boolean): - *Private keys only*. If ``True`` (default), the key is encoded - with `PKCS#8`_. If ``False``, it is encoded in the custom - OpenSSL/OpenSSH container. - - protection (string): - *Only in combination with a pass phrase*. - The encryption scheme to use to protect the output. - - If :data:`pkcs8` takes value ``True``, this is the PKCS#8 - algorithm to use for deriving the secret and encrypting - the private DSA key. - For a complete list of algorithms, see :mod:`Cryptodome.IO.PKCS8`. - The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*. - - If :data:`pkcs8` is ``False``, the obsolete PEM encryption scheme is - used. It is based on MD5 for key derivation, and Triple DES for - encryption. Parameter :data:`protection` is then ignored. - - The combination ``format='DER'`` and ``pkcs8=False`` is not allowed - if a passphrase is present. - - randfunc (callable): - A function that returns random bytes. - By default it is :func:`Cryptodome.Random.get_random_bytes`. - - Returns: - byte string : the encoded key - - Raises: - ValueError : when the format is unknown or when you try to encrypt a private - key with *DER* format and OpenSSL/OpenSSH. - - .. warning:: - If you don't provide a pass phrase, the private key will be - exported in the clear! - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - """ - - if passphrase is not None: - passphrase = tobytes(passphrase) - - if randfunc is None: - randfunc = Random.get_random_bytes - - if format == 'OpenSSH': - tup1 = [self._key[x].to_bytes() for x in ('p', 'q', 'g', 'y')] - - def func(x): - if (bord(x[0]) & 0x80): - return bchr(0) + x - else: - return x - - tup2 = [func(x) for x in tup1] - keyparts = [b'ssh-dss'] + tup2 - keystring = b''.join( - [struct.pack(">I", len(kp)) + kp for kp in keyparts] - ) - return b'ssh-dss ' + binascii.b2a_base64(keystring)[:-1] - - # DER format is always used, even in case of PEM, which simply - # encodes it into BASE64. - params = DerSequence([self.p, self.q, self.g]) - if self.has_private(): - if pkcs8 is None: - pkcs8 = True - if pkcs8: - if not protection: - protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' - private_key = DerInteger(self.x).encode() - binary_key = PKCS8.wrap( - private_key, oid, passphrase, - protection, key_params=params, - randfunc=randfunc - ) - if passphrase: - key_type = 'ENCRYPTED PRIVATE' - else: - key_type = 'PRIVATE' - passphrase = None - else: - if format != 'PEM' and passphrase: - raise ValueError("DSA private key cannot be encrypted") - ints = [0, self.p, self.q, self.g, self.y, self.x] - binary_key = DerSequence(ints).encode() - key_type = "DSA PRIVATE" - else: - if pkcs8: - raise ValueError("PKCS#8 is only meaningful for private keys") - - binary_key = _create_subject_public_key_info(oid, - DerInteger(self.y), params) - key_type = "PUBLIC" - - if format == 'DER': - return binary_key - if format == 'PEM': - pem_str = PEM.encode( - binary_key, key_type + " KEY", - passphrase, randfunc - ) - return tobytes(pem_str) - raise ValueError("Unknown key format '%s'. Cannot export the DSA key." % format) - - # Backward-compatibility - exportKey = export_key - publickey = public_key - - # Methods defined in PyCryptodome that we don't support anymore - - def sign(self, M, K): - raise NotImplementedError("Use module Cryptodome.Signature.DSS instead") - - def verify(self, M, signature): - raise NotImplementedError("Use module Cryptodome.Signature.DSS instead") - - def encrypt(self, plaintext, K): - raise NotImplementedError - - def decrypt(self, ciphertext): - raise NotImplementedError - - def blind(self, M, B): - raise NotImplementedError - - def unblind(self, M, B): - raise NotImplementedError - - def size(self): - raise NotImplementedError + :undocumented: exportKey, publickey + """ + + _keydata = ["y", "g", "p", "q", "x"] + + def __init__(self, key_dict): + input_set = set(key_dict.keys()) + public_set = set(("y", "g", "p", "q")) + if not public_set.issubset(input_set): + raise ValueError( + "Some DSA components are missing = %s" % str(public_set - input_set), + ) + extra_set = input_set - public_set + if extra_set and extra_set != set(("x",)): + raise ValueError( + "Unknown DSA components = %s" % str(extra_set - set(("x",))), + ) + self._key = dict(key_dict) + + def _sign(self, m, k): + if not self.has_private(): + raise TypeError("DSA public key cannot be used for signing") + if not (1 < k < self.q): + raise ValueError("k is not between 2 and q-1") + + x, q, p, g = [self._key[comp] for comp in ["x", "q", "p", "g"]] + + blind_factor = Integer.random_range( + min_inclusive=1, + max_exclusive=q, + ) + inv_blind_k = (blind_factor * k).inverse(q) + blind_x = x * blind_factor + + r = pow(g, k, p) % q # r = (g**k mod p) mod q + s = (inv_blind_k * (blind_factor * m + blind_x * r)) % q + return map(int, (r, s)) + + def _verify(self, m, sig): + r, s = sig + y, q, p, g = [self._key[comp] for comp in ["y", "q", "p", "g"]] + if not (0 < r < q) or not (0 < s < q): + return False + w = Integer(s).inverse(q) + u1 = (w * m) % q + u2 = (w * r) % q + v = (pow(g, u1, p) * pow(y, u2, p) % p) % q + return v == r + + def has_private(self): + """Whether this is a DSA private key""" + + return "x" in self._key + + def can_encrypt(self): # legacy + return False + + def can_sign(self): # legacy + return True + + def public_key(self): + """A matching DSA public key. + + Returns: + a new :class:`DsaKey` object + """ + + public_components = dict((k, self._key[k]) for k in ("y", "g", "p", "q")) + return DsaKey(public_components) + + def __eq__(self, other): + if bool(self.has_private()) != bool(other.has_private()): + return False + + result = True + for comp in self._keydata: + result = result and (getattr(self._key, comp, None) == getattr(other._key, comp, None)) + return result + + def __ne__(self, other): + return not self.__eq__(other) + + def __getstate__(self): + # DSA key is not pickable + from pickle import PicklingError + + raise PicklingError + + def domain(self): + """The DSA domain parameters. + + Returns + tuple : (p,q,g) + """ + + return [int(self._key[comp]) for comp in ("p", "q", "g")] + + def __repr__(self): + attrs = [] + for k in self._keydata: + if k == "p": + bits = Integer(self.p).size_in_bits() + attrs.append("p(%d)" % (bits,)) + elif hasattr(self, k): + attrs.append(k) + if self.has_private(): + attrs.append("private") + # PY3K: This is meant to be text, do not change to bytes (data) + return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs)) + + def __getattr__(self, item): + try: + return int(self._key[item]) + except KeyError: + raise AttributeError(item) + + def export_key( + self, + format="PEM", + pkcs8=None, + passphrase=None, + protection=None, + randfunc=None, + ): + """Export this DSA key. + + Args: + format (string): + The encoding for the output: + + - *'PEM'* (default). ASCII as per `RFC1421`_/ `RFC1423`_. + - *'DER'*. Binary ASN.1 encoding. + - *'OpenSSH'*. ASCII one-liner as per `RFC4253`_. + Only suitable for public keys, not for private keys. + + passphrase (string): + *Private keys only*. The pass phrase to protect the output. + + pkcs8 (boolean): + *Private keys only*. If ``True`` (default), the key is encoded + with `PKCS#8`_. If ``False``, it is encoded in the custom + OpenSSL/OpenSSH container. + + protection (string): + *Only in combination with a pass phrase*. + The encryption scheme to use to protect the output. + + If :data:`pkcs8` takes value ``True``, this is the PKCS#8 + algorithm to use for deriving the secret and encrypting + the private DSA key. + For a complete list of algorithms, see :mod:`Cryptodome.IO.PKCS8`. + The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*. + + If :data:`pkcs8` is ``False``, the obsolete PEM encryption scheme is + used. It is based on MD5 for key derivation, and Triple DES for + encryption. Parameter :data:`protection` is then ignored. + + The combination ``format='DER'`` and ``pkcs8=False`` is not allowed + if a passphrase is present. + + randfunc (callable): + A function that returns random bytes. + By default it is :func:`Cryptodome.Random.get_random_bytes`. + + Returns: + byte string : the encoded key + + Raises: + ValueError : when the format is unknown or when you try to encrypt a private + key with *DER* format and OpenSSL/OpenSSH. + + .. warning:: + If you don't provide a pass phrase, the private key will be + exported in the clear! + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt + .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + """ + + if passphrase is not None: + passphrase = tobytes(passphrase) + + if randfunc is None: + randfunc = Random.get_random_bytes + + if format == "OpenSSH": + tup1 = [self._key[x].to_bytes() for x in ("p", "q", "g", "y")] + + def func(x): + if bord(x[0]) & 0x80: + return bchr(0) + x + else: + return x + + tup2 = [func(x) for x in tup1] + keyparts = [b"ssh-dss"] + tup2 + keystring = b"".join( + [struct.pack(">I", len(kp)) + kp for kp in keyparts], + ) + return b"ssh-dss " + binascii.b2a_base64(keystring)[:-1] + + # DER format is always used, even in case of PEM, which simply + # encodes it into BASE64. + params = DerSequence([self.p, self.q, self.g]) + if self.has_private(): + if pkcs8 is None: + pkcs8 = True + if pkcs8: + if not protection: + protection = "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC" + private_key = DerInteger(self.x).encode() + binary_key = PKCS8.wrap( + private_key, + oid, + passphrase, + protection, + key_params=params, + randfunc=randfunc, + ) + if passphrase: + key_type = "ENCRYPTED PRIVATE" + else: + key_type = "PRIVATE" + passphrase = None + else: + if format != "PEM" and passphrase: + raise ValueError("DSA private key cannot be encrypted") + ints = [0, self.p, self.q, self.g, self.y, self.x] + binary_key = DerSequence(ints).encode() + key_type = "DSA PRIVATE" + else: + if pkcs8: + raise ValueError("PKCS#8 is only meaningful for private keys") + + binary_key = _create_subject_public_key_info( + oid, + DerInteger(self.y), + params, + ) + key_type = "PUBLIC" + + if format == "DER": + return binary_key + if format == "PEM": + pem_str = PEM.encode( + binary_key, + key_type + " KEY", + passphrase, + randfunc, + ) + return tobytes(pem_str) + raise ValueError("Unknown key format '%s'. Cannot export the DSA key." % format) + + # Backward-compatibility + exportKey = export_key + publickey = public_key + + # Methods defined in PyCryptodome that we don't support anymore + + def sign(self, M, K): + raise NotImplementedError("Use module Cryptodome.Signature.DSS instead") + + def verify(self, M, signature): + raise NotImplementedError("Use module Cryptodome.Signature.DSS instead") + + def encrypt(self, plaintext, K): + raise NotImplementedError + + def decrypt(self, ciphertext): + raise NotImplementedError + + def blind(self, M, B): + raise NotImplementedError + + def unblind(self, M, B): + raise NotImplementedError + + def size(self): + raise NotImplementedError def _generate_domain(L, randfunc): - """Generate a new set of DSA domain parameters""" - - N = { 1024:160, 2048:224, 3072:256 }.get(L) - if N is None: - raise ValueError("Invalid modulus length (%d)" % L) - - outlen = SHA256.digest_size * 8 - n = (L + outlen - 1) // outlen - 1 # ceil(L/outlen) -1 - b_ = L - 1 - (n * outlen) - - # Generate q (A.1.1.2) - q = Integer(4) - upper_bit = 1 << (N - 1) - while test_probable_prime(q, randfunc) != PROBABLY_PRIME: - seed = randfunc(64) - U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1) - q = U | upper_bit | 1 - - assert(q.size_in_bits() == N) - - # Generate p (A.1.1.2) - offset = 1 - upper_bit = 1 << (L - 1) - while True: - V = [ SHA256.new(seed + Integer(offset + j).to_bytes()).digest() - for j in iter_range(n + 1) ] - V = [ Integer.from_bytes(v) for v in V ] - W = sum([V[i] * (1 << (i * outlen)) for i in iter_range(n)], - (V[n] & ((1 << b_) - 1)) * (1 << (n * outlen))) - - X = Integer(W + upper_bit) # 2^{L-1} < X < 2^{L} - assert(X.size_in_bits() == L) - - c = X % (q * 2) - p = X - (c - 1) # 2q divides (p-1) - if p.size_in_bits() == L and \ - test_probable_prime(p, randfunc) == PROBABLY_PRIME: - break - offset += n + 1 - - # Generate g (A.2.3, index=1) - e = (p - 1) // q - for count in itertools.count(1): - U = seed + b"ggen" + bchr(1) + Integer(count).to_bytes() - W = Integer.from_bytes(SHA256.new(U).digest()) - g = pow(W, e, p) - if g != 1: - break - - return (p, q, g, seed) + """Generate a new set of DSA domain parameters""" + + N = {1024: 160, 2048: 224, 3072: 256}.get(L) + if N is None: + raise ValueError("Invalid modulus length (%d)" % L) + + outlen = SHA256.digest_size * 8 + n = (L + outlen - 1) // outlen - 1 # ceil(L/outlen) -1 + b_ = L - 1 - (n * outlen) + + # Generate q (A.1.1.2) + q = Integer(4) + upper_bit = 1 << (N - 1) + while test_probable_prime(q, randfunc) != PROBABLY_PRIME: + seed = randfunc(64) + U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1) + q = U | upper_bit | 1 + + assert q.size_in_bits() == N + + # Generate p (A.1.1.2) + offset = 1 + upper_bit = 1 << (L - 1) + while True: + V = [SHA256.new(seed + Integer(offset + j).to_bytes()).digest() for j in iter_range(n + 1)] + V = [Integer.from_bytes(v) for v in V] + W = sum( + [V[i] * (1 << (i * outlen)) for i in iter_range(n)], + (V[n] & ((1 << b_) - 1)) * (1 << (n * outlen)), + ) + + X = Integer(W + upper_bit) # 2^{L-1} < X < 2^{L} + assert X.size_in_bits() == L + + c = X % (q * 2) + p = X - (c - 1) # 2q divides (p-1) + if p.size_in_bits() == L and test_probable_prime(p, randfunc) == PROBABLY_PRIME: + break + offset += n + 1 + + # Generate g (A.2.3, index=1) + e = (p - 1) // q + for count in itertools.count(1): + U = seed + b"ggen" + bchr(1) + Integer(count).to_bytes() + W = Integer.from_bytes(SHA256.new(U).digest()) + g = pow(W, e, p) + if g != 1: + break + + return (p, q, g, seed) def generate(bits, randfunc=None, domain=None): - """Generate a new DSA key pair. - - The algorithm follows Appendix A.1/A.2 and B.1 of `FIPS 186-4`_, - respectively for domain generation and key pair generation. - - Args: - bits (integer): - Key length, or size (in bits) of the DSA modulus *p*. - It must be 1024, 2048 or 3072. - - randfunc (callable): - Random number generation function; it accepts a single integer N - and return a string of random data N bytes long. - If not specified, :func:`Cryptodome.Random.get_random_bytes` is used. - - domain (tuple): - The DSA domain parameters *p*, *q* and *g* as a list of 3 - integers. Size of *p* and *q* must comply to `FIPS 186-4`_. - If not specified, the parameters are created anew. - - Returns: - :class:`DsaKey` : a new DSA key object - - Raises: - ValueError : when **bits** is too little, too big, or not a multiple of 64. - - .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if randfunc is None: - randfunc = Random.get_random_bytes - - if domain: - p, q, g = map(Integer, domain) - - ## Perform consistency check on domain parameters - # P and Q must be prime - fmt_error = test_probable_prime(p) == COMPOSITE - fmt_error |= test_probable_prime(q) == COMPOSITE - # Verify Lagrange's theorem for sub-group - fmt_error |= ((p - 1) % q) != 0 - fmt_error |= g <= 1 or g >= p - fmt_error |= pow(g, q, p) != 1 - if fmt_error: - raise ValueError("Invalid DSA domain parameters") - else: - p, q, g, _ = _generate_domain(bits, randfunc) - - L = p.size_in_bits() - N = q.size_in_bits() - - if L != bits: - raise ValueError("Mismatch between size of modulus (%d)" - " and 'bits' parameter (%d)" % (L, bits)) - - if (L, N) not in [(1024, 160), (2048, 224), - (2048, 256), (3072, 256)]: - raise ValueError("Lengths of p and q (%d, %d) are not compatible" - "to FIPS 186-3" % (L, N)) - - if not 1 < g < p: - raise ValueError("Incorrent DSA generator") - - # B.1.1 - c = Integer.random(exact_bits=N + 64, randfunc=randfunc) - x = c % (q - 1) + 1 # 1 <= x <= q-1 - y = pow(g, x, p) - - key_dict = { 'y':y, 'g':g, 'p':p, 'q':q, 'x':x } - return DsaKey(key_dict) + """Generate a new DSA key pair. + + The algorithm follows Appendix A.1/A.2 and B.1 of `FIPS 186-4`_, + respectively for domain generation and key pair generation. + + Args: + bits (integer): + Key length, or size (in bits) of the DSA modulus *p*. + It must be 1024, 2048 or 3072. + + randfunc (callable): + Random number generation function; it accepts a single integer N + and return a string of random data N bytes long. + If not specified, :func:`Cryptodome.Random.get_random_bytes` is used. + + domain (tuple): + The DSA domain parameters *p*, *q* and *g* as a list of 3 + integers. Size of *p* and *q* must comply to `FIPS 186-4`_. + If not specified, the parameters are created anew. + + Returns: + :class:`DsaKey` : a new DSA key object + + Raises: + ValueError : when **bits** is too little, too big, or not a multiple of 64. + + .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ + + if randfunc is None: + randfunc = Random.get_random_bytes + + if domain: + p, q, g = map(Integer, domain) + + ## Perform consistency check on domain parameters + # P and Q must be prime + fmt_error = test_probable_prime(p) == COMPOSITE + fmt_error |= test_probable_prime(q) == COMPOSITE + # Verify Lagrange's theorem for sub-group + fmt_error |= ((p - 1) % q) != 0 + fmt_error |= g <= 1 or g >= p + fmt_error |= pow(g, q, p) != 1 + if fmt_error: + raise ValueError("Invalid DSA domain parameters") + else: + p, q, g, _ = _generate_domain(bits, randfunc) + + L = p.size_in_bits() + N = q.size_in_bits() + + if L != bits: + raise ValueError( + "Mismatch between size of modulus (%d) and 'bits' parameter (%d)" % (L, bits), + ) + + if (L, N) not in [ + (1024, 160), + (2048, 224), + (2048, 256), + (3072, 256), + ]: + raise ValueError( + "Lengths of p and q (%d, %d) are not compatibleto FIPS 186-3" % (L, N), + ) + + if not 1 < g < p: + raise ValueError("Incorrent DSA generator") + + # B.1.1 + c = Integer.random(exact_bits=N + 64, randfunc=randfunc) + x = c % (q - 1) + 1 # 1 <= x <= q-1 + y = pow(g, x, p) + + key_dict = {"y": y, "g": g, "p": p, "q": q, "x": x} + return DsaKey(key_dict) def construct(tup, consistency_check=True): - """Construct a DSA key from a tuple of valid DSA components. - - Args: - tup (tuple): - A tuple of long integers, with 4 or 5 items - in the following order: - - 1. Public key (*y*). - 2. Sub-group generator (*g*). - 3. Modulus, finite field order (*p*). - 4. Sub-group order (*q*). - 5. Private key (*x*). Optional. - - consistency_check (boolean): - If ``True``, the library will verify that the provided components - fulfil the main DSA properties. - - Raises: - ValueError: when the key being imported fails the most basic DSA validity checks. - - Returns: - :class:`DsaKey` : a DSA key object - """ - - key_dict = dict(zip(('y', 'g', 'p', 'q', 'x'), map(Integer, tup))) - key = DsaKey(key_dict) - - fmt_error = False - if consistency_check: - # P and Q must be prime - fmt_error = test_probable_prime(key.p) == COMPOSITE - fmt_error |= test_probable_prime(key.q) == COMPOSITE - # Verify Lagrange's theorem for sub-group - fmt_error |= ((key.p - 1) % key.q) != 0 - fmt_error |= key.g <= 1 or key.g >= key.p - fmt_error |= pow(key.g, key.q, key.p) != 1 - # Public key - fmt_error |= key.y <= 0 or key.y >= key.p - if hasattr(key, 'x'): - fmt_error |= key.x <= 0 or key.x >= key.q - fmt_error |= pow(key.g, key.x, key.p) != key.y - - if fmt_error: - raise ValueError("Invalid DSA key components") - - return key + """Construct a DSA key from a tuple of valid DSA components. + + Args: + tup (tuple): + A tuple of long integers, with 4 or 5 items + in the following order: + + 1. Public key (*y*). + 2. Sub-group generator (*g*). + 3. Modulus, finite field order (*p*). + 4. Sub-group order (*q*). + 5. Private key (*x*). Optional. + + consistency_check (boolean): + If ``True``, the library will verify that the provided components + fulfil the main DSA properties. + + Raises: + ValueError: when the key being imported fails the most basic DSA validity checks. + + Returns: + :class:`DsaKey` : a DSA key object + """ + + key_dict = dict(zip(("y", "g", "p", "q", "x"), map(Integer, tup))) + key = DsaKey(key_dict) + + fmt_error = False + if consistency_check: + # P and Q must be prime + fmt_error = test_probable_prime(key.p) == COMPOSITE + fmt_error |= test_probable_prime(key.q) == COMPOSITE + # Verify Lagrange's theorem for sub-group + fmt_error |= ((key.p - 1) % key.q) != 0 + fmt_error |= key.g <= 1 or key.g >= key.p + fmt_error |= pow(key.g, key.q, key.p) != 1 + # Public key + fmt_error |= key.y <= 0 or key.y >= key.p + if hasattr(key, "x"): + fmt_error |= key.x <= 0 or key.x >= key.q + fmt_error |= pow(key.g, key.x, key.p) != key.y + + if fmt_error: + raise ValueError("Invalid DSA key components") + + return key # Dss-Parms ::= SEQUENCE { @@ -542,133 +571,134 @@ def construct(tup, consistency_check=True): # } # DSAPublicKey ::= INTEGER -- public key, y + def _import_openssl_private(encoded, passphrase, params): - if params: - raise ValueError("DSA private key already comes with parameters") - der = DerSequence().decode(encoded, nr_elements=6, only_ints_expected=True) - if der[0] != 0: - raise ValueError("No version found") - tup = [der[comp] for comp in (4, 3, 1, 2, 5)] - return construct(tup) + if params: + raise ValueError("DSA private key already comes with parameters") + der = DerSequence().decode(encoded, nr_elements=6, only_ints_expected=True) + if der[0] != 0: + raise ValueError("No version found") + tup = [der[comp] for comp in (4, 3, 1, 2, 5)] + return construct(tup) def _import_subjectPublicKeyInfo(encoded, passphrase, params): + algoid, encoded_key, emb_params = _expand_subject_public_key_info(encoded) + if algoid != oid: + raise ValueError("No DSA subjectPublicKeyInfo") + if params and emb_params: + raise ValueError("Too many DSA parameters") - algoid, encoded_key, emb_params = _expand_subject_public_key_info(encoded) - if algoid != oid: - raise ValueError("No DSA subjectPublicKeyInfo") - if params and emb_params: - raise ValueError("Too many DSA parameters") - - y = DerInteger().decode(encoded_key).value - p, q, g = list(DerSequence().decode(params or emb_params)) - tup = (y, g, p, q) - return construct(tup) + y = DerInteger().decode(encoded_key).value + p, q, g = list(DerSequence().decode(params or emb_params)) + tup = (y, g, p, q) + return construct(tup) def _import_x509_cert(encoded, passphrase, params): - - sp_info = _extract_subject_public_key_info(encoded) - return _import_subjectPublicKeyInfo(sp_info, None, params) + sp_info = _extract_subject_public_key_info(encoded) + return _import_subjectPublicKeyInfo(sp_info, None, params) def _import_pkcs8(encoded, passphrase, params): - if params: - raise ValueError("PKCS#8 already includes parameters") - k = PKCS8.unwrap(encoded, passphrase) - if k[0] != oid: - raise ValueError("No PKCS#8 encoded DSA key") - x = DerInteger().decode(k[1]).value - p, q, g = list(DerSequence().decode(k[2])) - tup = (pow(g, x, p), g, p, q, x) - return construct(tup) + if params: + raise ValueError("PKCS#8 already includes parameters") + k = PKCS8.unwrap(encoded, passphrase) + if k[0] != oid: + raise ValueError("No PKCS#8 encoded DSA key") + x = DerInteger().decode(k[1]).value + p, q, g = list(DerSequence().decode(k[2])) + tup = (pow(g, x, p), g, p, q, x) + return construct(tup) def _import_key_der(key_data, passphrase, params): - """Import a DSA key (public or private half), encoded in DER form.""" + """Import a DSA key (public or private half), encoded in DER form.""" - decodings = (_import_openssl_private, - _import_subjectPublicKeyInfo, - _import_x509_cert, - _import_pkcs8) + decodings = ( + _import_openssl_private, + _import_subjectPublicKeyInfo, + _import_x509_cert, + _import_pkcs8, + ) - for decoding in decodings: - try: - return decoding(key_data, passphrase, params) - except ValueError: - pass + for decoding in decodings: + try: + return decoding(key_data, passphrase, params) + except ValueError: + pass - raise ValueError("DSA key format is not supported") + raise ValueError("DSA key format is not supported") def import_key(extern_key, passphrase=None): - """Import a DSA key. + """Import a DSA key. - Args: - extern_key (string or byte string): - The DSA key to import. + Args: + extern_key (string or byte string): + The DSA key to import. - The following formats are supported for a DSA **public** key: + The following formats are supported for a DSA **public** key: - - X.509 certificate (binary DER or PEM) - - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM) - - OpenSSH (ASCII one-liner, see `RFC4253`_) + - X.509 certificate (binary DER or PEM) + - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM) + - OpenSSH (ASCII one-liner, see `RFC4253`_) - The following formats are supported for a DSA **private** key: + The following formats are supported for a DSA **private** key: - - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` - DER SEQUENCE (binary or PEM) - - OpenSSL/OpenSSH custom format (binary or PEM) + - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` + DER SEQUENCE (binary or PEM) + - OpenSSL/OpenSSH custom format (binary or PEM) - For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. + For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. - passphrase (string): - In case of an encrypted private key, this is the pass phrase - from which the decryption key is derived. + passphrase (string): + In case of an encrypted private key, this is the pass phrase + from which the decryption key is derived. - Encryption may be applied either at the `PKCS#8`_ or at the PEM level. + Encryption may be applied either at the `PKCS#8`_ or at the PEM level. - Returns: - :class:`DsaKey` : a DSA key object + Returns: + :class:`DsaKey` : a DSA key object - Raises: - ValueError : when the given key cannot be parsed (possibly because - the pass phrase is wrong). + Raises: + ValueError : when the given key cannot be parsed (possibly because + the pass phrase is wrong). - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt - .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt - """ + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt + .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt + """ - extern_key = tobytes(extern_key) - if passphrase is not None: - passphrase = tobytes(passphrase) + extern_key = tobytes(extern_key) + if passphrase is not None: + passphrase = tobytes(passphrase) - if extern_key.startswith(b'-----'): - # This is probably a PEM encoded key - (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) - if enc_flag: - passphrase = None - return _import_key_der(der, passphrase, None) + if extern_key.startswith(b"-----"): + # This is probably a PEM encoded key + (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) + if enc_flag: + passphrase = None + return _import_key_der(der, passphrase, None) - if extern_key.startswith(b'ssh-dss '): - # This is probably a public OpenSSH key - keystring = binascii.a2b_base64(extern_key.split(b' ')[1]) - keyparts = [] - while len(keystring) > 4: - length = struct.unpack(">I", keystring[:4])[0] - keyparts.append(keystring[4:4 + length]) - keystring = keystring[4 + length:] - if keyparts[0] == b"ssh-dss": - tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)] - return construct(tup) + if extern_key.startswith(b"ssh-dss "): + # This is probably a public OpenSSH key + keystring = binascii.a2b_base64(extern_key.split(b" ")[1]) + keyparts = [] + while len(keystring) > 4: + length = struct.unpack(">I", keystring[:4])[0] + keyparts.append(keystring[4 : 4 + length]) + keystring = keystring[4 + length :] + if keyparts[0] == b"ssh-dss": + tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)] + return construct(tup) - if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: - # This is probably a DER encoded key - return _import_key_der(extern_key, passphrase, None) + if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: + # This is probably a DER encoded key + return _import_key_der(extern_key, passphrase, None) - raise ValueError("DSA key format is not supported") + raise ValueError("DSA key format is not supported") # Backward compatibility diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/DSA.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/DSA.pyi index 354ac1f0..92db8596 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/DSA.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/DSA.pyi @@ -1,30 +1,42 @@ from typing import Dict, Tuple, Callable, Union, Optional -__all__ = ['generate', 'construct', 'DsaKey', 'import_key' ] +__all__ = ["generate", "construct", "DsaKey", "import_key"] RNG = Callable[[int], bytes] class DsaKey(object): - def __init__(self, key_dict: Dict[str, int]) -> None: ... - def has_private(self) -> bool: ... - def can_encrypt(self) -> bool: ... # legacy - def can_sign(self) -> bool: ... # legacy - def public_key(self) -> DsaKey: ... - def __eq__(self, other: object) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __getstate__(self) -> None: ... - def domain(self) -> Tuple[int, int, int]: ... - def __repr__(self) -> str: ... - def __getattr__(self, item: str) -> int: ... - def export_key(self, format: Optional[str]="PEM", pkcs8: Optional[bool]=None, passphrase: Optional[str]=None, - protection: Optional[str]=None, randfunc: Optional[RNG]=None) -> bytes: ... - # Backward-compatibility - exportKey = export_key - publickey = public_key + def __init__(self, key_dict: Dict[str, int]) -> None: ... + def has_private(self) -> bool: ... + def can_encrypt(self) -> bool: ... # legacy + def can_sign(self) -> bool: ... # legacy + def public_key(self) -> DsaKey: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def __getstate__(self) -> None: ... + def domain(self) -> Tuple[int, int, int]: ... + def __repr__(self) -> str: ... + def __getattr__(self, item: str) -> int: ... + def export_key( + self, + format: Optional[str] = "PEM", + pkcs8: Optional[bool] = None, + passphrase: Optional[str] = None, + protection: Optional[str] = None, + randfunc: Optional[RNG] = None, + ) -> bytes: ... + # Backward-compatibility + exportKey = export_key + publickey = public_key + +def generate( + bits: int, randfunc: Optional[RNG] = None, domain: Optional[Tuple[int, int, int]] = None +) -> DsaKey: ... +def construct( + tup: Union[Tuple[int, int, int, int], Tuple[int, int, int, int, int]], + consistency_check: Optional[bool] = True, +) -> DsaKey: ... +def import_key(extern_key: Union[str, bytes], passphrase: Optional[str] = None) -> DsaKey: ... -def generate(bits: int, randfunc: Optional[RNG]=None, domain: Optional[Tuple[int, int, int]]=None) -> DsaKey: ... -def construct(tup: Union[Tuple[int, int, int, int], Tuple[int, int, int, int, int]], consistency_check: Optional[bool]=True) -> DsaKey: ... -def import_key(extern_key: Union[str, bytes], passphrase: Optional[str]=None) -> DsaKey: ... # Backward compatibility importKey = import_key diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ECC.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ECC.py index bd9c8cb8..48dd9ff4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ECC.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ECC.py @@ -37,12 +37,18 @@ from Cryptodome.Util.py3compat import bord, tobytes, tostr, bchr, is_string from Cryptodome.Math.Numbers import Integer -from Cryptodome.Util.asn1 import (DerObjectId, DerOctetString, DerSequence, - DerBitString) - -from Cryptodome.PublicKey import (_expand_subject_public_key_info, - _create_subject_public_key_info, - _extract_subject_public_key_info) +from Cryptodome.Util.asn1 import ( + DerObjectId, + DerOctetString, + DerSequence, + DerBitString, +) + +from Cryptodome.PublicKey import ( + _expand_subject_public_key_info, + _create_subject_public_key_info, + _extract_subject_public_key_info, +) from Cryptodome.Hash import SHA512, SHAKE256 @@ -53,1290 +59,1294 @@ class UnsupportedEccFeature(ValueError): - pass + pass class EccKey(object): - r"""Class defining an ECC key. - Do not instantiate directly. - Use :func:`generate`, :func:`construct` or :func:`import_key` instead. - - :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. - :vartype curve: string - - :ivar pointQ: an ECC point representing the public component. - :vartype pointQ: :class:`EccPoint` or :class:`EccXPoint` - - :ivar d: A scalar that represents the private component - in NIST P curves. It is smaller than the - order of the generator point. - :vartype d: integer - - :ivar seed: A seed that represents the private component - in Ed22519 (32 bytes), Curve25519 (32 bytes), - Curve448 (56 bytes), Ed448 (57 bytes). - :vartype seed: bytes - """ - - def __init__(self, **kwargs): - """Create a new ECC key - - Keywords: - curve : string - The name of the curve. - d : integer - Mandatory for a private key one NIST P curves. - It must be in the range ``[1..order-1]``. - seed : bytes - Mandatory for a private key on Ed25519 (32 bytes), - Curve25519 (32 bytes), Curve448 (56 bytes) or Ed448 (57 bytes). - point : EccPoint or EccXPoint - Mandatory for a public key. If provided for a private key, - the implementation will NOT check whether it matches ``d``. - - Only one parameter among ``d``, ``seed`` or ``point`` may be used. - """ - - kwargs_ = dict(kwargs) - curve_name = kwargs_.pop("curve", None) - self._d = kwargs_.pop("d", None) - self._seed = kwargs_.pop("seed", None) - self._point = kwargs_.pop("point", None) - if curve_name is None and self._point: - curve_name = self._point.curve - if kwargs_: - raise TypeError("Unknown parameters: " + str(kwargs_)) - - if curve_name not in _curves: - raise ValueError("Unsupported curve (%s)" % curve_name) - self._curve = _curves[curve_name] - self.curve = self._curve.canonical - - count = int(self._d is not None) + int(self._seed is not None) - - if count == 0: - if self._point is None: - raise ValueError("At lest one between parameters 'point', 'd' or 'seed' must be specified") - return - - if count == 2: - raise ValueError("Parameters d and seed are mutually exclusive") - - # NIST P curves work with d, EdDSA works with seed - - # RFC 8032, 5.1.5 - if self._curve.id == _CurveID.ED25519: - if self._d is not None: - raise ValueError("Parameter d can only be used with NIST P curves") - if len(self._seed) != 32: - raise ValueError("Parameter seed must be 32 bytes long for Ed25519") - seed_hash = SHA512.new(self._seed).digest() # h - self._prefix = seed_hash[32:] - tmp = bytearray(seed_hash[:32]) - tmp[0] &= 0xF8 - tmp[31] = (tmp[31] & 0x7F) | 0x40 - self._d = Integer.from_bytes(tmp, byteorder='little') - # RFC 8032, 5.2.5 - elif self._curve.id == _CurveID.ED448: - if self._d is not None: - raise ValueError("Parameter d can only be used with NIST P curves") - if len(self._seed) != 57: - raise ValueError("Parameter seed must be 57 bytes long for Ed448") - seed_hash = SHAKE256.new(self._seed).read(114) # h - self._prefix = seed_hash[57:] - tmp = bytearray(seed_hash[:57]) - tmp[0] &= 0xFC - tmp[55] |= 0x80 - tmp[56] = 0 - self._d = Integer.from_bytes(tmp, byteorder='little') - # RFC 7748, 5 - elif self._curve.id == _CurveID.CURVE25519: - if self._d is not None: - raise ValueError("Parameter d can only be used with NIST P curves") - if len(self._seed) != 32: - raise ValueError("Parameter seed must be 32 bytes long for Curve25519") - tmp = bytearray(self._seed) - tmp[0] &= 0xF8 - tmp[31] = (tmp[31] & 0x7F) | 0x40 - self._d = Integer.from_bytes(tmp, byteorder='little') - elif self._curve.id == _CurveID.CURVE448: - if self._d is not None: - raise ValueError("Parameter d can only be used with NIST P curves") - if len(self._seed) != 56: - raise ValueError("Parameter seed must be 56 bytes long for Curve448") - tmp = bytearray(self._seed) - tmp[0] &= 0xFC - tmp[55] |= 0x80 - self._d = Integer.from_bytes(tmp, byteorder='little') - - else: - if self._seed is not None: - raise ValueError("Parameter 'seed' cannot be used with NIST P-curves") - self._d = Integer(self._d) - if not 1 <= self._d < self._curve.order: - raise ValueError("Parameter d must be an integer smaller than the curve order") - - def __eq__(self, other): - if not isinstance(other, EccKey): - return False - - if other.has_private() != self.has_private(): - return False - - return other.pointQ == self.pointQ - - def __repr__(self): - if self.has_private(): - if self._curve.is_edwards: - extra = ", seed=%s" % tostr(binascii.hexlify(self._seed)) - else: - extra = ", d=%d" % int(self._d) - else: - extra = "" - if self._curve.id in (_CurveID.CURVE25519, - _CurveID.CURVE448): - x = self.pointQ.x - result = "EccKey(curve='%s', point_x=%d%s)" % (self._curve.canonical, x, extra) - else: - x, y = self.pointQ.xy - result = "EccKey(curve='%s', point_x=%d, point_y=%d%s)" % (self._curve.canonical, x, y, extra) - return result - - def has_private(self): - """``True`` if this key can be used for making signatures or decrypting data.""" - - return self._d is not None - - # ECDSA - def _sign(self, z, k): - assert 0 < k < self._curve.order - - order = self._curve.order - blind = Integer.random_range(min_inclusive=1, - max_exclusive=order) - - blind_d = self._d * blind - inv_blind_k = (blind * k).inverse(order) - - r = (self._curve.G * k).x % order - s = inv_blind_k * (blind * z + blind_d * r) % order - return (r, s) - - # ECDSA - def _verify(self, z, rs): - order = self._curve.order - sinv = rs[1].inverse(order) - point1 = self._curve.G * ((sinv * z) % order) - point2 = self.pointQ * ((sinv * rs[0]) % order) - return (point1 + point2).x == rs[0] - - @property - def d(self): - if not self.has_private(): - raise ValueError("This is not a private ECC key") - return self._d - - @property - def seed(self): - if not self.has_private(): - raise ValueError("This is not a private ECC key") - return self._seed - - @property - def pointQ(self): - if self._point is None: - self._point = self._curve.G * self._d - return self._point - - def public_key(self): - """A matching ECC public key. - - Returns: - a new :class:`EccKey` object - """ - - return EccKey(curve=self._curve.canonical, point=self.pointQ) - - def _export_SEC1(self, compress): - if not self._curve.is_weierstrass: - raise ValueError("SEC1 format is only supported for NIST P curves") - - # See 2.2 in RFC5480 and 2.3.3 in SEC1 - # - # The first byte is: - # - 0x02: compressed, only X-coordinate, Y-coordinate is even - # - 0x03: compressed, only X-coordinate, Y-coordinate is odd - # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate - # - # PAI is in theory encoded as 0x00. - - modulus_bytes = self.pointQ.size_in_bytes() - - if compress: - if self.pointQ.y.is_odd(): - first_byte = b'\x03' - else: - first_byte = b'\x02' - public_key = (first_byte + - self.pointQ.x.to_bytes(modulus_bytes)) - else: - public_key = (b'\x04' + - self.pointQ.x.to_bytes(modulus_bytes) + - self.pointQ.y.to_bytes(modulus_bytes)) - return public_key - - def _export_eddsa_public(self): - x, y = self.pointQ.xy - if self._curve.id == _CurveID.ED25519: - result = bytearray(y.to_bytes(32, byteorder='little')) - result[31] = ((x & 1) << 7) | result[31] - elif self._curve.id == _CurveID.ED448: - result = bytearray(y.to_bytes(57, byteorder='little')) - result[56] = (x & 1) << 7 - else: - raise ValueError("Not an EdDSA key to export") - return bytes(result) - - def _export_montgomery_public(self): - if not self._curve.is_montgomery: - raise ValueError("Not a Montgomery key to export") - x = self.pointQ.x - field_size = self.pointQ.size_in_bytes() - result = bytearray(x.to_bytes(field_size, byteorder='little')) - return bytes(result) - - def _export_subjectPublicKeyInfo(self, compress): - if self._curve.is_edwards: - oid = self._curve.oid - public_key = self._export_eddsa_public() - params = None - elif self._curve.is_montgomery: - oid = self._curve.oid - public_key = self._export_montgomery_public() - params = None - else: - oid = "1.2.840.10045.2.1" # unrestricted - public_key = self._export_SEC1(compress) - params = DerObjectId(self._curve.oid) - - return _create_subject_public_key_info(oid, - public_key, - params) - - def _export_rfc5915_private_der(self, include_ec_params=True): - - assert self.has_private() - - # ECPrivateKey ::= SEQUENCE { - # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - # privateKey OCTET STRING, - # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - # publicKey [1] BIT STRING OPTIONAL - # } - - # Public key - uncompressed form - modulus_bytes = self.pointQ.size_in_bytes() - public_key = (b'\x04' + - self.pointQ.x.to_bytes(modulus_bytes) + - self.pointQ.y.to_bytes(modulus_bytes)) - - seq = [1, - DerOctetString(self.d.to_bytes(modulus_bytes)), - DerObjectId(self._curve.oid, explicit=0), - DerBitString(public_key, explicit=1)] - - if not include_ec_params: - del seq[2] - - return DerSequence(seq).encode() - - def _export_pkcs8(self, **kwargs): - from Cryptodome.IO import PKCS8 - - if kwargs.get('passphrase', None) is not None and 'protection' not in kwargs: - raise ValueError("At least the 'protection' parameter must be present") - - if self._seed is not None: - oid = self._curve.oid - private_key = DerOctetString(self._seed).encode() - params = None - else: - oid = "1.2.840.10045.2.1" # unrestricted - private_key = self._export_rfc5915_private_der(include_ec_params=False) - params = DerObjectId(self._curve.oid) - - result = PKCS8.wrap(private_key, - oid, - key_params=params, - **kwargs) - return result - - def _export_public_pem(self, compress): - from Cryptodome.IO import PEM - - encoded_der = self._export_subjectPublicKeyInfo(compress) - return PEM.encode(encoded_der, "PUBLIC KEY") - - def _export_private_pem(self, passphrase, **kwargs): - from Cryptodome.IO import PEM - - encoded_der = self._export_rfc5915_private_der() - return PEM.encode(encoded_der, "EC PRIVATE KEY", passphrase, **kwargs) - - def _export_private_clear_pkcs8_in_clear_pem(self): - from Cryptodome.IO import PEM - - encoded_der = self._export_pkcs8() - return PEM.encode(encoded_der, "PRIVATE KEY") - - def _export_private_encrypted_pkcs8_in_clear_pem(self, passphrase, **kwargs): - from Cryptodome.IO import PEM - - assert passphrase - if 'protection' not in kwargs: - raise ValueError("At least the 'protection' parameter should be present") - encoded_der = self._export_pkcs8(passphrase=passphrase, **kwargs) - return PEM.encode(encoded_der, "ENCRYPTED PRIVATE KEY") - - def _export_openssh(self, compress): - if self.has_private(): - raise ValueError("Cannot export OpenSSH private keys") - - desc = self._curve.openssh - - if desc is None: - raise ValueError("Cannot export %s keys as OpenSSH" % self.curve) - elif desc == "ssh-ed25519": - public_key = self._export_eddsa_public() - comps = (tobytes(desc), tobytes(public_key)) - else: - modulus_bytes = self.pointQ.size_in_bytes() - - if compress: - first_byte = 2 + self.pointQ.y.is_odd() - public_key = (bchr(first_byte) + - self.pointQ.x.to_bytes(modulus_bytes)) - else: - public_key = (b'\x04' + - self.pointQ.x.to_bytes(modulus_bytes) + - self.pointQ.y.to_bytes(modulus_bytes)) - - middle = desc.split("-")[2] - comps = (tobytes(desc), tobytes(middle), public_key) - - blob = b"".join([struct.pack(">I", len(x)) + x for x in comps]) - return desc + " " + tostr(binascii.b2a_base64(blob)) - - def export_key(self, **kwargs): - """Export this ECC key. - - Args: - format (string): - The output format: - - - ``'DER'``. The key will be encoded in ASN.1 DER format (binary). - For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure - defined in `RFC5480`_ will be used. - For a private key, the ASN.1 ``ECPrivateKey`` structure defined - in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope, - see the ``use_pkcs8`` flag below). - - ``'PEM'``. The key will be encoded in a PEM_ envelope (ASCII). - - ``'OpenSSH'``. The key will be encoded in the OpenSSH_ format - (ASCII, public keys only). - - ``'SEC1'``. The public key (i.e., the EC point) will be encoded - into ``bytes`` according to Section 2.3.3 of `SEC1`_ - (which is a subset of the older X9.62 ITU standard). - Only for NIST P-curves. - - ``'raw'``. The public key will be encoded as ``bytes``, - without any metadata. - - * For NIST P-curves: equivalent to ``'SEC1'``. - * For Ed25519 and Ed448: ``bytes`` in the format - defined in `RFC8032`_. - * For Curve25519 and Curve448: ``bytes`` in the format - defined in `RFC7748`_. - - passphrase (bytes or string): - (*Private keys only*) The passphrase to protect the - private key. - - use_pkcs8 (boolean): - (*Private keys only*) - If ``True`` (default and recommended), the `PKCS#8`_ representation - will be used. - It must be ``True`` for Ed25519, Ed448, Curve25519, and Curve448. - - If ``False`` and a passphrase is present, the obsolete PEM - encryption will be used. - - protection (string): - When a private key is exported with password-protection - and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be - present, - For all possible protection schemes, - refer to :ref:`the encryption parameters of PKCS#8`. - It is recommended to use ``'PBKDF2WithHMAC-SHA512AndAES128-CBC'``. - - compress (boolean): - If ``True``, the method returns a more compact representation - of the public key, with the X-coordinate only. - - If ``False`` (default), the method returns the full public key. - - This parameter is ignored for Ed25519/Ed448/Curve25519/Curve448, - as compression is mandatory. - - prot_params (dict): - When a private key is exported with password-protection - and PKCS#8 (both ``DER`` and ``PEM`` formats), this dictionary - contains the parameters to use to derive the encryption key - from the passphrase. - For all possible values, - refer to :ref:`the encryption parameters of PKCS#8`. - The recommendation is to use ``{'iteration_count':21000}`` for PBKDF2, - and ``{'iteration_count':131072}`` for scrypt. - - .. warning:: - If you don't provide a passphrase, the private key will be - exported in the clear! - - .. note:: - When exporting a private key with password-protection and `PKCS#8`_ - (both ``DER`` and ``PEM`` formats), any extra parameters - to ``export_key()`` will be passed to :mod:`Cryptodome.IO.PKCS8`. - - .. _PEM: http://www.ietf.org/rfc/rfc1421.txt - .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt - .. _OpenSSH: http://www.openssh.com/txt/rfc5656.txt - .. _RFC5480: https://tools.ietf.org/html/rfc5480 - .. _SEC1: https://www.secg.org/sec1-v2.pdf - .. _RFC7748: https://tools.ietf.org/html/rfc7748 - - Returns: - A multi-line string (for ``'PEM'`` and ``'OpenSSH'``) or - ``bytes`` (for ``'DER'``, ``'SEC1'``, and ``'raw'``) with the encoded key. - """ - - args = kwargs.copy() - ext_format = args.pop("format") - if ext_format not in ("PEM", "DER", "OpenSSH", "SEC1", "raw"): - raise ValueError("Unknown format '%s'" % ext_format) - - compress = args.pop("compress", False) - - if self.has_private(): - passphrase = args.pop("passphrase", None) - if is_string(passphrase): - passphrase = tobytes(passphrase) - if not passphrase: - raise ValueError("Empty passphrase") - - use_pkcs8 = args.pop("use_pkcs8", True) - if use_pkcs8 is False: - if self._curve.is_edwards: - raise ValueError("'pkcs8' must be True for EdDSA curves") - if self._curve.is_montgomery: - raise ValueError("'pkcs8' must be True for Curve25519") - if 'protection' in args: - raise ValueError("'protection' is only supported for PKCS#8") - - if ext_format == "PEM": - if use_pkcs8: - if passphrase: - return self._export_private_encrypted_pkcs8_in_clear_pem(passphrase, **args) - else: - return self._export_private_clear_pkcs8_in_clear_pem() - else: - return self._export_private_pem(passphrase, **args) - elif ext_format == "DER": - # DER - if passphrase and not use_pkcs8: - raise ValueError("Private keys can only be encrpyted with DER using PKCS#8") - if use_pkcs8: - return self._export_pkcs8(passphrase=passphrase, **args) - else: - return self._export_rfc5915_private_der() - else: - raise ValueError("Private keys cannot be exported " - "in the '%s' format" % ext_format) - else: # Public key - if args: - raise ValueError("Unexpected parameters: '%s'" % args) - if ext_format == "PEM": - return self._export_public_pem(compress) - elif ext_format == "DER": - return self._export_subjectPublicKeyInfo(compress) - elif ext_format == "SEC1": - return self._export_SEC1(compress) - elif ext_format == "raw": - if self._curve.is_edwards: - return self._export_eddsa_public() - elif self._curve.is_montgomery: - return self._export_montgomery_public() - else: - return self._export_SEC1(compress) - else: - return self._export_openssh(compress) + r"""Class defining an ECC key. + Do not instantiate directly. + Use :func:`generate`, :func:`construct` or :func:`import_key` instead. + + :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. + :vartype curve: string + + :ivar pointQ: an ECC point representing the public component. + :vartype pointQ: :class:`EccPoint` or :class:`EccXPoint` + + :ivar d: A scalar that represents the private component + in NIST P curves. It is smaller than the + order of the generator point. + :vartype d: integer + + :ivar seed: A seed that represents the private component + in Ed22519 (32 bytes), Curve25519 (32 bytes), + Curve448 (56 bytes), Ed448 (57 bytes). + :vartype seed: bytes + """ + + def __init__(self, **kwargs): + """Create a new ECC key + + Keywords: + curve : string + The name of the curve. + d : integer + Mandatory for a private key one NIST P curves. + It must be in the range ``[1..order-1]``. + seed : bytes + Mandatory for a private key on Ed25519 (32 bytes), + Curve25519 (32 bytes), Curve448 (56 bytes) or Ed448 (57 bytes). + point : EccPoint or EccXPoint + Mandatory for a public key. If provided for a private key, + the implementation will NOT check whether it matches ``d``. + + Only one parameter among ``d``, ``seed`` or ``point`` may be used. + """ + + kwargs_ = dict(kwargs) + curve_name = kwargs_.pop("curve", None) + self._d = kwargs_.pop("d", None) + self._seed = kwargs_.pop("seed", None) + self._point = kwargs_.pop("point", None) + if curve_name is None and self._point: + curve_name = self._point.curve + if kwargs_: + raise TypeError("Unknown parameters: " + str(kwargs_)) + + if curve_name not in _curves: + raise ValueError("Unsupported curve (%s)" % curve_name) + self._curve = _curves[curve_name] + self.curve = self._curve.canonical + + count = int(self._d is not None) + int(self._seed is not None) + + if count == 0: + if self._point is None: + raise ValueError("At lest one between parameters 'point', 'd' or 'seed' must be specified") + return + + if count == 2: + raise ValueError("Parameters d and seed are mutually exclusive") + + # NIST P curves work with d, EdDSA works with seed + + # RFC 8032, 5.1.5 + if self._curve.id == _CurveID.ED25519: + if self._d is not None: + raise ValueError("Parameter d can only be used with NIST P curves") + if len(self._seed) != 32: + raise ValueError("Parameter seed must be 32 bytes long for Ed25519") + seed_hash = SHA512.new(self._seed).digest() # h + self._prefix = seed_hash[32:] + tmp = bytearray(seed_hash[:32]) + tmp[0] &= 0xF8 + tmp[31] = (tmp[31] & 0x7F) | 0x40 + self._d = Integer.from_bytes(tmp, byteorder="little") + # RFC 8032, 5.2.5 + elif self._curve.id == _CurveID.ED448: + if self._d is not None: + raise ValueError("Parameter d can only be used with NIST P curves") + if len(self._seed) != 57: + raise ValueError("Parameter seed must be 57 bytes long for Ed448") + seed_hash = SHAKE256.new(self._seed).read(114) # h + self._prefix = seed_hash[57:] + tmp = bytearray(seed_hash[:57]) + tmp[0] &= 0xFC + tmp[55] |= 0x80 + tmp[56] = 0 + self._d = Integer.from_bytes(tmp, byteorder="little") + # RFC 7748, 5 + elif self._curve.id == _CurveID.CURVE25519: + if self._d is not None: + raise ValueError("Parameter d can only be used with NIST P curves") + if len(self._seed) != 32: + raise ValueError("Parameter seed must be 32 bytes long for Curve25519") + tmp = bytearray(self._seed) + tmp[0] &= 0xF8 + tmp[31] = (tmp[31] & 0x7F) | 0x40 + self._d = Integer.from_bytes(tmp, byteorder="little") + elif self._curve.id == _CurveID.CURVE448: + if self._d is not None: + raise ValueError("Parameter d can only be used with NIST P curves") + if len(self._seed) != 56: + raise ValueError("Parameter seed must be 56 bytes long for Curve448") + tmp = bytearray(self._seed) + tmp[0] &= 0xFC + tmp[55] |= 0x80 + self._d = Integer.from_bytes(tmp, byteorder="little") + + else: + if self._seed is not None: + raise ValueError("Parameter 'seed' cannot be used with NIST P-curves") + self._d = Integer(self._d) + if not 1 <= self._d < self._curve.order: + raise ValueError("Parameter d must be an integer smaller than the curve order") + + def __eq__(self, other): + if not isinstance(other, EccKey): + return False + + if other.has_private() != self.has_private(): + return False + + return other.pointQ == self.pointQ + + def __repr__(self): + if self.has_private(): + if self._curve.is_edwards: + extra = ", seed=%s" % tostr(binascii.hexlify(self._seed)) + else: + extra = ", d=%d" % int(self._d) + else: + extra = "" + if self._curve.id in ( + _CurveID.CURVE25519, + _CurveID.CURVE448, + ): + x = self.pointQ.x + result = "EccKey(curve='%s', point_x=%d%s)" % (self._curve.canonical, x, extra) + else: + x, y = self.pointQ.xy + result = "EccKey(curve='%s', point_x=%d, point_y=%d%s)" % (self._curve.canonical, x, y, extra) + return result + + def has_private(self): + """``True`` if this key can be used for making signatures or decrypting data.""" + + return self._d is not None + + # ECDSA + def _sign(self, z, k): + assert 0 < k < self._curve.order + + order = self._curve.order + blind = Integer.random_range( + min_inclusive=1, + max_exclusive=order, + ) + + blind_d = self._d * blind + inv_blind_k = (blind * k).inverse(order) + + r = (self._curve.G * k).x % order + s = inv_blind_k * (blind * z + blind_d * r) % order + return (r, s) + + # ECDSA + def _verify(self, z, rs): + order = self._curve.order + sinv = rs[1].inverse(order) + point1 = self._curve.G * ((sinv * z) % order) + point2 = self.pointQ * ((sinv * rs[0]) % order) + return (point1 + point2).x == rs[0] + + @property + def d(self): + if not self.has_private(): + raise ValueError("This is not a private ECC key") + return self._d + + @property + def seed(self): + if not self.has_private(): + raise ValueError("This is not a private ECC key") + return self._seed + + @property + def pointQ(self): + if self._point is None: + self._point = self._curve.G * self._d + return self._point + + def public_key(self): + """A matching ECC public key. + + Returns: + a new :class:`EccKey` object + """ + + return EccKey(curve=self._curve.canonical, point=self.pointQ) + + def _export_SEC1(self, compress): + if not self._curve.is_weierstrass: + raise ValueError("SEC1 format is only supported for NIST P curves") + + # See 2.2 in RFC5480 and 2.3.3 in SEC1 + # + # The first byte is: + # - 0x02: compressed, only X-coordinate, Y-coordinate is even + # - 0x03: compressed, only X-coordinate, Y-coordinate is odd + # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate + # + # PAI is in theory encoded as 0x00. + + modulus_bytes = self.pointQ.size_in_bytes() + + if compress: + if self.pointQ.y.is_odd(): + first_byte = b"\x03" + else: + first_byte = b"\x02" + public_key = first_byte + self.pointQ.x.to_bytes(modulus_bytes) + else: + public_key = ( + b"\x04" + self.pointQ.x.to_bytes(modulus_bytes) + self.pointQ.y.to_bytes(modulus_bytes) + ) + return public_key + + def _export_eddsa_public(self): + x, y = self.pointQ.xy + if self._curve.id == _CurveID.ED25519: + result = bytearray(y.to_bytes(32, byteorder="little")) + result[31] = ((x & 1) << 7) | result[31] + elif self._curve.id == _CurveID.ED448: + result = bytearray(y.to_bytes(57, byteorder="little")) + result[56] = (x & 1) << 7 + else: + raise ValueError("Not an EdDSA key to export") + return bytes(result) + + def _export_montgomery_public(self): + if not self._curve.is_montgomery: + raise ValueError("Not a Montgomery key to export") + x = self.pointQ.x + field_size = self.pointQ.size_in_bytes() + result = bytearray(x.to_bytes(field_size, byteorder="little")) + return bytes(result) + + def _export_subjectPublicKeyInfo(self, compress): + if self._curve.is_edwards: + oid = self._curve.oid + public_key = self._export_eddsa_public() + params = None + elif self._curve.is_montgomery: + oid = self._curve.oid + public_key = self._export_montgomery_public() + params = None + else: + oid = "1.2.840.10045.2.1" # unrestricted + public_key = self._export_SEC1(compress) + params = DerObjectId(self._curve.oid) + + return _create_subject_public_key_info( + oid, + public_key, + params, + ) + + def _export_rfc5915_private_der(self, include_ec_params=True): + assert self.has_private() + + # ECPrivateKey ::= SEQUENCE { + # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + # privateKey OCTET STRING, + # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + # publicKey [1] BIT STRING OPTIONAL + # } + + # Public key - uncompressed form + modulus_bytes = self.pointQ.size_in_bytes() + public_key = b"\x04" + self.pointQ.x.to_bytes(modulus_bytes) + self.pointQ.y.to_bytes(modulus_bytes) + + seq = [ + 1, + DerOctetString(self.d.to_bytes(modulus_bytes)), + DerObjectId(self._curve.oid, explicit=0), + DerBitString(public_key, explicit=1), + ] + + if not include_ec_params: + del seq[2] + + return DerSequence(seq).encode() + + def _export_pkcs8(self, **kwargs): + from Cryptodome.IO import PKCS8 + + if kwargs.get("passphrase", None) is not None and "protection" not in kwargs: + raise ValueError("At least the 'protection' parameter must be present") + + if self._seed is not None: + oid = self._curve.oid + private_key = DerOctetString(self._seed).encode() + params = None + else: + oid = "1.2.840.10045.2.1" # unrestricted + private_key = self._export_rfc5915_private_der(include_ec_params=False) + params = DerObjectId(self._curve.oid) + + result = PKCS8.wrap( + private_key, + oid, + key_params=params, + **kwargs, + ) + return result + + def _export_public_pem(self, compress): + from Cryptodome.IO import PEM + + encoded_der = self._export_subjectPublicKeyInfo(compress) + return PEM.encode(encoded_der, "PUBLIC KEY") + + def _export_private_pem(self, passphrase, **kwargs): + from Cryptodome.IO import PEM + + encoded_der = self._export_rfc5915_private_der() + return PEM.encode(encoded_der, "EC PRIVATE KEY", passphrase, **kwargs) + + def _export_private_clear_pkcs8_in_clear_pem(self): + from Cryptodome.IO import PEM + + encoded_der = self._export_pkcs8() + return PEM.encode(encoded_der, "PRIVATE KEY") + + def _export_private_encrypted_pkcs8_in_clear_pem(self, passphrase, **kwargs): + from Cryptodome.IO import PEM + + assert passphrase + if "protection" not in kwargs: + raise ValueError("At least the 'protection' parameter should be present") + encoded_der = self._export_pkcs8(passphrase=passphrase, **kwargs) + return PEM.encode(encoded_der, "ENCRYPTED PRIVATE KEY") + + def _export_openssh(self, compress): + if self.has_private(): + raise ValueError("Cannot export OpenSSH private keys") + + desc = self._curve.openssh + + if desc is None: + raise ValueError("Cannot export %s keys as OpenSSH" % self.curve) + elif desc == "ssh-ed25519": + public_key = self._export_eddsa_public() + comps = (tobytes(desc), tobytes(public_key)) + else: + modulus_bytes = self.pointQ.size_in_bytes() + + if compress: + first_byte = 2 + self.pointQ.y.is_odd() + public_key = bchr(first_byte) + self.pointQ.x.to_bytes(modulus_bytes) + else: + public_key = ( + b"\x04" + self.pointQ.x.to_bytes(modulus_bytes) + self.pointQ.y.to_bytes(modulus_bytes) + ) + + middle = desc.split("-")[2] + comps = (tobytes(desc), tobytes(middle), public_key) + + blob = b"".join([struct.pack(">I", len(x)) + x for x in comps]) + return desc + " " + tostr(binascii.b2a_base64(blob)) + + def export_key(self, **kwargs): + """Export this ECC key. + + Args: + format (string): + The output format: + + - ``'DER'``. The key will be encoded in ASN.1 DER format (binary). + For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure + defined in `RFC5480`_ will be used. + For a private key, the ASN.1 ``ECPrivateKey`` structure defined + in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope, + see the ``use_pkcs8`` flag below). + - ``'PEM'``. The key will be encoded in a PEM_ envelope (ASCII). + - ``'OpenSSH'``. The key will be encoded in the OpenSSH_ format + (ASCII, public keys only). + - ``'SEC1'``. The public key (i.e., the EC point) will be encoded + into ``bytes`` according to Section 2.3.3 of `SEC1`_ + (which is a subset of the older X9.62 ITU standard). + Only for NIST P-curves. + - ``'raw'``. The public key will be encoded as ``bytes``, + without any metadata. + + * For NIST P-curves: equivalent to ``'SEC1'``. + * For Ed25519 and Ed448: ``bytes`` in the format + defined in `RFC8032`_. + * For Curve25519 and Curve448: ``bytes`` in the format + defined in `RFC7748`_. + + passphrase (bytes or string): + (*Private keys only*) The passphrase to protect the + private key. + + use_pkcs8 (boolean): + (*Private keys only*) + If ``True`` (default and recommended), the `PKCS#8`_ representation + will be used. + It must be ``True`` for Ed25519, Ed448, Curve25519, and Curve448. + + If ``False`` and a passphrase is present, the obsolete PEM + encryption will be used. + + protection (string): + When a private key is exported with password-protection + and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be + present, + For all possible protection schemes, + refer to :ref:`the encryption parameters of PKCS#8`. + It is recommended to use ``'PBKDF2WithHMAC-SHA512AndAES128-CBC'``. + + compress (boolean): + If ``True``, the method returns a more compact representation + of the public key, with the X-coordinate only. + + If ``False`` (default), the method returns the full public key. + + This parameter is ignored for Ed25519/Ed448/Curve25519/Curve448, + as compression is mandatory. + + prot_params (dict): + When a private key is exported with password-protection + and PKCS#8 (both ``DER`` and ``PEM`` formats), this dictionary + contains the parameters to use to derive the encryption key + from the passphrase. + For all possible values, + refer to :ref:`the encryption parameters of PKCS#8`. + The recommendation is to use ``{'iteration_count':21000}`` for PBKDF2, + and ``{'iteration_count':131072}`` for scrypt. + + .. warning:: + If you don't provide a passphrase, the private key will be + exported in the clear! + + .. note:: + When exporting a private key with password-protection and `PKCS#8`_ + (both ``DER`` and ``PEM`` formats), any extra parameters + to ``export_key()`` will be passed to :mod:`Cryptodome.IO.PKCS8`. + + .. _PEM: http://www.ietf.org/rfc/rfc1421.txt + .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt + .. _OpenSSH: http://www.openssh.com/txt/rfc5656.txt + .. _RFC5480: https://tools.ietf.org/html/rfc5480 + .. _SEC1: https://www.secg.org/sec1-v2.pdf + .. _RFC7748: https://tools.ietf.org/html/rfc7748 + + Returns: + A multi-line string (for ``'PEM'`` and ``'OpenSSH'``) or + ``bytes`` (for ``'DER'``, ``'SEC1'``, and ``'raw'``) with the encoded key. + """ + + args = kwargs.copy() + ext_format = args.pop("format") + if ext_format not in ("PEM", "DER", "OpenSSH", "SEC1", "raw"): + raise ValueError("Unknown format '%s'" % ext_format) + + compress = args.pop("compress", False) + + if self.has_private(): + passphrase = args.pop("passphrase", None) + if is_string(passphrase): + passphrase = tobytes(passphrase) + if not passphrase: + raise ValueError("Empty passphrase") + + use_pkcs8 = args.pop("use_pkcs8", True) + if use_pkcs8 is False: + if self._curve.is_edwards: + raise ValueError("'pkcs8' must be True for EdDSA curves") + if self._curve.is_montgomery: + raise ValueError("'pkcs8' must be True for Curve25519") + if "protection" in args: + raise ValueError("'protection' is only supported for PKCS#8") + + if ext_format == "PEM": + if use_pkcs8: + if passphrase: + return self._export_private_encrypted_pkcs8_in_clear_pem(passphrase, **args) + else: + return self._export_private_clear_pkcs8_in_clear_pem() + else: + return self._export_private_pem(passphrase, **args) + elif ext_format == "DER": + # DER + if passphrase and not use_pkcs8: + raise ValueError("Private keys can only be encrpyted with DER using PKCS#8") + if use_pkcs8: + return self._export_pkcs8(passphrase=passphrase, **args) + else: + return self._export_rfc5915_private_der() + else: + raise ValueError( + "Private keys cannot be exported in the '%s' format" % ext_format, + ) + else: # Public key + if args: + raise ValueError("Unexpected parameters: '%s'" % args) + if ext_format == "PEM": + return self._export_public_pem(compress) + elif ext_format == "DER": + return self._export_subjectPublicKeyInfo(compress) + elif ext_format == "SEC1": + return self._export_SEC1(compress) + elif ext_format == "raw": + if self._curve.is_edwards: + return self._export_eddsa_public() + elif self._curve.is_montgomery: + return self._export_montgomery_public() + else: + return self._export_SEC1(compress) + else: + return self._export_openssh(compress) def generate(**kwargs): - """Generate a new private key on the given curve. - - Args: - - curve (string): - Mandatory. It must be a curve name defined in the `ECC table`_. - - randfunc (callable): - Optional. The RNG to read randomness from. - If ``None``, :func:`Cryptodome.Random.get_random_bytes` is used. - """ - - curve_name = kwargs.pop("curve") - curve = _curves[curve_name] - randfunc = kwargs.pop("randfunc", get_random_bytes) - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - if _curves[curve_name].id == _CurveID.ED25519: - seed = randfunc(32) - new_key = EccKey(curve=curve_name, seed=seed) - elif _curves[curve_name].id == _CurveID.ED448: - seed = randfunc(57) - new_key = EccKey(curve=curve_name, seed=seed) - elif _curves[curve_name].id == _CurveID.CURVE25519: - seed = randfunc(32) - new_key = EccKey(curve=curve_name, seed=seed) - _curves[curve_name].validate(new_key.pointQ) - elif _curves[curve_name].id == _CurveID.CURVE448: - seed = randfunc(56) - new_key = EccKey(curve=curve_name, seed=seed) - _curves[curve_name].validate(new_key.pointQ) - else: - d = Integer.random_range(min_inclusive=1, - max_exclusive=curve.order, - randfunc=randfunc) - new_key = EccKey(curve=curve_name, d=d) - - return new_key + """Generate a new private key on the given curve. + + Args: + + curve (string): + Mandatory. It must be a curve name defined in the `ECC table`_. + + randfunc (callable): + Optional. The RNG to read randomness from. + If ``None``, :func:`Cryptodome.Random.get_random_bytes` is used. + """ + + curve_name = kwargs.pop("curve") + curve = _curves[curve_name] + randfunc = kwargs.pop("randfunc", get_random_bytes) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + if _curves[curve_name].id == _CurveID.ED25519: + seed = randfunc(32) + new_key = EccKey(curve=curve_name, seed=seed) + elif _curves[curve_name].id == _CurveID.ED448: + seed = randfunc(57) + new_key = EccKey(curve=curve_name, seed=seed) + elif _curves[curve_name].id == _CurveID.CURVE25519: + seed = randfunc(32) + new_key = EccKey(curve=curve_name, seed=seed) + _curves[curve_name].validate(new_key.pointQ) + elif _curves[curve_name].id == _CurveID.CURVE448: + seed = randfunc(56) + new_key = EccKey(curve=curve_name, seed=seed) + _curves[curve_name].validate(new_key.pointQ) + else: + d = Integer.random_range( + min_inclusive=1, + max_exclusive=curve.order, + randfunc=randfunc, + ) + new_key = EccKey(curve=curve_name, d=d) + + return new_key def construct(**kwargs): - """Build a new ECC key (private or public) starting - from some base components. - - In most cases, you will already have an existing key - which you can read in with :func:`import_key` instead - of this function. - - Args: - curve (string): - Mandatory. The name of the elliptic curve, as defined in the `ECC table`_. + """Build a new ECC key (private or public) starting + from some base components. - d (integer): - Mandatory for a private key and a NIST P-curve (e.g., P-256). - It must be an integer in the range ``[1..order-1]``. + In most cases, you will already have an existing key + which you can read in with :func:`import_key` instead + of this function. - seed (bytes): - Mandatory for a private key and curves Ed25519 (32 bytes), - Curve25519 (32 bytes), Curve448 (56 bytes) and Ed448 (57 bytes). + Args: + curve (string): + Mandatory. The name of the elliptic curve, as defined in the `ECC table`_. - point_x (integer): - The X coordinate (affine) of the ECC point. - Mandatory for a public key. + d (integer): + Mandatory for a private key and a NIST P-curve (e.g., P-256). + It must be an integer in the range ``[1..order-1]``. - point_y (integer): - The Y coordinate (affine) of the ECC point. - Mandatory for a public key, - except for Curve25519 and Curve448. + seed (bytes): + Mandatory for a private key and curves Ed25519 (32 bytes), + Curve25519 (32 bytes), Curve448 (56 bytes) and Ed448 (57 bytes). - Returns: - :class:`EccKey` : a new ECC key object - """ + point_x (integer): + The X coordinate (affine) of the ECC point. + Mandatory for a public key. - curve_name = kwargs["curve"] - curve = _curves[curve_name] - point_x = kwargs.pop("point_x", None) - point_y = kwargs.pop("point_y", None) + point_y (integer): + The Y coordinate (affine) of the ECC point. + Mandatory for a public key, + except for Curve25519 and Curve448. - if "point" in kwargs: - raise TypeError("Unknown keyword: point") + Returns: + :class:`EccKey` : a new ECC key object + """ - if curve.id == _CurveID.CURVE25519: + curve_name = kwargs["curve"] + curve = _curves[curve_name] + point_x = kwargs.pop("point_x", None) + point_y = kwargs.pop("point_y", None) - if point_x is not None: - kwargs["point"] = EccXPoint(point_x, curve_name) - new_key = EccKey(**kwargs) - curve.validate(new_key.pointQ) + if "point" in kwargs: + raise TypeError("Unknown keyword: point") - elif curve.id == _CurveID.CURVE448: + if curve.id == _CurveID.CURVE25519: + if point_x is not None: + kwargs["point"] = EccXPoint(point_x, curve_name) + new_key = EccKey(**kwargs) + curve.validate(new_key.pointQ) - if point_x is not None: - kwargs["point"] = EccXPoint(point_x, curve_name) - new_key = EccKey(**kwargs) - curve.validate(new_key.pointQ) + elif curve.id == _CurveID.CURVE448: + if point_x is not None: + kwargs["point"] = EccXPoint(point_x, curve_name) + new_key = EccKey(**kwargs) + curve.validate(new_key.pointQ) - else: + else: + if None not in (point_x, point_y): + kwargs["point"] = EccPoint(point_x, point_y, curve_name) + new_key = EccKey(**kwargs) - if None not in (point_x, point_y): - kwargs["point"] = EccPoint(point_x, point_y, curve_name) - new_key = EccKey(**kwargs) + # Validate that the private key matches the public one + # because EccKey will not do that automatically + if new_key.has_private() and "point" in kwargs: + pub_key = curve.G * new_key.d + if pub_key.xy != (point_x, point_y): + raise ValueError("Private and public ECC keys do not match") - # Validate that the private key matches the public one - # because EccKey will not do that automatically - if new_key.has_private() and 'point' in kwargs: - pub_key = curve.G * new_key.d - if pub_key.xy != (point_x, point_y): - raise ValueError("Private and public ECC keys do not match") - - return new_key + return new_key def _import_public_der(ec_point, curve_oid=None, curve_name=None): - """Convert an encoded EC point into an EccKey object - - ec_point: byte string with the EC point (SEC1-encoded) - curve_oid: string with the name the curve - curve_name: string with the OID of the curve - - Either curve_id or curve_name must be specified - - """ - - for _curve_name, curve in _curves.items(): - if curve_oid and curve.oid == curve_oid: - break - if curve_name == _curve_name: - break - else: - if curve_oid: - raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) - else: - raise UnsupportedEccFeature("Unsupported ECC curve (%s)" % curve_name) - - # See 2.2 in RFC5480 and 2.3.3 in SEC1 - # The first byte is: - # - 0x02: compressed, only X-coordinate, Y-coordinate is even - # - 0x03: compressed, only X-coordinate, Y-coordinate is odd - # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate - # - # PAI is in theory encoded as 0x00. - - modulus_bytes = curve.p.size_in_bytes() - point_type = bord(ec_point[0]) - - # Uncompressed point - if point_type == 0x04: - if len(ec_point) != (1 + 2 * modulus_bytes): - raise ValueError("Incorrect EC point length") - x = Integer.from_bytes(ec_point[1:modulus_bytes+1]) - y = Integer.from_bytes(ec_point[modulus_bytes+1:]) - # Compressed point - elif point_type in (0x02, 0x03): - if len(ec_point) != (1 + modulus_bytes): - raise ValueError("Incorrect EC point length") - x = Integer.from_bytes(ec_point[1:]) - # Right now, we only support Short Weierstrass curves - y = (x**3 - x*3 + curve.b).sqrt(curve.p) - if point_type == 0x02 and y.is_odd(): - y = curve.p - y - if point_type == 0x03 and y.is_even(): - y = curve.p - y - else: - raise ValueError("Incorrect EC point encoding") - - return construct(curve=_curve_name, point_x=x, point_y=y) + """Convert an encoded EC point into an EccKey object + + ec_point: byte string with the EC point (SEC1-encoded) + curve_oid: string with the name the curve + curve_name: string with the OID of the curve + + Either curve_id or curve_name must be specified + + """ + + for _curve_name, curve in _curves.items(): + if curve_oid and curve.oid == curve_oid: + break + if curve_name == _curve_name: + break + else: + if curve_oid: + raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) + else: + raise UnsupportedEccFeature("Unsupported ECC curve (%s)" % curve_name) + + # See 2.2 in RFC5480 and 2.3.3 in SEC1 + # The first byte is: + # - 0x02: compressed, only X-coordinate, Y-coordinate is even + # - 0x03: compressed, only X-coordinate, Y-coordinate is odd + # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate + # + # PAI is in theory encoded as 0x00. + + modulus_bytes = curve.p.size_in_bytes() + point_type = bord(ec_point[0]) + + # Uncompressed point + if point_type == 0x04: + if len(ec_point) != (1 + 2 * modulus_bytes): + raise ValueError("Incorrect EC point length") + x = Integer.from_bytes(ec_point[1 : modulus_bytes + 1]) + y = Integer.from_bytes(ec_point[modulus_bytes + 1 :]) + # Compressed point + elif point_type in (0x02, 0x03): + if len(ec_point) != (1 + modulus_bytes): + raise ValueError("Incorrect EC point length") + x = Integer.from_bytes(ec_point[1:]) + # Right now, we only support Short Weierstrass curves + y = (x**3 - x * 3 + curve.b).sqrt(curve.p) + if point_type == 0x02 and y.is_odd(): + y = curve.p - y + if point_type == 0x03 and y.is_even(): + y = curve.p - y + else: + raise ValueError("Incorrect EC point encoding") + + return construct(curve=_curve_name, point_x=x, point_y=y) def _import_subjectPublicKeyInfo(encoded, *kwargs): - """Convert a subjectPublicKeyInfo into an EccKey object""" - - # See RFC5480 - - # Parse the generic subjectPublicKeyInfo structure - oid, ec_point, params = _expand_subject_public_key_info(encoded) - - nist_p_oids = ( - "1.2.840.10045.2.1", # id-ecPublicKey (unrestricted) - "1.3.132.1.12", # id-ecDH - "1.3.132.1.13" # id-ecMQV - ) - eddsa_oids = { - "1.3.101.112": ("Ed25519", _import_ed25519_public_key), # id-Ed25519 - "1.3.101.113": ("Ed448", _import_ed448_public_key) # id-Ed448 - } - xdh_oids = { - "1.3.101.110": ("Curve25519", _import_curve25519_public_key), # id-X25519 - "1.3.101.111": ("Curve448", _import_curve448_public_key), # id-X448 - } - - if oid in nist_p_oids: - # See RFC5480 - - # Parameters are mandatory and encoded as ECParameters - # ECParameters ::= CHOICE { - # namedCurve OBJECT IDENTIFIER - # -- implicitCurve NULL - # -- specifiedCurve SpecifiedECDomain - # } - # implicitCurve and specifiedCurve are not supported (as per RFC) - if not params: - raise ValueError("Missing ECC parameters for ECC OID %s" % oid) - try: - curve_oid = DerObjectId().decode(params).value - except ValueError: - raise ValueError("Error decoding namedCurve") - - # ECPoint ::= OCTET STRING - return _import_public_der(ec_point, curve_oid=curve_oid) - - elif oid in eddsa_oids: - # See RFC8410 - curve_name, import_eddsa_public_key = eddsa_oids[oid] - - # Parameters must be absent - if params: - raise ValueError("Unexpected ECC parameters for ECC OID %s" % oid) - - x, y = import_eddsa_public_key(ec_point) - return construct(point_x=x, point_y=y, curve=curve_name) - - elif oid in xdh_oids: - curve_name, import_xdh_public_key = xdh_oids[oid] - - # Parameters must be absent - if params: - raise ValueError("Unexpected ECC parameters for ECC OID %s" % oid) - - x = import_xdh_public_key(ec_point) - return construct(point_x=x, curve=curve_name) - - else: - raise UnsupportedEccFeature("Unsupported ECC OID: %s" % oid) + """Convert a subjectPublicKeyInfo into an EccKey object""" + + # See RFC5480 + + # Parse the generic subjectPublicKeyInfo structure + oid, ec_point, params = _expand_subject_public_key_info(encoded) + + nist_p_oids = ( + "1.2.840.10045.2.1", # id-ecPublicKey (unrestricted) + "1.3.132.1.12", # id-ecDH + "1.3.132.1.13", # id-ecMQV + ) + eddsa_oids = { + "1.3.101.112": ("Ed25519", _import_ed25519_public_key), # id-Ed25519 + "1.3.101.113": ("Ed448", _import_ed448_public_key), # id-Ed448 + } + xdh_oids = { + "1.3.101.110": ("Curve25519", _import_curve25519_public_key), # id-X25519 + "1.3.101.111": ("Curve448", _import_curve448_public_key), # id-X448 + } + + if oid in nist_p_oids: + # See RFC5480 + + # Parameters are mandatory and encoded as ECParameters + # ECParameters ::= CHOICE { + # namedCurve OBJECT IDENTIFIER + # -- implicitCurve NULL + # -- specifiedCurve SpecifiedECDomain + # } + # implicitCurve and specifiedCurve are not supported (as per RFC) + if not params: + raise ValueError("Missing ECC parameters for ECC OID %s" % oid) + try: + curve_oid = DerObjectId().decode(params).value + except ValueError: + raise ValueError("Error decoding namedCurve") + + # ECPoint ::= OCTET STRING + return _import_public_der(ec_point, curve_oid=curve_oid) + + elif oid in eddsa_oids: + # See RFC8410 + curve_name, import_eddsa_public_key = eddsa_oids[oid] + + # Parameters must be absent + if params: + raise ValueError("Unexpected ECC parameters for ECC OID %s" % oid) + + x, y = import_eddsa_public_key(ec_point) + return construct(point_x=x, point_y=y, curve=curve_name) + + elif oid in xdh_oids: + curve_name, import_xdh_public_key = xdh_oids[oid] + + # Parameters must be absent + if params: + raise ValueError("Unexpected ECC parameters for ECC OID %s" % oid) + + x = import_xdh_public_key(ec_point) + return construct(point_x=x, curve=curve_name) + + else: + raise UnsupportedEccFeature("Unsupported ECC OID: %s" % oid) def _import_rfc5915_der(encoded, passphrase, curve_oid=None): - - # See RFC5915 https://tools.ietf.org/html/rfc5915 - # - # ECPrivateKey ::= SEQUENCE { - # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - # privateKey OCTET STRING, - # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - # publicKey [1] BIT STRING OPTIONAL - # } - - ec_private_key = DerSequence().decode(encoded, nr_elements=(2, 3, 4)) - if ec_private_key[0] != 1: - raise ValueError("Incorrect ECC private key version") - - scalar_bytes = DerOctetString().decode(ec_private_key[1]).payload - - next_element = 2 - - # Try to decode 'parameters' - if next_element < len(ec_private_key): - try: - parameters = DerObjectId(explicit=0).decode(ec_private_key[next_element]).value - if curve_oid is not None and parameters != curve_oid: - raise ValueError("Curve mismatch") - curve_oid = parameters - next_element += 1 - except ValueError: - pass - - if curve_oid is None: - raise ValueError("No curve found") - - for curve_name, curve in _curves.items(): - if curve.oid == curve_oid: - break - else: - raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) - - modulus_bytes = curve.p.size_in_bytes() - if len(scalar_bytes) != modulus_bytes: - raise ValueError("Private key is too small") - - # Try to decode 'publicKey' - point_x = point_y = None - if next_element < len(ec_private_key): - try: - public_key_enc = DerBitString(explicit=1).decode(ec_private_key[next_element]).value - public_key = _import_public_der(public_key_enc, curve_oid=curve_oid) - point_x = public_key.pointQ.x - point_y = public_key.pointQ.y - next_element += 1 - except ValueError: - pass - - d = Integer.from_bytes(scalar_bytes) - return construct(curve=curve_name, d=d, point_x=point_x, point_y=point_y) + # See RFC5915 https://tools.ietf.org/html/rfc5915 + # + # ECPrivateKey ::= SEQUENCE { + # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + # privateKey OCTET STRING, + # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + # publicKey [1] BIT STRING OPTIONAL + # } + + ec_private_key = DerSequence().decode(encoded, nr_elements=(2, 3, 4)) + if ec_private_key[0] != 1: + raise ValueError("Incorrect ECC private key version") + + scalar_bytes = DerOctetString().decode(ec_private_key[1]).payload + + next_element = 2 + + # Try to decode 'parameters' + if next_element < len(ec_private_key): + try: + parameters = DerObjectId(explicit=0).decode(ec_private_key[next_element]).value + if curve_oid is not None and parameters != curve_oid: + raise ValueError("Curve mismatch") + curve_oid = parameters + next_element += 1 + except ValueError: + pass + + if curve_oid is None: + raise ValueError("No curve found") + + for curve_name, curve in _curves.items(): + if curve.oid == curve_oid: + break + else: + raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) + + modulus_bytes = curve.p.size_in_bytes() + if len(scalar_bytes) != modulus_bytes: + raise ValueError("Private key is too small") + + # Try to decode 'publicKey' + point_x = point_y = None + if next_element < len(ec_private_key): + try: + public_key_enc = DerBitString(explicit=1).decode(ec_private_key[next_element]).value + public_key = _import_public_der(public_key_enc, curve_oid=curve_oid) + point_x = public_key.pointQ.x + point_y = public_key.pointQ.y + next_element += 1 + except ValueError: + pass + + d = Integer.from_bytes(scalar_bytes) + return construct(curve=curve_name, d=d, point_x=point_x, point_y=point_y) def _import_pkcs8(encoded, passphrase): - from Cryptodome.IO import PKCS8 - - algo_oid, private_key, params = PKCS8.unwrap(encoded, passphrase) - - nist_p_oids = ( - "1.2.840.10045.2.1", # id-ecPublicKey (unrestricted) - "1.3.132.1.12", # id-ecDH - "1.3.132.1.13" # id-ecMQV - ) - eddsa_oids = { - "1.3.101.112": "Ed25519", # id-Ed25519 - "1.3.101.113": "Ed448", # id-Ed448 - } - xdh_oids = { - "1.3.101.110": "Curve25519", # id-X25519 - "1.3.101.111": "Curve448", # id-X448 - } - - if algo_oid in nist_p_oids: - curve_oid = DerObjectId().decode(params).value - return _import_rfc5915_der(private_key, passphrase, curve_oid) - elif algo_oid in eddsa_oids: - if params is not None: - raise ValueError("EdDSA ECC private key must not have parameters") - curve_oid = None - seed = DerOctetString().decode(private_key).payload - return construct(curve=eddsa_oids[algo_oid], seed=seed) - elif algo_oid in xdh_oids: - curve_name = xdh_oids[algo_oid] - if params is not None: - raise ValueError("%s ECC private key must not have parameters" % - curve_name) - curve_oid = None - seed = DerOctetString().decode(private_key).payload - return construct(curve=xdh_oids[algo_oid], seed=seed) - else: - raise UnsupportedEccFeature("Unsupported ECC purpose (OID: %s)" % algo_oid) + from Cryptodome.IO import PKCS8 + + algo_oid, private_key, params = PKCS8.unwrap(encoded, passphrase) + + nist_p_oids = ( + "1.2.840.10045.2.1", # id-ecPublicKey (unrestricted) + "1.3.132.1.12", # id-ecDH + "1.3.132.1.13", # id-ecMQV + ) + eddsa_oids = { + "1.3.101.112": "Ed25519", # id-Ed25519 + "1.3.101.113": "Ed448", # id-Ed448 + } + xdh_oids = { + "1.3.101.110": "Curve25519", # id-X25519 + "1.3.101.111": "Curve448", # id-X448 + } + + if algo_oid in nist_p_oids: + curve_oid = DerObjectId().decode(params).value + return _import_rfc5915_der(private_key, passphrase, curve_oid) + elif algo_oid in eddsa_oids: + if params is not None: + raise ValueError("EdDSA ECC private key must not have parameters") + curve_oid = None + seed = DerOctetString().decode(private_key).payload + return construct(curve=eddsa_oids[algo_oid], seed=seed) + elif algo_oid in xdh_oids: + curve_name = xdh_oids[algo_oid] + if params is not None: + raise ValueError( + "%s ECC private key must not have parameters" % curve_name, + ) + curve_oid = None + seed = DerOctetString().decode(private_key).payload + return construct(curve=xdh_oids[algo_oid], seed=seed) + else: + raise UnsupportedEccFeature("Unsupported ECC purpose (OID: %s)" % algo_oid) def _import_x509_cert(encoded, *kwargs): - - sp_info = _extract_subject_public_key_info(encoded) - return _import_subjectPublicKeyInfo(sp_info) + sp_info = _extract_subject_public_key_info(encoded) + return _import_subjectPublicKeyInfo(sp_info) def _import_der(encoded, passphrase): - - try: - return _import_subjectPublicKeyInfo(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - try: - return _import_x509_cert(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - try: - return _import_rfc5915_der(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - try: - return _import_pkcs8(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - raise ValueError("Not an ECC DER key") + try: + return _import_subjectPublicKeyInfo(encoded, passphrase) + except UnsupportedEccFeature as err: + raise err + except (ValueError, TypeError, IndexError): + pass + + try: + return _import_x509_cert(encoded, passphrase) + except UnsupportedEccFeature as err: + raise err + except (ValueError, TypeError, IndexError): + pass + + try: + return _import_rfc5915_der(encoded, passphrase) + except UnsupportedEccFeature as err: + raise err + except (ValueError, TypeError, IndexError): + pass + + try: + return _import_pkcs8(encoded, passphrase) + except UnsupportedEccFeature as err: + raise err + except (ValueError, TypeError, IndexError): + pass + + raise ValueError("Not an ECC DER key") def _import_openssh_public(encoded): - parts = encoded.split(b' ') - if len(parts) not in (2, 3): - raise ValueError("Not an openssh public key") - - try: - keystring = binascii.a2b_base64(parts[1]) - - keyparts = [] - while len(keystring) > 4: - lk = struct.unpack(">I", keystring[:4])[0] - keyparts.append(keystring[4:4 + lk]) - keystring = keystring[4 + lk:] - - if parts[0] != keyparts[0]: - raise ValueError("Mismatch in openssh public key") - - # NIST P curves - if parts[0].startswith(b"ecdsa-sha2-"): - - for curve_name, curve in _curves.items(): - if curve.openssh is None: - continue - if not curve.openssh.startswith("ecdsa-sha2"): - continue - middle = tobytes(curve.openssh.split("-")[2]) - if keyparts[1] == middle: - break - else: - raise ValueError("Unsupported ECC curve: " + middle) - - ecc_key = _import_public_der(keyparts[2], curve_oid=curve.oid) - - # EdDSA - elif parts[0] == b"ssh-ed25519": - x, y = _import_ed25519_public_key(keyparts[1]) - ecc_key = construct(curve="Ed25519", point_x=x, point_y=y) - else: - raise ValueError("Unsupported SSH key type: " + parts[0]) - - except (IndexError, TypeError, binascii.Error): - raise ValueError("Error parsing SSH key type: " + parts[0]) - - return ecc_key + parts = encoded.split(b" ") + if len(parts) not in (2, 3): + raise ValueError("Not an openssh public key") + + try: + keystring = binascii.a2b_base64(parts[1]) + + keyparts = [] + while len(keystring) > 4: + lk = struct.unpack(">I", keystring[:4])[0] + keyparts.append(keystring[4 : 4 + lk]) + keystring = keystring[4 + lk :] + + if parts[0] != keyparts[0]: + raise ValueError("Mismatch in openssh public key") + + # NIST P curves + if parts[0].startswith(b"ecdsa-sha2-"): + for curve_name, curve in _curves.items(): + if curve.openssh is None: + continue + if not curve.openssh.startswith("ecdsa-sha2"): + continue + middle = tobytes(curve.openssh.split("-")[2]) + if keyparts[1] == middle: + break + else: + raise ValueError("Unsupported ECC curve: " + middle) + + ecc_key = _import_public_der(keyparts[2], curve_oid=curve.oid) + + # EdDSA + elif parts[0] == b"ssh-ed25519": + x, y = _import_ed25519_public_key(keyparts[1]) + ecc_key = construct(curve="Ed25519", point_x=x, point_y=y) + else: + raise ValueError("Unsupported SSH key type: " + parts[0]) + + except (IndexError, TypeError, binascii.Error): + raise ValueError("Error parsing SSH key type: " + parts[0]) + + return ecc_key def _import_openssh_private_ecc(data, password): + from ._openssh import ( + import_openssh_private_generic, + read_bytes, + read_string, + check_padding, + ) - from ._openssh import (import_openssh_private_generic, - read_bytes, read_string, check_padding) - - key_type, decrypted = import_openssh_private_generic(data, password) + key_type, decrypted = import_openssh_private_generic(data, password) - eddsa_keys = { - "ssh-ed25519": ("Ed25519", _import_ed25519_public_key, 32), - } + eddsa_keys = { + "ssh-ed25519": ("Ed25519", _import_ed25519_public_key, 32), + } - # https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04 - if key_type.startswith("ecdsa-sha2"): + # https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04 + if key_type.startswith("ecdsa-sha2"): + ecdsa_curve_name, decrypted = read_string(decrypted) + if ecdsa_curve_name not in _curves: + raise UnsupportedEccFeature("Unsupported ECC curve %s" % ecdsa_curve_name) + curve = _curves[ecdsa_curve_name] + modulus_bytes = (curve.modulus_bits + 7) // 8 - ecdsa_curve_name, decrypted = read_string(decrypted) - if ecdsa_curve_name not in _curves: - raise UnsupportedEccFeature("Unsupported ECC curve %s" % ecdsa_curve_name) - curve = _curves[ecdsa_curve_name] - modulus_bytes = (curve.modulus_bits + 7) // 8 + public_key, decrypted = read_bytes(decrypted) - public_key, decrypted = read_bytes(decrypted) + if bord(public_key[0]) != 4: + raise ValueError("Only uncompressed OpenSSH EC keys are supported") + if len(public_key) != 2 * modulus_bytes + 1: + raise ValueError("Incorrect public key length") - if bord(public_key[0]) != 4: - raise ValueError("Only uncompressed OpenSSH EC keys are supported") - if len(public_key) != 2 * modulus_bytes + 1: - raise ValueError("Incorrect public key length") + point_x = Integer.from_bytes(public_key[1 : 1 + modulus_bytes]) + point_y = Integer.from_bytes(public_key[1 + modulus_bytes :]) - point_x = Integer.from_bytes(public_key[1:1+modulus_bytes]) - point_y = Integer.from_bytes(public_key[1+modulus_bytes:]) + private_key, decrypted = read_bytes(decrypted) + d = Integer.from_bytes(private_key) - private_key, decrypted = read_bytes(decrypted) - d = Integer.from_bytes(private_key) + params = {"d": d, "curve": ecdsa_curve_name} - params = {'d': d, 'curve': ecdsa_curve_name} + elif key_type in eddsa_keys: + curve_name, import_eddsa_public_key, seed_len = eddsa_keys[key_type] - elif key_type in eddsa_keys: + public_key, decrypted = read_bytes(decrypted) + point_x, point_y = import_eddsa_public_key(public_key) - curve_name, import_eddsa_public_key, seed_len = eddsa_keys[key_type] + private_public_key, decrypted = read_bytes(decrypted) + seed = private_public_key[:seed_len] - public_key, decrypted = read_bytes(decrypted) - point_x, point_y = import_eddsa_public_key(public_key) + params = {"seed": seed, "curve": curve_name} + else: + raise ValueError("Unsupport SSH agent key type:" + key_type) - private_public_key, decrypted = read_bytes(decrypted) - seed = private_public_key[:seed_len] + _, padded = read_string(decrypted) # Comment + check_padding(padded) - params = {'seed': seed, 'curve': curve_name} - else: - raise ValueError("Unsupport SSH agent key type:" + key_type) - - _, padded = read_string(decrypted) # Comment - check_padding(padded) - - return construct(point_x=point_x, point_y=point_y, **params) + return construct(point_x=point_x, point_y=point_y, **params) def _import_ed25519_public_key(encoded): - """Import an Ed25519 ECC public key, encoded as raw bytes as described - in RFC8032_. - - Args: - encoded (bytes): - The Ed25519 public key to import. It must be 32 bytes long. - - Returns: - x and y (integer) - - Raises: - ValueError: when the given key cannot be parsed. - - .. _RFC8032: https://datatracker.ietf.org/doc/html/rfc8032 - """ - - if len(encoded) != 32: - raise ValueError("Incorrect length. Only Ed25519 public keys are supported.") - - p = Integer(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed) # 2**255 - 19 - d = 37095705934669439343138083508754565189542113879843219016388785533085940283555 - - y = bytearray(encoded) - x_lsb = y[31] >> 7 - y[31] &= 0x7F - point_y = Integer.from_bytes(y, byteorder='little') - if point_y >= p: - raise ValueError("Invalid Ed25519 key (y)") - if point_y == 1: - return 0, 1 - - u = (point_y**2 - 1) % p - v = ((point_y**2 % p) * d + 1) % p - try: - v_inv = v.inverse(p) - x2 = (u * v_inv) % p - point_x = Integer._tonelli_shanks(x2, p) - if (point_x & 1) != x_lsb: - point_x = p - point_x - except ValueError: - raise ValueError("Invalid Ed25519 public key") - return point_x, point_y + """Import an Ed25519 ECC public key, encoded as raw bytes as described + in RFC8032_. + + Args: + encoded (bytes): + The Ed25519 public key to import. It must be 32 bytes long. + + Returns: + x and y (integer) + + Raises: + ValueError: when the given key cannot be parsed. + + .. _RFC8032: https://datatracker.ietf.org/doc/html/rfc8032 + """ + + if len(encoded) != 32: + raise ValueError("Incorrect length. Only Ed25519 public keys are supported.") + + p = Integer(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED) # 2**255 - 19 + d = 37095705934669439343138083508754565189542113879843219016388785533085940283555 + + y = bytearray(encoded) + x_lsb = y[31] >> 7 + y[31] &= 0x7F + point_y = Integer.from_bytes(y, byteorder="little") + if point_y >= p: + raise ValueError("Invalid Ed25519 key (y)") + if point_y == 1: + return 0, 1 + + u = (point_y**2 - 1) % p + v = ((point_y**2 % p) * d + 1) % p + try: + v_inv = v.inverse(p) + x2 = (u * v_inv) % p + point_x = Integer._tonelli_shanks(x2, p) + if (point_x & 1) != x_lsb: + point_x = p - point_x + except ValueError: + raise ValueError("Invalid Ed25519 public key") + return point_x, point_y def _import_curve25519_public_key(encoded): - """Import a Curve25519 ECC public key, - encoded as raw bytes as described in RFC7748_. + """Import a Curve25519 ECC public key, + encoded as raw bytes as described in RFC7748_. - Args: - encoded (bytes): - The Curve25519 public key to import. It must be 32 bytes long. + Args: + encoded (bytes): + The Curve25519 public key to import. It must be 32 bytes long. - Returns: - x (integer) + Returns: + x (integer) - Raises: - ValueError: when the given key cannot be parsed. + Raises: + ValueError: when the given key cannot be parsed. - .. _RFC7748: https://datatracker.ietf.org/doc/html/rfc7748 - """ + .. _RFC7748: https://datatracker.ietf.org/doc/html/rfc7748 + """ - if len(encoded) != 32: - raise ValueError("Incorrect Curve25519 key length") + if len(encoded) != 32: + raise ValueError("Incorrect Curve25519 key length") - x = bytearray(encoded) - # RFC 7741, Section 5 - x[31] &= 0x7F - point_x = Integer.from_bytes(x, byteorder='little') + x = bytearray(encoded) + # RFC 7741, Section 5 + x[31] &= 0x7F + point_x = Integer.from_bytes(x, byteorder="little") - return point_x + return point_x def _import_curve448_public_key(encoded): - """Import a Curve448 ECC public key, - encoded as raw bytes as described in RFC7748_. + """Import a Curve448 ECC public key, + encoded as raw bytes as described in RFC7748_. - Args: - encoded (bytes): - The Curve448 public key to import. It must be 56 bytes long. + Args: + encoded (bytes): + The Curve448 public key to import. It must be 56 bytes long. - Returns: - x (integer) + Returns: + x (integer) - Raises: - ValueError: when the given key cannot be parsed. + Raises: + ValueError: when the given key cannot be parsed. - .. _RFC7748: https://datatracker.ietf.org/doc/html/rfc7748 - """ + .. _RFC7748: https://datatracker.ietf.org/doc/html/rfc7748 + """ - if len(encoded) != 56: - raise ValueError("Incorrect Curve448 key length") + if len(encoded) != 56: + raise ValueError("Incorrect Curve448 key length") - point_x = Integer.from_bytes(encoded, byteorder='little') + point_x = Integer.from_bytes(encoded, byteorder="little") - return point_x + return point_x def _import_ed448_public_key(encoded): - """Import an Ed448 ECC public key, encoded as raw bytes as described - in RFC8032_. + """Import an Ed448 ECC public key, encoded as raw bytes as described + in RFC8032_. - Args: - encoded (bytes): - The Ed448 public key to import. It must be 57 bytes long. + Args: + encoded (bytes): + The Ed448 public key to import. It must be 57 bytes long. - Returns: - x and y (integer) + Returns: + x and y (integer) - Raises: - ValueError: when the given key cannot be parsed. + Raises: + ValueError: when the given key cannot be parsed. - .. _RFC8032: https://datatracker.ietf.org/doc/html/rfc8032 - """ + .. _RFC8032: https://datatracker.ietf.org/doc/html/rfc8032 + """ - if len(encoded) != 57: - raise ValueError("Incorrect length. Only Ed448 public keys are supported.") + if len(encoded) != 57: + raise ValueError("Incorrect length. Only Ed448 public keys are supported.") - p = _curves['curve448'].p - d = p - 39081 + p = _curves["curve448"].p + d = p - 39081 - y = encoded[:56] - x_lsb = bord(encoded[56]) >> 7 - point_y = Integer.from_bytes(y, byteorder='little') - if point_y >= p: - raise ValueError("Invalid Ed448 key (y)") - if point_y == 1: - return 0, 1 + y = encoded[:56] + x_lsb = bord(encoded[56]) >> 7 + point_y = Integer.from_bytes(y, byteorder="little") + if point_y >= p: + raise ValueError("Invalid Ed448 key (y)") + if point_y == 1: + return 0, 1 - u = (point_y**2 - 1) % p - v = ((point_y**2 % p) * d - 1) % p - try: - v_inv = v.inverse(p) - x2 = (u * v_inv) % p - point_x = Integer._tonelli_shanks(x2, p) - if (point_x & 1) != x_lsb: - point_x = p - point_x - except ValueError: - raise ValueError("Invalid Ed448 public key") - return point_x, point_y + u = (point_y**2 - 1) % p + v = ((point_y**2 % p) * d - 1) % p + try: + v_inv = v.inverse(p) + x2 = (u * v_inv) % p + point_x = Integer._tonelli_shanks(x2, p) + if (point_x & 1) != x_lsb: + point_x = p - point_x + except ValueError: + raise ValueError("Invalid Ed448 public key") + return point_x, point_y def import_key(encoded, passphrase=None, curve_name=None): - """Import an ECC key (public or private). - - Args: - encoded (bytes or multi-line string): - The ECC key to import. - The function will try to automatically detect the right format. - - Supported formats for an ECC **public** key: - - * X.509 certificate: binary (DER) or ASCII (PEM). - * X.509 ``subjectPublicKeyInfo``: binary (DER) or ASCII (PEM). - * SEC1_ (or X9.62), as ``bytes``. NIST P curves only. - You must also provide the ``curve_name`` (with a value from the `ECC table`_) - * OpenSSH line, defined in RFC5656_ and RFC8709_ (ASCII). - This is normally the content of files like ``~/.ssh/id_ecdsa.pub``. - - Supported formats for an ECC **private** key: - - * A binary ``ECPrivateKey`` structure, as defined in `RFC5915`_ (DER). - NIST P curves only. - * A `PKCS#8`_ structure (or the more recent Asymmetric Key - Package, RFC5958_): binary (DER) or ASCII (PEM). - * `OpenSSH 6.5`_ and newer versions (ASCII). - - Private keys can be in the clear or password-protected. - - For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. - - passphrase (byte string): - The passphrase to use for decrypting a private key. - Encryption may be applied protected at the PEM level (not recommended) - or at the PKCS#8 level (recommended). - This parameter is ignored if the key in input is not encrypted. - - curve_name (string): - For a SEC1 encoding only. This is the name of the curve, - as defined in the `ECC table`_. - - .. note:: - - To import EdDSA private and public keys, when encoded as raw ``bytes``, use: - - * :func:`Cryptodome.Signature.eddsa.import_public_key`, or - * :func:`Cryptodome.Signature.eddsa.import_private_key`. - - .. note:: - - To import X25519/X448 private and public keys, when encoded as raw ``bytes``, use: - - * :func:`Cryptodome.Protocol.DH.import_x25519_public_key` - * :func:`Cryptodome.Protocol.DH.import_x25519_private_key` - * :func:`Cryptodome.Protocol.DH.import_x448_public_key` - * :func:`Cryptodome.Protocol.DH.import_x448_private_key` - - Returns: - :class:`EccKey` : a new ECC key object - - Raises: - ValueError: when the given key cannot be parsed (possibly because - the pass phrase is wrong). - - .. _RFC1421: https://datatracker.ietf.org/doc/html/rfc1421 - .. _RFC1423: https://datatracker.ietf.org/doc/html/rfc1423 - .. _RFC5915: https://datatracker.ietf.org/doc/html/rfc5915 - .. _RFC5656: https://datatracker.ietf.org/doc/html/rfc5656 - .. _RFC8709: https://datatracker.ietf.org/doc/html/rfc8709 - .. _RFC5958: https://datatracker.ietf.org/doc/html/rfc5958 - .. _`PKCS#8`: https://datatracker.ietf.org/doc/html/rfc5208 - .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf - .. _SEC1: https://www.secg.org/sec1-v2.pdf - """ - - from Cryptodome.IO import PEM - - encoded = tobytes(encoded) - if passphrase is not None: - passphrase = tobytes(passphrase) - - # PEM - if encoded.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'): - text_encoded = tostr(encoded) - openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) - result = _import_openssh_private_ecc(openssh_encoded, passphrase) - return result - - elif encoded.startswith(b'-----'): - - text_encoded = tostr(encoded) - - # Remove any EC PARAMETERS section - # Ignore its content because the curve type must be already given in the key - ecparams_start = "-----BEGIN EC PARAMETERS-----" - ecparams_end = "-----END EC PARAMETERS-----" - text_encoded = re.sub(ecparams_start + ".*?" + ecparams_end, "", - text_encoded, - flags=re.DOTALL) - - der_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) - if enc_flag: - passphrase = None - try: - result = _import_der(der_encoded, passphrase) - except UnsupportedEccFeature as uef: - raise uef - except ValueError: - raise ValueError("Invalid DER encoding inside the PEM file") - return result - - # OpenSSH - if encoded.startswith((b'ecdsa-sha2-', b'ssh-ed25519')): - return _import_openssh_public(encoded) - - # DER - if len(encoded) > 0 and bord(encoded[0]) == 0x30: - return _import_der(encoded, passphrase) - - # SEC1 - if len(encoded) > 0 and bord(encoded[0]) in (0x02, 0x03, 0x04): - if curve_name is None: - raise ValueError("No curve name was provided") - return _import_public_der(encoded, curve_name=curve_name) - - raise ValueError("ECC key format is not supported") + """Import an ECC key (public or private). + + Args: + encoded (bytes or multi-line string): + The ECC key to import. + The function will try to automatically detect the right format. + + Supported formats for an ECC **public** key: + + * X.509 certificate: binary (DER) or ASCII (PEM). + * X.509 ``subjectPublicKeyInfo``: binary (DER) or ASCII (PEM). + * SEC1_ (or X9.62), as ``bytes``. NIST P curves only. + You must also provide the ``curve_name`` (with a value from the `ECC table`_) + * OpenSSH line, defined in RFC5656_ and RFC8709_ (ASCII). + This is normally the content of files like ``~/.ssh/id_ecdsa.pub``. + + Supported formats for an ECC **private** key: + + * A binary ``ECPrivateKey`` structure, as defined in `RFC5915`_ (DER). + NIST P curves only. + * A `PKCS#8`_ structure (or the more recent Asymmetric Key + Package, RFC5958_): binary (DER) or ASCII (PEM). + * `OpenSSH 6.5`_ and newer versions (ASCII). + + Private keys can be in the clear or password-protected. + + For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. + + passphrase (byte string): + The passphrase to use for decrypting a private key. + Encryption may be applied protected at the PEM level (not recommended) + or at the PKCS#8 level (recommended). + This parameter is ignored if the key in input is not encrypted. + + curve_name (string): + For a SEC1 encoding only. This is the name of the curve, + as defined in the `ECC table`_. + + .. note:: + + To import EdDSA private and public keys, when encoded as raw ``bytes``, use: + + * :func:`Cryptodome.Signature.eddsa.import_public_key`, or + * :func:`Cryptodome.Signature.eddsa.import_private_key`. + + .. note:: + + To import X25519/X448 private and public keys, when encoded as raw ``bytes``, use: + + * :func:`Cryptodome.Protocol.DH.import_x25519_public_key` + * :func:`Cryptodome.Protocol.DH.import_x25519_private_key` + * :func:`Cryptodome.Protocol.DH.import_x448_public_key` + * :func:`Cryptodome.Protocol.DH.import_x448_private_key` + + Returns: + :class:`EccKey` : a new ECC key object + + Raises: + ValueError: when the given key cannot be parsed (possibly because + the pass phrase is wrong). + + .. _RFC1421: https://datatracker.ietf.org/doc/html/rfc1421 + .. _RFC1423: https://datatracker.ietf.org/doc/html/rfc1423 + .. _RFC5915: https://datatracker.ietf.org/doc/html/rfc5915 + .. _RFC5656: https://datatracker.ietf.org/doc/html/rfc5656 + .. _RFC8709: https://datatracker.ietf.org/doc/html/rfc8709 + .. _RFC5958: https://datatracker.ietf.org/doc/html/rfc5958 + .. _`PKCS#8`: https://datatracker.ietf.org/doc/html/rfc5208 + .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf + .. _SEC1: https://www.secg.org/sec1-v2.pdf + """ + + from Cryptodome.IO import PEM + + encoded = tobytes(encoded) + if passphrase is not None: + passphrase = tobytes(passphrase) + + # PEM + if encoded.startswith(b"-----BEGIN OPENSSH PRIVATE KEY"): + text_encoded = tostr(encoded) + openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) + result = _import_openssh_private_ecc(openssh_encoded, passphrase) + return result + + elif encoded.startswith(b"-----"): + text_encoded = tostr(encoded) + + # Remove any EC PARAMETERS section + # Ignore its content because the curve type must be already given in the key + ecparams_start = "-----BEGIN EC PARAMETERS-----" + ecparams_end = "-----END EC PARAMETERS-----" + text_encoded = re.sub( + ecparams_start + ".*?" + ecparams_end, + "", + text_encoded, + flags=re.DOTALL, + ) + + der_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) + if enc_flag: + passphrase = None + try: + result = _import_der(der_encoded, passphrase) + except UnsupportedEccFeature as uef: + raise uef + except ValueError: + raise ValueError("Invalid DER encoding inside the PEM file") + return result + + # OpenSSH + if encoded.startswith((b"ecdsa-sha2-", b"ssh-ed25519")): + return _import_openssh_public(encoded) + + # DER + if len(encoded) > 0 and bord(encoded[0]) == 0x30: + return _import_der(encoded, passphrase) + + # SEC1 + if len(encoded) > 0 and bord(encoded[0]) in (0x02, 0x03, 0x04): + if curve_name is None: + raise ValueError("No curve name was provided") + return _import_public_der(encoded, curve_name=curve_name) + + raise ValueError("ECC key format is not supported") if __name__ == "__main__": + import time - import time - - d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd + d = 0xC51E4753AFDEC1E6B6C6A5B992F43F8DD0C7A8933072708B6522468B2FFB06FD - point = _curves['p256'].G.copy() - count = 3000 + point = _curves["p256"].G.copy() + count = 3000 - start = time.time() - for x in range(count): - pointX = point * d - print("(P-256 G)", (time.time() - start) / count * 1000, "ms") + start = time.time() + for x in range(count): + pointX = point * d + print("(P-256 G)", (time.time() - start) / count * 1000, "ms") - start = time.time() - for x in range(count): - pointX = pointX * d - print("(P-256 arbitrary point)", (time.time() - start) / count * 1000, "ms") + start = time.time() + for x in range(count): + pointX = pointX * d + print("(P-256 arbitrary point)", (time.time() - start) / count * 1000, "ms") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ECC.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ECC.pyi index 3d647277..dd40d169 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ECC.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ECC.pyi @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Union, Callable, Optional, Tuple, Dict, NamedTuple, Any, overload, Literal +from typing import Union, Callable, Optional, Dict, NamedTuple, Any, overload, Literal from typing_extensions import TypedDict, Unpack, NotRequired from Cryptodome.Math.Numbers import Integer @@ -11,70 +11,59 @@ from ._point import EccXPoint as EccXPoint RNG = Callable[[int], bytes] - -class UnsupportedEccFeature(ValueError): - ... +class UnsupportedEccFeature(ValueError): ... class ExportParams(TypedDict): - passphrase: NotRequired[Union[bytes, str]] - use_pkcs8: NotRequired[bool] - protection: NotRequired[str] - compress: NotRequired[bool] - prot_params: NotRequired[ProtParams] - + passphrase: NotRequired[Union[bytes, str]] + use_pkcs8: NotRequired[bool] + protection: NotRequired[str] + compress: NotRequired[bool] + prot_params: NotRequired[ProtParams] class EccKey(object): - curve: str - def __init__(self, *, curve: str = ..., d: int = ..., point: EccPoint = ...) -> None: ... - def __eq__(self, other: object) -> bool: ... - def __repr__(self) -> str: ... - def has_private(self) -> bool: ... - @property - def d(self) -> int: ... - @property - def pointQ(self) -> EccPoint: ... - def public_key(self) -> EccKey: ... - - @overload - def export_key(self, - *, - format: Literal['PEM', 'OpenSSH'], - **kwargs: Unpack[ExportParams]) -> str: ... - - @overload - def export_key(self, - *, - format: Literal['DER', 'SEC1', 'raw'], - **kwargs: Unpack[ExportParams]) -> bytes: ... - - -_Curve = NamedTuple("_Curve", [('p', Integer), - ('order', Integer), - ('b', Integer), - ('Gx', Integer), - ('Gy', Integer), - ('G', EccPoint), - ('modulus_bits', int), - ('oid', str), - ('context', Any), - ('desc', str), - ('openssh', Union[str, None]), - ]) + curve: str + def __init__(self, *, curve: str = ..., d: int = ..., point: EccPoint = ...) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __repr__(self) -> str: ... + def has_private(self) -> bool: ... + @property + def d(self) -> int: ... + @property + def pointQ(self) -> EccPoint: ... + def public_key(self) -> EccKey: ... + @overload + def export_key(self, *, format: Literal["PEM", "OpenSSH"], **kwargs: Unpack[ExportParams]) -> str: ... + @overload + def export_key( + self, *, format: Literal["DER", "SEC1", "raw"], **kwargs: Unpack[ExportParams] + ) -> bytes: ... + +_Curve = NamedTuple( + "_Curve", + [ + ("p", Integer), + ("order", Integer), + ("b", Integer), + ("Gx", Integer), + ("Gy", Integer), + ("G", EccPoint), + ("modulus_bits", int), + ("oid", str), + ("context", Any), + ("desc", str), + ("openssh", Union[str, None]), + ], +) _curves: Dict[str, _Curve] -def _import_rfc5915_der(encoded: bytes, - passphrase: Optional[str] = None, - curve_oid: Optional[str] = None) -> EccKey: ... - +def _import_rfc5915_der( + encoded: bytes, passphrase: Optional[str] = None, curve_oid: Optional[str] = None +) -> EccKey: ... def generate(**kwargs: Union[str, RNG]) -> EccKey: ... def construct(**kwargs: Union[str, int]) -> EccKey: ... - - -def import_key(encoded: Union[bytes, str], - passphrase: Optional[str] = None, - curve_name: Optional[str] = None) -> EccKey: ... - - +def import_key( + encoded: Union[bytes, str], passphrase: Optional[str] = None, curve_name: Optional[str] = None +) -> EccKey: ... def _import_ed25519_public_key(encoded: bytes) -> EccKey: ... def _import_ed448_public_key(encoded: bytes) -> EccKey: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ElGamal.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ElGamal.py index 95c219e6..a26ce68b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ElGamal.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ElGamal.py @@ -23,78 +23,91 @@ # SOFTWARE. # =================================================================== -__all__ = ['generate', 'construct', 'ElGamalKey'] +__all__ = ["generate", "construct", "ElGamalKey"] from Cryptodome import Random -from Cryptodome.Math.Primality import ( generate_probable_safe_prime, - test_probable_prime, COMPOSITE ) +from Cryptodome.Math.Primality import ( + generate_probable_safe_prime, + test_probable_prime, + COMPOSITE, +) from Cryptodome.Math.Numbers import Integer + # Generate an ElGamal key with N bits def generate(bits, randfunc): - """Randomly generate a fresh, new ElGamal key. + """Randomly generate a fresh, new ElGamal key. + + The key will be safe for use for both encryption and signature + (although it should be used for **only one** purpose). + + Args: + bits (int): + Key length, or size (in bits) of the modulus *p*. + The recommended value is 2048. + randfunc (callable): + Random number generation function; it should accept + a single integer *N* and return a string of random + *N* random bytes. + + Return: + an :class:`ElGamalKey` object + """ + + obj = ElGamalKey() + + # Generate a safe prime p + # See Algorithm 4.86 in Handbook of Applied Cryptography + obj.p = generate_probable_safe_prime(exact_bits=bits, randfunc=randfunc) + q = (obj.p - 1) >> 1 + + # Generate generator g + while 1: + # Choose a square residue; it will generate a cyclic group of order q. + obj.g = pow( + Integer.random_range( + min_inclusive=2, + max_exclusive=obj.p, + randfunc=randfunc, + ), + 2, + obj.p, + ) + + # We must avoid g=2 because of Bleichenbacher's attack described + # in "Generating ElGamal signatures without knowning the secret key", + # 1996 + if obj.g in (1, 2): + continue + + # Discard g if it divides p-1 because of the attack described + # in Note 11.67 (iii) in HAC + if (obj.p - 1) % obj.g == 0: + continue + + # g^{-1} must not divide p-1 because of Khadir's attack + # described in "Conditions of the generator for forging ElGamal + # signature", 2011 + ginv = obj.g.inverse(obj.p) + if (obj.p - 1) % ginv == 0: + continue + + # Found + break + + # Generate private key x + obj.x = Integer.random_range( + min_inclusive=2, + max_exclusive=obj.p - 1, + randfunc=randfunc, + ) + # Generate public key y + obj.y = pow(obj.g, obj.x, obj.p) + return obj - The key will be safe for use for both encryption and signature - (although it should be used for **only one** purpose). - - Args: - bits (int): - Key length, or size (in bits) of the modulus *p*. - The recommended value is 2048. - randfunc (callable): - Random number generation function; it should accept - a single integer *N* and return a string of random - *N* random bytes. - - Return: - an :class:`ElGamalKey` object - """ - - obj=ElGamalKey() - - # Generate a safe prime p - # See Algorithm 4.86 in Handbook of Applied Cryptography - obj.p = generate_probable_safe_prime(exact_bits=bits, randfunc=randfunc) - q = (obj.p - 1) >> 1 - - # Generate generator g - while 1: - # Choose a square residue; it will generate a cyclic group of order q. - obj.g = pow(Integer.random_range(min_inclusive=2, - max_exclusive=obj.p, - randfunc=randfunc), 2, obj.p) - - # We must avoid g=2 because of Bleichenbacher's attack described - # in "Generating ElGamal signatures without knowning the secret key", - # 1996 - if obj.g in (1, 2): - continue - - # Discard g if it divides p-1 because of the attack described - # in Note 11.67 (iii) in HAC - if (obj.p - 1) % obj.g == 0: - continue - - # g^{-1} must not divide p-1 because of Khadir's attack - # described in "Conditions of the generator for forging ElGamal - # signature", 2011 - ginv = obj.g.inverse(obj.p) - if (obj.p - 1) % ginv == 0: - continue - - # Found - break - - # Generate private key x - obj.x = Integer.random_range(min_inclusive=2, - max_exclusive=obj.p-1, - randfunc=randfunc) - # Generate public key y - obj.y = pow(obj.g, obj.x, obj.p) - return obj def construct(tup): - r"""Construct an ElGamal key from a tuple of valid ElGamal components. + r"""Construct an ElGamal key from a tuple of valid ElGamal components. The modulus *p* must be a prime. The following conditions must apply: @@ -125,162 +138,166 @@ def construct(tup): an :class:`ElGamalKey` object """ - obj=ElGamalKey() - if len(tup) not in [3,4]: - raise ValueError('argument for construct() wrong length') - for i in range(len(tup)): - field = obj._keydata[i] - setattr(obj, field, Integer(tup[i])) + obj = ElGamalKey() + if len(tup) not in [3, 4]: + raise ValueError("argument for construct() wrong length") + for i in range(len(tup)): + field = obj._keydata[i] + setattr(obj, field, Integer(tup[i])) - fmt_error = test_probable_prime(obj.p) == COMPOSITE - fmt_error |= obj.g<=1 or obj.g>=obj.p - fmt_error |= pow(obj.g, obj.p-1, obj.p)!=1 - fmt_error |= obj.y<1 or obj.y>=obj.p - if len(tup)==4: - fmt_error |= obj.x<=1 or obj.x>=obj.p - fmt_error |= pow(obj.g, obj.x, obj.p)!=obj.y + fmt_error = test_probable_prime(obj.p) == COMPOSITE + fmt_error |= obj.g <= 1 or obj.g >= obj.p + fmt_error |= pow(obj.g, obj.p - 1, obj.p) != 1 + fmt_error |= obj.y < 1 or obj.y >= obj.p + if len(tup) == 4: + fmt_error |= obj.x <= 1 or obj.x >= obj.p + fmt_error |= pow(obj.g, obj.x, obj.p) != obj.y - if fmt_error: - raise ValueError("Invalid ElGamal key components") + if fmt_error: + raise ValueError("Invalid ElGamal key components") - return obj + return obj -class ElGamalKey(object): - r"""Class defining an ElGamal key. - Do not instantiate directly. - Use :func:`generate` or :func:`construct` instead. - :ivar p: Modulus - :vartype d: integer - - :ivar g: Generator - :vartype e: integer - - :ivar y: Public key component - :vartype y: integer - - :ivar x: Private key component - :vartype x: integer - """ - - #: Dictionary of ElGamal parameters. - #: - #: A public key will only have the following entries: - #: - #: - **y**, the public key. - #: - **g**, the generator. - #: - **p**, the modulus. - #: - #: A private key will also have: - #: - #: - **x**, the private key. - _keydata=['p', 'g', 'y', 'x'] - - def __init__(self, randfunc=None): - if randfunc is None: - randfunc = Random.new().read - self._randfunc = randfunc - - def _encrypt(self, M, K): - a=pow(self.g, K, self.p) - b=( pow(self.y, K, self.p)*M ) % self.p - return [int(a), int(b)] - - def _decrypt(self, M): - if (not hasattr(self, 'x')): - raise TypeError('Private key not available in this object') - r = Integer.random_range(min_inclusive=2, - max_exclusive=self.p-1, - randfunc=self._randfunc) - a_blind = (pow(self.g, r, self.p) * M[0]) % self.p - ax=pow(a_blind, self.x, self.p) - plaintext_blind = (ax.inverse(self.p) * M[1] ) % self.p - plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p - return int(plaintext) - - def _sign(self, M, K): - if (not hasattr(self, 'x')): - raise TypeError('Private key not available in this object') - p1=self.p-1 - K = Integer(K) - if (K.gcd(p1)!=1): - raise ValueError('Bad K value: GCD(K,p-1)!=1') - a=pow(self.g, K, self.p) - t=(Integer(M)-self.x*a) % p1 - while t<0: t=t+p1 - b=(t*K.inverse(p1)) % p1 - return [int(a), int(b)] - - def _verify(self, M, sig): - sig = [Integer(x) for x in sig] - if sig[0]<1 or sig[0]>self.p-1: - return 0 - v1=pow(self.y, sig[0], self.p) - v1=(v1*pow(sig[0], sig[1], self.p)) % self.p - v2=pow(self.g, M, self.p) - if v1==v2: - return 1 - return 0 - - def has_private(self): - """Whether this is an ElGamal private key""" - - if hasattr(self, 'x'): - return 1 - else: - return 0 - - def can_encrypt(self): - return True - - def can_sign(self): - return True - - def publickey(self): - """A matching ElGamal public key. - - Returns: - a new :class:`ElGamalKey` object - """ - return construct((self.p, self.g, self.y)) - - def __eq__(self, other): - if bool(self.has_private()) != bool(other.has_private()): - return False - - result = True - for comp in self._keydata: - result = result and (getattr(self.key, comp, None) == - getattr(other.key, comp, None)) - return result - - def __ne__(self, other): - return not self.__eq__(other) - - def __getstate__(self): - # ElGamal key is not pickable - from pickle import PicklingError - raise PicklingError - - # Methods defined in PyCryptodome that we don't support anymore - - def sign(self, M, K): - raise NotImplementedError - - def verify(self, M, signature): - raise NotImplementedError - - def encrypt(self, plaintext, K): - raise NotImplementedError - - def decrypt(self, ciphertext): - raise NotImplementedError - - def blind(self, M, B): - raise NotImplementedError - - def unblind(self, M, B): - raise NotImplementedError - - def size(self): - raise NotImplementedError +class ElGamalKey(object): + r"""Class defining an ElGamal key. + Do not instantiate directly. + Use :func:`generate` or :func:`construct` instead. + + :ivar p: Modulus + :vartype d: integer + + :ivar g: Generator + :vartype e: integer + + :ivar y: Public key component + :vartype y: integer + + :ivar x: Private key component + :vartype x: integer + """ + + #: Dictionary of ElGamal parameters. + #: + #: A public key will only have the following entries: + #: + #: - **y**, the public key. + #: - **g**, the generator. + #: - **p**, the modulus. + #: + #: A private key will also have: + #: + #: - **x**, the private key. + _keydata = ["p", "g", "y", "x"] + + def __init__(self, randfunc=None): + if randfunc is None: + randfunc = Random.new().read + self._randfunc = randfunc + + def _encrypt(self, M, K): + a = pow(self.g, K, self.p) + b = (pow(self.y, K, self.p) * M) % self.p + return [int(a), int(b)] + + def _decrypt(self, M): + if not hasattr(self, "x"): + raise TypeError("Private key not available in this object") + r = Integer.random_range( + min_inclusive=2, + max_exclusive=self.p - 1, + randfunc=self._randfunc, + ) + a_blind = (pow(self.g, r, self.p) * M[0]) % self.p + ax = pow(a_blind, self.x, self.p) + plaintext_blind = (ax.inverse(self.p) * M[1]) % self.p + plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p + return int(plaintext) + + def _sign(self, M, K): + if not hasattr(self, "x"): + raise TypeError("Private key not available in this object") + p1 = self.p - 1 + K = Integer(K) + if K.gcd(p1) != 1: + raise ValueError("Bad K value: GCD(K,p-1)!=1") + a = pow(self.g, K, self.p) + t = (Integer(M) - self.x * a) % p1 + while t < 0: + t = t + p1 + b = (t * K.inverse(p1)) % p1 + return [int(a), int(b)] + + def _verify(self, M, sig): + sig = [Integer(x) for x in sig] + if sig[0] < 1 or sig[0] > self.p - 1: + return 0 + v1 = pow(self.y, sig[0], self.p) + v1 = (v1 * pow(sig[0], sig[1], self.p)) % self.p + v2 = pow(self.g, M, self.p) + if v1 == v2: + return 1 + return 0 + + def has_private(self): + """Whether this is an ElGamal private key""" + + if hasattr(self, "x"): + return 1 + else: + return 0 + + def can_encrypt(self): + return True + + def can_sign(self): + return True + + def publickey(self): + """A matching ElGamal public key. + + Returns: + a new :class:`ElGamalKey` object + """ + return construct((self.p, self.g, self.y)) + + def __eq__(self, other): + if bool(self.has_private()) != bool(other.has_private()): + return False + + result = True + for comp in self._keydata: + result = result and (getattr(self.key, comp, None) == getattr(other.key, comp, None)) + return result + + def __ne__(self, other): + return not self.__eq__(other) + + def __getstate__(self): + # ElGamal key is not pickable + from pickle import PicklingError + + raise PicklingError + + # Methods defined in PyCryptodome that we don't support anymore + + def sign(self, M, K): + raise NotImplementedError + + def verify(self, M, signature): + raise NotImplementedError + + def encrypt(self, plaintext, K): + raise NotImplementedError + + def decrypt(self, ciphertext): + raise NotImplementedError + + def blind(self, M, B): + raise NotImplementedError + + def unblind(self, M, B): + raise NotImplementedError + + def size(self): + raise NotImplementedError diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ElGamal.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ElGamal.pyi index 90485313..310257e1 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ElGamal.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/ElGamal.pyi @@ -1,6 +1,6 @@ from typing import Callable, Union, Tuple, Optional -__all__ = ['generate', 'construct', 'ElGamalKey'] +__all__ = ["generate", "construct", "ElGamalKey"] RNG = Callable[[int], bytes] @@ -8,11 +8,11 @@ def generate(bits: int, randfunc: RNG) -> ElGamalKey: ... def construct(tup: Union[Tuple[int, int, int], Tuple[int, int, int, int]]) -> ElGamalKey: ... class ElGamalKey(object): - def __init__(self, randfunc: Optional[RNG]=None) -> None: ... - def has_private(self) -> bool: ... - def can_encrypt(self) -> bool: ... - def can_sign(self) -> bool: ... - def publickey(self) -> ElGamalKey: ... - def __eq__(self, other: object) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __getstate__(self) -> None: ... + def __init__(self, randfunc: Optional[RNG] = None) -> None: ... + def has_private(self) -> bool: ... + def can_encrypt(self) -> bool: ... + def can_sign(self) -> bool: ... + def publickey(self) -> ElGamalKey: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def __getstate__(self) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/RSA.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/RSA.py index 476785e2..0ca71e15 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/RSA.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/RSA.py @@ -29,8 +29,13 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = ['generate', 'construct', 'import_key', - 'RsaKey', 'oid'] +__all__ = [ + "generate", + "construct", + "import_key", + "RsaKey", + "oid", +] import binascii import struct @@ -41,503 +46,539 @@ from Cryptodome.Util.number import bytes_to_long from Cryptodome.Math.Numbers import Integer -from Cryptodome.Math.Primality import (test_probable_prime, - generate_probable_prime, COMPOSITE) +from Cryptodome.Math.Primality import ( + test_probable_prime, + generate_probable_prime, + COMPOSITE, +) -from Cryptodome.PublicKey import (_expand_subject_public_key_info, - _create_subject_public_key_info, - _extract_subject_public_key_info) +from Cryptodome.PublicKey import ( + _expand_subject_public_key_info, + _create_subject_public_key_info, + _extract_subject_public_key_info, +) class RsaKey(object): - r"""Class defining an RSA key, private or public. - Do not instantiate directly. - Use :func:`generate`, :func:`construct` or :func:`import_key` instead. + r"""Class defining an RSA key, private or public. + Do not instantiate directly. + Use :func:`generate`, :func:`construct` or :func:`import_key` instead. + + :ivar n: RSA modulus + :vartype n: integer + + :ivar e: RSA public exponent + :vartype e: integer + + :ivar d: RSA private exponent + :vartype d: integer + + :ivar p: First factor of the RSA modulus + :vartype p: integer + + :ivar q: Second factor of the RSA modulus + :vartype q: integer + + :ivar invp: Chinese remainder component (:math:`p^{-1} \text{mod } q`) + :vartype invp: integer + + :ivar invq: Chinese remainder component (:math:`q^{-1} \text{mod } p`) + :vartype invq: integer + + :ivar u: Same as ``invp`` + :vartype u: integer + """ + + def __init__(self, **kwargs): + """Build an RSA key. + + :Keywords: + n : integer + The modulus. + e : integer + The public exponent. + d : integer + The private exponent. Only required for private keys. + p : integer + The first factor of the modulus. Only required for private keys. + q : integer + The second factor of the modulus. Only required for private keys. + u : integer + The CRT coefficient (inverse of p modulo q). Only required for + private keys. + """ + + input_set = set(kwargs.keys()) + public_set = set(("n", "e")) + private_set = public_set | set(("p", "q", "d", "u")) + if input_set not in (private_set, public_set): + raise ValueError("Some RSA components are missing") + for component, value in kwargs.items(): + setattr(self, "_" + component, value) + if input_set == private_set: + self._dp = self._d % (self._p - 1) # = (e⁻¹) mod (p-1) + self._dq = self._d % (self._q - 1) # = (e⁻¹) mod (q-1) + self._invq = None # will be computed on demand + + @property + def n(self): + return int(self._n) + + @property + def e(self): + return int(self._e) + + @property + def d(self): + if not self.has_private(): + raise AttributeError("No private exponent available for public keys") + return int(self._d) + + @property + def p(self): + if not self.has_private(): + raise AttributeError("No CRT component 'p' available for public keys") + return int(self._p) + + @property + def q(self): + if not self.has_private(): + raise AttributeError("No CRT component 'q' available for public keys") + return int(self._q) + + @property + def dp(self): + if not self.has_private(): + raise AttributeError("No CRT component 'dp' available for public keys") + return int(self._dp) + + @property + def dq(self): + if not self.has_private(): + raise AttributeError("No CRT component 'dq' available for public keys") + return int(self._dq) + + @property + def invq(self): + if not self.has_private(): + raise AttributeError("No CRT component 'invq' available for public keys") + if self._invq is None: + self._invq = self._q.inverse(self._p) + return int(self._invq) + + @property + def invp(self): + return self.u + + @property + def u(self): + if not self.has_private(): + raise AttributeError("No CRT component 'u' available for public keys") + return int(self._u) + + def size_in_bits(self): + """Size of the RSA modulus in bits""" + return self._n.size_in_bits() + + def size_in_bytes(self): + """The minimal amount of bytes that can hold the RSA modulus""" + return (self._n.size_in_bits() - 1) // 8 + 1 + + def _encrypt(self, plaintext): + if not 0 <= plaintext < self._n: + raise ValueError("Plaintext too large") + return int(pow(Integer(plaintext), self._e, self._n)) + + def _decrypt_to_bytes(self, ciphertext): + if not 0 <= ciphertext < self._n: + raise ValueError("Ciphertext too large") + if not self.has_private(): + raise TypeError("This is not a private key") + + # Blinded RSA decryption (to prevent timing attacks): + # Step 1: Generate random secret blinding factor r, + # such that 0 < r < n-1 + r = Integer.random_range(min_inclusive=1, max_exclusive=self._n) + # Step 2: Compute c' = c * r**e mod n + cp = Integer(ciphertext) * pow(r, self._e, self._n) % self._n + # Step 3: Compute m' = c'**d mod n (normal RSA decryption) + m1 = pow(cp, self._dp, self._p) + m2 = pow(cp, self._dq, self._q) + h = ((m2 - m1) * self._u) % self._q + mp = h * self._p + m1 + # Step 4: Compute m = m' * (r**(-1)) mod n + # then encode into a big endian byte string + result = Integer._mult_modulo_bytes( + r.inverse(self._n), + mp, + self._n, + ) + return result + + def _decrypt(self, ciphertext): + """Legacy private method""" + + return bytes_to_long(self._decrypt_to_bytes(ciphertext)) + + def has_private(self): + """Whether this is an RSA private key""" + + return hasattr(self, "_d") + + def can_encrypt(self): # legacy + return True + + def can_sign(self): # legacy + return True + + def public_key(self): + """A matching RSA public key. + + Returns: + a new :class:`RsaKey` object + """ + return RsaKey(n=self._n, e=self._e) + + def __eq__(self, other): + if self.has_private() != other.has_private(): + return False + if self.n != other.n or self.e != other.e: + return False + if not self.has_private(): + return True + return self.d == other.d + + def __ne__(self, other): + return not (self == other) + + def __getstate__(self): + # RSA key is not pickable + from pickle import PicklingError + + raise PicklingError + + def __repr__(self): + if self.has_private(): + extra = ", d=%d, p=%d, q=%d, u=%d" % ( + int(self._d), + int(self._p), + int(self._q), + int(self._u), + ) + else: + extra = "" + return "RsaKey(n=%d, e=%d%s)" % (int(self._n), int(self._e), extra) + + def __str__(self): + if self.has_private(): + key_type = "Private" + else: + key_type = "Public" + return "%s RSA key at 0x%X" % (key_type, id(self)) + + def export_key( + self, + format="PEM", + passphrase=None, + pkcs=1, + protection=None, + randfunc=None, + prot_params=None, + ): + """Export this RSA key. + + Keyword Args: + format (string): + The desired output format: + + - ``'PEM'``. (default) Text output, according to `RFC1421`_/`RFC1423`_. + - ``'DER'``. Binary output. + - ``'OpenSSH'``. Text output, according to the OpenSSH specification. + Only suitable for public keys (not private keys). + + Note that PEM contains a DER structure. + + passphrase (bytes or string): + (*Private keys only*) The passphrase to protect the + private key. + + pkcs (integer): + (*Private keys only*) The standard to use for + serializing the key: PKCS#1 or PKCS#8. + + With ``pkcs=1`` (*default*), the private key is encoded with a + simple `PKCS#1`_ structure (``RSAPrivateKey``). The key cannot be + securely encrypted. + + With ``pkcs=8``, the private key is encoded with a `PKCS#8`_ structure + (``PrivateKeyInfo``). PKCS#8 offers the best ways to securely + encrypt the key. + + .. note:: + This parameter is ignored for a public key. + For DER and PEM, the output is always an + ASN.1 DER ``SubjectPublicKeyInfo`` structure. + + protection (string): + (*For private keys only*) + The encryption scheme to use for protecting the private key + using the passphrase. + + You can only specify a value if ``pkcs=8``. + For all possible protection schemes, + refer to :ref:`the encryption parameters of PKCS#8`. + The recommended value is + ``'PBKDF2WithHMAC-SHA512AndAES256-CBC'``. + + If ``None`` (default), the behavior depends on :attr:`format`: + + - if ``format='PEM'``, the obsolete PEM encryption scheme is used. + It is based on MD5 for key derivation, and 3DES for encryption. + + - if ``format='DER'``, the ``'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'`` + scheme is used. + + prot_params (dict): + (*For private keys only*) + + The parameters to use to derive the encryption key + from the passphrase. ``'protection'`` must be also specified. + For all possible values, + refer to :ref:`the encryption parameters of PKCS#8`. + The recommendation is to use ``{'iteration_count':21000}`` for PBKDF2, + and ``{'iteration_count':131072}`` for scrypt. + + randfunc (callable): + A function that provides random bytes. Only used for PEM encoding. + The default is :func:`Cryptodome.Random.get_random_bytes`. + + Returns: + bytes: the encoded key + + Raises: + ValueError:when the format is unknown or when you try to encrypt a private + key with *DER* format and PKCS#1. + + .. warning:: + If you don't provide a pass phrase, the private key will be + exported in the clear! + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt + .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + """ + + if passphrase is not None: + passphrase = tobytes(passphrase) + + if randfunc is None: + randfunc = Random.get_random_bytes + + if format == "OpenSSH": + e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)] + if bord(e_bytes[0]) & 0x80: + e_bytes = b"\x00" + e_bytes + if bord(n_bytes[0]) & 0x80: + n_bytes = b"\x00" + n_bytes + keyparts = [b"ssh-rsa", e_bytes, n_bytes] + keystring = b"".join([struct.pack(">I", len(kp)) + kp for kp in keyparts]) + return b"ssh-rsa " + binascii.b2a_base64(keystring)[:-1] + + # DER format is always used, even in case of PEM, which simply + # encodes it into BASE64. + if self.has_private(): + binary_key = DerSequence( + [ + 0, + self.n, + self.e, + self.d, + self.p, + self.q, + self.d % (self.p - 1), + self.d % (self.q - 1), + Integer(self.q).inverse(self.p), + ] + ).encode() + if pkcs == 1: + key_type = "RSA PRIVATE KEY" + if format == "DER" and passphrase: + raise ValueError("PKCS#1 private key cannot be encrypted") + else: # PKCS#8 + from Cryptodome.IO import PKCS8 + + if format == "PEM" and protection is None: + key_type = "PRIVATE KEY" + binary_key = PKCS8.wrap( + binary_key, + oid, + None, + key_params=DerNull(), + ) + else: + key_type = "ENCRYPTED PRIVATE KEY" + if not protection: + if prot_params: + raise ValueError("'protection' parameter must be set") + protection = "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC" + binary_key = PKCS8.wrap( + binary_key, + oid, + passphrase, + protection, + prot_params=prot_params, + key_params=DerNull(), + ) + passphrase = None + else: + key_type = "PUBLIC KEY" + binary_key = _create_subject_public_key_info( + oid, + DerSequence( + [ + self.n, + self.e, + ] + ), + DerNull(), + ) + + if format == "DER": + return binary_key + if format == "PEM": + from Cryptodome.IO import PEM + + pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc) + return tobytes(pem_str) + + raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format) + + # Backward compatibility + def exportKey(self, *args, **kwargs): + """:meta private:""" + return self.export_key(*args, **kwargs) + + def publickey(self): + """:meta private:""" + return self.public_key() + + # Methods defined in PyCryptodome that we don't support anymore + def sign(self, M, K): + """:meta private:""" + raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead") + + def verify(self, M, signature): + """:meta private:""" + raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead") + + def encrypt(self, plaintext, K): + """:meta private:""" + raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead") + + def decrypt(self, ciphertext): + """:meta private:""" + raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead") + + def blind(self, M, B): + """:meta private:""" + raise NotImplementedError + + def unblind(self, M, B): + """:meta private:""" + raise NotImplementedError + + def size(self): + """:meta private:""" + raise NotImplementedError - :ivar n: RSA modulus - :vartype n: integer - :ivar e: RSA public exponent - :vartype e: integer - - :ivar d: RSA private exponent - :vartype d: integer - - :ivar p: First factor of the RSA modulus - :vartype p: integer - - :ivar q: Second factor of the RSA modulus - :vartype q: integer - - :ivar invp: Chinese remainder component (:math:`p^{-1} \text{mod } q`) - :vartype invp: integer - - :ivar invq: Chinese remainder component (:math:`q^{-1} \text{mod } p`) - :vartype invq: integer - - :ivar u: Same as ``invp`` - :vartype u: integer - """ - - def __init__(self, **kwargs): - """Build an RSA key. - - :Keywords: - n : integer - The modulus. - e : integer - The public exponent. - d : integer - The private exponent. Only required for private keys. - p : integer - The first factor of the modulus. Only required for private keys. - q : integer - The second factor of the modulus. Only required for private keys. - u : integer - The CRT coefficient (inverse of p modulo q). Only required for - private keys. - """ - - input_set = set(kwargs.keys()) - public_set = set(('n', 'e')) - private_set = public_set | set(('p', 'q', 'd', 'u')) - if input_set not in (private_set, public_set): - raise ValueError("Some RSA components are missing") - for component, value in kwargs.items(): - setattr(self, "_" + component, value) - if input_set == private_set: - self._dp = self._d % (self._p - 1) # = (e⁻¹) mod (p-1) - self._dq = self._d % (self._q - 1) # = (e⁻¹) mod (q-1) - self._invq = None # will be computed on demand - - @property - def n(self): - return int(self._n) - - @property - def e(self): - return int(self._e) - - @property - def d(self): - if not self.has_private(): - raise AttributeError("No private exponent available for public keys") - return int(self._d) - - @property - def p(self): - if not self.has_private(): - raise AttributeError("No CRT component 'p' available for public keys") - return int(self._p) - - @property - def q(self): - if not self.has_private(): - raise AttributeError("No CRT component 'q' available for public keys") - return int(self._q) - - @property - def dp(self): - if not self.has_private(): - raise AttributeError("No CRT component 'dp' available for public keys") - return int(self._dp) - - @property - def dq(self): - if not self.has_private(): - raise AttributeError("No CRT component 'dq' available for public keys") - return int(self._dq) - - @property - def invq(self): - if not self.has_private(): - raise AttributeError("No CRT component 'invq' available for public keys") - if self._invq is None: - self._invq = self._q.inverse(self._p) - return int(self._invq) - - @property - def invp(self): - return self.u - - @property - def u(self): - if not self.has_private(): - raise AttributeError("No CRT component 'u' available for public keys") - return int(self._u) - - def size_in_bits(self): - """Size of the RSA modulus in bits""" - return self._n.size_in_bits() - - def size_in_bytes(self): - """The minimal amount of bytes that can hold the RSA modulus""" - return (self._n.size_in_bits() - 1) // 8 + 1 - - def _encrypt(self, plaintext): - if not 0 <= plaintext < self._n: - raise ValueError("Plaintext too large") - return int(pow(Integer(plaintext), self._e, self._n)) - - def _decrypt_to_bytes(self, ciphertext): - if not 0 <= ciphertext < self._n: - raise ValueError("Ciphertext too large") - if not self.has_private(): - raise TypeError("This is not a private key") - - # Blinded RSA decryption (to prevent timing attacks): - # Step 1: Generate random secret blinding factor r, - # such that 0 < r < n-1 - r = Integer.random_range(min_inclusive=1, max_exclusive=self._n) - # Step 2: Compute c' = c * r**e mod n - cp = Integer(ciphertext) * pow(r, self._e, self._n) % self._n - # Step 3: Compute m' = c'**d mod n (normal RSA decryption) - m1 = pow(cp, self._dp, self._p) - m2 = pow(cp, self._dq, self._q) - h = ((m2 - m1) * self._u) % self._q - mp = h * self._p + m1 - # Step 4: Compute m = m' * (r**(-1)) mod n - # then encode into a big endian byte string - result = Integer._mult_modulo_bytes( - r.inverse(self._n), - mp, - self._n) - return result - - def _decrypt(self, ciphertext): - """Legacy private method""" - - return bytes_to_long(self._decrypt_to_bytes(ciphertext)) - - def has_private(self): - """Whether this is an RSA private key""" - - return hasattr(self, "_d") - - def can_encrypt(self): # legacy - return True - - def can_sign(self): # legacy - return True - - def public_key(self): - """A matching RSA public key. - - Returns: - a new :class:`RsaKey` object - """ - return RsaKey(n=self._n, e=self._e) - - def __eq__(self, other): - if self.has_private() != other.has_private(): - return False - if self.n != other.n or self.e != other.e: - return False - if not self.has_private(): - return True - return (self.d == other.d) - - def __ne__(self, other): - return not (self == other) - - def __getstate__(self): - # RSA key is not pickable - from pickle import PicklingError - raise PicklingError - - def __repr__(self): - if self.has_private(): - extra = ", d=%d, p=%d, q=%d, u=%d" % (int(self._d), int(self._p), - int(self._q), int(self._u)) - else: - extra = "" - return "RsaKey(n=%d, e=%d%s)" % (int(self._n), int(self._e), extra) - - def __str__(self): - if self.has_private(): - key_type = "Private" - else: - key_type = "Public" - return "%s RSA key at 0x%X" % (key_type, id(self)) - - def export_key(self, format='PEM', passphrase=None, pkcs=1, - protection=None, randfunc=None, prot_params=None): - """Export this RSA key. - - Keyword Args: - format (string): - The desired output format: - - - ``'PEM'``. (default) Text output, according to `RFC1421`_/`RFC1423`_. - - ``'DER'``. Binary output. - - ``'OpenSSH'``. Text output, according to the OpenSSH specification. - Only suitable for public keys (not private keys). - - Note that PEM contains a DER structure. - - passphrase (bytes or string): - (*Private keys only*) The passphrase to protect the - private key. - - pkcs (integer): - (*Private keys only*) The standard to use for - serializing the key: PKCS#1 or PKCS#8. - - With ``pkcs=1`` (*default*), the private key is encoded with a - simple `PKCS#1`_ structure (``RSAPrivateKey``). The key cannot be - securely encrypted. - - With ``pkcs=8``, the private key is encoded with a `PKCS#8`_ structure - (``PrivateKeyInfo``). PKCS#8 offers the best ways to securely - encrypt the key. - - .. note:: - This parameter is ignored for a public key. - For DER and PEM, the output is always an - ASN.1 DER ``SubjectPublicKeyInfo`` structure. - - protection (string): - (*For private keys only*) - The encryption scheme to use for protecting the private key - using the passphrase. - - You can only specify a value if ``pkcs=8``. - For all possible protection schemes, - refer to :ref:`the encryption parameters of PKCS#8`. - The recommended value is - ``'PBKDF2WithHMAC-SHA512AndAES256-CBC'``. - - If ``None`` (default), the behavior depends on :attr:`format`: - - - if ``format='PEM'``, the obsolete PEM encryption scheme is used. - It is based on MD5 for key derivation, and 3DES for encryption. - - - if ``format='DER'``, the ``'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'`` - scheme is used. - - prot_params (dict): - (*For private keys only*) - - The parameters to use to derive the encryption key - from the passphrase. ``'protection'`` must be also specified. - For all possible values, - refer to :ref:`the encryption parameters of PKCS#8`. - The recommendation is to use ``{'iteration_count':21000}`` for PBKDF2, - and ``{'iteration_count':131072}`` for scrypt. - - randfunc (callable): - A function that provides random bytes. Only used for PEM encoding. - The default is :func:`Cryptodome.Random.get_random_bytes`. - - Returns: - bytes: the encoded key - - Raises: - ValueError:when the format is unknown or when you try to encrypt a private - key with *DER* format and PKCS#1. - - .. warning:: - If you don't provide a pass phrase, the private key will be - exported in the clear! - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - """ - - if passphrase is not None: - passphrase = tobytes(passphrase) - - if randfunc is None: - randfunc = Random.get_random_bytes - - if format == 'OpenSSH': - e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)] - if bord(e_bytes[0]) & 0x80: - e_bytes = b'\x00' + e_bytes - if bord(n_bytes[0]) & 0x80: - n_bytes = b'\x00' + n_bytes - keyparts = [b'ssh-rsa', e_bytes, n_bytes] - keystring = b''.join([struct.pack(">I", len(kp)) + kp for kp in keyparts]) - return b'ssh-rsa ' + binascii.b2a_base64(keystring)[:-1] - - # DER format is always used, even in case of PEM, which simply - # encodes it into BASE64. - if self.has_private(): - binary_key = DerSequence([0, - self.n, - self.e, - self.d, - self.p, - self.q, - self.d % (self.p-1), - self.d % (self.q-1), - Integer(self.q).inverse(self.p) - ]).encode() - if pkcs == 1: - key_type = 'RSA PRIVATE KEY' - if format == 'DER' and passphrase: - raise ValueError("PKCS#1 private key cannot be encrypted") - else: # PKCS#8 - from Cryptodome.IO import PKCS8 - - if format == 'PEM' and protection is None: - key_type = 'PRIVATE KEY' - binary_key = PKCS8.wrap(binary_key, oid, None, - key_params=DerNull()) - else: - key_type = 'ENCRYPTED PRIVATE KEY' - if not protection: - if prot_params: - raise ValueError("'protection' parameter must be set") - protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' - binary_key = PKCS8.wrap(binary_key, oid, - passphrase, protection, - prot_params=prot_params, - key_params=DerNull()) - passphrase = None - else: - key_type = "PUBLIC KEY" - binary_key = _create_subject_public_key_info(oid, - DerSequence([self.n, - self.e]), - DerNull() - ) - - if format == 'DER': - return binary_key - if format == 'PEM': - from Cryptodome.IO import PEM - - pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc) - return tobytes(pem_str) - - raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format) - - # Backward compatibility - def exportKey(self, *args, **kwargs): - """:meta private:""" - return self.export_key(*args, **kwargs) - - def publickey(self): - """:meta private:""" - return self.public_key() - - # Methods defined in PyCryptodome that we don't support anymore - def sign(self, M, K): - """:meta private:""" - raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead") - - def verify(self, M, signature): - """:meta private:""" - raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead") - - def encrypt(self, plaintext, K): - """:meta private:""" - raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead") - - def decrypt(self, ciphertext): - """:meta private:""" - raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead") - - def blind(self, M, B): - """:meta private:""" - raise NotImplementedError - - def unblind(self, M, B): - """:meta private:""" - raise NotImplementedError - - def size(self): - """:meta private:""" - raise NotImplementedError +def generate(bits, randfunc=None, e=65537): + """Create a new RSA key pair. + The algorithm closely follows NIST `FIPS 186-4`_ in its + sections B.3.1 and B.3.3. The modulus is the product of + two non-strong probable primes. + Each prime passes a suitable number of Miller-Rabin tests + with random bases and a single Lucas test. -def generate(bits, randfunc=None, e=65537): - """Create a new RSA key pair. + Args: + bits (integer): + Key length, or size (in bits) of the RSA modulus. + It must be at least 1024, but **2048 is recommended.** + The FIPS standard only defines 1024, 2048 and 3072. + Keyword Args: + randfunc (callable): + Function that returns random bytes. + The default is :func:`Cryptodome.Random.get_random_bytes`. + e (integer): + Public RSA exponent. It must be an odd positive integer. + It is typically a small number with very few ones in its + binary representation. + The FIPS standard requires the public exponent to be + at least 65537 (the default). - The algorithm closely follows NIST `FIPS 186-4`_ in its - sections B.3.1 and B.3.3. The modulus is the product of - two non-strong probable primes. - Each prime passes a suitable number of Miller-Rabin tests - with random bases and a single Lucas test. + Returns: an RSA key object (:class:`RsaKey`, with private key). - Args: - bits (integer): - Key length, or size (in bits) of the RSA modulus. - It must be at least 1024, but **2048 is recommended.** - The FIPS standard only defines 1024, 2048 and 3072. - Keyword Args: - randfunc (callable): - Function that returns random bytes. - The default is :func:`Cryptodome.Random.get_random_bytes`. - e (integer): - Public RSA exponent. It must be an odd positive integer. - It is typically a small number with very few ones in its - binary representation. - The FIPS standard requires the public exponent to be - at least 65537 (the default). - - Returns: an RSA key object (:class:`RsaKey`, with private key). - - .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ + .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ - if bits < 1024: - raise ValueError("RSA modulus length must be >= 1024") - if e % 2 == 0 or e < 3: - raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.") + if bits < 1024: + raise ValueError("RSA modulus length must be >= 1024") + if e % 2 == 0 or e < 3: + raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.") - if randfunc is None: - randfunc = Random.get_random_bytes + if randfunc is None: + randfunc = Random.get_random_bytes - d = n = Integer(1) - e = Integer(e) + d = n = Integer(1) + e = Integer(e) - while n.size_in_bits() != bits and d < (1 << (bits // 2)): - # Generate the prime factors of n: p and q. - # By construciton, their product is always - # 2^{bits-1} < p*q < 2^bits. - size_q = bits // 2 - size_p = bits - size_q + while n.size_in_bits() != bits and d < (1 << (bits // 2)): + # Generate the prime factors of n: p and q. + # By construciton, their product is always + # 2^{bits-1} < p*q < 2^bits. + size_q = bits // 2 + size_p = bits - size_q - min_p = min_q = (Integer(1) << (2 * size_q - 1)).sqrt() - if size_q != size_p: - min_p = (Integer(1) << (2 * size_p - 1)).sqrt() + min_p = min_q = (Integer(1) << (2 * size_q - 1)).sqrt() + if size_q != size_p: + min_p = (Integer(1) << (2 * size_p - 1)).sqrt() - def filter_p(candidate): - return candidate > min_p and (candidate - 1).gcd(e) == 1 + def filter_p(candidate): + return candidate > min_p and (candidate - 1).gcd(e) == 1 - p = generate_probable_prime(exact_bits=size_p, - randfunc=randfunc, - prime_filter=filter_p) + p = generate_probable_prime( + exact_bits=size_p, + randfunc=randfunc, + prime_filter=filter_p, + ) - min_distance = Integer(1) << (bits // 2 - 100) + min_distance = Integer(1) << (bits // 2 - 100) - def filter_q(candidate): - return (candidate > min_q and - (candidate - 1).gcd(e) == 1 and - abs(candidate - p) > min_distance) + def filter_q(candidate): + return candidate > min_q and (candidate - 1).gcd(e) == 1 and abs(candidate - p) > min_distance - q = generate_probable_prime(exact_bits=size_q, - randfunc=randfunc, - prime_filter=filter_q) + q = generate_probable_prime( + exact_bits=size_q, + randfunc=randfunc, + prime_filter=filter_q, + ) - n = p * q - lcm = (p - 1).lcm(q - 1) - d = e.inverse(lcm) + n = p * q + lcm = (p - 1).lcm(q - 1) + d = e.inverse(lcm) - if p > q: - p, q = q, p + if p > q: + p, q = q, p - u = p.inverse(q) + u = p.inverse(q) - return RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) + return RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) def construct(rsa_components, consistency_check=True): - r"""Construct an RSA key from a tuple of valid RSA components. + r"""Construct an RSA key from a tuple of valid RSA components. The modulus **n** must be the product of two primes. The public exponent **e** must be odd and larger than 1. @@ -577,284 +618,286 @@ def construct(rsa_components, consistency_check=True): Returns: An RSA key object (:class:`RsaKey`). """ - class InputComps(object): - pass - - input_comps = InputComps() - for (comp, value) in zip(('n', 'e', 'd', 'p', 'q', 'u'), rsa_components): - setattr(input_comps, comp, Integer(value)) - - n = input_comps.n - e = input_comps.e - if not hasattr(input_comps, 'd'): - key = RsaKey(n=n, e=e) - else: - d = input_comps.d - if hasattr(input_comps, 'q'): - p = input_comps.p - q = input_comps.q - else: - # Compute factors p and q from the private exponent d. - # We assume that n has no more than two factors. - # See 8.2.2(i) in Handbook of Applied Cryptography. - ktot = d * e - 1 - # The quantity d*e-1 is a multiple of phi(n), even, - # and can be represented as t*2^s. - t = ktot - while t % 2 == 0: - t //= 2 - # Cycle through all multiplicative inverses in Zn. - # The algorithm is non-deterministic, but there is a 50% chance - # any candidate a leads to successful factoring. - # See "Digitalized Signatures and Public Key Functions as Intractable - # as Factorization", M. Rabin, 1979 - spotted = False - a = Integer(2) - while not spotted and a < 100: - k = Integer(t) - # Cycle through all values a^{t*2^i}=a^k - while k < ktot: - cand = pow(a, k, n) - # Check if a^k is a non-trivial root of unity (mod n) - if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: - # We have found a number such that (cand-1)(cand+1)=0 (mod n). - # Either of the terms divides n. - p = Integer(n).gcd(cand + 1) - spotted = True - break - k *= 2 - # This value was not any good... let's try another! - a += 2 - if not spotted: - raise ValueError("Unable to compute factors p and q from exponent d.") - # Found ! - assert ((n % p) == 0) - q = n // p - - if hasattr(input_comps, 'u'): - u = input_comps.u - else: - u = p.inverse(q) - - # Build key object - key = RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) - - # Verify consistency of the key - if consistency_check: - - # Modulus and public exponent must be coprime - if e <= 1 or e >= n: - raise ValueError("Invalid RSA public exponent") - if Integer(n).gcd(e) != 1: - raise ValueError("RSA public exponent is not coprime to modulus") - - # For RSA, modulus must be odd - if not n & 1: - raise ValueError("RSA modulus is not odd") - - if key.has_private(): - # Modulus and private exponent must be coprime - if d <= 1 or d >= n: - raise ValueError("Invalid RSA private exponent") - if Integer(n).gcd(d) != 1: - raise ValueError("RSA private exponent is not coprime to modulus") - # Modulus must be product of 2 primes - if p * q != n: - raise ValueError("RSA factors do not match modulus") - if test_probable_prime(p) == COMPOSITE: - raise ValueError("RSA factor p is composite") - if test_probable_prime(q) == COMPOSITE: - raise ValueError("RSA factor q is composite") - # See Carmichael theorem - phi = (p - 1) * (q - 1) - lcm = phi // (p - 1).gcd(q - 1) - if (e * d % int(lcm)) != 1: - raise ValueError("Invalid RSA condition") - if hasattr(key, 'u'): - # CRT coefficient - if u <= 1 or u >= q: - raise ValueError("Invalid RSA component u") - if (p * u % q) != 1: - raise ValueError("Invalid RSA component u with p") - - return key + class InputComps(object): + pass + + input_comps = InputComps() + for comp, value in zip(("n", "e", "d", "p", "q", "u"), rsa_components): + setattr(input_comps, comp, Integer(value)) + + n = input_comps.n + e = input_comps.e + if not hasattr(input_comps, "d"): + key = RsaKey(n=n, e=e) + else: + d = input_comps.d + if hasattr(input_comps, "q"): + p = input_comps.p + q = input_comps.q + else: + # Compute factors p and q from the private exponent d. + # We assume that n has no more than two factors. + # See 8.2.2(i) in Handbook of Applied Cryptography. + ktot = d * e - 1 + # The quantity d*e-1 is a multiple of phi(n), even, + # and can be represented as t*2^s. + t = ktot + while t % 2 == 0: + t //= 2 + # Cycle through all multiplicative inverses in Zn. + # The algorithm is non-deterministic, but there is a 50% chance + # any candidate a leads to successful factoring. + # See "Digitalized Signatures and Public Key Functions as Intractable + # as Factorization", M. Rabin, 1979 + spotted = False + a = Integer(2) + while not spotted and a < 100: + k = Integer(t) + # Cycle through all values a^{t*2^i}=a^k + while k < ktot: + cand = pow(a, k, n) + # Check if a^k is a non-trivial root of unity (mod n) + if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: + # We have found a number such that (cand-1)(cand+1)=0 (mod n). + # Either of the terms divides n. + p = Integer(n).gcd(cand + 1) + spotted = True + break + k *= 2 + # This value was not any good... let's try another! + a += 2 + if not spotted: + raise ValueError("Unable to compute factors p and q from exponent d.") + # Found ! + assert (n % p) == 0 + q = n // p + + if hasattr(input_comps, "u"): + u = input_comps.u + else: + u = p.inverse(q) + + # Build key object + key = RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) + + # Verify consistency of the key + if consistency_check: + # Modulus and public exponent must be coprime + if e <= 1 or e >= n: + raise ValueError("Invalid RSA public exponent") + if Integer(n).gcd(e) != 1: + raise ValueError("RSA public exponent is not coprime to modulus") + + # For RSA, modulus must be odd + if not n & 1: + raise ValueError("RSA modulus is not odd") + + if key.has_private(): + # Modulus and private exponent must be coprime + if d <= 1 or d >= n: + raise ValueError("Invalid RSA private exponent") + if Integer(n).gcd(d) != 1: + raise ValueError("RSA private exponent is not coprime to modulus") + # Modulus must be product of 2 primes + if p * q != n: + raise ValueError("RSA factors do not match modulus") + if test_probable_prime(p) == COMPOSITE: + raise ValueError("RSA factor p is composite") + if test_probable_prime(q) == COMPOSITE: + raise ValueError("RSA factor q is composite") + # See Carmichael theorem + phi = (p - 1) * (q - 1) + lcm = phi // (p - 1).gcd(q - 1) + if (e * d % int(lcm)) != 1: + raise ValueError("Invalid RSA condition") + if hasattr(key, "u"): + # CRT coefficient + if u <= 1 or u >= q: + raise ValueError("Invalid RSA component u") + if (p * u % q) != 1: + raise ValueError("Invalid RSA component u with p") + + return key def _import_pkcs1_private(encoded, *kwargs): - # RSAPrivateKey ::= SEQUENCE { - # version Version, - # modulus INTEGER, -- n - # publicExponent INTEGER, -- e - # privateExponent INTEGER, -- d - # prime1 INTEGER, -- p - # prime2 INTEGER, -- q - # exponent1 INTEGER, -- d mod (p-1) - # exponent2 INTEGER, -- d mod (q-1) - # coefficient INTEGER -- (inverse of q) mod p - # } - # - # Version ::= INTEGER - der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True) - if der[0] != 0: - raise ValueError("No PKCS#1 encoding of an RSA private key") - return construct(der[1:6] + [Integer(der[4]).inverse(der[5])]) + # RSAPrivateKey ::= SEQUENCE { + # version Version, + # modulus INTEGER, -- n + # publicExponent INTEGER, -- e + # privateExponent INTEGER, -- d + # prime1 INTEGER, -- p + # prime2 INTEGER, -- q + # exponent1 INTEGER, -- d mod (p-1) + # exponent2 INTEGER, -- d mod (q-1) + # coefficient INTEGER -- (inverse of q) mod p + # } + # + # Version ::= INTEGER + der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True) + if der[0] != 0: + raise ValueError("No PKCS#1 encoding of an RSA private key") + return construct(der[1:6] + [Integer(der[4]).inverse(der[5])]) def _import_pkcs1_public(encoded, *kwargs): - # RSAPublicKey ::= SEQUENCE { - # modulus INTEGER, -- n - # publicExponent INTEGER -- e - # } - der = DerSequence().decode(encoded, nr_elements=2, only_ints_expected=True) - return construct(der) + # RSAPublicKey ::= SEQUENCE { + # modulus INTEGER, -- n + # publicExponent INTEGER -- e + # } + der = DerSequence().decode(encoded, nr_elements=2, only_ints_expected=True) + return construct(der) def _import_subjectPublicKeyInfo(encoded, *kwargs): + oids = (oid, "1.2.840.113549.1.1.10") - oids = (oid, "1.2.840.113549.1.1.10") - - algoid, encoded_key, params = _expand_subject_public_key_info(encoded) - if algoid not in oids or params is not None: - raise ValueError("No RSA subjectPublicKeyInfo") - return _import_pkcs1_public(encoded_key) + algoid, encoded_key, params = _expand_subject_public_key_info(encoded) + if algoid not in oids or params is not None: + raise ValueError("No RSA subjectPublicKeyInfo") + return _import_pkcs1_public(encoded_key) def _import_x509_cert(encoded, *kwargs): - - sp_info = _extract_subject_public_key_info(encoded) - return _import_subjectPublicKeyInfo(sp_info) + sp_info = _extract_subject_public_key_info(encoded) + return _import_subjectPublicKeyInfo(sp_info) def _import_pkcs8(encoded, passphrase): - from Cryptodome.IO import PKCS8 + from Cryptodome.IO import PKCS8 - oids = (oid, "1.2.840.113549.1.1.10") + oids = (oid, "1.2.840.113549.1.1.10") - k = PKCS8.unwrap(encoded, passphrase) - if k[0] not in oids: - raise ValueError("No PKCS#8 encoded RSA key") - return _import_keyDER(k[1], passphrase) + k = PKCS8.unwrap(encoded, passphrase) + if k[0] not in oids: + raise ValueError("No PKCS#8 encoded RSA key") + return _import_keyDER(k[1], passphrase) def _import_keyDER(extern_key, passphrase): - """Import an RSA key (public or private half), encoded in DER form.""" + """Import an RSA key (public or private half), encoded in DER form.""" - decodings = (_import_pkcs1_private, - _import_pkcs1_public, - _import_subjectPublicKeyInfo, - _import_x509_cert, - _import_pkcs8) + decodings = ( + _import_pkcs1_private, + _import_pkcs1_public, + _import_subjectPublicKeyInfo, + _import_x509_cert, + _import_pkcs8, + ) - for decoding in decodings: - try: - return decoding(extern_key, passphrase) - except ValueError: - pass + for decoding in decodings: + try: + return decoding(extern_key, passphrase) + except ValueError: + pass - raise ValueError("RSA key format is not supported") + raise ValueError("RSA key format is not supported") def _import_openssh_private_rsa(data, password): + from ._openssh import ( + import_openssh_private_generic, + read_bytes, + read_string, + check_padding, + ) - from ._openssh import (import_openssh_private_generic, - read_bytes, read_string, check_padding) + ssh_name, decrypted = import_openssh_private_generic(data, password) - ssh_name, decrypted = import_openssh_private_generic(data, password) + if ssh_name != "ssh-rsa": + raise ValueError("This SSH key is not RSA") - if ssh_name != "ssh-rsa": - raise ValueError("This SSH key is not RSA") + n, decrypted = read_bytes(decrypted) + e, decrypted = read_bytes(decrypted) + d, decrypted = read_bytes(decrypted) + iqmp, decrypted = read_bytes(decrypted) + p, decrypted = read_bytes(decrypted) + q, decrypted = read_bytes(decrypted) - n, decrypted = read_bytes(decrypted) - e, decrypted = read_bytes(decrypted) - d, decrypted = read_bytes(decrypted) - iqmp, decrypted = read_bytes(decrypted) - p, decrypted = read_bytes(decrypted) - q, decrypted = read_bytes(decrypted) + _, padded = read_string(decrypted) # Comment + check_padding(padded) - _, padded = read_string(decrypted) # Comment - check_padding(padded) - - build = [Integer.from_bytes(x) for x in (n, e, d, q, p, iqmp)] - return construct(build) + build = [Integer.from_bytes(x) for x in (n, e, d, q, p, iqmp)] + return construct(build) def import_key(extern_key, passphrase=None): - """Import an RSA key (public or private). - - Args: - extern_key (string or byte string): - The RSA key to import. - - The following formats are supported for an RSA **public key**: - - - X.509 certificate (binary or PEM format) - - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM - encoding) - - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding) - - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII) - - The following formats are supported for an RSA **private key**: - - - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding) - - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` - DER SEQUENCE (binary or PEM encoding) - - OpenSSH (text format, introduced in `OpenSSH 6.5`_) - - For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. - - passphrase (string or byte string): - For private keys only, the pass phrase that encrypts the key. - - Returns: An RSA key object (:class:`RsaKey`). - - Raises: - ValueError/IndexError/TypeError: - When the given key cannot be parsed (possibly because the pass - phrase is wrong). - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf - """ - - from Cryptodome.IO import PEM - - extern_key = tobytes(extern_key) - if passphrase is not None: - passphrase = tobytes(passphrase) - - if extern_key.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'): - text_encoded = tostr(extern_key) - openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) - result = _import_openssh_private_rsa(openssh_encoded, passphrase) - return result - - if extern_key.startswith(b'-----'): - # This is probably a PEM encoded key. - (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) - if enc_flag: - passphrase = None - return _import_keyDER(der, passphrase) - - if extern_key.startswith(b'ssh-rsa '): - # This is probably an OpenSSH key - keystring = binascii.a2b_base64(extern_key.split(b' ')[1]) - keyparts = [] - while len(keystring) > 4: - length = struct.unpack(">I", keystring[:4])[0] - keyparts.append(keystring[4:4 + length]) - keystring = keystring[4 + length:] - e = Integer.from_bytes(keyparts[1]) - n = Integer.from_bytes(keyparts[2]) - return construct([n, e]) - - if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: - # This is probably a DER encoded key - return _import_keyDER(extern_key, passphrase) - - raise ValueError("RSA key format is not supported") + """Import an RSA key (public or private). + + Args: + extern_key (string or byte string): + The RSA key to import. + + The following formats are supported for an RSA **public key**: + + - X.509 certificate (binary or PEM format) + - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM + encoding) + - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding) + - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII) + + The following formats are supported for an RSA **private key**: + + - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding) + - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` + DER SEQUENCE (binary or PEM encoding) + - OpenSSH (text format, introduced in `OpenSSH 6.5`_) + + For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. + + passphrase (string or byte string): + For private keys only, the pass phrase that encrypts the key. + + Returns: An RSA key object (:class:`RsaKey`). + + Raises: + ValueError/IndexError/TypeError: + When the given key cannot be parsed (possibly because the pass + phrase is wrong). + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt + .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf + """ + + from Cryptodome.IO import PEM + + extern_key = tobytes(extern_key) + if passphrase is not None: + passphrase = tobytes(passphrase) + + if extern_key.startswith(b"-----BEGIN OPENSSH PRIVATE KEY"): + text_encoded = tostr(extern_key) + openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) + result = _import_openssh_private_rsa(openssh_encoded, passphrase) + return result + + if extern_key.startswith(b"-----"): + # This is probably a PEM encoded key. + (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) + if enc_flag: + passphrase = None + return _import_keyDER(der, passphrase) + + if extern_key.startswith(b"ssh-rsa "): + # This is probably an OpenSSH key + keystring = binascii.a2b_base64(extern_key.split(b" ")[1]) + keyparts = [] + while len(keystring) > 4: + length = struct.unpack(">I", keystring[:4])[0] + keyparts.append(keystring[4 : 4 + length]) + keystring = keystring[4 + length :] + e = Integer.from_bytes(keyparts[1]) + n = Integer.from_bytes(keyparts[2]) + return construct([n, e]) + + if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: + # This is probably a DER encoded key + return _import_keyDER(extern_key, passphrase) + + raise ValueError("RSA key format is not supported") # Backward compatibility diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/RSA.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/RSA.pyi index 85f6c4a3..c0183c74 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/RSA.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/RSA.pyi @@ -3,74 +3,77 @@ from typing import Callable, Union, Tuple, Optional, overload, Literal from Cryptodome.Math.Numbers import Integer from Cryptodome.IO._PBES import ProtParams -__all__ = ['generate', 'construct', 'import_key', - 'RsaKey', 'oid'] +__all__ = ["generate", "construct", "import_key", "RsaKey", "oid"] RNG = Callable[[int], bytes] class RsaKey(object): - def __init__(self, **kwargs: int) -> None: ... + def __init__(self, **kwargs: int) -> None: ... + @property + def n(self) -> int: ... + @property + def e(self) -> int: ... + @property + def d(self) -> int: ... + @property + def p(self) -> int: ... + @property + def q(self) -> int: ... + @property + def u(self) -> int: ... + @property + def invp(self) -> int: ... + @property + def invq(self) -> int: ... + def size_in_bits(self) -> int: ... + def size_in_bytes(self) -> int: ... + def has_private(self) -> bool: ... + def can_encrypt(self) -> bool: ... # legacy + def can_sign(self) -> bool: ... # legacy + def public_key(self) -> RsaKey: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def __getstate__(self) -> None: ... + def __repr__(self) -> str: ... + def __str__(self) -> str: ... + @overload + def export_key( + self, + format: Optional[str] = "PEM", + passphrase: Optional[str] = None, + pkcs: Optional[int] = 1, + protection: Optional[str] = None, + randfunc: Optional[RNG] = None, + ) -> bytes: ... + @overload + def export_key( + self, + *, + format: Optional[str] = "PEM", + passphrase: str, + pkcs: Literal[8], + protection: str, + randfunc: Optional[RNG] = None, + prot_params: ProtParams, + ) -> bytes: ... - @property - def n(self) -> int: ... - @property - def e(self) -> int: ... - @property - def d(self) -> int: ... - @property - def p(self) -> int: ... - @property - def q(self) -> int: ... - @property - def u(self) -> int: ... - @property - def invp(self) -> int: ... - @property - def invq(self) -> int: ... - - def size_in_bits(self) -> int: ... - def size_in_bytes(self) -> int: ... - def has_private(self) -> bool: ... - def can_encrypt(self) -> bool: ... # legacy - def can_sign(self) -> bool:... # legacy - def public_key(self) -> RsaKey: ... - def __eq__(self, other: object) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __getstate__(self) -> None: ... - def __repr__(self) -> str: ... - def __str__(self) -> str: ... - - @overload - def export_key(self, - format: Optional[str]="PEM", - passphrase: Optional[str]=None, - pkcs: Optional[int]=1, - protection: Optional[str]=None, - randfunc: Optional[RNG]=None - ) -> bytes: ... - @overload - def export_key(self, *, - format: Optional[str]="PEM", - passphrase: str, - pkcs: Literal[8], - protection: str, - randfunc: Optional[RNG]=None, - prot_params: ProtParams, - ) -> bytes: ... - - # Backward compatibility - exportKey = export_key - publickey = public_key + # Backward compatibility + exportKey = export_key + publickey = public_key Int = Union[int, Integer] -def generate(bits: int, randfunc: Optional[RNG]=None, e: Optional[int]=65537) -> RsaKey: ... -def construct(rsa_components: Union[Tuple[Int, Int], # n, e - Tuple[Int, Int, Int], # n, e, d - Tuple[Int, Int, Int, Int, Int], # n, e, d, p, q - Tuple[Int, Int, Int, Int, Int, Int]], # n, e, d, p, q, crt_q - consistency_check: Optional[bool]=True) -> RsaKey: ... -def import_key(extern_key: Union[str, bytes], passphrase: Optional[str]=None) -> RsaKey: ... +def generate(bits: int, randfunc: Optional[RNG] = None, e: Optional[int] = 65537) -> RsaKey: ... +def construct( + rsa_components: Union[ + Tuple[Int, Int], # n, e + Tuple[Int, Int, Int], # n, e, d + Tuple[Int, Int, Int, Int, Int], # n, e, d, p, q + Tuple[Int, Int, Int, Int, Int, Int], + ], # n, e, d, p, q, crt_q + consistency_check: Optional[bool] = True, +) -> RsaKey: ... +def import_key(extern_key: Union[str, bytes], passphrase: Optional[str] = None) -> RsaKey: ... # Backward compatibility importKey = import_key diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/__init__.py index 99b67a43..eba06cd6 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/__init__.py @@ -18,77 +18,86 @@ # SOFTWARE. # =================================================================== -from Cryptodome.Util.asn1 import (DerSequence, DerInteger, DerBitString, - DerObjectId, DerNull) +from Cryptodome.Util.asn1 import ( + DerSequence, + DerInteger, + DerBitString, + DerObjectId, + DerNull, +) def _expand_subject_public_key_info(encoded): - """Parse a SubjectPublicKeyInfo structure. - - It returns a triple with: - * OID (string) - * encoded public key (bytes) - * Algorithm parameters (bytes or None) - """ - - # - # SubjectPublicKeyInfo ::= SEQUENCE { - # algorithm AlgorithmIdentifier, - # subjectPublicKey BIT STRING - # } - # - # AlgorithmIdentifier ::= SEQUENCE { - # algorithm OBJECT IDENTIFIER, - # parameters ANY DEFINED BY algorithm OPTIONAL - # } - # - - spki = DerSequence().decode(encoded, nr_elements=2) - algo = DerSequence().decode(spki[0], nr_elements=(1,2)) - algo_oid = DerObjectId().decode(algo[0]) - spk = DerBitString().decode(spki[1]).value - - if len(algo) == 1: - algo_params = None - else: - try: - DerNull().decode(algo[1]) - algo_params = None - except: - algo_params = algo[1] - - return algo_oid.value, spk, algo_params + """Parse a SubjectPublicKeyInfo structure. + + It returns a triple with: + * OID (string) + * encoded public key (bytes) + * Algorithm parameters (bytes or None) + """ + + # + # SubjectPublicKeyInfo ::= SEQUENCE { + # algorithm AlgorithmIdentifier, + # subjectPublicKey BIT STRING + # } + # + # AlgorithmIdentifier ::= SEQUENCE { + # algorithm OBJECT IDENTIFIER, + # parameters ANY DEFINED BY algorithm OPTIONAL + # } + # + + spki = DerSequence().decode(encoded, nr_elements=2) + algo = DerSequence().decode(spki[0], nr_elements=(1, 2)) + algo_oid = DerObjectId().decode(algo[0]) + spk = DerBitString().decode(spki[1]).value + + if len(algo) == 1: + algo_params = None + else: + try: + DerNull().decode(algo[1]) + algo_params = None + except: + algo_params = algo[1] + + return algo_oid.value, spk, algo_params def _create_subject_public_key_info(algo_oid, public_key, params): + if params is None: + algorithm = DerSequence([DerObjectId(algo_oid)]) + else: + algorithm = DerSequence([DerObjectId(algo_oid), params]) - if params is None: - algorithm = DerSequence([DerObjectId(algo_oid)]) - else: - algorithm = DerSequence([DerObjectId(algo_oid), params]) - - spki = DerSequence([algorithm, - DerBitString(public_key) - ]) - return spki.encode() + spki = DerSequence( + [ + algorithm, + DerBitString(public_key), + ] + ) + return spki.encode() def _extract_subject_public_key_info(x509_certificate): - """Extract subjectPublicKeyInfo from a DER X.509 certificate.""" - - certificate = DerSequence().decode(x509_certificate, nr_elements=3) - tbs_certificate = DerSequence().decode(certificate[0], - nr_elements=range(6, 11)) - - index = 5 - try: - tbs_certificate[0] + 1 - # Version not present - version = 1 - except TypeError: - version = DerInteger(explicit=0).decode(tbs_certificate[0]).value - if version not in (2, 3): - raise ValueError("Incorrect X.509 certificate version") - index = 6 - - return tbs_certificate[index] + """Extract subjectPublicKeyInfo from a DER X.509 certificate.""" + + certificate = DerSequence().decode(x509_certificate, nr_elements=3) + tbs_certificate = DerSequence().decode( + certificate[0], + nr_elements=range(6, 11), + ) + + index = 5 + try: + tbs_certificate[0] + 1 + # Version not present + version = 1 + except TypeError: + version = DerInteger(explicit=0).decode(tbs_certificate[0]).value + if version not in (2, 3): + raise ValueError("Incorrect X.509 certificate version") + index = 6 + + return tbs_certificate[index] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_curve.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_curve.py index 0027f611..17d60c92 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_curve.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_curve.py @@ -18,20 +18,34 @@ # - rawlib the reference to the dynamic libary with the low-level functions # - validate a function that raises an exception if the the input point is invalid -class _Curve(object): - def __init__(self, p, b, order, Gx, Gy, G, modulus_bits, oid, context, - canonical, openssh, rawlib, validate=None): - self.p = p - self.b = b - self.order = order - self.Gx = Gx - self.Gy = Gy - self.G = G - self.modulus_bits = modulus_bits - self.oid = oid - self.context = context - self.canonical = canonical - self.openssh = openssh - self.rawlib = rawlib - self.validate = validate +class _Curve(object): + def __init__( + self, + p, + b, + order, + Gx, + Gy, + G, + modulus_bits, + oid, + context, + canonical, + openssh, + rawlib, + validate=None, + ): + self.p = p + self.b = b + self.order = order + self.Gx = Gx + self.Gy = Gy + self.G = G + self.modulus_bits = modulus_bits + self.oid = oid + self.context = context + self.canonical = canonical + self.openssh = openssh + self.rawlib = rawlib + self.validate = validate diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_edwards.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_edwards.py index 55de7b78..463dccfd 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_edwards.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_edwards.py @@ -3,17 +3,22 @@ from ._curve import _Curve from Cryptodome.Math.Numbers import Integer -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - SmartPointer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, +) def ed25519_curve(): - p = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed # 2**255 - 19 - order = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed - Gx = 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a - Gy = 0x6666666666666666666666666666666666666666666666666666666666666658 + p = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED # 2**255 - 19 + order = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED + Gx = 0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A + Gy = 0x6666666666666666666666666666666666666666666666666666666666666658 - _ed25519_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._ed25519", """ + _ed25519_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._ed25519", + """ typedef void Point; int ed25519_new_point(Point **out, const uint8_t x[32], @@ -28,41 +33,46 @@ def ed25519_curve(): int ed25519_double(Point *p); int ed25519_add(Point *P1, const Point *P2); int ed25519_scalar(Point *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed); -""") +""", + ) - class EcLib(object): - new_point = _ed25519_lib.ed25519_new_point - clone = _ed25519_lib.ed25519_clone - free_point = _ed25519_lib.ed25519_free_point - cmp = _ed25519_lib.ed25519_cmp - neg = _ed25519_lib.ed25519_neg - get_xy = _ed25519_lib.ed25519_get_xy - double = _ed25519_lib.ed25519_double - add = _ed25519_lib.ed25519_add - scalar = _ed25519_lib.ed25519_scalar + class EcLib(object): + new_point = _ed25519_lib.ed25519_new_point + clone = _ed25519_lib.ed25519_clone + free_point = _ed25519_lib.ed25519_free_point + cmp = _ed25519_lib.ed25519_cmp + neg = _ed25519_lib.ed25519_neg + get_xy = _ed25519_lib.ed25519_get_xy + double = _ed25519_lib.ed25519_double + add = _ed25519_lib.ed25519_add + scalar = _ed25519_lib.ed25519_scalar - ed25519 = _Curve(Integer(p), - None, - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 255, - "1.3.101.112", # RFC8410 - None, - "Ed25519", - "ssh-ed25519", - EcLib) - return ed25519 + ed25519 = _Curve( + Integer(p), + None, + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 255, + "1.3.101.112", # RFC8410 + None, + "Ed25519", + "ssh-ed25519", + EcLib, + ) + return ed25519 def ed448_curve(): - p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff # 2**448 - 2**224 - 1 - order = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3 - Gx = 0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e - Gy = 0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF # 2**448 - 2**224 - 1 + order = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3 + Gx = 0x4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E + Gy = 0x693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14 - _ed448_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._ed448", """ + _ed448_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._ed448", + """ typedef void EcContext; typedef void PointEd448; int ed448_new_context(EcContext **pec_ctx); @@ -81,36 +91,39 @@ def ed448_curve(): int ed448_double(PointEd448 *p); int ed448_add(PointEd448 *P1, const PointEd448 *P2); int ed448_scalar(PointEd448 *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed); -""") +""", + ) - class EcLib(object): - new_point = _ed448_lib.ed448_new_point - clone = _ed448_lib.ed448_clone - free_point = _ed448_lib.ed448_free_point - cmp = _ed448_lib.ed448_cmp - neg = _ed448_lib.ed448_neg - get_xy = _ed448_lib.ed448_get_xy - double = _ed448_lib.ed448_double - add = _ed448_lib.ed448_add - scalar = _ed448_lib.ed448_scalar + class EcLib(object): + new_point = _ed448_lib.ed448_new_point + clone = _ed448_lib.ed448_clone + free_point = _ed448_lib.ed448_free_point + cmp = _ed448_lib.ed448_cmp + neg = _ed448_lib.ed448_neg + get_xy = _ed448_lib.ed448_get_xy + double = _ed448_lib.ed448_double + add = _ed448_lib.ed448_add + scalar = _ed448_lib.ed448_scalar - ed448_context = VoidPointer() - result = _ed448_lib.ed448_new_context(ed448_context.address_of()) - if result: - raise ImportError("Error %d initializing Ed448 context" % result) + ed448_context = VoidPointer() + result = _ed448_lib.ed448_new_context(ed448_context.address_of()) + if result: + raise ImportError("Error %d initializing Ed448 context" % result) - context = SmartPointer(ed448_context.get(), _ed448_lib.ed448_free_context) + context = SmartPointer(ed448_context.get(), _ed448_lib.ed448_free_context) - ed448 = _Curve(Integer(p), - None, - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 448, - "1.3.101.113", # RFC8410 - context, - "Ed448", - None, - EcLib) - return ed448 + ed448 = _Curve( + Integer(p), + None, + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 448, + "1.3.101.113", # RFC8410 + context, + "Ed448", + None, + EcLib, + ) + return ed448 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_montgomery.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_montgomery.py index 5e5fd51d..b1010d0b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_montgomery.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_montgomery.py @@ -3,15 +3,20 @@ from ._curve import _Curve from Cryptodome.Math.Numbers import Integer -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - SmartPointer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, +) def curve25519_curve(): - p = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed # 2**255 - 19 - order = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed + p = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED # 2**255 - 19 + order = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED - _curve25519_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._curve25519", """ + _curve25519_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._curve25519", + """ typedef void Point; int curve25519_new_point(Point **out, @@ -23,69 +28,72 @@ def curve25519_curve(): int curve25519_get_x(uint8_t *xb, size_t modsize, Point *p); int curve25519_scalar(Point *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed); int curve25519_cmp(const Point *ecp1, const Point *ecp2); -""") - - class EcLib(object): - new_point = _curve25519_lib.curve25519_new_point - clone = _curve25519_lib.curve25519_clone - free_point = _curve25519_lib.curve25519_free_point - get_x = _curve25519_lib.curve25519_get_x - scalar = _curve25519_lib.curve25519_scalar - cmp = _curve25519_lib.curve25519_cmp - - def _validate_x25519_point(point): - - p2 = p * 2 - x1 = 325606250916557431795983626356110631294008115727848805560023387167927233504 - x2 = 39382357235489614581723060781553021112529911719440698176882885853963445705823 - - # http://cr.yp.to/ecdh.html#validate - deny_list = ( - 0, - 1, - x1, - x2, - p - 1, - p, - p + 1, - p + x1, - p + x2, - p2 - 1, - p2, - p2 + 1, - ) - - try: - valid = point.x not in deny_list - except ValueError: - valid = False - - if not valid: - raise ValueError("Invalid Curve25519 public key") - - curve25519 = _Curve(Integer(p), - None, - Integer(order), - Integer(9), - None, - None, - 255, - "1.3.101.110", # RFC8410 - None, - "Curve25519", - None, - EcLib, - _validate_x25519_point, - ) - - return curve25519 +""", + ) + + class EcLib(object): + new_point = _curve25519_lib.curve25519_new_point + clone = _curve25519_lib.curve25519_clone + free_point = _curve25519_lib.curve25519_free_point + get_x = _curve25519_lib.curve25519_get_x + scalar = _curve25519_lib.curve25519_scalar + cmp = _curve25519_lib.curve25519_cmp + + def _validate_x25519_point(point): + p2 = p * 2 + x1 = 325606250916557431795983626356110631294008115727848805560023387167927233504 + x2 = 39382357235489614581723060781553021112529911719440698176882885853963445705823 + + # http://cr.yp.to/ecdh.html#validate + deny_list = ( + 0, + 1, + x1, + x2, + p - 1, + p, + p + 1, + p + x1, + p + x2, + p2 - 1, + p2, + p2 + 1, + ) + + try: + valid = point.x not in deny_list + except ValueError: + valid = False + + if not valid: + raise ValueError("Invalid Curve25519 public key") + + curve25519 = _Curve( + Integer(p), + None, + Integer(order), + Integer(9), + None, + None, + 255, + "1.3.101.110", # RFC8410 + None, + "Curve25519", + None, + EcLib, + _validate_x25519_point, + ) + + return curve25519 def curve448_curve(): - p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff # 2**448 - 2**224 - 1 - order = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF # 2**448 - 2**224 - 1 + order = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3 - _curve448_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._curve448", """ + _curve448_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._curve448", + """ typedef void Curve448Context; typedef void Curve448Point; @@ -100,53 +108,55 @@ def curve448_curve(): int curve448_get_x(uint8_t *xb, size_t modsize, const Curve448Point *p); int curve448_scalar(Curve448Point *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed); int curve448_cmp(const Curve448Point *ecp1, const Curve448Point *ecp2); -""") - - class EcLib(object): - new_context = _curve448_lib.curve448_new_context - free_context = _curve448_lib.curve448_free_context - new_point = _curve448_lib.curve448_new_point - clone = _curve448_lib.curve448_clone - free_point = _curve448_lib.curve448_free_point - get_x = _curve448_lib.curve448_get_x - scalar = _curve448_lib.curve448_scalar - cmp = _curve448_lib.curve448_cmp - - curve448_context = VoidPointer() - result = EcLib.new_context(curve448_context.address_of()) - if result: - raise ImportError("Error %d initializing Curve448 context" % result) - - def _validate_x448_point(point): - deny_list = ( - 0, - 1, - p - 1, - p, - p + 1, - ) - - try: - valid = point.x not in deny_list - except ValueError: - valid = False - - if not valid: - raise ValueError("Invalid Curve448 public key") - - curve448 = _Curve(Integer(p), - None, - Integer(order), - Integer(5), - None, - None, - 448, - "1.3.101.111", # RFC8410 - SmartPointer(curve448_context.get(), EcLib.free_context), - "Curve448", - None, - EcLib, - _validate_x448_point, - ) - - return curve448 +""", + ) + + class EcLib(object): + new_context = _curve448_lib.curve448_new_context + free_context = _curve448_lib.curve448_free_context + new_point = _curve448_lib.curve448_new_point + clone = _curve448_lib.curve448_clone + free_point = _curve448_lib.curve448_free_point + get_x = _curve448_lib.curve448_get_x + scalar = _curve448_lib.curve448_scalar + cmp = _curve448_lib.curve448_cmp + + curve448_context = VoidPointer() + result = EcLib.new_context(curve448_context.address_of()) + if result: + raise ImportError("Error %d initializing Curve448 context" % result) + + def _validate_x448_point(point): + deny_list = ( + 0, + 1, + p - 1, + p, + p + 1, + ) + + try: + valid = point.x not in deny_list + except ValueError: + valid = False + + if not valid: + raise ValueError("Invalid Curve448 public key") + + curve448 = _Curve( + Integer(p), + None, + Integer(order), + Integer(5), + None, + None, + 448, + "1.3.101.111", # RFC8410 + SmartPointer(curve448_context.get(), EcLib.free_context), + "Curve448", + None, + EcLib, + _validate_x448_point, + ) + + return curve448 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_nist_ecc.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_nist_ecc.py index 3065c65b..affeb670 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_nist_ecc.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_nist_ecc.py @@ -3,14 +3,21 @@ from ._curve import _Curve from Cryptodome.Math.Numbers import Integer -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - SmartPointer, c_size_t, c_uint8_ptr, - c_ulonglong) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + c_ulonglong, +) from Cryptodome.Util.number import long_to_bytes from Cryptodome.Random.random import getrandbits -_ec_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._ec_ws", """ +_ec_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._ec_ws", + """ typedef void EcContext; typedef void EcPoint; int ec_ws_new_context(EcContext **pec_ctx, @@ -39,208 +46,224 @@ int ec_ws_clone(EcPoint **pecp2, const EcPoint *ecp); int ec_ws_cmp(const EcPoint *ecp1, const EcPoint *ecp2); int ec_ws_neg(EcPoint *p); -""") +""", +) class EcLib(object): - new_context = _ec_lib.ec_ws_new_context - free_context = _ec_lib.ec_ws_free_context - new_point = _ec_lib.ec_ws_new_point - free_point = _ec_lib.ec_ws_free_point - get_xy = _ec_lib.ec_ws_get_xy - double = _ec_lib.ec_ws_double - add = _ec_lib.ec_ws_add - scalar = _ec_lib.ec_ws_scalar - clone = _ec_lib.ec_ws_clone - cmp = _ec_lib.ec_ws_cmp - neg = _ec_lib.ec_ws_neg + new_context = _ec_lib.ec_ws_new_context + free_context = _ec_lib.ec_ws_free_context + new_point = _ec_lib.ec_ws_new_point + free_point = _ec_lib.ec_ws_free_point + get_xy = _ec_lib.ec_ws_get_xy + double = _ec_lib.ec_ws_double + add = _ec_lib.ec_ws_add + scalar = _ec_lib.ec_ws_scalar + clone = _ec_lib.ec_ws_clone + cmp = _ec_lib.ec_ws_cmp + neg = _ec_lib.ec_ws_neg def p192_curve(): - p = 0xfffffffffffffffffffffffffffffffeffffffffffffffff - b = 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1 - order = 0xffffffffffffffffffffffff99def836146bc9b1b4d22831 - Gx = 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 - Gy = 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811 - - p192_modulus = long_to_bytes(p, 24) - p192_b = long_to_bytes(b, 24) - p192_order = long_to_bytes(order, 24) - - ec_p192_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p192_context.address_of(), - c_uint8_ptr(p192_modulus), - c_uint8_ptr(p192_b), - c_uint8_ptr(p192_order), - c_size_t(len(p192_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-192 context" % result) - - context = SmartPointer(ec_p192_context.get(), _ec_lib.ec_ws_free_context) - p192 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 192, - "1.2.840.10045.3.1.1", # ANSI X9.62 / SEC2 - context, - "NIST P-192", - "ecdsa-sha2-nistp192", - EcLib) - return p192 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF + b = 0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1 + order = 0xFFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831 + Gx = 0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012 + Gy = 0x07192B95FFC8DA78631011ED6B24CDD573F977A11E794811 + + p192_modulus = long_to_bytes(p, 24) + p192_b = long_to_bytes(b, 24) + p192_order = long_to_bytes(order, 24) + + ec_p192_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p192_context.address_of(), + c_uint8_ptr(p192_modulus), + c_uint8_ptr(p192_b), + c_uint8_ptr(p192_order), + c_size_t(len(p192_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-192 context" % result) + + context = SmartPointer(ec_p192_context.get(), _ec_lib.ec_ws_free_context) + p192 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 192, + "1.2.840.10045.3.1.1", # ANSI X9.62 / SEC2 + context, + "NIST P-192", + "ecdsa-sha2-nistp192", + EcLib, + ) + return p192 def p224_curve(): - p = 0xffffffffffffffffffffffffffffffff000000000000000000000001 - b = 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4 - order = 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d - Gx = 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21 - Gy = 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34 - - p224_modulus = long_to_bytes(p, 28) - p224_b = long_to_bytes(b, 28) - p224_order = long_to_bytes(order, 28) - - ec_p224_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p224_context.address_of(), - c_uint8_ptr(p224_modulus), - c_uint8_ptr(p224_b), - c_uint8_ptr(p224_order), - c_size_t(len(p224_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-224 context" % result) - - context = SmartPointer(ec_p224_context.get(), _ec_lib.ec_ws_free_context) - p224 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 224, - "1.3.132.0.33", # SEC 2 - context, - "NIST P-224", - "ecdsa-sha2-nistp224", - EcLib) - return p224 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001 + b = 0xB4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4 + order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D + Gx = 0xB70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21 + Gy = 0xBD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34 + + p224_modulus = long_to_bytes(p, 28) + p224_b = long_to_bytes(b, 28) + p224_order = long_to_bytes(order, 28) + + ec_p224_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p224_context.address_of(), + c_uint8_ptr(p224_modulus), + c_uint8_ptr(p224_b), + c_uint8_ptr(p224_order), + c_size_t(len(p224_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-224 context" % result) + + context = SmartPointer(ec_p224_context.get(), _ec_lib.ec_ws_free_context) + p224 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 224, + "1.3.132.0.33", # SEC 2 + context, + "NIST P-224", + "ecdsa-sha2-nistp224", + EcLib, + ) + return p224 def p256_curve(): - p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff - b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b - order = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 - Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 - Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 - - p256_modulus = long_to_bytes(p, 32) - p256_b = long_to_bytes(b, 32) - p256_order = long_to_bytes(order, 32) - - ec_p256_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p256_context.address_of(), - c_uint8_ptr(p256_modulus), - c_uint8_ptr(p256_b), - c_uint8_ptr(p256_order), - c_size_t(len(p256_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-256 context" % result) - - context = SmartPointer(ec_p256_context.get(), _ec_lib.ec_ws_free_context) - p256 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 256, - "1.2.840.10045.3.1.7", # ANSI X9.62 / SEC2 - context, - "NIST P-256", - "ecdsa-sha2-nistp256", - EcLib) - return p256 + p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF + b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B + order = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 + Gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296 + Gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5 + + p256_modulus = long_to_bytes(p, 32) + p256_b = long_to_bytes(b, 32) + p256_order = long_to_bytes(order, 32) + + ec_p256_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p256_context.address_of(), + c_uint8_ptr(p256_modulus), + c_uint8_ptr(p256_b), + c_uint8_ptr(p256_order), + c_size_t(len(p256_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-256 context" % result) + + context = SmartPointer(ec_p256_context.get(), _ec_lib.ec_ws_free_context) + p256 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 256, + "1.2.840.10045.3.1.7", # ANSI X9.62 / SEC2 + context, + "NIST P-256", + "ecdsa-sha2-nistp256", + EcLib, + ) + return p256 def p384_curve(): - p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff - b = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef - order = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 - Gx = 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7 - Gy = 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F - - p384_modulus = long_to_bytes(p, 48) - p384_b = long_to_bytes(b, 48) - p384_order = long_to_bytes(order, 48) - - ec_p384_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p384_context.address_of(), - c_uint8_ptr(p384_modulus), - c_uint8_ptr(p384_b), - c_uint8_ptr(p384_order), - c_size_t(len(p384_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-384 context" % result) - - context = SmartPointer(ec_p384_context.get(), _ec_lib.ec_ws_free_context) - p384 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 384, - "1.3.132.0.34", # SEC 2 - context, - "NIST P-384", - "ecdsa-sha2-nistp384", - EcLib) - return p384 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF + b = 0xB3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF + order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973 + Gx = 0xAA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7 + Gy = 0x3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F + + p384_modulus = long_to_bytes(p, 48) + p384_b = long_to_bytes(b, 48) + p384_order = long_to_bytes(order, 48) + + ec_p384_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p384_context.address_of(), + c_uint8_ptr(p384_modulus), + c_uint8_ptr(p384_b), + c_uint8_ptr(p384_order), + c_size_t(len(p384_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-384 context" % result) + + context = SmartPointer(ec_p384_context.get(), _ec_lib.ec_ws_free_context) + p384 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 384, + "1.3.132.0.34", # SEC 2 + context, + "NIST P-384", + "ecdsa-sha2-nistp384", + EcLib, + ) + return p384 def p521_curve(): - p = 0x000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - b = 0x00000051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00 - order = 0x000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409 - Gx = 0x000000c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66 - Gy = 0x0000011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650 - - p521_modulus = long_to_bytes(p, 66) - p521_b = long_to_bytes(b, 66) - p521_order = long_to_bytes(order, 66) - - ec_p521_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p521_context.address_of(), - c_uint8_ptr(p521_modulus), - c_uint8_ptr(p521_b), - c_uint8_ptr(p521_order), - c_size_t(len(p521_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-521 context" % result) - - context = SmartPointer(ec_p521_context.get(), _ec_lib.ec_ws_free_context) - p521 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 521, - "1.3.132.0.35", # SEC 2 - context, - "NIST P-521", - "ecdsa-sha2-nistp521", - EcLib) - return p521 + p = 0x000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + b = 0x00000051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00 + order = 0x000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409 + Gx = 0x000000C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66 + Gy = 0x0000011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650 + + p521_modulus = long_to_bytes(p, 66) + p521_b = long_to_bytes(b, 66) + p521_order = long_to_bytes(order, 66) + + ec_p521_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p521_context.address_of(), + c_uint8_ptr(p521_modulus), + c_uint8_ptr(p521_b), + c_uint8_ptr(p521_order), + c_size_t(len(p521_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-521 context" % result) + + context = SmartPointer(ec_p521_context.get(), _ec_lib.ec_ws_free_context) + p521 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 521, + "1.3.132.0.35", # SEC 2 + context, + "NIST P-521", + "ecdsa-sha2-nistp521", + EcLib, + ) + return p521 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_openssh.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_openssh.py index 53b16df5..a6f060f0 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_openssh.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_openssh.py @@ -38,98 +38,100 @@ def read_int4(data): - if len(data) < 4: - raise ValueError("Insufficient data") - value = struct.unpack(">I", data[:4])[0] - return value, data[4:] + if len(data) < 4: + raise ValueError("Insufficient data") + value = struct.unpack(">I", data[:4])[0] + return value, data[4:] def read_bytes(data): - size, data = read_int4(data) - if len(data) < size: - raise ValueError("Insufficient data (V)") - return data[:size], data[size:] + size, data = read_int4(data) + if len(data) < size: + raise ValueError("Insufficient data (V)") + return data[:size], data[size:] def read_string(data): - s, d = read_bytes(data) - return tostr(s), d + s, d = read_bytes(data) + return tostr(s), d def check_padding(pad): - for v, x in enumerate(pad): - if bord(x) != ((v + 1) & 0xFF): - raise ValueError("Incorrect padding") + for v, x in enumerate(pad): + if bord(x) != ((v + 1) & 0xFF): + raise ValueError("Incorrect padding") def import_openssh_private_generic(data, password): - # https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD - # https://github.com/openssh/openssh-portable/blob/master/sshkey.c - # https://coolaj86.com/articles/the-openssh-private-key-format/ - # https://coolaj86.com/articles/the-ssh-public-key-format/ - - if not data.startswith(b'openssh-key-v1\x00'): - raise ValueError("Incorrect magic value") - data = data[15:] - - ciphername, data = read_string(data) - kdfname, data = read_string(data) - kdfoptions, data = read_bytes(data) - number_of_keys, data = read_int4(data) - - if number_of_keys != 1: - raise ValueError("We only handle 1 key at a time") - - _, data = read_string(data) # Public key - encrypted, data = read_bytes(data) - if data: - raise ValueError("Too much data") - - if len(encrypted) % 8 != 0: - raise ValueError("Incorrect payload length") - - # Decrypt if necessary - if ciphername == 'none': - decrypted = encrypted - else: - if (ciphername, kdfname) != ('aes256-ctr', 'bcrypt'): - raise ValueError("Unsupported encryption scheme %s/%s" % (ciphername, kdfname)) - - salt, kdfoptions = read_bytes(kdfoptions) - iterations, kdfoptions = read_int4(kdfoptions) - - if len(salt) != 16: - raise ValueError("Incorrect salt length") - if kdfoptions: - raise ValueError("Too much data in kdfoptions") - - pwd_sha512 = SHA512.new(password).digest() - # We need 32+16 = 48 bytes, therefore 2 bcrypt outputs are sufficient - stripes = [] - constant = b"OxychromaticBlowfishSwatDynamite" - for count in range(1, 3): - salt_sha512 = SHA512.new(salt + struct.pack(">I", count)).digest() - out_le = _bcrypt_hash(pwd_sha512, 6, salt_sha512, constant, False) - out = struct.pack("IIIIIIII", out_le)) - acc = bytearray(out) - for _ in range(1, iterations): - out_le = _bcrypt_hash(pwd_sha512, 6, SHA512.new(out).digest(), constant, False) - out = struct.pack("IIIIIIII", out_le)) - strxor(acc, out, output=acc) - stripes.append(acc[:24]) - - result = b"".join([bchr(a)+bchr(b) for (a, b) in zip(*stripes)]) - - cipher = AES.new(result[:32], - AES.MODE_CTR, - nonce=b"", - initial_value=result[32:32+16]) - decrypted = cipher.decrypt(encrypted) - - checkint1, decrypted = read_int4(decrypted) - checkint2, decrypted = read_int4(decrypted) - if checkint1 != checkint2: - raise ValueError("Incorrect checksum") - ssh_name, decrypted = read_string(decrypted) - - return ssh_name, decrypted + # https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD + # https://github.com/openssh/openssh-portable/blob/master/sshkey.c + # https://coolaj86.com/articles/the-openssh-private-key-format/ + # https://coolaj86.com/articles/the-ssh-public-key-format/ + + if not data.startswith(b"openssh-key-v1\x00"): + raise ValueError("Incorrect magic value") + data = data[15:] + + ciphername, data = read_string(data) + kdfname, data = read_string(data) + kdfoptions, data = read_bytes(data) + number_of_keys, data = read_int4(data) + + if number_of_keys != 1: + raise ValueError("We only handle 1 key at a time") + + _, data = read_string(data) # Public key + encrypted, data = read_bytes(data) + if data: + raise ValueError("Too much data") + + if len(encrypted) % 8 != 0: + raise ValueError("Incorrect payload length") + + # Decrypt if necessary + if ciphername == "none": + decrypted = encrypted + else: + if (ciphername, kdfname) != ("aes256-ctr", "bcrypt"): + raise ValueError("Unsupported encryption scheme %s/%s" % (ciphername, kdfname)) + + salt, kdfoptions = read_bytes(kdfoptions) + iterations, kdfoptions = read_int4(kdfoptions) + + if len(salt) != 16: + raise ValueError("Incorrect salt length") + if kdfoptions: + raise ValueError("Too much data in kdfoptions") + + pwd_sha512 = SHA512.new(password).digest() + # We need 32+16 = 48 bytes, therefore 2 bcrypt outputs are sufficient + stripes = [] + constant = b"OxychromaticBlowfishSwatDynamite" + for count in range(1, 3): + salt_sha512 = SHA512.new(salt + struct.pack(">I", count)).digest() + out_le = _bcrypt_hash(pwd_sha512, 6, salt_sha512, constant, False) + out = struct.pack("IIIIIIII", out_le)) + acc = bytearray(out) + for _ in range(1, iterations): + out_le = _bcrypt_hash(pwd_sha512, 6, SHA512.new(out).digest(), constant, False) + out = struct.pack("IIIIIIII", out_le)) + strxor(acc, out, output=acc) + stripes.append(acc[:24]) + + result = b"".join([bchr(a) + bchr(b) for (a, b) in zip(*stripes)]) + + cipher = AES.new( + result[:32], + AES.MODE_CTR, + nonce=b"", + initial_value=result[32 : 32 + 16], + ) + decrypted = cipher.decrypt(encrypted) + + checkint1, decrypted = read_int4(decrypted) + checkint2, decrypted = read_int4(decrypted) + if checkint1 != checkint2: + raise ValueError("Incorrect checksum") + ssh_name, decrypted = read_string(decrypted) + + return ssh_name, decrypted diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_point.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_point.py index 2afce9bc..79911eee 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_point.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_point.py @@ -4,490 +4,558 @@ import threading from Cryptodome.Util.number import bytes_to_long, long_to_bytes -from Cryptodome.Util._raw_api import (VoidPointer, null_pointer, - SmartPointer, c_size_t, c_uint8_ptr, - c_ulonglong) +from Cryptodome.Util._raw_api import ( + VoidPointer, + null_pointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + c_ulonglong, +) from Cryptodome.Math.Numbers import Integer from Cryptodome.Random.random import getrandbits class CurveID(object): - P192 = 1 - P224 = 2 - P256 = 3 - P384 = 4 - P521 = 5 - ED25519 = 6 - ED448 = 7 - CURVE25519 = 8 - CURVE448 = 9 + P192 = 1 + P224 = 2 + P256 = 3 + P384 = 4 + P521 = 5 + ED25519 = 6 + ED448 = 7 + CURVE25519 = 8 + CURVE448 = 9 class _Curves(object): - - curves = {} - curves_lock = threading.RLock() - - p192_names = ["p192", "NIST P-192", "P-192", "prime192v1", "secp192r1", - "nistp192"] - p224_names = ["p224", "NIST P-224", "P-224", "prime224v1", "secp224r1", - "nistp224"] - p256_names = ["p256", "NIST P-256", "P-256", "prime256v1", "secp256r1", - "nistp256"] - p384_names = ["p384", "NIST P-384", "P-384", "prime384v1", "secp384r1", - "nistp384"] - p521_names = ["p521", "NIST P-521", "P-521", "prime521v1", "secp521r1", - "nistp521"] - ed25519_names = ["ed25519", "Ed25519"] - ed448_names = ["ed448", "Ed448"] - curve25519_names = ["curve25519", "Curve25519", "X25519"] - curve448_names = ["curve448", "Curve448", "X448"] - - all_names = p192_names + p224_names + p256_names + p384_names + p521_names + \ - ed25519_names + ed448_names + curve25519_names + curve448_names - - def __contains__(self, item): - return item in self.all_names - - def __dir__(self): - return self.all_names - - def load(self, name): - if name in self.p192_names: - from . import _nist_ecc - p192 = _nist_ecc.p192_curve() - p192.id = CurveID.P192 - self.curves.update(dict.fromkeys(self.p192_names, p192)) - elif name in self.p224_names: - from . import _nist_ecc - p224 = _nist_ecc.p224_curve() - p224.id = CurveID.P224 - self.curves.update(dict.fromkeys(self.p224_names, p224)) - elif name in self.p256_names: - from . import _nist_ecc - p256 = _nist_ecc.p256_curve() - p256.id = CurveID.P256 - self.curves.update(dict.fromkeys(self.p256_names, p256)) - elif name in self.p384_names: - from . import _nist_ecc - p384 = _nist_ecc.p384_curve() - p384.id = CurveID.P384 - self.curves.update(dict.fromkeys(self.p384_names, p384)) - elif name in self.p521_names: - from . import _nist_ecc - p521 = _nist_ecc.p521_curve() - p521.id = CurveID.P521 - self.curves.update(dict.fromkeys(self.p521_names, p521)) - elif name in self.ed25519_names: - from . import _edwards - ed25519 = _edwards.ed25519_curve() - ed25519.id = CurveID.ED25519 - self.curves.update(dict.fromkeys(self.ed25519_names, ed25519)) - elif name in self.ed448_names: - from . import _edwards - ed448 = _edwards.ed448_curve() - ed448.id = CurveID.ED448 - self.curves.update(dict.fromkeys(self.ed448_names, ed448)) - elif name in self.curve25519_names: - from . import _montgomery - curve25519 = _montgomery.curve25519_curve() - curve25519.id = CurveID.CURVE25519 - self.curves.update(dict.fromkeys(self.curve25519_names, curve25519)) - elif name in self.curve448_names: - from . import _montgomery - curve448 = _montgomery.curve448_curve() - curve448.id = CurveID.CURVE448 - self.curves.update(dict.fromkeys(self.curve448_names, curve448)) - else: - raise ValueError("Unsupported curve '%s'" % name) - return self.curves[name] - - def __getitem__(self, name): - with self.curves_lock: - curve = self.curves.get(name) - if curve is None: - curve = self.load(name) - if name in self.curve25519_names or name in self.curve448_names: - curve.G = EccXPoint(curve.Gx, name) - else: - curve.G = EccPoint(curve.Gx, curve.Gy, name) - curve.is_edwards = curve.id in (CurveID.ED25519, CurveID.ED448) - curve.is_montgomery = curve.id in (CurveID.CURVE25519, - CurveID.CURVE448) - curve.is_weierstrass = not (curve.is_edwards or - curve.is_montgomery) - return curve - - def items(self): - # Load all curves - for name in self.all_names: - _ = self[name] - return self.curves.items() + curves = {} + curves_lock = threading.RLock() + + p192_names = [ + "p192", + "NIST P-192", + "P-192", + "prime192v1", + "secp192r1", + "nistp192", + ] + p224_names = [ + "p224", + "NIST P-224", + "P-224", + "prime224v1", + "secp224r1", + "nistp224", + ] + p256_names = [ + "p256", + "NIST P-256", + "P-256", + "prime256v1", + "secp256r1", + "nistp256", + ] + p384_names = [ + "p384", + "NIST P-384", + "P-384", + "prime384v1", + "secp384r1", + "nistp384", + ] + p521_names = [ + "p521", + "NIST P-521", + "P-521", + "prime521v1", + "secp521r1", + "nistp521", + ] + ed25519_names = ["ed25519", "Ed25519"] + ed448_names = ["ed448", "Ed448"] + curve25519_names = ["curve25519", "Curve25519", "X25519"] + curve448_names = ["curve448", "Curve448", "X448"] + + all_names = ( + p192_names + + p224_names + + p256_names + + p384_names + + p521_names + + ed25519_names + + ed448_names + + curve25519_names + + curve448_names + ) + + def __contains__(self, item): + return item in self.all_names + + def __dir__(self): + return self.all_names + + def load(self, name): + if name in self.p192_names: + from . import _nist_ecc + + p192 = _nist_ecc.p192_curve() + p192.id = CurveID.P192 + self.curves.update(dict.fromkeys(self.p192_names, p192)) + elif name in self.p224_names: + from . import _nist_ecc + + p224 = _nist_ecc.p224_curve() + p224.id = CurveID.P224 + self.curves.update(dict.fromkeys(self.p224_names, p224)) + elif name in self.p256_names: + from . import _nist_ecc + + p256 = _nist_ecc.p256_curve() + p256.id = CurveID.P256 + self.curves.update(dict.fromkeys(self.p256_names, p256)) + elif name in self.p384_names: + from . import _nist_ecc + + p384 = _nist_ecc.p384_curve() + p384.id = CurveID.P384 + self.curves.update(dict.fromkeys(self.p384_names, p384)) + elif name in self.p521_names: + from . import _nist_ecc + + p521 = _nist_ecc.p521_curve() + p521.id = CurveID.P521 + self.curves.update(dict.fromkeys(self.p521_names, p521)) + elif name in self.ed25519_names: + from . import _edwards + + ed25519 = _edwards.ed25519_curve() + ed25519.id = CurveID.ED25519 + self.curves.update(dict.fromkeys(self.ed25519_names, ed25519)) + elif name in self.ed448_names: + from . import _edwards + + ed448 = _edwards.ed448_curve() + ed448.id = CurveID.ED448 + self.curves.update(dict.fromkeys(self.ed448_names, ed448)) + elif name in self.curve25519_names: + from . import _montgomery + + curve25519 = _montgomery.curve25519_curve() + curve25519.id = CurveID.CURVE25519 + self.curves.update(dict.fromkeys(self.curve25519_names, curve25519)) + elif name in self.curve448_names: + from . import _montgomery + + curve448 = _montgomery.curve448_curve() + curve448.id = CurveID.CURVE448 + self.curves.update(dict.fromkeys(self.curve448_names, curve448)) + else: + raise ValueError("Unsupported curve '%s'" % name) + return self.curves[name] + + def __getitem__(self, name): + with self.curves_lock: + curve = self.curves.get(name) + if curve is None: + curve = self.load(name) + if name in self.curve25519_names or name in self.curve448_names: + curve.G = EccXPoint(curve.Gx, name) + else: + curve.G = EccPoint(curve.Gx, curve.Gy, name) + curve.is_edwards = curve.id in (CurveID.ED25519, CurveID.ED448) + curve.is_montgomery = curve.id in ( + CurveID.CURVE25519, + CurveID.CURVE448, + ) + curve.is_weierstrass = not (curve.is_edwards or curve.is_montgomery) + return curve + + def items(self): + # Load all curves + for name in self.all_names: + _ = self[name] + return self.curves.items() _curves = _Curves() class EccPoint(object): - """A class to model a point on an Elliptic Curve. - - The class supports operators for: - - * Adding two points: ``R = S + T`` - * In-place addition: ``S += T`` - * Negating a point: ``R = -T`` - * Comparing two points: ``if S == T: ...`` or ``if S != T: ...`` - * Multiplying a point by a scalar: ``R = S*k`` - * In-place multiplication by a scalar: ``T *= k`` - - :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. - :vartype curve: string - - :ivar x: The affine X-coordinate of the ECC point - :vartype x: integer - - :ivar y: The affine Y-coordinate of the ECC point - :vartype y: integer - - :ivar xy: The tuple with affine X- and Y- coordinates - """ - - def __init__(self, x, y, curve="p256"): - - try: - self._curve = _curves[curve] - except KeyError: - raise ValueError("Unknown curve name %s" % str(curve)) - self.curve = self._curve.canonical - - if self._curve.id == CurveID.CURVE25519: - raise ValueError("EccPoint cannot be created for Curve25519") - - modulus_bytes = self.size_in_bytes() - - xb = long_to_bytes(x, modulus_bytes) - yb = long_to_bytes(y, modulus_bytes) - if len(xb) != modulus_bytes or len(yb) != modulus_bytes: - raise ValueError("Incorrect coordinate length") - - new_point = self._curve.rawlib.new_point - free_func = self._curve.rawlib.free_point - - self._point = VoidPointer() - try: - context = self._curve.context.get() - except AttributeError: - context = null_pointer - result = new_point(self._point.address_of(), - c_uint8_ptr(xb), - c_uint8_ptr(yb), - c_size_t(modulus_bytes), - context) - - if result: - if result == 15: - raise ValueError("The EC point does not belong to the curve") - raise ValueError("Error %d while instantiating an EC point" % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the EC point - self._point = SmartPointer(self._point.get(), free_func) - - def set(self, point): - clone = self._curve.rawlib.clone - free_func = self._curve.rawlib.free_point - - self._point = VoidPointer() - result = clone(self._point.address_of(), - point._point.get()) - - if result: - raise ValueError("Error %d while cloning an EC point" % result) - - self._point = SmartPointer(self._point.get(), free_func) - return self - - def __eq__(self, point): - if not isinstance(point, EccPoint): - return False - - cmp_func = self._curve.rawlib.cmp - return 0 == cmp_func(self._point.get(), point._point.get()) - - # Only needed for Python 2 - def __ne__(self, point): - return not self == point - - def __neg__(self): - neg_func = self._curve.rawlib.neg - np = self.copy() - result = neg_func(np._point.get()) - if result: - raise ValueError("Error %d while inverting an EC point" % result) - return np - - def copy(self): - """Return a copy of this point.""" - x, y = self.xy - np = EccPoint(x, y, self.curve) - return np - - def is_point_at_infinity(self): - """``True`` if this is the *point-at-infinity*.""" - - if self._curve.is_edwards: - return self.x == 0 - else: - return self.xy == (0, 0) - - def point_at_infinity(self): - """Return the *point-at-infinity* for the curve.""" - - if self._curve.is_edwards: - return EccPoint(0, 1, self.curve) - else: - return EccPoint(0, 0, self.curve) - - @property - def x(self): - return self.xy[0] - - @property - def y(self): - return self.xy[1] - - @property - def xy(self): - modulus_bytes = self.size_in_bytes() - xb = bytearray(modulus_bytes) - yb = bytearray(modulus_bytes) - get_xy = self._curve.rawlib.get_xy - result = get_xy(c_uint8_ptr(xb), - c_uint8_ptr(yb), - c_size_t(modulus_bytes), - self._point.get()) - if result: - raise ValueError("Error %d while encoding an EC point" % result) - - return (Integer(bytes_to_long(xb)), Integer(bytes_to_long(yb))) - - def size_in_bytes(self): - """Size of each coordinate, in bytes.""" - return (self.size_in_bits() + 7) // 8 - - def size_in_bits(self): - """Size of each coordinate, in bits.""" - return self._curve.modulus_bits - - def double(self): - """Double this point (in-place operation). - - Returns: - This same object (to enable chaining). - """ - - double_func = self._curve.rawlib.double - result = double_func(self._point.get()) - if result: - raise ValueError("Error %d while doubling an EC point" % result) - return self - - def __iadd__(self, point): - """Add a second point to this one""" - - add_func = self._curve.rawlib.add - result = add_func(self._point.get(), point._point.get()) - if result: - if result == 16: - raise ValueError("EC points are not on the same curve") - raise ValueError("Error %d while adding two EC points" % result) - return self - - def __add__(self, point): - """Return a new point, the addition of this one and another""" - - np = self.copy() - np += point - return np - - def __imul__(self, scalar): - """Multiply this point by a scalar""" - - scalar_func = self._curve.rawlib.scalar - if scalar < 0: - raise ValueError("Scalar multiplication is only defined for non-negative integers") - sb = long_to_bytes(scalar) - result = scalar_func(self._point.get(), - c_uint8_ptr(sb), - c_size_t(len(sb)), - c_ulonglong(getrandbits(64))) - if result: - raise ValueError("Error %d during scalar multiplication" % result) - return self - - def __mul__(self, scalar): - """Return a new point, the scalar product of this one""" - - np = self.copy() - np *= scalar - return np - - def __rmul__(self, left_hand): - return self.__mul__(left_hand) + """A class to model a point on an Elliptic Curve. + + The class supports operators for: + + * Adding two points: ``R = S + T`` + * In-place addition: ``S += T`` + * Negating a point: ``R = -T`` + * Comparing two points: ``if S == T: ...`` or ``if S != T: ...`` + * Multiplying a point by a scalar: ``R = S*k`` + * In-place multiplication by a scalar: ``T *= k`` + + :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. + :vartype curve: string + + :ivar x: The affine X-coordinate of the ECC point + :vartype x: integer + + :ivar y: The affine Y-coordinate of the ECC point + :vartype y: integer + + :ivar xy: The tuple with affine X- and Y- coordinates + """ + + def __init__(self, x, y, curve="p256"): + try: + self._curve = _curves[curve] + except KeyError: + raise ValueError("Unknown curve name %s" % str(curve)) + self.curve = self._curve.canonical + + if self._curve.id == CurveID.CURVE25519: + raise ValueError("EccPoint cannot be created for Curve25519") + + modulus_bytes = self.size_in_bytes() + + xb = long_to_bytes(x, modulus_bytes) + yb = long_to_bytes(y, modulus_bytes) + if len(xb) != modulus_bytes or len(yb) != modulus_bytes: + raise ValueError("Incorrect coordinate length") + + new_point = self._curve.rawlib.new_point + free_func = self._curve.rawlib.free_point + + self._point = VoidPointer() + try: + context = self._curve.context.get() + except AttributeError: + context = null_pointer + result = new_point( + self._point.address_of(), + c_uint8_ptr(xb), + c_uint8_ptr(yb), + c_size_t(modulus_bytes), + context, + ) + + if result: + if result == 15: + raise ValueError("The EC point does not belong to the curve") + raise ValueError("Error %d while instantiating an EC point" % result) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the EC point + self._point = SmartPointer(self._point.get(), free_func) + + def set(self, point): + clone = self._curve.rawlib.clone + free_func = self._curve.rawlib.free_point + + self._point = VoidPointer() + result = clone( + self._point.address_of(), + point._point.get(), + ) + + if result: + raise ValueError("Error %d while cloning an EC point" % result) + + self._point = SmartPointer(self._point.get(), free_func) + return self + + def __eq__(self, point): + if not isinstance(point, EccPoint): + return False + + cmp_func = self._curve.rawlib.cmp + return 0 == cmp_func(self._point.get(), point._point.get()) + + # Only needed for Python 2 + def __ne__(self, point): + return not self == point + + def __neg__(self): + neg_func = self._curve.rawlib.neg + np = self.copy() + result = neg_func(np._point.get()) + if result: + raise ValueError("Error %d while inverting an EC point" % result) + return np + + def copy(self): + """Return a copy of this point.""" + x, y = self.xy + np = EccPoint(x, y, self.curve) + return np + + def is_point_at_infinity(self): + """``True`` if this is the *point-at-infinity*.""" + + if self._curve.is_edwards: + return self.x == 0 + else: + return self.xy == (0, 0) + + def point_at_infinity(self): + """Return the *point-at-infinity* for the curve.""" + + if self._curve.is_edwards: + return EccPoint(0, 1, self.curve) + else: + return EccPoint(0, 0, self.curve) + + @property + def x(self): + return self.xy[0] + + @property + def y(self): + return self.xy[1] + + @property + def xy(self): + modulus_bytes = self.size_in_bytes() + xb = bytearray(modulus_bytes) + yb = bytearray(modulus_bytes) + get_xy = self._curve.rawlib.get_xy + result = get_xy( + c_uint8_ptr(xb), + c_uint8_ptr(yb), + c_size_t(modulus_bytes), + self._point.get(), + ) + if result: + raise ValueError("Error %d while encoding an EC point" % result) + + return (Integer(bytes_to_long(xb)), Integer(bytes_to_long(yb))) + + def size_in_bytes(self): + """Size of each coordinate, in bytes.""" + return (self.size_in_bits() + 7) // 8 + + def size_in_bits(self): + """Size of each coordinate, in bits.""" + return self._curve.modulus_bits + + def double(self): + """Double this point (in-place operation). + + Returns: + This same object (to enable chaining). + """ + + double_func = self._curve.rawlib.double + result = double_func(self._point.get()) + if result: + raise ValueError("Error %d while doubling an EC point" % result) + return self + + def __iadd__(self, point): + """Add a second point to this one""" + + add_func = self._curve.rawlib.add + result = add_func(self._point.get(), point._point.get()) + if result: + if result == 16: + raise ValueError("EC points are not on the same curve") + raise ValueError("Error %d while adding two EC points" % result) + return self + + def __add__(self, point): + """Return a new point, the addition of this one and another""" + + np = self.copy() + np += point + return np + + def __imul__(self, scalar): + """Multiply this point by a scalar""" + + scalar_func = self._curve.rawlib.scalar + if scalar < 0: + raise ValueError("Scalar multiplication is only defined for non-negative integers") + sb = long_to_bytes(scalar) + result = scalar_func( + self._point.get(), + c_uint8_ptr(sb), + c_size_t(len(sb)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ValueError("Error %d during scalar multiplication" % result) + return self + + def __mul__(self, scalar): + """Return a new point, the scalar product of this one""" + + np = self.copy() + np *= scalar + return np + + def __rmul__(self, left_hand): + return self.__mul__(left_hand) class EccXPoint(object): - """A class to model a point on an Elliptic Curve, - where only the X-coordinate is exposed. - - The class supports operators for: - - * Multiplying a point by a scalar: ``R = S*k`` - * In-place multiplication by a scalar: ``T *= k`` - - :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. - :vartype curve: string - - :ivar x: The affine X-coordinate of the ECC point - :vartype x: integer - """ - - def __init__(self, x, curve): - # Once encoded, x must not exceed the length of the modulus, - # but its value may match or exceed the modulus itself - # (i.e., non-canonical value) - - try: - self._curve = _curves[curve] - except KeyError: - raise ValueError("Unknown curve name %s" % str(curve)) - self.curve = self._curve.canonical - - if self._curve.id not in (CurveID.CURVE25519, CurveID.CURVE448): - raise ValueError("EccXPoint can only be created for Curve25519/Curve448") - - new_point = self._curve.rawlib.new_point - free_func = self._curve.rawlib.free_point - - self._point = VoidPointer() - try: - context = self._curve.context.get() - except AttributeError: - context = null_pointer - - modulus_bytes = self.size_in_bytes() - - if x is None: - xb = null_pointer - else: - xb = c_uint8_ptr(long_to_bytes(x, modulus_bytes)) - if len(xb) != modulus_bytes: - raise ValueError("Incorrect coordinate length") - - self._point = VoidPointer() - result = new_point(self._point.address_of(), - xb, - c_size_t(modulus_bytes), - context) - - if result == 15: - raise ValueError("The EC point does not belong to the curve") - if result: - raise ValueError("Error %d while instantiating an EC point" % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the EC point - self._point = SmartPointer(self._point.get(), free_func) - - def set(self, point): - clone = self._curve.rawlib.clone - free_func = self._curve.rawlib.free_point - - self._point = VoidPointer() - result = clone(self._point.address_of(), - point._point.get()) - if result: - raise ValueError("Error %d while cloning an EC point" % result) - - self._point = SmartPointer(self._point.get(), free_func) - return self - - def __eq__(self, point): - if not isinstance(point, EccXPoint): - return False - - cmp_func = self._curve.rawlib.cmp - p1 = self._point.get() - p2 = point._point.get() - res = cmp_func(p1, p2) - return 0 == res - - def copy(self): - """Return a copy of this point.""" - - try: - x = self.x - except ValueError: - return self.point_at_infinity() - return EccXPoint(x, self.curve) - - def is_point_at_infinity(self): - """``True`` if this is the *point-at-infinity*.""" - - try: - _ = self.x - except ValueError: - return True - return False - - def point_at_infinity(self): - """Return the *point-at-infinity* for the curve.""" - - return EccXPoint(None, self.curve) - - @property - def x(self): - modulus_bytes = self.size_in_bytes() - xb = bytearray(modulus_bytes) - get_x = self._curve.rawlib.get_x - result = get_x(c_uint8_ptr(xb), - c_size_t(modulus_bytes), - self._point.get()) - if result == 19: # ERR_ECC_PAI - raise ValueError("No X coordinate for the point at infinity") - if result: - raise ValueError("Error %d while getting X of an EC point" % result) - return Integer(bytes_to_long(xb)) - - def size_in_bytes(self): - """Size of each coordinate, in bytes.""" - return (self.size_in_bits() + 7) // 8 - - def size_in_bits(self): - """Size of each coordinate, in bits.""" - return self._curve.modulus_bits - - def __imul__(self, scalar): - """Multiply this point by a scalar""" - - scalar_func = self._curve.rawlib.scalar - if scalar < 0: - raise ValueError("Scalar multiplication is only defined for non-negative integers") - sb = long_to_bytes(scalar) - result = scalar_func(self._point.get(), - c_uint8_ptr(sb), - c_size_t(len(sb)), - c_ulonglong(getrandbits(64))) - if result: - raise ValueError("Error %d during scalar multiplication" % result) - return self - - def __mul__(self, scalar): - """Return a new point, the scalar product of this one""" - - np = self.copy() - np *= scalar - return np - - def __rmul__(self, left_hand): - return self.__mul__(left_hand) + """A class to model a point on an Elliptic Curve, + where only the X-coordinate is exposed. + + The class supports operators for: + + * Multiplying a point by a scalar: ``R = S*k`` + * In-place multiplication by a scalar: ``T *= k`` + + :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. + :vartype curve: string + + :ivar x: The affine X-coordinate of the ECC point + :vartype x: integer + """ + + def __init__(self, x, curve): + # Once encoded, x must not exceed the length of the modulus, + # but its value may match or exceed the modulus itself + # (i.e., non-canonical value) + + try: + self._curve = _curves[curve] + except KeyError: + raise ValueError("Unknown curve name %s" % str(curve)) + self.curve = self._curve.canonical + + if self._curve.id not in (CurveID.CURVE25519, CurveID.CURVE448): + raise ValueError("EccXPoint can only be created for Curve25519/Curve448") + + new_point = self._curve.rawlib.new_point + free_func = self._curve.rawlib.free_point + + self._point = VoidPointer() + try: + context = self._curve.context.get() + except AttributeError: + context = null_pointer + + modulus_bytes = self.size_in_bytes() + + if x is None: + xb = null_pointer + else: + xb = c_uint8_ptr(long_to_bytes(x, modulus_bytes)) + if len(xb) != modulus_bytes: + raise ValueError("Incorrect coordinate length") + + self._point = VoidPointer() + result = new_point( + self._point.address_of(), + xb, + c_size_t(modulus_bytes), + context, + ) + + if result == 15: + raise ValueError("The EC point does not belong to the curve") + if result: + raise ValueError("Error %d while instantiating an EC point" % result) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the EC point + self._point = SmartPointer(self._point.get(), free_func) + + def set(self, point): + clone = self._curve.rawlib.clone + free_func = self._curve.rawlib.free_point + + self._point = VoidPointer() + result = clone( + self._point.address_of(), + point._point.get(), + ) + if result: + raise ValueError("Error %d while cloning an EC point" % result) + + self._point = SmartPointer(self._point.get(), free_func) + return self + + def __eq__(self, point): + if not isinstance(point, EccXPoint): + return False + + cmp_func = self._curve.rawlib.cmp + p1 = self._point.get() + p2 = point._point.get() + res = cmp_func(p1, p2) + return 0 == res + + def copy(self): + """Return a copy of this point.""" + + try: + x = self.x + except ValueError: + return self.point_at_infinity() + return EccXPoint(x, self.curve) + + def is_point_at_infinity(self): + """``True`` if this is the *point-at-infinity*.""" + + try: + _ = self.x + except ValueError: + return True + return False + + def point_at_infinity(self): + """Return the *point-at-infinity* for the curve.""" + + return EccXPoint(None, self.curve) + + @property + def x(self): + modulus_bytes = self.size_in_bytes() + xb = bytearray(modulus_bytes) + get_x = self._curve.rawlib.get_x + result = get_x( + c_uint8_ptr(xb), + c_size_t(modulus_bytes), + self._point.get(), + ) + if result == 19: # ERR_ECC_PAI + raise ValueError("No X coordinate for the point at infinity") + if result: + raise ValueError("Error %d while getting X of an EC point" % result) + return Integer(bytes_to_long(xb)) + + def size_in_bytes(self): + """Size of each coordinate, in bytes.""" + return (self.size_in_bits() + 7) // 8 + + def size_in_bits(self): + """Size of each coordinate, in bits.""" + return self._curve.modulus_bits + + def __imul__(self, scalar): + """Multiply this point by a scalar""" + + scalar_func = self._curve.rawlib.scalar + if scalar < 0: + raise ValueError("Scalar multiplication is only defined for non-negative integers") + sb = long_to_bytes(scalar) + result = scalar_func( + self._point.get(), + c_uint8_ptr(sb), + c_size_t(len(sb)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ValueError("Error %d during scalar multiplication" % result) + return self + + def __mul__(self, scalar): + """Return a new point, the scalar product of this one""" + + np = self.copy() + np *= scalar + return np + + def __rmul__(self, left_hand): + return self.__mul__(left_hand) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_point.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_point.pyi index 2518e2e4..3a9ac6cd 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_point.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/PublicKey/_point.pyi @@ -3,47 +3,42 @@ from typing import Union, Optional, Tuple from Cryptodome.Math.Numbers import Integer class EccPoint(object): - curve: str - def __init__(self, - x: Union[int, Integer], - y: Union[int, Integer], - curve: Optional[str] = ...) -> None: ... - - def set(self, point: EccPoint) -> EccPoint: ... - def __eq__(self, point: object) -> bool: ... - def __neg__(self) -> EccPoint: ... - def copy(self) -> EccPoint: ... - def is_point_at_infinity(self) -> bool: ... - def point_at_infinity(self) -> EccPoint: ... - @property - def x(self) -> int: ... - @property - def y(self) -> int: ... - @property - def xy(self) -> Tuple[int, int]: ... - def size_in_bytes(self) -> int: ... - def size_in_bits(self) -> int: ... - def double(self) -> EccPoint: ... - def __iadd__(self, point: EccPoint) -> EccPoint: ... - def __add__(self, point: EccPoint) -> EccPoint: ... - def __imul__(self, scalar: int) -> EccPoint: ... - def __mul__(self, scalar: int) -> EccPoint: ... - + curve: str + def __init__( + self, x: Union[int, Integer], y: Union[int, Integer], curve: Optional[str] = ... + ) -> None: ... + def set(self, point: EccPoint) -> EccPoint: ... + def __eq__(self, point: object) -> bool: ... + def __neg__(self) -> EccPoint: ... + def copy(self) -> EccPoint: ... + def is_point_at_infinity(self) -> bool: ... + def point_at_infinity(self) -> EccPoint: ... + @property + def x(self) -> int: ... + @property + def y(self) -> int: ... + @property + def xy(self) -> Tuple[int, int]: ... + def size_in_bytes(self) -> int: ... + def size_in_bits(self) -> int: ... + def double(self) -> EccPoint: ... + def __iadd__(self, point: EccPoint) -> EccPoint: ... + def __add__(self, point: EccPoint) -> EccPoint: ... + def __imul__(self, scalar: int) -> EccPoint: ... + def __mul__(self, scalar: int) -> EccPoint: ... class EccXPoint(object): - curve: str - def __init__(self, - x: Union[int, Integer], - curve: Optional[str] = ...) -> None: ... - def set(self, point: EccXPoint) -> EccXPoint: ... - def __eq__(self, point: object) -> bool: ... - def copy(self) -> EccXPoint: ... - def is_point_at_infinity(self) -> bool: ... - def point_at_infinity(self) -> EccXPoint: ... - @property - def x(self) -> int: ... - def size_in_bytes(self) -> int: ... - def size_in_bits(self) -> int: ... - def __imul__(self, scalar: int) -> EccXPoint: ... - def __mul__(self, scalar: int) -> EccXPoint: ... - def __rmul__(self, left_hand: int) -> EccXPoint: ... + curve: str + def __init__(self, x: Union[int, Integer], curve: Optional[str] = ...) -> None: ... + def set(self, point: EccXPoint) -> EccXPoint: ... + def __eq__(self, point: object) -> bool: ... + def copy(self) -> EccXPoint: ... + def is_point_at_infinity(self) -> bool: ... + def point_at_infinity(self) -> EccXPoint: ... + @property + def x(self) -> int: ... + def size_in_bytes(self) -> int: ... + def size_in_bits(self) -> int: ... + def __imul__(self, scalar: int) -> EccXPoint: ... + def __mul__(self, scalar: int) -> EccXPoint: ... + def __rmul__(self, left_hand: int) -> EccXPoint: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/__init__.py index fd18d864..860ef73c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/__init__.py @@ -20,38 +20,37 @@ # SOFTWARE. # =================================================================== -__all__ = ['new', 'get_random_bytes'] +__all__ = ["new", "get_random_bytes"] from os import urandom + class _UrandomRNG(object): + def read(self, n): + """Return a random byte string of the desired size.""" + return urandom(n) - def read(self, n): - """Return a random byte string of the desired size.""" - return urandom(n) + def flush(self): + """Method provided for backward compatibility only.""" + pass - def flush(self): - """Method provided for backward compatibility only.""" - pass + def reinit(self): + """Method provided for backward compatibility only.""" + pass - def reinit(self): - """Method provided for backward compatibility only.""" - pass + def close(self): + """Method provided for backward compatibility only.""" + pass - def close(self): - """Method provided for backward compatibility only.""" - pass - def new(*args, **kwargs): - """Return a file-like object that outputs cryptographically random bytes.""" - return _UrandomRNG() + """Return a file-like object that outputs cryptographically random bytes.""" + return _UrandomRNG() def atfork(): - pass + pass #: Function that returns a random byte string of the desired size. get_random_bytes = urandom - diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/__init__.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/__init__.pyi index ddc5b9b0..1cb3dd15 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/__init__.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/__init__.pyi @@ -1,19 +1,16 @@ from typing import Any -__all__ = ['new', 'get_random_bytes'] +__all__ = ["new", "get_random_bytes"] from os import urandom class _UrandomRNG(object): - - def read(self, n: int) -> bytes:... - def flush(self) -> None: ... - def reinit(self) -> None: ... - def close(self) -> None: ... + def read(self, n: int) -> bytes: ... + def flush(self) -> None: ... + def reinit(self) -> None: ... + def close(self) -> None: ... def new(*args: Any, **kwargs: Any) -> _UrandomRNG: ... - def atfork() -> None: ... get_random_bytes = urandom - diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/random.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/random.py index da307957..bc096715 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/random.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/random.py @@ -22,107 +22,108 @@ # SOFTWARE. # =================================================================== -__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample'] +__all__ = ["StrongRandom", "getrandbits", "randrange", "randint", "choice", "shuffle", "sample"] from Cryptodome import Random from Cryptodome.Util.py3compat import is_native_int + class StrongRandom(object): - def __init__(self, rng=None, randfunc=None): - if randfunc is None and rng is None: - self._randfunc = None - elif randfunc is not None and rng is None: - self._randfunc = randfunc - elif randfunc is None and rng is not None: - self._randfunc = rng.read - else: - raise ValueError("Cannot specify both 'rng' and 'randfunc'") - - def getrandbits(self, k): - """Return an integer with k random bits.""" - - if self._randfunc is None: - self._randfunc = Random.new().read - mask = (1 << k) - 1 - return mask & bytes_to_long(self._randfunc(ceil_div(k, 8))) - - def randrange(self, *args): - """randrange([start,] stop[, step]): - Return a randomly-selected element from range(start, stop, step).""" - if len(args) == 3: - (start, stop, step) = args - elif len(args) == 2: - (start, stop) = args - step = 1 - elif len(args) == 1: - (stop,) = args - start = 0 - step = 1 - else: - raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),)) - if (not is_native_int(start) or not is_native_int(stop) or not - is_native_int(step)): - raise TypeError("randrange requires integer arguments") - if step == 0: - raise ValueError("randrange step argument must not be zero") - - num_choices = ceil_div(stop - start, step) - if num_choices < 0: - num_choices = 0 - if num_choices < 1: - raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step)) - - # Pick a random number in the range of possible numbers - r = num_choices - while r >= num_choices: - r = self.getrandbits(size(num_choices)) - - return start + (step * r) - - def randint(self, a, b): - """Return a random integer N such that a <= N <= b.""" - if not is_native_int(a) or not is_native_int(b): - raise TypeError("randint requires integer arguments") - N = self.randrange(a, b+1) - assert a <= N <= b - return N - - def choice(self, seq): - """Return a random element from a (non-empty) sequence. - - If the seqence is empty, raises IndexError. - """ - if len(seq) == 0: - raise IndexError("empty sequence") - return seq[self.randrange(len(seq))] - - def shuffle(self, x): - """Shuffle the sequence in place.""" - # Fisher-Yates shuffle. O(n) - # See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle - # Working backwards from the end of the array, we choose a random item - # from the remaining items until all items have been chosen. - for i in range(len(x)-1, 0, -1): # iterate from len(x)-1 downto 1 - j = self.randrange(0, i+1) # choose random j such that 0 <= j <= i - x[i], x[j] = x[j], x[i] # exchange x[i] and x[j] - - def sample(self, population, k): - """Return a k-length list of unique elements chosen from the population sequence.""" - - num_choices = len(population) - if k > num_choices: - raise ValueError("sample larger than population") - - retval = [] - selected = {} # we emulate a set using a dict here - for i in range(k): - r = None - while r is None or r in selected: - r = self.randrange(num_choices) - retval.append(population[r]) - selected[r] = 1 - return retval + def __init__(self, rng=None, randfunc=None): + if randfunc is None and rng is None: + self._randfunc = None + elif randfunc is not None and rng is None: + self._randfunc = randfunc + elif randfunc is None and rng is not None: + self._randfunc = rng.read + else: + raise ValueError("Cannot specify both 'rng' and 'randfunc'") + + def getrandbits(self, k): + """Return an integer with k random bits.""" + + if self._randfunc is None: + self._randfunc = Random.new().read + mask = (1 << k) - 1 + return mask & bytes_to_long(self._randfunc(ceil_div(k, 8))) + + def randrange(self, *args): + """randrange([start,] stop[, step]): + Return a randomly-selected element from range(start, stop, step).""" + if len(args) == 3: + (start, stop, step) = args + elif len(args) == 2: + (start, stop) = args + step = 1 + elif len(args) == 1: + (stop,) = args + start = 0 + step = 1 + else: + raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),)) + if not is_native_int(start) or not is_native_int(stop) or not is_native_int(step): + raise TypeError("randrange requires integer arguments") + if step == 0: + raise ValueError("randrange step argument must not be zero") + + num_choices = ceil_div(stop - start, step) + if num_choices < 0: + num_choices = 0 + if num_choices < 1: + raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step)) + + # Pick a random number in the range of possible numbers + r = num_choices + while r >= num_choices: + r = self.getrandbits(size(num_choices)) + + return start + (step * r) + + def randint(self, a, b): + """Return a random integer N such that a <= N <= b.""" + if not is_native_int(a) or not is_native_int(b): + raise TypeError("randint requires integer arguments") + N = self.randrange(a, b + 1) + assert a <= N <= b + return N + + def choice(self, seq): + """Return a random element from a (non-empty) sequence. + + If the seqence is empty, raises IndexError. + """ + if len(seq) == 0: + raise IndexError("empty sequence") + return seq[self.randrange(len(seq))] + + def shuffle(self, x): + """Shuffle the sequence in place.""" + # Fisher-Yates shuffle. O(n) + # See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + # Working backwards from the end of the array, we choose a random item + # from the remaining items until all items have been chosen. + for i in range(len(x) - 1, 0, -1): # iterate from len(x)-1 downto 1 + j = self.randrange(0, i + 1) # choose random j such that 0 <= j <= i + x[i], x[j] = x[j], x[i] # exchange x[i] and x[j] + + def sample(self, population, k): + """Return a k-length list of unique elements chosen from the population sequence.""" + + num_choices = len(population) + if k > num_choices: + raise ValueError("sample larger than population") + + retval = [] + selected = {} # we emulate a set using a dict here + for i in range(k): + r = None + while r is None or r in selected: + r = self.randrange(num_choices) + retval.append(population[r]) + selected[r] = 1 + return retval + _r = StrongRandom() getrandbits = _r.getrandbits @@ -133,6 +134,6 @@ def sample(self, population, k): sample = _r.sample # These are at the bottom to avoid problems with recursive imports -from Cryptodome.Util.number import ceil_div, bytes_to_long, long_to_bytes, size +from Cryptodome.Util.number import ceil_div, bytes_to_long, size # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/random.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/random.pyi index 9b7cf7ee..dac98082 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/random.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Random/random.pyi @@ -1,17 +1,19 @@ -from typing import Callable, Tuple, Union, Sequence, Any, Optional, TypeVar +from typing import Callable, Sequence, Any, Optional, TypeVar -__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample'] +__all__ = ["StrongRandom", "getrandbits", "randrange", "randint", "choice", "shuffle", "sample"] -T = TypeVar('T') +T = TypeVar("T") class StrongRandom(object): - def __init__(self, rng: Optional[Any]=None, randfunc: Optional[Callable]=None) -> None: ... # TODO What is rng? - def getrandbits(self, k: int) -> int: ... - def randrange(self, start: int, stop: int = ..., step: int = ...) -> int: ... - def randint(self, a: int, b: int) -> int: ... - def choice(self, seq: Sequence[T]) -> T: ... - def shuffle(self, x: Sequence) -> None: ... - def sample(self, population: Sequence, k: int) -> list: ... + def __init__( + self, rng: Optional[Any] = None, randfunc: Optional[Callable] = None + ) -> None: ... # TODO What is rng? + def getrandbits(self, k: int) -> int: ... + def randrange(self, start: int, stop: int = ..., step: int = ...) -> int: ... + def randint(self, a: int, b: int) -> int: ... + def choice(self, seq: Sequence[T]) -> T: ... + def shuffle(self, x: Sequence) -> None: ... + def sample(self, population: Sequence, k: int) -> list: ... _r = StrongRandom() getrandbits = _r.getrandbits diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/__init__.py index 40f865d1..ff43a4a3 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/__init__.py @@ -28,37 +28,84 @@ def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Cipher import test_AES; tests += test_AES.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_ARC2; tests += test_ARC2.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_ARC4; tests += test_ARC4.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_Blowfish; tests += test_Blowfish.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CAST; tests += test_CAST.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_DES3; tests += test_DES3.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_DES; tests += test_DES.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_Salsa20; tests += test_Salsa20.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_ChaCha20; tests += test_ChaCha20.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_ChaCha20_Poly1305; tests += test_ChaCha20_Poly1305.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_pkcs1_15; tests += test_pkcs1_15.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_pkcs1_oaep; tests += test_pkcs1_oaep.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_OCB; tests += test_OCB.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CBC; tests += test_CBC.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CFB; tests += test_CFB.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_OpenPGP; tests += test_OpenPGP.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_OFB; tests += test_OFB.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CTR; tests += test_CTR.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CCM; tests += test_CCM.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_EAX; tests += test_EAX.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_GCM; tests += test_GCM.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_SIV; tests += test_SIV.get_tests(config=config) - - if sys.version_info >= (3, 9): - from Cryptodome.SelfTest.Cipher import test_KW - tests += test_KW.get_tests(config=config) - - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + from Cryptodome.SelfTest.Cipher import test_AES + + tests += test_AES.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_ARC2 + + tests += test_ARC2.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_ARC4 + + tests += test_ARC4.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_Blowfish + + tests += test_Blowfish.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CAST + + tests += test_CAST.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_DES3 + + tests += test_DES3.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_DES + + tests += test_DES.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_Salsa20 + + tests += test_Salsa20.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_ChaCha20 + + tests += test_ChaCha20.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_ChaCha20_Poly1305 + + tests += test_ChaCha20_Poly1305.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_pkcs1_15 + + tests += test_pkcs1_15.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_pkcs1_oaep + + tests += test_pkcs1_oaep.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_OCB + + tests += test_OCB.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CBC + + tests += test_CBC.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CFB + + tests += test_CFB.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_OpenPGP + + tests += test_OpenPGP.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_OFB + + tests += test_OFB.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CTR + + tests += test_CTR.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CCM + + tests += test_CCM.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_EAX + + tests += test_EAX.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_GCM + + tests += test_GCM.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_SIV + + tests += test_SIV.get_tests(config=config) + + if sys.version_info >= (3, 9): + from Cryptodome.SelfTest.Cipher import test_KW + + tests += test_KW.get_tests(config=config) + + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/common.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/common.py index a13d4fbe..303fdecb 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/common.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/common.py @@ -25,486 +25,506 @@ """Self-testing for PyCryptodome hash modules""" import unittest -from binascii import a2b_hex, b2a_hex, hexlify +from binascii import a2b_hex, b2a_hex from Cryptodome.Util.py3compat import b -from Cryptodome.Util.strxor import strxor_c -class _NoDefault: pass # sentinel object -def _extract(d, k, default=_NoDefault): - """Get an item from a dictionary, and remove it from the dictionary.""" - try: - retval = d[k] - except KeyError: - if default is _NoDefault: - raise - return default - del d[k] - return retval - -# Generic cipher test case -class CipherSelfTest(unittest.TestCase): - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - - # Extract the parameters - params = params.copy() - self.description = _extract(params, 'description') - self.key = b(_extract(params, 'key')) - self.plaintext = b(_extract(params, 'plaintext')) - self.ciphertext = b(_extract(params, 'ciphertext')) - self.module_name = _extract(params, 'module_name', None) - self.assoc_data = _extract(params, 'assoc_data', None) - self.mac = _extract(params, 'mac', None) - if self.assoc_data: - self.mac = b(self.mac) - - mode = _extract(params, 'mode', None) - self.mode_name = str(mode) - - if mode is not None: - # Block cipher - self.mode = getattr(self.module, "MODE_" + mode) - - self.iv = _extract(params, 'iv', None) - if self.iv is None: - self.iv = _extract(params, 'nonce', None) - if self.iv is not None: - self.iv = b(self.iv) - - else: - # Stream cipher - self.mode = None - self.iv = _extract(params, 'iv', None) - if self.iv is not None: - self.iv = b(self.iv) - - self.extra_params = params - - def shortDescription(self): - return self.description - - def _new(self): - params = self.extra_params.copy() - key = a2b_hex(self.key) - - old_style = [] - if self.mode is not None: - old_style = [ self.mode ] - if self.iv is not None: - old_style += [ a2b_hex(self.iv) ] - - return self.module.new(key, *old_style, **params) - - def isMode(self, name): - if not hasattr(self.module, "MODE_"+name): - return False - return self.mode == getattr(self.module, "MODE_"+name) - - def runTest(self): - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) - assoc_data = [] - if self.assoc_data: - assoc_data = [ a2b_hex(b(x)) for x in self.assoc_data] - - ct = None - pt = None - - # - # Repeat the same encryption or decryption twice and verify - # that the result is always the same - # - for i in range(2): - cipher = self._new() - decipher = self._new() - - # Only AEAD modes - for comp in assoc_data: - cipher.update(comp) - decipher.update(comp) - - ctX = b2a_hex(cipher.encrypt(plaintext)) - ptX = b2a_hex(decipher.decrypt(ciphertext)) - - if ct: - self.assertEqual(ct, ctX) - self.assertEqual(pt, ptX) - ct, pt = ctX, ptX - - self.assertEqual(self.ciphertext, ct) # encrypt - self.assertEqual(self.plaintext, pt) # decrypt - - if self.mac: - mac = b2a_hex(cipher.digest()) - self.assertEqual(self.mac, mac) - decipher.verify(a2b_hex(self.mac)) +class _NoDefault: + pass # sentinel object -class CipherStreamingSelfTest(CipherSelfTest): - def shortDescription(self): - desc = self.module_name - if self.mode is not None: - desc += " in %s mode" % (self.mode_name,) - return "%s should behave like a stream cipher" % (desc,) +def _extract(d, k, default=_NoDefault): + """Get an item from a dictionary, and remove it from the dictionary.""" + try: + retval = d[k] + except KeyError: + if default is _NoDefault: + raise + return default + del d[k] + return retval - def runTest(self): - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) - # The cipher should work like a stream cipher +# Generic cipher test case +class CipherSelfTest(unittest.TestCase): + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + + # Extract the parameters + params = params.copy() + self.description = _extract(params, "description") + self.key = b(_extract(params, "key")) + self.plaintext = b(_extract(params, "plaintext")) + self.ciphertext = b(_extract(params, "ciphertext")) + self.module_name = _extract(params, "module_name", None) + self.assoc_data = _extract(params, "assoc_data", None) + self.mac = _extract(params, "mac", None) + if self.assoc_data: + self.mac = b(self.mac) + + mode = _extract(params, "mode", None) + self.mode_name = str(mode) + + if mode is not None: + # Block cipher + self.mode = getattr(self.module, "MODE_" + mode) + + self.iv = _extract(params, "iv", None) + if self.iv is None: + self.iv = _extract(params, "nonce", None) + if self.iv is not None: + self.iv = b(self.iv) + + else: + # Stream cipher + self.mode = None + self.iv = _extract(params, "iv", None) + if self.iv is not None: + self.iv = b(self.iv) + + self.extra_params = params + + def shortDescription(self): + return self.description + + def _new(self): + params = self.extra_params.copy() + key = a2b_hex(self.key) + + old_style = [] + if self.mode is not None: + old_style = [self.mode] + if self.iv is not None: + old_style += [a2b_hex(self.iv)] + + return self.module.new(key, *old_style, **params) + + def isMode(self, name): + if not hasattr(self.module, "MODE_" + name): + return False + return self.mode == getattr(self.module, "MODE_" + name) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + assoc_data = [] + if self.assoc_data: + assoc_data = [a2b_hex(b(x)) for x in self.assoc_data] + + ct = None + pt = None + + # + # Repeat the same encryption or decryption twice and verify + # that the result is always the same + # + for i in range(2): + cipher = self._new() + decipher = self._new() + + # Only AEAD modes + for comp in assoc_data: + cipher.update(comp) + decipher.update(comp) + + ctX = b2a_hex(cipher.encrypt(plaintext)) + ptX = b2a_hex(decipher.decrypt(ciphertext)) + + if ct: + self.assertEqual(ct, ctX) + self.assertEqual(pt, ptX) + ct, pt = ctX, ptX + + self.assertEqual(self.ciphertext, ct) # encrypt + self.assertEqual(self.plaintext, pt) # decrypt + + if self.mac: + mac = b2a_hex(cipher.digest()) + self.assertEqual(self.mac, mac) + decipher.verify(a2b_hex(self.mac)) - # Test counter mode encryption, 3 bytes at a time - ct3 = [] - cipher = self._new() - for i in range(0, len(plaintext), 3): - ct3.append(cipher.encrypt(plaintext[i:i+3])) - ct3 = b2a_hex(b("").join(ct3)) - self.assertEqual(self.ciphertext, ct3) # encryption (3 bytes at a time) - # Test counter mode decryption, 3 bytes at a time - pt3 = [] - cipher = self._new() - for i in range(0, len(ciphertext), 3): - pt3.append(cipher.encrypt(ciphertext[i:i+3])) - # PY3K: This is meant to be text, do not change to bytes (data) - pt3 = b2a_hex(b("").join(pt3)) - self.assertEqual(self.plaintext, pt3) # decryption (3 bytes at a time) +class CipherStreamingSelfTest(CipherSelfTest): + def shortDescription(self): + desc = self.module_name + if self.mode is not None: + desc += " in %s mode" % (self.mode_name,) + return "%s should behave like a stream cipher" % (desc,) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + + # The cipher should work like a stream cipher + + # Test counter mode encryption, 3 bytes at a time + ct3 = [] + cipher = self._new() + for i in range(0, len(plaintext), 3): + ct3.append(cipher.encrypt(plaintext[i : i + 3])) + ct3 = b2a_hex(b("").join(ct3)) + self.assertEqual(self.ciphertext, ct3) # encryption (3 bytes at a time) + + # Test counter mode decryption, 3 bytes at a time + pt3 = [] + cipher = self._new() + for i in range(0, len(ciphertext), 3): + pt3.append(cipher.encrypt(ciphertext[i : i + 3])) + # PY3K: This is meant to be text, do not change to bytes (data) + pt3 = b2a_hex(b("").join(pt3)) + self.assertEqual(self.plaintext, pt3) # decryption (3 bytes at a time) class RoundtripTest(unittest.TestCase): - def __init__(self, module, params): - from Cryptodome import Random - unittest.TestCase.__init__(self) - self.module = module - self.iv = Random.get_random_bytes(module.block_size) - self.key = b(params['key']) - self.plaintext = 100 * b(params['plaintext']) - self.module_name = params.get('module_name', None) + def __init__(self, module, params): + from Cryptodome import Random - def shortDescription(self): - return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,) + unittest.TestCase.__init__(self) + self.module = module + self.iv = Random.get_random_bytes(module.block_size) + self.key = b(params["key"]) + self.plaintext = 100 * b(params["plaintext"]) + self.module_name = params.get("module_name", None) - def runTest(self): + def shortDescription(self): + return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,) - ## ECB mode - mode = self.module.MODE_ECB - encryption_cipher = self.module.new(a2b_hex(self.key), mode) - ciphertext = encryption_cipher.encrypt(self.plaintext) - decryption_cipher = self.module.new(a2b_hex(self.key), mode) - decrypted_plaintext = decryption_cipher.decrypt(ciphertext) - self.assertEqual(self.plaintext, decrypted_plaintext) + def runTest(self): + ## ECB mode + mode = self.module.MODE_ECB + encryption_cipher = self.module.new(a2b_hex(self.key), mode) + ciphertext = encryption_cipher.encrypt(self.plaintext) + decryption_cipher = self.module.new(a2b_hex(self.key), mode) + decrypted_plaintext = decryption_cipher.decrypt(ciphertext) + self.assertEqual(self.plaintext, decrypted_plaintext) class IVLengthTest(unittest.TestCase): - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - self.key = b(params['key']) + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = b(params["key"]) - def shortDescription(self): - return "Check that all modes except MODE_ECB and MODE_CTR require an IV of the proper length" + def shortDescription(self): + return "Check that all modes except MODE_ECB and MODE_CTR require an IV of the proper length" - def runTest(self): - self.assertRaises(TypeError, self.module.new, a2b_hex(self.key), - self.module.MODE_ECB, b("")) + def runTest(self): + self.assertRaises( + TypeError, + self.module.new, + a2b_hex(self.key), + self.module.MODE_ECB, + b(""), + ) - def _dummy_counter(self): - return "\0" * self.module.block_size + def _dummy_counter(self): + return "\0" * self.module.block_size class NoDefaultECBTest(unittest.TestCase): - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - self.key = b(params['key']) + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = b(params["key"]) - def runTest(self): - self.assertRaises(TypeError, self.module.new, a2b_hex(self.key)) + def runTest(self): + self.assertRaises(TypeError, self.module.new, a2b_hex(self.key)) class BlockSizeTest(unittest.TestCase): - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - self.key = a2b_hex(b(params['key'])) + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = a2b_hex(b(params["key"])) - def runTest(self): - cipher = self.module.new(self.key, self.module.MODE_ECB) - self.assertEqual(cipher.block_size, self.module.block_size) + def runTest(self): + cipher = self.module.new(self.key, self.module.MODE_ECB) + self.assertEqual(cipher.block_size, self.module.block_size) class ByteArrayTest(unittest.TestCase): - """Verify we can use bytearray's for encrypting and decrypting""" - - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - - # Extract the parameters - params = params.copy() - self.description = _extract(params, 'description') - self.key = b(_extract(params, 'key')) - self.plaintext = b(_extract(params, 'plaintext')) - self.ciphertext = b(_extract(params, 'ciphertext')) - self.module_name = _extract(params, 'module_name', None) - self.assoc_data = _extract(params, 'assoc_data', None) - self.mac = _extract(params, 'mac', None) - if self.assoc_data: - self.mac = b(self.mac) - - mode = _extract(params, 'mode', None) - self.mode_name = str(mode) - - if mode is not None: - # Block cipher - self.mode = getattr(self.module, "MODE_" + mode) - - self.iv = _extract(params, 'iv', None) - if self.iv is None: - self.iv = _extract(params, 'nonce', None) - if self.iv is not None: - self.iv = b(self.iv) - else: - # Stream cipher - self.mode = None - self.iv = _extract(params, 'iv', None) - if self.iv is not None: - self.iv = b(self.iv) - - self.extra_params = params - - def _new(self): - params = self.extra_params.copy() - key = a2b_hex(self.key) - - old_style = [] - if self.mode is not None: - old_style = [ self.mode ] - if self.iv is not None: - old_style += [ a2b_hex(self.iv) ] - - return self.module.new(key, *old_style, **params) - - def runTest(self): - - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) - assoc_data = [] - if self.assoc_data: - assoc_data = [ bytearray(a2b_hex(b(x))) for x in self.assoc_data] - - cipher = self._new() - decipher = self._new() - - # Only AEAD modes - for comp in assoc_data: - cipher.update(comp) - decipher.update(comp) - - ct = b2a_hex(cipher.encrypt(bytearray(plaintext))) - pt = b2a_hex(decipher.decrypt(bytearray(ciphertext))) - - self.assertEqual(self.ciphertext, ct) # encrypt - self.assertEqual(self.plaintext, pt) # decrypt - - if self.mac: - mac = b2a_hex(cipher.digest()) - self.assertEqual(self.mac, mac) - decipher.verify(bytearray(a2b_hex(self.mac))) + """Verify we can use bytearray's for encrypting and decrypting""" + + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + + # Extract the parameters + params = params.copy() + self.description = _extract(params, "description") + self.key = b(_extract(params, "key")) + self.plaintext = b(_extract(params, "plaintext")) + self.ciphertext = b(_extract(params, "ciphertext")) + self.module_name = _extract(params, "module_name", None) + self.assoc_data = _extract(params, "assoc_data", None) + self.mac = _extract(params, "mac", None) + if self.assoc_data: + self.mac = b(self.mac) + + mode = _extract(params, "mode", None) + self.mode_name = str(mode) + + if mode is not None: + # Block cipher + self.mode = getattr(self.module, "MODE_" + mode) + + self.iv = _extract(params, "iv", None) + if self.iv is None: + self.iv = _extract(params, "nonce", None) + if self.iv is not None: + self.iv = b(self.iv) + else: + # Stream cipher + self.mode = None + self.iv = _extract(params, "iv", None) + if self.iv is not None: + self.iv = b(self.iv) + + self.extra_params = params + + def _new(self): + params = self.extra_params.copy() + key = a2b_hex(self.key) + + old_style = [] + if self.mode is not None: + old_style = [self.mode] + if self.iv is not None: + old_style += [a2b_hex(self.iv)] + + return self.module.new(key, *old_style, **params) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + assoc_data = [] + if self.assoc_data: + assoc_data = [bytearray(a2b_hex(b(x))) for x in self.assoc_data] + + cipher = self._new() + decipher = self._new() + + # Only AEAD modes + for comp in assoc_data: + cipher.update(comp) + decipher.update(comp) + + ct = b2a_hex(cipher.encrypt(bytearray(plaintext))) + pt = b2a_hex(decipher.decrypt(bytearray(ciphertext))) + + self.assertEqual(self.ciphertext, ct) # encrypt + self.assertEqual(self.plaintext, pt) # decrypt + + if self.mac: + mac = b2a_hex(cipher.digest()) + self.assertEqual(self.mac, mac) + decipher.verify(bytearray(a2b_hex(self.mac))) class MemoryviewTest(unittest.TestCase): - """Verify we can use memoryviews for encrypting and decrypting""" - - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - - # Extract the parameters - params = params.copy() - self.description = _extract(params, 'description') - self.key = b(_extract(params, 'key')) - self.plaintext = b(_extract(params, 'plaintext')) - self.ciphertext = b(_extract(params, 'ciphertext')) - self.module_name = _extract(params, 'module_name', None) - self.assoc_data = _extract(params, 'assoc_data', None) - self.mac = _extract(params, 'mac', None) - if self.assoc_data: - self.mac = b(self.mac) - - mode = _extract(params, 'mode', None) - self.mode_name = str(mode) - - if mode is not None: - # Block cipher - self.mode = getattr(self.module, "MODE_" + mode) - - self.iv = _extract(params, 'iv', None) - if self.iv is None: - self.iv = _extract(params, 'nonce', None) - if self.iv is not None: - self.iv = b(self.iv) - else: - # Stream cipher - self.mode = None - self.iv = _extract(params, 'iv', None) - if self.iv is not None: - self.iv = b(self.iv) - - self.extra_params = params - - def _new(self): - params = self.extra_params.copy() - key = a2b_hex(self.key) - - old_style = [] - if self.mode is not None: - old_style = [ self.mode ] - if self.iv is not None: - old_style += [ a2b_hex(self.iv) ] - - return self.module.new(key, *old_style, **params) - - def runTest(self): - - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) - assoc_data = [] - if self.assoc_data: - assoc_data = [ memoryview(a2b_hex(b(x))) for x in self.assoc_data] - - cipher = self._new() - decipher = self._new() - - # Only AEAD modes - for comp in assoc_data: - cipher.update(comp) - decipher.update(comp) - - ct = b2a_hex(cipher.encrypt(memoryview(plaintext))) - pt = b2a_hex(decipher.decrypt(memoryview(ciphertext))) - - self.assertEqual(self.ciphertext, ct) # encrypt - self.assertEqual(self.plaintext, pt) # decrypt - - if self.mac: - mac = b2a_hex(cipher.digest()) - self.assertEqual(self.mac, mac) - decipher.verify(memoryview(a2b_hex(self.mac))) + """Verify we can use memoryviews for encrypting and decrypting""" + + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + + # Extract the parameters + params = params.copy() + self.description = _extract(params, "description") + self.key = b(_extract(params, "key")) + self.plaintext = b(_extract(params, "plaintext")) + self.ciphertext = b(_extract(params, "ciphertext")) + self.module_name = _extract(params, "module_name", None) + self.assoc_data = _extract(params, "assoc_data", None) + self.mac = _extract(params, "mac", None) + if self.assoc_data: + self.mac = b(self.mac) + + mode = _extract(params, "mode", None) + self.mode_name = str(mode) + + if mode is not None: + # Block cipher + self.mode = getattr(self.module, "MODE_" + mode) + + self.iv = _extract(params, "iv", None) + if self.iv is None: + self.iv = _extract(params, "nonce", None) + if self.iv is not None: + self.iv = b(self.iv) + else: + # Stream cipher + self.mode = None + self.iv = _extract(params, "iv", None) + if self.iv is not None: + self.iv = b(self.iv) + + self.extra_params = params + + def _new(self): + params = self.extra_params.copy() + key = a2b_hex(self.key) + + old_style = [] + if self.mode is not None: + old_style = [self.mode] + if self.iv is not None: + old_style += [a2b_hex(self.iv)] + + return self.module.new(key, *old_style, **params) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + assoc_data = [] + if self.assoc_data: + assoc_data = [memoryview(a2b_hex(b(x))) for x in self.assoc_data] + + cipher = self._new() + decipher = self._new() + + # Only AEAD modes + for comp in assoc_data: + cipher.update(comp) + decipher.update(comp) + + ct = b2a_hex(cipher.encrypt(memoryview(plaintext))) + pt = b2a_hex(decipher.decrypt(memoryview(ciphertext))) + + self.assertEqual(self.ciphertext, ct) # encrypt + self.assertEqual(self.plaintext, pt) # decrypt + + if self.mac: + mac = b2a_hex(cipher.digest()) + self.assertEqual(self.mac, mac) + decipher.verify(memoryview(a2b_hex(self.mac))) def make_block_tests(module, module_name, test_data, additional_params=dict()): - tests = [] - extra_tests_added = False - for i in range(len(test_data)): - row = test_data[i] - - # Build the "params" dictionary with - # - plaintext - # - ciphertext - # - key - # - mode (default is ECB) - # - (optionally) description - # - (optionally) any other parameter that this cipher mode requires - params = {} - if len(row) == 3: - (params['plaintext'], params['ciphertext'], params['key']) = row - elif len(row) == 4: - (params['plaintext'], params['ciphertext'], params['key'], params['description']) = row - elif len(row) == 5: - (params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row - params.update(extra_params) - else: - raise AssertionError("Unsupported tuple size %d" % (len(row),)) - - if not "mode" in params: - params["mode"] = "ECB" - - # Build the display-name for the test - p2 = params.copy() - p_key = _extract(p2, 'key') - p_plaintext = _extract(p2, 'plaintext') - p_ciphertext = _extract(p2, 'ciphertext') - p_mode = _extract(p2, 'mode') - p_description = _extract(p2, 'description', None) - - if p_description is not None: - description = p_description - elif p_mode == 'ECB' and not p2: - description = "p=%s, k=%s" % (p_plaintext, p_key) - else: - description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) - name = "%s #%d: %s" % (module_name, i+1, description) - params['description'] = name - params['module_name'] = module_name - params.update(additional_params) - - # Add extra test(s) to the test suite before the current test - if not extra_tests_added: - tests += [ - RoundtripTest(module, params), - IVLengthTest(module, params), - NoDefaultECBTest(module, params), - ByteArrayTest(module, params), - BlockSizeTest(module, params), - ] - extra_tests_added = True - - # Add the current test to the test suite - tests.append(CipherSelfTest(module, params)) - - return tests + tests = [] + extra_tests_added = False + for i in range(len(test_data)): + row = test_data[i] + + # Build the "params" dictionary with + # - plaintext + # - ciphertext + # - key + # - mode (default is ECB) + # - (optionally) description + # - (optionally) any other parameter that this cipher mode requires + params = {} + if len(row) == 3: + (params["plaintext"], params["ciphertext"], params["key"]) = row + elif len(row) == 4: + (params["plaintext"], params["ciphertext"], params["key"], params["description"]) = row + elif len(row) == 5: + ( + params["plaintext"], + params["ciphertext"], + params["key"], + params["description"], + extra_params, + ) = row + params.update(extra_params) + else: + raise AssertionError("Unsupported tuple size %d" % (len(row),)) + + if "mode" not in params: + params["mode"] = "ECB" + + # Build the display-name for the test + p2 = params.copy() + p_key = _extract(p2, "key") + p_plaintext = _extract(p2, "plaintext") + p_ciphertext = _extract(p2, "ciphertext") + p_mode = _extract(p2, "mode") + p_description = _extract(p2, "description", None) + + if p_description is not None: + description = p_description + elif p_mode == "ECB" and not p2: + description = "p=%s, k=%s" % (p_plaintext, p_key) + else: + description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) + name = "%s #%d: %s" % (module_name, i + 1, description) + params["description"] = name + params["module_name"] = module_name + params.update(additional_params) + + # Add extra test(s) to the test suite before the current test + if not extra_tests_added: + tests += [ + RoundtripTest(module, params), + IVLengthTest(module, params), + NoDefaultECBTest(module, params), + ByteArrayTest(module, params), + BlockSizeTest(module, params), + ] + extra_tests_added = True + + # Add the current test to the test suite + tests.append(CipherSelfTest(module, params)) + + return tests + def make_stream_tests(module, module_name, test_data): - tests = [] - extra_tests_added = False - for i in range(len(test_data)): - row = test_data[i] - - # Build the "params" dictionary - params = {} - if len(row) == 3: - (params['plaintext'], params['ciphertext'], params['key']) = row - elif len(row) == 4: - (params['plaintext'], params['ciphertext'], params['key'], params['description']) = row - elif len(row) == 5: - (params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row - params.update(extra_params) - else: - raise AssertionError("Unsupported tuple size %d" % (len(row),)) - - # Build the display-name for the test - p2 = params.copy() - p_key = _extract(p2, 'key') - p_plaintext = _extract(p2, 'plaintext') - p_ciphertext = _extract(p2, 'ciphertext') - p_description = _extract(p2, 'description', None) - - if p_description is not None: - description = p_description - elif not p2: - description = "p=%s, k=%s" % (p_plaintext, p_key) - else: - description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) - name = "%s #%d: %s" % (module_name, i+1, description) - params['description'] = name - params['module_name'] = module_name - - # Add extra test(s) to the test suite before the current test - if not extra_tests_added: - tests += [ - ByteArrayTest(module, params), - ] - - tests.append(MemoryviewTest(module, params)) - extra_tests_added = True - - # Add the test to the test suite - tests.append(CipherSelfTest(module, params)) - tests.append(CipherStreamingSelfTest(module, params)) - return tests + tests = [] + extra_tests_added = False + for i in range(len(test_data)): + row = test_data[i] + + # Build the "params" dictionary + params = {} + if len(row) == 3: + (params["plaintext"], params["ciphertext"], params["key"]) = row + elif len(row) == 4: + (params["plaintext"], params["ciphertext"], params["key"], params["description"]) = row + elif len(row) == 5: + ( + params["plaintext"], + params["ciphertext"], + params["key"], + params["description"], + extra_params, + ) = row + params.update(extra_params) + else: + raise AssertionError("Unsupported tuple size %d" % (len(row),)) + + # Build the display-name for the test + p2 = params.copy() + p_key = _extract(p2, "key") + p_plaintext = _extract(p2, "plaintext") + p_ciphertext = _extract(p2, "ciphertext") + p_description = _extract(p2, "description", None) + + if p_description is not None: + description = p_description + elif not p2: + description = "p=%s, k=%s" % (p_plaintext, p_key) + else: + description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) + name = "%s #%d: %s" % (module_name, i + 1, description) + params["description"] = name + params["module_name"] = module_name + + # Add extra test(s) to the test suite before the current test + if not extra_tests_added: + tests += [ + ByteArrayTest(module, params), + ] + + tests.append(MemoryviewTest(module, params)) + extra_tests_added = True + + # Add the test to the test suite + tests.append(CipherSelfTest(module, params)) + tests.append(CipherStreamingSelfTest(module, params)) + return tests + # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_AES.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_AES.py index bd6c40ea..3edd8fd6 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_AES.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_AES.py @@ -30,1322 +30,2488 @@ from Cryptodome.Hash import SHA256 from Cryptodome.Cipher import AES from Cryptodome.Util.py3compat import * -from binascii import hexlify # This is a list of (plaintext, ciphertext, key[, description[, params]]) tuples. test_data = [ - # FIPS PUB 197 test vectors - # http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - - ('00112233445566778899aabbccddeeff', '69c4e0d86a7b0430d8cdb78070b4c55a', - '000102030405060708090a0b0c0d0e0f', 'FIPS 197 C.1 (AES-128)'), - - ('00112233445566778899aabbccddeeff', 'dda97ca4864cdfe06eaf70a0ec0d7191', - '000102030405060708090a0b0c0d0e0f1011121314151617', - 'FIPS 197 C.2 (AES-192)'), - - ('00112233445566778899aabbccddeeff', '8ea2b7ca516745bfeafc49904b496089', - '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - 'FIPS 197 C.3 (AES-256)'), - - # Rijndael128 test vectors - # Downloaded 2008-09-13 from - # http://www.iaik.tugraz.at/Research/krypto/AES/old/~rijmen/rijndael/testvalues.tar.gz - - # ecb_tbl.txt, KEYSIZE=128 - ('506812a45f08c889b97f5980038b8359', 'd8f532538289ef7d06b506a4fd5be9c9', - '00010203050607080a0b0c0d0f101112', - 'ecb-tbl-128: I=1'), - ('5c6d71ca30de8b8b00549984d2ec7d4b', '59ab30f4d4ee6e4ff9907ef65b1fb68c', - '14151617191a1b1c1e1f202123242526', - 'ecb-tbl-128: I=2'), - ('53f3f4c64f8616e4e7c56199f48f21f6', 'bf1ed2fcb2af3fd41443b56d85025cb1', - '28292a2b2d2e2f30323334353738393a', - 'ecb-tbl-128: I=3'), - ('a1eb65a3487165fb0f1c27ff9959f703', '7316632d5c32233edcb0780560eae8b2', - '3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-128: I=4'), - ('3553ecf0b1739558b08e350a98a39bfa', '408c073e3e2538072b72625e68b8364b', - '50515253555657585a5b5c5d5f606162', - 'ecb-tbl-128: I=5'), - ('67429969490b9711ae2b01dc497afde8', 'e1f94dfa776597beaca262f2f6366fea', - '64656667696a6b6c6e6f707173747576', - 'ecb-tbl-128: I=6'), - ('93385c1f2aec8bed192f5a8e161dd508', 'f29e986c6a1c27d7b29ffd7ee92b75f1', - '78797a7b7d7e7f80828384858788898a', - 'ecb-tbl-128: I=7'), - ('b5bf946be19beb8db3983b5f4c6e8ddb', '131c886a57f8c2e713aba6955e2b55b5', - '8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-128: I=8'), - ('41321ee10e21bd907227c4450ff42324', 'd2ab7662df9b8c740210e5eeb61c199d', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-128: I=9'), - ('00a82f59c91c8486d12c0a80124f6089', '14c10554b2859c484cab5869bbe7c470', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-128: I=10'), - ('7ce0fd076754691b4bbd9faf8a1372fe', 'db4d498f0a49cf55445d502c1f9ab3b5', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', - 'ecb-tbl-128: I=11'), - ('23605a8243d07764541bc5ad355b3129', '6d96fef7d66590a77a77bb2056667f7f', - 'dcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-128: I=12'), - ('12a8cfa23ea764fd876232b4e842bc44', '316fb68edba736c53e78477bf913725c', - 'f0f1f2f3f5f6f7f8fafbfcfdfe010002', - 'ecb-tbl-128: I=13'), - ('bcaf32415e8308b3723e5fdd853ccc80', '6936f2b93af8397fd3a771fc011c8c37', - '04050607090a0b0c0e0f101113141516', - 'ecb-tbl-128: I=14'), - ('89afae685d801ad747ace91fc49adde0', 'f3f92f7a9c59179c1fcc2c2ba0b082cd', - '2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-128: I=15'), - ('f521d07b484357c4a69e76124a634216', '6a95ea659ee3889158e7a9152ff04ebc', - '40414243454647484a4b4c4d4f505152', - 'ecb-tbl-128: I=16'), - ('3e23b3bc065bcc152407e23896d77783', '1959338344e945670678a5d432c90b93', - '54555657595a5b5c5e5f606163646566', - 'ecb-tbl-128: I=17'), - ('79f0fba002be1744670e7e99290d8f52', 'e49bddd2369b83ee66e6c75a1161b394', - '68696a6b6d6e6f70727374757778797a', - 'ecb-tbl-128: I=18'), - ('da23fe9d5bd63e1d72e3dafbe21a6c2a', 'd3388f19057ff704b70784164a74867d', - '7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-128: I=19'), - ('e3f5698ba90b6a022efd7db2c7e6c823', '23aa03e2d5e4cd24f3217e596480d1e1', - 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-128: I=20'), - ('bdc2691d4f1b73d2700679c3bcbf9c6e', 'c84113d68b666ab2a50a8bdb222e91b9', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2', - 'ecb-tbl-128: I=21'), - ('ba74e02093217ee1ba1b42bd5624349a', 'ac02403981cd4340b507963db65cb7b6', - '08090a0b0d0e0f10121314151718191a', - 'ecb-tbl-128: I=22'), - ('b5c593b5851c57fbf8b3f57715e8f680', '8d1299236223359474011f6bf5088414', - '6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-128: I=23'), - ('3da9bd9cec072381788f9387c3bbf4ee', '5a1d6ab8605505f7977e55b9a54d9b90', - '80818283858687888a8b8c8d8f909192', - 'ecb-tbl-128: I=24'), - ('4197f3051121702ab65d316b3c637374', '72e9c2d519cf555e4208805aabe3b258', - '94959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-128: I=25'), - ('9f46c62ec4f6ee3f6e8c62554bc48ab7', 'a8f3e81c4a23a39ef4d745dffe026e80', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', - 'ecb-tbl-128: I=26'), - ('0220673fe9e699a4ebc8e0dbeb6979c8', '546f646449d31458f9eb4ef5483aee6c', - 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-128: I=27'), - ('b2b99171337ded9bc8c2c23ff6f18867', '4dbe4bc84ac797c0ee4efb7f1a07401c', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', - 'ecb-tbl-128: I=28'), - ('a7facf4e301e984e5efeefd645b23505', '25e10bfb411bbd4d625ac8795c8ca3b3', - 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-128: I=29'), - ('f7c762e4a9819160fd7acfb6c4eedcdd', '315637405054ec803614e43def177579', - 'f8f9fafbfdfefe00020304050708090a', - 'ecb-tbl-128: I=30'), - ('9b64fc21ea08709f4915436faa70f1be', '60c5bc8a1410247295c6386c59e572a8', - '0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-128: I=31'), - ('52af2c3de07ee6777f55a4abfc100b3f', '01366fc8ca52dfe055d6a00a76471ba6', - '20212223252627282a2b2c2d2f303132', - 'ecb-tbl-128: I=32'), - ('2fca001224386c57aa3f968cbe2c816f', 'ecc46595516ec612449c3f581e7d42ff', - '34353637393a3b3c3e3f404143444546', - 'ecb-tbl-128: I=33'), - ('4149c73658a4a9c564342755ee2c132f', '6b7ffe4c602a154b06ee9c7dab5331c9', - '48494a4b4d4e4f50525354555758595a', - 'ecb-tbl-128: I=34'), - ('af60005a00a1772f7c07a48a923c23d2', '7da234c14039a240dd02dd0fbf84eb67', - '5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-128: I=35'), - ('6fccbc28363759914b6f0280afaf20c6', 'c7dc217d9e3604ffe7e91f080ecd5a3a', - '70717273757677787a7b7c7d7f808182', - 'ecb-tbl-128: I=36'), - ('7d82a43ddf4fefa2fc5947499884d386', '37785901863f5c81260ea41e7580cda5', - '84858687898a8b8c8e8f909193949596', - 'ecb-tbl-128: I=37'), - ('5d5a990eaab9093afe4ce254dfa49ef9', 'a07b9338e92ed105e6ad720fccce9fe4', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aa', - 'ecb-tbl-128: I=38'), - ('4cd1e2fd3f4434b553aae453f0ed1a02', 'ae0fb9722418cc21a7da816bbc61322c', - 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-128: I=39'), - ('5a2c9a9641d4299125fa1b9363104b5e', 'c826a193080ff91ffb21f71d3373c877', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', - 'ecb-tbl-128: I=40'), - ('b517fe34c0fa217d341740bfd4fe8dd4', '1181b11b0e494e8d8b0aa6b1d5ac2c48', - 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-128: I=41'), - ('014baf2278a69d331d5180103643e99a', '6743c3d1519ab4f2cd9a78ab09a511bd', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fa', - 'ecb-tbl-128: I=42'), - ('b529bd8164f20d0aa443d4932116841c', 'dc55c076d52bacdf2eefd952946a439d', - 'fcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-128: I=43'), - ('2e596dcbb2f33d4216a1176d5bd1e456', '711b17b590ffc72b5c8e342b601e8003', - '10111213151617181a1b1c1d1f202122', - 'ecb-tbl-128: I=44'), - ('7274a1ea2b7ee2424e9a0e4673689143', '19983bb0950783a537e1339f4aa21c75', - '24252627292a2b2c2e2f303133343536', - 'ecb-tbl-128: I=45'), - ('ae20020bd4f13e9d90140bee3b5d26af', '3ba7762e15554169c0f4fa39164c410c', - '38393a3b3d3e3f40424344454748494a', - 'ecb-tbl-128: I=46'), - ('baac065da7ac26e855e79c8849d75a02', 'a0564c41245afca7af8aa2e0e588ea89', - '4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-128: I=47'), - ('7c917d8d1d45fab9e2540e28832540cc', '5e36a42a2e099f54ae85ecd92e2381ed', - '60616263656667686a6b6c6d6f707172', - 'ecb-tbl-128: I=48'), - ('bde6f89e16daadb0e847a2a614566a91', '770036f878cd0f6ca2268172f106f2fe', - '74757677797a7b7c7e7f808183848586', - 'ecb-tbl-128: I=49'), - ('c9de163725f1f5be44ebb1db51d07fbc', '7e4e03908b716116443ccf7c94e7c259', - '88898a8b8d8e8f90929394959798999a', - 'ecb-tbl-128: I=50'), - ('3af57a58f0c07dffa669572b521e2b92', '482735a48c30613a242dd494c7f9185d', - '9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-128: I=51'), - ('3d5ebac306dde4604f1b4fbbbfcdae55', 'b4c0f6c9d4d7079addf9369fc081061d', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', - 'ecb-tbl-128: I=52'), - ('c2dfa91bceb76a1183c995020ac0b556', 'd5810fe0509ac53edcd74f89962e6270', - 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-128: I=53'), - ('c70f54305885e9a0746d01ec56c8596b', '03f17a16b3f91848269ecdd38ebb2165', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9ea', - 'ecb-tbl-128: I=54'), - ('c4f81b610e98012ce000182050c0c2b2', 'da1248c3180348bad4a93b4d9856c9df', - 'ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-128: I=55'), - ('eaab86b1d02a95d7404eff67489f97d4', '3d10d7b63f3452c06cdf6cce18be0c2c', - '00010203050607080a0b0c0d0f101112', - 'ecb-tbl-128: I=56'), - ('7c55bdb40b88870b52bec3738de82886', '4ab823e7477dfddc0e6789018fcb6258', - '14151617191a1b1c1e1f202123242526', - 'ecb-tbl-128: I=57'), - ('ba6eaa88371ff0a3bd875e3f2a975ce0', 'e6478ba56a77e70cfdaa5c843abde30e', - '28292a2b2d2e2f30323334353738393a', - 'ecb-tbl-128: I=58'), - ('08059130c4c24bd30cf0575e4e0373dc', '1673064895fbeaf7f09c5429ff75772d', - '3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-128: I=59'), - ('9a8eab004ef53093dfcf96f57e7eda82', '4488033ae9f2efd0ca9383bfca1a94e9', - '50515253555657585a5b5c5d5f606162', - 'ecb-tbl-128: I=60'), - ('0745b589e2400c25f117b1d796c28129', '978f3b8c8f9d6f46626cac3c0bcb9217', - '64656667696a6b6c6e6f707173747576', - 'ecb-tbl-128: I=61'), - ('2f1777781216cec3f044f134b1b92bbe', 'e08c8a7e582e15e5527f1d9e2eecb236', - '78797a7b7d7e7f80828384858788898a', - 'ecb-tbl-128: I=62'), - ('353a779ffc541b3a3805d90ce17580fc', 'cec155b76ac5ffda4cf4f9ca91e49a7a', - '8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-128: I=63'), - ('1a1eae4415cefcf08c4ac1c8f68bea8f', 'd5ac7165763225dd2a38cdc6862c29ad', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-128: I=64'), - ('e6e7e4e5b0b3b2b5d4d5aaab16111013', '03680fe19f7ce7275452020be70e8204', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-128: I=65'), - ('f8f9fafbfbf8f9e677767170efe0e1e2', '461df740c9781c388e94bb861ceb54f6', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', - 'ecb-tbl-128: I=66'), - ('63626160a1a2a3a445444b4a75727370', '451bd60367f96483042742219786a074', - 'dcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-128: I=67'), - ('717073720605040b2d2c2b2a05fafbf9', 'e4dfa42671a02e57ef173b85c0ea9f2b', - 'f0f1f2f3f5f6f7f8fafbfcfdfe010002', - 'ecb-tbl-128: I=68'), - ('78797a7beae9e8ef3736292891969794', 'ed11b89e76274282227d854700a78b9e', - '04050607090a0b0c0e0f101113141516', - 'ecb-tbl-128: I=69'), - ('838281803231300fdddcdbdaa0afaead', '433946eaa51ea47af33895f2b90b3b75', - '18191a1b1d1e1f20222324252728292a', - 'ecb-tbl-128: I=70'), - ('18191a1bbfbcbdba75747b7a7f78797a', '6bc6d616a5d7d0284a5910ab35022528', - '2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-128: I=71'), - ('848586879b989996a3a2a5a4849b9a99', 'd2a920ecfe919d354b5f49eae9719c98', - '40414243454647484a4b4c4d4f505152', - 'ecb-tbl-128: I=72'), - ('0001020322212027cacbf4f551565754', '3a061b17f6a92885efbd0676985b373d', - '54555657595a5b5c5e5f606163646566', - 'ecb-tbl-128: I=73'), - ('cecfcccdafacadb2515057564a454447', 'fadeec16e33ea2f4688499d157e20d8f', - '68696a6b6d6e6f70727374757778797a', - 'ecb-tbl-128: I=74'), - ('92939091cdcecfc813121d1c80878685', '5cdefede59601aa3c3cda36fa6b1fa13', - '7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-128: I=75'), - ('d2d3d0d16f6c6d6259585f5ed1eeefec', '9574b00039844d92ebba7ee8719265f8', - '90919293959697989a9b9c9d9fa0a1a2', - 'ecb-tbl-128: I=76'), - ('acadaeaf878485820f0e1110d5d2d3d0', '9a9cf33758671787e5006928188643fa', - 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-128: I=77'), - ('9091929364676619e6e7e0e1757a7b78', '2cddd634c846ba66bb46cbfea4a674f9', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9ca', - 'ecb-tbl-128: I=78'), - ('babbb8b98a89888f74757a7b92959497', 'd28bae029393c3e7e26e9fafbbb4b98f', - 'cccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-128: I=79'), - ('8d8c8f8e6e6d6c633b3a3d3ccad5d4d7', 'ec27529b1bee0a9ab6a0d73ebc82e9b7', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2', - 'ecb-tbl-128: I=80'), - ('86878485010203040808f7f767606162', '3cb25c09472aff6ee7e2b47ccd7ccb17', - 'f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-128: I=81'), - ('8e8f8c8d656667788a8b8c8d010e0f0c', 'dee33103a7283370d725e44ca38f8fe5', - '08090a0b0d0e0f10121314151718191a', - 'ecb-tbl-128: I=82'), - ('c8c9cacb858687807a7b7475e7e0e1e2', '27f9bcd1aac64bffc11e7815702c1a69', - '1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-128: I=83'), - ('6d6c6f6e5053525d8c8d8a8badd2d3d0', '5df534ffad4ed0749a9988e9849d0021', - '30313233353637383a3b3c3d3f404142', - 'ecb-tbl-128: I=84'), - ('28292a2b393a3b3c0607181903040506', 'a48bee75db04fb60ca2b80f752a8421b', - '44454647494a4b4c4e4f505153545556', - 'ecb-tbl-128: I=85'), - ('a5a4a7a6b0b3b28ddbdadddcbdb2b3b0', '024c8cf70bc86ee5ce03678cb7af45f9', - '58595a5b5d5e5f60626364656768696a', - 'ecb-tbl-128: I=86'), - ('323330316467666130313e3f2c2b2a29', '3c19ac0f8a3a3862ce577831301e166b', - '6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-128: I=87'), - ('27262524080b0a05171611100b141516', 'c5e355b796a57421d59ca6be82e73bca', - '80818283858687888a8b8c8d8f909192', - 'ecb-tbl-128: I=88'), - ('040506074142434435340b0aa3a4a5a6', 'd94033276417abfb05a69d15b6e386e2', - '94959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-128: I=89'), - ('242526271112130c61606766bdb2b3b0', '24b36559ea3a9b9b958fe6da3e5b8d85', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', - 'ecb-tbl-128: I=90'), - ('4b4a4948252627209e9f9091cec9c8cb', '20fd4feaa0e8bf0cce7861d74ef4cb72', - 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-128: I=91'), - ('68696a6b6665646b9f9e9998d9e6e7e4', '350e20d5174277b9ec314c501570a11d', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', - 'ecb-tbl-128: I=92'), - ('34353637c5c6c7c0f0f1eeef7c7b7a79', '87a29d61b7c604d238fe73045a7efd57', - 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-128: I=93'), - ('32333031c2c1c13f0d0c0b0a050a0b08', '2c3164c1cc7d0064816bdc0faa362c52', - 'f8f9fafbfdfefe00020304050708090a', - 'ecb-tbl-128: I=94'), - ('cdcccfcebebdbcbbabaaa5a4181f1e1d', '195fe5e8a05a2ed594f6e4400eee10b3', - '0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-128: I=95'), - ('212023223635343ba0a1a6a7445b5a59', 'e4663df19b9a21a5a284c2bd7f905025', - '20212223252627282a2b2c2d2f303132', - 'ecb-tbl-128: I=96'), - ('0e0f0c0da8abaaad2f2e515002050407', '21b88714cfb4e2a933bd281a2c4743fd', - '34353637393a3b3c3e3f404143444546', - 'ecb-tbl-128: I=97'), - ('070605042a2928378e8f8889bdb2b3b0', 'cbfc3980d704fd0fc54378ab84e17870', - '48494a4b4d4e4f50525354555758595a', - 'ecb-tbl-128: I=98'), - ('cbcac9c893909196a9a8a7a6a5a2a3a0', 'bc5144baa48bdeb8b63e22e03da418ef', - '5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-128: I=99'), - ('80818283c1c2c3cc9c9d9a9b0cf3f2f1', '5a1dbaef1ee2984b8395da3bdffa3ccc', - '70717273757677787a7b7c7d7f808182', - 'ecb-tbl-128: I=100'), - ('1213101125262720fafbe4e5b1b6b7b4', 'f0b11cd0729dfcc80cec903d97159574', - '84858687898a8b8c8e8f909193949596', - 'ecb-tbl-128: I=101'), - ('7f7e7d7c3033320d97969190222d2c2f', '9f95314acfddc6d1914b7f19a9cc8209', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aa', - 'ecb-tbl-128: I=102'), - ('4e4f4c4d484b4a4d81808f8e53545556', '595736f6f0f70914a94e9e007f022519', - 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-128: I=103'), - ('dcdddedfb0b3b2bd15141312a1bebfbc', '1f19f57892cae586fcdfb4c694deb183', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', - 'ecb-tbl-128: I=104'), - ('93929190282b2a2dc4c5fafb92959497', '540700ee1f6f3dab0b3eddf6caee1ef5', - 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-128: I=105'), - ('f5f4f7f6c4c7c6d9373631307e717073', '14a342a91019a331687a2254e6626ca2', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fa', - 'ecb-tbl-128: I=106'), - ('93929190b6b5b4b364656a6b05020300', '7b25f3c3b2eea18d743ef283140f29ff', - 'fcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-128: I=107'), - ('babbb8b90d0e0f00a4a5a2a3043b3a39', '46c2587d66e5e6fa7f7ca6411ad28047', - '10111213151617181a1b1c1d1f202122', - 'ecb-tbl-128: I=108'), - ('d8d9dadb7f7c7d7a10110e0f787f7e7d', '09470e72229d954ed5ee73886dfeeba9', - '24252627292a2b2c2e2f303133343536', - 'ecb-tbl-128: I=109'), - ('fefffcfdefeced923b3a3d3c6768696a', 'd77c03de92d4d0d79ef8d4824ef365eb', - '38393a3b3d3e3f40424344454748494a', - 'ecb-tbl-128: I=110'), - ('d6d7d4d58a89888f96979899a5a2a3a0', '1d190219f290e0f1715d152d41a23593', - '4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-128: I=111'), - ('18191a1ba8abaaa5303136379b848586', 'a2cd332ce3a0818769616292e87f757b', - '60616263656667686a6b6c6d6f707172', - 'ecb-tbl-128: I=112'), - ('6b6a6968a4a7a6a1d6d72829b0b7b6b5', 'd54afa6ce60fbf9341a3690e21385102', - '74757677797a7b7c7e7f808183848586', - 'ecb-tbl-128: I=113'), - ('000102038a89889755545352a6a9a8ab', '06e5c364ded628a3f5e05e613e356f46', - '88898a8b8d8e8f90929394959798999a', - 'ecb-tbl-128: I=114'), - ('2d2c2f2eb3b0b1b6b6b7b8b9f2f5f4f7', 'eae63c0e62556dac85d221099896355a', - '9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-128: I=115'), - ('979695943536373856575051e09f9e9d', '1fed060e2c6fc93ee764403a889985a2', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', - 'ecb-tbl-128: I=116'), - ('a4a5a6a7989b9a9db1b0afae7a7d7c7f', 'c25235c1a30fdec1c7cb5c5737b2a588', - 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-128: I=117'), - ('c1c0c3c2686b6a55a8a9aeafeae5e4e7', '796dbef95147d4d30873ad8b7b92efc0', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9ea', - 'ecb-tbl-128: I=118'), - ('c1c0c3c2141716118c8d828364636261', 'cbcf0fb34d98d0bd5c22ce37211a46bf', - 'ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-128: I=119'), - ('93929190cccfcec196979091e0fffefd', '94b44da6466126cafa7c7fd09063fc24', - '00010203050607080a0b0c0d0f101112', - 'ecb-tbl-128: I=120'), - ('b4b5b6b7f9fafbfc25241b1a6e69686b', 'd78c5b5ebf9b4dbda6ae506c5074c8fe', - '14151617191a1b1c1e1f202123242526', - 'ecb-tbl-128: I=121'), - ('868784850704051ac7c6c1c08788898a', '6c27444c27204b043812cf8cf95f9769', - '28292a2b2d2e2f30323334353738393a', - 'ecb-tbl-128: I=122'), - ('f4f5f6f7aaa9a8affdfcf3f277707172', 'be94524ee5a2aa50bba8b75f4c0aebcf', - '3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-128: I=123'), - ('d3d2d1d00605040bc3c2c5c43e010003', 'a0aeaae91ba9f31f51aeb3588cf3a39e', - '50515253555657585a5b5c5d5f606162', - 'ecb-tbl-128: I=124'), - ('73727170424140476a6b74750d0a0b08', '275297779c28266ef9fe4c6a13c08488', - '64656667696a6b6c6e6f707173747576', - 'ecb-tbl-128: I=125'), - ('c2c3c0c10a0908f754555253a1aeafac', '86523d92bb8672cb01cf4a77fd725882', - '78797a7b7d7e7f80828384858788898a', - 'ecb-tbl-128: I=126'), - ('6d6c6f6ef8fbfafd82838c8df8fffefd', '4b8327640e9f33322a04dd96fcbf9a36', - '8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-128: I=127'), - ('f5f4f7f684878689a6a7a0a1d2cdcccf', 'ce52af650d088ca559425223f4d32694', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-128: I=128'), - - # ecb_tbl.txt, KEYSIZE=192 - ('2d33eef2c0430a8a9ebf45e809c40bb6', 'dff4945e0336df4c1c56bc700eff837f', - '00010203050607080a0b0c0d0f10111214151617191a1b1c', - 'ecb-tbl-192: I=1'), - ('6aa375d1fa155a61fb72353e0a5a8756', 'b6fddef4752765e347d5d2dc196d1252', - '1e1f20212324252628292a2b2d2e2f30323334353738393a', - 'ecb-tbl-192: I=2'), - ('bc3736518b9490dcb8ed60eb26758ed4', 'd23684e3d963b3afcf1a114aca90cbd6', - '3c3d3e3f41424344464748494b4c4d4e5051525355565758', - 'ecb-tbl-192: I=3'), - ('aa214402b46cffb9f761ec11263a311e', '3a7ac027753e2a18c2ceab9e17c11fd0', - '5a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-192: I=4'), - ('02aea86e572eeab66b2c3af5e9a46fd6', '8f6786bd007528ba26603c1601cdd0d8', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394', - 'ecb-tbl-192: I=5'), - ('e2aef6acc33b965c4fa1f91c75ff6f36', 'd17d073b01e71502e28b47ab551168b3', - '969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-192: I=6'), - ('0659df46427162b9434865dd9499f91d', 'a469da517119fab95876f41d06d40ffa', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0', - 'ecb-tbl-192: I=7'), - ('49a44239c748feb456f59c276a5658df', '6091aa3b695c11f5c0b6ad26d3d862ff', - 'd2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-192: I=8'), - ('66208f6e9d04525bdedb2733b6a6be37', '70f9e67f9f8df1294131662dc6e69364', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c', - 'ecb-tbl-192: I=9'), - ('3393f8dfc729c97f5480b950bc9666b0', 'd154dcafad8b207fa5cbc95e9996b559', - '0e0f10111314151618191a1b1d1e1f20222324252728292a', - 'ecb-tbl-192: I=10'), - ('606834c8ce063f3234cf1145325dbd71', '4934d541e8b46fa339c805a7aeb9e5da', - '2c2d2e2f31323334363738393b3c3d3e4041424345464748', - 'ecb-tbl-192: I=11'), - ('fec1c04f529bbd17d8cecfcc4718b17f', '62564c738f3efe186e1a127a0c4d3c61', - '4a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-192: I=12'), - ('32df99b431ed5dc5acf8caf6dc6ce475', '07805aa043986eb23693e23bef8f3438', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384', - 'ecb-tbl-192: I=13'), - ('7fdc2b746f3f665296943b83710d1f82', 'df0b4931038bade848dee3b4b85aa44b', - '868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2', - 'ecb-tbl-192: I=14'), - ('8fba1510a3c5b87e2eaa3f7a91455ca2', '592d5fded76582e4143c65099309477c', - 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6b8b9babbbdbebfc0', - 'ecb-tbl-192: I=15'), - ('2c9b468b1c2eed92578d41b0716b223b', 'c9b8d6545580d3dfbcdd09b954ed4e92', - 'c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-192: I=16'), - ('0a2bbf0efc6bc0034f8a03433fca1b1a', '5dccd5d6eb7c1b42acb008201df707a0', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfc', - 'ecb-tbl-192: I=17'), - ('25260e1f31f4104d387222e70632504b', 'a2a91682ffeb6ed1d34340946829e6f9', - 'fefe01010304050608090a0b0d0e0f10121314151718191a', - 'ecb-tbl-192: I=18'), - ('c527d25a49f08a5228d338642ae65137', 'e45d185b797000348d9267960a68435d', - '1c1d1e1f21222324262728292b2c2d2e3031323335363738', - 'ecb-tbl-192: I=19'), - ('3b49fc081432f5890d0e3d87e884a69e', '45e060dae5901cda8089e10d4f4c246b', - '3a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-192: I=20'), - ('d173f9ed1e57597e166931df2754a083', 'f6951afacc0079a369c71fdcff45df50', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374', - 'ecb-tbl-192: I=21'), - ('8c2b7cafa5afe7f13562daeae1adede0', '9e95e00f351d5b3ac3d0e22e626ddad6', - '767778797b7c7d7e80818283858687888a8b8c8d8f909192', - 'ecb-tbl-192: I=22'), - ('aaf4ec8c1a815aeb826cab741339532c', '9cb566ff26d92dad083b51fdc18c173c', - '94959697999a9b9c9e9fa0a1a3a4a5a6a8a9aaabadaeafb0', - 'ecb-tbl-192: I=23'), - ('40be8c5d9108e663f38f1a2395279ecf', 'c9c82766176a9b228eb9a974a010b4fb', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebec', - 'ecb-tbl-192: I=24'), - ('0c8ad9bc32d43e04716753aa4cfbe351', 'd8e26aa02945881d5137f1c1e1386e88', - '2a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-192: I=25'), - ('1407b1d5f87d63357c8dc7ebbaebbfee', 'c0e024ccd68ff5ffa4d139c355a77c55', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364', - 'ecb-tbl-192: I=26'), - ('e62734d1ae3378c4549e939e6f123416', '0b18b3d16f491619da338640df391d43', - '84858687898a8b8c8e8f90919394959698999a9b9d9e9fa0', - 'ecb-tbl-192: I=27'), - ('5a752cff2a176db1a1de77f2d2cdee41', 'dbe09ac8f66027bf20cb6e434f252efc', - 'a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-192: I=28'), - ('a9c8c3a4eabedc80c64730ddd018cd88', '6d04e5e43c5b9cbe05feb9606b6480fe', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdc', - 'ecb-tbl-192: I=29'), - ('ee9b3dbbdb86180072130834d305999a', 'dd1d6553b96be526d9fee0fbd7176866', - '1a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-192: I=30'), - ('a7fa8c3586b8ebde7568ead6f634a879', '0260ca7e3f979fd015b0dd4690e16d2a', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354', - 'ecb-tbl-192: I=31'), - ('37e0f4a87f127d45ac936fe7ad88c10a', '9893734de10edcc8a67c3b110b8b8cc6', - '929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-192: I=32'), - ('3f77d8b5d92bac148e4e46f697a535c5', '93b30b750516b2d18808d710c2ee84ef', - '464748494b4c4d4e50515253555657585a5b5c5d5f606162', - 'ecb-tbl-192: I=33'), - ('d25ebb686c40f7e2c4da1014936571ca', '16f65fa47be3cb5e6dfe7c6c37016c0e', - '828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-192: I=34'), - ('4f1c769d1e5b0552c7eca84dea26a549', 'f3847210d5391e2360608e5acb560581', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbc', - 'ecb-tbl-192: I=35'), - ('8548e2f882d7584d0fafc54372b6633a', '8754462cd223366d0753913e6af2643d', - 'bebfc0c1c3c4c5c6c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', - 'ecb-tbl-192: I=36'), - ('87d7a336cb476f177cd2a51af2a62cdf', '1ea20617468d1b806a1fd58145462017', - 'dcdddedfe1e2e3e4e6e7e8e9ebecedeef0f1f2f3f5f6f7f8', - 'ecb-tbl-192: I=37'), - ('03b1feac668c4e485c1065dfc22b44ee', '3b155d927355d737c6be9dda60136e2e', - 'fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-192: I=38'), - ('bda15e66819fa72d653a6866aa287962', '26144f7b66daa91b6333dbd3850502b3', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334', - 'ecb-tbl-192: I=39'), - ('4d0c7a0d2505b80bf8b62ceb12467f0a', 'e4f9a4ab52ced8134c649bf319ebcc90', - '363738393b3c3d3e40414243454647484a4b4c4d4f505152', - 'ecb-tbl-192: I=40'), - ('626d34c9429b37211330986466b94e5f', 'b9ddd29ac6128a6cab121e34a4c62b36', - '54555657595a5b5c5e5f60616364656668696a6b6d6e6f70', - 'ecb-tbl-192: I=41'), - ('333c3e6bf00656b088a17e5ff0e7f60a', '6fcddad898f2ce4eff51294f5eaaf5c9', - '727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-192: I=42'), - ('687ed0cdc0d2a2bc8c466d05ef9d2891', 'c9a6fe2bf4028080bea6f7fc417bd7e3', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabac', - 'ecb-tbl-192: I=43'), - ('487830e78cc56c1693e64b2a6660c7b6', '6a2026846d8609d60f298a9c0673127f', - 'aeafb0b1b3b4b5b6b8b9babbbdbebfc0c2c3c4c5c7c8c9ca', - 'ecb-tbl-192: I=44'), - ('7a48d6b7b52b29392aa2072a32b66160', '2cb25c005e26efea44336c4c97a4240b', - 'cccdcecfd1d2d3d4d6d7d8d9dbdcdddee0e1e2e3e5e6e7e8', - 'ecb-tbl-192: I=45'), - ('907320e64c8c5314d10f8d7a11c8618d', '496967ab8680ddd73d09a0e4c7dcc8aa', - 'eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-192: I=46'), - ('b561f2ca2d6e65a4a98341f3ed9ff533', 'd5af94de93487d1f3a8c577cb84a66a4', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324', - 'ecb-tbl-192: I=47'), - ('df769380d212792d026f049e2e3e48ef', '84bdac569cae2828705f267cc8376e90', - '262728292b2c2d2e30313233353637383a3b3c3d3f404142', - 'ecb-tbl-192: I=48'), - ('79f374bc445bdabf8fccb8843d6054c6', 'f7401dda5ad5ab712b7eb5d10c6f99b6', - '44454647494a4b4c4e4f50515354555658595a5b5d5e5f60', - 'ecb-tbl-192: I=49'), - ('4e02f1242fa56b05c68dbae8fe44c9d6', '1c9d54318539ebd4c3b5b7e37bf119f0', - '626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-192: I=50'), - ('cf73c93cbff57ac635a6f4ad2a4a1545', 'aca572d65fb2764cffd4a6eca090ea0d', - '80818283858687888a8b8c8d8f90919294959697999a9b9c', - 'ecb-tbl-192: I=51'), - ('9923548e2875750725b886566784c625', '36d9c627b8c2a886a10ccb36eae3dfbb', - '9e9fa0a1a3a4a5a6a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', - 'ecb-tbl-192: I=52'), - ('4888336b723a022c9545320f836a4207', '010edbf5981e143a81d646e597a4a568', - 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdced0d1d2d3d5d6d7d8', - 'ecb-tbl-192: I=53'), - ('f84d9a5561b0608b1160dee000c41ba8', '8db44d538dc20cc2f40f3067fd298e60', - 'dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-192: I=54'), - ('c23192a0418e30a19b45ae3e3625bf22', '930eb53bc71e6ac4b82972bdcd5aafb3', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314', - 'ecb-tbl-192: I=55'), - ('b84e0690b28b0025381ad82a15e501a7', '6c42a81edcbc9517ccd89c30c95597b4', - '161718191b1c1d1e20212223252627282a2b2c2d2f303132', - 'ecb-tbl-192: I=56'), - ('acef5e5c108876c4f06269f865b8f0b0', 'da389847ad06df19d76ee119c71e1dd3', - '34353637393a3b3c3e3f40414344454648494a4b4d4e4f50', - 'ecb-tbl-192: I=57'), - ('0f1b3603e0f5ddea4548246153a5e064', 'e018fdae13d3118f9a5d1a647a3f0462', - '525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-192: I=58'), - ('fbb63893450d42b58c6d88cd3c1809e3', '2aa65db36264239d3846180fabdfad20', - '70717273757677787a7b7c7d7f80818284858687898a8b8c', - 'ecb-tbl-192: I=59'), - ('4bef736df150259dae0c91354e8a5f92', '1472163e9a4f780f1ceb44b07ecf4fdb', - '8e8f90919394959698999a9b9d9e9fa0a2a3a4a5a7a8a9aa', - 'ecb-tbl-192: I=60'), - ('7d2d46242056ef13d3c3fc93c128f4c7', 'c8273fdc8f3a9f72e91097614b62397c', - 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8', - 'ecb-tbl-192: I=61'), - ('e9c1ba2df415657a256edb33934680fd', '66c8427dcd733aaf7b3470cb7d976e3f', - 'cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-192: I=62'), - ('e23ee277b0aa0a1dfb81f7527c3514f1', '146131cb17f1424d4f8da91e6f80c1d0', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304', - 'ecb-tbl-192: I=63'), - ('3e7445b0b63caaf75e4a911e12106b4c', '2610d0ad83659081ae085266a88770dc', - '060708090b0c0d0e10111213151617181a1b1c1d1f202122', - 'ecb-tbl-192: I=64'), - ('767774752023222544455a5be6e1e0e3', '38a2b5a974b0575c5d733917fb0d4570', - '24252627292a2b2c2e2f30313334353638393a3b3d3e3f40', - 'ecb-tbl-192: I=65'), - ('72737475717e7f7ce9e8ebea696a6b6c', 'e21d401ebc60de20d6c486e4f39a588b', - '424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-192: I=66'), - ('dfdedddc25262728c9c8cfcef1eeefec', 'e51d5f88c670b079c0ca1f0c2c4405a2', - '60616263656667686a6b6c6d6f70717274757677797a7b7c', - 'ecb-tbl-192: I=67'), - ('fffe0100707776755f5e5d5c7675746b', '246a94788a642fb3d1b823c8762380c8', - '7e7f80818384858688898a8b8d8e8f90929394959798999a', - 'ecb-tbl-192: I=68'), - ('e0e1e2e3424140479f9e9190292e2f2c', 'b80c391c5c41a4c3b30c68e0e3d7550f', - '9c9d9e9fa1a2a3a4a6a7a8a9abacadaeb0b1b2b3b5b6b7b8', - 'ecb-tbl-192: I=69'), - ('2120272690efeeed3b3a39384e4d4c4b', 'b77c4754fc64eb9a1154a9af0bb1f21c', - 'babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-192: I=70'), - ('ecedeeef5350516ea1a0a7a6a3acadae', 'fb554de520d159a06bf219fc7f34a02f', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4', - 'ecb-tbl-192: I=71'), - ('32333c3d25222320e9e8ebeacecdccc3', 'a89fba152d76b4927beed160ddb76c57', - 'f6f7f8f9fbfcfdfe00010203050607080a0b0c0d0f101112', - 'ecb-tbl-192: I=72'), - ('40414243626160678a8bb4b511161714', '5676eab4a98d2e8473b3f3d46424247c', - '14151617191a1b1c1e1f20212324252628292a2b2d2e2f30', - 'ecb-tbl-192: I=73'), - ('94959293f5fafbf81f1e1d1c7c7f7e79', '4e8f068bd7ede52a639036ec86c33568', - '323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-192: I=74'), - ('bebfbcbd191a1b14cfcec9c8546b6a69', 'f0193c4d7aff1791ee4c07eb4a1824fc', - '50515253555657585a5b5c5d5f60616264656667696a6b6c', - 'ecb-tbl-192: I=75'), - ('2c2d3233898e8f8cbbbab9b8333031ce', 'ac8686eeca9ba761afe82d67b928c33f', - '6e6f70717374757678797a7b7d7e7f80828384858788898a', - 'ecb-tbl-192: I=76'), - ('84858687bfbcbdba37363938fdfafbf8', '5faf8573e33b145b6a369cd3606ab2c9', - '8c8d8e8f91929394969798999b9c9d9ea0a1a2a3a5a6a7a8', - 'ecb-tbl-192: I=77'), - ('828384857669686b909192930b08090e', '31587e9944ab1c16b844ecad0df2e7da', - 'aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-192: I=78'), - ('bebfbcbd9695948b707176779e919093', 'd017fecd91148aba37f6f3068aa67d8a', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4', - 'ecb-tbl-192: I=79'), - ('8b8a85846067666521202322d0d3d2dd', '788ef2f021a73cba2794b616078a8500', - 'e6e7e8e9ebecedeef0f1f2f3f5f6f7f8fafbfcfdfe010002', - 'ecb-tbl-192: I=80'), - ('76777475f1f2f3f4f8f9e6e777707172', '5d1ef20dced6bcbc12131ac7c54788aa', - '04050607090a0b0c0e0f10111314151618191a1b1d1e1f20', - 'ecb-tbl-192: I=81'), - ('a4a5a2a34f404142b4b5b6b727242522', 'b3c8cf961faf9ea05fdde6d1e4d8f663', - '222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-192: I=82'), - ('94959697e1e2e3ec16171011839c9d9e', '143075c70605861c7fac6526199e459f', - '40414243454647484a4b4c4d4f50515254555657595a5b5c', - 'ecb-tbl-192: I=83'), - ('03023d3c06010003dedfdcddfffcfde2', 'a5ae12eade9a87268d898bfc8fc0252a', - '5e5f60616364656668696a6b6d6e6f70727374757778797a', - 'ecb-tbl-192: I=84'), - ('10111213f1f2f3f4cecfc0c1dbdcddde', '0924f7cf2e877a4819f5244a360dcea9', - '7c7d7e7f81828384868788898b8c8d8e9091929395969798', - 'ecb-tbl-192: I=85'), - ('67666160724d4c4f1d1c1f1e73707176', '3d9e9635afcc3e291cc7ab3f27d1c99a', - '9a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-192: I=86'), - ('e6e7e4e5a8abaad584858283909f9e9d', '9d80feebf87510e2b8fb98bb54fd788c', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4', - 'ecb-tbl-192: I=87'), - ('71707f7e565150537d7c7f7e6162636c', '5f9d1a082a1a37985f174002eca01309', - 'd6d7d8d9dbdcdddee0e1e2e3e5e6e7e8eaebecedeff0f1f2', - 'ecb-tbl-192: I=88'), - ('64656667212223245555aaaa03040506', 'a390ebb1d1403930184a44b4876646e4', - 'f4f5f6f7f9fafbfcfefe01010304050608090a0b0d0e0f10', - 'ecb-tbl-192: I=89'), - ('9e9f9899aba4a5a6cfcecdcc2b28292e', '700fe918981c3195bb6c4bcb46b74e29', - '121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-192: I=90'), - ('c7c6c5c4d1d2d3dc626364653a454447', '907984406f7bf2d17fb1eb15b673d747', - '30313233353637383a3b3c3d3f40414244454647494a4b4c', - 'ecb-tbl-192: I=91'), - ('f6f7e8e9e0e7e6e51d1c1f1e5b585966', 'c32a956dcfc875c2ac7c7cc8b8cc26e1', - '4e4f50515354555658595a5b5d5e5f60626364656768696a', - 'ecb-tbl-192: I=92'), - ('bcbdbebf5d5e5f5868696667f4f3f2f1', '02646e2ebfa9b820cf8424e9b9b6eb51', - '6c6d6e6f71727374767778797b7c7d7e8081828385868788', - 'ecb-tbl-192: I=93'), - ('40414647b0afaead9b9a99989b98999e', '621fda3a5bbd54c6d3c685816bd4ead8', - '8a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-192: I=94'), - ('69686b6a0201001f0f0e0908b4bbbab9', 'd4e216040426dfaf18b152469bc5ac2f', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4', - 'ecb-tbl-192: I=95'), - ('c7c6c9c8d8dfdedd5a5b5859bebdbcb3', '9d0635b9d33b6cdbd71f5d246ea17cc8', - 'c6c7c8c9cbcccdced0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', - 'ecb-tbl-192: I=96'), - ('dedfdcdd787b7a7dfffee1e0b2b5b4b7', '10abad1bd9bae5448808765583a2cc1a', - 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6f8f9fafbfdfefe00', - 'ecb-tbl-192: I=97'), - ('4d4c4b4a606f6e6dd0d1d2d3fbf8f9fe', '6891889e16544e355ff65a793c39c9a8', - '020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-192: I=98'), - ('b7b6b5b4d7d4d5dae5e4e3e2e1fefffc', 'cc735582e68072c163cd9ddf46b91279', - '20212223252627282a2b2c2d2f30313234353637393a3b3c', - 'ecb-tbl-192: I=99'), - ('cecfb0b1f7f0f1f2aeafacad3e3d3c23', 'c5c68b9aeeb7f878df578efa562f9574', - '3e3f40414344454648494a4b4d4e4f50525354555758595a', - 'ecb-tbl-192: I=100'), - ('cacbc8c9cdcecfc812131c1d494e4f4c', '5f4764395a667a47d73452955d0d2ce8', - '5c5d5e5f61626364666768696b6c6d6e7071727375767778', - 'ecb-tbl-192: I=101'), - ('9d9c9b9ad22d2c2fb1b0b3b20c0f0e09', '701448331f66106cefddf1eb8267c357', - '7a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-192: I=102'), - ('7a7b787964676659959493924f404142', 'cb3ee56d2e14b4e1941666f13379d657', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4', - 'ecb-tbl-192: I=103'), - ('aaaba4a5cec9c8cb1f1e1d1caba8a9a6', '9fe16efd18ab6e1981191851fedb0764', - 'b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', - 'ecb-tbl-192: I=104'), - ('93929190282b2a2dc4c5fafb92959497', '3dc9ba24e1b223589b147adceb4c8e48', - 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6e8e9eaebedeeeff0', - 'ecb-tbl-192: I=105'), - ('efeee9e8ded1d0d339383b3a888b8a8d', '1c333032682e7d4de5e5afc05c3e483c', - 'f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-192: I=106'), - ('7f7e7d7ca2a1a0af78797e7f112e2f2c', 'd593cc99a95afef7e92038e05a59d00a', - '10111213151617181a1b1c1d1f20212224252627292a2b2c', - 'ecb-tbl-192: I=107'), - ('84859a9b2b2c2d2e868784852625245b', '51e7f96f53b4353923452c222134e1ec', - '2e2f30313334353638393a3b3d3e3f40424344454748494a', - 'ecb-tbl-192: I=108'), - ('b0b1b2b3070405026869666710171615', '4075b357a1a2b473400c3b25f32f81a4', - '4c4d4e4f51525354565758595b5c5d5e6061626365666768', - 'ecb-tbl-192: I=109'), - ('acadaaabbda2a3a00d0c0f0e595a5b5c', '302e341a3ebcd74f0d55f61714570284', - '6a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-192: I=110'), - ('121310115655544b5253545569666764', '57abdd8231280da01c5042b78cf76522', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4', - 'ecb-tbl-192: I=111'), - ('dedfd0d166616063eaebe8e94142434c', '17f9ea7eea17ac1adf0e190fef799e92', - 'a6a7a8a9abacadaeb0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', - 'ecb-tbl-192: I=112'), - ('dbdad9d81417161166677879e0e7e6e5', '2e1bdd563dd87ee5c338dd6d098d0a7a', - 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6d8d9dadbdddedfe0', - 'ecb-tbl-192: I=113'), - ('6a6b6c6de0efeeed2b2a2928c0c3c2c5', 'eb869996e6f8bfb2bfdd9e0c4504dbb2', - 'e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-192: I=114'), - ('b1b0b3b21714151a1a1b1c1d5649484b', 'c2e01549e9decf317468b3e018c61ba8', - '00010203050607080a0b0c0d0f10111214151617191a1b1c', - 'ecb-tbl-192: I=115'), - ('39380706a3a4a5a6c4c5c6c77271706f', '8da875d033c01dd463b244a1770f4a22', - '1e1f20212324252628292a2b2d2e2f30323334353738393a', - 'ecb-tbl-192: I=116'), - ('5c5d5e5f1013121539383736e2e5e4e7', '8ba0dcf3a186844f026d022f8839d696', - '3c3d3e3f41424344464748494b4c4d4e5051525355565758', - 'ecb-tbl-192: I=117'), - ('43424544ead5d4d72e2f2c2d64676661', 'e9691ff9a6cc6970e51670a0fd5b88c1', - '5a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-192: I=118'), - ('55545756989b9a65f8f9feff18171615', 'f2baec06faeed30f88ee63ba081a6e5b', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394', - 'ecb-tbl-192: I=119'), - ('05040b0a525554573c3d3e3f4a494847', '9c39d4c459ae5753394d6094adc21e78', - '969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-192: I=120'), - ('14151617595a5b5c8584fbfa8e89888b', '6345b532a11904502ea43ba99c6bd2b2', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0', - 'ecb-tbl-192: I=121'), - ('7c7d7a7bfdf2f3f029282b2a51525354', '5ffae3061a95172e4070cedce1e428c8', - 'd2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-192: I=122'), - ('38393a3b1e1d1c1341404746c23d3c3e', '0a4566be4cdf9adce5dec865b5ab34cd', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c', - 'ecb-tbl-192: I=123'), - ('8d8c939240474645818083827c7f7e41', 'ca17fcce79b7404f2559b22928f126fb', - '0e0f10111314151618191a1b1d1e1f20222324252728292a', - 'ecb-tbl-192: I=124'), - ('3b3a39381a19181f32333c3d45424340', '97ca39b849ed73a6470a97c821d82f58', - '2c2d2e2f31323334363738393b3c3d3e4041424345464748', - 'ecb-tbl-192: I=125'), - ('f0f1f6f738272625828380817f7c7d7a', '8198cb06bc684c6d3e9b7989428dcf7a', - '4a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-192: I=126'), - ('89888b8a0407061966676061141b1a19', 'f53c464c705ee0f28d9a4c59374928bd', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384', - 'ecb-tbl-192: I=127'), - ('d3d2dddcaaadacaf9c9d9e9fe8ebeae5', '9adb3d4cca559bb98c3e2ed73dbf1154', - '868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2', - 'ecb-tbl-192: I=128'), - - # ecb_tbl.txt, KEYSIZE=256 - ('834eadfccac7e1b30664b1aba44815ab', '1946dabf6a03a2a2c3d0b05080aed6fc', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=1'), - ('d9dc4dba3021b05d67c0518f72b62bf1', '5ed301d747d3cc715445ebdec62f2fb4', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=2'), - ('a291d86301a4a739f7392173aa3c604c', '6585c8f43d13a6beab6419fc5935b9d0', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=3'), - ('4264b2696498de4df79788a9f83e9390', '2a5b56a596680fcc0e05f5e0f151ecae', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=4'), - ('ee9932b3721804d5a83ef5949245b6f6', 'f5d6ff414fd2c6181494d20c37f2b8c4', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=5'), - ('e6248f55c5fdcbca9cbbb01c88a2ea77', '85399c01f59fffb5204f19f8482f00b8', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=6'), - ('b8358e41b9dff65fd461d55a99266247', '92097b4c88a041ddf98144bc8d22e8e7', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=7'), - ('f0e2d72260af58e21e015ab3a4c0d906', '89bd5b73b356ab412aef9f76cea2d65c', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=8'), - ('475b8b823ce8893db3c44a9f2a379ff7', '2536969093c55ff9454692f2fac2f530', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=9'), - ('688f5281945812862f5f3076cf80412f', '07fc76a872843f3f6e0081ee9396d637', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=10'), - ('08d1d2bc750af553365d35e75afaceaa', 'e38ba8ec2aa741358dcc93e8f141c491', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=11'), - ('8707121f47cc3efceca5f9a8474950a1', 'd028ee23e4a89075d0b03e868d7d3a42', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=12'), - ('e51aa0b135dba566939c3b6359a980c5', '8cd9423dfc459e547155c5d1d522e540', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=13'), - ('069a007fc76a459f98baf917fedf9521', '080e9517eb1677719acf728086040ae3', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=14'), - ('726165c1723fbcf6c026d7d00b091027', '7c1700211a3991fc0ecded0ab3e576b0', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=15'), - ('d7c544de91d55cfcde1f84ca382200ce', 'dabcbcc855839251db51e224fbe87435', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=16'), - ('fed3c9a161b9b5b2bd611b41dc9da357', '68d56fad0406947a4dd27a7448c10f1d', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=17'), - ('4f634cdc6551043409f30b635832cf82', 'da9a11479844d1ffee24bbf3719a9925', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=18'), - ('109ce98db0dfb36734d9f3394711b4e6', '5e4ba572f8d23e738da9b05ba24b8d81', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=19'), - ('4ea6dfaba2d8a02ffdffa89835987242', 'a115a2065d667e3f0b883837a6e903f8', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=20'), - ('5ae094f54af58e6e3cdbf976dac6d9ef', '3e9e90dc33eac2437d86ad30b137e66e', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=21'), - ('764d8e8e0f29926dbe5122e66354fdbe', '01ce82d8fbcdae824cb3c48e495c3692', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=22'), - ('3f0418f888cdf29a982bf6b75410d6a9', '0c9cff163ce936faaf083cfd3dea3117', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=23'), - ('e4a3e7cb12cdd56aa4a75197a9530220', '5131ba9bd48f2bba85560680df504b52', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=24'), - ('211677684aac1ec1a160f44c4ebf3f26', '9dc503bbf09823aec8a977a5ad26ccb2', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=25'), - ('d21e439ff749ac8f18d6d4b105e03895', '9a6db0c0862e506a9e397225884041d7', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=26'), - ('d9f6ff44646c4725bd4c0103ff5552a7', '430bf9570804185e1ab6365fc6a6860c', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=27'), - ('0b1256c2a00b976250cfc5b0c37ed382', '3525ebc02f4886e6a5a3762813e8ce8a', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=28'), - ('b056447ffc6dc4523a36cc2e972a3a79', '07fa265c763779cce224c7bad671027b', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=29'), - ('5e25ca78f0de55802524d38da3fe4456', 'e8b72b4e8be243438c9fff1f0e205872', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=30'), - ('a5bcf4728fa5eaad8567c0dc24675f83', '109d4f999a0e11ace1f05e6b22cbcb50', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=31'), - ('814e59f97ed84646b78b2ca022e9ca43', '45a5e8d4c3ed58403ff08d68a0cc4029', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=32'), - ('15478beec58f4775c7a7f5d4395514d7', '196865964db3d417b6bd4d586bcb7634', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=33'), - ('253548ffca461c67c8cbc78cd59f4756', '60436ad45ac7d30d99195f815d98d2ae', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=34'), - ('fd7ad8d73b9b0f8cc41600640f503d65', 'bb07a23f0b61014b197620c185e2cd75', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=35'), - ('06199de52c6cbf8af954cd65830bcd56', '5bc0b2850129c854423aff0751fe343b', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=36'), - ('f17c4ffe48e44c61bd891e257e725794', '7541a78f96738e6417d2a24bd2beca40', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=37'), - ('9a5b4a402a3e8a59be6bf5cd8154f029', 'b0a303054412882e464591f1546c5b9e', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=38'), - ('79bd40b91a7e07dc939d441782ae6b17', '778c06d8a355eeee214fcea14b4e0eef', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=39'), - ('d8ceaaf8976e5fbe1012d8c84f323799', '09614206d15cbace63227d06db6beebb', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=40'), - ('3316e2751e2e388b083da23dd6ac3fbe', '41b97fb20e427a9fdbbb358d9262255d', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=41'), - ('8b7cfbe37de7dca793521819242c5816', 'c1940f703d845f957652c2d64abd7adf', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=42'), - ('f23f033c0eebf8ec55752662fd58ce68', 'd2d44fcdae5332343366db297efcf21b', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=43'), - ('59eb34f6c8bdbacc5fc6ad73a59a1301', 'ea8196b79dbe167b6aa9896e287eed2b', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=44'), - ('dcde8b6bd5cf7cc22d9505e3ce81261a', 'd6b0b0c4ba6c7dbe5ed467a1e3f06c2d', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=45'), - ('e33cf7e524fed781e7042ff9f4b35dc7', 'ec51eb295250c22c2fb01816fb72bcae', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=46'), - ('27963c8facdf73062867d164df6d064c', 'aded6630a07ce9c7408a155d3bd0d36f', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=47'), - ('77b1ce386b551b995f2f2a1da994eef8', '697c9245b9937f32f5d1c82319f0363a', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=48'), - ('f083388b013679efcf0bb9b15d52ae5c', 'aad5ad50c6262aaec30541a1b7b5b19c', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-256: I=49'), - ('c5009e0dab55db0abdb636f2600290c8', '7d34b893855341ec625bd6875ac18c0d', - '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-256: I=50'), - ('7804881e26cd532d8514d3683f00f1b9', '7ef05105440f83862f5d780e88f02b41', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-256: I=51'), - ('46cddcd73d1eb53e675ca012870a92a3', 'c377c06403382061af2c9c93a8e70df6', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=52'), - ('a9fb44062bb07fe130a8e8299eacb1ab', '1dbdb3ffdc052dacc83318853abc6de5', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=53'), - ('2b6ff8d7a5cc3a28a22d5a6f221af26b', '69a6eab00432517d0bf483c91c0963c7', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=54'), - ('1a9527c29b8add4b0e3e656dbb2af8b4', '0797f41dc217c80446e1d514bd6ab197', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=55'), - ('7f99cf2c75244df015eb4b0c1050aeae', '9dfd76575902a637c01343c58e011a03', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=56'), - ('e84ff85b0d9454071909c1381646c4ed', 'acf4328ae78f34b9fa9b459747cc2658', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=57'), - ('89afd40f99521280d5399b12404f6db4', 'b0479aea12bac4fe2384cf98995150c6', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=58'), - ('a09ef32dbc5119a35ab7fa38656f0329', '9dd52789efe3ffb99f33b3da5030109a', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=59'), - ('61773457f068c376c7829b93e696e716', 'abbb755e4621ef8f1214c19f649fb9fd', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=60'), - ('a34f0cae726cce41dd498747d891b967', 'da27fb8174357bce2bed0e7354f380f9', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=61'), - ('856f59496c7388ee2d2b1a27b7697847', 'c59a0663f0993838f6e5856593bdc5ef', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=62'), - ('cb090c593ef7720bd95908fb93b49df4', 'ed60b264b5213e831607a99c0ce5e57e', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=63'), - ('a0ac75cd2f1923d460fc4d457ad95baf', 'e50548746846f3eb77b8c520640884ed', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=64'), - ('2a2b282974777689e8e9eeef525d5c5f', '28282cc7d21d6a2923641e52d188ef0c', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=65'), - ('909192939390919e0f0e09089788898a', '0dfa5b02abb18e5a815305216d6d4f8e', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=66'), - ('777675748d8e8f907170777649464744', '7359635c0eecefe31d673395fb46fb99', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=67'), - ('717073720605040b2d2c2b2a05fafbf9', '73c679f7d5aef2745c9737bb4c47fb36', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=68'), - ('64656667fefdfcc31b1a1d1ca5aaaba8', 'b192bd472a4d2eafb786e97458967626', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=69'), - ('dbdad9d86a696867b5b4b3b2c8d7d6d5', '0ec327f6c8a2b147598ca3fde61dc6a4', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=70'), - ('5c5d5e5fe3e0e1fe31303736333c3d3e', 'fc418eb3c41b859b38d4b6f646629729', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=71'), - ('545556574b48494673727574546b6a69', '30249e5ac282b1c981ea64b609f3a154', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=72'), - ('ecedeeefc6c5c4bb56575051f5fafbf8', '5e6e08646d12150776bb43c2d78a9703', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=73'), - ('464744452724252ac9c8cfced2cdcccf', 'faeb3d5de652cd3447dceb343f30394a', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=74'), - ('e6e7e4e54142435c878681801c131211', 'a8e88706823f6993ef80d05c1c7b2cf0', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=75'), - ('72737071cfcccdc2f9f8fffe710e0f0c', '8ced86677e6e00a1a1b15968f2d3cce6', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=76'), - ('505152537370714ec3c2c5c4010e0f0c', '9fc7c23858be03bdebb84e90db6786a9', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=77'), - ('a8a9aaab5c5f5e51aeafa8a93d222320', 'b4fbd65b33f70d8cf7f1111ac4649c36', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=78'), - ('dedfdcddf6f5f4eb10111617fef1f0f3', 'c5c32d5ed03c4b53cc8c1bd0ef0dbbf6', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=79'), - ('bdbcbfbe5e5d5c530b0a0d0cfac5c4c7', 'd1a7f03b773e5c212464b63709c6a891', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=80'), - ('8a8b8889050606f8f4f5f2f3636c6d6e', '6b7161d8745947ac6950438ea138d028', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-256: I=81'), - ('a6a7a4a54d4e4f40b2b3b4b539262724', 'fd47a9f7e366ee7a09bc508b00460661', - '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-256: I=82'), - ('9c9d9e9fe9eaebf40e0f08099b949596', '00d40b003dc3a0d9310b659b98c7e416', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-256: I=83'), - ('2d2c2f2e1013121dcccdcacbed121310', 'eea4c79dcc8e2bda691f20ac48be0717', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=84'), - ('f4f5f6f7edeeefd0eaebecedf7f8f9fa', 'e78f43b11c204403e5751f89d05a2509', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=85'), - ('3d3c3f3e282b2a2573727574150a0b08', 'd0f0e3d1f1244bb979931e38dd1786ef', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=86'), - ('b6b7b4b5f8fbfae5b4b5b2b3a0afaead', '042e639dc4e1e4dde7b75b749ea6f765', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=87'), - ('b7b6b5b4989b9a95878681809ba4a5a6', 'bc032fdd0efe29503a980a7d07ab46a8', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=88'), - ('a8a9aaabe5e6e798e9e8efee4748494a', '0c93ac949c0da6446effb86183b6c910', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=89'), - ('ecedeeefd9dadbd4b9b8bfbe657a7b78', 'e0d343e14da75c917b4a5cec4810d7c2', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=90'), - ('7f7e7d7c696a6b74cacbcccd929d9c9f', '0eafb821748408279b937b626792e619', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=91'), - ('08090a0b0605040bfffef9f8b9c6c7c4', 'fa1ac6e02d23b106a1fef18b274a553f', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=92'), - ('08090a0bf1f2f3ccfcfdfafb68676665', '0dadfe019cd12368075507df33c1a1e9', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=93'), - ('cacbc8c93a393837050403020d121310', '3a0879b414465d9ffbaf86b33a63a1b9', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=94'), - ('e9e8ebea8281809f8f8e8988343b3a39', '62199fadc76d0be1805d3ba0b7d914bf', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=95'), - ('515053524645444bd0d1d6d7340b0a09', '1b06d6c5d333e742730130cf78e719b4', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=96'), - ('42434041ecefee1193929594c6c9c8cb', 'f1f848824c32e9dcdcbf21580f069329', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=97'), - ('efeeedecc2c1c0cf76777071455a5b58', '1a09050cbd684f784d8e965e0782f28a', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=98'), - ('5f5e5d5c3f3c3d221d1c1b1a19161714', '79c2969e7ded2ba7d088f3f320692360', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=99'), - ('000102034142434c1c1d1a1b8d727371', '091a658a2f7444c16accb669450c7b63', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=100'), - ('8e8f8c8db1b2b38c56575051050a0b08', '97c1e3a72cca65fa977d5ed0e8a7bbfc', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=101'), - ('a7a6a5a4e8ebeae57f7e7978cad5d4d7', '70c430c6db9a17828937305a2df91a2a', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=102'), - ('8a8b888994979689454443429f909192', '629553457fbe2479098571c7c903fde8', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=103'), - ('8c8d8e8fe0e3e2ed45444342f1cecfcc', 'a25b25a61f612669e7d91265c7d476ba', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=104'), - ('fffefdfc4c4f4e31d8d9dedfb6b9b8bb', 'eb7e4e49b8ae0f024570dda293254fed', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=105'), - ('fdfcfffecccfcec12f2e29286679787b', '38fe15d61cca84516e924adce5014f67', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=106'), - ('67666564bab9b8a77071767719161714', '3ad208492249108c9f3ebeb167ad0583', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=107'), - ('9a9b98992d2e2f2084858283245b5a59', '299ba9f9bf5ab05c3580fc26edd1ed12', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=108'), - ('a4a5a6a70b0809365c5d5a5b2c232221', '19dc705b857a60fb07717b2ea5717781', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=109'), - ('464744455754555af3f2f5f4afb0b1b2', 'ffc8aeb885b5efcad06b6dbebf92e76b', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=110'), - ('323330317675746b7273747549464744', 'f58900c5e0b385253ff2546250a0142b', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=111'), - ('a8a9aaab181b1a15808186872b141516', '2ee67b56280bc462429cee6e3370cbc1', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=112'), - ('e7e6e5e4202323ddaaabacad343b3a39', '20db650a9c8e9a84ab4d25f7edc8f03f', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-256: I=113'), - ('a8a9aaab2221202fedecebea1e010003', '3c36da169525cf818843805f25b78ae5', - '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-256: I=114'), - ('f9f8fbfa5f5c5d42424344450e010003', '9a781d960db9e45e37779042fea51922', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-256: I=115'), - ('57565554f5f6f7f89697909120dfdedd', '6560395ec269c672a3c288226efdba77', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=116'), - ('f8f9fafbcccfcef1dddcdbda0e010003', '8c772b7a189ac544453d5916ebb27b9a', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=117'), - ('d9d8dbda7073727d80818687c2dddcdf', '77ca5468cc48e843d05f78eed9d6578f', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=118'), - ('c5c4c7c6080b0a1588898e8f68676665', '72cdcc71dc82c60d4429c9e2d8195baa', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=119'), - ('83828180dcdfded186878081f0cfcecd', '8080d68ce60e94b40b5b8b69eeb35afa', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=120'), - ('98999a9bdddedfa079787f7e0a050407', '44222d3cde299c04369d58ac0eba1e8e', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=121'), - ('cecfcccd4f4c4d429f9e9998dfc0c1c2', '9b8721b0a8dfc691c5bc5885dbfcb27a', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=122'), - ('404142436665647b29282f2eaba4a5a6', '0dc015ce9a3a3414b5e62ec643384183', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=123'), - ('33323130e6e5e4eb23222524dea1a0a3', '705715448a8da412025ce38345c2a148', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=124'), - ('cfcecdccf6f5f4cbe6e7e0e199969794', 'c32b5b0b6fbae165266c569f4b6ecf0b', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=125'), - ('babbb8b97271707fdcdddadb29363734', '4dca6c75192a01ddca9476af2a521e87', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=126'), - ('c9c8cbca4447465926272021545b5a59', '058691e627ecbc36ac07b6db423bd698', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=127'), - ('050407067477767956575051221d1c1f', '7444527095838fe080fc2bcdd30847eb', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=128'), - - # FIPS PUB 800-38A test vectors, 2001 edition. Annex F. - - ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', - '3ad77bb40d7a3660a89ecaf32466ef97'+'f5d3d58503b9699de785895a96fdbaaf'+ - '43b1cd7f598ece23881b00e3ed030688'+'7b0c785e27e8ad3f8223207104725dd4', - '2b7e151628aed2a6abf7158809cf4f3c', - 'NIST 800-38A, F.1.1, ECB and AES-128'), - - ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', - 'bd334f1d6e45f25ff712a214571fa5cc'+'974104846d0ad3ad7734ecb3ecee4eef'+ - 'ef7afd2270e2e60adce0ba2face6444e'+'9a4b41ba738d6c72fb16691603c18e0e', - '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', - 'NIST 800-38A, F.1.3, ECB and AES-192'), - - ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', - 'f3eed1bdb5d2a03c064b5a7e3db181f8'+'591ccb10d410ed26dc5ba74a31362870'+ - 'b6ed21b99ca6f4f9f153e7b1beafed1d'+'23304b7a39f9f3ff067d8d8f9e24ecc7', - '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', - 'NIST 800-38A, F.1.3, ECB and AES-256'), - + # FIPS PUB 197 test vectors + # http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + ( + "00112233445566778899aabbccddeeff", + "69c4e0d86a7b0430d8cdb78070b4c55a", + "000102030405060708090a0b0c0d0e0f", + "FIPS 197 C.1 (AES-128)", + ), + ( + "00112233445566778899aabbccddeeff", + "dda97ca4864cdfe06eaf70a0ec0d7191", + "000102030405060708090a0b0c0d0e0f1011121314151617", + "FIPS 197 C.2 (AES-192)", + ), + ( + "00112233445566778899aabbccddeeff", + "8ea2b7ca516745bfeafc49904b496089", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "FIPS 197 C.3 (AES-256)", + ), + # Rijndael128 test vectors + # Downloaded 2008-09-13 from + # http://www.iaik.tugraz.at/Research/krypto/AES/old/~rijmen/rijndael/testvalues.tar.gz + # ecb_tbl.txt, KEYSIZE=128 + ( + "506812a45f08c889b97f5980038b8359", + "d8f532538289ef7d06b506a4fd5be9c9", + "00010203050607080a0b0c0d0f101112", + "ecb-tbl-128: I=1", + ), + ( + "5c6d71ca30de8b8b00549984d2ec7d4b", + "59ab30f4d4ee6e4ff9907ef65b1fb68c", + "14151617191a1b1c1e1f202123242526", + "ecb-tbl-128: I=2", + ), + ( + "53f3f4c64f8616e4e7c56199f48f21f6", + "bf1ed2fcb2af3fd41443b56d85025cb1", + "28292a2b2d2e2f30323334353738393a", + "ecb-tbl-128: I=3", + ), + ( + "a1eb65a3487165fb0f1c27ff9959f703", + "7316632d5c32233edcb0780560eae8b2", + "3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-128: I=4", + ), + ( + "3553ecf0b1739558b08e350a98a39bfa", + "408c073e3e2538072b72625e68b8364b", + "50515253555657585a5b5c5d5f606162", + "ecb-tbl-128: I=5", + ), + ( + "67429969490b9711ae2b01dc497afde8", + "e1f94dfa776597beaca262f2f6366fea", + "64656667696a6b6c6e6f707173747576", + "ecb-tbl-128: I=6", + ), + ( + "93385c1f2aec8bed192f5a8e161dd508", + "f29e986c6a1c27d7b29ffd7ee92b75f1", + "78797a7b7d7e7f80828384858788898a", + "ecb-tbl-128: I=7", + ), + ( + "b5bf946be19beb8db3983b5f4c6e8ddb", + "131c886a57f8c2e713aba6955e2b55b5", + "8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-128: I=8", + ), + ( + "41321ee10e21bd907227c4450ff42324", + "d2ab7662df9b8c740210e5eeb61c199d", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-128: I=9", + ), + ( + "00a82f59c91c8486d12c0a80124f6089", + "14c10554b2859c484cab5869bbe7c470", + "b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-128: I=10", + ), + ( + "7ce0fd076754691b4bbd9faf8a1372fe", + "db4d498f0a49cf55445d502c1f9ab3b5", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9da", + "ecb-tbl-128: I=11", + ), + ( + "23605a8243d07764541bc5ad355b3129", + "6d96fef7d66590a77a77bb2056667f7f", + "dcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-128: I=12", + ), + ( + "12a8cfa23ea764fd876232b4e842bc44", + "316fb68edba736c53e78477bf913725c", + "f0f1f2f3f5f6f7f8fafbfcfdfe010002", + "ecb-tbl-128: I=13", + ), + ( + "bcaf32415e8308b3723e5fdd853ccc80", + "6936f2b93af8397fd3a771fc011c8c37", + "04050607090a0b0c0e0f101113141516", + "ecb-tbl-128: I=14", + ), + ( + "89afae685d801ad747ace91fc49adde0", + "f3f92f7a9c59179c1fcc2c2ba0b082cd", + "2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-128: I=15", + ), + ( + "f521d07b484357c4a69e76124a634216", + "6a95ea659ee3889158e7a9152ff04ebc", + "40414243454647484a4b4c4d4f505152", + "ecb-tbl-128: I=16", + ), + ( + "3e23b3bc065bcc152407e23896d77783", + "1959338344e945670678a5d432c90b93", + "54555657595a5b5c5e5f606163646566", + "ecb-tbl-128: I=17", + ), + ( + "79f0fba002be1744670e7e99290d8f52", + "e49bddd2369b83ee66e6c75a1161b394", + "68696a6b6d6e6f70727374757778797a", + "ecb-tbl-128: I=18", + ), + ( + "da23fe9d5bd63e1d72e3dafbe21a6c2a", + "d3388f19057ff704b70784164a74867d", + "7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-128: I=19", + ), + ( + "e3f5698ba90b6a022efd7db2c7e6c823", + "23aa03e2d5e4cd24f3217e596480d1e1", + "a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-128: I=20", + ), + ( + "bdc2691d4f1b73d2700679c3bcbf9c6e", + "c84113d68b666ab2a50a8bdb222e91b9", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2", + "ecb-tbl-128: I=21", + ), + ( + "ba74e02093217ee1ba1b42bd5624349a", + "ac02403981cd4340b507963db65cb7b6", + "08090a0b0d0e0f10121314151718191a", + "ecb-tbl-128: I=22", + ), + ( + "b5c593b5851c57fbf8b3f57715e8f680", + "8d1299236223359474011f6bf5088414", + "6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-128: I=23", + ), + ( + "3da9bd9cec072381788f9387c3bbf4ee", + "5a1d6ab8605505f7977e55b9a54d9b90", + "80818283858687888a8b8c8d8f909192", + "ecb-tbl-128: I=24", + ), + ( + "4197f3051121702ab65d316b3c637374", + "72e9c2d519cf555e4208805aabe3b258", + "94959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-128: I=25", + ), + ( + "9f46c62ec4f6ee3f6e8c62554bc48ab7", + "a8f3e81c4a23a39ef4d745dffe026e80", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9ba", + "ecb-tbl-128: I=26", + ), + ( + "0220673fe9e699a4ebc8e0dbeb6979c8", + "546f646449d31458f9eb4ef5483aee6c", + "bcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-128: I=27", + ), + ( + "b2b99171337ded9bc8c2c23ff6f18867", + "4dbe4bc84ac797c0ee4efb7f1a07401c", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2", + "ecb-tbl-128: I=28", + ), + ( + "a7facf4e301e984e5efeefd645b23505", + "25e10bfb411bbd4d625ac8795c8ca3b3", + "e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-128: I=29", + ), + ( + "f7c762e4a9819160fd7acfb6c4eedcdd", + "315637405054ec803614e43def177579", + "f8f9fafbfdfefe00020304050708090a", + "ecb-tbl-128: I=30", + ), + ( + "9b64fc21ea08709f4915436faa70f1be", + "60c5bc8a1410247295c6386c59e572a8", + "0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-128: I=31", + ), + ( + "52af2c3de07ee6777f55a4abfc100b3f", + "01366fc8ca52dfe055d6a00a76471ba6", + "20212223252627282a2b2c2d2f303132", + "ecb-tbl-128: I=32", + ), + ( + "2fca001224386c57aa3f968cbe2c816f", + "ecc46595516ec612449c3f581e7d42ff", + "34353637393a3b3c3e3f404143444546", + "ecb-tbl-128: I=33", + ), + ( + "4149c73658a4a9c564342755ee2c132f", + "6b7ffe4c602a154b06ee9c7dab5331c9", + "48494a4b4d4e4f50525354555758595a", + "ecb-tbl-128: I=34", + ), + ( + "af60005a00a1772f7c07a48a923c23d2", + "7da234c14039a240dd02dd0fbf84eb67", + "5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-128: I=35", + ), + ( + "6fccbc28363759914b6f0280afaf20c6", + "c7dc217d9e3604ffe7e91f080ecd5a3a", + "70717273757677787a7b7c7d7f808182", + "ecb-tbl-128: I=36", + ), + ( + "7d82a43ddf4fefa2fc5947499884d386", + "37785901863f5c81260ea41e7580cda5", + "84858687898a8b8c8e8f909193949596", + "ecb-tbl-128: I=37", + ), + ( + "5d5a990eaab9093afe4ce254dfa49ef9", + "a07b9338e92ed105e6ad720fccce9fe4", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aa", + "ecb-tbl-128: I=38", + ), + ( + "4cd1e2fd3f4434b553aae453f0ed1a02", + "ae0fb9722418cc21a7da816bbc61322c", + "acadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-128: I=39", + ), + ( + "5a2c9a9641d4299125fa1b9363104b5e", + "c826a193080ff91ffb21f71d3373c877", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2", + "ecb-tbl-128: I=40", + ), + ( + "b517fe34c0fa217d341740bfd4fe8dd4", + "1181b11b0e494e8d8b0aa6b1d5ac2c48", + "d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-128: I=41", + ), + ( + "014baf2278a69d331d5180103643e99a", + "6743c3d1519ab4f2cd9a78ab09a511bd", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fa", + "ecb-tbl-128: I=42", + ), + ( + "b529bd8164f20d0aa443d4932116841c", + "dc55c076d52bacdf2eefd952946a439d", + "fcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-128: I=43", + ), + ( + "2e596dcbb2f33d4216a1176d5bd1e456", + "711b17b590ffc72b5c8e342b601e8003", + "10111213151617181a1b1c1d1f202122", + "ecb-tbl-128: I=44", + ), + ( + "7274a1ea2b7ee2424e9a0e4673689143", + "19983bb0950783a537e1339f4aa21c75", + "24252627292a2b2c2e2f303133343536", + "ecb-tbl-128: I=45", + ), + ( + "ae20020bd4f13e9d90140bee3b5d26af", + "3ba7762e15554169c0f4fa39164c410c", + "38393a3b3d3e3f40424344454748494a", + "ecb-tbl-128: I=46", + ), + ( + "baac065da7ac26e855e79c8849d75a02", + "a0564c41245afca7af8aa2e0e588ea89", + "4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-128: I=47", + ), + ( + "7c917d8d1d45fab9e2540e28832540cc", + "5e36a42a2e099f54ae85ecd92e2381ed", + "60616263656667686a6b6c6d6f707172", + "ecb-tbl-128: I=48", + ), + ( + "bde6f89e16daadb0e847a2a614566a91", + "770036f878cd0f6ca2268172f106f2fe", + "74757677797a7b7c7e7f808183848586", + "ecb-tbl-128: I=49", + ), + ( + "c9de163725f1f5be44ebb1db51d07fbc", + "7e4e03908b716116443ccf7c94e7c259", + "88898a8b8d8e8f90929394959798999a", + "ecb-tbl-128: I=50", + ), + ( + "3af57a58f0c07dffa669572b521e2b92", + "482735a48c30613a242dd494c7f9185d", + "9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-128: I=51", + ), + ( + "3d5ebac306dde4604f1b4fbbbfcdae55", + "b4c0f6c9d4d7079addf9369fc081061d", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2", + "ecb-tbl-128: I=52", + ), + ( + "c2dfa91bceb76a1183c995020ac0b556", + "d5810fe0509ac53edcd74f89962e6270", + "c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-128: I=53", + ), + ( + "c70f54305885e9a0746d01ec56c8596b", + "03f17a16b3f91848269ecdd38ebb2165", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9ea", + "ecb-tbl-128: I=54", + ), + ( + "c4f81b610e98012ce000182050c0c2b2", + "da1248c3180348bad4a93b4d9856c9df", + "ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-128: I=55", + ), + ( + "eaab86b1d02a95d7404eff67489f97d4", + "3d10d7b63f3452c06cdf6cce18be0c2c", + "00010203050607080a0b0c0d0f101112", + "ecb-tbl-128: I=56", + ), + ( + "7c55bdb40b88870b52bec3738de82886", + "4ab823e7477dfddc0e6789018fcb6258", + "14151617191a1b1c1e1f202123242526", + "ecb-tbl-128: I=57", + ), + ( + "ba6eaa88371ff0a3bd875e3f2a975ce0", + "e6478ba56a77e70cfdaa5c843abde30e", + "28292a2b2d2e2f30323334353738393a", + "ecb-tbl-128: I=58", + ), + ( + "08059130c4c24bd30cf0575e4e0373dc", + "1673064895fbeaf7f09c5429ff75772d", + "3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-128: I=59", + ), + ( + "9a8eab004ef53093dfcf96f57e7eda82", + "4488033ae9f2efd0ca9383bfca1a94e9", + "50515253555657585a5b5c5d5f606162", + "ecb-tbl-128: I=60", + ), + ( + "0745b589e2400c25f117b1d796c28129", + "978f3b8c8f9d6f46626cac3c0bcb9217", + "64656667696a6b6c6e6f707173747576", + "ecb-tbl-128: I=61", + ), + ( + "2f1777781216cec3f044f134b1b92bbe", + "e08c8a7e582e15e5527f1d9e2eecb236", + "78797a7b7d7e7f80828384858788898a", + "ecb-tbl-128: I=62", + ), + ( + "353a779ffc541b3a3805d90ce17580fc", + "cec155b76ac5ffda4cf4f9ca91e49a7a", + "8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-128: I=63", + ), + ( + "1a1eae4415cefcf08c4ac1c8f68bea8f", + "d5ac7165763225dd2a38cdc6862c29ad", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-128: I=64", + ), + ( + "e6e7e4e5b0b3b2b5d4d5aaab16111013", + "03680fe19f7ce7275452020be70e8204", + "b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-128: I=65", + ), + ( + "f8f9fafbfbf8f9e677767170efe0e1e2", + "461df740c9781c388e94bb861ceb54f6", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9da", + "ecb-tbl-128: I=66", + ), + ( + "63626160a1a2a3a445444b4a75727370", + "451bd60367f96483042742219786a074", + "dcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-128: I=67", + ), + ( + "717073720605040b2d2c2b2a05fafbf9", + "e4dfa42671a02e57ef173b85c0ea9f2b", + "f0f1f2f3f5f6f7f8fafbfcfdfe010002", + "ecb-tbl-128: I=68", + ), + ( + "78797a7beae9e8ef3736292891969794", + "ed11b89e76274282227d854700a78b9e", + "04050607090a0b0c0e0f101113141516", + "ecb-tbl-128: I=69", + ), + ( + "838281803231300fdddcdbdaa0afaead", + "433946eaa51ea47af33895f2b90b3b75", + "18191a1b1d1e1f20222324252728292a", + "ecb-tbl-128: I=70", + ), + ( + "18191a1bbfbcbdba75747b7a7f78797a", + "6bc6d616a5d7d0284a5910ab35022528", + "2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-128: I=71", + ), + ( + "848586879b989996a3a2a5a4849b9a99", + "d2a920ecfe919d354b5f49eae9719c98", + "40414243454647484a4b4c4d4f505152", + "ecb-tbl-128: I=72", + ), + ( + "0001020322212027cacbf4f551565754", + "3a061b17f6a92885efbd0676985b373d", + "54555657595a5b5c5e5f606163646566", + "ecb-tbl-128: I=73", + ), + ( + "cecfcccdafacadb2515057564a454447", + "fadeec16e33ea2f4688499d157e20d8f", + "68696a6b6d6e6f70727374757778797a", + "ecb-tbl-128: I=74", + ), + ( + "92939091cdcecfc813121d1c80878685", + "5cdefede59601aa3c3cda36fa6b1fa13", + "7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-128: I=75", + ), + ( + "d2d3d0d16f6c6d6259585f5ed1eeefec", + "9574b00039844d92ebba7ee8719265f8", + "90919293959697989a9b9c9d9fa0a1a2", + "ecb-tbl-128: I=76", + ), + ( + "acadaeaf878485820f0e1110d5d2d3d0", + "9a9cf33758671787e5006928188643fa", + "a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-128: I=77", + ), + ( + "9091929364676619e6e7e0e1757a7b78", + "2cddd634c846ba66bb46cbfea4a674f9", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9ca", + "ecb-tbl-128: I=78", + ), + ( + "babbb8b98a89888f74757a7b92959497", + "d28bae029393c3e7e26e9fafbbb4b98f", + "cccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-128: I=79", + ), + ( + "8d8c8f8e6e6d6c633b3a3d3ccad5d4d7", + "ec27529b1bee0a9ab6a0d73ebc82e9b7", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2", + "ecb-tbl-128: I=80", + ), + ( + "86878485010203040808f7f767606162", + "3cb25c09472aff6ee7e2b47ccd7ccb17", + "f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-128: I=81", + ), + ( + "8e8f8c8d656667788a8b8c8d010e0f0c", + "dee33103a7283370d725e44ca38f8fe5", + "08090a0b0d0e0f10121314151718191a", + "ecb-tbl-128: I=82", + ), + ( + "c8c9cacb858687807a7b7475e7e0e1e2", + "27f9bcd1aac64bffc11e7815702c1a69", + "1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-128: I=83", + ), + ( + "6d6c6f6e5053525d8c8d8a8badd2d3d0", + "5df534ffad4ed0749a9988e9849d0021", + "30313233353637383a3b3c3d3f404142", + "ecb-tbl-128: I=84", + ), + ( + "28292a2b393a3b3c0607181903040506", + "a48bee75db04fb60ca2b80f752a8421b", + "44454647494a4b4c4e4f505153545556", + "ecb-tbl-128: I=85", + ), + ( + "a5a4a7a6b0b3b28ddbdadddcbdb2b3b0", + "024c8cf70bc86ee5ce03678cb7af45f9", + "58595a5b5d5e5f60626364656768696a", + "ecb-tbl-128: I=86", + ), + ( + "323330316467666130313e3f2c2b2a29", + "3c19ac0f8a3a3862ce577831301e166b", + "6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-128: I=87", + ), + ( + "27262524080b0a05171611100b141516", + "c5e355b796a57421d59ca6be82e73bca", + "80818283858687888a8b8c8d8f909192", + "ecb-tbl-128: I=88", + ), + ( + "040506074142434435340b0aa3a4a5a6", + "d94033276417abfb05a69d15b6e386e2", + "94959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-128: I=89", + ), + ( + "242526271112130c61606766bdb2b3b0", + "24b36559ea3a9b9b958fe6da3e5b8d85", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9ba", + "ecb-tbl-128: I=90", + ), + ( + "4b4a4948252627209e9f9091cec9c8cb", + "20fd4feaa0e8bf0cce7861d74ef4cb72", + "bcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-128: I=91", + ), + ( + "68696a6b6665646b9f9e9998d9e6e7e4", + "350e20d5174277b9ec314c501570a11d", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2", + "ecb-tbl-128: I=92", + ), + ( + "34353637c5c6c7c0f0f1eeef7c7b7a79", + "87a29d61b7c604d238fe73045a7efd57", + "e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-128: I=93", + ), + ( + "32333031c2c1c13f0d0c0b0a050a0b08", + "2c3164c1cc7d0064816bdc0faa362c52", + "f8f9fafbfdfefe00020304050708090a", + "ecb-tbl-128: I=94", + ), + ( + "cdcccfcebebdbcbbabaaa5a4181f1e1d", + "195fe5e8a05a2ed594f6e4400eee10b3", + "0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-128: I=95", + ), + ( + "212023223635343ba0a1a6a7445b5a59", + "e4663df19b9a21a5a284c2bd7f905025", + "20212223252627282a2b2c2d2f303132", + "ecb-tbl-128: I=96", + ), + ( + "0e0f0c0da8abaaad2f2e515002050407", + "21b88714cfb4e2a933bd281a2c4743fd", + "34353637393a3b3c3e3f404143444546", + "ecb-tbl-128: I=97", + ), + ( + "070605042a2928378e8f8889bdb2b3b0", + "cbfc3980d704fd0fc54378ab84e17870", + "48494a4b4d4e4f50525354555758595a", + "ecb-tbl-128: I=98", + ), + ( + "cbcac9c893909196a9a8a7a6a5a2a3a0", + "bc5144baa48bdeb8b63e22e03da418ef", + "5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-128: I=99", + ), + ( + "80818283c1c2c3cc9c9d9a9b0cf3f2f1", + "5a1dbaef1ee2984b8395da3bdffa3ccc", + "70717273757677787a7b7c7d7f808182", + "ecb-tbl-128: I=100", + ), + ( + "1213101125262720fafbe4e5b1b6b7b4", + "f0b11cd0729dfcc80cec903d97159574", + "84858687898a8b8c8e8f909193949596", + "ecb-tbl-128: I=101", + ), + ( + "7f7e7d7c3033320d97969190222d2c2f", + "9f95314acfddc6d1914b7f19a9cc8209", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aa", + "ecb-tbl-128: I=102", + ), + ( + "4e4f4c4d484b4a4d81808f8e53545556", + "595736f6f0f70914a94e9e007f022519", + "acadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-128: I=103", + ), + ( + "dcdddedfb0b3b2bd15141312a1bebfbc", + "1f19f57892cae586fcdfb4c694deb183", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2", + "ecb-tbl-128: I=104", + ), + ( + "93929190282b2a2dc4c5fafb92959497", + "540700ee1f6f3dab0b3eddf6caee1ef5", + "d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-128: I=105", + ), + ( + "f5f4f7f6c4c7c6d9373631307e717073", + "14a342a91019a331687a2254e6626ca2", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fa", + "ecb-tbl-128: I=106", + ), + ( + "93929190b6b5b4b364656a6b05020300", + "7b25f3c3b2eea18d743ef283140f29ff", + "fcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-128: I=107", + ), + ( + "babbb8b90d0e0f00a4a5a2a3043b3a39", + "46c2587d66e5e6fa7f7ca6411ad28047", + "10111213151617181a1b1c1d1f202122", + "ecb-tbl-128: I=108", + ), + ( + "d8d9dadb7f7c7d7a10110e0f787f7e7d", + "09470e72229d954ed5ee73886dfeeba9", + "24252627292a2b2c2e2f303133343536", + "ecb-tbl-128: I=109", + ), + ( + "fefffcfdefeced923b3a3d3c6768696a", + "d77c03de92d4d0d79ef8d4824ef365eb", + "38393a3b3d3e3f40424344454748494a", + "ecb-tbl-128: I=110", + ), + ( + "d6d7d4d58a89888f96979899a5a2a3a0", + "1d190219f290e0f1715d152d41a23593", + "4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-128: I=111", + ), + ( + "18191a1ba8abaaa5303136379b848586", + "a2cd332ce3a0818769616292e87f757b", + "60616263656667686a6b6c6d6f707172", + "ecb-tbl-128: I=112", + ), + ( + "6b6a6968a4a7a6a1d6d72829b0b7b6b5", + "d54afa6ce60fbf9341a3690e21385102", + "74757677797a7b7c7e7f808183848586", + "ecb-tbl-128: I=113", + ), + ( + "000102038a89889755545352a6a9a8ab", + "06e5c364ded628a3f5e05e613e356f46", + "88898a8b8d8e8f90929394959798999a", + "ecb-tbl-128: I=114", + ), + ( + "2d2c2f2eb3b0b1b6b6b7b8b9f2f5f4f7", + "eae63c0e62556dac85d221099896355a", + "9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-128: I=115", + ), + ( + "979695943536373856575051e09f9e9d", + "1fed060e2c6fc93ee764403a889985a2", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2", + "ecb-tbl-128: I=116", + ), + ( + "a4a5a6a7989b9a9db1b0afae7a7d7c7f", + "c25235c1a30fdec1c7cb5c5737b2a588", + "c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-128: I=117", + ), + ( + "c1c0c3c2686b6a55a8a9aeafeae5e4e7", + "796dbef95147d4d30873ad8b7b92efc0", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9ea", + "ecb-tbl-128: I=118", + ), + ( + "c1c0c3c2141716118c8d828364636261", + "cbcf0fb34d98d0bd5c22ce37211a46bf", + "ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-128: I=119", + ), + ( + "93929190cccfcec196979091e0fffefd", + "94b44da6466126cafa7c7fd09063fc24", + "00010203050607080a0b0c0d0f101112", + "ecb-tbl-128: I=120", + ), + ( + "b4b5b6b7f9fafbfc25241b1a6e69686b", + "d78c5b5ebf9b4dbda6ae506c5074c8fe", + "14151617191a1b1c1e1f202123242526", + "ecb-tbl-128: I=121", + ), + ( + "868784850704051ac7c6c1c08788898a", + "6c27444c27204b043812cf8cf95f9769", + "28292a2b2d2e2f30323334353738393a", + "ecb-tbl-128: I=122", + ), + ( + "f4f5f6f7aaa9a8affdfcf3f277707172", + "be94524ee5a2aa50bba8b75f4c0aebcf", + "3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-128: I=123", + ), + ( + "d3d2d1d00605040bc3c2c5c43e010003", + "a0aeaae91ba9f31f51aeb3588cf3a39e", + "50515253555657585a5b5c5d5f606162", + "ecb-tbl-128: I=124", + ), + ( + "73727170424140476a6b74750d0a0b08", + "275297779c28266ef9fe4c6a13c08488", + "64656667696a6b6c6e6f707173747576", + "ecb-tbl-128: I=125", + ), + ( + "c2c3c0c10a0908f754555253a1aeafac", + "86523d92bb8672cb01cf4a77fd725882", + "78797a7b7d7e7f80828384858788898a", + "ecb-tbl-128: I=126", + ), + ( + "6d6c6f6ef8fbfafd82838c8df8fffefd", + "4b8327640e9f33322a04dd96fcbf9a36", + "8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-128: I=127", + ), + ( + "f5f4f7f684878689a6a7a0a1d2cdcccf", + "ce52af650d088ca559425223f4d32694", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-128: I=128", + ), + # ecb_tbl.txt, KEYSIZE=192 + ( + "2d33eef2c0430a8a9ebf45e809c40bb6", + "dff4945e0336df4c1c56bc700eff837f", + "00010203050607080a0b0c0d0f10111214151617191a1b1c", + "ecb-tbl-192: I=1", + ), + ( + "6aa375d1fa155a61fb72353e0a5a8756", + "b6fddef4752765e347d5d2dc196d1252", + "1e1f20212324252628292a2b2d2e2f30323334353738393a", + "ecb-tbl-192: I=2", + ), + ( + "bc3736518b9490dcb8ed60eb26758ed4", + "d23684e3d963b3afcf1a114aca90cbd6", + "3c3d3e3f41424344464748494b4c4d4e5051525355565758", + "ecb-tbl-192: I=3", + ), + ( + "aa214402b46cffb9f761ec11263a311e", + "3a7ac027753e2a18c2ceab9e17c11fd0", + "5a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-192: I=4", + ), + ( + "02aea86e572eeab66b2c3af5e9a46fd6", + "8f6786bd007528ba26603c1601cdd0d8", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394", + "ecb-tbl-192: I=5", + ), + ( + "e2aef6acc33b965c4fa1f91c75ff6f36", + "d17d073b01e71502e28b47ab551168b3", + "969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-192: I=6", + ), + ( + "0659df46427162b9434865dd9499f91d", + "a469da517119fab95876f41d06d40ffa", + "b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0", + "ecb-tbl-192: I=7", + ), + ( + "49a44239c748feb456f59c276a5658df", + "6091aa3b695c11f5c0b6ad26d3d862ff", + "d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-192: I=8", + ), + ( + "66208f6e9d04525bdedb2733b6a6be37", + "70f9e67f9f8df1294131662dc6e69364", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c", + "ecb-tbl-192: I=9", + ), + ( + "3393f8dfc729c97f5480b950bc9666b0", + "d154dcafad8b207fa5cbc95e9996b559", + "0e0f10111314151618191a1b1d1e1f20222324252728292a", + "ecb-tbl-192: I=10", + ), + ( + "606834c8ce063f3234cf1145325dbd71", + "4934d541e8b46fa339c805a7aeb9e5da", + "2c2d2e2f31323334363738393b3c3d3e4041424345464748", + "ecb-tbl-192: I=11", + ), + ( + "fec1c04f529bbd17d8cecfcc4718b17f", + "62564c738f3efe186e1a127a0c4d3c61", + "4a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-192: I=12", + ), + ( + "32df99b431ed5dc5acf8caf6dc6ce475", + "07805aa043986eb23693e23bef8f3438", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384", + "ecb-tbl-192: I=13", + ), + ( + "7fdc2b746f3f665296943b83710d1f82", + "df0b4931038bade848dee3b4b85aa44b", + "868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2", + "ecb-tbl-192: I=14", + ), + ( + "8fba1510a3c5b87e2eaa3f7a91455ca2", + "592d5fded76582e4143c65099309477c", + "a4a5a6a7a9aaabacaeafb0b1b3b4b5b6b8b9babbbdbebfc0", + "ecb-tbl-192: I=15", + ), + ( + "2c9b468b1c2eed92578d41b0716b223b", + "c9b8d6545580d3dfbcdd09b954ed4e92", + "c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-192: I=16", + ), + ( + "0a2bbf0efc6bc0034f8a03433fca1b1a", + "5dccd5d6eb7c1b42acb008201df707a0", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfc", + "ecb-tbl-192: I=17", + ), + ( + "25260e1f31f4104d387222e70632504b", + "a2a91682ffeb6ed1d34340946829e6f9", + "fefe01010304050608090a0b0d0e0f10121314151718191a", + "ecb-tbl-192: I=18", + ), + ( + "c527d25a49f08a5228d338642ae65137", + "e45d185b797000348d9267960a68435d", + "1c1d1e1f21222324262728292b2c2d2e3031323335363738", + "ecb-tbl-192: I=19", + ), + ( + "3b49fc081432f5890d0e3d87e884a69e", + "45e060dae5901cda8089e10d4f4c246b", + "3a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-192: I=20", + ), + ( + "d173f9ed1e57597e166931df2754a083", + "f6951afacc0079a369c71fdcff45df50", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374", + "ecb-tbl-192: I=21", + ), + ( + "8c2b7cafa5afe7f13562daeae1adede0", + "9e95e00f351d5b3ac3d0e22e626ddad6", + "767778797b7c7d7e80818283858687888a8b8c8d8f909192", + "ecb-tbl-192: I=22", + ), + ( + "aaf4ec8c1a815aeb826cab741339532c", + "9cb566ff26d92dad083b51fdc18c173c", + "94959697999a9b9c9e9fa0a1a3a4a5a6a8a9aaabadaeafb0", + "ecb-tbl-192: I=23", + ), + ( + "40be8c5d9108e663f38f1a2395279ecf", + "c9c82766176a9b228eb9a974a010b4fb", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebec", + "ecb-tbl-192: I=24", + ), + ( + "0c8ad9bc32d43e04716753aa4cfbe351", + "d8e26aa02945881d5137f1c1e1386e88", + "2a2b2c2d2f30313234353637393a3b3c3e3f404143444546", + "ecb-tbl-192: I=25", + ), + ( + "1407b1d5f87d63357c8dc7ebbaebbfee", + "c0e024ccd68ff5ffa4d139c355a77c55", + "48494a4b4d4e4f50525354555758595a5c5d5e5f61626364", + "ecb-tbl-192: I=26", + ), + ( + "e62734d1ae3378c4549e939e6f123416", + "0b18b3d16f491619da338640df391d43", + "84858687898a8b8c8e8f90919394959698999a9b9d9e9fa0", + "ecb-tbl-192: I=27", + ), + ( + "5a752cff2a176db1a1de77f2d2cdee41", + "dbe09ac8f66027bf20cb6e434f252efc", + "a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-192: I=28", + ), + ( + "a9c8c3a4eabedc80c64730ddd018cd88", + "6d04e5e43c5b9cbe05feb9606b6480fe", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdc", + "ecb-tbl-192: I=29", + ), + ( + "ee9b3dbbdb86180072130834d305999a", + "dd1d6553b96be526d9fee0fbd7176866", + "1a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-192: I=30", + ), + ( + "a7fa8c3586b8ebde7568ead6f634a879", + "0260ca7e3f979fd015b0dd4690e16d2a", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354", + "ecb-tbl-192: I=31", + ), + ( + "37e0f4a87f127d45ac936fe7ad88c10a", + "9893734de10edcc8a67c3b110b8b8cc6", + "929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-192: I=32", + ), + ( + "3f77d8b5d92bac148e4e46f697a535c5", + "93b30b750516b2d18808d710c2ee84ef", + "464748494b4c4d4e50515253555657585a5b5c5d5f606162", + "ecb-tbl-192: I=33", + ), + ( + "d25ebb686c40f7e2c4da1014936571ca", + "16f65fa47be3cb5e6dfe7c6c37016c0e", + "828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-192: I=34", + ), + ( + "4f1c769d1e5b0552c7eca84dea26a549", + "f3847210d5391e2360608e5acb560581", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbc", + "ecb-tbl-192: I=35", + ), + ( + "8548e2f882d7584d0fafc54372b6633a", + "8754462cd223366d0753913e6af2643d", + "bebfc0c1c3c4c5c6c8c9cacbcdcecfd0d2d3d4d5d7d8d9da", + "ecb-tbl-192: I=36", + ), + ( + "87d7a336cb476f177cd2a51af2a62cdf", + "1ea20617468d1b806a1fd58145462017", + "dcdddedfe1e2e3e4e6e7e8e9ebecedeef0f1f2f3f5f6f7f8", + "ecb-tbl-192: I=37", + ), + ( + "03b1feac668c4e485c1065dfc22b44ee", + "3b155d927355d737c6be9dda60136e2e", + "fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-192: I=38", + ), + ( + "bda15e66819fa72d653a6866aa287962", + "26144f7b66daa91b6333dbd3850502b3", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334", + "ecb-tbl-192: I=39", + ), + ( + "4d0c7a0d2505b80bf8b62ceb12467f0a", + "e4f9a4ab52ced8134c649bf319ebcc90", + "363738393b3c3d3e40414243454647484a4b4c4d4f505152", + "ecb-tbl-192: I=40", + ), + ( + "626d34c9429b37211330986466b94e5f", + "b9ddd29ac6128a6cab121e34a4c62b36", + "54555657595a5b5c5e5f60616364656668696a6b6d6e6f70", + "ecb-tbl-192: I=41", + ), + ( + "333c3e6bf00656b088a17e5ff0e7f60a", + "6fcddad898f2ce4eff51294f5eaaf5c9", + "727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-192: I=42", + ), + ( + "687ed0cdc0d2a2bc8c466d05ef9d2891", + "c9a6fe2bf4028080bea6f7fc417bd7e3", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabac", + "ecb-tbl-192: I=43", + ), + ( + "487830e78cc56c1693e64b2a6660c7b6", + "6a2026846d8609d60f298a9c0673127f", + "aeafb0b1b3b4b5b6b8b9babbbdbebfc0c2c3c4c5c7c8c9ca", + "ecb-tbl-192: I=44", + ), + ( + "7a48d6b7b52b29392aa2072a32b66160", + "2cb25c005e26efea44336c4c97a4240b", + "cccdcecfd1d2d3d4d6d7d8d9dbdcdddee0e1e2e3e5e6e7e8", + "ecb-tbl-192: I=45", + ), + ( + "907320e64c8c5314d10f8d7a11c8618d", + "496967ab8680ddd73d09a0e4c7dcc8aa", + "eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-192: I=46", + ), + ( + "b561f2ca2d6e65a4a98341f3ed9ff533", + "d5af94de93487d1f3a8c577cb84a66a4", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324", + "ecb-tbl-192: I=47", + ), + ( + "df769380d212792d026f049e2e3e48ef", + "84bdac569cae2828705f267cc8376e90", + "262728292b2c2d2e30313233353637383a3b3c3d3f404142", + "ecb-tbl-192: I=48", + ), + ( + "79f374bc445bdabf8fccb8843d6054c6", + "f7401dda5ad5ab712b7eb5d10c6f99b6", + "44454647494a4b4c4e4f50515354555658595a5b5d5e5f60", + "ecb-tbl-192: I=49", + ), + ( + "4e02f1242fa56b05c68dbae8fe44c9d6", + "1c9d54318539ebd4c3b5b7e37bf119f0", + "626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-192: I=50", + ), + ( + "cf73c93cbff57ac635a6f4ad2a4a1545", + "aca572d65fb2764cffd4a6eca090ea0d", + "80818283858687888a8b8c8d8f90919294959697999a9b9c", + "ecb-tbl-192: I=51", + ), + ( + "9923548e2875750725b886566784c625", + "36d9c627b8c2a886a10ccb36eae3dfbb", + "9e9fa0a1a3a4a5a6a8a9aaabadaeafb0b2b3b4b5b7b8b9ba", + "ecb-tbl-192: I=52", + ), + ( + "4888336b723a022c9545320f836a4207", + "010edbf5981e143a81d646e597a4a568", + "bcbdbebfc1c2c3c4c6c7c8c9cbcccdced0d1d2d3d5d6d7d8", + "ecb-tbl-192: I=53", + ), + ( + "f84d9a5561b0608b1160dee000c41ba8", + "8db44d538dc20cc2f40f3067fd298e60", + "dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-192: I=54", + ), + ( + "c23192a0418e30a19b45ae3e3625bf22", + "930eb53bc71e6ac4b82972bdcd5aafb3", + "f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314", + "ecb-tbl-192: I=55", + ), + ( + "b84e0690b28b0025381ad82a15e501a7", + "6c42a81edcbc9517ccd89c30c95597b4", + "161718191b1c1d1e20212223252627282a2b2c2d2f303132", + "ecb-tbl-192: I=56", + ), + ( + "acef5e5c108876c4f06269f865b8f0b0", + "da389847ad06df19d76ee119c71e1dd3", + "34353637393a3b3c3e3f40414344454648494a4b4d4e4f50", + "ecb-tbl-192: I=57", + ), + ( + "0f1b3603e0f5ddea4548246153a5e064", + "e018fdae13d3118f9a5d1a647a3f0462", + "525354555758595a5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-192: I=58", + ), + ( + "fbb63893450d42b58c6d88cd3c1809e3", + "2aa65db36264239d3846180fabdfad20", + "70717273757677787a7b7c7d7f80818284858687898a8b8c", + "ecb-tbl-192: I=59", + ), + ( + "4bef736df150259dae0c91354e8a5f92", + "1472163e9a4f780f1ceb44b07ecf4fdb", + "8e8f90919394959698999a9b9d9e9fa0a2a3a4a5a7a8a9aa", + "ecb-tbl-192: I=60", + ), + ( + "7d2d46242056ef13d3c3fc93c128f4c7", + "c8273fdc8f3a9f72e91097614b62397c", + "acadaeafb1b2b3b4b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8", + "ecb-tbl-192: I=61", + ), + ( + "e9c1ba2df415657a256edb33934680fd", + "66c8427dcd733aaf7b3470cb7d976e3f", + "cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-192: I=62", + ), + ( + "e23ee277b0aa0a1dfb81f7527c3514f1", + "146131cb17f1424d4f8da91e6f80c1d0", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304", + "ecb-tbl-192: I=63", + ), + ( + "3e7445b0b63caaf75e4a911e12106b4c", + "2610d0ad83659081ae085266a88770dc", + "060708090b0c0d0e10111213151617181a1b1c1d1f202122", + "ecb-tbl-192: I=64", + ), + ( + "767774752023222544455a5be6e1e0e3", + "38a2b5a974b0575c5d733917fb0d4570", + "24252627292a2b2c2e2f30313334353638393a3b3d3e3f40", + "ecb-tbl-192: I=65", + ), + ( + "72737475717e7f7ce9e8ebea696a6b6c", + "e21d401ebc60de20d6c486e4f39a588b", + "424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-192: I=66", + ), + ( + "dfdedddc25262728c9c8cfcef1eeefec", + "e51d5f88c670b079c0ca1f0c2c4405a2", + "60616263656667686a6b6c6d6f70717274757677797a7b7c", + "ecb-tbl-192: I=67", + ), + ( + "fffe0100707776755f5e5d5c7675746b", + "246a94788a642fb3d1b823c8762380c8", + "7e7f80818384858688898a8b8d8e8f90929394959798999a", + "ecb-tbl-192: I=68", + ), + ( + "e0e1e2e3424140479f9e9190292e2f2c", + "b80c391c5c41a4c3b30c68e0e3d7550f", + "9c9d9e9fa1a2a3a4a6a7a8a9abacadaeb0b1b2b3b5b6b7b8", + "ecb-tbl-192: I=69", + ), + ( + "2120272690efeeed3b3a39384e4d4c4b", + "b77c4754fc64eb9a1154a9af0bb1f21c", + "babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-192: I=70", + ), + ( + "ecedeeef5350516ea1a0a7a6a3acadae", + "fb554de520d159a06bf219fc7f34a02f", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4", + "ecb-tbl-192: I=71", + ), + ( + "32333c3d25222320e9e8ebeacecdccc3", + "a89fba152d76b4927beed160ddb76c57", + "f6f7f8f9fbfcfdfe00010203050607080a0b0c0d0f101112", + "ecb-tbl-192: I=72", + ), + ( + "40414243626160678a8bb4b511161714", + "5676eab4a98d2e8473b3f3d46424247c", + "14151617191a1b1c1e1f20212324252628292a2b2d2e2f30", + "ecb-tbl-192: I=73", + ), + ( + "94959293f5fafbf81f1e1d1c7c7f7e79", + "4e8f068bd7ede52a639036ec86c33568", + "323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-192: I=74", + ), + ( + "bebfbcbd191a1b14cfcec9c8546b6a69", + "f0193c4d7aff1791ee4c07eb4a1824fc", + "50515253555657585a5b5c5d5f60616264656667696a6b6c", + "ecb-tbl-192: I=75", + ), + ( + "2c2d3233898e8f8cbbbab9b8333031ce", + "ac8686eeca9ba761afe82d67b928c33f", + "6e6f70717374757678797a7b7d7e7f80828384858788898a", + "ecb-tbl-192: I=76", + ), + ( + "84858687bfbcbdba37363938fdfafbf8", + "5faf8573e33b145b6a369cd3606ab2c9", + "8c8d8e8f91929394969798999b9c9d9ea0a1a2a3a5a6a7a8", + "ecb-tbl-192: I=77", + ), + ( + "828384857669686b909192930b08090e", + "31587e9944ab1c16b844ecad0df2e7da", + "aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-192: I=78", + ), + ( + "bebfbcbd9695948b707176779e919093", + "d017fecd91148aba37f6f3068aa67d8a", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4", + "ecb-tbl-192: I=79", + ), + ( + "8b8a85846067666521202322d0d3d2dd", + "788ef2f021a73cba2794b616078a8500", + "e6e7e8e9ebecedeef0f1f2f3f5f6f7f8fafbfcfdfe010002", + "ecb-tbl-192: I=80", + ), + ( + "76777475f1f2f3f4f8f9e6e777707172", + "5d1ef20dced6bcbc12131ac7c54788aa", + "04050607090a0b0c0e0f10111314151618191a1b1d1e1f20", + "ecb-tbl-192: I=81", + ), + ( + "a4a5a2a34f404142b4b5b6b727242522", + "b3c8cf961faf9ea05fdde6d1e4d8f663", + "222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-192: I=82", + ), + ( + "94959697e1e2e3ec16171011839c9d9e", + "143075c70605861c7fac6526199e459f", + "40414243454647484a4b4c4d4f50515254555657595a5b5c", + "ecb-tbl-192: I=83", + ), + ( + "03023d3c06010003dedfdcddfffcfde2", + "a5ae12eade9a87268d898bfc8fc0252a", + "5e5f60616364656668696a6b6d6e6f70727374757778797a", + "ecb-tbl-192: I=84", + ), + ( + "10111213f1f2f3f4cecfc0c1dbdcddde", + "0924f7cf2e877a4819f5244a360dcea9", + "7c7d7e7f81828384868788898b8c8d8e9091929395969798", + "ecb-tbl-192: I=85", + ), + ( + "67666160724d4c4f1d1c1f1e73707176", + "3d9e9635afcc3e291cc7ab3f27d1c99a", + "9a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-192: I=86", + ), + ( + "e6e7e4e5a8abaad584858283909f9e9d", + "9d80feebf87510e2b8fb98bb54fd788c", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4", + "ecb-tbl-192: I=87", + ), + ( + "71707f7e565150537d7c7f7e6162636c", + "5f9d1a082a1a37985f174002eca01309", + "d6d7d8d9dbdcdddee0e1e2e3e5e6e7e8eaebecedeff0f1f2", + "ecb-tbl-192: I=88", + ), + ( + "64656667212223245555aaaa03040506", + "a390ebb1d1403930184a44b4876646e4", + "f4f5f6f7f9fafbfcfefe01010304050608090a0b0d0e0f10", + "ecb-tbl-192: I=89", + ), + ( + "9e9f9899aba4a5a6cfcecdcc2b28292e", + "700fe918981c3195bb6c4bcb46b74e29", + "121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-192: I=90", + ), + ( + "c7c6c5c4d1d2d3dc626364653a454447", + "907984406f7bf2d17fb1eb15b673d747", + "30313233353637383a3b3c3d3f40414244454647494a4b4c", + "ecb-tbl-192: I=91", + ), + ( + "f6f7e8e9e0e7e6e51d1c1f1e5b585966", + "c32a956dcfc875c2ac7c7cc8b8cc26e1", + "4e4f50515354555658595a5b5d5e5f60626364656768696a", + "ecb-tbl-192: I=92", + ), + ( + "bcbdbebf5d5e5f5868696667f4f3f2f1", + "02646e2ebfa9b820cf8424e9b9b6eb51", + "6c6d6e6f71727374767778797b7c7d7e8081828385868788", + "ecb-tbl-192: I=93", + ), + ( + "40414647b0afaead9b9a99989b98999e", + "621fda3a5bbd54c6d3c685816bd4ead8", + "8a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-192: I=94", + ), + ( + "69686b6a0201001f0f0e0908b4bbbab9", + "d4e216040426dfaf18b152469bc5ac2f", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4", + "ecb-tbl-192: I=95", + ), + ( + "c7c6c9c8d8dfdedd5a5b5859bebdbcb3", + "9d0635b9d33b6cdbd71f5d246ea17cc8", + "c6c7c8c9cbcccdced0d1d2d3d5d6d7d8dadbdcdddfe0e1e2", + "ecb-tbl-192: I=96", + ), + ( + "dedfdcdd787b7a7dfffee1e0b2b5b4b7", + "10abad1bd9bae5448808765583a2cc1a", + "e4e5e6e7e9eaebeceeeff0f1f3f4f5f6f8f9fafbfdfefe00", + "ecb-tbl-192: I=97", + ), + ( + "4d4c4b4a606f6e6dd0d1d2d3fbf8f9fe", + "6891889e16544e355ff65a793c39c9a8", + "020304050708090a0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-192: I=98", + ), + ( + "b7b6b5b4d7d4d5dae5e4e3e2e1fefffc", + "cc735582e68072c163cd9ddf46b91279", + "20212223252627282a2b2c2d2f30313234353637393a3b3c", + "ecb-tbl-192: I=99", + ), + ( + "cecfb0b1f7f0f1f2aeafacad3e3d3c23", + "c5c68b9aeeb7f878df578efa562f9574", + "3e3f40414344454648494a4b4d4e4f50525354555758595a", + "ecb-tbl-192: I=100", + ), + ( + "cacbc8c9cdcecfc812131c1d494e4f4c", + "5f4764395a667a47d73452955d0d2ce8", + "5c5d5e5f61626364666768696b6c6d6e7071727375767778", + "ecb-tbl-192: I=101", + ), + ( + "9d9c9b9ad22d2c2fb1b0b3b20c0f0e09", + "701448331f66106cefddf1eb8267c357", + "7a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-192: I=102", + ), + ( + "7a7b787964676659959493924f404142", + "cb3ee56d2e14b4e1941666f13379d657", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4", + "ecb-tbl-192: I=103", + ), + ( + "aaaba4a5cec9c8cb1f1e1d1caba8a9a6", + "9fe16efd18ab6e1981191851fedb0764", + "b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8cacbcccdcfd0d1d2", + "ecb-tbl-192: I=104", + ), + ( + "93929190282b2a2dc4c5fafb92959497", + "3dc9ba24e1b223589b147adceb4c8e48", + "d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6e8e9eaebedeeeff0", + "ecb-tbl-192: I=105", + ), + ( + "efeee9e8ded1d0d339383b3a888b8a8d", + "1c333032682e7d4de5e5afc05c3e483c", + "f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-192: I=106", + ), + ( + "7f7e7d7ca2a1a0af78797e7f112e2f2c", + "d593cc99a95afef7e92038e05a59d00a", + "10111213151617181a1b1c1d1f20212224252627292a2b2c", + "ecb-tbl-192: I=107", + ), + ( + "84859a9b2b2c2d2e868784852625245b", + "51e7f96f53b4353923452c222134e1ec", + "2e2f30313334353638393a3b3d3e3f40424344454748494a", + "ecb-tbl-192: I=108", + ), + ( + "b0b1b2b3070405026869666710171615", + "4075b357a1a2b473400c3b25f32f81a4", + "4c4d4e4f51525354565758595b5c5d5e6061626365666768", + "ecb-tbl-192: I=109", + ), + ( + "acadaaabbda2a3a00d0c0f0e595a5b5c", + "302e341a3ebcd74f0d55f61714570284", + "6a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-192: I=110", + ), + ( + "121310115655544b5253545569666764", + "57abdd8231280da01c5042b78cf76522", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4", + "ecb-tbl-192: I=111", + ), + ( + "dedfd0d166616063eaebe8e94142434c", + "17f9ea7eea17ac1adf0e190fef799e92", + "a6a7a8a9abacadaeb0b1b2b3b5b6b7b8babbbcbdbfc0c1c2", + "ecb-tbl-192: I=112", + ), + ( + "dbdad9d81417161166677879e0e7e6e5", + "2e1bdd563dd87ee5c338dd6d098d0a7a", + "c4c5c6c7c9cacbcccecfd0d1d3d4d5d6d8d9dadbdddedfe0", + "ecb-tbl-192: I=113", + ), + ( + "6a6b6c6de0efeeed2b2a2928c0c3c2c5", + "eb869996e6f8bfb2bfdd9e0c4504dbb2", + "e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-192: I=114", + ), + ( + "b1b0b3b21714151a1a1b1c1d5649484b", + "c2e01549e9decf317468b3e018c61ba8", + "00010203050607080a0b0c0d0f10111214151617191a1b1c", + "ecb-tbl-192: I=115", + ), + ( + "39380706a3a4a5a6c4c5c6c77271706f", + "8da875d033c01dd463b244a1770f4a22", + "1e1f20212324252628292a2b2d2e2f30323334353738393a", + "ecb-tbl-192: I=116", + ), + ( + "5c5d5e5f1013121539383736e2e5e4e7", + "8ba0dcf3a186844f026d022f8839d696", + "3c3d3e3f41424344464748494b4c4d4e5051525355565758", + "ecb-tbl-192: I=117", + ), + ( + "43424544ead5d4d72e2f2c2d64676661", + "e9691ff9a6cc6970e51670a0fd5b88c1", + "5a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-192: I=118", + ), + ( + "55545756989b9a65f8f9feff18171615", + "f2baec06faeed30f88ee63ba081a6e5b", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394", + "ecb-tbl-192: I=119", + ), + ( + "05040b0a525554573c3d3e3f4a494847", + "9c39d4c459ae5753394d6094adc21e78", + "969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-192: I=120", + ), + ( + "14151617595a5b5c8584fbfa8e89888b", + "6345b532a11904502ea43ba99c6bd2b2", + "b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0", + "ecb-tbl-192: I=121", + ), + ( + "7c7d7a7bfdf2f3f029282b2a51525354", + "5ffae3061a95172e4070cedce1e428c8", + "d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-192: I=122", + ), + ( + "38393a3b1e1d1c1341404746c23d3c3e", + "0a4566be4cdf9adce5dec865b5ab34cd", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c", + "ecb-tbl-192: I=123", + ), + ( + "8d8c939240474645818083827c7f7e41", + "ca17fcce79b7404f2559b22928f126fb", + "0e0f10111314151618191a1b1d1e1f20222324252728292a", + "ecb-tbl-192: I=124", + ), + ( + "3b3a39381a19181f32333c3d45424340", + "97ca39b849ed73a6470a97c821d82f58", + "2c2d2e2f31323334363738393b3c3d3e4041424345464748", + "ecb-tbl-192: I=125", + ), + ( + "f0f1f6f738272625828380817f7c7d7a", + "8198cb06bc684c6d3e9b7989428dcf7a", + "4a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-192: I=126", + ), + ( + "89888b8a0407061966676061141b1a19", + "f53c464c705ee0f28d9a4c59374928bd", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384", + "ecb-tbl-192: I=127", + ), + ( + "d3d2dddcaaadacaf9c9d9e9fe8ebeae5", + "9adb3d4cca559bb98c3e2ed73dbf1154", + "868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2", + "ecb-tbl-192: I=128", + ), + # ecb_tbl.txt, KEYSIZE=256 + ( + "834eadfccac7e1b30664b1aba44815ab", + "1946dabf6a03a2a2c3d0b05080aed6fc", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=1", + ), + ( + "d9dc4dba3021b05d67c0518f72b62bf1", + "5ed301d747d3cc715445ebdec62f2fb4", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=2", + ), + ( + "a291d86301a4a739f7392173aa3c604c", + "6585c8f43d13a6beab6419fc5935b9d0", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=3", + ), + ( + "4264b2696498de4df79788a9f83e9390", + "2a5b56a596680fcc0e05f5e0f151ecae", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-256: I=4", + ), + ( + "ee9932b3721804d5a83ef5949245b6f6", + "f5d6ff414fd2c6181494d20c37f2b8c4", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-256: I=5", + ), + ( + "e6248f55c5fdcbca9cbbb01c88a2ea77", + "85399c01f59fffb5204f19f8482f00b8", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-256: I=6", + ), + ( + "b8358e41b9dff65fd461d55a99266247", + "92097b4c88a041ddf98144bc8d22e8e7", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-256: I=7", + ), + ( + "f0e2d72260af58e21e015ab3a4c0d906", + "89bd5b73b356ab412aef9f76cea2d65c", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-256: I=8", + ), + ( + "475b8b823ce8893db3c44a9f2a379ff7", + "2536969093c55ff9454692f2fac2f530", + "40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-256: I=9", + ), + ( + "688f5281945812862f5f3076cf80412f", + "07fc76a872843f3f6e0081ee9396d637", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-256: I=10", + ), + ( + "08d1d2bc750af553365d35e75afaceaa", + "e38ba8ec2aa741358dcc93e8f141c491", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-256: I=11", + ), + ( + "8707121f47cc3efceca5f9a8474950a1", + "d028ee23e4a89075d0b03e868d7d3a42", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-256: I=12", + ), + ( + "e51aa0b135dba566939c3b6359a980c5", + "8cd9423dfc459e547155c5d1d522e540", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-256: I=13", + ), + ( + "069a007fc76a459f98baf917fedf9521", + "080e9517eb1677719acf728086040ae3", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-256: I=14", + ), + ( + "726165c1723fbcf6c026d7d00b091027", + "7c1700211a3991fc0ecded0ab3e576b0", + "30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-256: I=15", + ), + ( + "d7c544de91d55cfcde1f84ca382200ce", + "dabcbcc855839251db51e224fbe87435", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-256: I=16", + ), + ( + "fed3c9a161b9b5b2bd611b41dc9da357", + "68d56fad0406947a4dd27a7448c10f1d", + "80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-256: I=17", + ), + ( + "4f634cdc6551043409f30b635832cf82", + "da9a11479844d1ffee24bbf3719a9925", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-256: I=18", + ), + ( + "109ce98db0dfb36734d9f3394711b4e6", + "5e4ba572f8d23e738da9b05ba24b8d81", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-256: I=19", + ), + ( + "4ea6dfaba2d8a02ffdffa89835987242", + "a115a2065d667e3f0b883837a6e903f8", + "70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-256: I=20", + ), + ( + "5ae094f54af58e6e3cdbf976dac6d9ef", + "3e9e90dc33eac2437d86ad30b137e66e", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-256: I=21", + ), + ( + "764d8e8e0f29926dbe5122e66354fdbe", + "01ce82d8fbcdae824cb3c48e495c3692", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-256: I=22", + ), + ( + "3f0418f888cdf29a982bf6b75410d6a9", + "0c9cff163ce936faaf083cfd3dea3117", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-256: I=23", + ), + ( + "e4a3e7cb12cdd56aa4a75197a9530220", + "5131ba9bd48f2bba85560680df504b52", + "10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-256: I=24", + ), + ( + "211677684aac1ec1a160f44c4ebf3f26", + "9dc503bbf09823aec8a977a5ad26ccb2", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-256: I=25", + ), + ( + "d21e439ff749ac8f18d6d4b105e03895", + "9a6db0c0862e506a9e397225884041d7", + "60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-256: I=26", + ), + ( + "d9f6ff44646c4725bd4c0103ff5552a7", + "430bf9570804185e1ab6365fc6a6860c", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-256: I=27", + ), + ( + "0b1256c2a00b976250cfc5b0c37ed382", + "3525ebc02f4886e6a5a3762813e8ce8a", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-256: I=28", + ), + ( + "b056447ffc6dc4523a36cc2e972a3a79", + "07fa265c763779cce224c7bad671027b", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-256: I=29", + ), + ( + "5e25ca78f0de55802524d38da3fe4456", + "e8b72b4e8be243438c9fff1f0e205872", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=30", + ), + ( + "a5bcf4728fa5eaad8567c0dc24675f83", + "109d4f999a0e11ace1f05e6b22cbcb50", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=31", + ), + ( + "814e59f97ed84646b78b2ca022e9ca43", + "45a5e8d4c3ed58403ff08d68a0cc4029", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=32", + ), + ( + "15478beec58f4775c7a7f5d4395514d7", + "196865964db3d417b6bd4d586bcb7634", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-256: I=33", + ), + ( + "253548ffca461c67c8cbc78cd59f4756", + "60436ad45ac7d30d99195f815d98d2ae", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-256: I=34", + ), + ( + "fd7ad8d73b9b0f8cc41600640f503d65", + "bb07a23f0b61014b197620c185e2cd75", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-256: I=35", + ), + ( + "06199de52c6cbf8af954cd65830bcd56", + "5bc0b2850129c854423aff0751fe343b", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-256: I=36", + ), + ( + "f17c4ffe48e44c61bd891e257e725794", + "7541a78f96738e6417d2a24bd2beca40", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-256: I=37", + ), + ( + "9a5b4a402a3e8a59be6bf5cd8154f029", + "b0a303054412882e464591f1546c5b9e", + "40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-256: I=38", + ), + ( + "79bd40b91a7e07dc939d441782ae6b17", + "778c06d8a355eeee214fcea14b4e0eef", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-256: I=39", + ), + ( + "d8ceaaf8976e5fbe1012d8c84f323799", + "09614206d15cbace63227d06db6beebb", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-256: I=40", + ), + ( + "3316e2751e2e388b083da23dd6ac3fbe", + "41b97fb20e427a9fdbbb358d9262255d", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-256: I=41", + ), + ( + "8b7cfbe37de7dca793521819242c5816", + "c1940f703d845f957652c2d64abd7adf", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-256: I=42", + ), + ( + "f23f033c0eebf8ec55752662fd58ce68", + "d2d44fcdae5332343366db297efcf21b", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-256: I=43", + ), + ( + "59eb34f6c8bdbacc5fc6ad73a59a1301", + "ea8196b79dbe167b6aa9896e287eed2b", + "30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-256: I=44", + ), + ( + "dcde8b6bd5cf7cc22d9505e3ce81261a", + "d6b0b0c4ba6c7dbe5ed467a1e3f06c2d", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-256: I=45", + ), + ( + "e33cf7e524fed781e7042ff9f4b35dc7", + "ec51eb295250c22c2fb01816fb72bcae", + "80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-256: I=46", + ), + ( + "27963c8facdf73062867d164df6d064c", + "aded6630a07ce9c7408a155d3bd0d36f", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-256: I=47", + ), + ( + "77b1ce386b551b995f2f2a1da994eef8", + "697c9245b9937f32f5d1c82319f0363a", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-256: I=48", + ), + ( + "f083388b013679efcf0bb9b15d52ae5c", + "aad5ad50c6262aaec30541a1b7b5b19c", + "f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-256: I=49", + ), + ( + "c5009e0dab55db0abdb636f2600290c8", + "7d34b893855341ec625bd6875ac18c0d", + "20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546", + "ecb-tbl-256: I=50", + ), + ( + "7804881e26cd532d8514d3683f00f1b9", + "7ef05105440f83862f5d780e88f02b41", + "48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-256: I=51", + ), + ( + "46cddcd73d1eb53e675ca012870a92a3", + "c377c06403382061af2c9c93a8e70df6", + "70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-256: I=52", + ), + ( + "a9fb44062bb07fe130a8e8299eacb1ab", + "1dbdb3ffdc052dacc83318853abc6de5", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-256: I=53", + ), + ( + "2b6ff8d7a5cc3a28a22d5a6f221af26b", + "69a6eab00432517d0bf483c91c0963c7", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-256: I=54", + ), + ( + "1a9527c29b8add4b0e3e656dbb2af8b4", + "0797f41dc217c80446e1d514bd6ab197", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-256: I=55", + ), + ( + "7f99cf2c75244df015eb4b0c1050aeae", + "9dfd76575902a637c01343c58e011a03", + "10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-256: I=56", + ), + ( + "e84ff85b0d9454071909c1381646c4ed", + "acf4328ae78f34b9fa9b459747cc2658", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-256: I=57", + ), + ( + "89afd40f99521280d5399b12404f6db4", + "b0479aea12bac4fe2384cf98995150c6", + "60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-256: I=58", + ), + ( + "a09ef32dbc5119a35ab7fa38656f0329", + "9dd52789efe3ffb99f33b3da5030109a", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-256: I=59", + ), + ( + "61773457f068c376c7829b93e696e716", + "abbb755e4621ef8f1214c19f649fb9fd", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-256: I=60", + ), + ( + "a34f0cae726cce41dd498747d891b967", + "da27fb8174357bce2bed0e7354f380f9", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-256: I=61", + ), + ( + "856f59496c7388ee2d2b1a27b7697847", + "c59a0663f0993838f6e5856593bdc5ef", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=62", + ), + ( + "cb090c593ef7720bd95908fb93b49df4", + "ed60b264b5213e831607a99c0ce5e57e", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=63", + ), + ( + "a0ac75cd2f1923d460fc4d457ad95baf", + "e50548746846f3eb77b8c520640884ed", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=64", + ), + ( + "2a2b282974777689e8e9eeef525d5c5f", + "28282cc7d21d6a2923641e52d188ef0c", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-256: I=65", + ), + ( + "909192939390919e0f0e09089788898a", + "0dfa5b02abb18e5a815305216d6d4f8e", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-256: I=66", + ), + ( + "777675748d8e8f907170777649464744", + "7359635c0eecefe31d673395fb46fb99", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-256: I=67", + ), + ( + "717073720605040b2d2c2b2a05fafbf9", + "73c679f7d5aef2745c9737bb4c47fb36", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-256: I=68", + ), + ( + "64656667fefdfcc31b1a1d1ca5aaaba8", + "b192bd472a4d2eafb786e97458967626", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-256: I=69", + ), + ( + "dbdad9d86a696867b5b4b3b2c8d7d6d5", + "0ec327f6c8a2b147598ca3fde61dc6a4", + "40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-256: I=70", + ), + ( + "5c5d5e5fe3e0e1fe31303736333c3d3e", + "fc418eb3c41b859b38d4b6f646629729", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-256: I=71", + ), + ( + "545556574b48494673727574546b6a69", + "30249e5ac282b1c981ea64b609f3a154", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-256: I=72", + ), + ( + "ecedeeefc6c5c4bb56575051f5fafbf8", + "5e6e08646d12150776bb43c2d78a9703", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-256: I=73", + ), + ( + "464744452724252ac9c8cfced2cdcccf", + "faeb3d5de652cd3447dceb343f30394a", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-256: I=74", + ), + ( + "e6e7e4e54142435c878681801c131211", + "a8e88706823f6993ef80d05c1c7b2cf0", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-256: I=75", + ), + ( + "72737071cfcccdc2f9f8fffe710e0f0c", + "8ced86677e6e00a1a1b15968f2d3cce6", + "30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-256: I=76", + ), + ( + "505152537370714ec3c2c5c4010e0f0c", + "9fc7c23858be03bdebb84e90db6786a9", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-256: I=77", + ), + ( + "a8a9aaab5c5f5e51aeafa8a93d222320", + "b4fbd65b33f70d8cf7f1111ac4649c36", + "80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-256: I=78", + ), + ( + "dedfdcddf6f5f4eb10111617fef1f0f3", + "c5c32d5ed03c4b53cc8c1bd0ef0dbbf6", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-256: I=79", + ), + ( + "bdbcbfbe5e5d5c530b0a0d0cfac5c4c7", + "d1a7f03b773e5c212464b63709c6a891", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-256: I=80", + ), + ( + "8a8b8889050606f8f4f5f2f3636c6d6e", + "6b7161d8745947ac6950438ea138d028", + "f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-256: I=81", + ), + ( + "a6a7a4a54d4e4f40b2b3b4b539262724", + "fd47a9f7e366ee7a09bc508b00460661", + "20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546", + "ecb-tbl-256: I=82", + ), + ( + "9c9d9e9fe9eaebf40e0f08099b949596", + "00d40b003dc3a0d9310b659b98c7e416", + "48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-256: I=83", + ), + ( + "2d2c2f2e1013121dcccdcacbed121310", + "eea4c79dcc8e2bda691f20ac48be0717", + "70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-256: I=84", + ), + ( + "f4f5f6f7edeeefd0eaebecedf7f8f9fa", + "e78f43b11c204403e5751f89d05a2509", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-256: I=85", + ), + ( + "3d3c3f3e282b2a2573727574150a0b08", + "d0f0e3d1f1244bb979931e38dd1786ef", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-256: I=86", + ), + ( + "b6b7b4b5f8fbfae5b4b5b2b3a0afaead", + "042e639dc4e1e4dde7b75b749ea6f765", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-256: I=87", + ), + ( + "b7b6b5b4989b9a95878681809ba4a5a6", + "bc032fdd0efe29503a980a7d07ab46a8", + "10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-256: I=88", + ), + ( + "a8a9aaabe5e6e798e9e8efee4748494a", + "0c93ac949c0da6446effb86183b6c910", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-256: I=89", + ), + ( + "ecedeeefd9dadbd4b9b8bfbe657a7b78", + "e0d343e14da75c917b4a5cec4810d7c2", + "60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-256: I=90", + ), + ( + "7f7e7d7c696a6b74cacbcccd929d9c9f", + "0eafb821748408279b937b626792e619", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-256: I=91", + ), + ( + "08090a0b0605040bfffef9f8b9c6c7c4", + "fa1ac6e02d23b106a1fef18b274a553f", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-256: I=92", + ), + ( + "08090a0bf1f2f3ccfcfdfafb68676665", + "0dadfe019cd12368075507df33c1a1e9", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-256: I=93", + ), + ( + "cacbc8c93a393837050403020d121310", + "3a0879b414465d9ffbaf86b33a63a1b9", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=94", + ), + ( + "e9e8ebea8281809f8f8e8988343b3a39", + "62199fadc76d0be1805d3ba0b7d914bf", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=95", + ), + ( + "515053524645444bd0d1d6d7340b0a09", + "1b06d6c5d333e742730130cf78e719b4", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=96", + ), + ( + "42434041ecefee1193929594c6c9c8cb", + "f1f848824c32e9dcdcbf21580f069329", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-256: I=97", + ), + ( + "efeeedecc2c1c0cf76777071455a5b58", + "1a09050cbd684f784d8e965e0782f28a", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-256: I=98", + ), + ( + "5f5e5d5c3f3c3d221d1c1b1a19161714", + "79c2969e7ded2ba7d088f3f320692360", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-256: I=99", + ), + ( + "000102034142434c1c1d1a1b8d727371", + "091a658a2f7444c16accb669450c7b63", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-256: I=100", + ), + ( + "8e8f8c8db1b2b38c56575051050a0b08", + "97c1e3a72cca65fa977d5ed0e8a7bbfc", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-256: I=101", + ), + ( + "a7a6a5a4e8ebeae57f7e7978cad5d4d7", + "70c430c6db9a17828937305a2df91a2a", + "40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-256: I=102", + ), + ( + "8a8b888994979689454443429f909192", + "629553457fbe2479098571c7c903fde8", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-256: I=103", + ), + ( + "8c8d8e8fe0e3e2ed45444342f1cecfcc", + "a25b25a61f612669e7d91265c7d476ba", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-256: I=104", + ), + ( + "fffefdfc4c4f4e31d8d9dedfb6b9b8bb", + "eb7e4e49b8ae0f024570dda293254fed", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-256: I=105", + ), + ( + "fdfcfffecccfcec12f2e29286679787b", + "38fe15d61cca84516e924adce5014f67", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-256: I=106", + ), + ( + "67666564bab9b8a77071767719161714", + "3ad208492249108c9f3ebeb167ad0583", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-256: I=107", + ), + ( + "9a9b98992d2e2f2084858283245b5a59", + "299ba9f9bf5ab05c3580fc26edd1ed12", + "30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-256: I=108", + ), + ( + "a4a5a6a70b0809365c5d5a5b2c232221", + "19dc705b857a60fb07717b2ea5717781", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-256: I=109", + ), + ( + "464744455754555af3f2f5f4afb0b1b2", + "ffc8aeb885b5efcad06b6dbebf92e76b", + "80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-256: I=110", + ), + ( + "323330317675746b7273747549464744", + "f58900c5e0b385253ff2546250a0142b", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-256: I=111", + ), + ( + "a8a9aaab181b1a15808186872b141516", + "2ee67b56280bc462429cee6e3370cbc1", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-256: I=112", + ), + ( + "e7e6e5e4202323ddaaabacad343b3a39", + "20db650a9c8e9a84ab4d25f7edc8f03f", + "f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-256: I=113", + ), + ( + "a8a9aaab2221202fedecebea1e010003", + "3c36da169525cf818843805f25b78ae5", + "20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546", + "ecb-tbl-256: I=114", + ), + ( + "f9f8fbfa5f5c5d42424344450e010003", + "9a781d960db9e45e37779042fea51922", + "48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-256: I=115", + ), + ( + "57565554f5f6f7f89697909120dfdedd", + "6560395ec269c672a3c288226efdba77", + "70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-256: I=116", + ), + ( + "f8f9fafbcccfcef1dddcdbda0e010003", + "8c772b7a189ac544453d5916ebb27b9a", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-256: I=117", + ), + ( + "d9d8dbda7073727d80818687c2dddcdf", + "77ca5468cc48e843d05f78eed9d6578f", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-256: I=118", + ), + ( + "c5c4c7c6080b0a1588898e8f68676665", + "72cdcc71dc82c60d4429c9e2d8195baa", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-256: I=119", + ), + ( + "83828180dcdfded186878081f0cfcecd", + "8080d68ce60e94b40b5b8b69eeb35afa", + "10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-256: I=120", + ), + ( + "98999a9bdddedfa079787f7e0a050407", + "44222d3cde299c04369d58ac0eba1e8e", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-256: I=121", + ), + ( + "cecfcccd4f4c4d429f9e9998dfc0c1c2", + "9b8721b0a8dfc691c5bc5885dbfcb27a", + "60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-256: I=122", + ), + ( + "404142436665647b29282f2eaba4a5a6", + "0dc015ce9a3a3414b5e62ec643384183", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-256: I=123", + ), + ( + "33323130e6e5e4eb23222524dea1a0a3", + "705715448a8da412025ce38345c2a148", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-256: I=124", + ), + ( + "cfcecdccf6f5f4cbe6e7e0e199969794", + "c32b5b0b6fbae165266c569f4b6ecf0b", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-256: I=125", + ), + ( + "babbb8b97271707fdcdddadb29363734", + "4dca6c75192a01ddca9476af2a521e87", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=126", + ), + ( + "c9c8cbca4447465926272021545b5a59", + "058691e627ecbc36ac07b6db423bd698", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=127", + ), + ( + "050407067477767956575051221d1c1f", + "7444527095838fe080fc2bcdd30847eb", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=128", + ), + # FIPS PUB 800-38A test vectors, 2001 edition. Annex F. + ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "3ad77bb40d7a3660a89ecaf32466ef97" + + "f5d3d58503b9699de785895a96fdbaaf" + + "43b1cd7f598ece23881b00e3ed030688" + + "7b0c785e27e8ad3f8223207104725dd4", + "2b7e151628aed2a6abf7158809cf4f3c", + "NIST 800-38A, F.1.1, ECB and AES-128", + ), + ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "bd334f1d6e45f25ff712a214571fa5cc" + + "974104846d0ad3ad7734ecb3ecee4eef" + + "ef7afd2270e2e60adce0ba2face6444e" + + "9a4b41ba738d6c72fb16691603c18e0e", + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", + "NIST 800-38A, F.1.3, ECB and AES-192", + ), + ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "f3eed1bdb5d2a03c064b5a7e3db181f8" + + "591ccb10d410ed26dc5ba74a31362870" + + "b6ed21b99ca6f4f9f153e7b1beafed1d" + + "23304b7a39f9f3ff067d8d8f9e24ecc7", + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", + "NIST 800-38A, F.1.3, ECB and AES-256", + ), ] test_data_8_lanes = [] for td in test_data: - test_data_8_lanes.append((td[0] * 8, td[1] * 8, td[2], td[3])) + test_data_8_lanes.append((td[0] * 8, td[1] * 8, td[2], td[3])) test_data += test_data_8_lanes -class TestMultipleBlocks(unittest.TestCase): - def __init__(self, use_aesni): - unittest.TestCase.__init__(self) - self.use_aesni = use_aesni - - def runTest(self): - # Encrypt data which is 8*2+4 bytes long, so as to trigger (for the - # AESNI variant) both the path that parallelizes 8 lanes and the one - # that processes data serially +class TestMultipleBlocks(unittest.TestCase): + def __init__(self, use_aesni): + unittest.TestCase.__init__(self) + self.use_aesni = use_aesni - tvs = [ - (b'a' * 16, 'c0b27011eb15bf144d2fc9fae80ea16d4c231cb230416c5fac02e6835ad9d7d0'), - (b'a' * 24, 'df8435ce361a78c535b41dcb57da952abbf9ee5954dc6fbcd75fd00fa626915d'), - (b'a' * 32, '211402de6c80db1f92ba255881178e1f70783b8cfd3b37808205e48b80486cd8') - ] + def runTest(self): + # Encrypt data which is 8*2+4 bytes long, so as to trigger (for the + # AESNI variant) both the path that parallelizes 8 lanes and the one + # that processes data serially - for key, expected in tvs: + tvs = [ + (b"a" * 16, "c0b27011eb15bf144d2fc9fae80ea16d4c231cb230416c5fac02e6835ad9d7d0"), + (b"a" * 24, "df8435ce361a78c535b41dcb57da952abbf9ee5954dc6fbcd75fd00fa626915d"), + (b"a" * 32, "211402de6c80db1f92ba255881178e1f70783b8cfd3b37808205e48b80486cd8"), + ] - cipher = AES.new(key, AES.MODE_ECB, use_aesni=self.use_aesni) - h = SHA256.new() + for key, expected in tvs: + cipher = AES.new(key, AES.MODE_ECB, use_aesni=self.use_aesni) + h = SHA256.new() - pt = b"".join([ tobytes('{0:016x}'.format(x)) for x in range(20) ]) - ct = cipher.encrypt(pt) - self.assertEqual(SHA256.new(ct).hexdigest(), expected) + pt = b"".join([tobytes("{0:016x}".format(x)) for x in range(20)]) + ct = cipher.encrypt(pt) + self.assertEqual(SHA256.new(ct).hexdigest(), expected) class TestIncompleteBlocks(unittest.TestCase): + def __init__(self, use_aesni): + unittest.TestCase.__init__(self) + self.use_aesni = use_aesni - def __init__(self, use_aesni): - unittest.TestCase.__init__(self) - self.use_aesni = use_aesni + def runTest(self): + # Encrypt data with length not multiple of 16 bytes - def runTest(self): - # Encrypt data with length not multiple of 16 bytes + cipher = AES.new(b"4" * 16, AES.MODE_ECB, use_aesni=self.use_aesni) - cipher = AES.new(b'4'*16, AES.MODE_ECB, use_aesni=self.use_aesni) + for msg_len in range(1, 16): + self.assertRaises(ValueError, cipher.encrypt, b"1" * msg_len) + self.assertRaises(ValueError, cipher.encrypt, b"1" * (msg_len + 16)) + self.assertRaises(ValueError, cipher.decrypt, b"1" * msg_len) + self.assertRaises(ValueError, cipher.decrypt, b"1" * (msg_len + 16)) - for msg_len in range(1, 16): - self.assertRaises(ValueError, cipher.encrypt, b'1' * msg_len) - self.assertRaises(ValueError, cipher.encrypt, b'1' * (msg_len+16)) - self.assertRaises(ValueError, cipher.decrypt, b'1' * msg_len) - self.assertRaises(ValueError, cipher.decrypt, b'1' * (msg_len+16)) - - self.assertEqual(cipher.encrypt(b''), b'') - self.assertEqual(cipher.decrypt(b''), b'') + self.assertEqual(cipher.encrypt(b""), b"") + self.assertEqual(cipher.decrypt(b""), b"") class TestOutput(unittest.TestCase): + def __init__(self, use_aesni): + unittest.TestCase.__init__(self) + self.use_aesni = use_aesni + + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def __init__(self, use_aesni): - unittest.TestCase.__init__(self) - self.use_aesni = use_aesni + cipher = AES.new(b"4" * 16, AES.MODE_ECB, use_aesni=self.use_aesni) - def runTest(self): - # Encrypt/Decrypt data and test output parameter + pt = b"5" * 16 + ct = cipher.encrypt(pt) - cipher = AES.new(b'4'*16, AES.MODE_ECB, use_aesni=self.use_aesni) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - shorter_output = bytearray(15) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(15) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from Cryptodome.Util import _cpu_features - from .common import make_block_tests + from Cryptodome.Util import _cpu_features + from .common import make_block_tests + + tests = make_block_tests(AES, "AES", test_data, {"use_aesni": False}) + tests += [TestMultipleBlocks(False)] + tests += [TestIncompleteBlocks(False)] + if _cpu_features.have_aes_ni(): + # Run tests with AES-NI instructions if they are available. + tests += make_block_tests(AES, "AESNI", test_data, {"use_aesni": True}) + tests += [TestMultipleBlocks(True)] + tests += [TestIncompleteBlocks(True)] + tests += [TestOutput(True)] + else: + print("Skipping AESNI tests") + return tests + - tests = make_block_tests(AES, "AES", test_data, {'use_aesni': False}) - tests += [ TestMultipleBlocks(False) ] - tests += [ TestIncompleteBlocks(False) ] - if _cpu_features.have_aes_ni(): - # Run tests with AES-NI instructions if they are available. - tests += make_block_tests(AES, "AESNI", test_data, {'use_aesni': True}) - tests += [ TestMultipleBlocks(True) ] - tests += [ TestIncompleteBlocks(True) ] - tests += [ TestOutput(True) ] - else: - print("Skipping AESNI tests") - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ARC2.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ARC2.py index 00725069..861638a6 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ARC2.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ARC2.py @@ -32,136 +32,242 @@ # This is a list of (plaintext, ciphertext, key[, description[, extra_params]]) tuples. test_data = [ - # Test vectors from RFC 2268 - - # 63-bit effective key length - ('0000000000000000', 'ebb773f993278eff', '0000000000000000', - 'RFC2268-1', dict(effective_keylen=63)), - - # 64-bit effective key length - ('ffffffffffffffff', '278b27e42e2f0d49', 'ffffffffffffffff', - 'RFC2268-2', dict(effective_keylen=64)), - ('1000000000000001', '30649edf9be7d2c2', '3000000000000000', - 'RFC2268-3', dict(effective_keylen=64)), - #('0000000000000000', '61a8a244adacccf0', '88', - # 'RFC2268-4', dict(effective_keylen=64)), - ('0000000000000000', '6ccf4308974c267f', '88bca90e90875a', - 'RFC2268-5', dict(effective_keylen=64)), - ('0000000000000000', '1a807d272bbe5db1', '88bca90e90875a7f0f79c384627bafb2', - 'RFC2268-6', dict(effective_keylen=64)), - - # 128-bit effective key length - ('0000000000000000', '2269552ab0f85ca6', '88bca90e90875a7f0f79c384627bafb2', - "RFC2268-7", dict(effective_keylen=128)), - ('0000000000000000', '5b78d3a43dfff1f1', - '88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e', - "RFC2268-8", dict(effective_keylen=129)), - - # Test vectors from PyCryptodome 2.0.1's testdata.py - # 1024-bit effective key length - ('0000000000000000', '624fb3e887419e48', '5068696c6970476c617373', - 'PCTv201-0'), - ('ffffffffffffffff', '79cadef44c4a5a85', '5068696c6970476c617373', - 'PCTv201-1'), - ('0001020304050607', '90411525b34e4c2c', '5068696c6970476c617373', - 'PCTv201-2'), - ('0011223344556677', '078656aaba61cbfb', '5068696c6970476c617373', - 'PCTv201-3'), - ('0000000000000000', 'd7bcc5dbb4d6e56a', 'ffffffffffffffff', - 'PCTv201-4'), - ('ffffffffffffffff', '7259018ec557b357', 'ffffffffffffffff', - 'PCTv201-5'), - ('0001020304050607', '93d20a497f2ccb62', 'ffffffffffffffff', - 'PCTv201-6'), - ('0011223344556677', 'cb15a7f819c0014d', 'ffffffffffffffff', - 'PCTv201-7'), - ('0000000000000000', '63ac98cdf3843a7a', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', - 'PCTv201-8'), - ('ffffffffffffffff', '3fb49e2fa12371dd', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', - 'PCTv201-9'), - ('0001020304050607', '46414781ab387d5f', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', - 'PCTv201-10'), - ('0011223344556677', 'be09dc81feaca271', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', - 'PCTv201-11'), - ('0000000000000000', 'e64221e608be30ab', '53e5ffe553', - 'PCTv201-12'), - ('ffffffffffffffff', '862bc60fdcd4d9a9', '53e5ffe553', - 'PCTv201-13'), - ('0001020304050607', '6a34da50fa5e47de', '53e5ffe553', - 'PCTv201-14'), - ('0011223344556677', '584644c34503122c', '53e5ffe553', - 'PCTv201-15'), + # Test vectors from RFC 2268 + # 63-bit effective key length + ( + "0000000000000000", + "ebb773f993278eff", + "0000000000000000", + "RFC2268-1", + dict(effective_keylen=63), + ), + # 64-bit effective key length + ( + "ffffffffffffffff", + "278b27e42e2f0d49", + "ffffffffffffffff", + "RFC2268-2", + dict(effective_keylen=64), + ), + ( + "1000000000000001", + "30649edf9be7d2c2", + "3000000000000000", + "RFC2268-3", + dict(effective_keylen=64), + ), + # ('0000000000000000', '61a8a244adacccf0', '88', + # 'RFC2268-4', dict(effective_keylen=64)), + ( + "0000000000000000", + "6ccf4308974c267f", + "88bca90e90875a", + "RFC2268-5", + dict(effective_keylen=64), + ), + ( + "0000000000000000", + "1a807d272bbe5db1", + "88bca90e90875a7f0f79c384627bafb2", + "RFC2268-6", + dict(effective_keylen=64), + ), + # 128-bit effective key length + ( + "0000000000000000", + "2269552ab0f85ca6", + "88bca90e90875a7f0f79c384627bafb2", + "RFC2268-7", + dict(effective_keylen=128), + ), + ( + "0000000000000000", + "5b78d3a43dfff1f1", + "88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e", + "RFC2268-8", + dict(effective_keylen=129), + ), + # Test vectors from PyCryptodome 2.0.1's testdata.py + # 1024-bit effective key length + ( + "0000000000000000", + "624fb3e887419e48", + "5068696c6970476c617373", + "PCTv201-0", + ), + ( + "ffffffffffffffff", + "79cadef44c4a5a85", + "5068696c6970476c617373", + "PCTv201-1", + ), + ( + "0001020304050607", + "90411525b34e4c2c", + "5068696c6970476c617373", + "PCTv201-2", + ), + ( + "0011223344556677", + "078656aaba61cbfb", + "5068696c6970476c617373", + "PCTv201-3", + ), + ( + "0000000000000000", + "d7bcc5dbb4d6e56a", + "ffffffffffffffff", + "PCTv201-4", + ), + ( + "ffffffffffffffff", + "7259018ec557b357", + "ffffffffffffffff", + "PCTv201-5", + ), + ( + "0001020304050607", + "93d20a497f2ccb62", + "ffffffffffffffff", + "PCTv201-6", + ), + ( + "0011223344556677", + "cb15a7f819c0014d", + "ffffffffffffffff", + "PCTv201-7", + ), + ( + "0000000000000000", + "63ac98cdf3843a7a", + "ffffffffffffffff5065746572477265656e6177617953e5ffe553", + "PCTv201-8", + ), + ( + "ffffffffffffffff", + "3fb49e2fa12371dd", + "ffffffffffffffff5065746572477265656e6177617953e5ffe553", + "PCTv201-9", + ), + ( + "0001020304050607", + "46414781ab387d5f", + "ffffffffffffffff5065746572477265656e6177617953e5ffe553", + "PCTv201-10", + ), + ( + "0011223344556677", + "be09dc81feaca271", + "ffffffffffffffff5065746572477265656e6177617953e5ffe553", + "PCTv201-11", + ), + ( + "0000000000000000", + "e64221e608be30ab", + "53e5ffe553", + "PCTv201-12", + ), + ( + "ffffffffffffffff", + "862bc60fdcd4d9a9", + "53e5ffe553", + "PCTv201-13", + ), + ( + "0001020304050607", + "6a34da50fa5e47de", + "53e5ffe553", + "PCTv201-14", + ), + ( + "0011223344556677", + "584644c34503122c", + "53e5ffe553", + "PCTv201-15", + ), ] + class BufferOverflowTest(unittest.TestCase): - # Test a buffer overflow found in older versions of PyCrypto + # Test a buffer overflow found in older versions of PyCrypto - def runTest(self): - """ARC2 with keylength > 128""" - key = b("x") * 16384 - self.assertRaises(ValueError, ARC2.new, key, ARC2.MODE_ECB) + def runTest(self): + """ARC2 with keylength > 128""" + key = b("x") * 16384 + self.assertRaises(ValueError, ARC2.new, key, ARC2.MODE_ECB) -class KeyLength(unittest.TestCase): - def runTest(self): - ARC2.new(b'\x00' * 16, ARC2.MODE_ECB, effective_keylen=40) - self.assertRaises(ValueError, ARC2.new, bchr(0) * 4, ARC2.MODE_ECB) - self.assertRaises(ValueError, ARC2.new, bchr(0) * 129, ARC2.MODE_ECB) +class KeyLength(unittest.TestCase): + def runTest(self): + ARC2.new(b"\x00" * 16, ARC2.MODE_ECB, effective_keylen=40) + self.assertRaises(ValueError, ARC2.new, bchr(0) * 4, ARC2.MODE_ECB) + self.assertRaises(ValueError, ARC2.new, bchr(0) * 129, ARC2.MODE_ECB) - self.assertRaises(ValueError, ARC2.new, bchr(0) * 16, ARC2.MODE_ECB, - effective_keylen=39) - self.assertRaises(ValueError, ARC2.new, bchr(0) * 16, ARC2.MODE_ECB, - effective_keylen=1025) + self.assertRaises( + ValueError, + ARC2.new, + bchr(0) * 16, + ARC2.MODE_ECB, + effective_keylen=39, + ) + self.assertRaises( + ValueError, + ARC2.new, + bchr(0) * 16, + ARC2.MODE_ECB, + effective_keylen=1025, + ) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter + cipher = ARC2.new(b"4" * 16, ARC2.MODE_ECB) - cipher = ARC2.new(b'4'*16, ARC2.MODE_ECB) + pt = b"5" * 16 + ct = cipher.encrypt(pt) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) + + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from Cryptodome.Cipher import ARC2 - from .common import make_block_tests + from Cryptodome.Cipher import ARC2 + from .common import make_block_tests + + tests = make_block_tests(ARC2, "ARC2", test_data) + tests.append(BufferOverflowTest()) + tests.append(KeyLength()) + tests += [TestOutput()] + + return tests - tests = make_block_tests(ARC2, "ARC2", test_data) - tests.append(BufferOverflowTest()) - tests.append(KeyLength()) - tests += [TestOutput()] - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ARC4.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ARC4.py index a160c983..4bbf5988 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ARC4.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ARC4.py @@ -34,438 +34,455 @@ # This is a list of (plaintext, ciphertext, key[, description]) tuples. test_data = [ - # Test vectors from Eric Rescorla's message with the subject - # "RC4 compatibility testing", sent to the cipherpunks mailing list on - # September 13, 1994. - # http://cypherpunks.venona.com/date/1994/09/msg00420.html - - ('0123456789abcdef', '75b7878099e0c596', '0123456789abcdef', - 'Test vector 0'), - - ('0000000000000000', '7494c2e7104b0879', '0123456789abcdef', - 'Test vector 1'), - - ('0000000000000000', 'de188941a3375d3a', '0000000000000000', - 'Test vector 2'), - - ('00000000000000000000', 'd6a141a7ec3c38dfbd61', 'ef012345', - 'Test vector 3'), - - ('01' * 512, - '7595c3e6114a09780c4ad452338e1ffd9a1be9498f813d76533449b6778dcad8' - + 'c78a8d2ba9ac66085d0e53d59c26c2d1c490c1ebbe0ce66d1b6b1b13b6b919b8' - + '47c25a91447a95e75e4ef16779cde8bf0a95850e32af9689444fd377108f98fd' - + 'cbd4e726567500990bcc7e0ca3c4aaa304a387d20f3b8fbbcd42a1bd311d7a43' - + '03dda5ab078896ae80c18b0af66dff319616eb784e495ad2ce90d7f772a81747' - + 'b65f62093b1e0db9e5ba532fafec47508323e671327df9444432cb7367cec82f' - + '5d44c0d00b67d650a075cd4b70dedd77eb9b10231b6b5b741347396d62897421' - + 'd43df9b42e446e358e9c11a9b2184ecbef0cd8e7a877ef968f1390ec9b3d35a5' - + '585cb009290e2fcde7b5ec66d9084be44055a619d9dd7fc3166f9487f7cb2729' - + '12426445998514c15d53a18c864ce3a2b7555793988126520eacf2e3066e230c' - + '91bee4dd5304f5fd0405b35bd99c73135d3d9bc335ee049ef69b3867bf2d7bd1' - + 'eaa595d8bfc0066ff8d31509eb0c6caa006c807a623ef84c3d33c195d23ee320' - + 'c40de0558157c822d4b8c569d849aed59d4e0fd7f379586b4b7ff684ed6a189f' - + '7486d49b9c4bad9ba24b96abf924372c8a8fffb10d55354900a77a3db5f205e1' - + 'b99fcd8660863a159ad4abe40fa48934163ddde542a6585540fd683cbfd8c00f' - + '12129a284deacc4cdefe58be7137541c047126c8d49e2755ab181ab7e940b0c0', - '0123456789abcdef', - "Test vector 4"), - # shortest key - generated with arc4 package - ('7468697320697320616e206578616d706c65', - '7260677d38495a09585d69321e17eaf3cdd0', - '01'), + # Test vectors from Eric Rescorla's message with the subject + # "RC4 compatibility testing", sent to the cipherpunks mailing list on + # September 13, 1994. + # http://cypherpunks.venona.com/date/1994/09/msg00420.html + ( + "0123456789abcdef", + "75b7878099e0c596", + "0123456789abcdef", + "Test vector 0", + ), + ( + "0000000000000000", + "7494c2e7104b0879", + "0123456789abcdef", + "Test vector 1", + ), + ( + "0000000000000000", + "de188941a3375d3a", + "0000000000000000", + "Test vector 2", + ), + ( + "00000000000000000000", + "d6a141a7ec3c38dfbd61", + "ef012345", + "Test vector 3", + ), + ( + "01" * 512, + "7595c3e6114a09780c4ad452338e1ffd9a1be9498f813d76533449b6778dcad8" + + "c78a8d2ba9ac66085d0e53d59c26c2d1c490c1ebbe0ce66d1b6b1b13b6b919b8" + + "47c25a91447a95e75e4ef16779cde8bf0a95850e32af9689444fd377108f98fd" + + "cbd4e726567500990bcc7e0ca3c4aaa304a387d20f3b8fbbcd42a1bd311d7a43" + + "03dda5ab078896ae80c18b0af66dff319616eb784e495ad2ce90d7f772a81747" + + "b65f62093b1e0db9e5ba532fafec47508323e671327df9444432cb7367cec82f" + + "5d44c0d00b67d650a075cd4b70dedd77eb9b10231b6b5b741347396d62897421" + + "d43df9b42e446e358e9c11a9b2184ecbef0cd8e7a877ef968f1390ec9b3d35a5" + + "585cb009290e2fcde7b5ec66d9084be44055a619d9dd7fc3166f9487f7cb2729" + + "12426445998514c15d53a18c864ce3a2b7555793988126520eacf2e3066e230c" + + "91bee4dd5304f5fd0405b35bd99c73135d3d9bc335ee049ef69b3867bf2d7bd1" + + "eaa595d8bfc0066ff8d31509eb0c6caa006c807a623ef84c3d33c195d23ee320" + + "c40de0558157c822d4b8c569d849aed59d4e0fd7f379586b4b7ff684ed6a189f" + + "7486d49b9c4bad9ba24b96abf924372c8a8fffb10d55354900a77a3db5f205e1" + + "b99fcd8660863a159ad4abe40fa48934163ddde542a6585540fd683cbfd8c00f" + + "12129a284deacc4cdefe58be7137541c047126c8d49e2755ab181ab7e940b0c0", + "0123456789abcdef", + "Test vector 4", + ), + # shortest key - generated with arc4 package + ( + "7468697320697320616e206578616d706c65", + "7260677d38495a09585d69321e17eaf3cdd0", + "01", + ), ] class RFC6229_Tests(unittest.TestCase): - # Test vectors from RFC 6229. Each test vector is a tuple with two items: - # the ARC4 key and a dictionary. The dictionary has keystream offsets as keys - # and the 16-byte keystream starting at the relevant offset as value. - rfc6229_data = [ - # Page 3 - ( - '0102030405', - { - 0: 'b2 39 63 05 f0 3d c0 27 cc c3 52 4a 0a 11 18 a8', - 16: '69 82 94 4f 18 fc 82 d5 89 c4 03 a4 7a 0d 09 19', - 240: '28 cb 11 32 c9 6c e2 86 42 1d ca ad b8 b6 9e ae', - 256: '1c fc f6 2b 03 ed db 64 1d 77 df cf 7f 8d 8c 93', - 496: '42 b7 d0 cd d9 18 a8 a3 3d d5 17 81 c8 1f 40 41', - 512: '64 59 84 44 32 a7 da 92 3c fb 3e b4 98 06 61 f6', - 752: 'ec 10 32 7b de 2b ee fd 18 f9 27 76 80 45 7e 22', - 768: 'eb 62 63 8d 4f 0b a1 fe 9f ca 20 e0 5b f8 ff 2b', - 1008: '45 12 90 48 e6 a0 ed 0b 56 b4 90 33 8f 07 8d a5', - 1024: '30 ab bc c7 c2 0b 01 60 9f 23 ee 2d 5f 6b b7 df', - 1520: '32 94 f7 44 d8 f9 79 05 07 e7 0f 62 e5 bb ce ea', - 1536: 'd8 72 9d b4 18 82 25 9b ee 4f 82 53 25 f5 a1 30', - 2032: '1e b1 4a 0c 13 b3 bf 47 fa 2a 0b a9 3a d4 5b 8b', - 2048: 'cc 58 2f 8b a9 f2 65 e2 b1 be 91 12 e9 75 d2 d7', - 3056: 'f2 e3 0f 9b d1 02 ec bf 75 aa ad e9 bc 35 c4 3c', - 3072: 'ec 0e 11 c4 79 dc 32 9d c8 da 79 68 fe 96 56 81', - 4080: '06 83 26 a2 11 84 16 d2 1f 9d 04 b2 cd 1c a0 50', - 4096: 'ff 25 b5 89 95 99 67 07 e5 1f bd f0 8b 34 d8 75' - } - ), - # Page 4 - ( - '01020304050607', - { - 0: '29 3f 02 d4 7f 37 c9 b6 33 f2 af 52 85 fe b4 6b', - 16: 'e6 20 f1 39 0d 19 bd 84 e2 e0 fd 75 20 31 af c1', - 240: '91 4f 02 53 1c 92 18 81 0d f6 0f 67 e3 38 15 4c', - 256: 'd0 fd b5 83 07 3c e8 5a b8 39 17 74 0e c0 11 d5', - 496: '75 f8 14 11 e8 71 cf fa 70 b9 0c 74 c5 92 e4 54', - 512: '0b b8 72 02 93 8d ad 60 9e 87 a5 a1 b0 79 e5 e4', - 752: 'c2 91 12 46 b6 12 e7 e7 b9 03 df ed a1 da d8 66', - 768: '32 82 8f 91 50 2b 62 91 36 8d e8 08 1d e3 6f c2', - 1008: 'f3 b9 a7 e3 b2 97 bf 9a d8 04 51 2f 90 63 ef f1', - 1024: '8e cb 67 a9 ba 1f 55 a5 a0 67 e2 b0 26 a3 67 6f', - 1520: 'd2 aa 90 2b d4 2d 0d 7c fd 34 0c d4 58 10 52 9f', - 1536: '78 b2 72 c9 6e 42 ea b4 c6 0b d9 14 e3 9d 06 e3', - 2032: 'f4 33 2f d3 1a 07 93 96 ee 3c ee 3f 2a 4f f0 49', - 2048: '05 45 97 81 d4 1f da 7f 30 c1 be 7e 12 46 c6 23', - 3056: 'ad fd 38 68 b8 e5 14 85 d5 e6 10 01 7e 3d d6 09', - 3072: 'ad 26 58 1c 0c 5b e4 5f 4c ea 01 db 2f 38 05 d5', - 4080: 'f3 17 2c ef fc 3b 3d 99 7c 85 cc d5 af 1a 95 0c', - 4096: 'e7 4b 0b 97 31 22 7f d3 7c 0e c0 8a 47 dd d8 b8' - } - ), - ( - '0102030405060708', - { - 0: '97 ab 8a 1b f0 af b9 61 32 f2 f6 72 58 da 15 a8', - 16: '82 63 ef db 45 c4 a1 86 84 ef 87 e6 b1 9e 5b 09', - 240: '96 36 eb c9 84 19 26 f4 f7 d1 f3 62 bd df 6e 18', - 256: 'd0 a9 90 ff 2c 05 fe f5 b9 03 73 c9 ff 4b 87 0a', - 496: '73 23 9f 1d b7 f4 1d 80 b6 43 c0 c5 25 18 ec 63', - 512: '16 3b 31 99 23 a6 bd b4 52 7c 62 61 26 70 3c 0f', - 752: '49 d6 c8 af 0f 97 14 4a 87 df 21 d9 14 72 f9 66', - 768: '44 17 3a 10 3b 66 16 c5 d5 ad 1c ee 40 c8 63 d0', - 1008: '27 3c 9c 4b 27 f3 22 e4 e7 16 ef 53 a4 7d e7 a4', - 1024: 'c6 d0 e7 b2 26 25 9f a9 02 34 90 b2 61 67 ad 1d', - 1520: '1f e8 98 67 13 f0 7c 3d 9a e1 c1 63 ff 8c f9 d3', - 1536: '83 69 e1 a9 65 61 0b e8 87 fb d0 c7 91 62 aa fb', - 2032: '0a 01 27 ab b4 44 84 b9 fb ef 5a bc ae 1b 57 9f', - 2048: 'c2 cd ad c6 40 2e 8e e8 66 e1 f3 7b db 47 e4 2c', - 3056: '26 b5 1e a3 7d f8 e1 d6 f7 6f c3 b6 6a 74 29 b3', - 3072: 'bc 76 83 20 5d 4f 44 3d c1 f2 9d da 33 15 c8 7b', - 4080: 'd5 fa 5a 34 69 d2 9a aa f8 3d 23 58 9d b8 c8 5b', - 4096: '3f b4 6e 2c 8f 0f 06 8e dc e8 cd cd 7d fc 58 62' - } - ), - # Page 5 - ( - '0102030405060708090a', - { - 0: 'ed e3 b0 46 43 e5 86 cc 90 7d c2 18 51 70 99 02', - 16: '03 51 6b a7 8f 41 3b eb 22 3a a5 d4 d2 df 67 11', - 240: '3c fd 6c b5 8e e0 fd de 64 01 76 ad 00 00 04 4d', - 256: '48 53 2b 21 fb 60 79 c9 11 4c 0f fd 9c 04 a1 ad', - 496: '3e 8c ea 98 01 71 09 97 90 84 b1 ef 92 f9 9d 86', - 512: 'e2 0f b4 9b db 33 7e e4 8b 8d 8d c0 f4 af ef fe', - 752: '5c 25 21 ea cd 79 66 f1 5e 05 65 44 be a0 d3 15', - 768: 'e0 67 a7 03 19 31 a2 46 a6 c3 87 5d 2f 67 8a cb', - 1008: 'a6 4f 70 af 88 ae 56 b6 f8 75 81 c0 e2 3e 6b 08', - 1024: 'f4 49 03 1d e3 12 81 4e c6 f3 19 29 1f 4a 05 16', - 1520: 'bd ae 85 92 4b 3c b1 d0 a2 e3 3a 30 c6 d7 95 99', - 1536: '8a 0f ed db ac 86 5a 09 bc d1 27 fb 56 2e d6 0a', - 2032: 'b5 5a 0a 5b 51 a1 2a 8b e3 48 99 c3 e0 47 51 1a', - 2048: 'd9 a0 9c ea 3c e7 5f e3 96 98 07 03 17 a7 13 39', - 3056: '55 22 25 ed 11 77 f4 45 84 ac 8c fa 6c 4e b5 fc', - 3072: '7e 82 cb ab fc 95 38 1b 08 09 98 44 21 29 c2 f8', - 4080: '1f 13 5e d1 4c e6 0a 91 36 9d 23 22 be f2 5e 3c', - 4096: '08 b6 be 45 12 4a 43 e2 eb 77 95 3f 84 dc 85 53' - } - ), - ( - '0102030405060708090a0b0c0d0e0f10', - { - 0: '9a c7 cc 9a 60 9d 1e f7 b2 93 28 99 cd e4 1b 97', - 16: '52 48 c4 95 90 14 12 6a 6e 8a 84 f1 1d 1a 9e 1c', - 240: '06 59 02 e4 b6 20 f6 cc 36 c8 58 9f 66 43 2f 2b', - 256: 'd3 9d 56 6b c6 bc e3 01 07 68 15 15 49 f3 87 3f', - 496: 'b6 d1 e6 c4 a5 e4 77 1c ad 79 53 8d f2 95 fb 11', - 512: 'c6 8c 1d 5c 55 9a 97 41 23 df 1d bc 52 a4 3b 89', - 752: 'c5 ec f8 8d e8 97 fd 57 fe d3 01 70 1b 82 a2 59', - 768: 'ec cb e1 3d e1 fc c9 1c 11 a0 b2 6c 0b c8 fa 4d', - 1008: 'e7 a7 25 74 f8 78 2a e2 6a ab cf 9e bc d6 60 65', - 1024: 'bd f0 32 4e 60 83 dc c6 d3 ce dd 3c a8 c5 3c 16', - 1520: 'b4 01 10 c4 19 0b 56 22 a9 61 16 b0 01 7e d2 97', - 1536: 'ff a0 b5 14 64 7e c0 4f 63 06 b8 92 ae 66 11 81', - 2032: 'd0 3d 1b c0 3c d3 3d 70 df f9 fa 5d 71 96 3e bd', - 2048: '8a 44 12 64 11 ea a7 8b d5 1e 8d 87 a8 87 9b f5', - 3056: 'fa be b7 60 28 ad e2 d0 e4 87 22 e4 6c 46 15 a3', - 3072: 'c0 5d 88 ab d5 03 57 f9 35 a6 3c 59 ee 53 76 23', - 4080: 'ff 38 26 5c 16 42 c1 ab e8 d3 c2 fe 5e 57 2b f8', - 4096: 'a3 6a 4c 30 1a e8 ac 13 61 0c cb c1 22 56 ca cc' - } - ), - # Page 6 - ( - '0102030405060708090a0b0c0d0e0f101112131415161718', - { - 0: '05 95 e5 7f e5 f0 bb 3c 70 6e da c8 a4 b2 db 11', - 16: 'df de 31 34 4a 1a f7 69 c7 4f 07 0a ee 9e 23 26', - 240: 'b0 6b 9b 1e 19 5d 13 d8 f4 a7 99 5c 45 53 ac 05', - 256: '6b d2 37 8e c3 41 c9 a4 2f 37 ba 79 f8 8a 32 ff', - 496: 'e7 0b ce 1d f7 64 5a db 5d 2c 41 30 21 5c 35 22', - 512: '9a 57 30 c7 fc b4 c9 af 51 ff da 89 c7 f1 ad 22', - 752: '04 85 05 5f d4 f6 f0 d9 63 ef 5a b9 a5 47 69 82', - 768: '59 1f c6 6b cd a1 0e 45 2b 03 d4 55 1f 6b 62 ac', - 1008: '27 53 cc 83 98 8a fa 3e 16 88 a1 d3 b4 2c 9a 02', - 1024: '93 61 0d 52 3d 1d 3f 00 62 b3 c2 a3 bb c7 c7 f0', - 1520: '96 c2 48 61 0a ad ed fe af 89 78 c0 3d e8 20 5a', - 1536: '0e 31 7b 3d 1c 73 b9 e9 a4 68 8f 29 6d 13 3a 19', - 2032: 'bd f0 e6 c3 cc a5 b5 b9 d5 33 b6 9c 56 ad a1 20', - 2048: '88 a2 18 b6 e2 ec e1 e6 24 6d 44 c7 59 d1 9b 10', - 3056: '68 66 39 7e 95 c1 40 53 4f 94 26 34 21 00 6e 40', - 3072: '32 cb 0a 1e 95 42 c6 b3 b8 b3 98 ab c3 b0 f1 d5', - 4080: '29 a0 b8 ae d5 4a 13 23 24 c6 2e 42 3f 54 b4 c8', - 4096: '3c b0 f3 b5 02 0a 98 b8 2a f9 fe 15 44 84 a1 68' - } - ), - ( - '0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', - { - 0: 'ea a6 bd 25 88 0b f9 3d 3f 5d 1e 4c a2 61 1d 91', - 16: 'cf a4 5c 9f 7e 71 4b 54 bd fa 80 02 7c b1 43 80', - 240: '11 4a e3 44 de d7 1b 35 f2 e6 0f eb ad 72 7f d8', - 256: '02 e1 e7 05 6b 0f 62 39 00 49 64 22 94 3e 97 b6', - 496: '91 cb 93 c7 87 96 4e 10 d9 52 7d 99 9c 6f 93 6b', - 512: '49 b1 8b 42 f8 e8 36 7c be b5 ef 10 4b a1 c7 cd', - 752: '87 08 4b 3b a7 00 ba de 95 56 10 67 27 45 b3 74', - 768: 'e7 a7 b9 e9 ec 54 0d 5f f4 3b db 12 79 2d 1b 35', - 1008: 'c7 99 b5 96 73 8f 6b 01 8c 76 c7 4b 17 59 bd 90', - 1024: '7f ec 5b fd 9f 9b 89 ce 65 48 30 90 92 d7 e9 58', - 1520: '40 f2 50 b2 6d 1f 09 6a 4a fd 4c 34 0a 58 88 15', - 1536: '3e 34 13 5c 79 db 01 02 00 76 76 51 cf 26 30 73', - 2032: 'f6 56 ab cc f8 8d d8 27 02 7b 2c e9 17 d4 64 ec', - 2048: '18 b6 25 03 bf bc 07 7f ba bb 98 f2 0d 98 ab 34', - 3056: '8a ed 95 ee 5b 0d cb fb ef 4e b2 1d 3a 3f 52 f9', - 3072: '62 5a 1a b0 0e e3 9a 53 27 34 6b dd b0 1a 9c 18', - 4080: 'a1 3a 7c 79 c7 e1 19 b5 ab 02 96 ab 28 c3 00 b9', - 4096: 'f3 e4 c0 a2 e0 2d 1d 01 f7 f0 a7 46 18 af 2b 48' - } - ), - # Page 7 - ( - '833222772a', - { - 0: '80 ad 97 bd c9 73 df 8a 2e 87 9e 92 a4 97 ef da', - 16: '20 f0 60 c2 f2 e5 12 65 01 d3 d4 fe a1 0d 5f c0', - 240: 'fa a1 48 e9 90 46 18 1f ec 6b 20 85 f3 b2 0e d9', - 256: 'f0 da f5 ba b3 d5 96 83 98 57 84 6f 73 fb fe 5a', - 496: '1c 7e 2f c4 63 92 32 fe 29 75 84 b2 96 99 6b c8', - 512: '3d b9 b2 49 40 6c c8 ed ff ac 55 cc d3 22 ba 12', - 752: 'e4 f9 f7 e0 06 61 54 bb d1 25 b7 45 56 9b c8 97', - 768: '75 d5 ef 26 2b 44 c4 1a 9c f6 3a e1 45 68 e1 b9', - 1008: '6d a4 53 db f8 1e 82 33 4a 3d 88 66 cb 50 a1 e3', - 1024: '78 28 d0 74 11 9c ab 5c 22 b2 94 d7 a9 bf a0 bb', - 1520: 'ad b8 9c ea 9a 15 fb e6 17 29 5b d0 4b 8c a0 5c', - 1536: '62 51 d8 7f d4 aa ae 9a 7e 4a d5 c2 17 d3 f3 00', - 2032: 'e7 11 9b d6 dd 9b 22 af e8 f8 95 85 43 28 81 e2', - 2048: '78 5b 60 fd 7e c4 e9 fc b6 54 5f 35 0d 66 0f ab', - 3056: 'af ec c0 37 fd b7 b0 83 8e b3 d7 0b cd 26 83 82', - 3072: 'db c1 a7 b4 9d 57 35 8c c9 fa 6d 61 d7 3b 7c f0', - 4080: '63 49 d1 26 a3 7a fc ba 89 79 4f 98 04 91 4f dc', - 4096: 'bf 42 c3 01 8c 2f 7c 66 bf de 52 49 75 76 81 15' - } - ), - ( - '1910833222772a', - { - 0: 'bc 92 22 db d3 27 4d 8f c6 6d 14 cc bd a6 69 0b', - 16: '7a e6 27 41 0c 9a 2b e6 93 df 5b b7 48 5a 63 e3', - 240: '3f 09 31 aa 03 de fb 30 0f 06 01 03 82 6f 2a 64', - 256: 'be aa 9e c8 d5 9b b6 81 29 f3 02 7c 96 36 11 81', - 496: '74 e0 4d b4 6d 28 64 8d 7d ee 8a 00 64 b0 6c fe', - 512: '9b 5e 81 c6 2f e0 23 c5 5b e4 2f 87 bb f9 32 b8', - 752: 'ce 17 8f c1 82 6e fe cb c1 82 f5 79 99 a4 61 40', - 768: '8b df 55 cd 55 06 1c 06 db a6 be 11 de 4a 57 8a', - 1008: '62 6f 5f 4d ce 65 25 01 f3 08 7d 39 c9 2c c3 49', - 1024: '42 da ac 6a 8f 9a b9 a7 fd 13 7c 60 37 82 56 82', - 1520: 'cc 03 fd b7 91 92 a2 07 31 2f 53 f5 d4 dc 33 d9', - 1536: 'f7 0f 14 12 2a 1c 98 a3 15 5d 28 b8 a0 a8 a4 1d', - 2032: '2a 3a 30 7a b2 70 8a 9c 00 fe 0b 42 f9 c2 d6 a1', - 2048: '86 26 17 62 7d 22 61 ea b0 b1 24 65 97 ca 0a e9', - 3056: '55 f8 77 ce 4f 2e 1d db bf 8e 13 e2 cd e0 fd c8', - 3072: '1b 15 56 cb 93 5f 17 33 37 70 5f bb 5d 50 1f c1', - 4080: 'ec d0 e9 66 02 be 7f 8d 50 92 81 6c cc f2 c2 e9', - 4096: '02 78 81 fa b4 99 3a 1c 26 20 24 a9 4f ff 3f 61' - } - ), - # Page 8 - ( - '641910833222772a', - { - 0: 'bb f6 09 de 94 13 17 2d 07 66 0c b6 80 71 69 26', - 16: '46 10 1a 6d ab 43 11 5d 6c 52 2b 4f e9 36 04 a9', - 240: 'cb e1 ff f2 1c 96 f3 ee f6 1e 8f e0 54 2c bd f0', - 256: '34 79 38 bf fa 40 09 c5 12 cf b4 03 4b 0d d1 a7', - 496: '78 67 a7 86 d0 0a 71 47 90 4d 76 dd f1 e5 20 e3', - 512: '8d 3e 9e 1c ae fc cc b3 fb f8 d1 8f 64 12 0b 32', - 752: '94 23 37 f8 fd 76 f0 fa e8 c5 2d 79 54 81 06 72', - 768: 'b8 54 8c 10 f5 16 67 f6 e6 0e 18 2f a1 9b 30 f7', - 1008: '02 11 c7 c6 19 0c 9e fd 12 37 c3 4c 8f 2e 06 c4', - 1024: 'bd a6 4f 65 27 6d 2a ac b8 f9 02 12 20 3a 80 8e', - 1520: 'bd 38 20 f7 32 ff b5 3e c1 93 e7 9d 33 e2 7c 73', - 1536: 'd0 16 86 16 86 19 07 d4 82 e3 6c da c8 cf 57 49', - 2032: '97 b0 f0 f2 24 b2 d2 31 71 14 80 8f b0 3a f7 a0', - 2048: 'e5 96 16 e4 69 78 79 39 a0 63 ce ea 9a f9 56 d1', - 3056: 'c4 7e 0d c1 66 09 19 c1 11 01 20 8f 9e 69 aa 1f', - 3072: '5a e4 f1 28 96 b8 37 9a 2a ad 89 b5 b5 53 d6 b0', - 4080: '6b 6b 09 8d 0c 29 3b c2 99 3d 80 bf 05 18 b6 d9', - 4096: '81 70 cc 3c cd 92 a6 98 62 1b 93 9d d3 8f e7 b9' - } - ), - ( - '8b37641910833222772a', - { - 0: 'ab 65 c2 6e dd b2 87 60 0d b2 fd a1 0d 1e 60 5c', - 16: 'bb 75 90 10 c2 96 58 f2 c7 2d 93 a2 d1 6d 29 30', - 240: 'b9 01 e8 03 6e d1 c3 83 cd 3c 4c 4d d0 a6 ab 05', - 256: '3d 25 ce 49 22 92 4c 55 f0 64 94 33 53 d7 8a 6c', - 496: '12 c1 aa 44 bb f8 7e 75 e6 11 f6 9b 2c 38 f4 9b', - 512: '28 f2 b3 43 4b 65 c0 98 77 47 00 44 c6 ea 17 0d', - 752: 'bd 9e f8 22 de 52 88 19 61 34 cf 8a f7 83 93 04', - 768: '67 55 9c 23 f0 52 15 84 70 a2 96 f7 25 73 5a 32', - 1008: '8b ab 26 fb c2 c1 2b 0f 13 e2 ab 18 5e ab f2 41', - 1024: '31 18 5a 6d 69 6f 0c fa 9b 42 80 8b 38 e1 32 a2', - 1520: '56 4d 3d ae 18 3c 52 34 c8 af 1e 51 06 1c 44 b5', - 1536: '3c 07 78 a7 b5 f7 2d 3c 23 a3 13 5c 7d 67 b9 f4', - 2032: 'f3 43 69 89 0f cf 16 fb 51 7d ca ae 44 63 b2 dd', - 2048: '02 f3 1c 81 e8 20 07 31 b8 99 b0 28 e7 91 bf a7', - 3056: '72 da 64 62 83 22 8c 14 30 08 53 70 17 95 61 6f', - 3072: '4e 0a 8c 6f 79 34 a7 88 e2 26 5e 81 d6 d0 c8 f4', - 4080: '43 8d d5 ea fe a0 11 1b 6f 36 b4 b9 38 da 2a 68', - 4096: '5f 6b fc 73 81 58 74 d9 71 00 f0 86 97 93 57 d8' - } - ), - # Page 9 - ( - 'ebb46227c6cc8b37641910833222772a', - { - 0: '72 0c 94 b6 3e df 44 e1 31 d9 50 ca 21 1a 5a 30', - 16: 'c3 66 fd ea cf 9c a8 04 36 be 7c 35 84 24 d2 0b', - 240: 'b3 39 4a 40 aa bf 75 cb a4 22 82 ef 25 a0 05 9f', - 256: '48 47 d8 1d a4 94 2d bc 24 9d ef c4 8c 92 2b 9f', - 496: '08 12 8c 46 9f 27 53 42 ad da 20 2b 2b 58 da 95', - 512: '97 0d ac ef 40 ad 98 72 3b ac 5d 69 55 b8 17 61', - 752: '3c b8 99 93 b0 7b 0c ed 93 de 13 d2 a1 10 13 ac', - 768: 'ef 2d 67 6f 15 45 c2 c1 3d c6 80 a0 2f 4a db fe', - 1008: 'b6 05 95 51 4f 24 bc 9f e5 22 a6 ca d7 39 36 44', - 1024: 'b5 15 a8 c5 01 17 54 f5 90 03 05 8b db 81 51 4e', - 1520: '3c 70 04 7e 8c bc 03 8e 3b 98 20 db 60 1d a4 95', - 1536: '11 75 da 6e e7 56 de 46 a5 3e 2b 07 56 60 b7 70', - 2032: '00 a5 42 bb a0 21 11 cc 2c 65 b3 8e bd ba 58 7e', - 2048: '58 65 fd bb 5b 48 06 41 04 e8 30 b3 80 f2 ae de', - 3056: '34 b2 1a d2 ad 44 e9 99 db 2d 7f 08 63 f0 d9 b6', - 3072: '84 a9 21 8f c3 6e 8a 5f 2c cf be ae 53 a2 7d 25', - 4080: 'a2 22 1a 11 b8 33 cc b4 98 a5 95 40 f0 54 5f 4a', - 4096: '5b be b4 78 7d 59 e5 37 3f db ea 6c 6f 75 c2 9b' - } - ), - ( - 'c109163908ebe51debb46227c6cc8b37641910833222772a', - { - 0: '54 b6 4e 6b 5a 20 b5 e2 ec 84 59 3d c7 98 9d a7', - 16: 'c1 35 ee e2 37 a8 54 65 ff 97 dc 03 92 4f 45 ce', - 240: 'cf cc 92 2f b4 a1 4a b4 5d 61 75 aa bb f2 d2 01', - 256: '83 7b 87 e2 a4 46 ad 0e f7 98 ac d0 2b 94 12 4f', - 496: '17 a6 db d6 64 92 6a 06 36 b3 f4 c3 7a 4f 46 94', - 512: '4a 5f 9f 26 ae ee d4 d4 a2 5f 63 2d 30 52 33 d9', - 752: '80 a3 d0 1e f0 0c 8e 9a 42 09 c1 7f 4e eb 35 8c', - 768: 'd1 5e 7d 5f fa aa bc 02 07 bf 20 0a 11 77 93 a2', - 1008: '34 96 82 bf 58 8e aa 52 d0 aa 15 60 34 6a ea fa', - 1024: 'f5 85 4c db 76 c8 89 e3 ad 63 35 4e 5f 72 75 e3', - 1520: '53 2c 7c ec cb 39 df 32 36 31 84 05 a4 b1 27 9c', - 1536: 'ba ef e6 d9 ce b6 51 84 22 60 e0 d1 e0 5e 3b 90', - 2032: 'e8 2d 8c 6d b5 4e 3c 63 3f 58 1c 95 2b a0 42 07', - 2048: '4b 16 e5 0a bd 38 1b d7 09 00 a9 cd 9a 62 cb 23', - 3056: '36 82 ee 33 bd 14 8b d9 f5 86 56 cd 8f 30 d9 fb', - 3072: '1e 5a 0b 84 75 04 5d 9b 20 b2 62 86 24 ed fd 9e', - 4080: '63 ed d6 84 fb 82 62 82 fe 52 8f 9c 0e 92 37 bc', - 4096: 'e4 dd 2e 98 d6 96 0f ae 0b 43 54 54 56 74 33 91' - } - ), - # Page 10 - ( - '1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a', - { - 0: 'dd 5b cb 00 18 e9 22 d4 94 75 9d 7c 39 5d 02 d3', - 16: 'c8 44 6f 8f 77 ab f7 37 68 53 53 eb 89 a1 c9 eb', - 240: 'af 3e 30 f9 c0 95 04 59 38 15 15 75 c3 fb 90 98', - 256: 'f8 cb 62 74 db 99 b8 0b 1d 20 12 a9 8e d4 8f 0e', - 496: '25 c3 00 5a 1c b8 5d e0 76 25 98 39 ab 71 98 ab', - 512: '9d cb c1 83 e8 cb 99 4b 72 7b 75 be 31 80 76 9c', - 752: 'a1 d3 07 8d fa 91 69 50 3e d9 d4 49 1d ee 4e b2', - 768: '85 14 a5 49 58 58 09 6f 59 6e 4b cd 66 b1 06 65', - 1008: '5f 40 d5 9e c1 b0 3b 33 73 8e fa 60 b2 25 5d 31', - 1024: '34 77 c7 f7 64 a4 1b ac ef f9 0b f1 4f 92 b7 cc', - 1520: 'ac 4e 95 36 8d 99 b9 eb 78 b8 da 8f 81 ff a7 95', - 1536: '8c 3c 13 f8 c2 38 8b b7 3f 38 57 6e 65 b7 c4 46', - 2032: '13 c4 b9 c1 df b6 65 79 ed dd 8a 28 0b 9f 73 16', - 2048: 'dd d2 78 20 55 01 26 69 8e fa ad c6 4b 64 f6 6e', - 3056: 'f0 8f 2e 66 d2 8e d1 43 f3 a2 37 cf 9d e7 35 59', - 3072: '9e a3 6c 52 55 31 b8 80 ba 12 43 34 f5 7b 0b 70', - 4080: 'd5 a3 9e 3d fc c5 02 80 ba c4 a6 b5 aa 0d ca 7d', - 4096: '37 0b 1c 1f e6 55 91 6d 97 fd 0d 47 ca 1d 72 b8' - } - ) - ] + # Test vectors from RFC 6229. Each test vector is a tuple with two items: + # the ARC4 key and a dictionary. The dictionary has keystream offsets as keys + # and the 16-byte keystream starting at the relevant offset as value. + rfc6229_data = [ + # Page 3 + ( + "0102030405", + { + 0: "b2 39 63 05 f0 3d c0 27 cc c3 52 4a 0a 11 18 a8", + 16: "69 82 94 4f 18 fc 82 d5 89 c4 03 a4 7a 0d 09 19", + 240: "28 cb 11 32 c9 6c e2 86 42 1d ca ad b8 b6 9e ae", + 256: "1c fc f6 2b 03 ed db 64 1d 77 df cf 7f 8d 8c 93", + 496: "42 b7 d0 cd d9 18 a8 a3 3d d5 17 81 c8 1f 40 41", + 512: "64 59 84 44 32 a7 da 92 3c fb 3e b4 98 06 61 f6", + 752: "ec 10 32 7b de 2b ee fd 18 f9 27 76 80 45 7e 22", + 768: "eb 62 63 8d 4f 0b a1 fe 9f ca 20 e0 5b f8 ff 2b", + 1008: "45 12 90 48 e6 a0 ed 0b 56 b4 90 33 8f 07 8d a5", + 1024: "30 ab bc c7 c2 0b 01 60 9f 23 ee 2d 5f 6b b7 df", + 1520: "32 94 f7 44 d8 f9 79 05 07 e7 0f 62 e5 bb ce ea", + 1536: "d8 72 9d b4 18 82 25 9b ee 4f 82 53 25 f5 a1 30", + 2032: "1e b1 4a 0c 13 b3 bf 47 fa 2a 0b a9 3a d4 5b 8b", + 2048: "cc 58 2f 8b a9 f2 65 e2 b1 be 91 12 e9 75 d2 d7", + 3056: "f2 e3 0f 9b d1 02 ec bf 75 aa ad e9 bc 35 c4 3c", + 3072: "ec 0e 11 c4 79 dc 32 9d c8 da 79 68 fe 96 56 81", + 4080: "06 83 26 a2 11 84 16 d2 1f 9d 04 b2 cd 1c a0 50", + 4096: "ff 25 b5 89 95 99 67 07 e5 1f bd f0 8b 34 d8 75", + }, + ), + # Page 4 + ( + "01020304050607", + { + 0: "29 3f 02 d4 7f 37 c9 b6 33 f2 af 52 85 fe b4 6b", + 16: "e6 20 f1 39 0d 19 bd 84 e2 e0 fd 75 20 31 af c1", + 240: "91 4f 02 53 1c 92 18 81 0d f6 0f 67 e3 38 15 4c", + 256: "d0 fd b5 83 07 3c e8 5a b8 39 17 74 0e c0 11 d5", + 496: "75 f8 14 11 e8 71 cf fa 70 b9 0c 74 c5 92 e4 54", + 512: "0b b8 72 02 93 8d ad 60 9e 87 a5 a1 b0 79 e5 e4", + 752: "c2 91 12 46 b6 12 e7 e7 b9 03 df ed a1 da d8 66", + 768: "32 82 8f 91 50 2b 62 91 36 8d e8 08 1d e3 6f c2", + 1008: "f3 b9 a7 e3 b2 97 bf 9a d8 04 51 2f 90 63 ef f1", + 1024: "8e cb 67 a9 ba 1f 55 a5 a0 67 e2 b0 26 a3 67 6f", + 1520: "d2 aa 90 2b d4 2d 0d 7c fd 34 0c d4 58 10 52 9f", + 1536: "78 b2 72 c9 6e 42 ea b4 c6 0b d9 14 e3 9d 06 e3", + 2032: "f4 33 2f d3 1a 07 93 96 ee 3c ee 3f 2a 4f f0 49", + 2048: "05 45 97 81 d4 1f da 7f 30 c1 be 7e 12 46 c6 23", + 3056: "ad fd 38 68 b8 e5 14 85 d5 e6 10 01 7e 3d d6 09", + 3072: "ad 26 58 1c 0c 5b e4 5f 4c ea 01 db 2f 38 05 d5", + 4080: "f3 17 2c ef fc 3b 3d 99 7c 85 cc d5 af 1a 95 0c", + 4096: "e7 4b 0b 97 31 22 7f d3 7c 0e c0 8a 47 dd d8 b8", + }, + ), + ( + "0102030405060708", + { + 0: "97 ab 8a 1b f0 af b9 61 32 f2 f6 72 58 da 15 a8", + 16: "82 63 ef db 45 c4 a1 86 84 ef 87 e6 b1 9e 5b 09", + 240: "96 36 eb c9 84 19 26 f4 f7 d1 f3 62 bd df 6e 18", + 256: "d0 a9 90 ff 2c 05 fe f5 b9 03 73 c9 ff 4b 87 0a", + 496: "73 23 9f 1d b7 f4 1d 80 b6 43 c0 c5 25 18 ec 63", + 512: "16 3b 31 99 23 a6 bd b4 52 7c 62 61 26 70 3c 0f", + 752: "49 d6 c8 af 0f 97 14 4a 87 df 21 d9 14 72 f9 66", + 768: "44 17 3a 10 3b 66 16 c5 d5 ad 1c ee 40 c8 63 d0", + 1008: "27 3c 9c 4b 27 f3 22 e4 e7 16 ef 53 a4 7d e7 a4", + 1024: "c6 d0 e7 b2 26 25 9f a9 02 34 90 b2 61 67 ad 1d", + 1520: "1f e8 98 67 13 f0 7c 3d 9a e1 c1 63 ff 8c f9 d3", + 1536: "83 69 e1 a9 65 61 0b e8 87 fb d0 c7 91 62 aa fb", + 2032: "0a 01 27 ab b4 44 84 b9 fb ef 5a bc ae 1b 57 9f", + 2048: "c2 cd ad c6 40 2e 8e e8 66 e1 f3 7b db 47 e4 2c", + 3056: "26 b5 1e a3 7d f8 e1 d6 f7 6f c3 b6 6a 74 29 b3", + 3072: "bc 76 83 20 5d 4f 44 3d c1 f2 9d da 33 15 c8 7b", + 4080: "d5 fa 5a 34 69 d2 9a aa f8 3d 23 58 9d b8 c8 5b", + 4096: "3f b4 6e 2c 8f 0f 06 8e dc e8 cd cd 7d fc 58 62", + }, + ), + # Page 5 + ( + "0102030405060708090a", + { + 0: "ed e3 b0 46 43 e5 86 cc 90 7d c2 18 51 70 99 02", + 16: "03 51 6b a7 8f 41 3b eb 22 3a a5 d4 d2 df 67 11", + 240: "3c fd 6c b5 8e e0 fd de 64 01 76 ad 00 00 04 4d", + 256: "48 53 2b 21 fb 60 79 c9 11 4c 0f fd 9c 04 a1 ad", + 496: "3e 8c ea 98 01 71 09 97 90 84 b1 ef 92 f9 9d 86", + 512: "e2 0f b4 9b db 33 7e e4 8b 8d 8d c0 f4 af ef fe", + 752: "5c 25 21 ea cd 79 66 f1 5e 05 65 44 be a0 d3 15", + 768: "e0 67 a7 03 19 31 a2 46 a6 c3 87 5d 2f 67 8a cb", + 1008: "a6 4f 70 af 88 ae 56 b6 f8 75 81 c0 e2 3e 6b 08", + 1024: "f4 49 03 1d e3 12 81 4e c6 f3 19 29 1f 4a 05 16", + 1520: "bd ae 85 92 4b 3c b1 d0 a2 e3 3a 30 c6 d7 95 99", + 1536: "8a 0f ed db ac 86 5a 09 bc d1 27 fb 56 2e d6 0a", + 2032: "b5 5a 0a 5b 51 a1 2a 8b e3 48 99 c3 e0 47 51 1a", + 2048: "d9 a0 9c ea 3c e7 5f e3 96 98 07 03 17 a7 13 39", + 3056: "55 22 25 ed 11 77 f4 45 84 ac 8c fa 6c 4e b5 fc", + 3072: "7e 82 cb ab fc 95 38 1b 08 09 98 44 21 29 c2 f8", + 4080: "1f 13 5e d1 4c e6 0a 91 36 9d 23 22 be f2 5e 3c", + 4096: "08 b6 be 45 12 4a 43 e2 eb 77 95 3f 84 dc 85 53", + }, + ), + ( + "0102030405060708090a0b0c0d0e0f10", + { + 0: "9a c7 cc 9a 60 9d 1e f7 b2 93 28 99 cd e4 1b 97", + 16: "52 48 c4 95 90 14 12 6a 6e 8a 84 f1 1d 1a 9e 1c", + 240: "06 59 02 e4 b6 20 f6 cc 36 c8 58 9f 66 43 2f 2b", + 256: "d3 9d 56 6b c6 bc e3 01 07 68 15 15 49 f3 87 3f", + 496: "b6 d1 e6 c4 a5 e4 77 1c ad 79 53 8d f2 95 fb 11", + 512: "c6 8c 1d 5c 55 9a 97 41 23 df 1d bc 52 a4 3b 89", + 752: "c5 ec f8 8d e8 97 fd 57 fe d3 01 70 1b 82 a2 59", + 768: "ec cb e1 3d e1 fc c9 1c 11 a0 b2 6c 0b c8 fa 4d", + 1008: "e7 a7 25 74 f8 78 2a e2 6a ab cf 9e bc d6 60 65", + 1024: "bd f0 32 4e 60 83 dc c6 d3 ce dd 3c a8 c5 3c 16", + 1520: "b4 01 10 c4 19 0b 56 22 a9 61 16 b0 01 7e d2 97", + 1536: "ff a0 b5 14 64 7e c0 4f 63 06 b8 92 ae 66 11 81", + 2032: "d0 3d 1b c0 3c d3 3d 70 df f9 fa 5d 71 96 3e bd", + 2048: "8a 44 12 64 11 ea a7 8b d5 1e 8d 87 a8 87 9b f5", + 3056: "fa be b7 60 28 ad e2 d0 e4 87 22 e4 6c 46 15 a3", + 3072: "c0 5d 88 ab d5 03 57 f9 35 a6 3c 59 ee 53 76 23", + 4080: "ff 38 26 5c 16 42 c1 ab e8 d3 c2 fe 5e 57 2b f8", + 4096: "a3 6a 4c 30 1a e8 ac 13 61 0c cb c1 22 56 ca cc", + }, + ), + # Page 6 + ( + "0102030405060708090a0b0c0d0e0f101112131415161718", + { + 0: "05 95 e5 7f e5 f0 bb 3c 70 6e da c8 a4 b2 db 11", + 16: "df de 31 34 4a 1a f7 69 c7 4f 07 0a ee 9e 23 26", + 240: "b0 6b 9b 1e 19 5d 13 d8 f4 a7 99 5c 45 53 ac 05", + 256: "6b d2 37 8e c3 41 c9 a4 2f 37 ba 79 f8 8a 32 ff", + 496: "e7 0b ce 1d f7 64 5a db 5d 2c 41 30 21 5c 35 22", + 512: "9a 57 30 c7 fc b4 c9 af 51 ff da 89 c7 f1 ad 22", + 752: "04 85 05 5f d4 f6 f0 d9 63 ef 5a b9 a5 47 69 82", + 768: "59 1f c6 6b cd a1 0e 45 2b 03 d4 55 1f 6b 62 ac", + 1008: "27 53 cc 83 98 8a fa 3e 16 88 a1 d3 b4 2c 9a 02", + 1024: "93 61 0d 52 3d 1d 3f 00 62 b3 c2 a3 bb c7 c7 f0", + 1520: "96 c2 48 61 0a ad ed fe af 89 78 c0 3d e8 20 5a", + 1536: "0e 31 7b 3d 1c 73 b9 e9 a4 68 8f 29 6d 13 3a 19", + 2032: "bd f0 e6 c3 cc a5 b5 b9 d5 33 b6 9c 56 ad a1 20", + 2048: "88 a2 18 b6 e2 ec e1 e6 24 6d 44 c7 59 d1 9b 10", + 3056: "68 66 39 7e 95 c1 40 53 4f 94 26 34 21 00 6e 40", + 3072: "32 cb 0a 1e 95 42 c6 b3 b8 b3 98 ab c3 b0 f1 d5", + 4080: "29 a0 b8 ae d5 4a 13 23 24 c6 2e 42 3f 54 b4 c8", + 4096: "3c b0 f3 b5 02 0a 98 b8 2a f9 fe 15 44 84 a1 68", + }, + ), + ( + "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + { + 0: "ea a6 bd 25 88 0b f9 3d 3f 5d 1e 4c a2 61 1d 91", + 16: "cf a4 5c 9f 7e 71 4b 54 bd fa 80 02 7c b1 43 80", + 240: "11 4a e3 44 de d7 1b 35 f2 e6 0f eb ad 72 7f d8", + 256: "02 e1 e7 05 6b 0f 62 39 00 49 64 22 94 3e 97 b6", + 496: "91 cb 93 c7 87 96 4e 10 d9 52 7d 99 9c 6f 93 6b", + 512: "49 b1 8b 42 f8 e8 36 7c be b5 ef 10 4b a1 c7 cd", + 752: "87 08 4b 3b a7 00 ba de 95 56 10 67 27 45 b3 74", + 768: "e7 a7 b9 e9 ec 54 0d 5f f4 3b db 12 79 2d 1b 35", + 1008: "c7 99 b5 96 73 8f 6b 01 8c 76 c7 4b 17 59 bd 90", + 1024: "7f ec 5b fd 9f 9b 89 ce 65 48 30 90 92 d7 e9 58", + 1520: "40 f2 50 b2 6d 1f 09 6a 4a fd 4c 34 0a 58 88 15", + 1536: "3e 34 13 5c 79 db 01 02 00 76 76 51 cf 26 30 73", + 2032: "f6 56 ab cc f8 8d d8 27 02 7b 2c e9 17 d4 64 ec", + 2048: "18 b6 25 03 bf bc 07 7f ba bb 98 f2 0d 98 ab 34", + 3056: "8a ed 95 ee 5b 0d cb fb ef 4e b2 1d 3a 3f 52 f9", + 3072: "62 5a 1a b0 0e e3 9a 53 27 34 6b dd b0 1a 9c 18", + 4080: "a1 3a 7c 79 c7 e1 19 b5 ab 02 96 ab 28 c3 00 b9", + 4096: "f3 e4 c0 a2 e0 2d 1d 01 f7 f0 a7 46 18 af 2b 48", + }, + ), + # Page 7 + ( + "833222772a", + { + 0: "80 ad 97 bd c9 73 df 8a 2e 87 9e 92 a4 97 ef da", + 16: "20 f0 60 c2 f2 e5 12 65 01 d3 d4 fe a1 0d 5f c0", + 240: "fa a1 48 e9 90 46 18 1f ec 6b 20 85 f3 b2 0e d9", + 256: "f0 da f5 ba b3 d5 96 83 98 57 84 6f 73 fb fe 5a", + 496: "1c 7e 2f c4 63 92 32 fe 29 75 84 b2 96 99 6b c8", + 512: "3d b9 b2 49 40 6c c8 ed ff ac 55 cc d3 22 ba 12", + 752: "e4 f9 f7 e0 06 61 54 bb d1 25 b7 45 56 9b c8 97", + 768: "75 d5 ef 26 2b 44 c4 1a 9c f6 3a e1 45 68 e1 b9", + 1008: "6d a4 53 db f8 1e 82 33 4a 3d 88 66 cb 50 a1 e3", + 1024: "78 28 d0 74 11 9c ab 5c 22 b2 94 d7 a9 bf a0 bb", + 1520: "ad b8 9c ea 9a 15 fb e6 17 29 5b d0 4b 8c a0 5c", + 1536: "62 51 d8 7f d4 aa ae 9a 7e 4a d5 c2 17 d3 f3 00", + 2032: "e7 11 9b d6 dd 9b 22 af e8 f8 95 85 43 28 81 e2", + 2048: "78 5b 60 fd 7e c4 e9 fc b6 54 5f 35 0d 66 0f ab", + 3056: "af ec c0 37 fd b7 b0 83 8e b3 d7 0b cd 26 83 82", + 3072: "db c1 a7 b4 9d 57 35 8c c9 fa 6d 61 d7 3b 7c f0", + 4080: "63 49 d1 26 a3 7a fc ba 89 79 4f 98 04 91 4f dc", + 4096: "bf 42 c3 01 8c 2f 7c 66 bf de 52 49 75 76 81 15", + }, + ), + ( + "1910833222772a", + { + 0: "bc 92 22 db d3 27 4d 8f c6 6d 14 cc bd a6 69 0b", + 16: "7a e6 27 41 0c 9a 2b e6 93 df 5b b7 48 5a 63 e3", + 240: "3f 09 31 aa 03 de fb 30 0f 06 01 03 82 6f 2a 64", + 256: "be aa 9e c8 d5 9b b6 81 29 f3 02 7c 96 36 11 81", + 496: "74 e0 4d b4 6d 28 64 8d 7d ee 8a 00 64 b0 6c fe", + 512: "9b 5e 81 c6 2f e0 23 c5 5b e4 2f 87 bb f9 32 b8", + 752: "ce 17 8f c1 82 6e fe cb c1 82 f5 79 99 a4 61 40", + 768: "8b df 55 cd 55 06 1c 06 db a6 be 11 de 4a 57 8a", + 1008: "62 6f 5f 4d ce 65 25 01 f3 08 7d 39 c9 2c c3 49", + 1024: "42 da ac 6a 8f 9a b9 a7 fd 13 7c 60 37 82 56 82", + 1520: "cc 03 fd b7 91 92 a2 07 31 2f 53 f5 d4 dc 33 d9", + 1536: "f7 0f 14 12 2a 1c 98 a3 15 5d 28 b8 a0 a8 a4 1d", + 2032: "2a 3a 30 7a b2 70 8a 9c 00 fe 0b 42 f9 c2 d6 a1", + 2048: "86 26 17 62 7d 22 61 ea b0 b1 24 65 97 ca 0a e9", + 3056: "55 f8 77 ce 4f 2e 1d db bf 8e 13 e2 cd e0 fd c8", + 3072: "1b 15 56 cb 93 5f 17 33 37 70 5f bb 5d 50 1f c1", + 4080: "ec d0 e9 66 02 be 7f 8d 50 92 81 6c cc f2 c2 e9", + 4096: "02 78 81 fa b4 99 3a 1c 26 20 24 a9 4f ff 3f 61", + }, + ), + # Page 8 + ( + "641910833222772a", + { + 0: "bb f6 09 de 94 13 17 2d 07 66 0c b6 80 71 69 26", + 16: "46 10 1a 6d ab 43 11 5d 6c 52 2b 4f e9 36 04 a9", + 240: "cb e1 ff f2 1c 96 f3 ee f6 1e 8f e0 54 2c bd f0", + 256: "34 79 38 bf fa 40 09 c5 12 cf b4 03 4b 0d d1 a7", + 496: "78 67 a7 86 d0 0a 71 47 90 4d 76 dd f1 e5 20 e3", + 512: "8d 3e 9e 1c ae fc cc b3 fb f8 d1 8f 64 12 0b 32", + 752: "94 23 37 f8 fd 76 f0 fa e8 c5 2d 79 54 81 06 72", + 768: "b8 54 8c 10 f5 16 67 f6 e6 0e 18 2f a1 9b 30 f7", + 1008: "02 11 c7 c6 19 0c 9e fd 12 37 c3 4c 8f 2e 06 c4", + 1024: "bd a6 4f 65 27 6d 2a ac b8 f9 02 12 20 3a 80 8e", + 1520: "bd 38 20 f7 32 ff b5 3e c1 93 e7 9d 33 e2 7c 73", + 1536: "d0 16 86 16 86 19 07 d4 82 e3 6c da c8 cf 57 49", + 2032: "97 b0 f0 f2 24 b2 d2 31 71 14 80 8f b0 3a f7 a0", + 2048: "e5 96 16 e4 69 78 79 39 a0 63 ce ea 9a f9 56 d1", + 3056: "c4 7e 0d c1 66 09 19 c1 11 01 20 8f 9e 69 aa 1f", + 3072: "5a e4 f1 28 96 b8 37 9a 2a ad 89 b5 b5 53 d6 b0", + 4080: "6b 6b 09 8d 0c 29 3b c2 99 3d 80 bf 05 18 b6 d9", + 4096: "81 70 cc 3c cd 92 a6 98 62 1b 93 9d d3 8f e7 b9", + }, + ), + ( + "8b37641910833222772a", + { + 0: "ab 65 c2 6e dd b2 87 60 0d b2 fd a1 0d 1e 60 5c", + 16: "bb 75 90 10 c2 96 58 f2 c7 2d 93 a2 d1 6d 29 30", + 240: "b9 01 e8 03 6e d1 c3 83 cd 3c 4c 4d d0 a6 ab 05", + 256: "3d 25 ce 49 22 92 4c 55 f0 64 94 33 53 d7 8a 6c", + 496: "12 c1 aa 44 bb f8 7e 75 e6 11 f6 9b 2c 38 f4 9b", + 512: "28 f2 b3 43 4b 65 c0 98 77 47 00 44 c6 ea 17 0d", + 752: "bd 9e f8 22 de 52 88 19 61 34 cf 8a f7 83 93 04", + 768: "67 55 9c 23 f0 52 15 84 70 a2 96 f7 25 73 5a 32", + 1008: "8b ab 26 fb c2 c1 2b 0f 13 e2 ab 18 5e ab f2 41", + 1024: "31 18 5a 6d 69 6f 0c fa 9b 42 80 8b 38 e1 32 a2", + 1520: "56 4d 3d ae 18 3c 52 34 c8 af 1e 51 06 1c 44 b5", + 1536: "3c 07 78 a7 b5 f7 2d 3c 23 a3 13 5c 7d 67 b9 f4", + 2032: "f3 43 69 89 0f cf 16 fb 51 7d ca ae 44 63 b2 dd", + 2048: "02 f3 1c 81 e8 20 07 31 b8 99 b0 28 e7 91 bf a7", + 3056: "72 da 64 62 83 22 8c 14 30 08 53 70 17 95 61 6f", + 3072: "4e 0a 8c 6f 79 34 a7 88 e2 26 5e 81 d6 d0 c8 f4", + 4080: "43 8d d5 ea fe a0 11 1b 6f 36 b4 b9 38 da 2a 68", + 4096: "5f 6b fc 73 81 58 74 d9 71 00 f0 86 97 93 57 d8", + }, + ), + # Page 9 + ( + "ebb46227c6cc8b37641910833222772a", + { + 0: "72 0c 94 b6 3e df 44 e1 31 d9 50 ca 21 1a 5a 30", + 16: "c3 66 fd ea cf 9c a8 04 36 be 7c 35 84 24 d2 0b", + 240: "b3 39 4a 40 aa bf 75 cb a4 22 82 ef 25 a0 05 9f", + 256: "48 47 d8 1d a4 94 2d bc 24 9d ef c4 8c 92 2b 9f", + 496: "08 12 8c 46 9f 27 53 42 ad da 20 2b 2b 58 da 95", + 512: "97 0d ac ef 40 ad 98 72 3b ac 5d 69 55 b8 17 61", + 752: "3c b8 99 93 b0 7b 0c ed 93 de 13 d2 a1 10 13 ac", + 768: "ef 2d 67 6f 15 45 c2 c1 3d c6 80 a0 2f 4a db fe", + 1008: "b6 05 95 51 4f 24 bc 9f e5 22 a6 ca d7 39 36 44", + 1024: "b5 15 a8 c5 01 17 54 f5 90 03 05 8b db 81 51 4e", + 1520: "3c 70 04 7e 8c bc 03 8e 3b 98 20 db 60 1d a4 95", + 1536: "11 75 da 6e e7 56 de 46 a5 3e 2b 07 56 60 b7 70", + 2032: "00 a5 42 bb a0 21 11 cc 2c 65 b3 8e bd ba 58 7e", + 2048: "58 65 fd bb 5b 48 06 41 04 e8 30 b3 80 f2 ae de", + 3056: "34 b2 1a d2 ad 44 e9 99 db 2d 7f 08 63 f0 d9 b6", + 3072: "84 a9 21 8f c3 6e 8a 5f 2c cf be ae 53 a2 7d 25", + 4080: "a2 22 1a 11 b8 33 cc b4 98 a5 95 40 f0 54 5f 4a", + 4096: "5b be b4 78 7d 59 e5 37 3f db ea 6c 6f 75 c2 9b", + }, + ), + ( + "c109163908ebe51debb46227c6cc8b37641910833222772a", + { + 0: "54 b6 4e 6b 5a 20 b5 e2 ec 84 59 3d c7 98 9d a7", + 16: "c1 35 ee e2 37 a8 54 65 ff 97 dc 03 92 4f 45 ce", + 240: "cf cc 92 2f b4 a1 4a b4 5d 61 75 aa bb f2 d2 01", + 256: "83 7b 87 e2 a4 46 ad 0e f7 98 ac d0 2b 94 12 4f", + 496: "17 a6 db d6 64 92 6a 06 36 b3 f4 c3 7a 4f 46 94", + 512: "4a 5f 9f 26 ae ee d4 d4 a2 5f 63 2d 30 52 33 d9", + 752: "80 a3 d0 1e f0 0c 8e 9a 42 09 c1 7f 4e eb 35 8c", + 768: "d1 5e 7d 5f fa aa bc 02 07 bf 20 0a 11 77 93 a2", + 1008: "34 96 82 bf 58 8e aa 52 d0 aa 15 60 34 6a ea fa", + 1024: "f5 85 4c db 76 c8 89 e3 ad 63 35 4e 5f 72 75 e3", + 1520: "53 2c 7c ec cb 39 df 32 36 31 84 05 a4 b1 27 9c", + 1536: "ba ef e6 d9 ce b6 51 84 22 60 e0 d1 e0 5e 3b 90", + 2032: "e8 2d 8c 6d b5 4e 3c 63 3f 58 1c 95 2b a0 42 07", + 2048: "4b 16 e5 0a bd 38 1b d7 09 00 a9 cd 9a 62 cb 23", + 3056: "36 82 ee 33 bd 14 8b d9 f5 86 56 cd 8f 30 d9 fb", + 3072: "1e 5a 0b 84 75 04 5d 9b 20 b2 62 86 24 ed fd 9e", + 4080: "63 ed d6 84 fb 82 62 82 fe 52 8f 9c 0e 92 37 bc", + 4096: "e4 dd 2e 98 d6 96 0f ae 0b 43 54 54 56 74 33 91", + }, + ), + # Page 10 + ( + "1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a", + { + 0: "dd 5b cb 00 18 e9 22 d4 94 75 9d 7c 39 5d 02 d3", + 16: "c8 44 6f 8f 77 ab f7 37 68 53 53 eb 89 a1 c9 eb", + 240: "af 3e 30 f9 c0 95 04 59 38 15 15 75 c3 fb 90 98", + 256: "f8 cb 62 74 db 99 b8 0b 1d 20 12 a9 8e d4 8f 0e", + 496: "25 c3 00 5a 1c b8 5d e0 76 25 98 39 ab 71 98 ab", + 512: "9d cb c1 83 e8 cb 99 4b 72 7b 75 be 31 80 76 9c", + 752: "a1 d3 07 8d fa 91 69 50 3e d9 d4 49 1d ee 4e b2", + 768: "85 14 a5 49 58 58 09 6f 59 6e 4b cd 66 b1 06 65", + 1008: "5f 40 d5 9e c1 b0 3b 33 73 8e fa 60 b2 25 5d 31", + 1024: "34 77 c7 f7 64 a4 1b ac ef f9 0b f1 4f 92 b7 cc", + 1520: "ac 4e 95 36 8d 99 b9 eb 78 b8 da 8f 81 ff a7 95", + 1536: "8c 3c 13 f8 c2 38 8b b7 3f 38 57 6e 65 b7 c4 46", + 2032: "13 c4 b9 c1 df b6 65 79 ed dd 8a 28 0b 9f 73 16", + 2048: "dd d2 78 20 55 01 26 69 8e fa ad c6 4b 64 f6 6e", + 3056: "f0 8f 2e 66 d2 8e d1 43 f3 a2 37 cf 9d e7 35 59", + 3072: "9e a3 6c 52 55 31 b8 80 ba 12 43 34 f5 7b 0b 70", + 4080: "d5 a3 9e 3d fc c5 02 80 ba c4 a6 b5 aa 0d ca 7d", + 4096: "37 0b 1c 1f e6 55 91 6d 97 fd 0d 47 ca 1d 72 b8", + }, + ), + ] - def test_keystream(self): - for tv in self.rfc6229_data: - key = unhexlify(b((tv[0]))) - cipher = ARC4.new(key) - count = 0 - for offset in range(0, 4096+1, 16): - ct = cipher.encrypt(b('\x00')*16) - expected = tv[1].get(offset) - if expected: - expected = unhexlify(b(expected.replace(" ", ''))) - self.assertEqual(ct, expected) - count += 1 - self.assertEqual(count, len(tv[1])) + def test_keystream(self): + for tv in self.rfc6229_data: + key = unhexlify(b((tv[0]))) + cipher = ARC4.new(key) + count = 0 + for offset in range(0, 4096 + 1, 16): + ct = cipher.encrypt(b("\x00") * 16) + expected = tv[1].get(offset) + if expected: + expected = unhexlify(b(expected.replace(" ", ""))) + self.assertEqual(ct, expected) + count += 1 + self.assertEqual(count, len(tv[1])) class Drop_Tests(unittest.TestCase): - key = b('\xAA')*16 - data = b('\x00')*5000 + key = b("\xaa") * 16 + data = b("\x00") * 5000 - def setUp(self): - self.cipher = ARC4.new(self.key) + def setUp(self): + self.cipher = ARC4.new(self.key) - def test_drop256_encrypt(self): - cipher_drop = ARC4.new(self.key, 256) - ct_drop = cipher_drop.encrypt(self.data[:16]) - ct = self.cipher.encrypt(self.data)[256:256+16] - self.assertEqual(ct_drop, ct) + def test_drop256_encrypt(self): + cipher_drop = ARC4.new(self.key, 256) + ct_drop = cipher_drop.encrypt(self.data[:16]) + ct = self.cipher.encrypt(self.data)[256 : 256 + 16] + self.assertEqual(ct_drop, ct) - def test_drop256_decrypt(self): - cipher_drop = ARC4.new(self.key, 256) - pt_drop = cipher_drop.decrypt(self.data[:16]) - pt = self.cipher.decrypt(self.data)[256:256+16] - self.assertEqual(pt_drop, pt) + def test_drop256_decrypt(self): + cipher_drop = ARC4.new(self.key, 256) + pt_drop = cipher_drop.decrypt(self.data[:16]) + pt = self.cipher.decrypt(self.data)[256 : 256 + 16] + self.assertEqual(pt_drop, pt) class KeyLength(unittest.TestCase): - - def runTest(self): - self.assertRaises(ValueError, ARC4.new, b'') - self.assertRaises(ValueError, ARC4.new, b'\x00' * 257) + def runTest(self): + self.assertRaises(ValueError, ARC4.new, b"") + self.assertRaises(ValueError, ARC4.new, b"\x00" * 257) def get_tests(config={}): - from .common import make_stream_tests - tests = make_stream_tests(ARC4, "ARC4", test_data) - tests += list_test_cases(RFC6229_Tests) - tests += list_test_cases(Drop_Tests) - tests.append(KeyLength()) - return tests + from .common import make_stream_tests + + tests = make_stream_tests(ARC4, "ARC4", test_data) + tests += list_test_cases(RFC6229_Tests) + tests += list_test_cases(Drop_Tests) + tests.append(KeyLength()) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_Blowfish.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_Blowfish.py index ca5c6033..93efc56b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_Blowfish.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_Blowfish.py @@ -32,129 +32,164 @@ # This is a list of (plaintext, ciphertext, key) tuples. test_data = [ - # Test vectors from http://www.schneier.com/code/vectors.txt - ('0000000000000000', '4ef997456198dd78', '0000000000000000'), - ('ffffffffffffffff', '51866fd5b85ecb8a', 'ffffffffffffffff'), - ('1000000000000001', '7d856f9a613063f2', '3000000000000000'), - ('1111111111111111', '2466dd878b963c9d', '1111111111111111'), - ('1111111111111111', '61f9c3802281b096', '0123456789abcdef'), - ('0123456789abcdef', '7d0cc630afda1ec7', '1111111111111111'), - ('0000000000000000', '4ef997456198dd78', '0000000000000000'), - ('0123456789abcdef', '0aceab0fc6a0a28d', 'fedcba9876543210'), - ('01a1d6d039776742', '59c68245eb05282b', '7ca110454a1a6e57'), - ('5cd54ca83def57da', 'b1b8cc0b250f09a0', '0131d9619dc1376e'), - ('0248d43806f67172', '1730e5778bea1da4', '07a1133e4a0b2686'), - ('51454b582ddf440a', 'a25e7856cf2651eb', '3849674c2602319e'), - ('42fd443059577fa2', '353882b109ce8f1a', '04b915ba43feb5b6'), - ('059b5e0851cf143a', '48f4d0884c379918', '0113b970fd34f2ce'), - ('0756d8e0774761d2', '432193b78951fc98', '0170f175468fb5e6'), - ('762514b829bf486a', '13f04154d69d1ae5', '43297fad38e373fe'), - ('3bdd119049372802', '2eedda93ffd39c79', '07a7137045da2a16'), - ('26955f6835af609a', 'd887e0393c2da6e3', '04689104c2fd3b2f'), - ('164d5e404f275232', '5f99d04f5b163969', '37d06bb516cb7546'), - ('6b056e18759f5cca', '4a057a3b24d3977b', '1f08260d1ac2465e'), - ('004bd6ef09176062', '452031c1e4fada8e', '584023641aba6176'), - ('480d39006ee762f2', '7555ae39f59b87bd', '025816164629b007'), - ('437540c8698f3cfa', '53c55f9cb49fc019', '49793ebc79b3258f'), - ('072d43a077075292', '7a8e7bfa937e89a3', '4fb05e1515ab73a7'), - ('02fe55778117f12a', 'cf9c5d7a4986adb5', '49e95d6d4ca229bf'), - ('1d9d5c5018f728c2', 'd1abb290658bc778', '018310dc409b26d6'), - ('305532286d6f295a', '55cb3774d13ef201', '1c587f1c13924fef'), - ('0123456789abcdef', 'fa34ec4847b268b2', '0101010101010101'), - ('0123456789abcdef', 'a790795108ea3cae', '1f1f1f1f0e0e0e0e'), - ('0123456789abcdef', 'c39e072d9fac631d', 'e0fee0fef1fef1fe'), - ('ffffffffffffffff', '014933e0cdaff6e4', '0000000000000000'), - ('0000000000000000', 'f21e9a77b71c49bc', 'ffffffffffffffff'), - ('0000000000000000', '245946885754369a', '0123456789abcdef'), - ('ffffffffffffffff', '6b5c5a9c5d9e0a5a', 'fedcba9876543210'), - #('fedcba9876543210', 'f9ad597c49db005e', 'f0'), - #('fedcba9876543210', 'e91d21c1d961a6d6', 'f0e1'), - #('fedcba9876543210', 'e9c2b70a1bc65cf3', 'f0e1d2'), - ('fedcba9876543210', 'be1e639408640f05', 'f0e1d2c3'), - ('fedcba9876543210', 'b39e44481bdb1e6e', 'f0e1d2c3b4'), - ('fedcba9876543210', '9457aa83b1928c0d', 'f0e1d2c3b4a5'), - ('fedcba9876543210', '8bb77032f960629d', 'f0e1d2c3b4a596'), - ('fedcba9876543210', 'e87a244e2cc85e82', 'f0e1d2c3b4a59687'), - ('fedcba9876543210', '15750e7a4f4ec577', 'f0e1d2c3b4a5968778'), - ('fedcba9876543210', '122ba70b3ab64ae0', 'f0e1d2c3b4a596877869'), - ('fedcba9876543210', '3a833c9affc537f6', 'f0e1d2c3b4a5968778695a'), - ('fedcba9876543210', '9409da87a90f6bf2', 'f0e1d2c3b4a5968778695a4b'), - ('fedcba9876543210', '884f80625060b8b4', 'f0e1d2c3b4a5968778695a4b3c'), - ('fedcba9876543210', '1f85031c19e11968', 'f0e1d2c3b4a5968778695a4b3c2d'), - ('fedcba9876543210', '79d9373a714ca34f', 'f0e1d2c3b4a5968778695a4b3c2d1e'), - ('fedcba9876543210', '93142887ee3be15c', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f'), - ('fedcba9876543210', '03429e838ce2d14b', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f00'), - ('fedcba9876543210', 'a4299e27469ff67b', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f0011'), - ('fedcba9876543210', 'afd5aed1c1bc96a8', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f001122'), - ('fedcba9876543210', '10851c0e3858da9f', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233'), - ('fedcba9876543210', 'e6f51ed79b9db21f', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344'), - ('fedcba9876543210', '64a6e14afd36b46f', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455'), - ('fedcba9876543210', '80c7d7d45a5479ad', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566'), - ('fedcba9876543210', '05044b62fa52d080', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677'), + # Test vectors from http://www.schneier.com/code/vectors.txt + ("0000000000000000", "4ef997456198dd78", "0000000000000000"), + ("ffffffffffffffff", "51866fd5b85ecb8a", "ffffffffffffffff"), + ("1000000000000001", "7d856f9a613063f2", "3000000000000000"), + ("1111111111111111", "2466dd878b963c9d", "1111111111111111"), + ("1111111111111111", "61f9c3802281b096", "0123456789abcdef"), + ("0123456789abcdef", "7d0cc630afda1ec7", "1111111111111111"), + ("0000000000000000", "4ef997456198dd78", "0000000000000000"), + ("0123456789abcdef", "0aceab0fc6a0a28d", "fedcba9876543210"), + ("01a1d6d039776742", "59c68245eb05282b", "7ca110454a1a6e57"), + ("5cd54ca83def57da", "b1b8cc0b250f09a0", "0131d9619dc1376e"), + ("0248d43806f67172", "1730e5778bea1da4", "07a1133e4a0b2686"), + ("51454b582ddf440a", "a25e7856cf2651eb", "3849674c2602319e"), + ("42fd443059577fa2", "353882b109ce8f1a", "04b915ba43feb5b6"), + ("059b5e0851cf143a", "48f4d0884c379918", "0113b970fd34f2ce"), + ("0756d8e0774761d2", "432193b78951fc98", "0170f175468fb5e6"), + ("762514b829bf486a", "13f04154d69d1ae5", "43297fad38e373fe"), + ("3bdd119049372802", "2eedda93ffd39c79", "07a7137045da2a16"), + ("26955f6835af609a", "d887e0393c2da6e3", "04689104c2fd3b2f"), + ("164d5e404f275232", "5f99d04f5b163969", "37d06bb516cb7546"), + ("6b056e18759f5cca", "4a057a3b24d3977b", "1f08260d1ac2465e"), + ("004bd6ef09176062", "452031c1e4fada8e", "584023641aba6176"), + ("480d39006ee762f2", "7555ae39f59b87bd", "025816164629b007"), + ("437540c8698f3cfa", "53c55f9cb49fc019", "49793ebc79b3258f"), + ("072d43a077075292", "7a8e7bfa937e89a3", "4fb05e1515ab73a7"), + ("02fe55778117f12a", "cf9c5d7a4986adb5", "49e95d6d4ca229bf"), + ("1d9d5c5018f728c2", "d1abb290658bc778", "018310dc409b26d6"), + ("305532286d6f295a", "55cb3774d13ef201", "1c587f1c13924fef"), + ("0123456789abcdef", "fa34ec4847b268b2", "0101010101010101"), + ("0123456789abcdef", "a790795108ea3cae", "1f1f1f1f0e0e0e0e"), + ("0123456789abcdef", "c39e072d9fac631d", "e0fee0fef1fef1fe"), + ("ffffffffffffffff", "014933e0cdaff6e4", "0000000000000000"), + ("0000000000000000", "f21e9a77b71c49bc", "ffffffffffffffff"), + ("0000000000000000", "245946885754369a", "0123456789abcdef"), + ("ffffffffffffffff", "6b5c5a9c5d9e0a5a", "fedcba9876543210"), + # ('fedcba9876543210', 'f9ad597c49db005e', 'f0'), + # ('fedcba9876543210', 'e91d21c1d961a6d6', 'f0e1'), + # ('fedcba9876543210', 'e9c2b70a1bc65cf3', 'f0e1d2'), + ("fedcba9876543210", "be1e639408640f05", "f0e1d2c3"), + ("fedcba9876543210", "b39e44481bdb1e6e", "f0e1d2c3b4"), + ("fedcba9876543210", "9457aa83b1928c0d", "f0e1d2c3b4a5"), + ("fedcba9876543210", "8bb77032f960629d", "f0e1d2c3b4a596"), + ("fedcba9876543210", "e87a244e2cc85e82", "f0e1d2c3b4a59687"), + ("fedcba9876543210", "15750e7a4f4ec577", "f0e1d2c3b4a5968778"), + ("fedcba9876543210", "122ba70b3ab64ae0", "f0e1d2c3b4a596877869"), + ("fedcba9876543210", "3a833c9affc537f6", "f0e1d2c3b4a5968778695a"), + ("fedcba9876543210", "9409da87a90f6bf2", "f0e1d2c3b4a5968778695a4b"), + ("fedcba9876543210", "884f80625060b8b4", "f0e1d2c3b4a5968778695a4b3c"), + ("fedcba9876543210", "1f85031c19e11968", "f0e1d2c3b4a5968778695a4b3c2d"), + ("fedcba9876543210", "79d9373a714ca34f", "f0e1d2c3b4a5968778695a4b3c2d1e"), + ( + "fedcba9876543210", + "93142887ee3be15c", + "f0e1d2c3b4a5968778695a4b3c2d1e0f", + ), + ( + "fedcba9876543210", + "03429e838ce2d14b", + "f0e1d2c3b4a5968778695a4b3c2d1e0f00", + ), + ( + "fedcba9876543210", + "a4299e27469ff67b", + "f0e1d2c3b4a5968778695a4b3c2d1e0f0011", + ), + ( + "fedcba9876543210", + "afd5aed1c1bc96a8", + "f0e1d2c3b4a5968778695a4b3c2d1e0f001122", + ), + ( + "fedcba9876543210", + "10851c0e3858da9f", + "f0e1d2c3b4a5968778695a4b3c2d1e0f00112233", + ), + ( + "fedcba9876543210", + "e6f51ed79b9db21f", + "f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344", + ), + ( + "fedcba9876543210", + "64a6e14afd36b46f", + "f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455", + ), + ( + "fedcba9876543210", + "80c7d7d45a5479ad", + "f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566", + ), + ( + "fedcba9876543210", + "05044b62fa52d080", + "f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677", + ), ] class KeyLength(unittest.TestCase): - - def runTest(self): - self.assertRaises(ValueError, Blowfish.new, bchr(0) * 3, - Blowfish.MODE_ECB) - self.assertRaises(ValueError, Blowfish.new, bchr(0) * 57, - Blowfish.MODE_ECB) + def runTest(self): + self.assertRaises( + ValueError, + Blowfish.new, + bchr(0) * 3, + Blowfish.MODE_ECB, + ) + self.assertRaises( + ValueError, + Blowfish.new, + bchr(0) * 57, + Blowfish.MODE_ECB, + ) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter + + cipher = Blowfish.new(b"4" * 16, Blowfish.MODE_ECB) - def runTest(self): - # Encrypt/Decrypt data and test output parameter + pt = b"5" * 16 + ct = cipher.encrypt(pt) - cipher = Blowfish.new(b'4'*16, Blowfish.MODE_ECB) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from .common import make_block_tests - tests = make_block_tests(Blowfish, "Blowfish", test_data) - tests.append(KeyLength()) - tests += [TestOutput()] - return tests + from .common import make_block_tests + + tests = make_block_tests(Blowfish, "Blowfish", test_data) + tests.append(KeyLength()) + tests += [TestOutput()] + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CAST.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CAST.py index 8bc21fd3..a97a31ce 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CAST.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CAST.py @@ -32,70 +32,76 @@ # This is a list of (plaintext, ciphertext, key) tuples. test_data = [ - # Test vectors from RFC 2144, B.1 - ('0123456789abcdef', '238b4fe5847e44b2', - '0123456712345678234567893456789a', - '128-bit key'), - - ('0123456789abcdef', 'eb6a711a2c02271b', - '01234567123456782345', - '80-bit key'), - - ('0123456789abcdef', '7ac816d16e9b302e', - '0123456712', - '40-bit key'), + # Test vectors from RFC 2144, B.1 + ( + "0123456789abcdef", + "238b4fe5847e44b2", + "0123456712345678234567893456789a", + "128-bit key", + ), + ( + "0123456789abcdef", + "eb6a711a2c02271b", + "01234567123456782345", + "80-bit key", + ), + ( + "0123456789abcdef", + "7ac816d16e9b302e", + "0123456712", + "40-bit key", + ), ] class KeyLength(unittest.TestCase): - - def runTest(self): - self.assertRaises(ValueError, CAST.new, bchr(0) * 4, CAST.MODE_ECB) - self.assertRaises(ValueError, CAST.new, bchr(0) * 17, CAST.MODE_ECB) + def runTest(self): + self.assertRaises(ValueError, CAST.new, bchr(0) * 4, CAST.MODE_ECB) + self.assertRaises(ValueError, CAST.new, bchr(0) * 17, CAST.MODE_ECB) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter + + cipher = CAST.new(b"4" * 16, CAST.MODE_ECB) - def runTest(self): - # Encrypt/Decrypt data and test output parameter + pt = b"5" * 16 + ct = cipher.encrypt(pt) - cipher = CAST.new(b'4'*16, CAST.MODE_ECB) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from .common import make_block_tests + from .common import make_block_tests + + tests = make_block_tests(CAST, "CAST", test_data) + tests.append(KeyLength()) + tests.append(TestOutput()) + return tests - tests = make_block_tests(CAST, "CAST", test_data) - tests.append(KeyLength()) - tests.append(TestOutput()) - return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CBC.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CBC.py index f118eb6b..eca54125 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CBC.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CBC.py @@ -39,518 +39,568 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) -class BlockChainingTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - key_192 = get_tag_random("key_192", 24) - iv_128 = get_tag_random("iv_128", 16) - iv_64 = get_tag_random("iv_64", 8) - data_128 = get_tag_random("data_128", 16) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_loopback_64(self): - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - pt = get_tag_random("plaintext", 8 * 100) - ct = cipher.encrypt(pt) - - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_iv(self): - # If not passed, the iv is created randomly - cipher = AES.new(self.key_128, self.aes_mode) - iv1 = cipher.iv - cipher = AES.new(self.key_128, self.aes_mode) - iv2 = cipher.iv - self.assertNotEqual(iv1, iv2) - self.assertEqual(len(iv1), 16) - - # IV can be passed in uppercase or lowercase - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - ct = cipher.encrypt(self.data_128) - - cipher = AES.new(self.key_128, self.aes_mode, iv=self.iv_128) - self.assertEqual(ct, cipher.encrypt(self.data_128)) - - cipher = AES.new(self.key_128, self.aes_mode, IV=self.iv_128) - self.assertEqual(ct, cipher.encrypt(self.data_128)) - - def test_iv_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode, - iv = u'test1234567890-*') - - def test_only_one_iv(self): - # Only one IV/iv keyword allowed - self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode, - iv=self.iv_128, IV=self.iv_128) - - def test_iv_with_matching_length(self): - self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode, - b"") - self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode, - self.iv_128[:15]) - self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode, - self.iv_128 + b"0") - - def test_block_size_128(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_block_size_64(self): - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - self.assertEqual(cipher.block_size, DES3.block_size) - - def test_unaligned_data_128(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - for wrong_length in range(1,16): - self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length) - - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - for wrong_length in range(1,16): - self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length) - - def test_unaligned_data_64(self): - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - for wrong_length in range(1,8): - self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length) - - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - for wrong_length in range(1,8): - self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length) - - def test_IV_iv_attributes(self): - data = get_tag_random("data", 16 * 100) - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - getattr(cipher, func)(data) - self.assertEqual(cipher.iv, self.iv_128) - self.assertEqual(cipher.IV, self.iv_128) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode, - self.iv_128, 7) - self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode, - iv=self.iv_128, unknown=7) - # But some are only known by the base cipher (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, self.aes_mode, iv=self.iv_128, use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_bytearray(self): - data = b"1" * 128 - data_ba = bytearray(data) - - # Encrypt - key_ba = bytearray(self.key_128) - iv_ba = bytearray(self.iv_128) - - cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128) - ref1 = cipher1.encrypt(data) - - cipher2 = AES.new(key_ba, self.aes_mode, iv_ba) - key_ba[:3] = b'\xFF\xFF\xFF' - iv_ba[:3] = b'\xFF\xFF\xFF' - ref2 = cipher2.encrypt(data_ba) - - self.assertEqual(ref1, ref2) - self.assertEqual(cipher1.iv, cipher2.iv) - - # Decrypt - key_ba = bytearray(self.key_128) - iv_ba = bytearray(self.iv_128) - - cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128) - ref3 = cipher3.decrypt(data) - - cipher4 = AES.new(key_ba, self.aes_mode, iv_ba) - key_ba[:3] = b'\xFF\xFF\xFF' - iv_ba[:3] = b'\xFF\xFF\xFF' - ref4 = cipher4.decrypt(data_ba) - - self.assertEqual(ref3, ref4) - - def test_memoryview(self): - data = b"1" * 128 - data_mv = memoryview(bytearray(data)) - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - iv_mv = memoryview(bytearray(self.iv_128)) - - cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128) - ref1 = cipher1.encrypt(data) - - cipher2 = AES.new(key_mv, self.aes_mode, iv_mv) - key_mv[:3] = b'\xFF\xFF\xFF' - iv_mv[:3] = b'\xFF\xFF\xFF' - ref2 = cipher2.encrypt(data_mv) - - self.assertEqual(ref1, ref2) - self.assertEqual(cipher1.iv, cipher2.iv) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - iv_mv = memoryview(bytearray(self.iv_128)) - - cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128) - ref3 = cipher3.decrypt(data) - - cipher4 = AES.new(key_mv, self.aes_mode, iv_mv) - key_mv[:3] = b'\xFF\xFF\xFF' - iv_mv[:3] = b'\xFF\xFF\xFF' - ref4 = cipher4.decrypt(data_mv) - - self.assertEqual(ref3, ref4) - - def test_output_param(self): - pt = b'5' * 128 - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) - - output = bytearray(128) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - - def test_output_param_same_buffer(self): - - pt = b'5' * 128 - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) +class BlockChainingTests(unittest.TestCase): + key_128 = get_tag_random("key_128", 16) + key_192 = get_tag_random("key_192", 24) + iv_128 = get_tag_random("iv_128", 16) + iv_64 = get_tag_random("iv_64", 8) + data_128 = get_tag_random("data_128", 16) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_loopback_64(self): + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + pt = get_tag_random("plaintext", 8 * 100) + ct = cipher.encrypt(pt) + + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_iv(self): + # If not passed, the iv is created randomly + cipher = AES.new(self.key_128, self.aes_mode) + iv1 = cipher.iv + cipher = AES.new(self.key_128, self.aes_mode) + iv2 = cipher.iv + self.assertNotEqual(iv1, iv2) + self.assertEqual(len(iv1), 16) + + # IV can be passed in uppercase or lowercase + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + ct = cipher.encrypt(self.data_128) + + cipher = AES.new(self.key_128, self.aes_mode, iv=self.iv_128) + self.assertEqual(ct, cipher.encrypt(self.data_128)) + + cipher = AES.new(self.key_128, self.aes_mode, IV=self.iv_128) + self.assertEqual(ct, cipher.encrypt(self.data_128)) + + def test_iv_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + self.aes_mode, + iv="test1234567890-*", + ) + + def test_only_one_iv(self): + # Only one IV/iv keyword allowed + self.assertRaises( + TypeError, + AES.new, + self.key_128, + self.aes_mode, + iv=self.iv_128, + IV=self.iv_128, + ) + + def test_iv_with_matching_length(self): + self.assertRaises( + ValueError, + AES.new, + self.key_128, + self.aes_mode, + b"", + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + self.aes_mode, + self.iv_128[:15], + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + self.aes_mode, + self.iv_128 + b"0", + ) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_block_size_64(self): + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + self.assertEqual(cipher.block_size, DES3.block_size) + + def test_unaligned_data_128(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + for wrong_length in range(1, 16): + self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length) + + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + for wrong_length in range(1, 16): + self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length) + + def test_unaligned_data_64(self): + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + for wrong_length in range(1, 8): + self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length) + + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + for wrong_length in range(1, 8): + self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length) + + def test_IV_iv_attributes(self): + data = get_tag_random("data", 16 * 100) + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + getattr(cipher, func)(data) + self.assertEqual(cipher.iv, self.iv_128) + self.assertEqual(cipher.IV, self.iv_128) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + self.aes_mode, + self.iv_128, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + self.aes_mode, + iv=self.iv_128, + unknown=7, + ) + # But some are only known by the base cipher (e.g. use_aesni consumed by the AES module) + AES.new(self.key_128, self.aes_mode, iv=self.iv_128, use_aesni=False) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_bytearray(self): + data = b"1" * 128 + data_ba = bytearray(data) + + # Encrypt + key_ba = bytearray(self.key_128) + iv_ba = bytearray(self.iv_128) + + cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128) + ref1 = cipher1.encrypt(data) + + cipher2 = AES.new(key_ba, self.aes_mode, iv_ba) + key_ba[:3] = b"\xff\xff\xff" + iv_ba[:3] = b"\xff\xff\xff" + ref2 = cipher2.encrypt(data_ba) + + self.assertEqual(ref1, ref2) + self.assertEqual(cipher1.iv, cipher2.iv) + + # Decrypt + key_ba = bytearray(self.key_128) + iv_ba = bytearray(self.iv_128) + + cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128) + ref3 = cipher3.decrypt(data) + + cipher4 = AES.new(key_ba, self.aes_mode, iv_ba) + key_ba[:3] = b"\xff\xff\xff" + iv_ba[:3] = b"\xff\xff\xff" + ref4 = cipher4.decrypt(data_ba) + + self.assertEqual(ref3, ref4) + + def test_memoryview(self): + data = b"1" * 128 + data_mv = memoryview(bytearray(data)) + + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + iv_mv = memoryview(bytearray(self.iv_128)) + + cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128) + ref1 = cipher1.encrypt(data) + + cipher2 = AES.new(key_mv, self.aes_mode, iv_mv) + key_mv[:3] = b"\xff\xff\xff" + iv_mv[:3] = b"\xff\xff\xff" + ref2 = cipher2.encrypt(data_mv) + + self.assertEqual(ref1, ref2) + self.assertEqual(cipher1.iv, cipher2.iv) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + iv_mv = memoryview(bytearray(self.iv_128)) + + cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128) + ref3 = cipher3.decrypt(data) + + cipher4 = AES.new(key_mv, self.aes_mode, iv_mv) + key_mv[:3] = b"\xff\xff\xff" + iv_mv[:3] = b"\xff\xff\xff" + ref4 = cipher4.decrypt(data_mv) + + self.assertEqual(ref3, ref4) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + ct = cipher.encrypt(pt) + + output = bytearray(128) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt_ba = bytearray(pt) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - res = cipher.encrypt(pt_ba, output=pt_ba) - self.assertEqual(ct, pt_ba) - self.assertEqual(res, None) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - ct_ba = bytearray(ct) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - res = cipher.decrypt(ct_ba, output=ct_ba) - self.assertEqual(pt, ct_ba) - self.assertEqual(res, None) + def test_output_param_same_buffer(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + ct = cipher.encrypt(pt) + pt_ba = bytearray(pt) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + res = cipher.encrypt(pt_ba, output=pt_ba) + self.assertEqual(ct, pt_ba) + self.assertEqual(res, None) - def test_output_param_memoryview(self): + ct_ba = bytearray(ct) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + res = cipher.decrypt(ct_ba, output=ct_ba) + self.assertEqual(pt, ct_ba) + self.assertEqual(res, None) - pt = b'5' * 128 - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + ct = cipher.encrypt(pt) - output = memoryview(bytearray(128)) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + output = memoryview(bytearray(128)) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - def test_output_param_neg(self): - LEN_PT = 128 + def test_output_param_neg(self): + LEN_PT = 128 - pt = b'5' * LEN_PT - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) + pt = b"5" * LEN_PT + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + ct = cipher.encrypt(pt) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * LEN_PT) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * LEN_PT) - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) class CbcTests(BlockChainingTests): - aes_mode = AES.MODE_CBC - des3_mode = DES3.MODE_CBC + aes_mode = AES.MODE_CBC + des3_mode = DES3.MODE_CBC class NistBlockChainingVectors(unittest.TestCase): - - def _do_kat_aes_test(self, file_name): - - test_vectors = load_test_vectors(("Cipher", "AES"), - file_name, - "AES CBC KAT", - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - - cipher = AES.new(tv.key, self.aes_mode, tv.iv) - if direction == "[ENCRYPT]": - self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) - elif direction == "[DECRYPT]": - self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) - else: - assert False - - # See Section 6.4.2 in AESAVS - def _do_mct_aes_test(self, file_name): - - test_vectors = load_test_vectors(("Cipher", "AES"), - file_name, - "AES CBC Montecarlo", - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - cipher = AES.new(tv.key, self.aes_mode, tv.iv) - - if direction == '[ENCRYPT]': - cts = [ tv.iv ] - for count in range(1000): - cts.append(cipher.encrypt(tv.plaintext)) - tv.plaintext = cts[-2] - self.assertEqual(cts[-1], tv.ciphertext) - elif direction == '[DECRYPT]': - pts = [ tv.iv] - for count in range(1000): - pts.append(cipher.decrypt(tv.ciphertext)) - tv.ciphertext = pts[-2] - self.assertEqual(pts[-1], tv.plaintext) - else: - assert False - - def _do_tdes_test(self, file_name): - - test_vectors = load_test_vectors(("Cipher", "TDES"), - file_name, - "TDES CBC KAT", - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - if hasattr(tv, "keys"): - cipher = DES.new(tv.keys, self.des_mode, tv.iv) - else: - if tv.key1 != tv.key3: - key = tv.key1 + tv.key2 + tv.key3 # Option 3 - else: - key = tv.key1 + tv.key2 # Option 2 - cipher = DES3.new(key, self.des3_mode, tv.iv) - - if direction == "[ENCRYPT]": - self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) - elif direction == "[DECRYPT]": - self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) - else: - assert False + def _do_kat_aes_test(self, file_name): + test_vectors = load_test_vectors( + ("Cipher", "AES"), + file_name, + "AES CBC KAT", + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + + cipher = AES.new(tv.key, self.aes_mode, tv.iv) + if direction == "[ENCRYPT]": + self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) + elif direction == "[DECRYPT]": + self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) + else: + assert False + + # See Section 6.4.2 in AESAVS + def _do_mct_aes_test(self, file_name): + test_vectors = load_test_vectors( + ("Cipher", "AES"), + file_name, + "AES CBC Montecarlo", + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + cipher = AES.new(tv.key, self.aes_mode, tv.iv) + + if direction == "[ENCRYPT]": + cts = [tv.iv] + for count in range(1000): + cts.append(cipher.encrypt(tv.plaintext)) + tv.plaintext = cts[-2] + self.assertEqual(cts[-1], tv.ciphertext) + elif direction == "[DECRYPT]": + pts = [tv.iv] + for count in range(1000): + pts.append(cipher.decrypt(tv.ciphertext)) + tv.ciphertext = pts[-2] + self.assertEqual(pts[-1], tv.plaintext) + else: + assert False + + def _do_tdes_test(self, file_name): + test_vectors = load_test_vectors( + ("Cipher", "TDES"), + file_name, + "TDES CBC KAT", + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + if hasattr(tv, "keys"): + cipher = DES.new(tv.keys, self.des_mode, tv.iv) + else: + if tv.key1 != tv.key3: + key = tv.key1 + tv.key2 + tv.key3 # Option 3 + else: + key = tv.key1 + tv.key2 # Option 2 + cipher = DES3.new(key, self.des3_mode, tv.iv) + + if direction == "[ENCRYPT]": + self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) + elif direction == "[DECRYPT]": + self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) + else: + assert False class NistCbcVectors(NistBlockChainingVectors): - aes_mode = AES.MODE_CBC - des_mode = DES.MODE_CBC - des3_mode = DES3.MODE_CBC + aes_mode = AES.MODE_CBC + des_mode = DES.MODE_CBC + des3_mode = DES3.MODE_CBC # Create one test method per file nist_aes_kat_mmt_files = ( - # KAT - "CBCGFSbox128.rsp", - "CBCGFSbox192.rsp", - "CBCGFSbox256.rsp", - "CBCKeySbox128.rsp", - "CBCKeySbox192.rsp", - "CBCKeySbox256.rsp", - "CBCVarKey128.rsp", - "CBCVarKey192.rsp", - "CBCVarKey256.rsp", - "CBCVarTxt128.rsp", - "CBCVarTxt192.rsp", - "CBCVarTxt256.rsp", - # MMT - "CBCMMT128.rsp", - "CBCMMT192.rsp", - "CBCMMT256.rsp", - ) + # KAT + "CBCGFSbox128.rsp", + "CBCGFSbox192.rsp", + "CBCGFSbox256.rsp", + "CBCKeySbox128.rsp", + "CBCKeySbox192.rsp", + "CBCKeySbox256.rsp", + "CBCVarKey128.rsp", + "CBCVarKey192.rsp", + "CBCVarKey256.rsp", + "CBCVarTxt128.rsp", + "CBCVarTxt192.rsp", + "CBCVarTxt256.rsp", + # MMT + "CBCMMT128.rsp", + "CBCMMT192.rsp", + "CBCMMT256.rsp", +) nist_aes_mct_files = ( - "CBCMCT128.rsp", - "CBCMCT192.rsp", - "CBCMCT256.rsp", - ) + "CBCMCT128.rsp", + "CBCMCT192.rsp", + "CBCMCT256.rsp", +) for file_name in nist_aes_kat_mmt_files: - def new_func(self, file_name=file_name): - self._do_kat_aes_test(file_name) - setattr(NistCbcVectors, "test_AES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_kat_aes_test(file_name) + + setattr(NistCbcVectors, "test_AES_" + file_name, new_func) for file_name in nist_aes_mct_files: - def new_func(self, file_name=file_name): - self._do_mct_aes_test(file_name) - setattr(NistCbcVectors, "test_AES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_mct_aes_test(file_name) + + setattr(NistCbcVectors, "test_AES_" + file_name, new_func) del file_name, new_func nist_tdes_files = ( - "TCBCMMT2.rsp", # 2TDES - "TCBCMMT3.rsp", # 3TDES - "TCBCinvperm.rsp", # Single DES - "TCBCpermop.rsp", - "TCBCsubtab.rsp", - "TCBCvarkey.rsp", - "TCBCvartext.rsp", - ) + "TCBCMMT2.rsp", # 2TDES + "TCBCMMT3.rsp", # 3TDES + "TCBCinvperm.rsp", # Single DES + "TCBCpermop.rsp", + "TCBCsubtab.rsp", + "TCBCvarkey.rsp", + "TCBCvartext.rsp", +) for file_name in nist_tdes_files: - def new_func(self, file_name=file_name): - self._do_tdes_test(file_name) - setattr(NistCbcVectors, "test_TDES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_tdes_test(file_name) + + setattr(NistCbcVectors, "test_TDES_" + file_name, new_func) # END OF NIST CBC TEST VECTORS class SP800TestVectors(unittest.TestCase): - """Class exercising the CBC test vectors found in Section F.2 - of NIST SP 800-3A""" - - def test_aes_128(self): - key = '2b7e151628aed2a6abf7158809cf4f3c' - iv = '000102030405060708090a0b0c0d0e0f' - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '7649abac8119b246cee98e9b12e9197d' +\ - '5086cb9b507219ee95db113a917678b2' +\ - '73bed6b8e3c1743b7116e69e22229516' +\ - '3ff1caa1681fac09120eca307586e1a7' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_192(self): - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - iv = '000102030405060708090a0b0c0d0e0f' - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '4f021db243bc633d7178183a9fa071e8' +\ - 'b4d9ada9ad7dedf4e5e738763f69145a' +\ - '571b242012fb7ae07fa9baac3df102e0' +\ - '08b0e27988598881d920a9e64f5615cd' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_256(self): - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - iv = '000102030405060708090a0b0c0d0e0f' - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = 'f58c4c04d6e5f1ba779eabfb5f7bfbd6' +\ - '9cfc4e967edb808d679f777bc6702c7d' +\ - '39f23369a9d9bacfa530e26304231461' +\ - 'b2eb05e2c39be9fcda6c19078c6a9d1b' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) + """Class exercising the CBC test vectors found in Section F.2 + of NIST SP 800-3A""" + + def test_aes_128(self): + key = "2b7e151628aed2a6abf7158809cf4f3c" + iv = "000102030405060708090a0b0c0d0e0f" + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "7649abac8119b246cee98e9b12e9197d" + + "5086cb9b507219ee95db113a917678b2" + + "73bed6b8e3c1743b7116e69e22229516" + + "3ff1caa1681fac09120eca307586e1a7" + ) + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_192(self): + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + iv = "000102030405060708090a0b0c0d0e0f" + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "4f021db243bc633d7178183a9fa071e8" + + "b4d9ada9ad7dedf4e5e738763f69145a" + + "571b242012fb7ae07fa9baac3df102e0" + + "08b0e27988598881d920a9e64f5615cd" + ) + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_256(self): + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + iv = "000102030405060708090a0b0c0d0e0f" + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "f58c4c04d6e5f1ba779eabfb5f7bfbd6" + + "9cfc4e967edb808d679f777bc6702c7d" + + "39f23369a9d9bacfa530e26304231461" + + "b2eb05e2c39be9fcda6c19078c6a9d1b" + ) + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) def get_tests(config={}): - tests = [] - tests += list_test_cases(CbcTests) - if config.get('slow_tests'): - tests += list_test_cases(NistCbcVectors) - tests += list_test_cases(SP800TestVectors) - return tests + tests = [] + tests += list_test_cases(CbcTests) + if config.get("slow_tests"): + tests += list_test_cases(NistCbcVectors) + tests += list_test_cases(SP800TestVectors) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CCM.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CCM.py index c179f16e..91df8390 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CCM.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CCM.py @@ -43,928 +43,1162 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class CcmTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # If not passed, the nonce is created randomly - cipher = AES.new(self.key_128, AES.MODE_CCM) - nonce1 = cipher.nonce - cipher = AES.new(self.key_128, AES.MODE_CCM) - nonce2 = cipher.nonce - self.assertEqual(len(nonce1), 11) - self.assertNotEqual(nonce1, nonce2) - - cipher = AES.new(self.key_128, AES.MODE_CCM, self.nonce_96) - ct = cipher.encrypt(self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CCM, - nonce=u'test12345678') - - def test_nonce_length(self): - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM, - nonce=b"") - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM, - nonce=bchr(1) * 6) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM, - nonce=bchr(1) * 14) - for x in range(7, 13 + 1): - AES.new(self.key_128, AES.MODE_CCM, nonce=bchr(1) * x) - - def test_block_size(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 11 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_CCM).nonce - nonce2 = AES.new(self.key_128, AES.MODE_CCM).nonce - self.assertEqual(len(nonce1), 11) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CCM, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - # Invalid MAC length - for mac_len in range(3, 17 + 1, 2): - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, mac_len=mac_len) - - # Valid MAC length - for mac_len in range(4, 16 + 1, 2): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - mac_len=mac_len) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), mac_len) - - # Default MAC length - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_longer_assoc_data_than_declared(self): - # More than zero - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=0) - self.assertRaises(ValueError, cipher.update, b"1") - - # Too large - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=15) - self.assertRaises(ValueError, cipher.update, self.data) - - def test_shorter_assoc_data_than_expected(self): - DATA_LEN = len(self.data) - - # With plaintext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=DATA_LEN + 1) - cipher.update(self.data) - self.assertRaises(ValueError, cipher.encrypt, self.data) - - # With empty plaintext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=DATA_LEN + 1) - cipher.update(self.data) - self.assertRaises(ValueError, cipher.digest) - - # With ciphertext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=DATA_LEN + 1) - cipher.update(self.data) - self.assertRaises(ValueError, cipher.decrypt, self.data) - - # With empty ciphertext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=DATA_LEN + 1) - cipher.update(self.data) - self.assertRaises(ValueError, cipher.verify, mac) - - def test_shorter_and_longer_plaintext_than_declared(self): - DATA_LEN = len(self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=DATA_LEN + 1) - cipher.encrypt(self.data) - self.assertRaises(ValueError, cipher.digest) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=DATA_LEN - 1) - self.assertRaises(ValueError, cipher.encrypt, self.data) - - def test_shorter_ciphertext_than_declared(self): - DATA_LEN = len(self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=DATA_LEN + 1) - cipher.decrypt(ct) - self.assertRaises(ValueError, cipher.verify, mac) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=DATA_LEN - 1) - self.assertRaises(ValueError, cipher.decrypt, ct) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=127, assoc_len=127) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b"" - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=127, assoc_len=127) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b"" - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - data_ba = bytearray(self.data) - - cipher1 = AES.new(self.key_128, - AES.MODE_CCM, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) - tag = cipher1.digest() - - cipher2 = AES.new(key_ba, - AES.MODE_CCM, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_ba) - data_ba[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - del data_ba - - cipher4 = AES.new(key_ba, - AES.MODE_CCM, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - data_mv = memoryview(bytearray(self.data)) - - cipher1 = AES.new(self.key_128, - AES.MODE_CCM, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) - tag = cipher1.digest() - - cipher2 = AES.new(key_mv, - AES.MODE_CCM, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_mv) - data_mv[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - del data_mv - - cipher4 = AES.new(key_mv, - AES.MODE_CCM, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - tag = cipher.digest() - - output = bytearray(128) - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - res, tag_out = cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - self.assertEqual(tag, tag_out) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - res = cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - - def test_output_param_neg(self): - - pt = b'5' * 16 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) - - shorter_output = bytearray(15) - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) - - def test_message_too_long(self): - - nonce = b'N' * 13 - self.assertRaises(CCMMessageTooLongError, - AES.new, - self.key_128, - AES.MODE_CCM, - nonce=nonce, - assoc_len=20, - msg_len=0x10000) - - nonce = b'N' * 7 - self.assertRaises(CCMMessageTooLongError, - AES.new, - self.key_128, - AES.MODE_CCM, - nonce=nonce, - assoc_len=20, - msg_len=2**64) - - nonce = b'N' * 13 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=nonce) - self.assertRaises(CCMMessageTooLongError, - cipher.encrypt, - b'C' * 0x10000) - - nonce = b'N' * 13 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=nonce) - self.assertRaises(CCMMessageTooLongError, - cipher.decrypt, - b'C' * 0x10000) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # If not passed, the nonce is created randomly + cipher = AES.new(self.key_128, AES.MODE_CCM) + nonce1 = cipher.nonce + cipher = AES.new(self.key_128, AES.MODE_CCM) + nonce2 = cipher.nonce + self.assertEqual(len(nonce1), 11) + self.assertNotEqual(nonce1, nonce2) + + cipher = AES.new(self.key_128, AES.MODE_CCM, self.nonce_96) + ct = cipher.encrypt(self.data) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertEqual(ct, cipher.encrypt(self.data)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce="test12345678", + ) + + def test_nonce_length(self): + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=b"", + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=bchr(1) * 6, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=bchr(1) * 14, + ) + for x in range(7, 13 + 1): + AES.new(self.key_128, AES.MODE_CCM, nonce=bchr(1) * x) + + def test_block_size(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 11 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_CCM).nonce + nonce2 = AES.new(self.key_128, AES.MODE_CCM).nonce + self.assertEqual(len(nonce1), 11) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CCM, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + # Invalid MAC length + for mac_len in range(3, 17 + 1, 2): + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + mac_len=mac_len, + ) + + # Valid MAC length + for mac_len in range(4, 16 + 1, 2): + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + mac_len=mac_len, + ) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), mac_len) + + # Default MAC length + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_longer_assoc_data_than_declared(self): + # More than zero + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=0, + ) + self.assertRaises(ValueError, cipher.update, b"1") + + # Too large + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=15, + ) + self.assertRaises(ValueError, cipher.update, self.data) + + def test_shorter_assoc_data_than_expected(self): + DATA_LEN = len(self.data) + + # With plaintext + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=DATA_LEN + 1, + ) + cipher.update(self.data) + self.assertRaises(ValueError, cipher.encrypt, self.data) + + # With empty plaintext + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=DATA_LEN + 1, + ) + cipher.update(self.data) + self.assertRaises(ValueError, cipher.digest) + + # With ciphertext + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=DATA_LEN + 1, + ) + cipher.update(self.data) + self.assertRaises(ValueError, cipher.decrypt, self.data) + + # With empty ciphertext + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + mac = cipher.digest() + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=DATA_LEN + 1, + ) + cipher.update(self.data) + self.assertRaises(ValueError, cipher.verify, mac) + + def test_shorter_and_longer_plaintext_than_declared(self): + DATA_LEN = len(self.data) + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=DATA_LEN + 1, + ) + cipher.encrypt(self.data) + self.assertRaises(ValueError, cipher.digest) + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=DATA_LEN - 1, + ) + self.assertRaises(ValueError, cipher.encrypt, self.data) + + def test_shorter_ciphertext_than_declared(self): + DATA_LEN = len(self.data) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=DATA_LEN + 1, + ) + cipher.decrypt(ct) + self.assertRaises(ValueError, cipher.verify, mac) + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=DATA_LEN - 1, + ) + self.assertRaises(ValueError, cipher.decrypt, ct) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=127, + assoc_len=127, + ) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b"" + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=127, + assoc_len=127, + ) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b"" + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + data_ba = bytearray(self.data) + + cipher1 = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + tag = cipher1.digest() + + cipher2 = AES.new( + key_ba, + AES.MODE_CCM, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + data_ba[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + del data_ba + + cipher4 = AES.new( + key_ba, + AES.MODE_CCM, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher4.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + data_mv = memoryview(bytearray(self.data)) + + cipher1 = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + tag = cipher1.digest() + + cipher2 = AES.new( + key_mv, + AES.MODE_CCM, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + data_mv[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + del data_mv + + cipher4 = AES.new( + key_mv, + AES.MODE_CCM, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher4.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + tag = cipher.digest() + + output = bytearray(128) + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + res, tag_out = cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + self.assertEqual(tag, tag_out) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + res = cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + pt = b"5" * 16 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) + + shorter_output = bytearray(15) + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + + def test_message_too_long(self): + nonce = b"N" * 13 + self.assertRaises( + CCMMessageTooLongError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=nonce, + assoc_len=20, + msg_len=0x10000, + ) + + nonce = b"N" * 7 + self.assertRaises( + CCMMessageTooLongError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=nonce, + assoc_len=20, + msg_len=2**64, + ) + + nonce = b"N" * 13 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=nonce) + self.assertRaises( + CCMMessageTooLongError, + cipher.encrypt, + b"C" * 0x10000, + ) + + nonce = b"N" * 13 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=nonce) + self.assertRaises( + CCMMessageTooLongError, + cipher.decrypt, + b"C" * 0x10000, + ) class CcmFSMTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 16) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - for assoc_len in (None, 0): - for msg_len in (None, len(self.data)): - # Verify path INIT->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - # Verify path INIT->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - for assoc_len in (None, len(self.data)): - for msg_len in (None, 0): - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.update(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.update(self.data) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - for assoc_len in (None, len(self.data)): - for msg_len in (None, len(self.data)): - # Verify path INIT->UPDATE->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.update(self.data) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.update(self.data) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - # Only possible if msg_len is declared in advance - for method_name in "encrypt", "decrypt": - for auth_data in (None, b"333", self.data, - self.data + b"3"): - if auth_data is None: - assoc_len = None - else: - assoc_len = len(auth_data) - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - msg_len=64, - assoc_len=assoc_len) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data) - method(self.data) - method(self.data) - method(self.data) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - ct, mac = cipher.encrypt_and_digest(self.data) - - # decrypt_and_verify - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data, pt) - - def test_invalid_multiple_encrypt_decrypt_without_msg_len(self): - # Once per method, with or without assoc. data - for method_name in "encrypt", "decrypt": - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data) - method = getattr(cipher, method_name) - method(self.data) - self.assertRaises(TypeError, method, self.data) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - msg_len=32) - if assoc_data_present: - cipher.update(self.data) - getattr(cipher, method1_name)(self.data) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.encrypt(self.data) - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 16) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + for assoc_len in (None, 0): + for msg_len in (None, len(self.data)): + # Verify path INIT->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + # Verify path INIT->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + for assoc_len in (None, len(self.data)): + for msg_len in (None, 0): + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.update(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.update(self.data) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + for assoc_len in (None, len(self.data)): + for msg_len in (None, len(self.data)): + # Verify path INIT->UPDATE->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.update(self.data) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.update(self.data) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + # Only possible if msg_len is declared in advance + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b"333", + self.data, + self.data + b"3", + ): + if auth_data is None: + assoc_len = None + else: + assoc_len = len(auth_data) + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=64, + assoc_len=assoc_len, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data) + method(self.data) + method(self.data) + method(self.data) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + ct, mac = cipher.encrypt_and_digest(self.data) + + # decrypt_and_verify + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data, pt) + + def test_invalid_multiple_encrypt_decrypt_without_msg_len(self): + # Once per method, with or without assoc. data + for method_name in "encrypt", "decrypt": + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data) + method = getattr(cipher, method_name) + method(self.data) + self.assertRaises(TypeError, method, self.data) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=32, + ) + if assoc_data_present: + cipher.update(self.data) + getattr(cipher, method1_name)(self.data) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.encrypt(self.data) + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) class TestVectors(unittest.TestCase): - """Class exercising the CCM test vectors found in Appendix C - of NIST SP 800-38C and in RFC 3610""" - - # List of test vectors, each made up of: - # - authenticated data - # - plaintext - # - ciphertext - # - MAC - # - AES key - # - nonce - test_vectors_hex = [ - # NIST SP 800 38C - ( '0001020304050607', - '20212223', - '7162015b', - '4dac255d', - '404142434445464748494a4b4c4d4e4f', - '10111213141516'), - ( '000102030405060708090a0b0c0d0e0f', - '202122232425262728292a2b2c2d2e2f', - 'd2a1f0e051ea5f62081a7792073d593d', - '1fc64fbfaccd', - '404142434445464748494a4b4c4d4e4f', - '1011121314151617'), - ( '000102030405060708090a0b0c0d0e0f10111213', - '202122232425262728292a2b2c2d2e2f3031323334353637', - 'e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5', - '484392fbc1b09951', - '404142434445464748494a4b4c4d4e4f', - '101112131415161718191a1b'), - ( (''.join(["%02X" % (x*16+y) for x in range(0,16) for y in range(0,16)]))*256, - '202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f', - '69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72', - 'b4ac6bec93e8598e7f0dadbcea5b', - '404142434445464748494a4b4c4d4e4f', - '101112131415161718191a1b1c'), - # RFC3610 - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e', - '588c979a61c663d2f066d0c2c0f989806d5f6b61dac384', - '17e8d12cfdf926e0', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000003020100a0a1a2a3a4a5'), - ( - '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b', - 'a091d56e10400916', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000004030201a0a1a2a3a4a5'), - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', - '51b1e5f44a197d1da46b0f8e2d282ae871e838bb64da859657', - '4adaa76fbd9fb0c5', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000005040302A0A1A2A3A4A5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e', - 'a28c6865939a9a79faaa5c4c2a9d4a91cdac8c', - '96c861b9c9e61ef1', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000006050403a0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e1f', - 'dcf1fb7b5d9e23fb9d4e131253658ad86ebdca3e', - '51e83f077d9c2d93', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000007060504a0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e1f20', - '6fc1b011f006568b5171a42d953d469b2570a4bd87', - '405a0443ac91cb94', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000008070605a0a1a2a3a4a5'), - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e', - '0135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c', - '048c56602c97acbb7490', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000009080706a0a1a2a3a4a5'), - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '7b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24', - 'c17b4433f434963f34b4', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000a090807a0a1a2a3a4a5'), - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', - '82531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197', - 'ea9c07e56b5eb17e5f4e', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000b0a0908a0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e', - '07342594157785152b074098330abb141b947b', - '566aa9406b4d999988dd', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000c0b0a09a0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e1f', - '676bb20380b0e301e8ab79590a396da78b834934', - 'f53aa2e9107a8b6c022c', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000d0c0b0aa0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e1f20', - 'c0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43', - 'cd1aa31662e7ad65d6db', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000e0d0c0ba0a1a2a3a4a5'), - ( '0be1a88bace018b1', - '08e8cf97d820ea258460e96ad9cf5289054d895ceac47c', - '4cb97f86a2a4689a877947ab8091ef5386a6ffbdd080f8', - 'e78cf7cb0cddd7b3', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00412b4ea9cdbe3c9696766cfa'), - ( '63018f76dc8a1bcb', - '9020ea6f91bdd85afa0039ba4baff9bfb79c7028949cd0ec', - '4ccb1e7ca981befaa0726c55d378061298c85c92814abc33', - 'c52ee81d7d77c08a', - 'd7828d13b2b0bdc325a76236df93cc6b', - '0033568ef7b2633c9696766cfa'), - ( 'aa6cfa36cae86b40', - 'b916e0eacc1c00d7dcec68ec0b3bbb1a02de8a2d1aa346132e', - 'b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708', - 'a776796edb723506', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00103fe41336713c9696766cfa'), - ( 'd0d0735c531e1becf049c244', - '12daac5630efa5396f770ce1a66b21f7b2101c', - '14d253c3967b70609b7cbb7c49916028324526', - '9a6f49975bcadeaf', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00764c63b8058e3c9696766cfa'), - ( '77b60f011c03e1525899bcae', - 'e88b6a46c78d63e52eb8c546efb5de6f75e9cc0d', - '5545ff1a085ee2efbf52b2e04bee1e2336c73e3f', - '762c0c7744fe7e3c', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00f8b678094e3b3c9696766cfa'), - ( 'cd9044d2b71fdb8120ea60c0', - '6435acbafb11a82e2f071d7ca4a5ebd93a803ba87f', - '009769ecabdf48625594c59251e6035722675e04c8', - '47099e5ae0704551', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00d560912d3f703c9696766cfa'), - ( 'd85bc7e69f944fb8', - '8a19b950bcf71a018e5e6701c91787659809d67dbedd18', - 'bc218daa947427b6db386a99ac1aef23ade0b52939cb6a', - '637cf9bec2408897c6ba', - 'd7828d13b2b0bdc325a76236df93cc6b', - '0042fff8f1951c3c9696766cfa'), - ( '74a0ebc9069f5b37', - '1761433c37c5a35fc1f39f406302eb907c6163be38c98437', - '5810e6fd25874022e80361a478e3e9cf484ab04f447efff6', - 'f0a477cc2fc9bf548944', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00920f40e56cdc3c9696766cfa'), - ( '44a3aa3aae6475ca', - 'a434a8e58500c6e41530538862d686ea9e81301b5ae4226bfa', - 'f2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f154', - '4d4151a4ed3a8b87b9ce', - 'd7828d13b2b0bdc325a76236df93cc6b', - '0027ca0c7120bc3c9696766cfa'), - ( 'ec46bb63b02520c33c49fd70', - 'b96b49e21d621741632875db7f6c9243d2d7c2', - '31d750a09da3ed7fddd49a2032aabf17ec8ebf', - '7d22c8088c666be5c197', - 'd7828d13b2b0bdc325a76236df93cc6b', - '005b8ccbcd9af83c9696766cfa'), - ( '47a65ac78b3d594227e85e71', - 'e2fcfbb880442c731bf95167c8ffd7895e337076', - 'e882f1dbd38ce3eda7c23f04dd65071eb41342ac', - 'df7e00dccec7ae52987d', - 'd7828d13b2b0bdc325a76236df93cc6b', - '003ebe94044b9a3c9696766cfa'), - ( '6e37a6ef546d955d34ab6059', - 'abf21c0b02feb88f856df4a37381bce3cc128517d4', - 'f32905b88a641b04b9c9ffb58cc390900f3da12ab1', - '6dce9e82efa16da62059', - 'd7828d13b2b0bdc325a76236df93cc6b', - '008d493b30ae8b3c9696766cfa'), - ] - - test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - # Encrypt - cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Class exercising the CCM test vectors found in Appendix C + of NIST SP 800-38C and in RFC 3610""" + + # List of test vectors, each made up of: + # - authenticated data + # - plaintext + # - ciphertext + # - MAC + # - AES key + # - nonce + test_vectors_hex = [ + # NIST SP 800 38C + ( + "0001020304050607", + "20212223", + "7162015b", + "4dac255d", + "404142434445464748494a4b4c4d4e4f", + "10111213141516", + ), + ( + "000102030405060708090a0b0c0d0e0f", + "202122232425262728292a2b2c2d2e2f", + "d2a1f0e051ea5f62081a7792073d593d", + "1fc64fbfaccd", + "404142434445464748494a4b4c4d4e4f", + "1011121314151617", + ), + ( + "000102030405060708090a0b0c0d0e0f10111213", + "202122232425262728292a2b2c2d2e2f3031323334353637", + "e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5", + "484392fbc1b09951", + "404142434445464748494a4b4c4d4e4f", + "101112131415161718191a1b", + ), + ( + ("".join(["%02X" % (x * 16 + y) for x in range(0, 16) for y in range(0, 16)])) * 256, + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72", + "b4ac6bec93e8598e7f0dadbcea5b", + "404142434445464748494a4b4c4d4e4f", + "101112131415161718191a1b1c", + ), + # RFC3610 + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e", + "588c979a61c663d2f066d0c2c0f989806d5f6b61dac384", + "17e8d12cfdf926e0", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000003020100a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b", + "a091d56e10400916", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000004030201a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "51b1e5f44a197d1da46b0f8e2d282ae871e838bb64da859657", + "4adaa76fbd9fb0c5", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000005040302A0A1A2A3A4A5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e", + "a28c6865939a9a79faaa5c4c2a9d4a91cdac8c", + "96c861b9c9e61ef1", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000006050403a0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e1f", + "dcf1fb7b5d9e23fb9d4e131253658ad86ebdca3e", + "51e83f077d9c2d93", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000007060504a0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "6fc1b011f006568b5171a42d953d469b2570a4bd87", + "405a0443ac91cb94", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000008070605a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e", + "0135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c", + "048c56602c97acbb7490", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000009080706a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "7b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24", + "c17b4433f434963f34b4", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000a090807a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "82531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197", + "ea9c07e56b5eb17e5f4e", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000b0a0908a0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e", + "07342594157785152b074098330abb141b947b", + "566aa9406b4d999988dd", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000c0b0a09a0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e1f", + "676bb20380b0e301e8ab79590a396da78b834934", + "f53aa2e9107a8b6c022c", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000d0c0b0aa0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "c0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43", + "cd1aa31662e7ad65d6db", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000e0d0c0ba0a1a2a3a4a5", + ), + ( + "0be1a88bace018b1", + "08e8cf97d820ea258460e96ad9cf5289054d895ceac47c", + "4cb97f86a2a4689a877947ab8091ef5386a6ffbdd080f8", + "e78cf7cb0cddd7b3", + "d7828d13b2b0bdc325a76236df93cc6b", + "00412b4ea9cdbe3c9696766cfa", + ), + ( + "63018f76dc8a1bcb", + "9020ea6f91bdd85afa0039ba4baff9bfb79c7028949cd0ec", + "4ccb1e7ca981befaa0726c55d378061298c85c92814abc33", + "c52ee81d7d77c08a", + "d7828d13b2b0bdc325a76236df93cc6b", + "0033568ef7b2633c9696766cfa", + ), + ( + "aa6cfa36cae86b40", + "b916e0eacc1c00d7dcec68ec0b3bbb1a02de8a2d1aa346132e", + "b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708", + "a776796edb723506", + "d7828d13b2b0bdc325a76236df93cc6b", + "00103fe41336713c9696766cfa", + ), + ( + "d0d0735c531e1becf049c244", + "12daac5630efa5396f770ce1a66b21f7b2101c", + "14d253c3967b70609b7cbb7c49916028324526", + "9a6f49975bcadeaf", + "d7828d13b2b0bdc325a76236df93cc6b", + "00764c63b8058e3c9696766cfa", + ), + ( + "77b60f011c03e1525899bcae", + "e88b6a46c78d63e52eb8c546efb5de6f75e9cc0d", + "5545ff1a085ee2efbf52b2e04bee1e2336c73e3f", + "762c0c7744fe7e3c", + "d7828d13b2b0bdc325a76236df93cc6b", + "00f8b678094e3b3c9696766cfa", + ), + ( + "cd9044d2b71fdb8120ea60c0", + "6435acbafb11a82e2f071d7ca4a5ebd93a803ba87f", + "009769ecabdf48625594c59251e6035722675e04c8", + "47099e5ae0704551", + "d7828d13b2b0bdc325a76236df93cc6b", + "00d560912d3f703c9696766cfa", + ), + ( + "d85bc7e69f944fb8", + "8a19b950bcf71a018e5e6701c91787659809d67dbedd18", + "bc218daa947427b6db386a99ac1aef23ade0b52939cb6a", + "637cf9bec2408897c6ba", + "d7828d13b2b0bdc325a76236df93cc6b", + "0042fff8f1951c3c9696766cfa", + ), + ( + "74a0ebc9069f5b37", + "1761433c37c5a35fc1f39f406302eb907c6163be38c98437", + "5810e6fd25874022e80361a478e3e9cf484ab04f447efff6", + "f0a477cc2fc9bf548944", + "d7828d13b2b0bdc325a76236df93cc6b", + "00920f40e56cdc3c9696766cfa", + ), + ( + "44a3aa3aae6475ca", + "a434a8e58500c6e41530538862d686ea9e81301b5ae4226bfa", + "f2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f154", + "4d4151a4ed3a8b87b9ce", + "d7828d13b2b0bdc325a76236df93cc6b", + "0027ca0c7120bc3c9696766cfa", + ), + ( + "ec46bb63b02520c33c49fd70", + "b96b49e21d621741632875db7f6c9243d2d7c2", + "31d750a09da3ed7fddd49a2032aabf17ec8ebf", + "7d22c8088c666be5c197", + "d7828d13b2b0bdc325a76236df93cc6b", + "005b8ccbcd9af83c9696766cfa", + ), + ( + "47a65ac78b3d594227e85e71", + "e2fcfbb880442c731bf95167c8ffd7895e337076", + "e882f1dbd38ce3eda7c23f04dd65071eb41342ac", + "df7e00dccec7ae52987d", + "d7828d13b2b0bdc325a76236df93cc6b", + "003ebe94044b9a3c9696766cfa", + ), + ( + "6e37a6ef546d955d34ab6059", + "abf21c0b02feb88f856df4a37381bce3cc128517d4", + "f32905b88a641b04b9c9ffb58cc390900f3da12ab1", + "6dce9e82efa16da62059", + "d7828d13b2b0bdc325a76236df93cc6b", + "008d493b30ae8b3c9696766cfa", + ), + ] + + test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, **extra_params): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._extra_params = extra_params - self._id = "None" - - def setUp(self): - - def filter_tag(group): - return group['tagSize'] // 8 - - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aes_ccm_test.json", - "Wycheproof AES CCM", - group_tag={'tag_size': filter_tag}) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt CCM Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - except ValueError as e: - if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e): - assert not tv.valid - return - if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e): - assert not tv.valid - return - raise e - - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt CCM Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - except ValueError as e: - if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e): - assert not tv.valid - return - if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e): - assert not tv.valid - return - raise e - - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def test_corrupt_decrypt(self, tv): - self._id = "Wycheproof Corrupt Decrypt CCM Test #" + str(tv.id) - if len(tv.iv) not in range(7, 13 + 1, 2) or len(tv.ct) == 0: - return - cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - cipher.update(tv.aad) - ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) - self.test_corrupt_decrypt(tv) + def __init__(self, wycheproof_warnings, **extra_params): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._extra_params = extra_params + self._id = "None" + + def setUp(self): + def filter_tag(group): + return group["tagSize"] // 8 + + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aes_ccm_test.json", + "Wycheproof AES CCM", + group_tag={"tag_size": filter_tag}, + ) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt CCM Test #" + str(tv.id) + + try: + cipher = AES.new( + tv.key, + AES.MODE_CCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + except ValueError as e: + if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e): + assert not tv.valid + return + if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e): + assert not tv.valid + return + raise e + + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt CCM Test #" + str(tv.id) + + try: + cipher = AES.new( + tv.key, + AES.MODE_CCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + except ValueError as e: + if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e): + assert not tv.valid + return + if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e): + assert not tv.valid + return + raise e + + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def test_corrupt_decrypt(self, tv): + self._id = "Wycheproof Corrupt Decrypt CCM Test #" + str(tv.id) + if len(tv.iv) not in range(7, 13 + 1, 2) or len(tv.ct) == 0: + return + cipher = AES.new( + tv.key, + AES.MODE_CCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + cipher.update(tv.aad) + ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) + self.test_corrupt_decrypt(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(CcmTests) + tests += list_test_cases(CcmFSMTests) + tests += [TestVectors()] + tests += [TestVectorsWycheproof(wycheproof_warnings)] + + return tests - tests = [] - tests += list_test_cases(CcmTests) - tests += list_test_cases(CcmFSMTests) - tests += [TestVectors()] - tests += [TestVectorsWycheproof(wycheproof_warnings)] - return tests +if __name__ == "__main__": + def suite(): + unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CFB.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CFB.py index 673bf8ed..b3872f6c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CFB.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CFB.py @@ -41,371 +41,421 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class CfbTests(BlockChainingTests): - - aes_mode = AES.MODE_CFB - des3_mode = DES3.MODE_CFB - - # Redefine test_unaligned_data_128/64 - - def test_unaligned_data_128(self): - plaintexts = [ b"7777777" ] * 100 - - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - def test_unaligned_data_64(self): - plaintexts = [ b"7777777" ] * 100 - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - # Extra - - def test_segment_size_128(self): - for bits in range(8, 129, 8): - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, - segment_size=bits) - - for bits in 0, 7, 9, 127, 129: - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CFB, - self.iv_128, - segment_size=bits) - - def test_segment_size_64(self): - for bits in range(8, 65, 8): - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, - segment_size=bits) - - for bits in 0, 7, 9, 63, 65: - self.assertRaises(ValueError, DES3.new, self.key_192, AES.MODE_CFB, - self.iv_64, - segment_size=bits) + aes_mode = AES.MODE_CFB + des3_mode = DES3.MODE_CFB + + # Redefine test_unaligned_data_128/64 + + def test_unaligned_data_128(self): + plaintexts = [b"7777777"] * 100 + + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + def test_unaligned_data_64(self): + plaintexts = [b"7777777"] * 100 + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + # Extra + + def test_segment_size_128(self): + for bits in range(8, 129, 8): + cipher = AES.new( + self.key_128, + AES.MODE_CFB, + self.iv_128, + segment_size=bits, + ) + + for bits in 0, 7, 9, 127, 129: + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CFB, + self.iv_128, + segment_size=bits, + ) + + def test_segment_size_64(self): + for bits in range(8, 65, 8): + cipher = DES3.new( + self.key_192, + DES3.MODE_CFB, + self.iv_64, + segment_size=bits, + ) + + for bits in 0, 7, 9, 63, 65: + self.assertRaises( + ValueError, + DES3.new, + self.key_192, + AES.MODE_CFB, + self.iv_64, + segment_size=bits, + ) class NistCfbVectors(unittest.TestCase): - - def _do_kat_aes_test(self, file_name, segment_size): - - test_vectors = load_test_vectors(("Cipher", "AES"), - file_name, - "AES CFB%d KAT" % segment_size, - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv, - segment_size=segment_size) - if direction == "[ENCRYPT]": - self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) - elif direction == "[DECRYPT]": - self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) - else: - assert False - - # See Section 6.4.5 in AESAVS - def _do_mct_aes_test(self, file_name, segment_size): - - test_vectors = load_test_vectors(("Cipher", "AES"), - file_name, - "AES CFB%d Montecarlo" % segment_size, - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - assert(segment_size in (8, 128)) - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv, - segment_size=segment_size) - - def get_input(input_text, output_seq, j): - # CFB128 - if segment_size == 128: - if j >= 2: - return output_seq[-2] - return [input_text, tv.iv][j] - # CFB8 - if j == 0: - return input_text - elif j <= 16: - return tv.iv[j - 1:j] - return output_seq[j - 17] - - if direction == '[ENCRYPT]': - cts = [] - for j in range(1000): - plaintext = get_input(tv.plaintext, cts, j) - cts.append(cipher.encrypt(plaintext)) - self.assertEqual(cts[-1], tv.ciphertext) - elif direction == '[DECRYPT]': - pts = [] - for j in range(1000): - ciphertext = get_input(tv.ciphertext, pts, j) - pts.append(cipher.decrypt(ciphertext)) - self.assertEqual(pts[-1], tv.plaintext) - else: - assert False - - def _do_tdes_test(self, file_name, segment_size): - - test_vectors = load_test_vectors(("Cipher", "TDES"), - file_name, - "TDES CFB%d KAT" % segment_size, - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - if hasattr(tv, "keys"): - cipher = DES.new(tv.keys, DES.MODE_CFB, tv.iv, - segment_size=segment_size) - else: - if tv.key1 != tv.key3: - key = tv.key1 + tv.key2 + tv.key3 # Option 3 - else: - key = tv.key1 + tv.key2 # Option 2 - cipher = DES3.new(key, DES3.MODE_CFB, tv.iv, - segment_size=segment_size) - if direction == "[ENCRYPT]": - self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) - elif direction == "[DECRYPT]": - self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) - else: - assert False + def _do_kat_aes_test(self, file_name, segment_size): + test_vectors = load_test_vectors( + ("Cipher", "AES"), + file_name, + "AES CFB%d KAT" % segment_size, + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + cipher = AES.new( + tv.key, + AES.MODE_CFB, + tv.iv, + segment_size=segment_size, + ) + if direction == "[ENCRYPT]": + self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) + elif direction == "[DECRYPT]": + self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) + else: + assert False + + # See Section 6.4.5 in AESAVS + def _do_mct_aes_test(self, file_name, segment_size): + test_vectors = load_test_vectors( + ("Cipher", "AES"), + file_name, + "AES CFB%d Montecarlo" % segment_size, + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + assert segment_size in (8, 128) + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + cipher = AES.new( + tv.key, + AES.MODE_CFB, + tv.iv, + segment_size=segment_size, + ) + + def get_input(input_text, output_seq, j): + # CFB128 + if segment_size == 128: + if j >= 2: + return output_seq[-2] + return [input_text, tv.iv][j] + # CFB8 + if j == 0: + return input_text + elif j <= 16: + return tv.iv[j - 1 : j] + return output_seq[j - 17] + + if direction == "[ENCRYPT]": + cts = [] + for j in range(1000): + plaintext = get_input(tv.plaintext, cts, j) + cts.append(cipher.encrypt(plaintext)) + self.assertEqual(cts[-1], tv.ciphertext) + elif direction == "[DECRYPT]": + pts = [] + for j in range(1000): + ciphertext = get_input(tv.ciphertext, pts, j) + pts.append(cipher.decrypt(ciphertext)) + self.assertEqual(pts[-1], tv.plaintext) + else: + assert False + + def _do_tdes_test(self, file_name, segment_size): + test_vectors = load_test_vectors( + ("Cipher", "TDES"), + file_name, + "TDES CFB%d KAT" % segment_size, + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + if hasattr(tv, "keys"): + cipher = DES.new( + tv.keys, + DES.MODE_CFB, + tv.iv, + segment_size=segment_size, + ) + else: + if tv.key1 != tv.key3: + key = tv.key1 + tv.key2 + tv.key3 # Option 3 + else: + key = tv.key1 + tv.key2 # Option 2 + cipher = DES3.new( + key, + DES3.MODE_CFB, + tv.iv, + segment_size=segment_size, + ) + if direction == "[ENCRYPT]": + self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) + elif direction == "[DECRYPT]": + self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) + else: + assert False # Create one test method per file nist_aes_kat_mmt_files = ( - # KAT - "CFB?GFSbox128.rsp", - "CFB?GFSbox192.rsp", - "CFB?GFSbox256.rsp", - "CFB?KeySbox128.rsp", - "CFB?KeySbox192.rsp", - "CFB?KeySbox256.rsp", - "CFB?VarKey128.rsp", - "CFB?VarKey192.rsp", - "CFB?VarKey256.rsp", - "CFB?VarTxt128.rsp", - "CFB?VarTxt192.rsp", - "CFB?VarTxt256.rsp", - # MMT - "CFB?MMT128.rsp", - "CFB?MMT192.rsp", - "CFB?MMT256.rsp", - ) + # KAT + "CFB?GFSbox128.rsp", + "CFB?GFSbox192.rsp", + "CFB?GFSbox256.rsp", + "CFB?KeySbox128.rsp", + "CFB?KeySbox192.rsp", + "CFB?KeySbox256.rsp", + "CFB?VarKey128.rsp", + "CFB?VarKey192.rsp", + "CFB?VarKey256.rsp", + "CFB?VarTxt128.rsp", + "CFB?VarTxt192.rsp", + "CFB?VarTxt256.rsp", + # MMT + "CFB?MMT128.rsp", + "CFB?MMT192.rsp", + "CFB?MMT256.rsp", +) nist_aes_mct_files = ( - "CFB?MCT128.rsp", - "CFB?MCT192.rsp", - "CFB?MCT256.rsp", - ) + "CFB?MCT128.rsp", + "CFB?MCT192.rsp", + "CFB?MCT256.rsp", +) for file_gen_name in nist_aes_kat_mmt_files: - for bits in "8", "128": - file_name = file_gen_name.replace("?", bits) - def new_func(self, file_name=file_name, bits=bits): - self._do_kat_aes_test(file_name, int(bits)) - setattr(NistCfbVectors, "test_AES_" + file_name, new_func) + for bits in "8", "128": + file_name = file_gen_name.replace("?", bits) + + def new_func(self, file_name=file_name, bits=bits): + self._do_kat_aes_test(file_name, int(bits)) + + setattr(NistCfbVectors, "test_AES_" + file_name, new_func) for file_gen_name in nist_aes_mct_files: - for bits in "8", "128": - file_name = file_gen_name.replace("?", bits) - def new_func(self, file_name=file_name, bits=bits): - self._do_mct_aes_test(file_name, int(bits)) - setattr(NistCfbVectors, "test_AES_" + file_name, new_func) + for bits in "8", "128": + file_name = file_gen_name.replace("?", bits) + + def new_func(self, file_name=file_name, bits=bits): + self._do_mct_aes_test(file_name, int(bits)) + + setattr(NistCfbVectors, "test_AES_" + file_name, new_func) del file_name, new_func nist_tdes_files = ( - "TCFB?MMT2.rsp", # 2TDES - "TCFB?MMT3.rsp", # 3TDES - "TCFB?invperm.rsp", # Single DES - "TCFB?permop.rsp", - "TCFB?subtab.rsp", - "TCFB?varkey.rsp", - "TCFB?vartext.rsp", - ) + "TCFB?MMT2.rsp", # 2TDES + "TCFB?MMT3.rsp", # 3TDES + "TCFB?invperm.rsp", # Single DES + "TCFB?permop.rsp", + "TCFB?subtab.rsp", + "TCFB?varkey.rsp", + "TCFB?vartext.rsp", +) for file_gen_name in nist_tdes_files: - for bits in "8", "64": - file_name = file_gen_name.replace("?", bits) - def new_func(self, file_name=file_name, bits=bits): - self._do_tdes_test(file_name, int(bits)) - setattr(NistCfbVectors, "test_TDES_" + file_name, new_func) + for bits in "8", "64": + file_name = file_gen_name.replace("?", bits) + + def new_func(self, file_name=file_name, bits=bits): + self._do_tdes_test(file_name, int(bits)) + + setattr(NistCfbVectors, "test_TDES_" + file_name, new_func) # END OF NIST CBC TEST VECTORS class SP800TestVectors(unittest.TestCase): - """Class exercising the CFB test vectors found in Section F.3 - of NIST SP 800-3A""" - - def test_aes_128_cfb8(self): - plaintext = '6bc1bee22e409f96e93d7e117393172aae2d' - ciphertext = '3b79424c9c0dd436bace9e0ed4586a4f32b9' - key = '2b7e151628aed2a6abf7158809cf4f3c' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_192_cfb8(self): - plaintext = '6bc1bee22e409f96e93d7e117393172aae2d' - ciphertext = 'cda2521ef0a905ca44cd057cbf0d47a0678a' - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_256_cfb8(self): - plaintext = '6bc1bee22e409f96e93d7e117393172aae2d' - ciphertext = 'dc1f1a8520a64db55fcc8ac554844e889700' - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_128_cfb128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '3b3fd92eb72dad20333449f8e83cfb4a' +\ - 'c8a64537a0b3a93fcde3cdad9f1ce58b' +\ - '26751f67a3cbb140b1808cf187a4f4df' +\ - 'c04b05357c5d1c0eeac4c66f9ff7f2e6' - key = '2b7e151628aed2a6abf7158809cf4f3c' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_192_cfb128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = 'cdc80d6fddf18cab34c25909c99a4174' +\ - '67ce7f7f81173621961a2b70171d3d7a' +\ - '2e1e8a1dd59b88b1c8e60fed1efac4c9' +\ - 'c05f9f9ca9834fa042ae8fba584b09ff' - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_256_cfb128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - - ciphertext = 'dc7e84bfda79164b7ecd8486985d3860' +\ - '39ffed143b28b1c832113c6331e5407b' +\ - 'df10132415e54b92a13ed0a8267ae2f9' +\ - '75a385741ab9cef82031623d55b1e471' - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) + """Class exercising the CFB test vectors found in Section F.3 + of NIST SP 800-3A""" + + def test_aes_128_cfb8(self): + plaintext = "6bc1bee22e409f96e93d7e117393172aae2d" + ciphertext = "3b79424c9c0dd436bace9e0ed4586a4f32b9" + key = "2b7e151628aed2a6abf7158809cf4f3c" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_192_cfb8(self): + plaintext = "6bc1bee22e409f96e93d7e117393172aae2d" + ciphertext = "cda2521ef0a905ca44cd057cbf0d47a0678a" + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_256_cfb8(self): + plaintext = "6bc1bee22e409f96e93d7e117393172aae2d" + ciphertext = "dc1f1a8520a64db55fcc8ac554844e889700" + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_128_cfb128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "3b3fd92eb72dad20333449f8e83cfb4a" + + "c8a64537a0b3a93fcde3cdad9f1ce58b" + + "26751f67a3cbb140b1808cf187a4f4df" + + "c04b05357c5d1c0eeac4c66f9ff7f2e6" + ) + key = "2b7e151628aed2a6abf7158809cf4f3c" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_192_cfb128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "cdc80d6fddf18cab34c25909c99a4174" + + "67ce7f7f81173621961a2b70171d3d7a" + + "2e1e8a1dd59b88b1c8e60fed1efac4c9" + + "c05f9f9ca9834fa042ae8fba584b09ff" + ) + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_256_cfb128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + + ciphertext = ( + "dc7e84bfda79164b7ecd8486985d3860" + + "39ffed143b28b1c832113c6331e5407b" + + "df10132415e54b92a13ed0a8267ae2f9" + + "75a385741ab9cef82031623d55b1e471" + ) + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) def get_tests(config={}): - tests = [] - tests += list_test_cases(CfbTests) - if config.get('slow_tests'): - tests += list_test_cases(NistCfbVectors) - tests += list_test_cases(SP800TestVectors) - return tests + tests = [] + tests += list_test_cases(CfbTests) + if config.get("slow_tests"): + tests += list_test_cases(NistCfbVectors) + tests += list_test_cases(SP800TestVectors) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CTR.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CTR.py index ef5be5d0..466a17d4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CTR.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_CTR.py @@ -37,436 +37,552 @@ from Cryptodome.Hash import SHAKE128, SHA256 from Cryptodome.Util import Counter -def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) - -class CtrTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - key_192 = get_tag_random("key_192", 24) - nonce_32 = get_tag_random("nonce_32", 4) - nonce_64 = get_tag_random("nonce_64", 8) - ctr_64 = Counter.new(32, prefix=nonce_32) - ctr_128 = Counter.new(64, prefix=nonce_64) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_loopback_64(self): - cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) - pt = get_tag_random("plaintext", 8 * 100) - ct = cipher.encrypt(pt) - - cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_invalid_counter_parameter(self): - # Counter object is required for ciphers with short block size - self.assertRaises(TypeError, DES3.new, self.key_192, AES.MODE_CTR) - # Positional arguments are not allowed (Counter must be passed as - # keyword) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, self.ctr_128) - - def test_nonce_attribute(self): - # Nonce attribute is the prefix passed to Counter (DES3) - cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) - self.assertEqual(cipher.nonce, self.nonce_32) - - # Nonce attribute is the prefix passed to Counter (AES) - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - self.assertEqual(cipher.nonce, self.nonce_64) - - # Nonce attribute is not defined if suffix is used in Counter - counter = Counter.new(64, prefix=self.nonce_32, suffix=self.nonce_32) - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - self.assertFalse(hasattr(cipher, "nonce")) - - def test_nonce_parameter(self): - # Nonce parameter becomes nonce attribute - cipher1 = AES.new(self.key_128, AES.MODE_CTR, nonce=self.nonce_64) - self.assertEqual(cipher1.nonce, self.nonce_64) - - counter = Counter.new(64, prefix=self.nonce_64, initial_value=0) - cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - pt = get_tag_random("plaintext", 65536) - self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) - - # Nonce is implicitly created (for AES) when no parameters are passed - nonce1 = AES.new(self.key_128, AES.MODE_CTR).nonce - nonce2 = AES.new(self.key_128, AES.MODE_CTR).nonce - self.assertNotEqual(nonce1, nonce2) - self.assertEqual(len(nonce1), 8) - - # Nonce can be zero-length - cipher = AES.new(self.key_128, AES.MODE_CTR, nonce=b"") - self.assertEqual(b"", cipher.nonce) - cipher.encrypt(b'0'*300) - - # Nonce and Counter are mutually exclusive - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, - counter=self.ctr_128, nonce=self.nonce_64) - - def test_initial_value_parameter(self): - # Test with nonce parameter - cipher1 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, initial_value=0xFFFF) - counter = Counter.new(64, prefix=self.nonce_64, initial_value=0xFFFF) - cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - pt = get_tag_random("plaintext", 65536) - self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) - - # Test without nonce parameter - cipher1 = AES.new(self.key_128, AES.MODE_CTR, - initial_value=0xFFFF) - counter = Counter.new(64, prefix=cipher1.nonce, initial_value=0xFFFF) - cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - pt = get_tag_random("plaintext", 65536) - self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) - - # Initial_value and Counter are mutually exclusive - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, - counter=self.ctr_128, initial_value=0) - - def test_initial_value_bytes_parameter(self): - # Same result as when passing an integer - cipher1 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, - initial_value=b"\x00"*6+b"\xFF\xFF") - cipher2 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, initial_value=0xFFFF) - pt = get_tag_random("plaintext", 65536) - self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) - - # Fail if the iv is too large - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - initial_value=b"5"*17) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, initial_value=b"5"*9) - - # Fail if the iv is too short - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - initial_value=b"5"*15) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, initial_value=b"5"*7) - - def test_iv_with_matching_length(self): - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - counter=Counter.new(120)) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - counter=Counter.new(136)) - - def test_block_size_128(self): - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_block_size_64(self): - cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) - self.assertEqual(cipher.block_size, DES3.block_size) - - def test_unaligned_data_128(self): - plaintexts = [ b"7777777" ] * 100 - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - def test_unaligned_data_64(self): - plaintexts = [ b"7777777" ] * 100 - cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, - 7, counter=self.ctr_128) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, - counter=self.ctr_128, unknown=7) - # But some are only known by the base cipher (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128, use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_wrap_around(self): - # Counter is only 8 bits, so we can only encrypt/decrypt 256 blocks (=4096 bytes) - counter = Counter.new(8, prefix=bchr(9) * 15) - max_bytes = 4096 - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - cipher.encrypt(b'9' * max_bytes) - self.assertRaises(OverflowError, cipher.encrypt, b'9') - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - self.assertRaises(OverflowError, cipher.encrypt, b'9' * (max_bytes + 1)) - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - cipher.decrypt(b'9' * max_bytes) - self.assertRaises(OverflowError, cipher.decrypt, b'9') - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - self.assertRaises(OverflowError, cipher.decrypt, b'9' * (max_bytes + 1)) - - def test_bytearray(self): - data = b"1" * 16 - iv = b"\x00" * 6 + b"\xFF\xFF" - - # Encrypt - cipher1 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, - initial_value=iv) - ref1 = cipher1.encrypt(data) - - cipher2 = AES.new(self.key_128, AES.MODE_CTR, - nonce=bytearray(self.nonce_64), - initial_value=bytearray(iv)) - ref2 = cipher2.encrypt(bytearray(data)) - - self.assertEqual(ref1, ref2) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - cipher3 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, - initial_value=iv) - ref3 = cipher3.decrypt(data) - - cipher4 = AES.new(self.key_128, AES.MODE_CTR, - nonce=bytearray(self.nonce_64), - initial_value=bytearray(iv)) - ref4 = cipher4.decrypt(bytearray(data)) - - self.assertEqual(ref3, ref4) - - def test_very_long_data(self): - cipher = AES.new(b'A' * 32, AES.MODE_CTR, nonce=b'') - ct = cipher.encrypt(b'B' * 1000000) - digest = SHA256.new(ct).hexdigest() - self.assertEqual(digest, "96204fc470476561a3a8f3b6fe6d24be85c87510b638142d1d0fb90989f8a6a6") - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - ct = cipher.encrypt(pt) - - output = bytearray(128) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - def test_output_param_neg(self): - LEN_PT = 128 - - pt = b'5' * LEN_PT - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - ct = cipher.encrypt(pt) - - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT) +def get_tag_random(tag, length): + return SHAKE128.new(data=tobytes(tag)).read(length) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT) - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) +class CtrTests(unittest.TestCase): + key_128 = get_tag_random("key_128", 16) + key_192 = get_tag_random("key_192", 24) + nonce_32 = get_tag_random("nonce_32", 4) + nonce_64 = get_tag_random("nonce_64", 8) + ctr_64 = Counter.new(32, prefix=nonce_32) + ctr_128 = Counter.new(64, prefix=nonce_64) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_loopback_64(self): + cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) + pt = get_tag_random("plaintext", 8 * 100) + ct = cipher.encrypt(pt) + + cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_invalid_counter_parameter(self): + # Counter object is required for ciphers with short block size + self.assertRaises(TypeError, DES3.new, self.key_192, AES.MODE_CTR) + # Positional arguments are not allowed (Counter must be passed as + # keyword) + self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, self.ctr_128) + + def test_nonce_attribute(self): + # Nonce attribute is the prefix passed to Counter (DES3) + cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) + self.assertEqual(cipher.nonce, self.nonce_32) + + # Nonce attribute is the prefix passed to Counter (AES) + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + self.assertEqual(cipher.nonce, self.nonce_64) + + # Nonce attribute is not defined if suffix is used in Counter + counter = Counter.new(64, prefix=self.nonce_32, suffix=self.nonce_32) + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + self.assertFalse(hasattr(cipher, "nonce")) + + def test_nonce_parameter(self): + # Nonce parameter becomes nonce attribute + cipher1 = AES.new(self.key_128, AES.MODE_CTR, nonce=self.nonce_64) + self.assertEqual(cipher1.nonce, self.nonce_64) + + counter = Counter.new(64, prefix=self.nonce_64, initial_value=0) + cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + pt = get_tag_random("plaintext", 65536) + self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) + + # Nonce is implicitly created (for AES) when no parameters are passed + nonce1 = AES.new(self.key_128, AES.MODE_CTR).nonce + nonce2 = AES.new(self.key_128, AES.MODE_CTR).nonce + self.assertNotEqual(nonce1, nonce2) + self.assertEqual(len(nonce1), 8) + + # Nonce can be zero-length + cipher = AES.new(self.key_128, AES.MODE_CTR, nonce=b"") + self.assertEqual(b"", cipher.nonce) + cipher.encrypt(b"0" * 300) + + # Nonce and Counter are mutually exclusive + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=self.ctr_128, + nonce=self.nonce_64, + ) + + def test_initial_value_parameter(self): + # Test with nonce parameter + cipher1 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=0xFFFF, + ) + counter = Counter.new(64, prefix=self.nonce_64, initial_value=0xFFFF) + cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + pt = get_tag_random("plaintext", 65536) + self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) + + # Test without nonce parameter + cipher1 = AES.new( + self.key_128, + AES.MODE_CTR, + initial_value=0xFFFF, + ) + counter = Counter.new(64, prefix=cipher1.nonce, initial_value=0xFFFF) + cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + pt = get_tag_random("plaintext", 65536) + self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) + + # Initial_value and Counter are mutually exclusive + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=self.ctr_128, + initial_value=0, + ) + + def test_initial_value_bytes_parameter(self): + # Same result as when passing an integer + cipher1 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=b"\x00" * 6 + b"\xff\xff", + ) + cipher2 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=0xFFFF, + ) + pt = get_tag_random("plaintext", 65536) + self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) + + # Fail if the iv is too large + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + initial_value=b"5" * 17, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=b"5" * 9, + ) + + # Fail if the iv is too short + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + initial_value=b"5" * 15, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=b"5" * 7, + ) + + def test_iv_with_matching_length(self): + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=Counter.new(120), + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=Counter.new(136), + ) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_block_size_64(self): + cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) + self.assertEqual(cipher.block_size, DES3.block_size) + + def test_unaligned_data_128(self): + plaintexts = [b"7777777"] * 100 + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + def test_unaligned_data_64(self): + plaintexts = [b"7777777"] * 100 + cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CTR, + 7, + counter=self.ctr_128, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=self.ctr_128, + unknown=7, + ) + # But some are only known by the base cipher (e.g. use_aesni consumed by the AES module) + AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128, use_aesni=False) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_wrap_around(self): + # Counter is only 8 bits, so we can only encrypt/decrypt 256 blocks (=4096 bytes) + counter = Counter.new(8, prefix=bchr(9) * 15) + max_bytes = 4096 + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + cipher.encrypt(b"9" * max_bytes) + self.assertRaises(OverflowError, cipher.encrypt, b"9") + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + self.assertRaises(OverflowError, cipher.encrypt, b"9" * (max_bytes + 1)) + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + cipher.decrypt(b"9" * max_bytes) + self.assertRaises(OverflowError, cipher.decrypt, b"9") + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + self.assertRaises(OverflowError, cipher.decrypt, b"9" * (max_bytes + 1)) + + def test_bytearray(self): + data = b"1" * 16 + iv = b"\x00" * 6 + b"\xff\xff" + + # Encrypt + cipher1 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=iv, + ) + ref1 = cipher1.encrypt(data) + + cipher2 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=bytearray(self.nonce_64), + initial_value=bytearray(iv), + ) + ref2 = cipher2.encrypt(bytearray(data)) + + self.assertEqual(ref1, ref2) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + cipher3 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=iv, + ) + ref3 = cipher3.decrypt(data) + + cipher4 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=bytearray(self.nonce_64), + initial_value=bytearray(iv), + ) + ref4 = cipher4.decrypt(bytearray(data)) + + self.assertEqual(ref3, ref4) + + def test_very_long_data(self): + cipher = AES.new(b"A" * 32, AES.MODE_CTR, nonce=b"") + ct = cipher.encrypt(b"B" * 1000000) + digest = SHA256.new(ct).hexdigest() + self.assertEqual(digest, "96204fc470476561a3a8f3b6fe6d24be85c87510b638142d1d0fb90989f8a6a6") + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + ct = cipher.encrypt(pt) + + output = bytearray(128) + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + ct = cipher.encrypt(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + LEN_PT = 128 + + pt = b"5" * LEN_PT + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + ct = cipher.encrypt(pt) + + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * LEN_PT) + + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * LEN_PT) + + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) class SP800TestVectors(unittest.TestCase): - """Class exercising the CTR test vectors found in Section F.5 - of NIST SP 800-38A""" - - def test_aes_128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '874d6191b620e3261bef6864990db6ce' +\ - '9806f66b7970fdff8617187bb9fffdff' +\ - '5ae4df3edbd5d35e5b4f09020db03eab' +\ - '1e031dda2fbe03d1792170a0f3009cee' - key = '2b7e151628aed2a6abf7158809cf4f3c' - counter = Counter.new(nbits=16, - prefix=unhexlify('f0f1f2f3f4f5f6f7f8f9fafbfcfd'), - initial_value=0xfeff) - - key = unhexlify(key) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_192(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '1abc932417521ca24f2b0459fe7e6e0b' +\ - '090339ec0aa6faefd5ccc2c6f4ce8e94' +\ - '1e36b26bd1ebc670d1bd1d665620abf7' +\ - '4f78a7f6d29809585a97daec58c6b050' - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - counter = Counter.new(nbits=16, - prefix=unhexlify('f0f1f2f3f4f5f6f7f8f9fafbfcfd'), - initial_value=0xfeff) - - key = unhexlify(key) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_256(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '601ec313775789a5b7a7f504bbf3d228' +\ - 'f443e3ca4d62b59aca84e990cacaf5c5' +\ - '2b0930daa23de94ce87017ba2d84988d' +\ - 'dfc9c58db67aada613c2dd08457941a6' - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - counter = Counter.new(nbits=16, - prefix=unhexlify('f0f1f2f3f4f5f6f7f8f9fafbfcfd'), - initial_value=0xfeff) - key = unhexlify(key) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) + """Class exercising the CTR test vectors found in Section F.5 + of NIST SP 800-38A""" + + def test_aes_128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "874d6191b620e3261bef6864990db6ce" + + "9806f66b7970fdff8617187bb9fffdff" + + "5ae4df3edbd5d35e5b4f09020db03eab" + + "1e031dda2fbe03d1792170a0f3009cee" + ) + key = "2b7e151628aed2a6abf7158809cf4f3c" + counter = Counter.new( + nbits=16, + prefix=unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfd"), + initial_value=0xFEFF, + ) + + key = unhexlify(key) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_192(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "1abc932417521ca24f2b0459fe7e6e0b" + + "090339ec0aa6faefd5ccc2c6f4ce8e94" + + "1e36b26bd1ebc670d1bd1d665620abf7" + + "4f78a7f6d29809585a97daec58c6b050" + ) + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + counter = Counter.new( + nbits=16, + prefix=unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfd"), + initial_value=0xFEFF, + ) + + key = unhexlify(key) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_256(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "601ec313775789a5b7a7f504bbf3d228" + + "f443e3ca4d62b59aca84e990cacaf5c5" + + "2b0930daa23de94ce87017ba2d84988d" + + "dfc9c58db67aada613c2dd08457941a6" + ) + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + counter = Counter.new( + nbits=16, + prefix=unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfd"), + initial_value=0xFEFF, + ) + key = unhexlify(key) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) class RFC3686TestVectors(unittest.TestCase): - - # Each item is a test vector with: - # - plaintext - # - ciphertext - # - key (AES 128, 192 or 256 bits) - # - counter prefix (4 byte nonce + 8 byte nonce) - data = ( - ('53696e676c6520626c6f636b206d7367', - 'e4095d4fb7a7b3792d6175a3261311b8', - 'ae6852f8121067cc4bf7a5765577f39e', - '000000300000000000000000'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '5104a106168a72d9790d41ee8edad388eb2e1efc46da57c8fce630df9141be28', - '7e24067817fae0d743d6ce1f32539163', - '006cb6dbc0543b59da48d90b'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223', - 'c1cf48a89f2ffdd9cf4652e9efdb72d74540a42bde6d7836d59a5ceaaef3105325b2072f', - '7691be035e5020a8ac6e618529f9a0dc', - '00e0017b27777f3f4a1786f0'), - ('53696e676c6520626c6f636b206d7367', - '4b55384fe259c9c84e7935a003cbe928', - '16af5b145fc9f579c175f93e3bfb0eed863d06ccfdb78515', - '0000004836733c147d6d93cb'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '453243fc609b23327edfaafa7131cd9f8490701c5ad4a79cfc1fe0ff42f4fb00', - '7c5cb2401b3dc33c19e7340819e0f69c678c3db8e6f6a91a', - '0096b03b020c6eadc2cb500d'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223', - '96893fc55e5c722f540b7dd1ddf7e758d288bc95c69165884536c811662f2188abee0935', - '02bf391ee8ecb159b959617b0965279bf59b60a786d3e0fe', - '0007bdfd5cbd60278dcc0912'), - ('53696e676c6520626c6f636b206d7367', - '145ad01dbf824ec7560863dc71e3e0c0', - '776beff2851db06f4c8a0542c8696f6c6a81af1eec96b4d37fc1d689e6c1c104', - '00000060db5672c97aa8f0b2'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - 'f05e231b3894612c49ee000b804eb2a9b8306b508f839d6a5530831d9344af1c', - 'f6d66d6bd52d59bb0796365879eff886c66dd51a5b6a99744b50590c87a23884', - '00faac24c1585ef15a43d875'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223', - 'eb6c52821d0bbbf7ce7594462aca4faab407df866569fd07f48cc0b583d6071f1ec0e6b8', - 'ff7a617ce69148e4f1726e2f43581de2aa62d9f805532edff1eed687fb54153d', - '001cc5b751a51d70a1c11148') - ) - - bindata = [] - for tv in data: - bindata.append([unhexlify(x) for x in tv]) - - def runTest(self): - for pt, ct, key, prefix in self.bindata: - counter = Counter.new(32, prefix=prefix) - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - result = cipher.encrypt(pt) - self.assertEqual(hexlify(ct), hexlify(result)) + # Each item is a test vector with: + # - plaintext + # - ciphertext + # - key (AES 128, 192 or 256 bits) + # - counter prefix (4 byte nonce + 8 byte nonce) + data = ( + ( + "53696e676c6520626c6f636b206d7367", + "e4095d4fb7a7b3792d6175a3261311b8", + "ae6852f8121067cc4bf7a5765577f39e", + "000000300000000000000000", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "5104a106168a72d9790d41ee8edad388eb2e1efc46da57c8fce630df9141be28", + "7e24067817fae0d743d6ce1f32539163", + "006cb6dbc0543b59da48d90b", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", + "c1cf48a89f2ffdd9cf4652e9efdb72d74540a42bde6d7836d59a5ceaaef3105325b2072f", + "7691be035e5020a8ac6e618529f9a0dc", + "00e0017b27777f3f4a1786f0", + ), + ( + "53696e676c6520626c6f636b206d7367", + "4b55384fe259c9c84e7935a003cbe928", + "16af5b145fc9f579c175f93e3bfb0eed863d06ccfdb78515", + "0000004836733c147d6d93cb", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "453243fc609b23327edfaafa7131cd9f8490701c5ad4a79cfc1fe0ff42f4fb00", + "7c5cb2401b3dc33c19e7340819e0f69c678c3db8e6f6a91a", + "0096b03b020c6eadc2cb500d", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", + "96893fc55e5c722f540b7dd1ddf7e758d288bc95c69165884536c811662f2188abee0935", + "02bf391ee8ecb159b959617b0965279bf59b60a786d3e0fe", + "0007bdfd5cbd60278dcc0912", + ), + ( + "53696e676c6520626c6f636b206d7367", + "145ad01dbf824ec7560863dc71e3e0c0", + "776beff2851db06f4c8a0542c8696f6c6a81af1eec96b4d37fc1d689e6c1c104", + "00000060db5672c97aa8f0b2", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "f05e231b3894612c49ee000b804eb2a9b8306b508f839d6a5530831d9344af1c", + "f6d66d6bd52d59bb0796365879eff886c66dd51a5b6a99744b50590c87a23884", + "00faac24c1585ef15a43d875", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", + "eb6c52821d0bbbf7ce7594462aca4faab407df866569fd07f48cc0b583d6071f1ec0e6b8", + "ff7a617ce69148e4f1726e2f43581de2aa62d9f805532edff1eed687fb54153d", + "001cc5b751a51d70a1c11148", + ), + ) + + bindata = [] + for tv in data: + bindata.append([unhexlify(x) for x in tv]) + + def runTest(self): + for pt, ct, key, prefix in self.bindata: + counter = Counter.new(32, prefix=prefix) + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + result = cipher.encrypt(pt) + self.assertEqual(hexlify(ct), hexlify(result)) def get_tests(config={}): - tests = [] - tests += list_test_cases(CtrTests) - tests += list_test_cases(SP800TestVectors) - tests += [ RFC3686TestVectors() ] - return tests + tests = [] + tests += list_test_cases(CtrTests) + tests += list_test_cases(SP800TestVectors) + tests += [RFC3686TestVectors()] + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ChaCha20.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ChaCha20.py index 92c6f3cf..979e73a4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ChaCha20.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ChaCha20.py @@ -28,264 +28,262 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -import os -import re import unittest -from binascii import hexlify, unhexlify +from binascii import unhexlify -from Cryptodome.Util.py3compat import b, tobytes, bchr -from Cryptodome.Util.strxor import strxor_c +from Cryptodome.Util.py3compat import b, bchr from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Cipher import ChaCha20 class ChaCha20Test(unittest.TestCase): - - def test_new_positive(self): - cipher = ChaCha20.new(key=b("0")*32, nonce=b"0"*8) - self.assertEqual(cipher.nonce, b"0" * 8) - cipher = ChaCha20.new(key=b("0")*32, nonce=b"0"*12) - self.assertEqual(cipher.nonce, b"0" * 12) - - def test_new_negative(self): - new = ChaCha20.new - self.assertRaises(TypeError, new) - self.assertRaises(TypeError, new, nonce=b("0")) - self.assertRaises(ValueError, new, nonce=b("0")*8, key=b("0")) - self.assertRaises(ValueError, new, nonce=b("0"), key=b("0")*32) - - def test_default_nonce(self): - cipher1 = ChaCha20.new(key=bchr(1) * 32) - cipher2 = ChaCha20.new(key=bchr(1) * 32) - self.assertEqual(len(cipher1.nonce), 8) - self.assertNotEqual(cipher1.nonce, cipher2.nonce) - - def test_nonce(self): - key = b'A' * 32 - - nonce1 = b'P' * 8 - cipher1 = ChaCha20.new(key=key, nonce=nonce1) - self.assertEqual(nonce1, cipher1.nonce) - - nonce2 = b'Q' * 12 - cipher2 = ChaCha20.new(key=key, nonce=nonce2) - self.assertEqual(nonce2, cipher2.nonce) - - def test_eiter_encrypt_or_decrypt(self): - """Verify that a cipher cannot be used for both decrypting and encrypting""" - - c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) - c1.encrypt(b("8")) - self.assertRaises(TypeError, c1.decrypt, b("9")) - - c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) - c2.decrypt(b("8")) - self.assertRaises(TypeError, c2.encrypt, b("9")) - - def test_round_trip(self): - pt = b("A") * 1024 - c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) - c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) - ct = c1.encrypt(pt) - self.assertEqual(c2.decrypt(ct), pt) - - self.assertEqual(c1.encrypt(b("")), b("")) - self.assertEqual(c2.decrypt(b("")), b("")) - - def test_streaming(self): - """Verify that an arbitrary number of bytes can be encrypted/decrypted""" - from Cryptodome.Hash import SHA1 - - segments = (1, 3, 5, 7, 11, 17, 23) - total = sum(segments) - - pt = b("") - while len(pt) < total: - pt += SHA1.new(pt).digest() - - cipher1 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) - ct = cipher1.encrypt(pt) - - cipher2 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) - cipher3 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) - idx = 0 - for segment in segments: - self.assertEqual(cipher2.decrypt(ct[idx:idx+segment]), pt[idx:idx+segment]) - self.assertEqual(cipher3.encrypt(pt[idx:idx+segment]), ct[idx:idx+segment]) - idx += segment - - def test_seek(self): - cipher1 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8) - - offset = 64 * 900 + 7 - pt = b("1") * 64 - - cipher1.encrypt(b("0") * offset) - ct1 = cipher1.encrypt(pt) - - cipher2 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8) - cipher2.seek(offset) - ct2 = cipher2.encrypt(pt) - - self.assertEqual(ct1, ct2) - - def test_seek_tv(self): - # Test Vector #4, A.1 from - # http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 - key = bchr(0) + bchr(255) + bchr(0) * 30 - nonce = bchr(0) * 8 - cipher = ChaCha20.new(key=key, nonce=nonce) - cipher.seek(64 * 2) - expected_key_stream = unhexlify(b( - "72d54dfbf12ec44b362692df94137f32" - "8fea8da73990265ec1bbbea1ae9af0ca" - "13b25aa26cb4a648cb9b9d1be65b2c09" - "24a66c54d545ec1b7374f4872e99f096" - )) - ct = cipher.encrypt(bchr(0) * len(expected_key_stream)) - self.assertEqual(expected_key_stream, ct) - - def test_rfc7539(self): - # from https://tools.ietf.org/html/rfc7539 Annex A.1 - # Each item is: key, nonce, block #, plaintext, ciphertext - tvs = [ - # Test Vector #1 - ( - "00"*32, - "00"*12, - 0, - "00"*16*4, - "76b8e0ada0f13d90405d6ae55386bd28" - "bdd219b8a08ded1aa836efcc8b770dc7" - "da41597c5157488d7724e03fb8d84a37" - "6a43b8f41518a11cc387b669b2ee6586" - ), - # Test Vector #2 - ( - "00"*31 + "01", - "00"*11 + "02", - 1, - "416e79207375626d697373696f6e2074" - "6f20746865204945544620696e74656e" - "6465642062792074686520436f6e7472" - "696275746f7220666f72207075626c69" - "636174696f6e20617320616c6c206f72" - "2070617274206f6620616e2049455446" - "20496e7465726e65742d447261667420" - "6f722052464320616e6420616e792073" - "746174656d656e74206d616465207769" - "7468696e2074686520636f6e74657874" - "206f6620616e20494554462061637469" - "7669747920697320636f6e7369646572" - "656420616e20224945544620436f6e74" - "7269627574696f6e222e205375636820" - "73746174656d656e747320696e636c75" - "6465206f72616c2073746174656d656e" - "747320696e2049455446207365737369" - "6f6e732c2061732077656c6c20617320" - "7772697474656e20616e6420656c6563" - "74726f6e696320636f6d6d756e696361" - "74696f6e73206d61646520617420616e" - "792074696d65206f7220706c6163652c" - "20776869636820617265206164647265" - "7373656420746f", - "a3fbf07df3fa2fde4f376ca23e827370" - "41605d9f4f4f57bd8cff2c1d4b7955ec" - "2a97948bd3722915c8f3d337f7d37005" - "0e9e96d647b7c39f56e031ca5eb6250d" - "4042e02785ececfa4b4bb5e8ead0440e" - "20b6e8db09d881a7c6132f420e527950" - "42bdfa7773d8a9051447b3291ce1411c" - "680465552aa6c405b7764d5e87bea85a" - "d00f8449ed8f72d0d662ab052691ca66" - "424bc86d2df80ea41f43abf937d3259d" - "c4b2d0dfb48a6c9139ddd7f76966e928" - "e635553ba76c5c879d7b35d49eb2e62b" - "0871cdac638939e25e8a1e0ef9d5280f" - "a8ca328b351c3c765989cbcf3daa8b6c" - "cc3aaf9f3979c92b3720fc88dc95ed84" - "a1be059c6499b9fda236e7e818b04b0b" - "c39c1e876b193bfe5569753f88128cc0" - "8aaa9b63d1a16f80ef2554d7189c411f" - "5869ca52c5b83fa36ff216b9c1d30062" - "bebcfd2dc5bce0911934fda79a86f6e6" - "98ced759c3ff9b6477338f3da4f9cd85" - "14ea9982ccafb341b2384dd902f3d1ab" - "7ac61dd29c6f21ba5b862f3730e37cfd" - "c4fd806c22f221" - ), - # Test Vector #3 - ( - "1c9240a5eb55d38af333888604f6b5f0" - "473917c1402b80099dca5cbc207075c0", - "00"*11 + "02", - 42, - "2754776173206272696c6c69672c2061" - "6e642074686520736c6974687920746f" - "7665730a446964206779726520616e64" - "2067696d626c6520696e207468652077" - "6162653a0a416c6c206d696d73792077" - "6572652074686520626f726f676f7665" - "732c0a416e6420746865206d6f6d6520" - "7261746873206f757467726162652e", - "62e6347f95ed87a45ffae7426f27a1df" - "5fb69110044c0d73118effa95b01e5cf" - "166d3df2d721caf9b21e5fb14c616871" - "fd84c54f9d65b283196c7fe4f60553eb" - "f39c6402c42234e32a356b3e764312a6" - "1a5532055716ead6962568f87d3f3f77" - "04c6a8d1bcd1bf4d50d6154b6da731b1" - "87b58dfd728afa36757a797ac188d1" - ) - ] - - for tv in tvs: - key = unhexlify(tv[0]) - nonce = unhexlify(tv[1]) - offset = tv[2] * 64 - pt = unhexlify(tv[3]) - ct_expect = unhexlify(tv[4]) - - cipher = ChaCha20.new(key=key, nonce=nonce) - if offset != 0: - cipher.seek(offset) - ct = cipher.encrypt(pt) - assert(ct == ct_expect) + def test_new_positive(self): + cipher = ChaCha20.new(key=b("0") * 32, nonce=b"0" * 8) + self.assertEqual(cipher.nonce, b"0" * 8) + cipher = ChaCha20.new(key=b("0") * 32, nonce=b"0" * 12) + self.assertEqual(cipher.nonce, b"0" * 12) + + def test_new_negative(self): + new = ChaCha20.new + self.assertRaises(TypeError, new) + self.assertRaises(TypeError, new, nonce=b("0")) + self.assertRaises(ValueError, new, nonce=b("0") * 8, key=b("0")) + self.assertRaises(ValueError, new, nonce=b("0"), key=b("0") * 32) + + def test_default_nonce(self): + cipher1 = ChaCha20.new(key=bchr(1) * 32) + cipher2 = ChaCha20.new(key=bchr(1) * 32) + self.assertEqual(len(cipher1.nonce), 8) + self.assertNotEqual(cipher1.nonce, cipher2.nonce) + + def test_nonce(self): + key = b"A" * 32 + + nonce1 = b"P" * 8 + cipher1 = ChaCha20.new(key=key, nonce=nonce1) + self.assertEqual(nonce1, cipher1.nonce) + + nonce2 = b"Q" * 12 + cipher2 = ChaCha20.new(key=key, nonce=nonce2) + self.assertEqual(nonce2, cipher2.nonce) + + def test_eiter_encrypt_or_decrypt(self): + """Verify that a cipher cannot be used for both decrypting and encrypting""" + + c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) + c1.encrypt(b("8")) + self.assertRaises(TypeError, c1.decrypt, b("9")) + + c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) + c2.decrypt(b("8")) + self.assertRaises(TypeError, c2.encrypt, b("9")) + + def test_round_trip(self): + pt = b("A") * 1024 + c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) + c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) + ct = c1.encrypt(pt) + self.assertEqual(c2.decrypt(ct), pt) + + self.assertEqual(c1.encrypt(b("")), b("")) + self.assertEqual(c2.decrypt(b("")), b("")) + + def test_streaming(self): + """Verify that an arbitrary number of bytes can be encrypted/decrypted""" + from Cryptodome.Hash import SHA1 + + segments = (1, 3, 5, 7, 11, 17, 23) + total = sum(segments) + + pt = b("") + while len(pt) < total: + pt += SHA1.new(pt).digest() + + cipher1 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) + ct = cipher1.encrypt(pt) + + cipher2 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) + cipher3 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) + idx = 0 + for segment in segments: + self.assertEqual(cipher2.decrypt(ct[idx : idx + segment]), pt[idx : idx + segment]) + self.assertEqual(cipher3.encrypt(pt[idx : idx + segment]), ct[idx : idx + segment]) + idx += segment + + def test_seek(self): + cipher1 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8) + + offset = 64 * 900 + 7 + pt = b("1") * 64 + + cipher1.encrypt(b("0") * offset) + ct1 = cipher1.encrypt(pt) + + cipher2 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8) + cipher2.seek(offset) + ct2 = cipher2.encrypt(pt) + + self.assertEqual(ct1, ct2) + + def test_seek_tv(self): + # Test Vector #4, A.1 from + # http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + key = bchr(0) + bchr(255) + bchr(0) * 30 + nonce = bchr(0) * 8 + cipher = ChaCha20.new(key=key, nonce=nonce) + cipher.seek(64 * 2) + expected_key_stream = unhexlify( + b( + "72d54dfbf12ec44b362692df94137f32" + "8fea8da73990265ec1bbbea1ae9af0ca" + "13b25aa26cb4a648cb9b9d1be65b2c09" + "24a66c54d545ec1b7374f4872e99f096", + ), + ) + ct = cipher.encrypt(bchr(0) * len(expected_key_stream)) + self.assertEqual(expected_key_stream, ct) + + def test_rfc7539(self): + # from https://tools.ietf.org/html/rfc7539 Annex A.1 + # Each item is: key, nonce, block #, plaintext, ciphertext + tvs = [ + # Test Vector #1 + ( + "00" * 32, + "00" * 12, + 0, + "00" * 16 * 4, + "76b8e0ada0f13d90405d6ae55386bd28" + "bdd219b8a08ded1aa836efcc8b770dc7" + "da41597c5157488d7724e03fb8d84a37" + "6a43b8f41518a11cc387b669b2ee6586", + ), + # Test Vector #2 + ( + "00" * 31 + "01", + "00" * 11 + "02", + 1, + "416e79207375626d697373696f6e2074" + "6f20746865204945544620696e74656e" + "6465642062792074686520436f6e7472" + "696275746f7220666f72207075626c69" + "636174696f6e20617320616c6c206f72" + "2070617274206f6620616e2049455446" + "20496e7465726e65742d447261667420" + "6f722052464320616e6420616e792073" + "746174656d656e74206d616465207769" + "7468696e2074686520636f6e74657874" + "206f6620616e20494554462061637469" + "7669747920697320636f6e7369646572" + "656420616e20224945544620436f6e74" + "7269627574696f6e222e205375636820" + "73746174656d656e747320696e636c75" + "6465206f72616c2073746174656d656e" + "747320696e2049455446207365737369" + "6f6e732c2061732077656c6c20617320" + "7772697474656e20616e6420656c6563" + "74726f6e696320636f6d6d756e696361" + "74696f6e73206d61646520617420616e" + "792074696d65206f7220706c6163652c" + "20776869636820617265206164647265" + "7373656420746f", + "a3fbf07df3fa2fde4f376ca23e827370" + "41605d9f4f4f57bd8cff2c1d4b7955ec" + "2a97948bd3722915c8f3d337f7d37005" + "0e9e96d647b7c39f56e031ca5eb6250d" + "4042e02785ececfa4b4bb5e8ead0440e" + "20b6e8db09d881a7c6132f420e527950" + "42bdfa7773d8a9051447b3291ce1411c" + "680465552aa6c405b7764d5e87bea85a" + "d00f8449ed8f72d0d662ab052691ca66" + "424bc86d2df80ea41f43abf937d3259d" + "c4b2d0dfb48a6c9139ddd7f76966e928" + "e635553ba76c5c879d7b35d49eb2e62b" + "0871cdac638939e25e8a1e0ef9d5280f" + "a8ca328b351c3c765989cbcf3daa8b6c" + "cc3aaf9f3979c92b3720fc88dc95ed84" + "a1be059c6499b9fda236e7e818b04b0b" + "c39c1e876b193bfe5569753f88128cc0" + "8aaa9b63d1a16f80ef2554d7189c411f" + "5869ca52c5b83fa36ff216b9c1d30062" + "bebcfd2dc5bce0911934fda79a86f6e6" + "98ced759c3ff9b6477338f3da4f9cd85" + "14ea9982ccafb341b2384dd902f3d1ab" + "7ac61dd29c6f21ba5b862f3730e37cfd" + "c4fd806c22f221", + ), + # Test Vector #3 + ( + "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "00" * 11 + "02", + 42, + "2754776173206272696c6c69672c2061" + "6e642074686520736c6974687920746f" + "7665730a446964206779726520616e64" + "2067696d626c6520696e207468652077" + "6162653a0a416c6c206d696d73792077" + "6572652074686520626f726f676f7665" + "732c0a416e6420746865206d6f6d6520" + "7261746873206f757467726162652e", + "62e6347f95ed87a45ffae7426f27a1df" + "5fb69110044c0d73118effa95b01e5cf" + "166d3df2d721caf9b21e5fb14c616871" + "fd84c54f9d65b283196c7fe4f60553eb" + "f39c6402c42234e32a356b3e764312a6" + "1a5532055716ead6962568f87d3f3f77" + "04c6a8d1bcd1bf4d50d6154b6da731b1" + "87b58dfd728afa36757a797ac188d1", + ), + ] + + for tv in tvs: + key = unhexlify(tv[0]) + nonce = unhexlify(tv[1]) + offset = tv[2] * 64 + pt = unhexlify(tv[3]) + ct_expect = unhexlify(tv[4]) + + cipher = ChaCha20.new(key=key, nonce=nonce) + if offset != 0: + cipher.seek(offset) + ct = cipher.encrypt(pt) + assert ct == ct_expect class XChaCha20Test(unittest.TestCase): + # From https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - # From https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - - def test_hchacha20(self): - # Section 2.2.1 + def test_hchacha20(self): + # Section 2.2.1 - from Cryptodome.Cipher.ChaCha20 import _HChaCha20 + from Cryptodome.Cipher.ChaCha20 import _HChaCha20 - key = b"00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f" - key = unhexlify(key.replace(b":", b"")) + key = ( + b"00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f" + ) + key = unhexlify(key.replace(b":", b"")) - nonce = b"00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27" - nonce = unhexlify(nonce.replace(b":", b"")) + nonce = b"00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27" + nonce = unhexlify(nonce.replace(b":", b"")) - subkey = _HChaCha20(key, nonce) + subkey = _HChaCha20(key, nonce) - expected = b"82413b42 27b27bfe d30e4250 8a877d73 a0f9e4d5 8a74a853 c12ec413 26d3ecdc" - expected = unhexlify(expected.replace(b" ", b"")) + expected = b"82413b42 27b27bfe d30e4250 8a877d73 a0f9e4d5 8a74a853 c12ec413 26d3ecdc" + expected = unhexlify(expected.replace(b" ", b"")) - self.assertEqual(subkey, expected) + self.assertEqual(subkey, expected) - def test_nonce(self): - key = b'A' * 32 - nonce = b'P' * 24 - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertEqual(nonce, cipher.nonce) + def test_nonce(self): + key = b"A" * 32 + nonce = b"P" * 24 + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertEqual(nonce, cipher.nonce) - def test_encrypt(self): - # Section A.3.2 + def test_encrypt(self): + # Section A.3.2 - pt = b""" + pt = b""" 5468652064686f6c65202870726f6e6f756e6365642022646f6c652229206973 20616c736f206b6e6f776e2061732074686520417369617469632077696c6420 646f672c2072656420646f672c20616e642077686973746c696e6720646f672e @@ -296,12 +294,12 @@ def test_encrypt(self): 736966696564207769746820776f6c7665732c20636f796f7465732c206a6163 6b616c732c20616e6420666f78657320696e20746865207461786f6e6f6d6963 2066616d696c792043616e696461652e""" - pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b"")) + pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b"")) - key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") - iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555658") + key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") + iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555658") - ct = b""" + ct = b""" 7d0a2e6b7f7c65a236542630294e063b7ab9b555a5d5149aa21e4ae1e4fbce87 ecc8e08a8b5e350abe622b2ffa617b202cfad72032a3037e76ffdcdc4376ee05 3a190d7e46ca1de04144850381b9cb29f051915386b8a710b8ac4d027b8b050f @@ -312,218 +310,220 @@ def test_encrypt(self): c0b63615cdad0480680f16515a7ace9d39236464328a37743ffc28f4ddb324f4 d0f5bbdc270c65b1749a6efff1fbaa09536175ccd29fb9e6057b307320d31683 8a9c71f70b5b5907a66f7ea49aadc409""" - ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b"")) + ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b"")) - cipher = ChaCha20.new(key=key, nonce=iv) - cipher.seek(64) # Counter = 1 - ct_test = cipher.encrypt(pt) - self.assertEqual(ct, ct_test) + cipher = ChaCha20.new(key=key, nonce=iv) + cipher.seek(64) # Counter = 1 + ct_test = cipher.encrypt(pt) + self.assertEqual(ct, ct_test) class ByteArrayTest(unittest.TestCase): - """Verify we can encrypt or decrypt bytearrays""" + """Verify we can encrypt or decrypt bytearrays""" - def runTest(self): + def runTest(self): + data = b"0123" + key = b"9" * 32 + nonce = b"t" * 8 - data = b"0123" - key = b"9" * 32 - nonce = b"t" * 8 + # Encryption + data_ba = bytearray(data) + key_ba = bytearray(key) + nonce_ba = bytearray(nonce) - # Encryption - data_ba = bytearray(data) - key_ba = bytearray(key) - nonce_ba = bytearray(nonce) + cipher1 = ChaCha20.new(key=key, nonce=nonce) + ct = cipher1.encrypt(data) - cipher1 = ChaCha20.new(key=key, nonce=nonce) - ct = cipher1.encrypt(data) + cipher2 = ChaCha20.new(key=key_ba, nonce=nonce_ba) + key_ba[:1] = b"\xff" + nonce_ba[:1] = b"\xff" + ct_test = cipher2.encrypt(data_ba) - cipher2 = ChaCha20.new(key=key_ba, nonce=nonce_ba) - key_ba[:1] = b'\xFF' - nonce_ba[:1] = b'\xFF' - ct_test = cipher2.encrypt(data_ba) + self.assertEqual(ct, ct_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) - self.assertEqual(ct, ct_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) + # Decryption + key_ba = bytearray(key) + nonce_ba = bytearray(nonce) + ct_ba = bytearray(ct) - # Decryption - key_ba = bytearray(key) - nonce_ba = bytearray(nonce) - ct_ba = bytearray(ct) + cipher3 = ChaCha20.new(key=key_ba, nonce=nonce_ba) + key_ba[:1] = b"\xff" + nonce_ba[:1] = b"\xff" + pt_test = cipher3.decrypt(ct_ba) - cipher3 = ChaCha20.new(key=key_ba, nonce=nonce_ba) - key_ba[:1] = b'\xFF' - nonce_ba[:1] = b'\xFF' - pt_test = cipher3.decrypt(ct_ba) - - self.assertEqual(data, pt_test) + self.assertEqual(data, pt_test) class MemoryviewTest(unittest.TestCase): - """Verify we can encrypt or decrypt bytearrays""" - - def runTest(self): + """Verify we can encrypt or decrypt bytearrays""" - data = b"0123" - key = b"9" * 32 - nonce = b"t" * 8 + def runTest(self): + data = b"0123" + key = b"9" * 32 + nonce = b"t" * 8 - # Encryption - data_mv = memoryview(bytearray(data)) - key_mv = memoryview(bytearray(key)) - nonce_mv = memoryview(bytearray(nonce)) + # Encryption + data_mv = memoryview(bytearray(data)) + key_mv = memoryview(bytearray(key)) + nonce_mv = memoryview(bytearray(nonce)) - cipher1 = ChaCha20.new(key=key, nonce=nonce) - ct = cipher1.encrypt(data) + cipher1 = ChaCha20.new(key=key, nonce=nonce) + ct = cipher1.encrypt(data) - cipher2 = ChaCha20.new(key=key_mv, nonce=nonce_mv) - key_mv[:1] = b'\xFF' - nonce_mv[:1] = b'\xFF' - ct_test = cipher2.encrypt(data_mv) + cipher2 = ChaCha20.new(key=key_mv, nonce=nonce_mv) + key_mv[:1] = b"\xff" + nonce_mv[:1] = b"\xff" + ct_test = cipher2.encrypt(data_mv) - self.assertEqual(ct, ct_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) + self.assertEqual(ct, ct_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) - # Decryption - key_mv = memoryview(bytearray(key)) - nonce_mv = memoryview(bytearray(nonce)) - ct_mv = memoryview(bytearray(ct)) + # Decryption + key_mv = memoryview(bytearray(key)) + nonce_mv = memoryview(bytearray(nonce)) + ct_mv = memoryview(bytearray(ct)) - cipher3 = ChaCha20.new(key=key_mv, nonce=nonce_mv) - key_mv[:1] = b'\xFF' - nonce_mv[:1] = b'\xFF' - pt_test = cipher3.decrypt(ct_mv) + cipher3 = ChaCha20.new(key=key_mv, nonce=nonce_mv) + key_mv[:1] = b"\xff" + nonce_mv[:1] = b"\xff" + pt_test = cipher3.decrypt(ct_mv) - self.assertEqual(data, pt_test) + self.assertEqual(data, pt_test) class ChaCha20_AGL_NIR(unittest.TestCase): - - # From http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 - # and http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 - tv = [ - ( "00" * 32, - "00" * 8, - "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc" - "8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11c" - "c387b669b2ee6586" - "9f07e7be5551387a98ba977c732d080d" - "cb0f29a048e3656912c6533e32ee7aed" - "29b721769ce64e43d57133b074d839d5" - "31ed1f28510afb45ace10a1f4b794d6f" - ), - ( "00" * 31 + "01", - "00" * 8, - "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952" - "ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea81" - "7e9ad275ae546963" - "3aeb5224ecf849929b9d828db1ced4dd" - "832025e8018b8160b82284f3c949aa5a" - "8eca00bbb4a73bdad192b5c42f73f2fd" - "4e273644c8b36125a64addeb006c13a0" - ), - ( "00" * 32, - "00" * 7 + "01", - "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df1" - "37821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e" - "445f41e3" - ), - ( "00" * 32, - "01" + "00" * 7, - "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd1" - "38e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d" - "6bbdb0041b2f586b" - ), - ( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b" - "1c1d1e1f", - "0001020304050607", - "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56" - "f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f1" - "5916155c2be8241a38008b9a26bc35941e2444177c8ade6689de9526" - "4986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e" - "09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a4750" - "32b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c5" - "07b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f7" - "6dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2" - "ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab7" - "8fab78c9" - ), - ( "00" * 32, - "00" * 7 + "02", - "c2c64d378cd536374ae204b9ef933fcd" - "1a8b2288b3dfa49672ab765b54ee27c7" - "8a970e0e955c14f3a88e741b97c286f7" - "5f8fc299e8148362fa198a39531bed6d" - ), - ] - - def runTest(self): - for (key, nonce, stream) in self.tv: - c = ChaCha20.new(key=unhexlify(b(key)), nonce=unhexlify(b(nonce))) - ct = unhexlify(b(stream)) - pt = b("\x00") * len(ct) - self.assertEqual(c.encrypt(pt), ct) + # From http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 + # and http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + tv = [ + ( + "00" * 32, + "00" * 8, + "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc" + "8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11c" + "c387b669b2ee6586" + "9f07e7be5551387a98ba977c732d080d" + "cb0f29a048e3656912c6533e32ee7aed" + "29b721769ce64e43d57133b074d839d5" + "31ed1f28510afb45ace10a1f4b794d6f", + ), + ( + "00" * 31 + "01", + "00" * 8, + "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952" + "ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea81" + "7e9ad275ae546963" + "3aeb5224ecf849929b9d828db1ced4dd" + "832025e8018b8160b82284f3c949aa5a" + "8eca00bbb4a73bdad192b5c42f73f2fd" + "4e273644c8b36125a64addeb006c13a0", + ), + ( + "00" * 32, + "00" * 7 + "01", + "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df1" + "37821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e" + "445f41e3", + ), + ( + "00" * 32, + "01" + "00" * 7, + "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd1" + "38e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d" + "6bbdb0041b2f586b", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "0001020304050607", + "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56" + "f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f1" + "5916155c2be8241a38008b9a26bc35941e2444177c8ade6689de9526" + "4986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e" + "09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a4750" + "32b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c5" + "07b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f7" + "6dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2" + "ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab7" + "8fab78c9", + ), + ( + "00" * 32, + "00" * 7 + "02", + "c2c64d378cd536374ae204b9ef933fcd" + "1a8b2288b3dfa49672ab765b54ee27c7" + "8a970e0e955c14f3a88e741b97c286f7" + "5f8fc299e8148362fa198a39531bed6d", + ), + ] + + def runTest(self): + for key, nonce, stream in self.tv: + c = ChaCha20.new(key=unhexlify(b(key)), nonce=unhexlify(b(nonce))) + ct = unhexlify(b(stream)) + pt = b("\x00") * len(ct) + self.assertEqual(c.encrypt(pt), ct) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter - - key = b'4' * 32 - nonce = b'5' * 8 - cipher = ChaCha20.new(key=key, nonce=nonce) + key = b"4" * 32 + nonce = b"5" * 8 + cipher = ChaCha20.new(key=key, nonce=nonce) - pt = b'5' * 300 - ct = cipher.encrypt(pt) + pt = b"5" * 300 + ct = cipher.encrypt(pt) - output = bytearray(len(pt)) - cipher = ChaCha20.new(key=key, nonce=nonce) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) + output = bytearray(len(pt)) + cipher = ChaCha20.new(key=key, nonce=nonce) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - cipher = ChaCha20.new(key=key, nonce=nonce) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + cipher = ChaCha20.new(key=key, nonce=nonce) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = memoryview(bytearray(len(pt))) - cipher = ChaCha20.new(key=key, nonce=nonce) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + output = memoryview(bytearray(len(pt))) + cipher = ChaCha20.new(key=key, nonce=nonce) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - cipher = ChaCha20.new(key=key, nonce=nonce) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher = ChaCha20.new(key=key, nonce=nonce) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*len(pt)) + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * len(pt)) - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*len(pt)) + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * len(pt)) - shorter_output = bytearray(len(pt) - 1) + shorter_output = bytearray(len(pt) - 1) - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - tests = [] - tests += list_test_cases(ChaCha20Test) - tests += list_test_cases(XChaCha20Test) - tests.append(ChaCha20_AGL_NIR()) - tests.append(ByteArrayTest()) - tests.append(MemoryviewTest()) - tests.append(TestOutput()) + tests = [] + tests += list_test_cases(ChaCha20Test) + tests += list_test_cases(XChaCha20Test) + tests.append(ChaCha20_AGL_NIR()) + tests.append(ByteArrayTest()) + tests.append(MemoryviewTest()) + tests.append(TestOutput()) + + return tests - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ChaCha20_Poly1305.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ChaCha20_Poly1305.py index 495028ab..c9c145c0 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ChaCha20_Poly1305.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_ChaCha20_Poly1305.py @@ -41,736 +41,868 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class ChaCha20Poly1305Tests(unittest.TestCase): - - key_256 = get_tag_random("key_256", 32) - nonce_96 = get_tag_random("nonce_96", 12) - data_128 = get_tag_random("data_128", 16) - - def test_loopback(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # Nonce can only be 8 or 12 bytes - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=b'H' * 8) - self.assertEqual(len(cipher.nonce), 8) - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=b'H' * 12) - self.assertEqual(len(cipher.nonce), 12) - - # If not passed, the nonce is created randomly - cipher = ChaCha20_Poly1305.new(key=self.key_256) - nonce1 = cipher.nonce - cipher = ChaCha20_Poly1305.new(key=self.key_256) - nonce2 = cipher.nonce - self.assertEqual(len(nonce1), 12) - self.assertNotEqual(nonce1, nonce2) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data_128)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, - ChaCha20_Poly1305.new, - key=self.key_256, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce can only be 8 or 12 bytes long - self.assertRaises(ValueError, - ChaCha20_Poly1305.new, - key=self.key_256, - nonce=b'0' * 7) - self.assertRaises(ValueError, - ChaCha20_Poly1305.new, - key=self.key_256, - nonce=b'') - - def test_block_size(self): - # Not based on block ciphers - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertFalse(hasattr(cipher, 'block_size')) - - def test_nonce_attribute(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 12 bytes long nonce is randomly generated - nonce1 = ChaCha20_Poly1305.new(key=self.key_256).nonce - nonce2 = ChaCha20_Poly1305.new(key=self.key_256).nonce - self.assertEqual(len(nonce1), 12) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, - ChaCha20_Poly1305.new, - key=self.key_256, - param=9) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data_128) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data_128) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b"" - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b"" - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_256) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data_128) - data_ba = bytearray(self.data_128) - - cipher1 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) - tag = cipher1.digest() - - cipher2 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - key_ba[:3] = b'\xFF\xFF\xFF' - nonce_ba[:3] = b'\xFF\xFF\xFF' - cipher2.update(header_ba) - header_ba[:3] = b'\xFF\xFF\xFF' - ct_test = cipher2.encrypt(data_ba) - data_ba[:3] = b'\x99\x99\x99' - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_256) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data_128) - ct_ba = bytearray(ct) - tag_ba = bytearray(tag) - del data_ba - - cipher3 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - key_ba[:3] = b'\xFF\xFF\xFF' - nonce_ba[:3] = b'\xFF\xFF\xFF' - cipher3.update(header_ba) - header_ba[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt(ct_ba) - ct_ba[:3] = b'\xFF\xFF\xFF' - cipher3.verify(tag_ba) - - self.assertEqual(pt_test, self.data_128) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_256)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data_128)) - data_mv = memoryview(bytearray(self.data_128)) - - cipher1 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) - tag = cipher1.digest() - - cipher2 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - key_mv[:3] = b'\xFF\xFF\xFF' - nonce_mv[:3] = b'\xFF\xFF\xFF' - cipher2.update(header_mv) - header_mv[:3] = b'\xFF\xFF\xFF' - ct_test = cipher2.encrypt(data_mv) - data_mv[:3] = b'\x99\x99\x99' - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_256)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data_128)) - ct_mv = memoryview(bytearray(ct)) - tag_mv = memoryview(bytearray(tag)) - del data_mv - - cipher3 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - key_mv[:3] = b'\xFF\xFF\xFF' - nonce_mv[:3] = b'\xFF\xFF\xFF' - cipher3.update(header_mv) - header_mv[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt(ct_mv) - ct_mv[:3] = b'\x99\x99\x99' - cipher3.verify(tag_mv) - - self.assertEqual(pt_test, self.data_128) + key_256 = get_tag_random("key_256", 32) + nonce_96 = get_tag_random("nonce_96", 12) + data_128 = get_tag_random("data_128", 16) + + def test_loopback(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # Nonce can only be 8 or 12 bytes + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=b"H" * 8, + ) + self.assertEqual(len(cipher.nonce), 8) + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=b"H" * 12, + ) + self.assertEqual(len(cipher.nonce), 12) + + # If not passed, the nonce is created randomly + cipher = ChaCha20_Poly1305.new(key=self.key_256) + nonce1 = cipher.nonce + cipher = ChaCha20_Poly1305.new(key=self.key_256) + nonce2 = cipher.nonce + self.assertEqual(len(nonce1), 12) + self.assertNotEqual(nonce1, nonce2) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data_128) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertEqual(ct, cipher.encrypt(self.data_128)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + ChaCha20_Poly1305.new, + key=self.key_256, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce can only be 8 or 12 bytes long + self.assertRaises( + ValueError, + ChaCha20_Poly1305.new, + key=self.key_256, + nonce=b"0" * 7, + ) + self.assertRaises( + ValueError, + ChaCha20_Poly1305.new, + key=self.key_256, + nonce=b"", + ) + + def test_block_size(self): + # Not based on block ciphers + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertFalse(hasattr(cipher, "block_size")) + + def test_nonce_attribute(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 12 bytes long nonce is randomly generated + nonce1 = ChaCha20_Poly1305.new(key=self.key_256).nonce + nonce2 = ChaCha20_Poly1305.new(key=self.key_256).nonce + self.assertEqual(len(nonce1), 12) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + ChaCha20_Poly1305.new, + key=self.key_256, + param=9, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + _, mac = cipher.encrypt_and_digest(self.data_128) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + ct, mac = cipher.encrypt_and_digest(self.data_128) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.hexverify(mac_hex) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b"" + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b"" + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_256) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data_128) + data_ba = bytearray(self.data_128) + + cipher1 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher1.update(self.data_128) + ct = cipher1.encrypt(self.data_128) + tag = cipher1.digest() + + cipher2 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + data_ba[:3] = b"\x99\x99\x99" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_256) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data_128) + ct_ba = bytearray(ct) + tag_ba = bytearray(tag) + del data_ba + + cipher3 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher3.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt(ct_ba) + ct_ba[:3] = b"\xff\xff\xff" + cipher3.verify(tag_ba) + + self.assertEqual(pt_test, self.data_128) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_256)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data_128)) + data_mv = memoryview(bytearray(self.data_128)) + + cipher1 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher1.update(self.data_128) + ct = cipher1.encrypt(self.data_128) + tag = cipher1.digest() + + cipher2 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + data_mv[:3] = b"\x99\x99\x99" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_256)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data_128)) + ct_mv = memoryview(bytearray(ct)) + tag_mv = memoryview(bytearray(tag)) + del data_mv + + cipher3 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher3.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt(ct_mv) + ct_mv[:3] = b"\x99\x99\x99" + cipher3.verify(tag_mv) + + self.assertEqual(pt_test, self.data_128) class XChaCha20Poly1305Tests(unittest.TestCase): - - def test_nonce(self): - # Nonce can only be 24 bytes - cipher = ChaCha20_Poly1305.new(key=b'Y' * 32, - nonce=b'H' * 24) - self.assertEqual(len(cipher.nonce), 24) - self.assertEqual(cipher.nonce, b'H' * 24) - - def test_encrypt(self): - # From https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - # Section A.3.1 - - pt = b""" + def test_nonce(self): + # Nonce can only be 24 bytes + cipher = ChaCha20_Poly1305.new( + key=b"Y" * 32, + nonce=b"H" * 24, + ) + self.assertEqual(len(cipher.nonce), 24) + self.assertEqual(cipher.nonce, b"H" * 24) + + def test_encrypt(self): + # From https://tools.ietf.org/html/draft-arciszewski-xchacha-03 + # Section A.3.1 + + pt = b""" 4c616469657320616e642047656e746c656d656e206f662074686520636c6173 73206f66202739393a204966204920636f756c64206f6666657220796f75206f 6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73 637265656e20776f756c642062652069742e""" - pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b"")) + pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b"")) - aad = unhexlify(b"50515253c0c1c2c3c4c5c6c7") - key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") - iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555657") + aad = unhexlify(b"50515253c0c1c2c3c4c5c6c7") + key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") + iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555657") - ct = b""" + ct = b""" bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb 731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b452 2f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff9 21f9664c97637da9768812f615c68b13b52e""" - ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b"")) + ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b"")) - tag = unhexlify(b"c0875924c1c7987947deafd8780acf49") + tag = unhexlify(b"c0875924c1c7987947deafd8780acf49") - cipher = ChaCha20_Poly1305.new(key=key, nonce=iv) - cipher.update(aad) - ct_test, tag_test = cipher.encrypt_and_digest(pt) + cipher = ChaCha20_Poly1305.new(key=key, nonce=iv) + cipher.update(aad) + ct_test, tag_test = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) - cipher = ChaCha20_Poly1305.new(key=key, nonce=iv) - cipher.update(aad) - cipher.decrypt_and_verify(ct, tag) + cipher = ChaCha20_Poly1305.new(key=key, nonce=iv) + cipher.update(aad) + cipher.decrypt_and_verify(ct, tag) class ChaCha20Poly1305FSMTests(unittest.TestCase): - - key_256 = get_tag_random("key_256", 32) - nonce_96 = get_tag_random("nonce_96", 12) - data_128 = get_tag_random("data_128", 16) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->DIGEST - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - # Verify path INIT->DECRYPT->VERIFY - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - # Verify path INIT->UPDATE->ENCRYPT->DIGEST - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->VERIFY - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - mac = cipher.digest() - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - for method_name in "encrypt", "decrypt": - for auth_data in (None, b"333", self.data_128, - self.data_128 + b"3"): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data_128) - method(self.data_128) - method(self.data_128) - method(self.data_128) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - ct, mac = cipher.encrypt_and_digest(self.data_128) - - # decrypt_and_verify - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data_128, pt) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data_128) - getattr(cipher, method1_name)(self.data_128) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data_128) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.encrypt(self.data_128) - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data_128) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) + key_256 = get_tag_random("key_256", 32) + nonce_96 = get_tag_random("nonce_96", 12) + data_128 = get_tag_random("data_128", 16) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->DIGEST + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + # Verify path INIT->DECRYPT->VERIFY + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + # Verify path INIT->UPDATE->ENCRYPT->DIGEST + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->VERIFY + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + mac = cipher.digest() + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b"333", + self.data_128, + self.data_128 + b"3", + ): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data_128) + method(self.data_128) + method(self.data_128) + method(self.data_128) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + ct, mac = cipher.encrypt_and_digest(self.data_128) + + # decrypt_and_verify + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data_128, pt) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data_128) + getattr(cipher, method1_name)(self.data_128) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data_128, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.encrypt(self.data_128) + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.encrypt_and_digest(self.data_128) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) def compact(x): - return unhexlify(x.replace(" ", "").replace(":", "")) + return unhexlify(x.replace(" ", "").replace(":", "")) class TestVectorsRFC(unittest.TestCase): - """Test cases from RFC7539""" - - # AAD, PT, CT, MAC, KEY, NONCE - test_vectors_hex = [ - ( '50 51 52 53 c0 c1 c2 c3 c4 c5 c6 c7', - '4c 61 64 69 65 73 20 61 6e 64 20 47 65 6e 74 6c' - '65 6d 65 6e 20 6f 66 20 74 68 65 20 63 6c 61 73' - '73 20 6f 66 20 27 39 39 3a 20 49 66 20 49 20 63' - '6f 75 6c 64 20 6f 66 66 65 72 20 79 6f 75 20 6f' - '6e 6c 79 20 6f 6e 65 20 74 69 70 20 66 6f 72 20' - '74 68 65 20 66 75 74 75 72 65 2c 20 73 75 6e 73' - '63 72 65 65 6e 20 77 6f 75 6c 64 20 62 65 20 69' - '74 2e', - 'd3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2' - 'a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6' - '3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b' - '1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36' - '92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58' - 'fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc' - '3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b' - '61 16', - '1a:e1:0b:59:4f:09:e2:6a:7e:90:2e:cb:d0:60:06:91', - '80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f' - '90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f', - '07 00 00 00' + '40 41 42 43 44 45 46 47', - ), - ( 'f3 33 88 86 00 00 00 00 00 00 4e 91', - '49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 73 20' - '61 72 65 20 64 72 61 66 74 20 64 6f 63 75 6d 65' - '6e 74 73 20 76 61 6c 69 64 20 66 6f 72 20 61 20' - '6d 61 78 69 6d 75 6d 20 6f 66 20 73 69 78 20 6d' - '6f 6e 74 68 73 20 61 6e 64 20 6d 61 79 20 62 65' - '20 75 70 64 61 74 65 64 2c 20 72 65 70 6c 61 63' - '65 64 2c 20 6f 72 20 6f 62 73 6f 6c 65 74 65 64' - '20 62 79 20 6f 74 68 65 72 20 64 6f 63 75 6d 65' - '6e 74 73 20 61 74 20 61 6e 79 20 74 69 6d 65 2e' - '20 49 74 20 69 73 20 69 6e 61 70 70 72 6f 70 72' - '69 61 74 65 20 74 6f 20 75 73 65 20 49 6e 74 65' - '72 6e 65 74 2d 44 72 61 66 74 73 20 61 73 20 72' - '65 66 65 72 65 6e 63 65 20 6d 61 74 65 72 69 61' - '6c 20 6f 72 20 74 6f 20 63 69 74 65 20 74 68 65' - '6d 20 6f 74 68 65 72 20 74 68 61 6e 20 61 73 20' - '2f e2 80 9c 77 6f 72 6b 20 69 6e 20 70 72 6f 67' - '72 65 73 73 2e 2f e2 80 9d', - '64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd' - '5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2' - '4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0' - 'bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf' - '33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81' - '14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55' - '97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38' - '36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4' - 'b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9' - '90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e' - 'af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a' - '0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a' - '0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e' - 'ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10' - '49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30' - '30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29' - 'a6 ad 5c b4 02 2b 02 70 9b', - 'ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38', - '1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0' - '47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0', - '00 00 00 00 01 02 03 04 05 06 07 08', - ) - ] - - test_vectors = [[unhexlify(x.replace(" ", "").replace(":", "")) for x in tv] for tv in test_vectors_hex] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - # Encrypt - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.update(assoc_data) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.update(assoc_data) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Test cases from RFC7539""" + + # AAD, PT, CT, MAC, KEY, NONCE + test_vectors_hex = [ + ( + "50 51 52 53 c0 c1 c2 c3 c4 c5 c6 c7", + "4c 61 64 69 65 73 20 61 6e 64 20 47 65 6e 74 6c" + "65 6d 65 6e 20 6f 66 20 74 68 65 20 63 6c 61 73" + "73 20 6f 66 20 27 39 39 3a 20 49 66 20 49 20 63" + "6f 75 6c 64 20 6f 66 66 65 72 20 79 6f 75 20 6f" + "6e 6c 79 20 6f 6e 65 20 74 69 70 20 66 6f 72 20" + "74 68 65 20 66 75 74 75 72 65 2c 20 73 75 6e 73" + "63 72 65 65 6e 20 77 6f 75 6c 64 20 62 65 20 69" + "74 2e", + "d3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2" + "a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6" + "3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b" + "1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36" + "92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58" + "fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc" + "3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b" + "61 16", + "1a:e1:0b:59:4f:09:e2:6a:7e:90:2e:cb:d0:60:06:91", + "80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f", + "07 00 00 00" + "40 41 42 43 44 45 46 47", + ), + ( + "f3 33 88 86 00 00 00 00 00 00 4e 91", + "49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 73 20" + "61 72 65 20 64 72 61 66 74 20 64 6f 63 75 6d 65" + "6e 74 73 20 76 61 6c 69 64 20 66 6f 72 20 61 20" + "6d 61 78 69 6d 75 6d 20 6f 66 20 73 69 78 20 6d" + "6f 6e 74 68 73 20 61 6e 64 20 6d 61 79 20 62 65" + "20 75 70 64 61 74 65 64 2c 20 72 65 70 6c 61 63" + "65 64 2c 20 6f 72 20 6f 62 73 6f 6c 65 74 65 64" + "20 62 79 20 6f 74 68 65 72 20 64 6f 63 75 6d 65" + "6e 74 73 20 61 74 20 61 6e 79 20 74 69 6d 65 2e" + "20 49 74 20 69 73 20 69 6e 61 70 70 72 6f 70 72" + "69 61 74 65 20 74 6f 20 75 73 65 20 49 6e 74 65" + "72 6e 65 74 2d 44 72 61 66 74 73 20 61 73 20 72" + "65 66 65 72 65 6e 63 65 20 6d 61 74 65 72 69 61" + "6c 20 6f 72 20 74 6f 20 63 69 74 65 20 74 68 65" + "6d 20 6f 74 68 65 72 20 74 68 61 6e 20 61 73 20" + "2f e2 80 9c 77 6f 72 6b 20 69 6e 20 70 72 6f 67" + "72 65 73 73 2e 2f e2 80 9d", + "64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd" + "5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2" + "4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0" + "bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf" + "33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81" + "14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55" + "97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38" + "36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4" + "b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9" + "90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e" + "af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a" + "0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a" + "0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e" + "ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10" + "49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30" + "30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29" + "a6 ad 5c b4 02 2b 02 70 9b", + "ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38", + "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f047 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", + "00 00 00 00 01 02 03 04 05 06 07 08", + ), + ] + + test_vectors = [[unhexlify(x.replace(" ", "").replace(":", "")) for x in tv] for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + cipher.update(assoc_data) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + cipher.update(assoc_data) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def load_tests(self, filename): - - def filter_tag(group): - return group['tagSize'] // 8 - - def filter_algo(root): - return root['algorithm'] - - result = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - filename, - "Wycheproof ChaCha20-Poly1305", - root_tag={'algo': filter_algo}, - group_tag={'tag_size': filter_tag}) - return result - - def setUp(self): - self.tv = [] - self.tv.extend(self.load_tests("chacha20_poly1305_test.json")) - self.tv.extend(self.load_tests("xchacha20_poly1305_test.json")) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt %s Test #%s" % (tv.algo, tv.id) - - try: - cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) - except ValueError as e: - assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e) - return - - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id) - - try: - cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) - except ValueError as e: - assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e) - return - - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def test_corrupt_decrypt(self, tv): - self._id = "Wycheproof Corrupt Decrypt ChaCha20-Poly1305 Test #" + str(tv.id) - if len(tv.iv) == 0 or len(tv.ct) < 1: - return - cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) - cipher.update(tv.aad) - ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) - self.test_corrupt_decrypt(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def load_tests(self, filename): + def filter_tag(group): + return group["tagSize"] // 8 + + def filter_algo(root): + return root["algorithm"] + + result = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + filename, + "Wycheproof ChaCha20-Poly1305", + root_tag={"algo": filter_algo}, + group_tag={"tag_size": filter_tag}, + ) + return result + + def setUp(self): + self.tv = [] + self.tv.extend(self.load_tests("chacha20_poly1305_test.json")) + self.tv.extend(self.load_tests("xchacha20_poly1305_test.json")) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt %s Test #%s" % (tv.algo, tv.id) + + try: + cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) + except ValueError as e: + assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e) + return + + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id) + + try: + cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) + except ValueError as e: + assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e) + return + + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def test_corrupt_decrypt(self, tv): + self._id = "Wycheproof Corrupt Decrypt ChaCha20-Poly1305 Test #" + str(tv.id) + if len(tv.iv) == 0 or len(tv.ct) < 1: + return + cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) + cipher.update(tv.aad) + ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) + self.test_corrupt_decrypt(tv) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter + key = b"4" * 32 + nonce = b"5" * 12 + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - key = b'4' * 32 - nonce = b'5' * 12 - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + pt = b"5" * 16 + ct = cipher.encrypt(pt) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + output = bytearray(16) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - output = bytearray(16) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(16)) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(16)) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + shorter_output = bytearray(7) - shorter_output = bytearray(7) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') - - tests = [] - tests += list_test_cases(ChaCha20Poly1305Tests) - tests += list_test_cases(XChaCha20Poly1305Tests) - tests += list_test_cases(ChaCha20Poly1305FSMTests) - tests += [TestVectorsRFC()] - tests += [TestVectorsWycheproof(wycheproof_warnings)] - tests += [TestOutput()] - return tests - - -if __name__ == '__main__': - def suite(): - unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(ChaCha20Poly1305Tests) + tests += list_test_cases(XChaCha20Poly1305Tests) + tests += list_test_cases(ChaCha20Poly1305FSMTests) + tests += [TestVectorsRFC()] + tests += [TestVectorsWycheproof(wycheproof_warnings)] + tests += [TestOutput()] + return tests + + +if __name__ == "__main__": + + def suite(): + unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_DES.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_DES.py index df1313af..bb419c65 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_DES.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_DES.py @@ -29,346 +29,832 @@ from Cryptodome.Cipher import DES # This is a list of (plaintext, ciphertext, key, description) tuples. -SP800_17_B1_KEY = '01' * 8 -SP800_17_B2_PT = '00' * 8 +SP800_17_B1_KEY = "01" * 8 +SP800_17_B2_PT = "00" * 8 test_data = [ - # Test vectors from Appendix A of NIST SP 800-17 - # "Modes of Operation Validation System (MOVS): Requirements and Procedures" - # http://csrc.nist.gov/publications/nistpubs/800-17/800-17.pdf - - # Appendix A - "Sample Round Outputs for the DES" - ('0000000000000000', '82dcbafbdeab6602', '10316e028c8f3b4a', - "NIST SP800-17 A"), - - # Table B.1 - Variable Plaintext Known Answer Test - ('8000000000000000', '95f8a5e5dd31d900', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #0'), - ('4000000000000000', 'dd7f121ca5015619', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #1'), - ('2000000000000000', '2e8653104f3834ea', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #2'), - ('1000000000000000', '4bd388ff6cd81d4f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #3'), - ('0800000000000000', '20b9e767b2fb1456', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #4'), - ('0400000000000000', '55579380d77138ef', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #5'), - ('0200000000000000', '6cc5defaaf04512f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #6'), - ('0100000000000000', '0d9f279ba5d87260', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #7'), - ('0080000000000000', 'd9031b0271bd5a0a', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #8'), - ('0040000000000000', '424250b37c3dd951', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #9'), - ('0020000000000000', 'b8061b7ecd9a21e5', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #10'), - ('0010000000000000', 'f15d0f286b65bd28', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #11'), - ('0008000000000000', 'add0cc8d6e5deba1', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #12'), - ('0004000000000000', 'e6d5f82752ad63d1', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #13'), - ('0002000000000000', 'ecbfe3bd3f591a5e', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #14'), - ('0001000000000000', 'f356834379d165cd', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #15'), - ('0000800000000000', '2b9f982f20037fa9', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #16'), - ('0000400000000000', '889de068a16f0be6', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #17'), - ('0000200000000000', 'e19e275d846a1298', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #18'), - ('0000100000000000', '329a8ed523d71aec', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #19'), - ('0000080000000000', 'e7fce22557d23c97', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #20'), - ('0000040000000000', '12a9f5817ff2d65d', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #21'), - ('0000020000000000', 'a484c3ad38dc9c19', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #22'), - ('0000010000000000', 'fbe00a8a1ef8ad72', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #23'), - ('0000008000000000', '750d079407521363', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #24'), - ('0000004000000000', '64feed9c724c2faf', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #25'), - ('0000002000000000', 'f02b263b328e2b60', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #26'), - ('0000001000000000', '9d64555a9a10b852', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #27'), - ('0000000800000000', 'd106ff0bed5255d7', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #28'), - ('0000000400000000', 'e1652c6b138c64a5', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #29'), - ('0000000200000000', 'e428581186ec8f46', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #30'), - ('0000000100000000', 'aeb5f5ede22d1a36', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #31'), - ('0000000080000000', 'e943d7568aec0c5c', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #32'), - ('0000000040000000', 'df98c8276f54b04b', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #33'), - ('0000000020000000', 'b160e4680f6c696f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #34'), - ('0000000010000000', 'fa0752b07d9c4ab8', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #35'), - ('0000000008000000', 'ca3a2b036dbc8502', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #36'), - ('0000000004000000', '5e0905517bb59bcf', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #37'), - ('0000000002000000', '814eeb3b91d90726', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #38'), - ('0000000001000000', '4d49db1532919c9f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #39'), - ('0000000000800000', '25eb5fc3f8cf0621', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #40'), - ('0000000000400000', 'ab6a20c0620d1c6f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #41'), - ('0000000000200000', '79e90dbc98f92cca', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #42'), - ('0000000000100000', '866ecedd8072bb0e', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #43'), - ('0000000000080000', '8b54536f2f3e64a8', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #44'), - ('0000000000040000', 'ea51d3975595b86b', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #45'), - ('0000000000020000', 'caffc6ac4542de31', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #46'), - ('0000000000010000', '8dd45a2ddf90796c', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #47'), - ('0000000000008000', '1029d55e880ec2d0', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #48'), - ('0000000000004000', '5d86cb23639dbea9', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #49'), - ('0000000000002000', '1d1ca853ae7c0c5f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #50'), - ('0000000000001000', 'ce332329248f3228', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #51'), - ('0000000000000800', '8405d1abe24fb942', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #52'), - ('0000000000000400', 'e643d78090ca4207', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #53'), - ('0000000000000200', '48221b9937748a23', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #54'), - ('0000000000000100', 'dd7c0bbd61fafd54', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #55'), - ('0000000000000080', '2fbc291a570db5c4', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #56'), - ('0000000000000040', 'e07c30d7e4e26e12', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #57'), - ('0000000000000020', '0953e2258e8e90a1', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #58'), - ('0000000000000010', '5b711bc4ceebf2ee', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #59'), - ('0000000000000008', 'cc083f1e6d9e85f6', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #60'), - ('0000000000000004', 'd2fd8867d50d2dfe', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #61'), - ('0000000000000002', '06e7ea22ce92708f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #62'), - ('0000000000000001', '166b40b44aba4bd6', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #63'), - - # Table B.2 - Variable Key Known Answer Test - (SP800_17_B2_PT, '95a8d72813daa94d', '8001010101010101', - 'NIST SP800-17 B.2 #0'), - (SP800_17_B2_PT, '0eec1487dd8c26d5', '4001010101010101', - 'NIST SP800-17 B.2 #1'), - (SP800_17_B2_PT, '7ad16ffb79c45926', '2001010101010101', - 'NIST SP800-17 B.2 #2'), - (SP800_17_B2_PT, 'd3746294ca6a6cf3', '1001010101010101', - 'NIST SP800-17 B.2 #3'), - (SP800_17_B2_PT, '809f5f873c1fd761', '0801010101010101', - 'NIST SP800-17 B.2 #4'), - (SP800_17_B2_PT, 'c02faffec989d1fc', '0401010101010101', - 'NIST SP800-17 B.2 #5'), - (SP800_17_B2_PT, '4615aa1d33e72f10', '0201010101010101', - 'NIST SP800-17 B.2 #6'), - (SP800_17_B2_PT, '2055123350c00858', '0180010101010101', - 'NIST SP800-17 B.2 #7'), - (SP800_17_B2_PT, 'df3b99d6577397c8', '0140010101010101', - 'NIST SP800-17 B.2 #8'), - (SP800_17_B2_PT, '31fe17369b5288c9', '0120010101010101', - 'NIST SP800-17 B.2 #9'), - (SP800_17_B2_PT, 'dfdd3cc64dae1642', '0110010101010101', - 'NIST SP800-17 B.2 #10'), - (SP800_17_B2_PT, '178c83ce2b399d94', '0108010101010101', - 'NIST SP800-17 B.2 #11'), - (SP800_17_B2_PT, '50f636324a9b7f80', '0104010101010101', - 'NIST SP800-17 B.2 #12'), - (SP800_17_B2_PT, 'a8468ee3bc18f06d', '0102010101010101', - 'NIST SP800-17 B.2 #13'), - (SP800_17_B2_PT, 'a2dc9e92fd3cde92', '0101800101010101', - 'NIST SP800-17 B.2 #14'), - (SP800_17_B2_PT, 'cac09f797d031287', '0101400101010101', - 'NIST SP800-17 B.2 #15'), - (SP800_17_B2_PT, '90ba680b22aeb525', '0101200101010101', - 'NIST SP800-17 B.2 #16'), - (SP800_17_B2_PT, 'ce7a24f350e280b6', '0101100101010101', - 'NIST SP800-17 B.2 #17'), - (SP800_17_B2_PT, '882bff0aa01a0b87', '0101080101010101', - 'NIST SP800-17 B.2 #18'), - (SP800_17_B2_PT, '25610288924511c2', '0101040101010101', - 'NIST SP800-17 B.2 #19'), - (SP800_17_B2_PT, 'c71516c29c75d170', '0101020101010101', - 'NIST SP800-17 B.2 #20'), - (SP800_17_B2_PT, '5199c29a52c9f059', '0101018001010101', - 'NIST SP800-17 B.2 #21'), - (SP800_17_B2_PT, 'c22f0a294a71f29f', '0101014001010101', - 'NIST SP800-17 B.2 #22'), - (SP800_17_B2_PT, 'ee371483714c02ea', '0101012001010101', - 'NIST SP800-17 B.2 #23'), - (SP800_17_B2_PT, 'a81fbd448f9e522f', '0101011001010101', - 'NIST SP800-17 B.2 #24'), - (SP800_17_B2_PT, '4f644c92e192dfed', '0101010801010101', - 'NIST SP800-17 B.2 #25'), - (SP800_17_B2_PT, '1afa9a66a6df92ae', '0101010401010101', - 'NIST SP800-17 B.2 #26'), - (SP800_17_B2_PT, 'b3c1cc715cb879d8', '0101010201010101', - 'NIST SP800-17 B.2 #27'), - (SP800_17_B2_PT, '19d032e64ab0bd8b', '0101010180010101', - 'NIST SP800-17 B.2 #28'), - (SP800_17_B2_PT, '3cfaa7a7dc8720dc', '0101010140010101', - 'NIST SP800-17 B.2 #29'), - (SP800_17_B2_PT, 'b7265f7f447ac6f3', '0101010120010101', - 'NIST SP800-17 B.2 #30'), - (SP800_17_B2_PT, '9db73b3c0d163f54', '0101010110010101', - 'NIST SP800-17 B.2 #31'), - (SP800_17_B2_PT, '8181b65babf4a975', '0101010108010101', - 'NIST SP800-17 B.2 #32'), - (SP800_17_B2_PT, '93c9b64042eaa240', '0101010104010101', - 'NIST SP800-17 B.2 #33'), - (SP800_17_B2_PT, '5570530829705592', '0101010102010101', - 'NIST SP800-17 B.2 #34'), - (SP800_17_B2_PT, '8638809e878787a0', '0101010101800101', - 'NIST SP800-17 B.2 #35'), - (SP800_17_B2_PT, '41b9a79af79ac208', '0101010101400101', - 'NIST SP800-17 B.2 #36'), - (SP800_17_B2_PT, '7a9be42f2009a892', '0101010101200101', - 'NIST SP800-17 B.2 #37'), - (SP800_17_B2_PT, '29038d56ba6d2745', '0101010101100101', - 'NIST SP800-17 B.2 #38'), - (SP800_17_B2_PT, '5495c6abf1e5df51', '0101010101080101', - 'NIST SP800-17 B.2 #39'), - (SP800_17_B2_PT, 'ae13dbd561488933', '0101010101040101', - 'NIST SP800-17 B.2 #40'), - (SP800_17_B2_PT, '024d1ffa8904e389', '0101010101020101', - 'NIST SP800-17 B.2 #41'), - (SP800_17_B2_PT, 'd1399712f99bf02e', '0101010101018001', - 'NIST SP800-17 B.2 #42'), - (SP800_17_B2_PT, '14c1d7c1cffec79e', '0101010101014001', - 'NIST SP800-17 B.2 #43'), - (SP800_17_B2_PT, '1de5279dae3bed6f', '0101010101012001', - 'NIST SP800-17 B.2 #44'), - (SP800_17_B2_PT, 'e941a33f85501303', '0101010101011001', - 'NIST SP800-17 B.2 #45'), - (SP800_17_B2_PT, 'da99dbbc9a03f379', '0101010101010801', - 'NIST SP800-17 B.2 #46'), - (SP800_17_B2_PT, 'b7fc92f91d8e92e9', '0101010101010401', - 'NIST SP800-17 B.2 #47'), - (SP800_17_B2_PT, 'ae8e5caa3ca04e85', '0101010101010201', - 'NIST SP800-17 B.2 #48'), - (SP800_17_B2_PT, '9cc62df43b6eed74', '0101010101010180', - 'NIST SP800-17 B.2 #49'), - (SP800_17_B2_PT, 'd863dbb5c59a91a0', '0101010101010140', - 'NIST SP800-17 B.2 #50'), - (SP800_17_B2_PT, 'a1ab2190545b91d7', '0101010101010120', - 'NIST SP800-17 B.2 #51'), - (SP800_17_B2_PT, '0875041e64c570f7', '0101010101010110', - 'NIST SP800-17 B.2 #52'), - (SP800_17_B2_PT, '5a594528bebef1cc', '0101010101010108', - 'NIST SP800-17 B.2 #53'), - (SP800_17_B2_PT, 'fcdb3291de21f0c0', '0101010101010104', - 'NIST SP800-17 B.2 #54'), - (SP800_17_B2_PT, '869efd7f9f265a09', '0101010101010102', - 'NIST SP800-17 B.2 #55'), + # Test vectors from Appendix A of NIST SP 800-17 + # "Modes of Operation Validation System (MOVS): Requirements and Procedures" + # http://csrc.nist.gov/publications/nistpubs/800-17/800-17.pdf + # Appendix A - "Sample Round Outputs for the DES" + ( + "0000000000000000", + "82dcbafbdeab6602", + "10316e028c8f3b4a", + "NIST SP800-17 A", + ), + # Table B.1 - Variable Plaintext Known Answer Test + ( + "8000000000000000", + "95f8a5e5dd31d900", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #0", + ), + ( + "4000000000000000", + "dd7f121ca5015619", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #1", + ), + ( + "2000000000000000", + "2e8653104f3834ea", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #2", + ), + ( + "1000000000000000", + "4bd388ff6cd81d4f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #3", + ), + ( + "0800000000000000", + "20b9e767b2fb1456", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #4", + ), + ( + "0400000000000000", + "55579380d77138ef", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #5", + ), + ( + "0200000000000000", + "6cc5defaaf04512f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #6", + ), + ( + "0100000000000000", + "0d9f279ba5d87260", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #7", + ), + ( + "0080000000000000", + "d9031b0271bd5a0a", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #8", + ), + ( + "0040000000000000", + "424250b37c3dd951", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #9", + ), + ( + "0020000000000000", + "b8061b7ecd9a21e5", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #10", + ), + ( + "0010000000000000", + "f15d0f286b65bd28", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #11", + ), + ( + "0008000000000000", + "add0cc8d6e5deba1", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #12", + ), + ( + "0004000000000000", + "e6d5f82752ad63d1", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #13", + ), + ( + "0002000000000000", + "ecbfe3bd3f591a5e", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #14", + ), + ( + "0001000000000000", + "f356834379d165cd", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #15", + ), + ( + "0000800000000000", + "2b9f982f20037fa9", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #16", + ), + ( + "0000400000000000", + "889de068a16f0be6", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #17", + ), + ( + "0000200000000000", + "e19e275d846a1298", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #18", + ), + ( + "0000100000000000", + "329a8ed523d71aec", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #19", + ), + ( + "0000080000000000", + "e7fce22557d23c97", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #20", + ), + ( + "0000040000000000", + "12a9f5817ff2d65d", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #21", + ), + ( + "0000020000000000", + "a484c3ad38dc9c19", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #22", + ), + ( + "0000010000000000", + "fbe00a8a1ef8ad72", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #23", + ), + ( + "0000008000000000", + "750d079407521363", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #24", + ), + ( + "0000004000000000", + "64feed9c724c2faf", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #25", + ), + ( + "0000002000000000", + "f02b263b328e2b60", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #26", + ), + ( + "0000001000000000", + "9d64555a9a10b852", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #27", + ), + ( + "0000000800000000", + "d106ff0bed5255d7", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #28", + ), + ( + "0000000400000000", + "e1652c6b138c64a5", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #29", + ), + ( + "0000000200000000", + "e428581186ec8f46", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #30", + ), + ( + "0000000100000000", + "aeb5f5ede22d1a36", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #31", + ), + ( + "0000000080000000", + "e943d7568aec0c5c", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #32", + ), + ( + "0000000040000000", + "df98c8276f54b04b", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #33", + ), + ( + "0000000020000000", + "b160e4680f6c696f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #34", + ), + ( + "0000000010000000", + "fa0752b07d9c4ab8", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #35", + ), + ( + "0000000008000000", + "ca3a2b036dbc8502", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #36", + ), + ( + "0000000004000000", + "5e0905517bb59bcf", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #37", + ), + ( + "0000000002000000", + "814eeb3b91d90726", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #38", + ), + ( + "0000000001000000", + "4d49db1532919c9f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #39", + ), + ( + "0000000000800000", + "25eb5fc3f8cf0621", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #40", + ), + ( + "0000000000400000", + "ab6a20c0620d1c6f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #41", + ), + ( + "0000000000200000", + "79e90dbc98f92cca", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #42", + ), + ( + "0000000000100000", + "866ecedd8072bb0e", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #43", + ), + ( + "0000000000080000", + "8b54536f2f3e64a8", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #44", + ), + ( + "0000000000040000", + "ea51d3975595b86b", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #45", + ), + ( + "0000000000020000", + "caffc6ac4542de31", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #46", + ), + ( + "0000000000010000", + "8dd45a2ddf90796c", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #47", + ), + ( + "0000000000008000", + "1029d55e880ec2d0", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #48", + ), + ( + "0000000000004000", + "5d86cb23639dbea9", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #49", + ), + ( + "0000000000002000", + "1d1ca853ae7c0c5f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #50", + ), + ( + "0000000000001000", + "ce332329248f3228", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #51", + ), + ( + "0000000000000800", + "8405d1abe24fb942", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #52", + ), + ( + "0000000000000400", + "e643d78090ca4207", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #53", + ), + ( + "0000000000000200", + "48221b9937748a23", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #54", + ), + ( + "0000000000000100", + "dd7c0bbd61fafd54", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #55", + ), + ( + "0000000000000080", + "2fbc291a570db5c4", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #56", + ), + ( + "0000000000000040", + "e07c30d7e4e26e12", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #57", + ), + ( + "0000000000000020", + "0953e2258e8e90a1", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #58", + ), + ( + "0000000000000010", + "5b711bc4ceebf2ee", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #59", + ), + ( + "0000000000000008", + "cc083f1e6d9e85f6", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #60", + ), + ( + "0000000000000004", + "d2fd8867d50d2dfe", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #61", + ), + ( + "0000000000000002", + "06e7ea22ce92708f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #62", + ), + ( + "0000000000000001", + "166b40b44aba4bd6", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #63", + ), + # Table B.2 - Variable Key Known Answer Test + ( + SP800_17_B2_PT, + "95a8d72813daa94d", + "8001010101010101", + "NIST SP800-17 B.2 #0", + ), + ( + SP800_17_B2_PT, + "0eec1487dd8c26d5", + "4001010101010101", + "NIST SP800-17 B.2 #1", + ), + ( + SP800_17_B2_PT, + "7ad16ffb79c45926", + "2001010101010101", + "NIST SP800-17 B.2 #2", + ), + ( + SP800_17_B2_PT, + "d3746294ca6a6cf3", + "1001010101010101", + "NIST SP800-17 B.2 #3", + ), + ( + SP800_17_B2_PT, + "809f5f873c1fd761", + "0801010101010101", + "NIST SP800-17 B.2 #4", + ), + ( + SP800_17_B2_PT, + "c02faffec989d1fc", + "0401010101010101", + "NIST SP800-17 B.2 #5", + ), + ( + SP800_17_B2_PT, + "4615aa1d33e72f10", + "0201010101010101", + "NIST SP800-17 B.2 #6", + ), + ( + SP800_17_B2_PT, + "2055123350c00858", + "0180010101010101", + "NIST SP800-17 B.2 #7", + ), + ( + SP800_17_B2_PT, + "df3b99d6577397c8", + "0140010101010101", + "NIST SP800-17 B.2 #8", + ), + ( + SP800_17_B2_PT, + "31fe17369b5288c9", + "0120010101010101", + "NIST SP800-17 B.2 #9", + ), + ( + SP800_17_B2_PT, + "dfdd3cc64dae1642", + "0110010101010101", + "NIST SP800-17 B.2 #10", + ), + ( + SP800_17_B2_PT, + "178c83ce2b399d94", + "0108010101010101", + "NIST SP800-17 B.2 #11", + ), + ( + SP800_17_B2_PT, + "50f636324a9b7f80", + "0104010101010101", + "NIST SP800-17 B.2 #12", + ), + ( + SP800_17_B2_PT, + "a8468ee3bc18f06d", + "0102010101010101", + "NIST SP800-17 B.2 #13", + ), + ( + SP800_17_B2_PT, + "a2dc9e92fd3cde92", + "0101800101010101", + "NIST SP800-17 B.2 #14", + ), + ( + SP800_17_B2_PT, + "cac09f797d031287", + "0101400101010101", + "NIST SP800-17 B.2 #15", + ), + ( + SP800_17_B2_PT, + "90ba680b22aeb525", + "0101200101010101", + "NIST SP800-17 B.2 #16", + ), + ( + SP800_17_B2_PT, + "ce7a24f350e280b6", + "0101100101010101", + "NIST SP800-17 B.2 #17", + ), + ( + SP800_17_B2_PT, + "882bff0aa01a0b87", + "0101080101010101", + "NIST SP800-17 B.2 #18", + ), + ( + SP800_17_B2_PT, + "25610288924511c2", + "0101040101010101", + "NIST SP800-17 B.2 #19", + ), + ( + SP800_17_B2_PT, + "c71516c29c75d170", + "0101020101010101", + "NIST SP800-17 B.2 #20", + ), + ( + SP800_17_B2_PT, + "5199c29a52c9f059", + "0101018001010101", + "NIST SP800-17 B.2 #21", + ), + ( + SP800_17_B2_PT, + "c22f0a294a71f29f", + "0101014001010101", + "NIST SP800-17 B.2 #22", + ), + ( + SP800_17_B2_PT, + "ee371483714c02ea", + "0101012001010101", + "NIST SP800-17 B.2 #23", + ), + ( + SP800_17_B2_PT, + "a81fbd448f9e522f", + "0101011001010101", + "NIST SP800-17 B.2 #24", + ), + ( + SP800_17_B2_PT, + "4f644c92e192dfed", + "0101010801010101", + "NIST SP800-17 B.2 #25", + ), + ( + SP800_17_B2_PT, + "1afa9a66a6df92ae", + "0101010401010101", + "NIST SP800-17 B.2 #26", + ), + ( + SP800_17_B2_PT, + "b3c1cc715cb879d8", + "0101010201010101", + "NIST SP800-17 B.2 #27", + ), + ( + SP800_17_B2_PT, + "19d032e64ab0bd8b", + "0101010180010101", + "NIST SP800-17 B.2 #28", + ), + ( + SP800_17_B2_PT, + "3cfaa7a7dc8720dc", + "0101010140010101", + "NIST SP800-17 B.2 #29", + ), + ( + SP800_17_B2_PT, + "b7265f7f447ac6f3", + "0101010120010101", + "NIST SP800-17 B.2 #30", + ), + ( + SP800_17_B2_PT, + "9db73b3c0d163f54", + "0101010110010101", + "NIST SP800-17 B.2 #31", + ), + ( + SP800_17_B2_PT, + "8181b65babf4a975", + "0101010108010101", + "NIST SP800-17 B.2 #32", + ), + ( + SP800_17_B2_PT, + "93c9b64042eaa240", + "0101010104010101", + "NIST SP800-17 B.2 #33", + ), + ( + SP800_17_B2_PT, + "5570530829705592", + "0101010102010101", + "NIST SP800-17 B.2 #34", + ), + ( + SP800_17_B2_PT, + "8638809e878787a0", + "0101010101800101", + "NIST SP800-17 B.2 #35", + ), + ( + SP800_17_B2_PT, + "41b9a79af79ac208", + "0101010101400101", + "NIST SP800-17 B.2 #36", + ), + ( + SP800_17_B2_PT, + "7a9be42f2009a892", + "0101010101200101", + "NIST SP800-17 B.2 #37", + ), + ( + SP800_17_B2_PT, + "29038d56ba6d2745", + "0101010101100101", + "NIST SP800-17 B.2 #38", + ), + ( + SP800_17_B2_PT, + "5495c6abf1e5df51", + "0101010101080101", + "NIST SP800-17 B.2 #39", + ), + ( + SP800_17_B2_PT, + "ae13dbd561488933", + "0101010101040101", + "NIST SP800-17 B.2 #40", + ), + ( + SP800_17_B2_PT, + "024d1ffa8904e389", + "0101010101020101", + "NIST SP800-17 B.2 #41", + ), + ( + SP800_17_B2_PT, + "d1399712f99bf02e", + "0101010101018001", + "NIST SP800-17 B.2 #42", + ), + ( + SP800_17_B2_PT, + "14c1d7c1cffec79e", + "0101010101014001", + "NIST SP800-17 B.2 #43", + ), + ( + SP800_17_B2_PT, + "1de5279dae3bed6f", + "0101010101012001", + "NIST SP800-17 B.2 #44", + ), + ( + SP800_17_B2_PT, + "e941a33f85501303", + "0101010101011001", + "NIST SP800-17 B.2 #45", + ), + ( + SP800_17_B2_PT, + "da99dbbc9a03f379", + "0101010101010801", + "NIST SP800-17 B.2 #46", + ), + ( + SP800_17_B2_PT, + "b7fc92f91d8e92e9", + "0101010101010401", + "NIST SP800-17 B.2 #47", + ), + ( + SP800_17_B2_PT, + "ae8e5caa3ca04e85", + "0101010101010201", + "NIST SP800-17 B.2 #48", + ), + ( + SP800_17_B2_PT, + "9cc62df43b6eed74", + "0101010101010180", + "NIST SP800-17 B.2 #49", + ), + ( + SP800_17_B2_PT, + "d863dbb5c59a91a0", + "0101010101010140", + "NIST SP800-17 B.2 #50", + ), + ( + SP800_17_B2_PT, + "a1ab2190545b91d7", + "0101010101010120", + "NIST SP800-17 B.2 #51", + ), + ( + SP800_17_B2_PT, + "0875041e64c570f7", + "0101010101010110", + "NIST SP800-17 B.2 #52", + ), + ( + SP800_17_B2_PT, + "5a594528bebef1cc", + "0101010101010108", + "NIST SP800-17 B.2 #53", + ), + ( + SP800_17_B2_PT, + "fcdb3291de21f0c0", + "0101010101010104", + "NIST SP800-17 B.2 #54", + ), + ( + SP800_17_B2_PT, + "869efd7f9f265a09", + "0101010101010102", + "NIST SP800-17 B.2 #55", + ), ] + class RonRivestTest(unittest.TestCase): - """ Ronald L. Rivest's DES test, see - http://people.csail.mit.edu/rivest/Destest.txt - ABSTRACT - -------- + """Ronald L. Rivest's DES test, see + http://people.csail.mit.edu/rivest/Destest.txt + ABSTRACT + -------- + + We present a simple way to test the correctness of a DES implementation: + Use the recurrence relation: - We present a simple way to test the correctness of a DES implementation: - Use the recurrence relation: + X0 = 9474B8E8C73BCA7D (hexadecimal) - X0 = 9474B8E8C73BCA7D (hexadecimal) + X(i+1) = IF (i is even) THEN E(Xi,Xi) ELSE D(Xi,Xi) - X(i+1) = IF (i is even) THEN E(Xi,Xi) ELSE D(Xi,Xi) + to compute a sequence of 64-bit values: X0, X1, X2, ..., X16. Here + E(X,K) denotes the DES encryption of X using key K, and D(X,K) denotes + the DES decryption of X using key K. If you obtain - to compute a sequence of 64-bit values: X0, X1, X2, ..., X16. Here - E(X,K) denotes the DES encryption of X using key K, and D(X,K) denotes - the DES decryption of X using key K. If you obtain + X16 = 1B1A2DDB4C642438 - X16 = 1B1A2DDB4C642438 + your implementation does not have any of the 36,568 possible single-fault + errors described herein. + """ - your implementation does not have any of the 36,568 possible single-fault - errors described herein. - """ - def runTest(self): - from binascii import b2a_hex + def runTest(self): + from binascii import b2a_hex - X = [] - X[0:] = [b'\x94\x74\xB8\xE8\xC7\x3B\xCA\x7D'] + X = [] + X[0:] = [b"\x94\x74\xb8\xe8\xc7\x3b\xca\x7d"] - for i in range(16): - c = DES.new(X[i],DES.MODE_ECB) - if not (i&1): # (num&1) returns 1 for odd numbers - X[i+1:] = [c.encrypt(X[i])] # even - else: - X[i+1:] = [c.decrypt(X[i])] # odd + for i in range(16): + c = DES.new(X[i], DES.MODE_ECB) + if not (i & 1): # (num&1) returns 1 for odd numbers + X[i + 1 :] = [c.encrypt(X[i])] # even + else: + X[i + 1 :] = [c.decrypt(X[i])] # odd - self.assertEqual(b2a_hex(X[16]), - b2a_hex(b'\x1B\x1A\x2D\xDB\x4C\x64\x24\x38')) + self.assertEqual( + b2a_hex(X[16]), + b2a_hex(b"\x1b\x1a\x2d\xdb\x4c\x64\x24\x38"), + ) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter + + cipher = DES.new(b"4" * 8, DES.MODE_ECB) - def runTest(self): - # Encrypt/Decrypt data and test output parameter + pt = b"5" * 8 + ct = cipher.encrypt(pt) - cipher = DES.new(b'4'*8, DES.MODE_ECB) + output = bytearray(8) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt = b'5' * 8 - ct = cipher.encrypt(pt) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = bytearray(8) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(8)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(8)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*8) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*8) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 8) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 8) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from .common import make_block_tests - tests = make_block_tests(DES, "DES", test_data) - tests += [RonRivestTest()] - tests += [TestOutput()] - return tests + from .common import make_block_tests + + tests = make_block_tests(DES, "DES", test_data) + tests += [RonRivestTest()] + tests += [TestOutput()] + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_DES3.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_DES3.py index 8f8479ba..5e4920d6 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_DES3.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_DES3.py @@ -36,19 +36,24 @@ # This is a list of (plaintext, ciphertext, key, description) tuples. test_data = [ - # Test vector from Appendix B of NIST SP 800-67 - # "Recommendation for the Triple Data Encryption Algorithm (TDEA) Block - # Cipher" - # http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf - ('54686520717566636b2062726f776e20666f78206a756d70', - 'a826fd8ce53b855fcce21c8112256fe668d5c05dd9b6b900', - '0123456789abcdef23456789abcdef01456789abcdef0123', - 'NIST SP800-67 B.1'), - - # This test is designed to test the DES3 API, not the correctness of the - # output. - ('21e81b7ade88a259', '5c577d4d9b20c0f8', - '9b397ebf81b1181e282f4bb8adbadc6b', 'Two-key 3DES'), + # Test vector from Appendix B of NIST SP 800-67 + # "Recommendation for the Triple Data Encryption Algorithm (TDEA) Block + # Cipher" + # http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf + ( + "54686520717566636b2062726f776e20666f78206a756d70", + "a826fd8ce53b855fcce21c8112256fe668d5c05dd9b6b900", + "0123456789abcdef23456789abcdef01456789abcdef0123", + "NIST SP800-67 B.1", + ), + # This test is designed to test the DES3 API, not the correctness of the + # output. + ( + "21e81b7ade88a259", + "5c577d4d9b20c0f8", + "9b397ebf81b1181e282f4bb8adbadc6b", + "Two-key 3DES", + ), ] # NIST CAVP test vectors @@ -56,140 +61,169 @@ nist_tdes_mmt_files = ("TECBMMT2.rsp", "TECBMMT3.rsp") for tdes_file in nist_tdes_mmt_files: - - test_vectors = load_test_vectors( - ("Cipher", "TDES"), - tdes_file, - "TDES ECB (%s)" % tdes_file, - {"count": lambda x: int(x)}) or [] - - for index, tv in enumerate(test_vectors): - - # The test vector file contains some directive lines - if isinstance(tv, str): - continue - - key = tv.key1 + tv.key2 + tv.key3 - test_data_item = (tostr(hexlify(tv.plaintext)), - tostr(hexlify(tv.ciphertext)), - tostr(hexlify(key)), - "%s (%s)" % (tdes_file, index)) - test_data.append(test_data_item) + test_vectors = ( + load_test_vectors( + ("Cipher", "TDES"), + tdes_file, + "TDES ECB (%s)" % tdes_file, + {"count": lambda x: int(x)}, + ) + or [] + ) + + for index, tv in enumerate(test_vectors): + # The test vector file contains some directive lines + if isinstance(tv, str): + continue + + key = tv.key1 + tv.key2 + tv.key3 + test_data_item = ( + tostr(hexlify(tv.plaintext)), + tostr(hexlify(tv.ciphertext)), + tostr(hexlify(key)), + "%s (%s)" % (tdes_file, index), + ) + test_data.append(test_data_item) class CheckParity(unittest.TestCase): - - def test_parity_option2(self): - before_2k = unhexlify("CABF326FA56734324FFCCABCDEFACABF") - after_2k = DES3.adjust_key_parity(before_2k) - self.assertEqual(after_2k, - unhexlify("CBBF326EA46734324FFDCBBCDFFBCBBF")) - - def test_parity_option3(self): - before_3k = unhexlify("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC") - after_3k = DES3.adjust_key_parity(before_3k) - self.assertEqual(after_3k, - unhexlify("ABABABABABABABABBABABABABABABABACDCDCDCDCDCDCDCD")) - - def test_degradation(self): - sub_key1 = bchr(1) * 8 - sub_key2 = bchr(255) * 8 - - # K1 == K2 - self.assertRaises(ValueError, DES3.adjust_key_parity, - sub_key1 * 2 + sub_key2) - - # K2 == K3 - self.assertRaises(ValueError, DES3.adjust_key_parity, - sub_key1 + sub_key2 * 2) - - # K1 == K2 == K3 - self.assertRaises(ValueError, DES3.adjust_key_parity, - sub_key1 * 3) - - # K1 == K2 (with different parity) - self.assertRaises(ValueError, DES3.adjust_key_parity, - sub_key1 + strxor_c(sub_key1, 1) + sub_key2) + def test_parity_option2(self): + before_2k = unhexlify("CABF326FA56734324FFCCABCDEFACABF") + after_2k = DES3.adjust_key_parity(before_2k) + self.assertEqual( + after_2k, + unhexlify("CBBF326EA46734324FFDCBBCDFFBCBBF"), + ) + + def test_parity_option3(self): + before_3k = unhexlify("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC") + after_3k = DES3.adjust_key_parity(before_3k) + self.assertEqual( + after_3k, + unhexlify("ABABABABABABABABBABABABABABABABACDCDCDCDCDCDCDCD"), + ) + + def test_degradation(self): + sub_key1 = bchr(1) * 8 + sub_key2 = bchr(255) * 8 + + # K1 == K2 + self.assertRaises( + ValueError, + DES3.adjust_key_parity, + sub_key1 * 2 + sub_key2, + ) + + # K2 == K3 + self.assertRaises( + ValueError, + DES3.adjust_key_parity, + sub_key1 + sub_key2 * 2, + ) + + # K1 == K2 == K3 + self.assertRaises( + ValueError, + DES3.adjust_key_parity, + sub_key1 * 3, + ) + + # K1 == K2 (with different parity) + self.assertRaises( + ValueError, + DES3.adjust_key_parity, + sub_key1 + strxor_c(sub_key1, 1) + sub_key2, + ) class DegenerateToDESTest(unittest.TestCase): - - def runTest(self): - sub_key1 = bchr(1) * 8 - sub_key2 = bchr(255) * 8 - - # K1 == K2 - self.assertRaises(ValueError, DES3.new, - sub_key1 * 2 + sub_key2, - DES3.MODE_ECB) - - # K2 == K3 - self.assertRaises(ValueError, DES3.new, - sub_key1 + sub_key2 * 2, - DES3.MODE_ECB) - - # K1 == K2 == K3 - self.assertRaises(ValueError, DES3.new, - sub_key1 * 3, - DES3.MODE_ECB) - - # K2 == K3 (parity is ignored) - self.assertRaises(ValueError, DES3.new, - sub_key1 + sub_key2 + strxor_c(sub_key2, 0x1), - DES3.MODE_ECB) + def runTest(self): + sub_key1 = bchr(1) * 8 + sub_key2 = bchr(255) * 8 + + # K1 == K2 + self.assertRaises( + ValueError, + DES3.new, + sub_key1 * 2 + sub_key2, + DES3.MODE_ECB, + ) + + # K2 == K3 + self.assertRaises( + ValueError, + DES3.new, + sub_key1 + sub_key2 * 2, + DES3.MODE_ECB, + ) + + # K1 == K2 == K3 + self.assertRaises( + ValueError, + DES3.new, + sub_key1 * 3, + DES3.MODE_ECB, + ) + + # K2 == K3 (parity is ignored) + self.assertRaises( + ValueError, + DES3.new, + sub_key1 + sub_key2 + strxor_c(sub_key2, 0x1), + DES3.MODE_ECB, + ) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter - - cipher = DES3.new(b'4'*8 + b'G'*8 + b'T'*8, DES3.MODE_ECB) + cipher = DES3.new(b"4" * 8 + b"G" * 8 + b"T" * 8, DES3.MODE_ECB) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + pt = b"5" * 16 + ct = cipher.encrypt(pt) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from .common import make_block_tests + from .common import make_block_tests - tests = [] - tests = make_block_tests(DES3, "DES3", test_data) - tests.append(DegenerateToDESTest()) - tests += list_test_cases(CheckParity) - tests += [TestOutput()] - return tests + tests = [] + tests = make_block_tests(DES3, "DES3", test_data) + tests.append(DegenerateToDESTest()) + tests += list_test_cases(CheckParity) + tests += [TestOutput()] + return tests -if __name__ == '__main__': - import unittest +if __name__ == "__main__": + import unittest - def suite(): - unittest.TestSuite(get_tests()) + def suite(): + unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_EAX.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_EAX.py index 4127a888..a83f0b68 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_EAX.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_EAX.py @@ -41,733 +41,836 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class EaxTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - key_192 = get_tag_random("key_192", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data_128 = get_tag_random("data_128", 16) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_loopback_64(self): - cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 8 * 100) - ct = cipher.encrypt(pt) - - cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # If not passed, the nonce is created randomly - cipher = AES.new(self.key_128, AES.MODE_EAX) - nonce1 = cipher.nonce - cipher = AES.new(self.key_128, AES.MODE_EAX) - nonce2 = cipher.nonce - self.assertEqual(len(nonce1), 16) - self.assertNotEqual(nonce1, nonce2) - - cipher = AES.new(self.key_128, AES.MODE_EAX, self.nonce_96) - ct = cipher.encrypt(self.data_128) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data_128)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_EAX, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce can be of any length (but not empty) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_EAX, - nonce=b"") - - for x in range(1, 128): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=bchr(1) * x) - cipher.encrypt(bchr(1)) - - def test_block_size_128(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_block_size_64(self): - cipher = DES3.new(self.key_192, AES.MODE_EAX, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, DES3.block_size) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 16 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_EAX).nonce - nonce2 = AES.new(self.key_128, AES.MODE_EAX).nonce - self.assertEqual(len(nonce1), 16) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_EAX, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_EAX, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96, - use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - # Invalid MAC length - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_EAX, - nonce=self.nonce_96, mac_len=2-1) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_EAX, - nonce=self.nonce_96, mac_len=16+1) - - # Valid MAC length - for mac_len in range(2, 16 + 1): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96, - mac_len=mac_len) - _, mac = cipher.encrypt_and_digest(self.data_128) - self.assertEqual(len(mac), mac_len) - - # Default MAC length - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data_128) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data_128) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b"" - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b"" - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data_128) - data_ba = bytearray(self.data_128) - - cipher1 = AES.new(self.key_128, - AES.MODE_EAX, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) - tag = cipher1.digest() - - cipher2 = AES.new(key_ba, - AES.MODE_EAX, - nonce=nonce_ba) - key_ba[:3] = b'\xFF\xFF\xFF' - nonce_ba[:3] = b'\xFF\xFF\xFF' - cipher2.update(header_ba) - header_ba[:3] = b'\xFF\xFF\xFF' - ct_test = cipher2.encrypt(data_ba) - data_ba[:3] = b'\x99\x99\x99' - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data_128) - ct_ba = bytearray(ct) - tag_ba = bytearray(tag) - del data_ba - - cipher3 = AES.new(key_ba, - AES.MODE_EAX, - nonce=nonce_ba) - key_ba[:3] = b'\xFF\xFF\xFF' - nonce_ba[:3] = b'\xFF\xFF\xFF' - cipher3.update(header_ba) - header_ba[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt(ct_ba) - ct_ba[:3] = b'\xFF\xFF\xFF' - cipher3.verify(tag_ba) - - self.assertEqual(pt_test, self.data_128) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data_128)) - data_mv = memoryview(bytearray(self.data_128)) - - cipher1 = AES.new(self.key_128, - AES.MODE_EAX, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) - tag = cipher1.digest() - - cipher2 = AES.new(key_mv, - AES.MODE_EAX, - nonce=nonce_mv) - key_mv[:3] = b'\xFF\xFF\xFF' - nonce_mv[:3] = b'\xFF\xFF\xFF' - cipher2.update(header_mv) - header_mv[:3] = b'\xFF\xFF\xFF' - ct_test = cipher2.encrypt(data_mv) - data_mv[:3] = b'\x99\x99\x99' - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data_128)) - ct_mv = memoryview(bytearray(ct)) - tag_mv = memoryview(bytearray(tag)) - del data_mv - - cipher3 = AES.new(key_mv, - AES.MODE_EAX, - nonce=nonce_mv) - key_mv[:3] = b'\xFF\xFF\xFF' - nonce_mv[:3] = b'\xFF\xFF\xFF' - cipher3.update(header_mv) - header_mv[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt(ct_mv) - ct_mv[:3] = b'\x99\x99\x99' - cipher3.verify(tag_mv) - - self.assertEqual(pt_test, self.data_128) - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - tag = cipher.digest() - - output = bytearray(128) - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - res, tag_out = cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - self.assertEqual(tag, tag_out) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - res = cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - - def test_output_param_neg(self): - LEN_PT = 16 - - pt = b'5' * LEN_PT - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT) - - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + key_128 = get_tag_random("key_128", 16) + key_192 = get_tag_random("key_192", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data_128 = get_tag_random("data_128", 16) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_loopback_64(self): + cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 8 * 100) + ct = cipher.encrypt(pt) + + cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # If not passed, the nonce is created randomly + cipher = AES.new(self.key_128, AES.MODE_EAX) + nonce1 = cipher.nonce + cipher = AES.new(self.key_128, AES.MODE_EAX) + nonce2 = cipher.nonce + self.assertEqual(len(nonce1), 16) + self.assertNotEqual(nonce1, nonce2) + + cipher = AES.new(self.key_128, AES.MODE_EAX, self.nonce_96) + ct = cipher.encrypt(self.data_128) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertEqual(ct, cipher.encrypt(self.data_128)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce can be of any length (but not empty) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce=b"", + ) + + for x in range(1, 128): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=bchr(1) * x) + cipher.encrypt(bchr(1)) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_block_size_64(self): + cipher = DES3.new(self.key_192, AES.MODE_EAX, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, DES3.block_size) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 16 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_EAX).nonce + nonce2 = AES.new(self.key_128, AES.MODE_EAX).nonce + self.assertEqual(len(nonce1), 16) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_EAX, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + # Invalid MAC length + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + mac_len=2 - 1, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + mac_len=16 + 1, + ) + + # Valid MAC length + for mac_len in range(2, 16 + 1): + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + mac_len=mac_len, + ) + _, mac = cipher.encrypt_and_digest(self.data_128) + self.assertEqual(len(mac), mac_len) + + # Default MAC length + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data_128) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data_128) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b"" + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b"" + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data_128) + data_ba = bytearray(self.data_128) + + cipher1 = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher1.update(self.data_128) + ct = cipher1.encrypt(self.data_128) + tag = cipher1.digest() + + cipher2 = AES.new( + key_ba, + AES.MODE_EAX, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + data_ba[:3] = b"\x99\x99\x99" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data_128) + ct_ba = bytearray(ct) + tag_ba = bytearray(tag) + del data_ba + + cipher3 = AES.new( + key_ba, + AES.MODE_EAX, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher3.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt(ct_ba) + ct_ba[:3] = b"\xff\xff\xff" + cipher3.verify(tag_ba) + + self.assertEqual(pt_test, self.data_128) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data_128)) + data_mv = memoryview(bytearray(self.data_128)) + + cipher1 = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher1.update(self.data_128) + ct = cipher1.encrypt(self.data_128) + tag = cipher1.digest() + + cipher2 = AES.new( + key_mv, + AES.MODE_EAX, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + data_mv[:3] = b"\x99\x99\x99" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data_128)) + ct_mv = memoryview(bytearray(ct)) + tag_mv = memoryview(bytearray(tag)) + del data_mv + + cipher3 = AES.new( + key_mv, + AES.MODE_EAX, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher3.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt(ct_mv) + ct_mv[:3] = b"\x99\x99\x99" + cipher3.verify(tag_mv) + + self.assertEqual(pt_test, self.data_128) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + tag = cipher.digest() + + output = bytearray(128) + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + res, tag_out = cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + self.assertEqual(tag, tag_out) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + res = cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + LEN_PT = 16 + + pt = b"5" * LEN_PT + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * LEN_PT) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * LEN_PT) + + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) class EaxFSMTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data_128 = get_tag_random("data_128", 16) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - # Verify path INIT->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.update(self.data_128) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.update(self.data_128) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - # Verify path INIT->UPDATE->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.update(self.data_128) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.update(self.data_128) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - for method_name in "encrypt", "decrypt": - for auth_data in (None, b"333", self.data_128, - self.data_128 + b"3"): - if auth_data is None: - assoc_len = None - else: - assoc_len = len(auth_data) - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data_128) - method(self.data_128) - method(self.data_128) - method(self.data_128) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(self.data_128) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(self.data_128) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(self.data_128) - ct, mac = cipher.encrypt_and_digest(self.data_128) - - # decrypt_and_verify - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(self.data_128) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data_128, pt) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data_128) - getattr(cipher, method1_name)(self.data_128) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data_128) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.encrypt(self.data_128) - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data_128) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data_128 = get_tag_random("data_128", 16) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + # Verify path INIT->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + # Verify path INIT->UPDATE->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b"333", + self.data_128, + self.data_128 + b"3", + ): + if auth_data is None: + assoc_len = None + else: + assoc_len = len(auth_data) + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data_128) + method(self.data_128) + method(self.data_128) + method(self.data_128) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(self.data_128) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(self.data_128) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(self.data_128) + ct, mac = cipher.encrypt_and_digest(self.data_128) + + # decrypt_and_verify + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(self.data_128) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data_128, pt) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data_128) + getattr(cipher, method1_name)(self.data_128) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data_128, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.encrypt(self.data_128) + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data_128) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) class TestVectorsPaper(unittest.TestCase): - """Class exercising the EAX test vectors found in - http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf""" - - test_vectors_hex = [ - ( '6bfb914fd07eae6b', - '', - '', - 'e037830e8389f27b025a2d6527e79d01', - '233952dee4d5ed5f9b9c6d6ff80ff478', - '62EC67F9C3A4A407FCB2A8C49031A8B3' - ), - ( - 'fa3bfd4806eb53fa', - 'f7fb', - '19dd', - '5c4c9331049d0bdab0277408f67967e5', - '91945d3f4dcbee0bf45ef52255f095a4', - 'BECAF043B0A23D843194BA972C66DEBD' - ), - ( '234a3463c1264ac6', - '1a47cb4933', - 'd851d5bae0', - '3a59f238a23e39199dc9266626c40f80', - '01f74ad64077f2e704c0f60ada3dd523', - '70C3DB4F0D26368400A10ED05D2BFF5E' - ), - ( - '33cce2eabff5a79d', - '481c9e39b1', - '632a9d131a', - 'd4c168a4225d8e1ff755939974a7bede', - 'd07cf6cbb7f313bdde66b727afd3c5e8', - '8408DFFF3C1A2B1292DC199E46B7D617' - ), - ( - 'aeb96eaebe2970e9', - '40d0c07da5e4', - '071dfe16c675', - 'cb0677e536f73afe6a14b74ee49844dd', - '35b6d0580005bbc12b0587124557d2c2', - 'FDB6B06676EEDC5C61D74276E1F8E816' - ), - ( - 'd4482d1ca78dce0f', - '4de3b35c3fc039245bd1fb7d', - '835bb4f15d743e350e728414', - 'abb8644fd6ccb86947c5e10590210a4f', - 'bd8e6e11475e60b268784c38c62feb22', - '6EAC5C93072D8E8513F750935E46DA1B' - ), - ( - '65d2017990d62528', - '8b0a79306c9ce7ed99dae4f87f8dd61636', - '02083e3979da014812f59f11d52630da30', - '137327d10649b0aa6e1c181db617d7f2', - '7c77d6e813bed5ac98baa417477a2e7d', - '1A8C98DCD73D38393B2BF1569DEEFC19' - ), - ( - '54b9f04e6a09189a', - '1bda122bce8a8dbaf1877d962b8592dd2d56', - '2ec47b2c4954a489afc7ba4897edcdae8cc3', - '3b60450599bd02c96382902aef7f832a', - '5fff20cafab119ca2fc73549e20f5b0d', - 'DDE59B97D722156D4D9AFF2BC7559826' - ), - ( - '899a175897561d7e', - '6cf36720872b8513f6eab1a8a44438d5ef11', - '0de18fd0fdd91e7af19f1d8ee8733938b1e8', - 'e7f6d2231618102fdb7fe55ff1991700', - 'a4a4782bcffd3ec5e7ef6d8c34a56123', - 'B781FCF2F75FA5A8DE97A9CA48E522EC' - ), - ( - '126735fcc320d25a', - 'ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7', - 'cb8920f87a6c75cff39627b56e3ed197c552d295a7', - 'cfc46afc253b4652b1af3795b124ab6e', - '8395fcf1e95bebd697bd010bc766aac3', - '22E7ADD93CFC6393C57EC0B3C17D6B44' - ), - ] - - test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - # Encrypt - cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Class exercising the EAX test vectors found in + http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf""" + + test_vectors_hex = [ + ( + "6bfb914fd07eae6b", + "", + "", + "e037830e8389f27b025a2d6527e79d01", + "233952dee4d5ed5f9b9c6d6ff80ff478", + "62EC67F9C3A4A407FCB2A8C49031A8B3", + ), + ( + "fa3bfd4806eb53fa", + "f7fb", + "19dd", + "5c4c9331049d0bdab0277408f67967e5", + "91945d3f4dcbee0bf45ef52255f095a4", + "BECAF043B0A23D843194BA972C66DEBD", + ), + ( + "234a3463c1264ac6", + "1a47cb4933", + "d851d5bae0", + "3a59f238a23e39199dc9266626c40f80", + "01f74ad64077f2e704c0f60ada3dd523", + "70C3DB4F0D26368400A10ED05D2BFF5E", + ), + ( + "33cce2eabff5a79d", + "481c9e39b1", + "632a9d131a", + "d4c168a4225d8e1ff755939974a7bede", + "d07cf6cbb7f313bdde66b727afd3c5e8", + "8408DFFF3C1A2B1292DC199E46B7D617", + ), + ( + "aeb96eaebe2970e9", + "40d0c07da5e4", + "071dfe16c675", + "cb0677e536f73afe6a14b74ee49844dd", + "35b6d0580005bbc12b0587124557d2c2", + "FDB6B06676EEDC5C61D74276E1F8E816", + ), + ( + "d4482d1ca78dce0f", + "4de3b35c3fc039245bd1fb7d", + "835bb4f15d743e350e728414", + "abb8644fd6ccb86947c5e10590210a4f", + "bd8e6e11475e60b268784c38c62feb22", + "6EAC5C93072D8E8513F750935E46DA1B", + ), + ( + "65d2017990d62528", + "8b0a79306c9ce7ed99dae4f87f8dd61636", + "02083e3979da014812f59f11d52630da30", + "137327d10649b0aa6e1c181db617d7f2", + "7c77d6e813bed5ac98baa417477a2e7d", + "1A8C98DCD73D38393B2BF1569DEEFC19", + ), + ( + "54b9f04e6a09189a", + "1bda122bce8a8dbaf1877d962b8592dd2d56", + "2ec47b2c4954a489afc7ba4897edcdae8cc3", + "3b60450599bd02c96382902aef7f832a", + "5fff20cafab119ca2fc73549e20f5b0d", + "DDE59B97D722156D4D9AFF2BC7559826", + ), + ( + "899a175897561d7e", + "6cf36720872b8513f6eab1a8a44438d5ef11", + "0de18fd0fdd91e7af19f1d8ee8733938b1e8", + "e7f6d2231618102fdb7fe55ff1991700", + "a4a4782bcffd3ec5e7ef6d8c34a56123", + "B781FCF2F75FA5A8DE97A9CA48E522EC", + ), + ( + "126735fcc320d25a", + "ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7", + "cb8920f87a6c75cff39627b56e3ed197c552d295a7", + "cfc46afc253b4652b1af3795b124ab6e", + "8395fcf1e95bebd697bd010bc766aac3", + "22E7ADD93CFC6393C57EC0B3C17D6B44", + ), + ] + + test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def setUp(self): - - def filter_tag(group): - return group['tagSize'] // 8 - - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aes_eax_test.json", - "Wycheproof EAX", - group_tag={'tag_size': filter_tag}) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt EAX Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) - except ValueError as e: - assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e) - return - - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt EAX Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) - except ValueError as e: - assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e) - return - - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def test_corrupt_decrypt(self, tv): - self._id = "Wycheproof Corrupt Decrypt EAX Test #" + str(tv.id) - if len(tv.iv) == 0 or len(tv.ct) < 1: - return - cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) - cipher.update(tv.aad) - ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) - self.test_corrupt_decrypt(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def setUp(self): + def filter_tag(group): + return group["tagSize"] // 8 + + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aes_eax_test.json", + "Wycheproof EAX", + group_tag={"tag_size": filter_tag}, + ) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt EAX Test #" + str(tv.id) + + try: + cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) + except ValueError as e: + assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e) + return + + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt EAX Test #" + str(tv.id) + + try: + cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) + except ValueError as e: + assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e) + return + + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def test_corrupt_decrypt(self, tv): + self._id = "Wycheproof Corrupt Decrypt EAX Test #" + str(tv.id) + if len(tv.iv) == 0 or len(tv.ct) < 1: + return + cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) + cipher.update(tv.aad) + ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) + self.test_corrupt_decrypt(tv) class TestOtherCiphers(unittest.TestCase): + @classmethod + def create_test(cls, name, factory, key_size): + def test_template(self, factory=factory, key_size=key_size): + cipher = factory.new( + get_tag_random("cipher", key_size), + factory.MODE_EAX, + nonce=b"nonce", + ) + ct, mac = cipher.encrypt_and_digest(b"plaintext") - @classmethod - def create_test(cls, name, factory, key_size): - - def test_template(self, factory=factory, key_size=key_size): - cipher = factory.new(get_tag_random("cipher", key_size), - factory.MODE_EAX, - nonce=b"nonce") - ct, mac = cipher.encrypt_and_digest(b"plaintext") - - cipher = factory.new(get_tag_random("cipher", key_size), - factory.MODE_EAX, - nonce=b"nonce") - pt2 = cipher.decrypt_and_verify(ct, mac) + cipher = factory.new( + get_tag_random("cipher", key_size), + factory.MODE_EAX, + nonce=b"nonce", + ) + pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(b"plaintext", pt2) + self.assertEqual(b"plaintext", pt2) - setattr(cls, "test_" + name, test_template) + setattr(cls, "test_" + name, test_template) -from Cryptodome.Cipher import DES, DES3, ARC2, CAST, Blowfish +from Cryptodome.Cipher import DES, ARC2, CAST, Blowfish TestOtherCiphers.create_test("DES_" + str(DES.key_size), DES, DES.key_size) for ks in DES3.key_size: - TestOtherCiphers.create_test("DES3_" + str(ks), DES3, ks) + TestOtherCiphers.create_test("DES3_" + str(ks), DES3, ks) for ks in ARC2.key_size: - TestOtherCiphers.create_test("ARC2_" + str(ks), ARC2, ks) + TestOtherCiphers.create_test("ARC2_" + str(ks), ARC2, ks) for ks in CAST.key_size: - TestOtherCiphers.create_test("CAST_" + str(ks), CAST, ks) + TestOtherCiphers.create_test("CAST_" + str(ks), CAST, ks) for ks in Blowfish.key_size: - TestOtherCiphers.create_test("Blowfish_" + str(ks), Blowfish, ks) + TestOtherCiphers.create_test("Blowfish_" + str(ks), Blowfish, ks) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") - tests = [] - tests += list_test_cases(EaxTests) - tests += list_test_cases(EaxFSMTests) - tests += [ TestVectorsPaper() ] - tests += [ TestVectorsWycheproof(wycheproof_warnings) ] - tests += list_test_cases(TestOtherCiphers) - return tests + tests = [] + tests += list_test_cases(EaxTests) + tests += list_test_cases(EaxFSMTests) + tests += [TestVectorsPaper()] + tests += [TestVectorsWycheproof(wycheproof_warnings)] + tests += list_test_cases(TestOtherCiphers) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_GCM.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_GCM.py index ac8e7412..8f19663c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_GCM.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_GCM.py @@ -44,908 +44,1043 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class GcmTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # Nonce is optional (a random one will be created) - AES.new(self.key_128, AES.MODE_GCM) - - cipher = AES.new(self.key_128, AES.MODE_GCM, self.nonce_96) - ct = cipher.encrypt(self.data) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_GCM, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce can be of any length (but not empty) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_GCM, - nonce=b"") - - for x in range(1, 128): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=bchr(1) * x) - cipher.encrypt(bchr(1)) - - def test_block_size_128(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 15 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_GCM).nonce - nonce2 = AES.new(self.key_128, AES.MODE_GCM).nonce - self.assertEqual(len(nonce1), 16) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_GCM, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_GCM, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96, - use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - # Invalid MAC length - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_GCM, - nonce=self.nonce_96, mac_len=3) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_GCM, - nonce=self.nonce_96, mac_len=16+1) - - # Valid MAC length - for mac_len in range(5, 16 + 1): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96, - mac_len=mac_len) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), mac_len) - - # Default MAC length - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b"" - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b"" - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - data_ba = bytearray(self.data) - - cipher1 = AES.new(self.key_128, - AES.MODE_GCM, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) - tag = cipher1.digest() - - cipher2 = AES.new(key_ba, - AES.MODE_GCM, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_ba) - data_ba[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - del data_ba - - cipher4 = AES.new(key_ba, - AES.MODE_GCM, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - data_mv = memoryview(bytearray(self.data)) - - cipher1 = AES.new(self.key_128, - AES.MODE_GCM, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) - tag = cipher1.digest() - - cipher2 = AES.new(key_mv, - AES.MODE_GCM, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_mv) - data_mv[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - del data_mv - - cipher4 = AES.new(key_mv, - AES.MODE_GCM, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - tag = cipher.digest() - - output = bytearray(128) - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - res, tag_out = cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - self.assertEqual(tag, tag_out) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - res = cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - - def test_output_param_neg(self): - LEN_PT = 128 - - pt = b'5' * LEN_PT - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT) - - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # Nonce is optional (a random one will be created) + AES.new(self.key_128, AES.MODE_GCM) + + cipher = AES.new(self.key_128, AES.MODE_GCM, self.nonce_96) + ct = cipher.encrypt(self.data) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertEqual(ct, cipher.encrypt(self.data)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce can be of any length (but not empty) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce=b"", + ) + + for x in range(1, 128): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=bchr(1) * x) + cipher.encrypt(bchr(1)) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 15 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_GCM).nonce + nonce2 = AES.new(self.key_128, AES.MODE_GCM).nonce + self.assertEqual(len(nonce1), 16) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_GCM, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + # Invalid MAC length + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + mac_len=3, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + mac_len=16 + 1, + ) + + # Valid MAC length + for mac_len in range(5, 16 + 1): + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + mac_len=mac_len, + ) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), mac_len) + + # Default MAC length + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b"" + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b"" + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + data_ba = bytearray(self.data) + + cipher1 = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + tag = cipher1.digest() + + cipher2 = AES.new( + key_ba, + AES.MODE_GCM, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + data_ba[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + del data_ba + + cipher4 = AES.new( + key_ba, + AES.MODE_GCM, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher4.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + data_mv = memoryview(bytearray(self.data)) + + cipher1 = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + tag = cipher1.digest() + + cipher2 = AES.new( + key_mv, + AES.MODE_GCM, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + data_mv[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + del data_mv + + cipher4 = AES.new( + key_mv, + AES.MODE_GCM, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher4.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + tag = cipher.digest() + + output = bytearray(128) + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + res, tag_out = cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + self.assertEqual(tag, tag_out) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + res = cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + LEN_PT = 128 + + pt = b"5" * LEN_PT + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * LEN_PT) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * LEN_PT) + + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) class GcmFSMTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - # Verify path INIT->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.update(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - # Verify path INIT->UPDATE->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.update(self.data) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - for method_name in "encrypt", "decrypt": - for auth_data in (None, b"333", self.data, - self.data + b"3"): - if auth_data is None: - assoc_len = None - else: - assoc_len = len(auth_data) - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data) - method(self.data) - method(self.data) - method(self.data) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(self.data) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(self.data) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(self.data) - ct, mac = cipher.encrypt_and_digest(self.data) - - # decrypt_and_verify - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(self.data) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data, pt) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data) - getattr(cipher, method1_name)(self.data) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.encrypt(self.data) - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + # Verify path INIT->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.update(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + # Verify path INIT->UPDATE->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.update(self.data) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b"333", + self.data, + self.data + b"3", + ): + if auth_data is None: + assoc_len = None + else: + assoc_len = len(auth_data) + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data) + method(self.data) + method(self.data) + method(self.data) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(self.data) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(self.data) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(self.data) + ct, mac = cipher.encrypt_and_digest(self.data) + + # decrypt_and_verify + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(self.data) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data, pt) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data) + getattr(cipher, method1_name)(self.data) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.encrypt(self.data) + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) class TestVectors(unittest.TestCase): - """Class exercising the GCM test vectors found in - http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf""" - - # List of test vectors, each made up of: - # - authenticated data - # - plaintext - # - ciphertext - # - MAC - # - AES key - # - nonce - test_vectors_hex = [ - ( - '', - '', - '', - '58e2fccefa7e3061367f1d57a4e7455a', - '00000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - '00000000000000000000000000000000', - '0388dace60b6a392f328c2b971b2fe78', - 'ab6e47d42cec13bdf53a67b21257bddf', - '00000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', - '42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' + - '21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985', - '4d5c2af327cd64a62cf35abd2ba6fab4', - 'feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' + - '21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091', - '5bc94fbc3221a5db94fae95ae7121a47', - 'feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423' + - '73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598', - '3612d2e79e3b0785561be14aaca2fccb', - 'feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbad' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7' + - '01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5', - '619cc5aefffe0bfa462af43c1699d050', - 'feffe9928665731c6d6a8f9467308308', - '9313225df88406e555909c5aff5269aa' + - '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' + - '16aedbf5a0de6a57a637b39b' - ), - ( - '', - '', - '', - 'cd33b28ac773f74ba00ed1f312572435', - '000000000000000000000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - '00000000000000000000000000000000', - '98e7247c07f0fe411c267e4384b0f600', - '2ff58d80033927ab8ef4d4587514f0fb', - '000000000000000000000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', - '3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' + - '7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256', - '9924a7c8587336bfb118024db8674a14', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' + - '7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710', - '2519498e80f1478f37ba55bd6d27618c', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057' + - 'fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7', - '65dcc57fcf623a24094fcca40d3533f8', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c', - 'cafebabefacedbad' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - 'd27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45' + - '81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b', - 'dcf566ff291c25bbb8568fc3d376a6d9', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c', - '9313225df88406e555909c5aff5269aa' + - '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' + - '16aedbf5a0de6a57a637b39b' - ), - ( - '', - '', - '', - '530f8afbc74536b9a963b4f1c4cb738b', - '0000000000000000000000000000000000000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - '00000000000000000000000000000000', - 'cea7403d4d606b6e074ec5d3baf39d18', - 'd0d1c8a799996bf0265b98b5d48ab919', - '0000000000000000000000000000000000000000000000000000000000000000', - '000000000000000000000000' - ), - ( '', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', - '522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' + - '8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad', - 'b094dac5d93471bdec1a502270e3cc6c', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' + - '8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662', - '76fc6ece0f4e1768cddf8853bb2d551b', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - 'c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0' + - 'feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f', - '3a337dbf46a792c45e454913fe2ea8f2', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbad' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4' + - '0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f', - 'a44a8266ee1c8eb0c8b5d4cf5ae9f19a', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', - '9313225df88406e555909c5aff5269aa' + - '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' + - '16aedbf5a0de6a57a637b39b' - ) - ] - - test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - - # Encrypt - cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Class exercising the GCM test vectors found in + http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf""" + + # List of test vectors, each made up of: + # - authenticated data + # - plaintext + # - ciphertext + # - MAC + # - AES key + # - nonce + test_vectors_hex = [ + ( + "", + "", + "", + "58e2fccefa7e3061367f1d57a4e7455a", + "00000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "00000000000000000000000000000000", + "0388dace60b6a392f328c2b971b2fe78", + "ab6e47d42cec13bdf53a67b21257bddf", + "00000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985", + "4d5c2af327cd64a62cf35abd2ba6fab4", + "feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091", + "5bc94fbc3221a5db94fae95ae7121a47", + "feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423" + + "73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598", + "3612d2e79e3b0785561be14aaca2fccb", + "feffe9928665731c6d6a8f9467308308", + "cafebabefacedbad", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7" + + "01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5", + "619cc5aefffe0bfa462af43c1699d050", + "feffe9928665731c6d6a8f9467308308", + "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b", + ), + ( + "", + "", + "", + "cd33b28ac773f74ba00ed1f312572435", + "000000000000000000000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "00000000000000000000000000000000", + "98e7247c07f0fe411c267e4384b0f600", + "2ff58d80033927ab8ef4d4587514f0fb", + "000000000000000000000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c" + + "7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256", + "9924a7c8587336bfb118024db8674a14", + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c" + + "7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710", + "2519498e80f1478f37ba55bd6d27618c", + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057" + + "fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7", + "65dcc57fcf623a24094fcca40d3533f8", + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbad", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45" + + "81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b", + "dcf566ff291c25bbb8568fc3d376a6d9", + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b", + ), + ( + "", + "", + "", + "530f8afbc74536b9a963b4f1c4cb738b", + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "00000000000000000000000000000000", + "cea7403d4d606b6e074ec5d3baf39d18", + "d0d1c8a799996bf0265b98b5d48ab919", + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa" + + "8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad", + "b094dac5d93471bdec1a502270e3cc6c", + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa" + + "8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662", + "76fc6ece0f4e1768cddf8853bb2d551b", + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0" + + "feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f", + "3a337dbf46a792c45e454913fe2ea8f2", + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbad", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4" + + "0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f", + "a44a8266ee1c8eb0c8b5d4cf5ae9f19a", + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b", + ), + ] + + test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsGueronKrasnov(unittest.TestCase): - """Class exercising the GCM test vectors found in - 'The fragility of AES-GCM authentication algorithm', Gueron, Krasnov - https://eprint.iacr.org/2013/157.pdf""" - - def test_1(self): - key = unhexlify("3da6c536d6295579c0959a7043efb503") - iv = unhexlify("2b926197d34e091ef722db94") - aad = unhexlify("00000000000000000000000000000000" + - "000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f") - digest = unhexlify("69dd586555ce3fcc89663801a71d957b") - - cipher = AES.new(key, AES.MODE_GCM, iv).update(aad) - self.assertEqual(digest, cipher.digest()) - - def test_2(self): - key = unhexlify("843ffcf5d2b72694d19ed01d01249412") - iv = unhexlify("dbcca32ebf9b804617c3aa9e") - aad = unhexlify("00000000000000000000000000000000" + - "101112131415161718191a1b1c1d1e1f") - pt = unhexlify("000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f" + - "404142434445464748494a4b4c4d4e4f") - ct = unhexlify("6268c6fa2a80b2d137467f092f657ac0" + - "4d89be2beaa623d61b5a868c8f03ff95" + - "d3dcee23ad2f1ab3a6c80eaf4b140eb0" + - "5de3457f0fbc111a6b43d0763aa422a3" + - "013cf1dc37fe417d1fbfc449b75d4cc5") - digest = unhexlify("3b629ccfbc1119b7319e1dce2cd6fd6d") - - cipher = AES.new(key, AES.MODE_GCM, iv).update(aad) - ct2, digest2 = cipher.encrypt_and_digest(pt) - - self.assertEqual(ct, ct2) - self.assertEqual(digest, digest2) + """Class exercising the GCM test vectors found in + 'The fragility of AES-GCM authentication algorithm', Gueron, Krasnov + https://eprint.iacr.org/2013/157.pdf""" + + def test_1(self): + key = unhexlify("3da6c536d6295579c0959a7043efb503") + iv = unhexlify("2b926197d34e091ef722db94") + aad = unhexlify( + "00000000000000000000000000000000" + + "000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f", + ) + digest = unhexlify("69dd586555ce3fcc89663801a71d957b") + + cipher = AES.new(key, AES.MODE_GCM, iv).update(aad) + self.assertEqual(digest, cipher.digest()) + + def test_2(self): + key = unhexlify("843ffcf5d2b72694d19ed01d01249412") + iv = unhexlify("dbcca32ebf9b804617c3aa9e") + aad = unhexlify( + "00000000000000000000000000000000" + "101112131415161718191a1b1c1d1e1f", + ) + pt = unhexlify( + "000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f", + ) + ct = unhexlify( + "6268c6fa2a80b2d137467f092f657ac0" + + "4d89be2beaa623d61b5a868c8f03ff95" + + "d3dcee23ad2f1ab3a6c80eaf4b140eb0" + + "5de3457f0fbc111a6b43d0763aa422a3" + + "013cf1dc37fe417d1fbfc449b75d4cc5", + ) + digest = unhexlify("3b629ccfbc1119b7319e1dce2cd6fd6d") + + cipher = AES.new(key, AES.MODE_GCM, iv).update(aad) + ct2, digest2 = cipher.encrypt_and_digest(pt) + + self.assertEqual(ct, ct2) + self.assertEqual(digest, digest2) class NISTTestVectorsGCM(unittest.TestCase): - - def __init__(self, a): - self.use_clmul = True - unittest.TestCase.__init__(self, a) + def __init__(self, a): + self.use_clmul = True + unittest.TestCase.__init__(self, a) class NISTTestVectorsGCM_no_clmul(unittest.TestCase): + def __init__(self, a): + self.use_clmul = False + unittest.TestCase.__init__(self, a) + + +test_vectors_nist = ( + load_test_vectors( + ("Cipher", "AES"), + "gcmDecrypt128.rsp", + "GCM decrypt", + {"count": lambda x: int(x)}, + ) + or [] +) + +test_vectors_nist += ( + load_test_vectors( + ("Cipher", "AES"), + "gcmEncryptExtIV128.rsp", + "GCM encrypt", + {"count": lambda x: int(x)}, + ) + or [] +) - def __init__(self, a): - self.use_clmul = False - unittest.TestCase.__init__(self, a) - - -test_vectors_nist = load_test_vectors( - ("Cipher", "AES"), - "gcmDecrypt128.rsp", - "GCM decrypt", - {"count": lambda x: int(x)}) or [] +for idx, tv in enumerate(test_vectors_nist): + # The test vector file contains some directive lines + if isinstance(tv, str): + continue + + def single_test(self, tv=tv): + self.description = tv.desc + cipher = AES.new( + tv.key, + AES.MODE_GCM, + nonce=tv.iv, + mac_len=len(tv.tag), + use_clmul=self.use_clmul, + ) + cipher.update(tv.aad) + if "FAIL" in tv.others: + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + tv.ct, + tv.tag, + ) + else: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + self.assertEqual(pt, tv.pt) + + setattr(NISTTestVectorsGCM, "test_%d" % idx, single_test) + setattr(NISTTestVectorsGCM_no_clmul, "test_%d" % idx, single_test) -test_vectors_nist += load_test_vectors( - ("Cipher", "AES"), - "gcmEncryptExtIV128.rsp", - "GCM encrypt", - {"count": lambda x: int(x)}) or [] -for idx, tv in enumerate(test_vectors_nist): +class TestVectorsWycheproof(unittest.TestCase): + def __init__(self, wycheproof_warnings, **extra_params): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._extra_params = extra_params + self._id = "None" + + def setUp(self): + def filter_tag(group): + return group["tagSize"] // 8 + + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aes_gcm_test.json", + "Wycheproof GCM", + group_tag={"tag_size": filter_tag}, + ) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt GCM Test #" + str(tv.id) + + try: + cipher = AES.new( + tv.key, + AES.MODE_GCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + except ValueError as e: + if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e): + return + raise e + + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt GCM Test #" + str(tv.id) + + try: + cipher = AES.new( + tv.key, + AES.MODE_GCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + except ValueError as e: + if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e): + return + raise e + + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def test_corrupt_decrypt(self, tv): + self._id = "Wycheproof Corrupt Decrypt GCM Test #" + str(tv.id) + if len(tv.iv) == 0 or len(tv.ct) < 1: + return + cipher = AES.new( + tv.key, + AES.MODE_GCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + cipher.update(tv.aad) + ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) + self.test_corrupt_decrypt(tv) - # The test vector file contains some directive lines - if isinstance(tv, str): - continue - def single_test(self, tv=tv): +class TestVariableLength(unittest.TestCase): + def __init__(self, **extra_params): + unittest.TestCase.__init__(self) + self._extra_params = extra_params - self.description = tv.desc - cipher = AES.new(tv.key, AES.MODE_GCM, nonce=tv.iv, - mac_len=len(tv.tag), use_clmul=self.use_clmul) - cipher.update(tv.aad) - if "FAIL" in tv.others: - self.assertRaises(ValueError, cipher.decrypt_and_verify, - tv.ct, tv.tag) - else: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - self.assertEqual(pt, tv.pt) + def runTest(self): + key = b"0" * 16 + h = SHA256.new() - setattr(NISTTestVectorsGCM, "test_%d" % idx, single_test) - setattr(NISTTestVectorsGCM_no_clmul, "test_%d" % idx, single_test) + for length in range(160): + nonce = "{0:04d}".format(length).encode("utf-8") + data = bchr(length) * length + cipher = AES.new(key, AES.MODE_GCM, nonce=nonce, **self._extra_params) + ct, tag = cipher.encrypt_and_digest(data) + h.update(ct) + h.update(tag) + self.assertEqual(h.hexdigest(), "7b7eb1ffbe67a2e53a912067c0ec8e62ebc7ce4d83490ea7426941349811bdf4") -class TestVectorsWycheproof(unittest.TestCase): - def __init__(self, wycheproof_warnings, **extra_params): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._extra_params = extra_params - self._id = "None" - - def setUp(self): - - def filter_tag(group): - return group['tagSize'] // 8 - - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aes_gcm_test.json", - "Wycheproof GCM", - group_tag={'tag_size': filter_tag}) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt GCM Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - except ValueError as e: - if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e): - return - raise e - - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt GCM Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - except ValueError as e: - if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e): - return - raise e - - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def test_corrupt_decrypt(self, tv): - self._id = "Wycheproof Corrupt Decrypt GCM Test #" + str(tv.id) - if len(tv.iv) == 0 or len(tv.ct) < 1: - return - cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - cipher.update(tv.aad) - ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) - self.test_corrupt_decrypt(tv) +def get_tests(config={}): + from Cryptodome.Util import _cpu_features + wycheproof_warnings = config.get("wycheproof_warnings") -class TestVariableLength(unittest.TestCase): + tests = [] + tests += list_test_cases(GcmTests) + tests += list_test_cases(GcmFSMTests) + tests += [TestVectors()] + tests += [TestVectorsWycheproof(wycheproof_warnings)] + tests += list_test_cases(TestVectorsGueronKrasnov) + tests += [TestVariableLength()] + if config.get("slow_tests"): + tests += list_test_cases(NISTTestVectorsGCM) - def __init__(self, **extra_params): - unittest.TestCase.__init__(self) - self._extra_params = extra_params + if _cpu_features.have_clmul(): + tests += [TestVectorsWycheproof(wycheproof_warnings, use_clmul=False)] + tests += [TestVariableLength(use_clmul=False)] + if config.get("slow_tests"): + tests += list_test_cases(NISTTestVectorsGCM_no_clmul) + else: + print("Skipping test of PCLMULDQD in AES GCM") - def runTest(self): - key = b'0' * 16 - h = SHA256.new() + return tests - for length in range(160): - nonce = '{0:04d}'.format(length).encode('utf-8') - data = bchr(length) * length - cipher = AES.new(key, AES.MODE_GCM, nonce=nonce, **self._extra_params) - ct, tag = cipher.encrypt_and_digest(data) - h.update(ct) - h.update(tag) - self.assertEqual(h.hexdigest(), "7b7eb1ffbe67a2e53a912067c0ec8e62ebc7ce4d83490ea7426941349811bdf4") +if __name__ == "__main__": + def suite(): + unittest.TestSuite(get_tests()) -def get_tests(config={}): - from Cryptodome.Util import _cpu_features - - wycheproof_warnings = config.get('wycheproof_warnings') - - tests = [] - tests += list_test_cases(GcmTests) - tests += list_test_cases(GcmFSMTests) - tests += [TestVectors()] - tests += [TestVectorsWycheproof(wycheproof_warnings)] - tests += list_test_cases(TestVectorsGueronKrasnov) - tests += [TestVariableLength()] - if config.get('slow_tests'): - tests += list_test_cases(NISTTestVectorsGCM) - - if _cpu_features.have_clmul(): - tests += [TestVectorsWycheproof(wycheproof_warnings, use_clmul=False)] - tests += [TestVariableLength(use_clmul=False)] - if config.get('slow_tests'): - tests += list_test_cases(NISTTestVectorsGCM_no_clmul) - else: - print("Skipping test of PCLMULDQD in AES GCM") - - return tests - - -if __name__ == '__main__': - def suite(): - unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_KW.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_KW.py index 4b530cf8..d7eb814d 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_KW.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_KW.py @@ -7,169 +7,183 @@ class KW_Tests(unittest.TestCase): - - # From RFC3394 - tvs = [ - ("000102030405060708090A0B0C0D0E0F", - "00112233445566778899AABBCCDDEEFF", - "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5"), - ("000102030405060708090A0B0C0D0E0F1011121314151617", - "00112233445566778899AABBCCDDEEFF", - "96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D"), - ("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "00112233445566778899AABBCCDDEEFF", - "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7"), - ("000102030405060708090A0B0C0D0E0F1011121314151617", - "00112233445566778899AABBCCDDEEFF0001020304050607", - "031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2"), - ("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "00112233445566778899AABBCCDDEEFF0001020304050607", - "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1"), - ("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F", - "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21"), - ] - - def test_rfc3394(self): - for tv in self.tvs: - kek, pt, ct = [bytes.fromhex(x) for x in tv] - - cipher = AES.new(kek, AES.MODE_KW) - ct2 = cipher.seal(pt) - - self.assertEqual(ct, ct2) - - cipher = AES.new(kek, AES.MODE_KW) - pt2 = cipher.unseal(ct) - self.assertEqual(pt, pt2) - - def test_neg1(self): - - cipher = AES.new(b'-' * 16, AES.MODE_KW) - - with self.assertRaises(ValueError): - cipher.seal(b'') - - with self.assertRaises(ValueError): - cipher.seal(b'8' * 17) - - def test_neg2(self): - - cipher = AES.new(b'-' * 16, AES.MODE_KW) - ct = bytearray(cipher.seal(b'7' * 16)) - - cipher = AES.new(b'-' * 16, AES.MODE_KW) - cipher.unseal(ct) - - cipher = AES.new(b'-' * 16, AES.MODE_KW) - ct[0] ^= 0xFF - with self.assertRaises(ValueError): - cipher.unseal(ct) + # From RFC3394 + tvs = [ + ( + "000102030405060708090A0B0C0D0E0F", + "00112233445566778899AABBCCDDEEFF", + "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5", + ), + ( + "000102030405060708090A0B0C0D0E0F1011121314151617", + "00112233445566778899AABBCCDDEEFF", + "96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D", + ), + ( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "00112233445566778899AABBCCDDEEFF", + "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7", + ), + ( + "000102030405060708090A0B0C0D0E0F1011121314151617", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2", + ), + ( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1", + ), + ( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F", + "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21", + ), + ] + + def test_rfc3394(self): + for tv in self.tvs: + kek, pt, ct = [bytes.fromhex(x) for x in tv] + + cipher = AES.new(kek, AES.MODE_KW) + ct2 = cipher.seal(pt) + + self.assertEqual(ct, ct2) + + cipher = AES.new(kek, AES.MODE_KW) + pt2 = cipher.unseal(ct) + self.assertEqual(pt, pt2) + + def test_neg1(self): + cipher = AES.new(b"-" * 16, AES.MODE_KW) + + with self.assertRaises(ValueError): + cipher.seal(b"") + + with self.assertRaises(ValueError): + cipher.seal(b"8" * 17) + + def test_neg2(self): + cipher = AES.new(b"-" * 16, AES.MODE_KW) + ct = bytearray(cipher.seal(b"7" * 16)) + + cipher = AES.new(b"-" * 16, AES.MODE_KW) + cipher.unseal(ct) + + cipher = AES.new(b"-" * 16, AES.MODE_KW) + ct[0] ^= 0xFF + with self.assertRaises(ValueError): + cipher.unseal(ct) class KW_Wycheproof(unittest.TestCase): - - def setUp(self): - self.vectors = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "kw_test.json", - "Wycheproof tests for KW") - - def test_wycheproof(self): - - if not self.vectors: - self.skipTest("No test vectors available") - - for vector in self.vectors: - with self.subTest(testId=vector.id): - cipher = AES.new(vector.key, AES.MODE_KW) - - try: - cipher.seal(vector.msg) - except ValueError: - if vector.valid: - raise - continue - - cipher = AES.new(vector.key, AES.MODE_KW) - try: - pt = cipher.unseal(vector.ct) - except ValueError: - if vector.valid: - raise - continue - - self.assertEqual(pt, vector.msg) + def setUp(self): + self.vectors = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "kw_test.json", + "Wycheproof tests for KW", + ) + + def test_wycheproof(self): + if not self.vectors: + self.skipTest("No test vectors available") + + for vector in self.vectors: + with self.subTest(testId=vector.id): + cipher = AES.new(vector.key, AES.MODE_KW) + + try: + cipher.seal(vector.msg) + except ValueError: + if vector.valid: + raise + continue + + cipher = AES.new(vector.key, AES.MODE_KW) + try: + pt = cipher.unseal(vector.ct) + except ValueError: + if vector.valid: + raise + continue + + self.assertEqual(pt, vector.msg) class KWP_Tests(unittest.TestCase): + tvs = [ + ( + "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8", + "c37b7e6492584340bed12207808941155068f738", + "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a", + ), + ( + "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8", + "466f7250617369", + "afbeb0f07dfbf5419200f2ccb50bb24f", + ), + ] - tvs = [ - ("5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8", - "c37b7e6492584340bed12207808941155068f738", - "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a"), - ("5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8", - "466f7250617369", - "afbeb0f07dfbf5419200f2ccb50bb24f"), - ] + def test_rfc5649(self): + for tv in self.tvs: + kek, pt, ct = [bytes.fromhex(x) for x in tv] - def test_rfc5649(self): - for tv in self.tvs: - kek, pt, ct = [bytes.fromhex(x) for x in tv] + cipher = AES.new(kek, AES.MODE_KWP) + ct2 = cipher.seal(pt) - cipher = AES.new(kek, AES.MODE_KWP) - ct2 = cipher.seal(pt) + self.assertEqual(ct, ct2) - self.assertEqual(ct, ct2) - - cipher = AES.new(kek, AES.MODE_KWP) - pt2 = cipher.unseal(ct) - self.assertEqual(pt, pt2) + cipher = AES.new(kek, AES.MODE_KWP) + pt2 = cipher.unseal(ct) + self.assertEqual(pt, pt2) class KWP_Wycheproof(unittest.TestCase): + def setUp(self): + self.vectors = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "kwp_test.json", + "Wycheproof tests for KWP", + ) + + def test_wycheproof(self): + if not self.vectors: + self.skipTest("No test vectors available") + + for vector in self.vectors: + with self.subTest(testId=vector.id): + cipher = AES.new(vector.key, AES.MODE_KWP) + + try: + cipher.seal(vector.msg) + except ValueError: + if vector.valid and not vector.warning: + raise + continue + + cipher = AES.new(vector.key, AES.MODE_KWP) + try: + pt = cipher.unseal(vector.ct) + except ValueError: + if vector.valid and not vector.warning: + raise + continue + + self.assertEqual(pt, vector.msg) - def setUp(self): - self.vectors = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "kwp_test.json", - "Wycheproof tests for KWP") - - def test_wycheproof(self): - - if not self.vectors: - self.skipTest("No test vectors available") - for vector in self.vectors: - with self.subTest(testId=vector.id): - cipher = AES.new(vector.key, AES.MODE_KWP) - - try: - cipher.seal(vector.msg) - except ValueError: - if vector.valid and not vector.warning: - raise - continue +def get_tests(config={}): + tests = [] + tests += list_test_cases(KW_Tests) + tests += list_test_cases(KWP_Tests) + tests += list_test_cases(KW_Wycheproof) + tests += list_test_cases(KWP_Wycheproof) + return tests - cipher = AES.new(vector.key, AES.MODE_KWP) - try: - pt = cipher.unseal(vector.ct) - except ValueError: - if vector.valid and not vector.warning: - raise - continue - self.assertEqual(pt, vector.msg) +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -def get_tests(config={}): - tests = [] - tests += list_test_cases(KW_Tests) - tests += list_test_cases(KWP_Tests) - tests += list_test_cases(KW_Wycheproof) - tests += list_test_cases(KWP_Wycheproof) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OCB.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OCB.py index 1f2ffbc5..ec3799a5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OCB.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OCB.py @@ -41,805 +41,922 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class OcbTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct, mac = cipher.encrypt_and_digest(pt) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # Nonce is optional - AES.new(self.key_128, AES.MODE_OCB) - - cipher = AES.new(self.key_128, AES.MODE_OCB, self.nonce_96) - ct = cipher.encrypt(self.data) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_OCB, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce cannot be empty - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, - nonce=b("")) - - # nonce can be up to 15 bytes long - for length in range(1, 16): - AES.new(self.key_128, AES.MODE_OCB, nonce=self.data[:length]) - - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, - nonce=self.data) - - def test_block_size_128(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - # By default, a 15 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce - nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce - self.assertEqual(len(nonce1), 15) - self.assertNotEqual(nonce1, nonce2) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 15 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce - nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce - self.assertEqual(len(nonce1), 15) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_OCB, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_OCB, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96, - use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - result = getattr(cipher, func)(b("")) - self.assertEqual(result, b("")) - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.encrypt(b("xyz")) - self.assertRaises(TypeError, cipher.decrypt, b("xyz")) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.decrypt(b("xyz")) - self.assertRaises(TypeError, cipher.encrypt, b("xyz")) - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - # Invalid MAC length - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, - nonce=self.nonce_96, mac_len=7) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, - nonce=self.nonce_96, mac_len=16+1) - - # Valid MAC length - for mac_len in range(8, 16 + 1): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96, - mac_len=mac_len) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), mac_len) - - # Default MAC length - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b("") - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - pt2 += cipher.decrypt() - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b("") - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - ct2 += cipher.encrypt() - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - data_ba = bytearray(self.data) - - cipher1 = AES.new(self.key_128, - AES.MODE_OCB, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) + cipher1.encrypt() - tag = cipher1.digest() - - cipher2 = AES.new(key_ba, - AES.MODE_OCB, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_ba) + cipher2.encrypt() - data_ba[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - del data_ba - - cipher4 = AES.new(key_ba, - AES.MODE_OCB, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - data_mv = memoryview(bytearray(self.data)) - - cipher1 = AES.new(self.key_128, - AES.MODE_OCB, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) + cipher1.encrypt() - tag = cipher1.digest() - - cipher2 = AES.new(key_mv, - AES.MODE_OCB, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_mv) + cipher2.encrypt() - data_mv[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - del data_mv - - cipher4 = AES.new(key_mv, - AES.MODE_OCB, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) - - self.assertEqual(self.data, pt_test) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct, mac = cipher.encrypt_and_digest(pt) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # Nonce is optional + AES.new(self.key_128, AES.MODE_OCB) + + cipher = AES.new(self.key_128, AES.MODE_OCB, self.nonce_96) + ct = cipher.encrypt(self.data) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertEqual(ct, cipher.encrypt(self.data)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce cannot be empty + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=b(""), + ) + + # nonce can be up to 15 bytes long + for length in range(1, 16): + AES.new(self.key_128, AES.MODE_OCB, nonce=self.data[:length]) + + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=self.data, + ) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + # By default, a 15 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce + nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce + self.assertEqual(len(nonce1), 15) + self.assertNotEqual(nonce1, nonce2) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 15 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce + nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce + self.assertEqual(len(nonce1), 15) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_OCB, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + result = getattr(cipher, func)(b("")) + self.assertEqual(result, b("")) + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.encrypt(b("xyz")) + self.assertRaises(TypeError, cipher.decrypt, b("xyz")) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.decrypt(b("xyz")) + self.assertRaises(TypeError, cipher.encrypt, b("xyz")) + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + # Invalid MAC length + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + mac_len=7, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + mac_len=16 + 1, + ) + + # Valid MAC length + for mac_len in range(8, 16 + 1): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + mac_len=mac_len, + ) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), mac_len) + + # Default MAC length + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b("") + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + pt2 += cipher.decrypt() + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b("") + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + ct2 += cipher.encrypt() + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + data_ba = bytearray(self.data) + + cipher1 = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + cipher1.encrypt() + tag = cipher1.digest() + + cipher2 = AES.new( + key_ba, + AES.MODE_OCB, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + cipher2.encrypt() + data_ba[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + del data_ba + + cipher4 = AES.new( + key_ba, + AES.MODE_OCB, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher4.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + data_mv = memoryview(bytearray(self.data)) + + cipher1 = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + cipher1.encrypt() + tag = cipher1.digest() + + cipher2 = AES.new( + key_mv, + AES.MODE_OCB, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + cipher2.encrypt() + data_mv[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + del data_mv + + cipher4 = AES.new( + key_mv, + AES.MODE_OCB, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher4.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) + + self.assertEqual(self.data, pt_test) class OcbFSMTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->ENCRYPT(NONE)->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - ct += cipher.encrypt() - mac = cipher.digest() - - # Verify path INIT->DECRYPT->DECRYPT(NONCE)->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.decrypt() - cipher.verify(mac) - - def test_invalid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - self.assertRaises(TypeError, cipher.digest) - - # Verify path INIT->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.decrypt(ct) - self.assertRaises(TypeError, cipher.verify) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - # Verify path INIT->UPDATE->ENCRYPT->ENCRYPT(NONE)->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - ct = cipher.encrypt(self.data) - ct += cipher.encrypt() - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->DECRYPT(NONE)->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.decrypt(ct) - cipher.decrypt() - cipher.verify(mac) - - # Verify path INIT->UPDATE->ENCRYPT->ENCRYPT_AND_DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - ct1 = cipher.encrypt(self.data[:2]) - ct2, mac = cipher.encrypt_and_digest(self.data[2:]) - - # Verify path INIT->UPDATE->DECRYPT->DECRYPT_AND_VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.decrypt(ct1) - cipher.decrypt_and_verify(ct2, mac) - - def test_invalid_encrypt_after_final(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.encrypt(self.data) - cipher.encrypt() - self.assertRaises(TypeError, cipher.encrypt, self.data) - - def test_invalid_decrypt_after_final(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.decrypt(self.data) - cipher.decrypt() - self.assertRaises(TypeError, cipher.decrypt, self.data) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - for method_name in "encrypt", "decrypt": - for auth_data in (None, b("333"), self.data, - self.data + b("3")): - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data) - method(self.data) - method(self.data) - method(self.data) - method() - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(self.data) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(self.data) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(self.data) - ct, mac = cipher.encrypt_and_digest(self.data) - - # decrypt_and_verify - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(self.data) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data, pt) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data) - getattr(cipher, method1_name)(self.data) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.encrypt(self.data) - cipher.encrypt() - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - ct += cipher.encrypt() - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.decrypt() - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->ENCRYPT(NONE)->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data) + ct += cipher.encrypt() + mac = cipher.digest() + + # Verify path INIT->DECRYPT->DECRYPT(NONCE)->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.decrypt() + cipher.verify(mac) + + def test_invalid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data) + self.assertRaises(TypeError, cipher.digest) + + # Verify path INIT->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + self.assertRaises(TypeError, cipher.verify) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + # Verify path INIT->UPDATE->ENCRYPT->ENCRYPT(NONE)->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + ct = cipher.encrypt(self.data) + ct += cipher.encrypt() + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->DECRYPT(NONE)->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.decrypt(ct) + cipher.decrypt() + cipher.verify(mac) + + # Verify path INIT->UPDATE->ENCRYPT->ENCRYPT_AND_DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + ct1 = cipher.encrypt(self.data[:2]) + ct2, mac = cipher.encrypt_and_digest(self.data[2:]) + + # Verify path INIT->UPDATE->DECRYPT->DECRYPT_AND_VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.decrypt(ct1) + cipher.decrypt_and_verify(ct2, mac) + + def test_invalid_encrypt_after_final(self): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.encrypt(self.data) + cipher.encrypt() + self.assertRaises(TypeError, cipher.encrypt, self.data) + + def test_invalid_decrypt_after_final(self): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.decrypt(self.data) + cipher.decrypt() + self.assertRaises(TypeError, cipher.decrypt, self.data) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b("333"), + self.data, + self.data + b("3"), + ): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data) + method(self.data) + method(self.data) + method(self.data) + method() + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(self.data) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(self.data) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(self.data) + ct, mac = cipher.encrypt_and_digest(self.data) + + # decrypt_and_verify + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(self.data) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data, pt) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data) + getattr(cipher, method1_name)(self.data) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.encrypt(self.data) + cipher.encrypt() + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + ct = cipher.encrypt(self.data) + ct += cipher.encrypt() + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.decrypt(ct) + cipher.decrypt() + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) def algo_rfc7253(keylen, taglen, noncelen): - """Implement the algorithm at page 18 of RFC 7253""" + """Implement the algorithm at page 18 of RFC 7253""" - key = bchr(0) * (keylen // 8 - 1) + bchr(taglen) - C = b"" + key = bchr(0) * (keylen // 8 - 1) + bchr(taglen) + C = b"" - for i in range(128): - S = bchr(0) * i + for i in range(128): + S = bchr(0) * i - N = long_to_bytes(3 * i + 1, noncelen // 8) - cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) - cipher.update(S) - C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() + N = long_to_bytes(3 * i + 1, noncelen // 8) + cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) + cipher.update(S) + C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() - N = long_to_bytes(3 * i + 2, noncelen // 8) - cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) - C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() + N = long_to_bytes(3 * i + 2, noncelen // 8) + cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) + C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() - N = long_to_bytes(3 * i + 3, noncelen // 8) - cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) - cipher.update(S) - C += cipher.encrypt() + cipher.digest() + N = long_to_bytes(3 * i + 3, noncelen // 8) + cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) + cipher.update(S) + C += cipher.encrypt() + cipher.digest() - N = long_to_bytes(385, noncelen // 8) - cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) - cipher.update(C) - return cipher.encrypt() + cipher.digest() + N = long_to_bytes(385, noncelen // 8) + cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) + cipher.update(C) + return cipher.encrypt() + cipher.digest() class OcbRfc7253Test(unittest.TestCase): - - # Tuple with - # - nonce - # - authenticated data - # - plaintext - # - ciphertext and 16 byte MAC tag - tv1_key = "000102030405060708090A0B0C0D0E0F" - tv1 = ( - ( - "BBAA99887766554433221100", - "", - "", - "785407BFFFC8AD9EDCC5520AC9111EE6" - ), - ( - "BBAA99887766554433221101", - "0001020304050607", - "0001020304050607", - "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009" - ), - ( - "BBAA99887766554433221102", - "0001020304050607", - "", - "81017F8203F081277152FADE694A0A00" - ), - ( - "BBAA99887766554433221103", - "", - "0001020304050607", - "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9" - ), - ( - "BBAA99887766554433221104", - "000102030405060708090A0B0C0D0E0F", - "000102030405060708090A0B0C0D0E0F", - "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5" - "701C1CCEC8FC3358" - ), - ( - "BBAA99887766554433221105", - "000102030405060708090A0B0C0D0E0F", - "", - "8CF761B6902EF764462AD86498CA6B97" - ), - ( - "BBAA99887766554433221106", - "", - "000102030405060708090A0B0C0D0E0F", - "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436B" - "DF06D8FA1ECA343D" - ), - ( - "BBAA99887766554433221107", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "1CA2207308C87C010756104D8840CE1952F09673A448A122" - "C92C62241051F57356D7F3C90BB0E07F" - ), - ( - "BBAA99887766554433221108", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "", - "6DC225A071FC1B9F7C69F93B0F1E10DE" - ), - ( - "BBAA99887766554433221109", - "", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3C" - "E725F32494B9F914D85C0B1EB38357FF" - ), - ( - "BBAA9988776655443322110A", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F", - "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DE" - "AFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240" - ), - ( - "BBAA9988776655443322110B", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F", - "", - "FE80690BEE8A485D11F32965BC9D2A32" - ), - ( - "BBAA9988776655443322110C", - "", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F", - "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF4" - "6040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF" - ), - ( - "BBAA9988776655443322110D", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "D5CA91748410C1751FF8A2F618255B68A0A12E093FF45460" - "6E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483" - "A7035490C5769E60" - ), - ( - "BBAA9988776655443322110E", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "", - "C5CD9D1850C141E358649994EE701B68" - ), - ( - "BBAA9988776655443322110F", - "", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15" - "A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95" - "A98CA5F3000B1479" - ) - ) - - # Tuple with - # - key - # - nonce - # - authenticated data - # - plaintext - # - ciphertext and 12 byte MAC tag - tv2 = ( - "0F0E0D0C0B0A09080706050403020100", - "BBAA9988776655443322110D", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1" - "A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD" - "AC4F02AA" - ) - - # Tuple with - # - key length - # - MAC tag length - # - Expected output - tv3 = ( - (128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"), - (192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"), - (256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"), - (128, 96, "77A3D8E73589158D25D01209"), - (192, 96, "05D56EAD2752C86BE6932C5E"), - (256, 96, "5458359AC23B0CBA9E6330DD"), - (128, 64, "192C9B7BD90BA06A"), - (192, 64, "0066BC6E0EF34E24"), - (256, 64, "7D4EA5D445501CBE"), - ) - - def test1(self): - key = unhexlify(b(self.tv1_key)) - for tv in self.tv1: - nonce, aad, pt, ct = [unhexlify(b(x)) for x in tv] - ct, mac_tag = ct[:-16], ct[-16:] - - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) - cipher.update(aad) - ct2 = cipher.encrypt(pt) + cipher.encrypt() - self.assertEqual(ct, ct2) - self.assertEqual(mac_tag, cipher.digest()) - - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) - cipher.update(aad) - pt2 = cipher.decrypt(ct) + cipher.decrypt() - self.assertEqual(pt, pt2) - cipher.verify(mac_tag) - - def test2(self): - - key, nonce, aad, pt, ct = [unhexlify(b(x)) for x in self.tv2] - ct, mac_tag = ct[:-12], ct[-12:] - - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12) - cipher.update(aad) - ct2 = cipher.encrypt(pt) + cipher.encrypt() - self.assertEqual(ct, ct2) - self.assertEqual(mac_tag, cipher.digest()) - - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12) - cipher.update(aad) - pt2 = cipher.decrypt(ct) + cipher.decrypt() - self.assertEqual(pt, pt2) - cipher.verify(mac_tag) - - def test3(self): - for keylen, taglen, result in self.tv3: - result2 = algo_rfc7253(keylen, taglen, 96) - self.assertEqual(unhexlify(b(result)), result2) + # Tuple with + # - nonce + # - authenticated data + # - plaintext + # - ciphertext and 16 byte MAC tag + tv1_key = "000102030405060708090A0B0C0D0E0F" + tv1 = ( + ( + "BBAA99887766554433221100", + "", + "", + "785407BFFFC8AD9EDCC5520AC9111EE6", + ), + ( + "BBAA99887766554433221101", + "0001020304050607", + "0001020304050607", + "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009", + ), + ( + "BBAA99887766554433221102", + "0001020304050607", + "", + "81017F8203F081277152FADE694A0A00", + ), + ( + "BBAA99887766554433221103", + "", + "0001020304050607", + "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9", + ), + ( + "BBAA99887766554433221104", + "000102030405060708090A0B0C0D0E0F", + "000102030405060708090A0B0C0D0E0F", + "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358", + ), + ( + "BBAA99887766554433221105", + "000102030405060708090A0B0C0D0E0F", + "", + "8CF761B6902EF764462AD86498CA6B97", + ), + ( + "BBAA99887766554433221106", + "", + "000102030405060708090A0B0C0D0E0F", + "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D", + ), + ( + "BBAA99887766554433221107", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F", + ), + ( + "BBAA99887766554433221108", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "", + "6DC225A071FC1B9F7C69F93B0F1E10DE", + ), + ( + "BBAA99887766554433221109", + "", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF", + ), + ( + "BBAA9988776655443322110A", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DE" + "AFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240", + ), + ( + "BBAA9988776655443322110B", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "", + "FE80690BEE8A485D11F32965BC9D2A32", + ), + ( + "BBAA9988776655443322110C", + "", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF4" + "6040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF", + ), + ( + "BBAA9988776655443322110D", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "D5CA91748410C1751FF8A2F618255B68A0A12E093FF45460" + "6E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483" + "A7035490C5769E60", + ), + ( + "BBAA9988776655443322110E", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "", + "C5CD9D1850C141E358649994EE701B68", + ), + ( + "BBAA9988776655443322110F", + "", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15" + "A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95" + "A98CA5F3000B1479", + ), + ) + + # Tuple with + # - key + # - nonce + # - authenticated data + # - plaintext + # - ciphertext and 12 byte MAC tag + tv2 = ( + "0F0E0D0C0B0A09080706050403020100", + "BBAA9988776655443322110D", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1" + "A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD" + "AC4F02AA", + ) + + # Tuple with + # - key length + # - MAC tag length + # - Expected output + tv3 = ( + (128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"), + (192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"), + (256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"), + (128, 96, "77A3D8E73589158D25D01209"), + (192, 96, "05D56EAD2752C86BE6932C5E"), + (256, 96, "5458359AC23B0CBA9E6330DD"), + (128, 64, "192C9B7BD90BA06A"), + (192, 64, "0066BC6E0EF34E24"), + (256, 64, "7D4EA5D445501CBE"), + ) + + def test1(self): + key = unhexlify(b(self.tv1_key)) + for tv in self.tv1: + nonce, aad, pt, ct = [unhexlify(b(x)) for x in tv] + ct, mac_tag = ct[:-16], ct[-16:] + + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) + cipher.update(aad) + ct2 = cipher.encrypt(pt) + cipher.encrypt() + self.assertEqual(ct, ct2) + self.assertEqual(mac_tag, cipher.digest()) + + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) + cipher.update(aad) + pt2 = cipher.decrypt(ct) + cipher.decrypt() + self.assertEqual(pt, pt2) + cipher.verify(mac_tag) + + def test2(self): + key, nonce, aad, pt, ct = [unhexlify(b(x)) for x in self.tv2] + ct, mac_tag = ct[:-12], ct[-12:] + + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12) + cipher.update(aad) + ct2 = cipher.encrypt(pt) + cipher.encrypt() + self.assertEqual(ct, ct2) + self.assertEqual(mac_tag, cipher.digest()) + + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12) + cipher.update(aad) + pt2 = cipher.decrypt(ct) + cipher.decrypt() + self.assertEqual(pt, pt2) + cipher.verify(mac_tag) + + def test3(self): + for keylen, taglen, result in self.tv3: + result2 = algo_rfc7253(keylen, taglen, 96) + self.assertEqual(unhexlify(b(result)), result2) class OcbDkgTest(unittest.TestCase): - """Test vectors from https://gitlab.com/dkg/ocb-test-vectors""" - - def test_1_2(self): - tvs = [] - for fi in (1, 2): - for nb in (104, 112, 120): - tv_file = load_test_vectors(("Cipher", "AES"), - "test-vector-%d-nonce%d.txt" % (fi, nb), - "DKG tests, %d, %d bits" % (fi, nb), - {}) - if tv_file is None: - break - key = tv_file[0].k - for tv in tv_file[1:]: - tv.k = key - tvs.append(tv) - - for tv in tvs: - k, n, a, p, c = tv.k, tv.n, tv.a, tv.p, tv.c - mac_len = len(c) - len(p) - cipher = AES.new(k, AES.MODE_OCB, nonce=n, mac_len=mac_len) - cipher.update(a) - c_out, tag_out = cipher.encrypt_and_digest(p) - self.assertEqual(c, c_out + tag_out) - - def test_3(self): - - def check(keylen, taglen, noncelen, exp): - result = algo_rfc7253(keylen, taglen, noncelen) - self.assertEqual(result, unhexlify(exp)) - - # test-vector-3-nonce104.txt - check(128, 128, 104, "C47F5F0341E15326D4D1C46F47F05062") - check(192, 128, 104, "95B9167A38EB80495DFC561A8486E109") - check(256, 128, 104, "AFE1CDDB97028FD92F8FB3C8CFBA7D83") - check(128, 96, 104, "F471B4983BA80946DF217A54") - check(192, 96, 104, "5AE828BC51C24D85FA5CC7B2") - check(256, 96, 104, "8C8335982E2B734616CAD14C") - check(128, 64, 104, "B553F74B85FD1E5B") - check(192, 64, 104, "3B49D20E513531F9") - check(256, 64, 104, "ED6DA5B1216BF8BB") - - # test-vector-3-nonce112.txt - check(128, 128, 112, "CA8AFCA031BAC3F480A583BD6C50A547") - check(192, 128, 112, "D170C1DF356308079DA9A3F619147148") - check(256, 128, 112, "57F94381F2F9231EFB04AECD323757C3") - check(128, 96, 112, "3A618B2531ED39F260C750DC") - check(192, 96, 112, "9071EB89FEDBADDA88FD286E") - check(256, 96, 112, "FDF0EFB97F21A39AC4BAB5AC") - check(128, 64, 112, "FAB2FF3A8DD82A13") - check(192, 64, 112, "AC01D912BD0737D3") - check(256, 64, 112, "9D1FD0B500EA4ECF") - - # test-vector-3-nonce120.txt - check(128, 128, 120, "9E043A7140A25FB91F43BCC9DD7E0F46") - check(192, 128, 120, "680000E53908323A7F396B955B8EC641") - check(256, 128, 120, "8304B97FAACDA56E676602E1878A7E6F") - check(128, 96, 120, "81F978AC9867E825D339847D") - check(192, 96, 120, "EFCF2D60B24926ADA48CF5B1") - check(256, 96, 120, "84961DC56E917B165E58C174") - check(128, 64, 120, "227AEE6C9D905A61") - check(192, 64, 120, "541DE691B9E1A2F9") - check(256, 64, 120, "B0E761381C7129FC") - - def test_2_bugfix(self): - nonce = unhexlify("EEDDCCBBAA9988776655443322110D") - key = unhexlify("0F0E0D0C0B0A09080706050403020100") - A = unhexlify("000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627") - P = unhexlify("000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627") - C = unhexlify("07E903BFC49552411ABC865F5ECE60F6FAD1F5A9F14D3070" - "FA2F1308A563207FFE14C1EEA44B22059C7484319D8A2C53" - "C236A7B3") - mac_len = len(C) - len(P) - - # Prior to version 3.17, a nonce of maximum length (15 bytes) - # was actually used as a 14 byte nonce. The last byte was erroneously - # ignored. - buggy_result = unhexlify("BA015C4E5AE54D76C890AE81BD40DC57" - "03EDC30E8AC2A58BC5D8FA4D61C5BAE6" - "C39BEAC435B2FD56A2A5085C1B135D77" - "0C8264B7") - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce[:-1], mac_len=mac_len) - cipher.update(A) - C_out2, tag_out2 = cipher.encrypt_and_digest(P) - self.assertEqual(buggy_result, C_out2 + tag_out2) + """Test vectors from https://gitlab.com/dkg/ocb-test-vectors""" + + def test_1_2(self): + tvs = [] + for fi in (1, 2): + for nb in (104, 112, 120): + tv_file = load_test_vectors( + ("Cipher", "AES"), + "test-vector-%d-nonce%d.txt" % (fi, nb), + "DKG tests, %d, %d bits" % (fi, nb), + {}, + ) + if tv_file is None: + break + key = tv_file[0].k + for tv in tv_file[1:]: + tv.k = key + tvs.append(tv) + + for tv in tvs: + k, n, a, p, c = tv.k, tv.n, tv.a, tv.p, tv.c + mac_len = len(c) - len(p) + cipher = AES.new(k, AES.MODE_OCB, nonce=n, mac_len=mac_len) + cipher.update(a) + c_out, tag_out = cipher.encrypt_and_digest(p) + self.assertEqual(c, c_out + tag_out) + + def test_3(self): + def check(keylen, taglen, noncelen, exp): + result = algo_rfc7253(keylen, taglen, noncelen) + self.assertEqual(result, unhexlify(exp)) + + # test-vector-3-nonce104.txt + check(128, 128, 104, "C47F5F0341E15326D4D1C46F47F05062") + check(192, 128, 104, "95B9167A38EB80495DFC561A8486E109") + check(256, 128, 104, "AFE1CDDB97028FD92F8FB3C8CFBA7D83") + check(128, 96, 104, "F471B4983BA80946DF217A54") + check(192, 96, 104, "5AE828BC51C24D85FA5CC7B2") + check(256, 96, 104, "8C8335982E2B734616CAD14C") + check(128, 64, 104, "B553F74B85FD1E5B") + check(192, 64, 104, "3B49D20E513531F9") + check(256, 64, 104, "ED6DA5B1216BF8BB") + + # test-vector-3-nonce112.txt + check(128, 128, 112, "CA8AFCA031BAC3F480A583BD6C50A547") + check(192, 128, 112, "D170C1DF356308079DA9A3F619147148") + check(256, 128, 112, "57F94381F2F9231EFB04AECD323757C3") + check(128, 96, 112, "3A618B2531ED39F260C750DC") + check(192, 96, 112, "9071EB89FEDBADDA88FD286E") + check(256, 96, 112, "FDF0EFB97F21A39AC4BAB5AC") + check(128, 64, 112, "FAB2FF3A8DD82A13") + check(192, 64, 112, "AC01D912BD0737D3") + check(256, 64, 112, "9D1FD0B500EA4ECF") + + # test-vector-3-nonce120.txt + check(128, 128, 120, "9E043A7140A25FB91F43BCC9DD7E0F46") + check(192, 128, 120, "680000E53908323A7F396B955B8EC641") + check(256, 128, 120, "8304B97FAACDA56E676602E1878A7E6F") + check(128, 96, 120, "81F978AC9867E825D339847D") + check(192, 96, 120, "EFCF2D60B24926ADA48CF5B1") + check(256, 96, 120, "84961DC56E917B165E58C174") + check(128, 64, 120, "227AEE6C9D905A61") + check(192, 64, 120, "541DE691B9E1A2F9") + check(256, 64, 120, "B0E761381C7129FC") + + def test_2_bugfix(self): + nonce = unhexlify("EEDDCCBBAA9988776655443322110D") + key = unhexlify("0F0E0D0C0B0A09080706050403020100") + A = unhexlify( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + ) + P = unhexlify( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + ) + C = unhexlify( + "07E903BFC49552411ABC865F5ECE60F6FAD1F5A9F14D3070" + "FA2F1308A563207FFE14C1EEA44B22059C7484319D8A2C53" + "C236A7B3", + ) + mac_len = len(C) - len(P) + + # Prior to version 3.17, a nonce of maximum length (15 bytes) + # was actually used as a 14 byte nonce. The last byte was erroneously + # ignored. + buggy_result = unhexlify( + "BA015C4E5AE54D76C890AE81BD40DC57" + "03EDC30E8AC2A58BC5D8FA4D61C5BAE6" + "C39BEAC435B2FD56A2A5085C1B135D77" + "0C8264B7", + ) + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce[:-1], mac_len=mac_len) + cipher.update(A) + C_out2, tag_out2 = cipher.encrypt_and_digest(P) + self.assertEqual(buggy_result, C_out2 + tag_out2) def get_tests(config={}): - tests = [] - tests += list_test_cases(OcbTests) - tests += list_test_cases(OcbFSMTests) - tests += list_test_cases(OcbRfc7253Test) - tests += list_test_cases(OcbDkgTest) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(OcbTests) + tests += list_test_cases(OcbFSMTests) + tests += list_test_cases(OcbRfc7253Test) + tests += list_test_cases(OcbDkgTest) + return tests + + +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OFB.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OFB.py index 9a8ef0a1..d4bd00a8 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OFB.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OFB.py @@ -35,204 +35,224 @@ from Cryptodome.Util.py3compat import tobytes from Cryptodome.Cipher import AES, DES3, DES from Cryptodome.Hash import SHAKE128 -from Cryptodome.SelfTest.loader import load_test_vectors_wycheproof + def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) + from Cryptodome.SelfTest.Cipher.test_CBC import BlockChainingTests -class OfbTests(BlockChainingTests): - aes_mode = AES.MODE_OFB - des3_mode = DES3.MODE_OFB +class OfbTests(BlockChainingTests): + aes_mode = AES.MODE_OFB + des3_mode = DES3.MODE_OFB - # Redefine test_unaligned_data_128/64 + # Redefine test_unaligned_data_128/64 - def test_unaligned_data_128(self): - plaintexts = [ b"7777777" ] * 100 + def test_unaligned_data_128(self): + plaintexts = [b"7777777"] * 100 - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - def test_unaligned_data_64(self): - plaintexts = [ b"7777777" ] * 100 - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + def test_unaligned_data_64(self): + plaintexts = [b"7777777"] * 100 + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) from Cryptodome.SelfTest.Cipher.test_CBC import NistBlockChainingVectors + class NistOfbVectors(NistBlockChainingVectors): - aes_mode = AES.MODE_OFB - des_mode = DES.MODE_OFB - des3_mode = DES3.MODE_OFB + aes_mode = AES.MODE_OFB + des_mode = DES.MODE_OFB + des3_mode = DES3.MODE_OFB # Create one test method per file nist_aes_kat_mmt_files = ( - # KAT - "OFBGFSbox128.rsp", - "OFBGFSbox192.rsp", - "OFBGFSbox256.rsp", - "OFBKeySbox128.rsp", - "OFBKeySbox192.rsp", - "OFBKeySbox256.rsp", - "OFBVarKey128.rsp", - "OFBVarKey192.rsp", - "OFBVarKey256.rsp", - "OFBVarTxt128.rsp", - "OFBVarTxt192.rsp", - "OFBVarTxt256.rsp", - # MMT - "OFBMMT128.rsp", - "OFBMMT192.rsp", - "OFBMMT256.rsp", - ) + # KAT + "OFBGFSbox128.rsp", + "OFBGFSbox192.rsp", + "OFBGFSbox256.rsp", + "OFBKeySbox128.rsp", + "OFBKeySbox192.rsp", + "OFBKeySbox256.rsp", + "OFBVarKey128.rsp", + "OFBVarKey192.rsp", + "OFBVarKey256.rsp", + "OFBVarTxt128.rsp", + "OFBVarTxt192.rsp", + "OFBVarTxt256.rsp", + # MMT + "OFBMMT128.rsp", + "OFBMMT192.rsp", + "OFBMMT256.rsp", +) nist_aes_mct_files = ( - "OFBMCT128.rsp", - "OFBMCT192.rsp", - "OFBMCT256.rsp", - ) + "OFBMCT128.rsp", + "OFBMCT192.rsp", + "OFBMCT256.rsp", +) for file_name in nist_aes_kat_mmt_files: - def new_func(self, file_name=file_name): - self._do_kat_aes_test(file_name) - setattr(NistOfbVectors, "test_AES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_kat_aes_test(file_name) + + setattr(NistOfbVectors, "test_AES_" + file_name, new_func) for file_name in nist_aes_mct_files: - def new_func(self, file_name=file_name): - self._do_mct_aes_test(file_name) - setattr(NistOfbVectors, "test_AES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_mct_aes_test(file_name) + + setattr(NistOfbVectors, "test_AES_" + file_name, new_func) del file_name, new_func nist_tdes_files = ( - "TOFBMMT2.rsp", # 2TDES - "TOFBMMT3.rsp", # 3TDES - "TOFBinvperm.rsp", # Single DES - "TOFBpermop.rsp", - "TOFBsubtab.rsp", - "TOFBvarkey.rsp", - "TOFBvartext.rsp", - ) + "TOFBMMT2.rsp", # 2TDES + "TOFBMMT3.rsp", # 3TDES + "TOFBinvperm.rsp", # Single DES + "TOFBpermop.rsp", + "TOFBsubtab.rsp", + "TOFBvarkey.rsp", + "TOFBvartext.rsp", +) for file_name in nist_tdes_files: - def new_func(self, file_name=file_name): - self._do_tdes_test(file_name) - setattr(NistOfbVectors, "test_TDES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_tdes_test(file_name) + + setattr(NistOfbVectors, "test_TDES_" + file_name, new_func) # END OF NIST OFB TEST VECTORS class SP800TestVectors(unittest.TestCase): - """Class exercising the OFB test vectors found in Section F.4 - of NIST SP 800-3A""" - - def test_aes_128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '3b3fd92eb72dad20333449f8e83cfb4a' +\ - '7789508d16918f03f53c52dac54ed825' +\ - '9740051e9c5fecf64344f7a82260edcc' +\ - '304c6528f659c77866a510d9c1d6ae5e' - key = '2b7e151628aed2a6abf7158809cf4f3c' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) - - def test_aes_192(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = 'cdc80d6fddf18cab34c25909c99a4174' +\ - 'fcc28b8d4c63837c09e81700c1100401' +\ - '8d9a9aeac0f6596f559c6d4daf59a5f2' +\ - '6d9f200857ca6c3e9cac524bd9acc92a' - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) - - def test_aes_256(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = 'dc7e84bfda79164b7ecd8486985d3860' +\ - '4febdc6740d20b3ac88f6ad82a4fb08d' +\ - '71ab47a086e86eedf39d1c5bba97c408' +\ - '0126141d67f37be8538f5a8be740e484' - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) + """Class exercising the OFB test vectors found in Section F.4 + of NIST SP 800-3A""" + + def test_aes_128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "3b3fd92eb72dad20333449f8e83cfb4a" + + "7789508d16918f03f53c52dac54ed825" + + "9740051e9c5fecf64344f7a82260edcc" + + "304c6528f659c77866a510d9c1d6ae5e" + ) + key = "2b7e151628aed2a6abf7158809cf4f3c" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) + + def test_aes_192(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "cdc80d6fddf18cab34c25909c99a4174" + + "fcc28b8d4c63837c09e81700c1100401" + + "8d9a9aeac0f6596f559c6d4daf59a5f2" + + "6d9f200857ca6c3e9cac524bd9acc92a" + ) + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) + + def test_aes_256(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "dc7e84bfda79164b7ecd8486985d3860" + + "4febdc6740d20b3ac88f6ad82a4fb08d" + + "71ab47a086e86eedf39d1c5bba97c408" + + "0126141d67f37be8538f5a8be740e484" + ) + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) def get_tests(config={}): - tests = [] - tests += list_test_cases(OfbTests) - if config.get('slow_tests'): - tests += list_test_cases(NistOfbVectors) - tests += list_test_cases(SP800TestVectors) - return tests + tests = [] + tests += list_test_cases(OfbTests) + if config.get("slow_tests"): + tests += list_test_cases(NistOfbVectors) + tests += list_test_cases(SP800TestVectors) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OpenPGP.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OpenPGP.py index 4090a1a0..bad208e4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OpenPGP.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_OpenPGP.py @@ -33,186 +33,186 @@ from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Util.py3compat import tobytes -from Cryptodome.Cipher import AES, DES3, DES +from Cryptodome.Cipher import AES, DES3 from Cryptodome.Hash import SHAKE128 + def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) from Cryptodome.SelfTest.Cipher.test_CBC import BlockChainingTests -class OpenPGPTests(BlockChainingTests): - aes_mode = AES.MODE_OPENPGP - des3_mode = DES3.MODE_OPENPGP +class OpenPGPTests(BlockChainingTests): + aes_mode = AES.MODE_OPENPGP + des3_mode = DES3.MODE_OPENPGP - # Redefine test_unaligned_data_128/64 + # Redefine test_unaligned_data_128/64 - key_128 = get_tag_random("key_128", 16) - key_192 = get_tag_random("key_192", 24) - iv_128 = get_tag_random("iv_128", 16) - iv_64 = get_tag_random("iv_64", 8) - data_128 = get_tag_random("data_128", 16) + key_128 = get_tag_random("key_128", 16) + key_192 = get_tag_random("key_192", 24) + iv_128 = get_tag_random("iv_128", 16) + iv_64 = get_tag_random("iv_64", 8) + data_128 = get_tag_random("data_128", 16) - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) - eiv, ct = ct[:18], ct[18:] + eiv, ct = ct[:18], ct[18:] - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) - def test_loopback_64(self): - cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) - pt = get_tag_random("plaintext", 8 * 100) - ct = cipher.encrypt(pt) + def test_loopback_64(self): + cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) + pt = get_tag_random("plaintext", 8 * 100) + ct = cipher.encrypt(pt) - eiv, ct = ct[:10], ct[10:] + eiv, ct = ct[:10], ct[10:] - cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, eiv) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) + cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, eiv) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) - def test_IV_iv_attributes(self): - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - eiv = cipher.encrypt(b"") - self.assertEqual(cipher.iv, self.iv_128) + def test_IV_iv_attributes(self): + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + eiv = cipher.encrypt(b"") + self.assertEqual(cipher.iv, self.iv_128) - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) - self.assertEqual(cipher.iv, self.iv_128) + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) + self.assertEqual(cipher.iv, self.iv_128) - def test_null_encryption_decryption(self): - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - eiv = cipher.encrypt(b"") + def test_null_encryption_decryption(self): + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + eiv = cipher.encrypt(b"") - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) - self.assertEqual(cipher.decrypt(b""), b"") + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) + self.assertEqual(cipher.decrypt(b""), b"") - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - eiv = cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + eiv = cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") - def test_unaligned_data_128(self): - plaintexts = [ b"7777777" ] * 100 + def test_unaligned_data_128(self): + plaintexts = [b"7777777"] * 100 - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - def test_unaligned_data_64(self): - plaintexts = [ b"7777777" ] * 100 + def test_unaligned_data_64(self): + plaintexts = [b"7777777"] * 100 - cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - def test_output_param(self): - pass + def test_output_param(self): + pass - def test_output_param_same_buffer(self): - pass + def test_output_param_same_buffer(self): + pass - def test_output_param_memoryview(self): - pass + def test_output_param_memoryview(self): + pass - def test_output_param_neg(self): - pass + def test_output_param_neg(self): + pass class TestVectors(unittest.TestCase): - - def test_aes(self): - # The following test vectors have been generated with gpg v1.4.0. - # The command line used was: - # - # gpg -c -z 0 --cipher-algo AES --passphrase secret_passphrase \ - # --disable-mdc --s2k-mode 0 --output ct pt - # - # As result, the content of the file 'pt' is encrypted with a key derived - # from 'secret_passphrase' and written to file 'ct'. - # Test vectors must be extracted from 'ct', which is a collection of - # TLVs (see RFC4880 for all details): - # - the encrypted data (with the encrypted IV as prefix) is the payload - # of the TLV with tag 9 (Symmetrical Encrypted Data Packet). - # This is the ciphertext in the test vector. - # - inside the encrypted part, there is a further layer of TLVs. One must - # look for tag 11 (Literal Data Packet); in its payload, after a short - # but time dependent header, there is the content of file 'pt'. - # In the test vector, the plaintext is the complete set of TLVs that gets - # encrypted. It is not just the content of 'pt'. - # - the key is the leftmost 16 bytes of the SHA1 digest of the password. - # The test vector contains such shortened digest. - # - # Note that encryption uses a clear IV, and decryption an encrypted IV - - plaintext = 'ac18620270744fb4f647426c61636b4361745768697465436174' - ciphertext = 'dc6b9e1f095de609765c59983db5956ae4f63aea7405389d2ebb' - key = '5baa61e4c9b93f3f0682250b6cf8331b' - iv = '3d7d3e62282add7eb203eeba5c800733' - encrypted_iv='fd934601ef49cb58b6d9aebca6056bdb96ef' - - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - key = unhexlify(key) - iv = unhexlify(iv) - encrypted_iv = unhexlify(encrypted_iv) - - cipher = AES.new(key, AES.MODE_OPENPGP, iv) - ct = cipher.encrypt(plaintext) - self.assertEqual(ct[:18], encrypted_iv) - self.assertEqual(ct[18:], ciphertext) - - cipher = AES.new(key, AES.MODE_OPENPGP, encrypted_iv) - pt = cipher.decrypt(ciphertext) - self.assertEqual(pt, plaintext) - - def test_des3(self): - # The following test vectors have been generated with gpg v1.4.0. - # The command line used was: - # gpg -c -z 0 --cipher-algo 3DES --passphrase secret_passphrase \ - # --disable-mdc --s2k-mode 0 --output ct pt - # For an explanation, see test_AES.py . - - plaintext = 'ac1762037074324fb53ba3596f73656d69746556616c6c6579' - ciphertext = '9979238528357b90e2e0be549cb0b2d5999b9a4a447e5c5c7d' - key = '7ade65b460f5ea9be35f9e14aa883a2048e3824aa616c0b2' - iv='cd47e2afb8b7e4b0' - encrypted_iv='6a7eef0b58050e8b904a' - - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - key = unhexlify(key) - iv = unhexlify(iv) - encrypted_iv = unhexlify(encrypted_iv) - - cipher = DES3.new(key, DES3.MODE_OPENPGP, iv) - ct = cipher.encrypt(plaintext) - self.assertEqual(ct[:10], encrypted_iv) - self.assertEqual(ct[10:], ciphertext) - - cipher = DES3.new(key, DES3.MODE_OPENPGP, encrypted_iv) - pt = cipher.decrypt(ciphertext) - self.assertEqual(pt, plaintext) + def test_aes(self): + # The following test vectors have been generated with gpg v1.4.0. + # The command line used was: + # + # gpg -c -z 0 --cipher-algo AES --passphrase secret_passphrase \ + # --disable-mdc --s2k-mode 0 --output ct pt + # + # As result, the content of the file 'pt' is encrypted with a key derived + # from 'secret_passphrase' and written to file 'ct'. + # Test vectors must be extracted from 'ct', which is a collection of + # TLVs (see RFC4880 for all details): + # - the encrypted data (with the encrypted IV as prefix) is the payload + # of the TLV with tag 9 (Symmetrical Encrypted Data Packet). + # This is the ciphertext in the test vector. + # - inside the encrypted part, there is a further layer of TLVs. One must + # look for tag 11 (Literal Data Packet); in its payload, after a short + # but time dependent header, there is the content of file 'pt'. + # In the test vector, the plaintext is the complete set of TLVs that gets + # encrypted. It is not just the content of 'pt'. + # - the key is the leftmost 16 bytes of the SHA1 digest of the password. + # The test vector contains such shortened digest. + # + # Note that encryption uses a clear IV, and decryption an encrypted IV + + plaintext = "ac18620270744fb4f647426c61636b4361745768697465436174" + ciphertext = "dc6b9e1f095de609765c59983db5956ae4f63aea7405389d2ebb" + key = "5baa61e4c9b93f3f0682250b6cf8331b" + iv = "3d7d3e62282add7eb203eeba5c800733" + encrypted_iv = "fd934601ef49cb58b6d9aebca6056bdb96ef" + + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + key = unhexlify(key) + iv = unhexlify(iv) + encrypted_iv = unhexlify(encrypted_iv) + + cipher = AES.new(key, AES.MODE_OPENPGP, iv) + ct = cipher.encrypt(plaintext) + self.assertEqual(ct[:18], encrypted_iv) + self.assertEqual(ct[18:], ciphertext) + + cipher = AES.new(key, AES.MODE_OPENPGP, encrypted_iv) + pt = cipher.decrypt(ciphertext) + self.assertEqual(pt, plaintext) + + def test_des3(self): + # The following test vectors have been generated with gpg v1.4.0. + # The command line used was: + # gpg -c -z 0 --cipher-algo 3DES --passphrase secret_passphrase \ + # --disable-mdc --s2k-mode 0 --output ct pt + # For an explanation, see test_AES.py . + + plaintext = "ac1762037074324fb53ba3596f73656d69746556616c6c6579" + ciphertext = "9979238528357b90e2e0be549cb0b2d5999b9a4a447e5c5c7d" + key = "7ade65b460f5ea9be35f9e14aa883a2048e3824aa616c0b2" + iv = "cd47e2afb8b7e4b0" + encrypted_iv = "6a7eef0b58050e8b904a" + + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + key = unhexlify(key) + iv = unhexlify(iv) + encrypted_iv = unhexlify(encrypted_iv) + + cipher = DES3.new(key, DES3.MODE_OPENPGP, iv) + ct = cipher.encrypt(plaintext) + self.assertEqual(ct[:10], encrypted_iv) + self.assertEqual(ct[10:], ciphertext) + + cipher = DES3.new(key, DES3.MODE_OPENPGP, encrypted_iv) + pt = cipher.decrypt(ciphertext) + self.assertEqual(pt, plaintext) def get_tests(config={}): - tests = [] - tests += list_test_cases(OpenPGPTests) - tests += list_test_cases(TestVectors) - return tests + tests = [] + tests += list_test_cases(OpenPGPTests) + tests += list_test_cases(TestVectors) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_SIV.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_SIV.py index d4bb5a9a..464c6401 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_SIV.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_SIV.py @@ -28,7 +28,6 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -import json import unittest from binascii import unhexlify @@ -39,514 +38,568 @@ from Cryptodome.Cipher import AES from Cryptodome.Hash import SHAKE128 -from Cryptodome.Util.strxor import strxor - def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class SivTests(unittest.TestCase): - - key_256 = get_tag_random("key_256", 32) - key_384 = get_tag_random("key_384", 48) - key_512 = get_tag_random("key_512", 64) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_loopback_128(self): - for key in self.key_256, self.key_384, self.key_512: - cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct, mac = cipher.encrypt_and_digest(pt) - - cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # Deterministic encryption - AES.new(self.key_256, AES.MODE_SIV) - - cipher = AES.new(self.key_256, AES.MODE_SIV, self.nonce_96) - ct1, tag1 = cipher.encrypt_and_digest(self.data) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct2, tag2 = cipher.encrypt_and_digest(self.data) - self.assertEqual(ct1 + tag1, ct2 + tag2) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_256, AES.MODE_SIV, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce can be of any length (but not empty) - self.assertRaises(ValueError, AES.new, self.key_256, AES.MODE_SIV, - nonce=b"") - - for x in range(1, 128): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=bchr(1) * x) - cipher.encrypt_and_digest(b'\x01') - - def test_block_size_128(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, no nonce is randomly generated - self.assertFalse(hasattr(AES.new(self.key_256, AES.MODE_SIV), "nonce")) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_256, AES.MODE_SIV, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_256, AES.MODE_SIV, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96, - use_aesni=False) - - def test_encrypt_excludes_decrypt(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - self.assertRaises(TypeError, cipher.decrypt, self.data) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - self.assertRaises(TypeError, cipher.decrypt_and_verify, - self.data, self.data) - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt_and_verify, - u'test1234567890-*', b"xxxx") - - def test_mac_len(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_bytearray(self): - - # Encrypt - key = bytearray(self.key_256) - nonce = bytearray(self.nonce_96) - data = bytearray(self.data) - header = bytearray(self.data) - - cipher1 = AES.new(self.key_256, - AES.MODE_SIV, - nonce=self.nonce_96) - cipher1.update(self.data) - ct, tag = cipher1.encrypt_and_digest(self.data) - - cipher2 = AES.new(key, - AES.MODE_SIV, - nonce=nonce) - key[:3] = b'\xFF\xFF\xFF' - nonce[:3] = b'\xFF\xFF\xFF' - cipher2.update(header) - header[:3] = b'\xFF\xFF\xFF' - ct_test, tag_test = cipher2.encrypt_and_digest(data) - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key = bytearray(self.key_256) - nonce = bytearray(self.nonce_96) - header = bytearray(self.data) - ct_ba = bytearray(ct) - tag_ba = bytearray(tag) - - cipher3 = AES.new(key, - AES.MODE_SIV, - nonce=nonce) - key[:3] = b'\xFF\xFF\xFF' - nonce[:3] = b'\xFF\xFF\xFF' - cipher3.update(header) - header[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba) - - self.assertEqual(self.data, pt_test) - - def test_memoryview(self): - - # Encrypt - key = memoryview(bytearray(self.key_256)) - nonce = memoryview(bytearray(self.nonce_96)) - data = memoryview(bytearray(self.data)) - header = memoryview(bytearray(self.data)) - - cipher1 = AES.new(self.key_256, - AES.MODE_SIV, - nonce=self.nonce_96) - cipher1.update(self.data) - ct, tag = cipher1.encrypt_and_digest(self.data) - - cipher2 = AES.new(key, - AES.MODE_SIV, - nonce=nonce) - key[:3] = b'\xFF\xFF\xFF' - nonce[:3] = b'\xFF\xFF\xFF' - cipher2.update(header) - header[:3] = b'\xFF\xFF\xFF' - ct_test, tag_test= cipher2.encrypt_and_digest(data) - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key = memoryview(bytearray(self.key_256)) - nonce = memoryview(bytearray(self.nonce_96)) - header = memoryview(bytearray(self.data)) - ct_ba = memoryview(bytearray(ct)) - tag_ba = memoryview(bytearray(tag)) - - cipher3 = AES.new(key, - AES.MODE_SIV, - nonce=nonce) - key[:3] = b'\xFF\xFF\xFF' - nonce[:3] = b'\xFF\xFF\xFF' - cipher3.update(header) - header[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba) - - self.assertEqual(self.data, pt_test) - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(pt) - - output = bytearray(128) - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - res, tag_out = cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - self.assertEqual(tag, tag_out) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - res = cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - - def test_output_param_neg(self): - LEN_PT = 128 - - pt = b'5' * LEN_PT - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(pt) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt_and_digest, pt, output=b'0' * LEN_PT) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag, output=b'0' * LEN_PT) - - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.encrypt_and_digest, pt, output=shorter_output) - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, tag, output=shorter_output) + key_256 = get_tag_random("key_256", 32) + key_384 = get_tag_random("key_384", 48) + key_512 = get_tag_random("key_512", 64) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_loopback_128(self): + for key in self.key_256, self.key_384, self.key_512: + cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct, mac = cipher.encrypt_and_digest(pt) + + cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # Deterministic encryption + AES.new(self.key_256, AES.MODE_SIV) + + cipher = AES.new(self.key_256, AES.MODE_SIV, self.nonce_96) + ct1, tag1 = cipher.encrypt_and_digest(self.data) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct2, tag2 = cipher.encrypt_and_digest(self.data) + self.assertEqual(ct1 + tag1, ct2 + tag2) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_256, + AES.MODE_SIV, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce can be of any length (but not empty) + self.assertRaises( + ValueError, + AES.new, + self.key_256, + AES.MODE_SIV, + nonce=b"", + ) + + for x in range(1, 128): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=bchr(1) * x) + cipher.encrypt_and_digest(b"\x01") + + def test_block_size_128(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, no nonce is randomly generated + self.assertFalse(hasattr(AES.new(self.key_256, AES.MODE_SIV), "nonce")) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_256, + AES.MODE_SIV, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_encrypt_excludes_decrypt(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + self.assertRaises(TypeError, cipher.decrypt, self.data) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + self.assertRaises( + TypeError, + cipher.decrypt_and_verify, + self.data, + self.data, + ) + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises( + TypeError, + cipher.decrypt_and_verify, + "test1234567890-*", + b"xxxx", + ) + + def test_mac_len(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_bytearray(self): + # Encrypt + key = bytearray(self.key_256) + nonce = bytearray(self.nonce_96) + data = bytearray(self.data) + header = bytearray(self.data) + + cipher1 = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct, tag = cipher1.encrypt_and_digest(self.data) + + cipher2 = AES.new( + key, + AES.MODE_SIV, + nonce=nonce, + ) + key[:3] = b"\xff\xff\xff" + nonce[:3] = b"\xff\xff\xff" + cipher2.update(header) + header[:3] = b"\xff\xff\xff" + ct_test, tag_test = cipher2.encrypt_and_digest(data) + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key = bytearray(self.key_256) + nonce = bytearray(self.nonce_96) + header = bytearray(self.data) + ct_ba = bytearray(ct) + tag_ba = bytearray(tag) + + cipher3 = AES.new( + key, + AES.MODE_SIV, + nonce=nonce, + ) + key[:3] = b"\xff\xff\xff" + nonce[:3] = b"\xff\xff\xff" + cipher3.update(header) + header[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba) + + self.assertEqual(self.data, pt_test) + + def test_memoryview(self): + # Encrypt + key = memoryview(bytearray(self.key_256)) + nonce = memoryview(bytearray(self.nonce_96)) + data = memoryview(bytearray(self.data)) + header = memoryview(bytearray(self.data)) + + cipher1 = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct, tag = cipher1.encrypt_and_digest(self.data) + + cipher2 = AES.new( + key, + AES.MODE_SIV, + nonce=nonce, + ) + key[:3] = b"\xff\xff\xff" + nonce[:3] = b"\xff\xff\xff" + cipher2.update(header) + header[:3] = b"\xff\xff\xff" + ct_test, tag_test = cipher2.encrypt_and_digest(data) + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key = memoryview(bytearray(self.key_256)) + nonce = memoryview(bytearray(self.nonce_96)) + header = memoryview(bytearray(self.data)) + ct_ba = memoryview(bytearray(ct)) + tag_ba = memoryview(bytearray(tag)) + + cipher3 = AES.new( + key, + AES.MODE_SIV, + nonce=nonce, + ) + key[:3] = b"\xff\xff\xff" + nonce[:3] = b"\xff\xff\xff" + cipher3.update(header) + header[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba) + + self.assertEqual(self.data, pt_test) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(pt) + + output = bytearray(128) + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + res, tag_out = cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + self.assertEqual(tag, tag_out) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + res = cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + LEN_PT = 128 + + pt = b"5" * LEN_PT + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(pt) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt_and_digest, pt, output=b"0" * LEN_PT) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag, output=b"0" * LEN_PT) + + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.encrypt_and_digest, pt, output=shorter_output) + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, tag, output=shorter_output) class SivFSMTests(unittest.TestCase): - - key_256 = get_tag_random("key_256", 32) - nonce_96 = get_tag_random("nonce_96", 12) - data = get_tag_random("data", 128) - - def test_invalid_init_encrypt(self): - # Path INIT->ENCRYPT fails - cipher = AES.new(self.key_256, AES.MODE_SIV, - nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, b"xxx") - - def test_invalid_init_decrypt(self): - # Path INIT->DECRYPT fails - cipher = AES.new(self.key_256, AES.MODE_SIV, - nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, b"xxx") - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_256, AES.MODE_SIV, - nonce=self.nonce_96) - cipher.update(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_256, AES.MODE_SIV, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.update(self.data) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.update(self.data) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.update(self.data) - ct, mac = cipher.encrypt_and_digest(self.data) - - # decrypt_and_verify - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.update(self.data) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data, pt) - - def test_invalid_multiple_encrypt_and_digest(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(self.data) - self.assertRaises(TypeError, cipher.encrypt_and_digest, b'') - - def test_invalid_multiple_decrypt_and_verify(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(self.data) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, tag) - self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag) + key_256 = get_tag_random("key_256", 32) + nonce_96 = get_tag_random("nonce_96", 12) + data = get_tag_random("data", 128) + + def test_invalid_init_encrypt(self): + # Path INIT->ENCRYPT fails + cipher = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + self.assertRaises(TypeError, cipher.encrypt, b"xxx") + + def test_invalid_init_decrypt(self): + # Path INIT->DECRYPT fails + cipher = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + self.assertRaises(TypeError, cipher.decrypt, b"xxx") + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + cipher.update(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.update(self.data) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.update(self.data) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.update(self.data) + ct, mac = cipher.encrypt_and_digest(self.data) + + # decrypt_and_verify + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.update(self.data) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data, pt) + + def test_invalid_multiple_encrypt_and_digest(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(self.data) + self.assertRaises(TypeError, cipher.encrypt_and_digest, b"") + + def test_invalid_multiple_decrypt_and_verify(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(self.data) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, tag) + self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag) def transform(tv): - new_tv = [[unhexlify(x) for x in tv[0].split("-")]] - new_tv += [ unhexlify(x) for x in tv[1:5]] - if tv[5]: - nonce = unhexlify(tv[5]) - else: - nonce = None - new_tv += [ nonce ] - return new_tv + new_tv = [[unhexlify(x) for x in tv[0].split("-")]] + new_tv += [unhexlify(x) for x in tv[1:5]] + if tv[5]: + nonce = unhexlify(tv[5]) + else: + nonce = None + new_tv += [nonce] + return new_tv class TestVectors(unittest.TestCase): - """Class exercising the SIV test vectors found in RFC5297""" - - # This is a list of tuples with 5 items: - # - # 1. Header + '|' + plaintext - # 2. Header + '|' + ciphertext + '|' + MAC - # 3. AES-128 key - # 4. Description - # 5. Dictionary of parameters to be passed to AES.new(). - # It must include the nonce. - # - # A "Header" is a dash ('-') separated sequece of components. - # - test_vectors_hex = [ - ( - '101112131415161718191a1b1c1d1e1f2021222324252627', - '112233445566778899aabbccddee', - '40c02b9690c4dc04daef7f6afe5c', - '85632d07c6e8f37f950acd320a2ecc93', - 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff', - None - ), - ( - '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988' + - '7766554433221100-102030405060708090a0', - '7468697320697320736f6d6520706c61696e7465787420746f20656e63727970' + - '74207573696e67205349562d414553', - 'cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829' + - 'ea64ad544a272e9c485b62a3fd5c0d', - '7bdb6e3b432667eb06f4d14bff2fbd0f', - '7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f', - '09f911029d74e35bd84156c5635688c0' - ), - ] - - test_vectors = [ transform(tv) for tv in test_vectors_hex ] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - - # Encrypt - cipher = AES.new(key, AES.MODE_SIV, nonce=nonce) - for x in assoc_data: - cipher.update(x) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = AES.new(key, AES.MODE_SIV, nonce=nonce) - for x in assoc_data: - cipher.update(x) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Class exercising the SIV test vectors found in RFC5297""" + + # This is a list of tuples with 5 items: + # + # 1. Header + '|' + plaintext + # 2. Header + '|' + ciphertext + '|' + MAC + # 3. AES-128 key + # 4. Description + # 5. Dictionary of parameters to be passed to AES.new(). + # It must include the nonce. + # + # A "Header" is a dash ('-') separated sequece of components. + # + test_vectors_hex = [ + ( + "101112131415161718191a1b1c1d1e1f2021222324252627", + "112233445566778899aabbccddee", + "40c02b9690c4dc04daef7f6afe5c", + "85632d07c6e8f37f950acd320a2ecc93", + "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + None, + ), + ( + "00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988" + + "7766554433221100-102030405060708090a0", + "7468697320697320736f6d6520706c61696e7465787420746f20656e63727970" + + "74207573696e67205349562d414553", + "cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829" + + "ea64ad544a272e9c485b62a3fd5c0d", + "7bdb6e3b432667eb06f4d14bff2fbd0f", + "7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f", + "09f911029d74e35bd84156c5635688c0", + ), + ] + + test_vectors = [transform(tv) for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = AES.new(key, AES.MODE_SIV, nonce=nonce) + for x in assoc_data: + cipher.update(x) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = AES.new(key, AES.MODE_SIV, nonce=nonce) + for x in assoc_data: + cipher.update(x) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self): - unittest.TestCase.__init__(self) - self._id = "None" - - def setUp(self): - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aes_siv_cmac_test.json", - "Wycheproof AES SIV") - - def shortDescription(self): - return self._id - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt AES-SIV Test #" + str(tv.id) - - cipher = AES.new(tv.key, AES.MODE_SIV) - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(tag + ct, tv.ct) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt AES_SIV Test #" + str(tv.id) - - cipher = AES.new(tv.key, AES.MODE_SIV) - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct[16:], tv.ct[:16]) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) + def __init__(self): + unittest.TestCase.__init__(self) + self._id = "None" + + def setUp(self): + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aes_siv_cmac_test.json", + "Wycheproof AES SIV", + ) + + def shortDescription(self): + return self._id + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt AES-SIV Test #" + str(tv.id) + + cipher = AES.new(tv.key, AES.MODE_SIV) + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(tag + ct, tv.ct) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt AES_SIV Test #" + str(tv.id) + + cipher = AES.new(tv.key, AES.MODE_SIV) + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct[16:], tv.ct[:16]) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) class TestVectorsWycheproof2(unittest.TestCase): - - def __init__(self): - unittest.TestCase.__init__(self) - self._id = "None" - - def setUp(self): - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aead_aes_siv_cmac_test.json", - "Wycheproof AEAD SIV") - - def shortDescription(self): - return self._id - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt AEAD-AES-SIV Test #" + str(tv.id) - - cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv) - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt AEAD-AES-SIV Test #" + str(tv.id) - - cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv) - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) + def __init__(self): + unittest.TestCase.__init__(self) + self._id = "None" + + def setUp(self): + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aead_aes_siv_cmac_test.json", + "Wycheproof AEAD SIV", + ) + + def shortDescription(self): + return self._id + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt AEAD-AES-SIV Test #" + str(tv.id) + + cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv) + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt AEAD-AES-SIV Test #" + str(tv.id) + + cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv) + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") - tests = [] - tests += list_test_cases(SivTests) - tests += list_test_cases(SivFSMTests) - tests += [ TestVectors() ] - tests += [ TestVectorsWycheproof() ] - tests += [ TestVectorsWycheproof2() ] - return tests + tests = [] + tests += list_test_cases(SivTests) + tests += list_test_cases(SivFSMTests) + tests += [TestVectors()] + tests += [TestVectorsWycheproof()] + tests += [TestVectorsWycheproof2()] + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_Salsa20.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_Salsa20.py index a4449062..a46c518b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_Salsa20.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_Salsa20.py @@ -37,331 +37,331 @@ # This is a list of (plaintext, ciphertext, key[, description[, params]]) # tuples. test_data = [ - # Test vectors are taken from - # http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors - ( '00' * 512, - '4dfa5e481da23ea09a31022050859936da52fcee218005164f267cb65f5cfd7f' - + '2b4f97e0ff16924a52df269515110a07f9e460bc65ef95da58f740b7d1dbb0aa' - + 'd64cec189c7eb8c6bbf3d7376c80a481d43e628701f6a27afb9fe23919f24114' - + '8db44f70d7063efcc3dd55a0893a613c3c6fe1c127bd6f59910589293bb6ef9e' - + 'e24819066dee1a64f49b0bbad5988635272b169af861f85df881939f29ada6fd' - + '0241410e8d332ae4798d929434a2630de451ec4e0169694cbaa7ebb121ea6a2b' - + 'da9c1581f429e0a00f7d67e23b730676783b262e8eb43a25f55fb90b3e753aef' - + '8c6713ec66c51881111593ccb3e8cb8f8de124080501eeeb389c4bcb6977cf95' - + '7d5789631eb4554400e1e025935dfa7b3e9039d61bdc58a8697d36815bf1985c' - + 'efdf7ae112e5bb81e37ecf0616ce7147fc08a93a367e08631f23c03b00a8da2f' - + 'aa5024e5c8d30aca43fc2d5082067b21b234bc741d68fb292c6012c3764ccee3' - + '1e364a5403e00cfee338a21a01e7d3cefd5a770ca0ab48c435ea6116435f7ad8' - + '30b217b49f978a68e207ed9f462af7fb195b2115fe8f24f152e4ddc32202d6f2' - + 'b52fafbcfbc202d8a259a611e901d3f62d065eb13f09bbc45cd45119b843efaa' - + 'b375703739daced4dd4059fd71c3c47fc2f9939670fad4a46066adcc6a564578' - + '3308b90ffb72be04a6b147cbe38cc0c3b9267c296a92a7c69873f9f263be9703', - '80000000000000000000000000000000', - '128 bits key, set 1, vector 0', - dict (iv='00'*8)), - - ( '00' * 512, - 'e3be8fdd8beca2e3ea8ef9475b29a6e7003951e1097a5c38d23b7a5fad9f6844' - + 'b22c97559e2723c7cbbd3fe4fc8d9a0744652a83e72a9c461876af4d7ef1a117' - + '8da2b74eef1b6283e7e20166abcae538e9716e4669e2816b6b20c5c356802001' - + 'cc1403a9a117d12a2669f456366d6ebb0f1246f1265150f793cdb4b253e348ae' - + '203d89bc025e802a7e0e00621d70aa36b7e07cb1e7d5b38d5e222b8b0e4b8407' - + '0142b1e29504767d76824850320b5368129fdd74e861b498e3be8d16f2d7d169' - + '57be81f47b17d9ae7c4ff15429a73e10acf250ed3a90a93c711308a74c6216a9' - + 'ed84cd126da7f28e8abf8bb63517e1ca98e712f4fb2e1a6aed9fdc73291faa17' - + '958211c4ba2ebd5838c635edb81f513a91a294e194f1c039aeec657dce40aa7e' - + '7c0af57cacefa40c9f14b71a4b3456a63e162ec7d8d10b8ffb1810d71001b618' - + '2f9f73da53b85405c11f7b2d890fa8ae0c7f2e926d8a98c7ec4e91b65120e988' - + '349631a700c6facec3471cb0413656e75e309456584084d7e12c5b43a41c43ed' - + '9a048abd9b880da65f6a665a20fe7b77cd292fe62cae644b7f7df69f32bdb331' - + '903e6505ce44fdc293920c6a9ec7057e23df7dad298f82ddf4efb7fdc7bfc622' - + '696afcfd0cddcc83c7e77f11a649d79acdc3354e9635ff137e929933a0bd6f53' - + '77efa105a3a4266b7c0d089d08f1e855cc32b15b93784a36e56a76cc64bc8477', - '8000000000000000000000000000000000000000000000000000000000000000', - '256 bits key, set 1, vector 0', - dict (iv='00'*8)), - - ( '00' * 512, - '169060ccb42bea7bee4d8012a02f3635eb7bca12859fa159cd559094b3507db8' - + '01735d1a1300102a9c9415546829cbd2021ba217b39b81d89c55b13d0c603359' - + '3f84159a3c84f4b4f4a0edcd9d38ff261a737909e0b66d68b5cac496f3a5be99' - + 'cb12c321ab711afaab36cc0947955e1a9bb952ed54425e7711279fbc81bb83f5' - + '6e55cea44e6daddb05858a153ea6213b3350c12aa1a83ef2726f09485fa71790' - + 'f9b9f922c7dda1113b1f9d56658ed3402803f511bc1f122601d5e7f0ff036e23' - + '23ef24bb24195b9fd574823cd8a40c29d86bd35c191e2038779ff696c712b6d8' - + '2e7014dbe1ac5d527af076c088c4a8d44317958189f6ef54933a7e0816b5b916' - + 'd8f12ed8afe9422b85e5cc9b8adec9d6cfabe8dbc1082bccc02f5a7266aa074c' - + 'a284e583a35837798cc0e69d4ce937653b8cdd65ce414b89138615ccb165ad19' - + '3c6b9c3d05eef4be921a10ea811fe61d11c6867600188e065daff90b509ec56b' - + 'd41e7e8968c478c78d590c2d2ee24ea009c8f49bc3d81672cfc47895a9e21c9a' - + '471ebf8e294bee5d2de436ac8d052bf31111b345f1da23c3a4d13b9fc5f0900a' - + 'a298f98f538973b8fad40d4d159777de2cfe2a3dead1645ddb49794827dba040' - + 'f70a0ff4ecd155e0f033604693a51e2363880e2ecf98699e7174af7c2c6b0fc6' - + '59ae329599a3949272a37b9b2183a0910922a3f325ae124dcbdd735364055ceb', - '09090909090909090909090909090909', - '128 bits key, set 2, vector 9', - dict (iv='00'*8)), - - ( '00' * 512, - '7041e747ceb22ed7812985465f50333124f971da1c5d6efe5ca201b886f31046' - + 'e757e5c3ec914f60ed1f6bce2819b6810953f12b8ba1199bf82d746a8b8a88f1' - + '142002978ec4c35b95dc2c82990f9e847a0ab45f2ca72625f5190c820f29f3aa' - + 'f5f0b5572b06b70a144f2a240c3b3098d4831fa1ce1459f8d1df226a6a79b0ab' - + '41e91799ef31b5ff3d756c19126b19025858ee70fbd69f2be955cb011c005e31' - + '32b271b378f39b0cb594e95c99ce6ff17735a541891845bbf0450afcb4a850b9' - + '4ee90afb713ae7e01295c74381180a3816d7020d5a396c0d97aaa783eaabb6ec' - + '44d5111157f2212d1b1b8fca7893e8b520cd482418c272ab119b569a2b9598eb' - + '355624d12e79adab81153b58cd22eaf1b2a32395dedc4a1c66f4d274070b9800' - + 'ea95766f0245a8295f8aadb36ddbbdfa936417c8dbc6235d19494036964d3e70' - + 'b125b0f800c3d53881d9d11e7970f827c2f9556935cd29e927b0aceb8cae5fd4' - + '0fd88a8854010a33db94c96c98735858f1c5df6844f864feaca8f41539313e7f' - + '3c0610214912cd5e6362197646207e2d64cd5b26c9dfe0822629dcbeb16662e8' - + '9ff5bf5cf2e499138a5e27bd5027329d0e68ddf53103e9e409523662e27f61f6' - + '5cf38c1232023e6a6ef66c315bcb2a4328642faabb7ca1e889e039e7c444b34b' - + 'b3443f596ac730f3df3dfcdb343c307c80f76e43e8898c5e8f43dc3bb280add0', - '0909090909090909090909090909090909090909090909090909090909090909', - '256 bits key, set 2, vector 9', - dict (iv='00'*8)), - - ( '00' * 1024, - '71daee5142d0728b41b6597933ebf467e43279e30978677078941602629cbf68' - + 'b73d6bd2c95f118d2b3e6ec955dabb6dc61c4143bc9a9b32b99dbe6866166dc0' - + '8631b7d6553050303d7252c264d3a90d26c853634813e09ad7545a6ce7e84a5d' - + 'fc75ec43431207d5319970b0faadb0e1510625bb54372c8515e28e2accf0a993' - + '0ad15f431874923d2a59e20d9f2a5367dba6051564f150287debb1db536ff9b0' - + '9ad981f25e5010d85d76ee0c305f755b25e6f09341e0812f95c94f42eead346e' - + '81f39c58c5faa2c88953dc0cac90469db2063cb5cdb22c9eae22afbf0506fca4' - + '1dc710b846fbdfe3c46883dd118f3a5e8b11b6afd9e71680d8666557301a2daa' - + 'fb9496c559784d35a035360885f9b17bd7191977deea932b981ebdb29057ae3c' - + '92cfeff5e6c5d0cb62f209ce342d4e35c69646ccd14e53350e488bb310a32f8b' - + '0248e70acc5b473df537ced3f81a014d4083932bedd62ed0e447b6766cd2604b' - + '706e9b346c4468beb46a34ecf1610ebd38331d52bf33346afec15eefb2a7699e' - + '8759db5a1f636a48a039688e39de34d995df9f27ed9edc8dd795e39e53d9d925' - + 'b278010565ff665269042f05096d94da3433d957ec13d2fd82a0066283d0d1ee' - + 'b81bf0ef133b7fd90248b8ffb499b2414cd4fa003093ff0864575a43749bf596' - + '02f26c717fa96b1d057697db08ebc3fa664a016a67dcef8807577cc3a09385d3' - + 'f4dc79b34364bb3b166ce65fe1dd28e3950fe6fa81063f7b16ce1c0e6daac1f8' - + '188455b77752045e863c9b256ad92bc6e2d08314c5bba191c274f42dfbb3d652' - + 'bb771956555e880f84cd8b827a4c5a52f3a099fa0259bd4aac3efd541f191170' - + '4412d6e85fbcc628b335875b9fef24807f6e1bc66c3186159e1e7f5a13913e02' - + 'd241ce2efdbcaa275039fb14eac5923d17ffbc7f1abd3b45e92127575bfbabf9' - + '3a257ebef0aa1437b326e41b585af572f7239c33b32981a1577a4f629b027e1e' - + 'b49d58cc497e944d79cef44357c2bf25442ab779651e991147bf79d6fd3a8868' - + '0cd3b1748e07fd10d78aceef6db8a5e563570d40127f754146c34a440f2a991a' - + '23fa39d365141f255041f2135c5cba4373452c114da1801bacca38610e3a6524' - + '2b822d32de4ab5a7d3cf9b61b37493c863bd12e2cae10530cddcda2cb7a5436b' - + 'ef8988d4d24e8cdc31b2d2a3586340bc5141f8f6632d0dd543bfed81eb471ba1' - + 'f3dc2225a15ffddcc03eb48f44e27e2aa390598adf83f15c6608a5f18d4dfcf0' - + 'f547d467a4d70b281c83a595d7660d0b62de78b9cca023cca89d7b1f83484638' - + '0e228c25f049184a612ef5bb3d37454e6cfa5b10dceda619d898a699b3c8981a' - + '173407844bb89b4287bf57dd6600c79e352c681d74b03fa7ea0d7bf6ad69f8a6' - + '8ecb001963bd2dd8a2baa0083ec09751cd9742402ad716be16d5c052304cfca1', - '0F62B5085BAE0154A7FA4DA0F34699EC', - '128 bits key, Set 6, vector# 3', - dict (iv='288FF65DC42B92F9')), - - ( '00' * 1024, - '5e5e71f90199340304abb22a37b6625bf883fb89ce3b21f54a10b81066ef87da' - + '30b77699aa7379da595c77dd59542da208e5954f89e40eb7aa80a84a6176663f' - + 'd910cde567cf1ff60f7040548d8f376bfd1f44c4774aac37410ede7d5c3463fc' - + '4508a603201d8495ad257894e5eb1914b53e8da5e4bf2bc83ac87ce55cc67df7' - + '093d9853d2a83a9c8be969175df7c807a17156df768445dd0874a9271c6537f5' - + 'ce0466473582375f067fa4fcdaf65dbc0139cd75e8c21a482f28c0fb8c3d9f94' - + '22606cc8e88fe28fe73ec3cb10ff0e8cc5f2a49e540f007265c65b7130bfdb98' - + '795b1df9522da46e48b30e55d9f0d787955ece720205b29c85f3ad9be33b4459' - + '7d21b54d06c9a60b04b8e640c64e566e51566730e86cf128ab14174f91bd8981' - + 'a6fb00fe587bbd6c38b5a1dfdb04ea7e61536fd229f957aa9b070ca931358e85' - + '11b92c53c523cb54828fb1513c5636fa9a0645b4a3c922c0db94986d92f314ff' - + '7852c03b231e4dceea5dd8cced621869cff818daf3c270ff3c8be2e5c74be767' - + 'a4e1fdf3327a934fe31e46df5a74ae2021cee021d958c4f615263d99a5ddae7f' - + 'eab45e6eccbafefe4761c57750847b7e75ee2e2f14333c0779ce4678f47b1e1b' - + '760a03a5f17d6e91d4b42313b3f1077ee270e432fe04917ed1fc8babebf7c941' - + '42b80dfb44a28a2a3e59093027606f6860bfb8c2e5897078cfccda7314c70035' - + 'f137de6f05daa035891d5f6f76e1df0fce1112a2ff0ac2bd3534b5d1bf4c7165' - + 'fb40a1b6eacb7f295711c4907ae457514a7010f3a342b4427593d61ba993bc59' - + '8bd09c56b9ee53aac5dd861fa4b4bb53888952a4aa9d8ca8671582de716270e1' - + '97375b3ee49e51fa2bf4ef32015dd9a764d966aa2ae541592d0aa650849e99ca' - + '5c6c39beebf516457cc32fe4c105bff314a12f1ec94bdf4d626f5d9b1cbbde42' - + 'e5733f0885765ba29e2e82c829d312f5fc7e180679ac84826c08d0a644b326d0' - + '44da0fdcc75fa53cfe4ced0437fa4df5a7ecbca8b4cb7c4a9ecf9a60d00a56eb' - + '81da52adc21f508dbb60a9503a3cc94a896616d86020d5b0e5c637329b6d396a' - + '41a21ba2c4a9493cf33fa2d4f10f77d5b12fdad7e478ccfe79b74851fc96a7ca' - + '6320c5efd561a222c0ab0fb44bbda0e42149611d2262bb7d1719150fa798718a' - + '0eec63ee297cad459869c8b0f06c4e2b56cbac03cd2605b2a924efedf85ec8f1' - + '9b0b6c90e7cbd933223ffeb1b3a3f9677657905829294c4c70acdb8b0891b47d' - + '0875d0cd6c0f4efe2917fc44b581ef0d1e4280197065d07da34ab33283364552' - + 'efad0bd9257b059acdd0a6f246812feb69e7e76065f27dbc2eee94da9cc41835' - + 'bf826e36e5cebe5d4d6a37a6a666246290ce51a0c082718ab0ec855668db1add' - + 'a658e5f257e0db39384d02e6145c4c00eaa079098f6d820d872de711b6ed08cf', - '0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C', - '256 bits key, Set 6, vector# 3', - dict (iv='288FF65DC42B92F9')), - + # Test vectors are taken from + # http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors + ( + "00" * 512, + "4dfa5e481da23ea09a31022050859936da52fcee218005164f267cb65f5cfd7f" + + "2b4f97e0ff16924a52df269515110a07f9e460bc65ef95da58f740b7d1dbb0aa" + + "d64cec189c7eb8c6bbf3d7376c80a481d43e628701f6a27afb9fe23919f24114" + + "8db44f70d7063efcc3dd55a0893a613c3c6fe1c127bd6f59910589293bb6ef9e" + + "e24819066dee1a64f49b0bbad5988635272b169af861f85df881939f29ada6fd" + + "0241410e8d332ae4798d929434a2630de451ec4e0169694cbaa7ebb121ea6a2b" + + "da9c1581f429e0a00f7d67e23b730676783b262e8eb43a25f55fb90b3e753aef" + + "8c6713ec66c51881111593ccb3e8cb8f8de124080501eeeb389c4bcb6977cf95" + + "7d5789631eb4554400e1e025935dfa7b3e9039d61bdc58a8697d36815bf1985c" + + "efdf7ae112e5bb81e37ecf0616ce7147fc08a93a367e08631f23c03b00a8da2f" + + "aa5024e5c8d30aca43fc2d5082067b21b234bc741d68fb292c6012c3764ccee3" + + "1e364a5403e00cfee338a21a01e7d3cefd5a770ca0ab48c435ea6116435f7ad8" + + "30b217b49f978a68e207ed9f462af7fb195b2115fe8f24f152e4ddc32202d6f2" + + "b52fafbcfbc202d8a259a611e901d3f62d065eb13f09bbc45cd45119b843efaa" + + "b375703739daced4dd4059fd71c3c47fc2f9939670fad4a46066adcc6a564578" + + "3308b90ffb72be04a6b147cbe38cc0c3b9267c296a92a7c69873f9f263be9703", + "80000000000000000000000000000000", + "128 bits key, set 1, vector 0", + dict(iv="00" * 8), + ), + ( + "00" * 512, + "e3be8fdd8beca2e3ea8ef9475b29a6e7003951e1097a5c38d23b7a5fad9f6844" + + "b22c97559e2723c7cbbd3fe4fc8d9a0744652a83e72a9c461876af4d7ef1a117" + + "8da2b74eef1b6283e7e20166abcae538e9716e4669e2816b6b20c5c356802001" + + "cc1403a9a117d12a2669f456366d6ebb0f1246f1265150f793cdb4b253e348ae" + + "203d89bc025e802a7e0e00621d70aa36b7e07cb1e7d5b38d5e222b8b0e4b8407" + + "0142b1e29504767d76824850320b5368129fdd74e861b498e3be8d16f2d7d169" + + "57be81f47b17d9ae7c4ff15429a73e10acf250ed3a90a93c711308a74c6216a9" + + "ed84cd126da7f28e8abf8bb63517e1ca98e712f4fb2e1a6aed9fdc73291faa17" + + "958211c4ba2ebd5838c635edb81f513a91a294e194f1c039aeec657dce40aa7e" + + "7c0af57cacefa40c9f14b71a4b3456a63e162ec7d8d10b8ffb1810d71001b618" + + "2f9f73da53b85405c11f7b2d890fa8ae0c7f2e926d8a98c7ec4e91b65120e988" + + "349631a700c6facec3471cb0413656e75e309456584084d7e12c5b43a41c43ed" + + "9a048abd9b880da65f6a665a20fe7b77cd292fe62cae644b7f7df69f32bdb331" + + "903e6505ce44fdc293920c6a9ec7057e23df7dad298f82ddf4efb7fdc7bfc622" + + "696afcfd0cddcc83c7e77f11a649d79acdc3354e9635ff137e929933a0bd6f53" + + "77efa105a3a4266b7c0d089d08f1e855cc32b15b93784a36e56a76cc64bc8477", + "8000000000000000000000000000000000000000000000000000000000000000", + "256 bits key, set 1, vector 0", + dict(iv="00" * 8), + ), + ( + "00" * 512, + "169060ccb42bea7bee4d8012a02f3635eb7bca12859fa159cd559094b3507db8" + + "01735d1a1300102a9c9415546829cbd2021ba217b39b81d89c55b13d0c603359" + + "3f84159a3c84f4b4f4a0edcd9d38ff261a737909e0b66d68b5cac496f3a5be99" + + "cb12c321ab711afaab36cc0947955e1a9bb952ed54425e7711279fbc81bb83f5" + + "6e55cea44e6daddb05858a153ea6213b3350c12aa1a83ef2726f09485fa71790" + + "f9b9f922c7dda1113b1f9d56658ed3402803f511bc1f122601d5e7f0ff036e23" + + "23ef24bb24195b9fd574823cd8a40c29d86bd35c191e2038779ff696c712b6d8" + + "2e7014dbe1ac5d527af076c088c4a8d44317958189f6ef54933a7e0816b5b916" + + "d8f12ed8afe9422b85e5cc9b8adec9d6cfabe8dbc1082bccc02f5a7266aa074c" + + "a284e583a35837798cc0e69d4ce937653b8cdd65ce414b89138615ccb165ad19" + + "3c6b9c3d05eef4be921a10ea811fe61d11c6867600188e065daff90b509ec56b" + + "d41e7e8968c478c78d590c2d2ee24ea009c8f49bc3d81672cfc47895a9e21c9a" + + "471ebf8e294bee5d2de436ac8d052bf31111b345f1da23c3a4d13b9fc5f0900a" + + "a298f98f538973b8fad40d4d159777de2cfe2a3dead1645ddb49794827dba040" + + "f70a0ff4ecd155e0f033604693a51e2363880e2ecf98699e7174af7c2c6b0fc6" + + "59ae329599a3949272a37b9b2183a0910922a3f325ae124dcbdd735364055ceb", + "09090909090909090909090909090909", + "128 bits key, set 2, vector 9", + dict(iv="00" * 8), + ), + ( + "00" * 512, + "7041e747ceb22ed7812985465f50333124f971da1c5d6efe5ca201b886f31046" + + "e757e5c3ec914f60ed1f6bce2819b6810953f12b8ba1199bf82d746a8b8a88f1" + + "142002978ec4c35b95dc2c82990f9e847a0ab45f2ca72625f5190c820f29f3aa" + + "f5f0b5572b06b70a144f2a240c3b3098d4831fa1ce1459f8d1df226a6a79b0ab" + + "41e91799ef31b5ff3d756c19126b19025858ee70fbd69f2be955cb011c005e31" + + "32b271b378f39b0cb594e95c99ce6ff17735a541891845bbf0450afcb4a850b9" + + "4ee90afb713ae7e01295c74381180a3816d7020d5a396c0d97aaa783eaabb6ec" + + "44d5111157f2212d1b1b8fca7893e8b520cd482418c272ab119b569a2b9598eb" + + "355624d12e79adab81153b58cd22eaf1b2a32395dedc4a1c66f4d274070b9800" + + "ea95766f0245a8295f8aadb36ddbbdfa936417c8dbc6235d19494036964d3e70" + + "b125b0f800c3d53881d9d11e7970f827c2f9556935cd29e927b0aceb8cae5fd4" + + "0fd88a8854010a33db94c96c98735858f1c5df6844f864feaca8f41539313e7f" + + "3c0610214912cd5e6362197646207e2d64cd5b26c9dfe0822629dcbeb16662e8" + + "9ff5bf5cf2e499138a5e27bd5027329d0e68ddf53103e9e409523662e27f61f6" + + "5cf38c1232023e6a6ef66c315bcb2a4328642faabb7ca1e889e039e7c444b34b" + + "b3443f596ac730f3df3dfcdb343c307c80f76e43e8898c5e8f43dc3bb280add0", + "0909090909090909090909090909090909090909090909090909090909090909", + "256 bits key, set 2, vector 9", + dict(iv="00" * 8), + ), + ( + "00" * 1024, + "71daee5142d0728b41b6597933ebf467e43279e30978677078941602629cbf68" + + "b73d6bd2c95f118d2b3e6ec955dabb6dc61c4143bc9a9b32b99dbe6866166dc0" + + "8631b7d6553050303d7252c264d3a90d26c853634813e09ad7545a6ce7e84a5d" + + "fc75ec43431207d5319970b0faadb0e1510625bb54372c8515e28e2accf0a993" + + "0ad15f431874923d2a59e20d9f2a5367dba6051564f150287debb1db536ff9b0" + + "9ad981f25e5010d85d76ee0c305f755b25e6f09341e0812f95c94f42eead346e" + + "81f39c58c5faa2c88953dc0cac90469db2063cb5cdb22c9eae22afbf0506fca4" + + "1dc710b846fbdfe3c46883dd118f3a5e8b11b6afd9e71680d8666557301a2daa" + + "fb9496c559784d35a035360885f9b17bd7191977deea932b981ebdb29057ae3c" + + "92cfeff5e6c5d0cb62f209ce342d4e35c69646ccd14e53350e488bb310a32f8b" + + "0248e70acc5b473df537ced3f81a014d4083932bedd62ed0e447b6766cd2604b" + + "706e9b346c4468beb46a34ecf1610ebd38331d52bf33346afec15eefb2a7699e" + + "8759db5a1f636a48a039688e39de34d995df9f27ed9edc8dd795e39e53d9d925" + + "b278010565ff665269042f05096d94da3433d957ec13d2fd82a0066283d0d1ee" + + "b81bf0ef133b7fd90248b8ffb499b2414cd4fa003093ff0864575a43749bf596" + + "02f26c717fa96b1d057697db08ebc3fa664a016a67dcef8807577cc3a09385d3" + + "f4dc79b34364bb3b166ce65fe1dd28e3950fe6fa81063f7b16ce1c0e6daac1f8" + + "188455b77752045e863c9b256ad92bc6e2d08314c5bba191c274f42dfbb3d652" + + "bb771956555e880f84cd8b827a4c5a52f3a099fa0259bd4aac3efd541f191170" + + "4412d6e85fbcc628b335875b9fef24807f6e1bc66c3186159e1e7f5a13913e02" + + "d241ce2efdbcaa275039fb14eac5923d17ffbc7f1abd3b45e92127575bfbabf9" + + "3a257ebef0aa1437b326e41b585af572f7239c33b32981a1577a4f629b027e1e" + + "b49d58cc497e944d79cef44357c2bf25442ab779651e991147bf79d6fd3a8868" + + "0cd3b1748e07fd10d78aceef6db8a5e563570d40127f754146c34a440f2a991a" + + "23fa39d365141f255041f2135c5cba4373452c114da1801bacca38610e3a6524" + + "2b822d32de4ab5a7d3cf9b61b37493c863bd12e2cae10530cddcda2cb7a5436b" + + "ef8988d4d24e8cdc31b2d2a3586340bc5141f8f6632d0dd543bfed81eb471ba1" + + "f3dc2225a15ffddcc03eb48f44e27e2aa390598adf83f15c6608a5f18d4dfcf0" + + "f547d467a4d70b281c83a595d7660d0b62de78b9cca023cca89d7b1f83484638" + + "0e228c25f049184a612ef5bb3d37454e6cfa5b10dceda619d898a699b3c8981a" + + "173407844bb89b4287bf57dd6600c79e352c681d74b03fa7ea0d7bf6ad69f8a6" + + "8ecb001963bd2dd8a2baa0083ec09751cd9742402ad716be16d5c052304cfca1", + "0F62B5085BAE0154A7FA4DA0F34699EC", + "128 bits key, Set 6, vector# 3", + dict(iv="288FF65DC42B92F9"), + ), + ( + "00" * 1024, + "5e5e71f90199340304abb22a37b6625bf883fb89ce3b21f54a10b81066ef87da" + + "30b77699aa7379da595c77dd59542da208e5954f89e40eb7aa80a84a6176663f" + + "d910cde567cf1ff60f7040548d8f376bfd1f44c4774aac37410ede7d5c3463fc" + + "4508a603201d8495ad257894e5eb1914b53e8da5e4bf2bc83ac87ce55cc67df7" + + "093d9853d2a83a9c8be969175df7c807a17156df768445dd0874a9271c6537f5" + + "ce0466473582375f067fa4fcdaf65dbc0139cd75e8c21a482f28c0fb8c3d9f94" + + "22606cc8e88fe28fe73ec3cb10ff0e8cc5f2a49e540f007265c65b7130bfdb98" + + "795b1df9522da46e48b30e55d9f0d787955ece720205b29c85f3ad9be33b4459" + + "7d21b54d06c9a60b04b8e640c64e566e51566730e86cf128ab14174f91bd8981" + + "a6fb00fe587bbd6c38b5a1dfdb04ea7e61536fd229f957aa9b070ca931358e85" + + "11b92c53c523cb54828fb1513c5636fa9a0645b4a3c922c0db94986d92f314ff" + + "7852c03b231e4dceea5dd8cced621869cff818daf3c270ff3c8be2e5c74be767" + + "a4e1fdf3327a934fe31e46df5a74ae2021cee021d958c4f615263d99a5ddae7f" + + "eab45e6eccbafefe4761c57750847b7e75ee2e2f14333c0779ce4678f47b1e1b" + + "760a03a5f17d6e91d4b42313b3f1077ee270e432fe04917ed1fc8babebf7c941" + + "42b80dfb44a28a2a3e59093027606f6860bfb8c2e5897078cfccda7314c70035" + + "f137de6f05daa035891d5f6f76e1df0fce1112a2ff0ac2bd3534b5d1bf4c7165" + + "fb40a1b6eacb7f295711c4907ae457514a7010f3a342b4427593d61ba993bc59" + + "8bd09c56b9ee53aac5dd861fa4b4bb53888952a4aa9d8ca8671582de716270e1" + + "97375b3ee49e51fa2bf4ef32015dd9a764d966aa2ae541592d0aa650849e99ca" + + "5c6c39beebf516457cc32fe4c105bff314a12f1ec94bdf4d626f5d9b1cbbde42" + + "e5733f0885765ba29e2e82c829d312f5fc7e180679ac84826c08d0a644b326d0" + + "44da0fdcc75fa53cfe4ced0437fa4df5a7ecbca8b4cb7c4a9ecf9a60d00a56eb" + + "81da52adc21f508dbb60a9503a3cc94a896616d86020d5b0e5c637329b6d396a" + + "41a21ba2c4a9493cf33fa2d4f10f77d5b12fdad7e478ccfe79b74851fc96a7ca" + + "6320c5efd561a222c0ab0fb44bbda0e42149611d2262bb7d1719150fa798718a" + + "0eec63ee297cad459869c8b0f06c4e2b56cbac03cd2605b2a924efedf85ec8f1" + + "9b0b6c90e7cbd933223ffeb1b3a3f9677657905829294c4c70acdb8b0891b47d" + + "0875d0cd6c0f4efe2917fc44b581ef0d1e4280197065d07da34ab33283364552" + + "efad0bd9257b059acdd0a6f246812feb69e7e76065f27dbc2eee94da9cc41835" + + "bf826e36e5cebe5d4d6a37a6a666246290ce51a0c082718ab0ec855668db1add" + + "a658e5f257e0db39384d02e6145c4c00eaa079098f6d820d872de711b6ed08cf", + "0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C", + "256 bits key, Set 6, vector# 3", + dict(iv="288FF65DC42B92F9"), + ), ] class KeyLength(unittest.TestCase): - - def runTest(self): - - nonce = bchr(0) * 8 - for key_length in (15, 30, 33): - key = bchr(1) * key_length - self.assertRaises(ValueError, Salsa20.new, key, nonce) + def runTest(self): + nonce = bchr(0) * 8 + for key_length in (15, 30, 33): + key = bchr(1) * key_length + self.assertRaises(ValueError, Salsa20.new, key, nonce) class NonceTests(unittest.TestCase): + def test_invalid_nonce_length(self): + key = bchr(1) * 16 + self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 7) + self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 9) - def test_invalid_nonce_length(self): - key = bchr(1) * 16 - self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 7) - self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 9) - - def test_default_nonce(self): - - cipher1 = Salsa20.new(bchr(1) * 16) - cipher2 = Salsa20.new(bchr(1) * 16) - self.assertEqual(len(cipher1.nonce), 8) - self.assertNotEqual(cipher1.nonce, cipher2.nonce) + def test_default_nonce(self): + cipher1 = Salsa20.new(bchr(1) * 16) + cipher2 = Salsa20.new(bchr(1) * 16) + self.assertEqual(len(cipher1.nonce), 8) + self.assertNotEqual(cipher1.nonce, cipher2.nonce) class ByteArrayTest(unittest.TestCase): - """Verify we can encrypt or decrypt bytearrays""" + """Verify we can encrypt or decrypt bytearrays""" - def runTest(self): + def runTest(self): + data = b"0123" + key = b"9" * 32 + nonce = b"t" * 8 - data = b"0123" - key = b"9" * 32 - nonce = b"t" * 8 + # Encryption + data_ba = bytearray(data) + key_ba = bytearray(key) + nonce_ba = bytearray(nonce) - # Encryption - data_ba = bytearray(data) - key_ba = bytearray(key) - nonce_ba = bytearray(nonce) + cipher1 = Salsa20.new(key=key, nonce=nonce) + ct = cipher1.encrypt(data) - cipher1 = Salsa20.new(key=key, nonce=nonce) - ct = cipher1.encrypt(data) + cipher2 = Salsa20.new(key=key_ba, nonce=nonce_ba) + key_ba[:1] = b"\xff" + nonce_ba[:1] = b"\xff" + ct_test = cipher2.encrypt(data_ba) - cipher2 = Salsa20.new(key=key_ba, nonce=nonce_ba) - key_ba[:1] = b'\xFF' - nonce_ba[:1] = b'\xFF' - ct_test = cipher2.encrypt(data_ba) + self.assertEqual(ct, ct_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) - self.assertEqual(ct, ct_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) + # Decryption + key_ba = bytearray(key) + nonce_ba = bytearray(nonce) + ct_ba = bytearray(ct) - # Decryption - key_ba = bytearray(key) - nonce_ba = bytearray(nonce) - ct_ba = bytearray(ct) + cipher3 = Salsa20.new(key=key_ba, nonce=nonce_ba) + key_ba[:1] = b"\xff" + nonce_ba[:1] = b"\xff" + pt_test = cipher3.decrypt(ct_ba) - cipher3 = Salsa20.new(key=key_ba, nonce=nonce_ba) - key_ba[:1] = b'\xFF' - nonce_ba[:1] = b'\xFF' - pt_test = cipher3.decrypt(ct_ba) - - self.assertEqual(data, pt_test) + self.assertEqual(data, pt_test) class MemoryviewTest(unittest.TestCase): - """Verify we can encrypt or decrypt bytearrays""" - - def runTest(self): + """Verify we can encrypt or decrypt bytearrays""" - data = b"0123" - key = b"9" * 32 - nonce = b"t" * 8 + def runTest(self): + data = b"0123" + key = b"9" * 32 + nonce = b"t" * 8 - # Encryption - data_mv = memoryview(bytearray(data)) - key_mv = memoryview(bytearray(key)) - nonce_mv = memoryview(bytearray(nonce)) + # Encryption + data_mv = memoryview(bytearray(data)) + key_mv = memoryview(bytearray(key)) + nonce_mv = memoryview(bytearray(nonce)) - cipher1 = Salsa20.new(key=key, nonce=nonce) - ct = cipher1.encrypt(data) + cipher1 = Salsa20.new(key=key, nonce=nonce) + ct = cipher1.encrypt(data) - cipher2 = Salsa20.new(key=key_mv, nonce=nonce_mv) - key_mv[:1] = b'\xFF' - nonce_mv[:1] = b'\xFF' - ct_test = cipher2.encrypt(data_mv) + cipher2 = Salsa20.new(key=key_mv, nonce=nonce_mv) + key_mv[:1] = b"\xff" + nonce_mv[:1] = b"\xff" + ct_test = cipher2.encrypt(data_mv) - self.assertEqual(ct, ct_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) + self.assertEqual(ct, ct_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) - # Decryption - key_mv = memoryview(bytearray(key)) - nonce_mv = memoryview(bytearray(nonce)) - ct_mv = memoryview(bytearray(ct)) + # Decryption + key_mv = memoryview(bytearray(key)) + nonce_mv = memoryview(bytearray(nonce)) + ct_mv = memoryview(bytearray(ct)) - cipher3 = Salsa20.new(key=key_mv, nonce=nonce_mv) - key_mv[:1] = b'\xFF' - nonce_mv[:1] = b'\xFF' - pt_test = cipher3.decrypt(ct_mv) + cipher3 = Salsa20.new(key=key_mv, nonce=nonce_mv) + key_mv[:1] = b"\xff" + nonce_mv[:1] = b"\xff" + pt_test = cipher3.decrypt(ct_mv) - self.assertEqual(data, pt_test) + self.assertEqual(data, pt_test) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter + key = b"4" * 32 + nonce = b"5" * 8 + cipher = Salsa20.new(key=key, nonce=nonce) - key = b'4' * 32 - nonce = b'5' * 8 - cipher = Salsa20.new(key=key, nonce=nonce) + pt = b"5" * 300 + ct = cipher.encrypt(pt) - pt = b'5' * 300 - ct = cipher.encrypt(pt) + output = bytearray(len(pt)) + cipher = Salsa20.new(key=key, nonce=nonce) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - output = bytearray(len(pt)) - cipher = Salsa20.new(key=key, nonce=nonce) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) + cipher = Salsa20.new(key=key, nonce=nonce) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - cipher = Salsa20.new(key=key, nonce=nonce) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(len(pt))) + cipher = Salsa20.new(key=key, nonce=nonce) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(len(pt))) - cipher = Salsa20.new(key=key, nonce=nonce) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + cipher = Salsa20.new(key=key, nonce=nonce) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - cipher = Salsa20.new(key=key, nonce=nonce) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher = Salsa20.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * len(pt)) - cipher = Salsa20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*len(pt)) + cipher = Salsa20.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * len(ct)) - cipher = Salsa20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*len(ct)) + shorter_output = bytearray(len(pt) - 1) - shorter_output = bytearray(len(pt) - 1) + cipher = Salsa20.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = Salsa20.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - - cipher = Salsa20.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + cipher = Salsa20.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - tests = make_stream_tests(Salsa20, "Salsa20", test_data) - tests.append(KeyLength()) - tests += list_test_cases(NonceTests) - tests.append(ByteArrayTest()) - tests.append(MemoryviewTest()) - tests.append(TestOutput()) + tests = make_stream_tests(Salsa20, "Salsa20", test_data) + tests.append(KeyLength()) + tests += list_test_cases(NonceTests) + tests.append(ByteArrayTest()) + tests.append(MemoryviewTest()) + tests.append(TestOutput()) + + return tests - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_pkcs1_15.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_pkcs1_15.py index 12c09dd6..e72d7baf 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_pkcs1_15.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_pkcs1_15.py @@ -34,41 +34,39 @@ def rws(t): - """Remove white spaces, tabs, and new lines from a string""" - for c in ['\n', '\t', ' ']: - t = t.replace(c, '') - return t + """Remove white spaces, tabs, and new lines from a string""" + for c in ["\n", "\t", " "]: + t = t.replace(c, "") + return t def t2b(t): - """Convert a text string with bytes in hex form to a byte string""" - clean = b(rws(t)) - if len(clean) % 2 == 1: - raise ValueError("Even number of characters expected") - return a2b_hex(clean) + """Convert a text string with bytes in hex form to a byte string""" + clean = b(rws(t)) + if len(clean) % 2 == 1: + raise ValueError("Even number of characters expected") + return a2b_hex(clean) class PKCS1_15_Tests(unittest.TestCase): - - def setUp(self): - self.rng = Random.new().read - self.key1024 = RSA.generate(1024, self.rng) - - # List of tuples with test data for PKCS#1 v1.5. - # Each tuple is made up by: - # Item #0: dictionary with RSA key component, or key to import - # Item #1: plaintext - # Item #2: ciphertext - # Item #3: random data - - _testData = ( - - # - # Generated with openssl 0.9.8o - # - ( - # Private key - '''-----BEGIN RSA PRIVATE KEY----- + def setUp(self): + self.rng = Random.new().read + self.key1024 = RSA.generate(1024, self.rng) + + # List of tuples with test data for PKCS#1 v1.5. + # Each tuple is made up by: + # Item #0: dictionary with RSA key component, or key to import + # Item #1: plaintext + # Item #2: ciphertext + # Item #3: random data + + _testData = ( + # + # Generated with openssl 0.9.8o + # + ( + # Private key + """-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDAiAnvIAOvqVwJTaYzsKnefZftgtXGE2hPJppGsWl78yz9jeXY W/FxX/gTPURArNhdnhP6n3p2ZaDIBrO2zizbgIXs0IsljTTcr4vnI8fMXzyNUOjA zP3nzMqZDZK6757XQAobOssMkBFqRWwilT/3DsBhRpl3iMUhF+wvpTSHewIDAQAB @@ -82,202 +80,205 @@ def setUp(self): 1JYNMtRen5unSAbIOxRcKkWz92F0LKpm9ZW/S9vFHO+mBcClMGoKJHiuQxLBsLbT NtEZfSJZAeS2sUtn3/0CQDb2M2zNBTF8LlM0nxmh0k9VGm5TVIyBEMcipmvOgqIs HKukWBcq9f/UOmS0oEhai/6g+Uf7VHJdWaeO5LzuvwU= ------END RSA PRIVATE KEY-----''', - # Plaintext - '''THIS IS PLAINTEXT\x0A''', - # Ciphertext - '''3f dc fd 3c cd 5c 9b 12 af 65 32 e3 f7 d0 da 36 +-----END RSA PRIVATE KEY-----""", + # Plaintext + """THIS IS PLAINTEXT\x0a""", + # Ciphertext + """3f dc fd 3c cd 5c 9b 12 af 65 32 e3 f7 d0 da 36 8f 8f d9 e3 13 1c 7f c8 b3 f9 c1 08 e4 eb 79 9c 91 89 1f 96 3b 94 77 61 99 a4 b1 ee 5d e6 17 c9 5d 0a b5 63 52 0a eb 00 45 38 2a fb b0 71 3d 11 f7 a1 9e a7 69 b3 af 61 c0 bb 04 5b 5d 4b 27 44 1f 5b 97 89 ba 6a 08 95 ee 4f a2 eb 56 64 e5 0f da 7c f9 9a 61 61 06 62 ed a0 bc 5f aa 6c 31 78 - 70 28 1a bb 98 3c e3 6a 60 3c d1 0b 0f 5a f4 75''', - # Random data - '''eb d7 7d 86 a4 35 23 a3 54 7e 02 0b 42 1d + 70 28 1a bb 98 3c e3 6a 60 3c d1 0b 0f 5a f4 75""", + # Random data + """eb d7 7d 86 a4 35 23 a3 54 7e 02 0b 42 1d 61 6c af 67 b8 4e 17 56 80 66 36 04 64 34 26 8a 47 dd 44 b3 1a b2 17 60 f4 91 2e e2 b5 95 64 cc f9 da c8 70 94 54 86 4c ef 5b 08 7d 18 c4 ab 8d 04 06 33 8f ca 15 5f 52 60 8a a1 0c f5 08 b5 4c bb 99 b8 94 25 04 9c e6 01 75 e6 f9 63 7a 65 61 - 13 8a a7 47 77 81 ae 0d b8 2c 4d 50 a5''' - ), - ) - - def testEncrypt1(self): - for test in self._testData: - # Build the key - key = RSA.importKey(test[0]) - # RNG that takes its random numbers from a pool given - # at initialization - class randGen: - def __init__(self, data): - self.data = data - self.idx = 0 - def __call__(self, N): - r = self.data[self.idx:self.idx+N] - self.idx += N - return r - # The real test - cipher = PKCS.new(key, randfunc=randGen(t2b(test[3]))) - ct = cipher.encrypt(b(test[1])) - self.assertEqual(ct, t2b(test[2])) - - def testEncrypt2(self): - # Verify that encryption fail if plaintext is too long - pt = '\x00'*(128-11+1) - cipher = PKCS.new(self.key1024) - self.assertRaises(ValueError, cipher.encrypt, pt) - - def testVerify1(self): - for test in self._testData: - key = RSA.importKey(test[0]) - expected_pt = b(test[1]) - ct = t2b(test[2]) - cipher = PKCS.new(key) - - # The real test - pt = cipher.decrypt(ct, None) - self.assertEqual(pt, expected_pt) - - pt = cipher.decrypt(ct, b'\xFF' * len(expected_pt)) - self.assertEqual(pt, expected_pt) - - def testVerify2(self): - # Verify that decryption fails if ciphertext is not as long as - # RSA modulus - cipher = PKCS.new(self.key1024) - self.assertRaises(ValueError, cipher.decrypt, '\x00'*127, "---") - self.assertRaises(ValueError, cipher.decrypt, '\x00'*129, "---") - - # Verify that decryption fails if there are less then 8 non-zero padding - # bytes - pt = b('\x00\x02' + '\xFF'*7 + '\x00' + '\x45'*118) - pt_int = bytes_to_long(pt) - ct_int = self.key1024._encrypt(pt_int) - ct = long_to_bytes(ct_int, 128) - self.assertEqual(b"---", cipher.decrypt(ct, b"---")) - - def testEncryptVerify1(self): - # Encrypt/Verify messages of length [0..RSAlen-11] - # and therefore padding [8..117] - for pt_len in range(0, 128 - 11 + 1): - pt = self.rng(pt_len) - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(pt) - pt2 = cipher.decrypt(ct, b'\xAA' * pt_len) - self.assertEqual(pt, pt2) - - def test_encrypt_verify_exp_pt_len(self): - - cipher = PKCS.new(self.key1024) - pt = b'5' * 16 - ct = cipher.encrypt(pt) - sentinel = b'\xAA' * 16 - - pt_A = cipher.decrypt(ct, sentinel, 16) - self.assertEqual(pt, pt_A) - - pt_B = cipher.decrypt(ct, sentinel, 15) - self.assertEqual(sentinel, pt_B) - - pt_C = cipher.decrypt(ct, sentinel, 17) - self.assertEqual(sentinel, pt_C) - - def testByteArray(self): - pt = b"XER" - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(bytearray(pt)) - pt2 = cipher.decrypt(bytearray(ct), '\xFF' * len(pt)) - self.assertEqual(pt, pt2) - - def testMemoryview(self): - pt = b"XER" - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(memoryview(bytearray(pt))) - pt2 = cipher.decrypt(memoryview(bytearray(ct)), b'\xFF' * len(pt)) - self.assertEqual(pt, pt2) - - def test_return_type(self): - pt = b"XYZ" - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(pt) - self.assertTrue(isinstance(ct, bytes)) - pt2 = cipher.decrypt(ct, b'\xAA' * 3) - self.assertTrue(isinstance(pt2, bytes)) + 13 8a a7 47 77 81 ae 0d b8 2c 4d 50 a5""", + ), + ) + + def testEncrypt1(self): + for test in self._testData: + # Build the key + key = RSA.importKey(test[0]) + + # RNG that takes its random numbers from a pool given + # at initialization + class randGen: + def __init__(self, data): + self.data = data + self.idx = 0 + + def __call__(self, N): + r = self.data[self.idx : self.idx + N] + self.idx += N + return r + + # The real test + cipher = PKCS.new(key, randfunc=randGen(t2b(test[3]))) + ct = cipher.encrypt(b(test[1])) + self.assertEqual(ct, t2b(test[2])) + + def testEncrypt2(self): + # Verify that encryption fail if plaintext is too long + pt = "\x00" * (128 - 11 + 1) + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.encrypt, pt) + + def testVerify1(self): + for test in self._testData: + key = RSA.importKey(test[0]) + expected_pt = b(test[1]) + ct = t2b(test[2]) + cipher = PKCS.new(key) + + # The real test + pt = cipher.decrypt(ct, None) + self.assertEqual(pt, expected_pt) + + pt = cipher.decrypt(ct, b"\xff" * len(expected_pt)) + self.assertEqual(pt, expected_pt) + + def testVerify2(self): + # Verify that decryption fails if ciphertext is not as long as + # RSA modulus + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.decrypt, "\x00" * 127, "---") + self.assertRaises(ValueError, cipher.decrypt, "\x00" * 129, "---") + + # Verify that decryption fails if there are less then 8 non-zero padding + # bytes + pt = b("\x00\x02" + "\xff" * 7 + "\x00" + "\x45" * 118) + pt_int = bytes_to_long(pt) + ct_int = self.key1024._encrypt(pt_int) + ct = long_to_bytes(ct_int, 128) + self.assertEqual(b"---", cipher.decrypt(ct, b"---")) + + def testEncryptVerify1(self): + # Encrypt/Verify messages of length [0..RSAlen-11] + # and therefore padding [8..117] + for pt_len in range(0, 128 - 11 + 1): + pt = self.rng(pt_len) + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(pt) + pt2 = cipher.decrypt(ct, b"\xaa" * pt_len) + self.assertEqual(pt, pt2) + + def test_encrypt_verify_exp_pt_len(self): + cipher = PKCS.new(self.key1024) + pt = b"5" * 16 + ct = cipher.encrypt(pt) + sentinel = b"\xaa" * 16 + + pt_A = cipher.decrypt(ct, sentinel, 16) + self.assertEqual(pt, pt_A) + + pt_B = cipher.decrypt(ct, sentinel, 15) + self.assertEqual(sentinel, pt_B) + + pt_C = cipher.decrypt(ct, sentinel, 17) + self.assertEqual(sentinel, pt_C) + + def testByteArray(self): + pt = b"XER" + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(bytearray(pt)) + pt2 = cipher.decrypt(bytearray(ct), "\xff" * len(pt)) + self.assertEqual(pt, pt2) + + def testMemoryview(self): + pt = b"XER" + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(memoryview(bytearray(pt))) + pt2 = cipher.decrypt(memoryview(bytearray(ct)), b"\xff" * len(pt)) + self.assertEqual(pt, pt2) + + def test_return_type(self): + pt = b"XYZ" + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(pt) + self.assertTrue(isinstance(ct, bytes)) + pt2 = cipher.decrypt(ct, b"\xaa" * 3) + self.assertTrue(isinstance(pt2, bytes)) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, skip_slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._skip_slow_tests = skip_slow_tests - self._id = "None" - - def load_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['privateKeyPem']) - - result = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - filename, - "Wycheproof PKCS#1v1.5 (%s)" % filename, - group_tag={'rsa_key': filter_rsa} - ) - return result - - def setUp(self): - self.tv = [] - self.tv.extend(self.load_tests("rsa_pkcs1_2048_test.json")) - if not self._skip_slow_tests: - self.tv.extend(self.load_tests("rsa_pkcs1_3072_test.json")) - self.tv.extend(self.load_tests("rsa_pkcs1_4096_test.json")) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt PKCS#1v1.5 Test #%s" % tv.id - sentinel = b'\xAA' * max(3, len(tv.msg)) - cipher = PKCS.new(tv.rsa_key) - try: - pt = cipher.decrypt(tv.ct, sentinel=sentinel) - except ValueError: - assert not tv.valid - else: - if pt == sentinel: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def runTest(self): - - for tv in self.tv: - self.test_decrypt(tv) + def __init__(self, wycheproof_warnings, skip_slow_tests): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._skip_slow_tests = skip_slow_tests + self._id = "None" + + def load_tests(self, filename): + def filter_rsa(group): + return RSA.import_key(group["privateKeyPem"]) + + result = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + filename, + "Wycheproof PKCS#1v1.5 (%s)" % filename, + group_tag={"rsa_key": filter_rsa}, + ) + return result + + def setUp(self): + self.tv = [] + self.tv.extend(self.load_tests("rsa_pkcs1_2048_test.json")) + if not self._skip_slow_tests: + self.tv.extend(self.load_tests("rsa_pkcs1_3072_test.json")) + self.tv.extend(self.load_tests("rsa_pkcs1_4096_test.json")) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt PKCS#1v1.5 Test #%s" % tv.id + sentinel = b"\xaa" * max(3, len(tv.msg)) + cipher = PKCS.new(tv.rsa_key) + try: + pt = cipher.decrypt(tv.ct, sentinel=sentinel) + except ValueError: + assert not tv.valid + else: + if pt == sentinel: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_decrypt(tv) def get_tests(config={}): - skip_slow_tests = not config.get('slow_tests') - wycheproof_warnings = config.get('wycheproof_warnings') + skip_slow_tests = not config.get("slow_tests") + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(PKCS1_15_Tests) + tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)] + return tests + - tests = [] - tests += list_test_cases(PKCS1_15_Tests) - tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)] - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_pkcs1_oaep.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_pkcs1_oaep.py index aa00c9cf..7052fe3f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_pkcs1_oaep.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Cipher/test_pkcs1_oaep.py @@ -35,133 +35,127 @@ def rws(t): - """Remove white spaces, tabs, and new lines from a string""" - for c in ['\n', '\t', ' ']: - t = t.replace(c, '') - return t + """Remove white spaces, tabs, and new lines from a string""" + for c in ["\n", "\t", " "]: + t = t.replace(c, "") + return t def t2b(t): - """Convert a text string with bytes in hex form to a byte string""" - clean = rws(t) - if len(clean) % 2 == 1: - raise ValueError("Even number of characters expected") - return a2b_hex(clean) + """Convert a text string with bytes in hex form to a byte string""" + clean = rws(t) + if len(clean) % 2 == 1: + raise ValueError("Even number of characters expected") + return a2b_hex(clean) class PKCS1_OAEP_Tests(unittest.TestCase): - - def setUp(self): - self.rng = Random.new().read - self.key1024 = RSA.generate(1024, self.rng) - - # List of tuples with test data for PKCS#1 OAEP - # Each tuple is made up by: - # Item #0: dictionary with RSA key component - # Item #1: plaintext - # Item #2: ciphertext - # Item #3: random data (=seed) - # Item #4: hash object - - _testData = ( - - # - # From in oaep-int.txt to be found in - # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - # - ( - # Private key - { - 'n':'''bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 + def setUp(self): + self.rng = Random.new().read + self.key1024 = RSA.generate(1024, self.rng) + + # List of tuples with test data for PKCS#1 OAEP + # Each tuple is made up by: + # Item #0: dictionary with RSA key component + # Item #1: plaintext + # Item #2: ciphertext + # Item #3: random data (=seed) + # Item #4: hash object + + _testData = ( + # + # From in oaep-int.txt to be found in + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + "n": """bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48 76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84 ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f - e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb''', - # Public key - 'e':'11', - # In the test vector, only p and q were given... - # d is computed offline as e^{-1} mod (p-1)(q-1) - 'd':'''a5dafc5341faf289c4b988db30c1cdf83f31251e0 + e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb""", + # Public key + "e": "11", + # In the test vector, only p and q were given... + # d is computed offline as e^{-1} mod (p-1)(q-1) + "d": """a5dafc5341faf289c4b988db30c1cdf83f31251e0 668b42784813801579641b29410b3c7998d6bc465745e5c3 92669d6870da2c082a939e37fdcb82ec93edac97ff3ad595 0accfbc111c76f1a9529444e56aaf68c56c092cd38dc3bef 5d20a939926ed4f74a13eddfbe1a1cecc4894af9428c2b7b - 8883fe4463a4bc85b1cb3c1''' - } - , - # Plaintext - '''d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49''', - # Ciphertext - '''12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 + 8883fe4463a4bc85b1cb3c1""", + }, + # Plaintext + """d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49""", + # Ciphertext + """12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7 63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6 53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb 6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0 24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48 da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d - 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55''', - # Random - '''aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2 - f0 6c b5 8f''', - # Hash - SHA1, - ), - - # - # From in oaep-vect.txt to be found in Example 1.1 - # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - # - ( - # Private key - { - 'n':'''a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 + 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55""", + # Random + """aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2 + f0 6c b5 8f""", + # Hash + SHA1, + ), + # + # From in oaep-vect.txt to be found in Example 1.1 + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + "n": """a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85 12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72 f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97 c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14 8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24 - 76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb''', - 'e':'''01 00 01''', - 'd':'''53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c + 76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb""", + "e": """01 00 01""", + "d": """53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c 55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd 8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b 15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55 fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73 2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de - f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 ''' - } - , - # Plaintext - '''66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 - 97 d5 0d ba 79 b9 87 00 4a fe fe 34''', - # Ciphertext - '''35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f + f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 """, + }, + # Plaintext + """66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 + 97 d5 0d ba 79 b9 87 00 4a fe fe 34""", + # Ciphertext + """35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f 7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb 21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01 03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22 d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26 d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c - 40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a''', - # Random - '''18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1 - dd a0 a5 ef''', - SHA1 - ), - - # - # From in oaep-vect.txt to be found in Example 2.1 - # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - # - ( - # Private key - { - 'n':'''01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5 + 40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a""", + # Random + """18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1 + dd a0 a5 ef""", + SHA1, + ), + # + # From in oaep-vect.txt to be found in Example 2.1 + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + "n": """01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5 e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e 49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba 7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d @@ -169,22 +163,22 @@ def setUp(self): de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05 5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66 32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f - 45''', - 'e':'''01 00 01''', - 'd':'''08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa + 45""", + "e": """01 00 01""", + "d": """08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa 4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93 c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47 39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0 8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59 41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25 - 25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39''' - }, - # Plaintext - '''8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6 - 52 b5 8c f1 d9 2f ec 57 0b ee e7''', - # Ciphertext - '''01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99 + 25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39""", + }, + # Plaintext + """8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6 + 52 b5 8c f1 d9 2f ec 57 0b ee e7""", + # Ciphertext + """01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99 2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a 5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34 @@ -192,21 +186,20 @@ def setUp(self): 56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72 - 0e''', - # Random - '''8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94 - e7 1b 17 82''', - SHA1 - ), - - # - # From in oaep-vect.txt to be found in Example 10.1 - # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - # - ( - # Private key - { - 'n':'''ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d + 0e""", + # Random + """8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94 + e7 1b 17 82""", + SHA1, + ), + # + # From in oaep-vect.txt to be found in Example 10.1 + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + "n": """ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8 df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4 02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5 @@ -221,9 +214,9 @@ def setUp(self): a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76 57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88 d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc - 36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb''', - 'e':'''01 00 01''', - 'd':'''05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85 + 36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb""", + "e": """01 00 01""", + "d": """05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85 25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59 6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0 d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d @@ -238,13 +231,13 @@ def setUp(self): 0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87 6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01 84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e - 97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79''' - }, - # Plaintext - '''8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70 - b0 89 53 b0 6b 4e b2 05 bc 16 94 ee''', - # Ciphertext - '''53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15 + 97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79""", + }, + # Plaintext + """8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70 + b0 89 53 b0 6b 4e b2 05 bc 16 94 ee""", + # Ciphertext + """53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15 52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19 ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14 @@ -259,248 +252,250 @@ def setUp(self): ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55 ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64 73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54 - bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc''', - # Random - '''47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0 - aa 63 bd 33''', - SHA1 - ), - ) - - def testEncrypt1(self): - # Verify encryption using all test vectors - for test in self._testData: - # Build the key - comps = [int(rws(test[0][x]), 16) for x in ('n', 'e')] - key = RSA.construct(comps) - - # RNG that takes its random numbers from a pool given - # at initialization - class randGen: - - def __init__(self, data): - self.data = data - self.idx = 0 - - def __call__(self, N): - r = self.data[self.idx:N] - self.idx += N - return r - - # The real test - cipher = PKCS.new(key, test[4], randfunc=randGen(t2b(test[3]))) - ct = cipher.encrypt(t2b(test[1])) - self.assertEqual(ct, t2b(test[2])) - - def testEncrypt2(self): - # Verify that encryption fails if plaintext is too long - pt = '\x00'*(128-2*20-2+1) - cipher = PKCS.new(self.key1024) - self.assertRaises(ValueError, cipher.encrypt, pt) - - def testDecrypt1(self): - # Verify decryption using all test vectors - for test in self._testData: - # Build the key - comps = [int(rws(test[0][x]),16) for x in ('n', 'e', 'd')] - key = RSA.construct(comps) - # The real test - cipher = PKCS.new(key, test[4]) - pt = cipher.decrypt(t2b(test[2])) - self.assertEqual(pt, t2b(test[1])) - - def testDecrypt2(self): - # Simplest possible negative tests - for ct_size in (127, 128, 129): - cipher = PKCS.new(self.key1024) - self.assertRaises(ValueError, cipher.decrypt, bchr(0x00)*ct_size) - - def testEncryptDecrypt1(self): - # Encrypt/Decrypt messages of length [0..128-2*20-2] - for pt_len in range(0, 128-2*20-2): - pt = self.rng(pt_len) - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(pt) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def testEncryptDecrypt2(self): - # Helper function to monitor what's requested from RNG - global asked - - def localRng(N): - global asked - asked += N - return self.rng(N) - - # Verify that OAEP is friendly to all hashes - for hashmod in (MD2, MD5, SHA1, SHA256, RIPEMD160): - # Verify that encrypt() asks for as many random bytes - # as the hash output size - asked = 0 - pt = self.rng(40) - cipher = PKCS.new(self.key1024, hashmod, randfunc=localRng) - ct = cipher.encrypt(pt) - self.assertEqual(cipher.decrypt(ct), pt) - self.assertEqual(asked, hashmod.digest_size) - - def testEncryptDecrypt3(self): - # Verify that OAEP supports labels - pt = self.rng(35) - xlabel = self.rng(22) - cipher = PKCS.new(self.key1024, label=xlabel) - ct = cipher.encrypt(pt) - self.assertEqual(cipher.decrypt(ct), pt) - - def testEncryptDecrypt4(self): - # Verify that encrypt() uses the custom MGF - global mgfcalls - # Helper function to monitor what's requested from MGF - - def newMGF(seed, maskLen): - global mgfcalls - mgfcalls += 1 - return b'\x00' * maskLen - - mgfcalls = 0 - pt = self.rng(32) - cipher = PKCS.new(self.key1024, mgfunc=newMGF) - ct = cipher.encrypt(pt) - self.assertEqual(mgfcalls, 2) - self.assertEqual(cipher.decrypt(ct), pt) - - def testByteArray(self): - pt = b("XER") - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(bytearray(pt)) - pt2 = cipher.decrypt(bytearray(ct)) - self.assertEqual(pt, pt2) - - def testMemoryview(self): - pt = b("XER") - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(memoryview(bytearray(pt))) - pt2 = cipher.decrypt(memoryview(bytearray(ct))) - self.assertEqual(pt, pt2) + bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc""", + # Random + """47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0 + aa 63 bd 33""", + SHA1, + ), + ) + + def testEncrypt1(self): + # Verify encryption using all test vectors + for test in self._testData: + # Build the key + comps = [int(rws(test[0][x]), 16) for x in ("n", "e")] + key = RSA.construct(comps) + + # RNG that takes its random numbers from a pool given + # at initialization + class randGen: + def __init__(self, data): + self.data = data + self.idx = 0 + + def __call__(self, N): + r = self.data[self.idx : N] + self.idx += N + return r + + # The real test + cipher = PKCS.new(key, test[4], randfunc=randGen(t2b(test[3]))) + ct = cipher.encrypt(t2b(test[1])) + self.assertEqual(ct, t2b(test[2])) + + def testEncrypt2(self): + # Verify that encryption fails if plaintext is too long + pt = "\x00" * (128 - 2 * 20 - 2 + 1) + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.encrypt, pt) + + def testDecrypt1(self): + # Verify decryption using all test vectors + for test in self._testData: + # Build the key + comps = [int(rws(test[0][x]), 16) for x in ("n", "e", "d")] + key = RSA.construct(comps) + # The real test + cipher = PKCS.new(key, test[4]) + pt = cipher.decrypt(t2b(test[2])) + self.assertEqual(pt, t2b(test[1])) + + def testDecrypt2(self): + # Simplest possible negative tests + for ct_size in (127, 128, 129): + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.decrypt, bchr(0x00) * ct_size) + + def testEncryptDecrypt1(self): + # Encrypt/Decrypt messages of length [0..128-2*20-2] + for pt_len in range(0, 128 - 2 * 20 - 2): + pt = self.rng(pt_len) + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(pt) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def testEncryptDecrypt2(self): + # Helper function to monitor what's requested from RNG + global asked + + def localRng(N): + global asked + asked += N + return self.rng(N) + + # Verify that OAEP is friendly to all hashes + for hashmod in (MD2, MD5, SHA1, SHA256, RIPEMD160): + # Verify that encrypt() asks for as many random bytes + # as the hash output size + asked = 0 + pt = self.rng(40) + cipher = PKCS.new(self.key1024, hashmod, randfunc=localRng) + ct = cipher.encrypt(pt) + self.assertEqual(cipher.decrypt(ct), pt) + self.assertEqual(asked, hashmod.digest_size) + + def testEncryptDecrypt3(self): + # Verify that OAEP supports labels + pt = self.rng(35) + xlabel = self.rng(22) + cipher = PKCS.new(self.key1024, label=xlabel) + ct = cipher.encrypt(pt) + self.assertEqual(cipher.decrypt(ct), pt) + + def testEncryptDecrypt4(self): + # Verify that encrypt() uses the custom MGF + global mgfcalls + # Helper function to monitor what's requested from MGF + + def newMGF(seed, maskLen): + global mgfcalls + mgfcalls += 1 + return b"\x00" * maskLen + + mgfcalls = 0 + pt = self.rng(32) + cipher = PKCS.new(self.key1024, mgfunc=newMGF) + ct = cipher.encrypt(pt) + self.assertEqual(mgfcalls, 2) + self.assertEqual(cipher.decrypt(ct), pt) + + def testByteArray(self): + pt = b("XER") + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(bytearray(pt)) + pt2 = cipher.decrypt(bytearray(ct)) + self.assertEqual(pt, pt2) + + def testMemoryview(self): + pt = b("XER") + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(memoryview(bytearray(pt))) + pt2 = cipher.decrypt(memoryview(bytearray(ct))) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, skip_slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._skip_slow_tests = skip_slow_tests - self._id = "None" - - def load_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['privateKeyPem']) - - def filter_sha(group): - if group['sha'] == "SHA-1": - return SHA1 - elif group['sha'] == "SHA-224": - return SHA224 - elif group['sha'] == "SHA-256": - return SHA256 - elif group['sha'] == "SHA-384": - return SHA384 - elif group['sha'] == "SHA-512": - return SHA512 - else: - raise ValueError("Unknown sha " + group['sha']) - - def filter_mgf(group): - if group['mgfSha'] == "SHA-1": - return lambda x, y: MGF1(x, y, SHA1) - elif group['mgfSha'] == "SHA-224": - return lambda x, y: MGF1(x, y, SHA224) - elif group['mgfSha'] == "SHA-256": - return lambda x, y: MGF1(x, y, SHA256) - elif group['mgfSha'] == "SHA-384": - return lambda x, y: MGF1(x, y, SHA384) - elif group['mgfSha'] == "SHA-512": - return lambda x, y: MGF1(x, y, SHA512) - else: - raise ValueError("Unknown mgf/sha " + group['mgfSha']) - - def filter_algo(group): - return "%s with MGF1/%s" % (group['sha'], group['mgfSha']) - - result = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - filename, - "Wycheproof PKCS#1 OAEP (%s)" % filename, - group_tag={'rsa_key': filter_rsa, - 'hash_mod': filter_sha, - 'mgf': filter_mgf, - 'algo': filter_algo} - ) - return result - - def setUp(self): - self.tv = [] - self.tv.extend(self.load_tests("rsa_oaep_2048_sha1_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha224_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha256_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha384_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha512_test.json")) - if not self._skip_slow_tests: - self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha256_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha512_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha256_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_misc_test.json")) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id) - - cipher = PKCS.new(tv.rsa_key, hashAlgo=tv.hash_mod, mgfunc=tv.mgf, label=tv.label) - try: - pt = cipher.decrypt(tv.ct) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def runTest(self): - - for tv in self.tv: - self.test_decrypt(tv) + def __init__(self, wycheproof_warnings, skip_slow_tests): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._skip_slow_tests = skip_slow_tests + self._id = "None" + + def load_tests(self, filename): + def filter_rsa(group): + return RSA.import_key(group["privateKeyPem"]) + + def filter_sha(group): + if group["sha"] == "SHA-1": + return SHA1 + elif group["sha"] == "SHA-224": + return SHA224 + elif group["sha"] == "SHA-256": + return SHA256 + elif group["sha"] == "SHA-384": + return SHA384 + elif group["sha"] == "SHA-512": + return SHA512 + else: + raise ValueError("Unknown sha " + group["sha"]) + + def filter_mgf(group): + if group["mgfSha"] == "SHA-1": + return lambda x, y: MGF1(x, y, SHA1) + elif group["mgfSha"] == "SHA-224": + return lambda x, y: MGF1(x, y, SHA224) + elif group["mgfSha"] == "SHA-256": + return lambda x, y: MGF1(x, y, SHA256) + elif group["mgfSha"] == "SHA-384": + return lambda x, y: MGF1(x, y, SHA384) + elif group["mgfSha"] == "SHA-512": + return lambda x, y: MGF1(x, y, SHA512) + else: + raise ValueError("Unknown mgf/sha " + group["mgfSha"]) + + def filter_algo(group): + return "%s with MGF1/%s" % (group["sha"], group["mgfSha"]) + + result = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + filename, + "Wycheproof PKCS#1 OAEP (%s)" % filename, + group_tag={ + "rsa_key": filter_rsa, + "hash_mod": filter_sha, + "mgf": filter_mgf, + "algo": filter_algo, + }, + ) + return result + + def setUp(self): + self.tv = [] + self.tv.extend(self.load_tests("rsa_oaep_2048_sha1_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha224_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha256_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha384_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha512_test.json")) + if not self._skip_slow_tests: + self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha256_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha512_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha256_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_misc_test.json")) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id) + + cipher = PKCS.new(tv.rsa_key, hashAlgo=tv.hash_mod, mgfunc=tv.mgf, label=tv.label) + try: + pt = cipher.decrypt(tv.ct) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_decrypt(tv) def get_tests(config={}): - skip_slow_tests = not config.get('slow_tests') - wycheproof_warnings = config.get('wycheproof_warnings') + skip_slow_tests = not config.get("slow_tests") + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(PKCS1_OAEP_Tests) + tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)] + return tests + - tests = [] - tests += list_test_cases(PKCS1_OAEP_Tests) - tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)] - return tests +if __name__ == "__main__": + def suite(): + unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/__init__.py index 5f5b9992..a6e40944 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/__init__.py @@ -26,37 +26,88 @@ __revision__ = "$Id$" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Hash import test_HMAC; tests += test_HMAC.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_CMAC; tests += test_CMAC.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_MD2; tests += test_MD2.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_MD4; tests += test_MD4.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_MD5; tests += test_MD5.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_RIPEMD160; tests += test_RIPEMD160.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA1; tests += test_SHA1.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA224; tests += test_SHA224.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA256; tests += test_SHA256.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA384; tests += test_SHA384.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA512; tests += test_SHA512.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA3_224; tests += test_SHA3_224.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA3_256; tests += test_SHA3_256.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA3_384; tests += test_SHA3_384.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA3_512; tests += test_SHA3_512.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_keccak; tests += test_keccak.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHAKE; tests += test_SHAKE.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_BLAKE2; tests += test_BLAKE2.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_Poly1305; tests += test_Poly1305.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_cSHAKE; tests += test_cSHAKE.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_KMAC; tests += test_KMAC.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_TupleHash; tests += test_TupleHash.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_KangarooTwelve; tests += test_KangarooTwelve.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_TurboSHAKE; tests += test_TurboSHAKE.get_tests(config=config) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + from Cryptodome.SelfTest.Hash import test_HMAC + + tests += test_HMAC.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_CMAC + + tests += test_CMAC.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_MD2 + + tests += test_MD2.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_MD4 + + tests += test_MD4.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_MD5 + + tests += test_MD5.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_RIPEMD160 + + tests += test_RIPEMD160.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA1 + + tests += test_SHA1.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA224 + + tests += test_SHA224.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA256 + + tests += test_SHA256.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA384 + + tests += test_SHA384.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA512 + + tests += test_SHA512.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA3_224 + + tests += test_SHA3_224.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA3_256 + + tests += test_SHA3_256.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA3_384 + + tests += test_SHA3_384.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA3_512 + + tests += test_SHA3_512.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_keccak + + tests += test_keccak.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHAKE + + tests += test_SHAKE.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_BLAKE2 + + tests += test_BLAKE2.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_Poly1305 + + tests += test_Poly1305.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_cSHAKE + + tests += test_cSHAKE.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_KMAC + + tests += test_KMAC.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_TupleHash + + tests += test_TupleHash.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_KangarooTwelve + + tests += test_KangarooTwelve.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_TurboSHAKE + + tests += test_TurboSHAKE.get_tests(config=config) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/common.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/common.py index 4ed92346..602c0a27 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/common.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/common.py @@ -28,263 +28,262 @@ import sys import unittest import binascii -import Cryptodome.Hash from binascii import hexlify, unhexlify from Cryptodome.Util.py3compat import b, tobytes from Cryptodome.Util.strxor import strxor_c + def t2b(hex_string): - shorter = re.sub(br'\s+', b'', tobytes(hex_string)) - return unhexlify(shorter) + shorter = re.sub(rb"\s+", b"", tobytes(hex_string)) + return unhexlify(shorter) class HashDigestSizeSelfTest(unittest.TestCase): + def __init__(self, hashmod, description, expected, extra_params): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + self.expected = expected + self.description = description + self.extra_params = extra_params - def __init__(self, hashmod, description, expected, extra_params): - unittest.TestCase.__init__(self) - self.hashmod = hashmod - self.expected = expected - self.description = description - self.extra_params = extra_params - - def shortDescription(self): - return self.description + def shortDescription(self): + return self.description - def runTest(self): - if "truncate" not in self.extra_params: - self.assertTrue(hasattr(self.hashmod, "digest_size")) - self.assertEqual(self.hashmod.digest_size, self.expected) - h = self.hashmod.new(**self.extra_params) - self.assertTrue(hasattr(h, "digest_size")) - self.assertEqual(h.digest_size, self.expected) + def runTest(self): + if "truncate" not in self.extra_params: + self.assertTrue(hasattr(self.hashmod, "digest_size")) + self.assertEqual(self.hashmod.digest_size, self.expected) + h = self.hashmod.new(**self.extra_params) + self.assertTrue(hasattr(h, "digest_size")) + self.assertEqual(h.digest_size, self.expected) class HashSelfTest(unittest.TestCase): - - def __init__(self, hashmod, description, expected, input, extra_params): - unittest.TestCase.__init__(self) - self.hashmod = hashmod - self.expected = expected.lower() - self.input = input - self.description = description - self.extra_params = extra_params - - def shortDescription(self): - return self.description - - def runTest(self): - h = self.hashmod.new(**self.extra_params) - h.update(self.input) - - out1 = binascii.b2a_hex(h.digest()) - out2 = h.hexdigest() - - h = self.hashmod.new(self.input, **self.extra_params) - - out3 = h.hexdigest() - out4 = binascii.b2a_hex(h.digest()) - - # PY3K: hexdigest() should return str(), and digest() bytes - self.assertEqual(self.expected, out1) # h = .new(); h.update(data); h.digest() - if sys.version_info[0] == 2: - self.assertEqual(self.expected, out2) # h = .new(); h.update(data); h.hexdigest() - self.assertEqual(self.expected, out3) # h = .new(data); h.hexdigest() - else: - self.assertEqual(self.expected.decode(), out2) # h = .new(); h.update(data); h.hexdigest() - self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest() - self.assertEqual(self.expected, out4) # h = .new(data); h.digest() - - # Verify that the .new() method produces a fresh hash object, except - # for MD5 and SHA1, which are hashlib objects. (But test any .new() - # method that does exist.) - if self.hashmod.__name__ not in ('Cryptodome.Hash.MD5', 'Cryptodome.Hash.SHA1') or hasattr(h, 'new'): - h2 = h.new() - h2.update(self.input) - out5 = binascii.b2a_hex(h2.digest()) - self.assertEqual(self.expected, out5) + def __init__(self, hashmod, description, expected, input, extra_params): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + self.expected = expected.lower() + self.input = input + self.description = description + self.extra_params = extra_params + + def shortDescription(self): + return self.description + + def runTest(self): + h = self.hashmod.new(**self.extra_params) + h.update(self.input) + + out1 = binascii.b2a_hex(h.digest()) + out2 = h.hexdigest() + + h = self.hashmod.new(self.input, **self.extra_params) + + out3 = h.hexdigest() + out4 = binascii.b2a_hex(h.digest()) + + # PY3K: hexdigest() should return str(), and digest() bytes + self.assertEqual(self.expected, out1) # h = .new(); h.update(data); h.digest() + if sys.version_info[0] == 2: + self.assertEqual(self.expected, out2) # h = .new(); h.update(data); h.hexdigest() + self.assertEqual(self.expected, out3) # h = .new(data); h.hexdigest() + else: + self.assertEqual(self.expected.decode(), out2) # h = .new(); h.update(data); h.hexdigest() + self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest() + self.assertEqual(self.expected, out4) # h = .new(data); h.digest() + + # Verify that the .new() method produces a fresh hash object, except + # for MD5 and SHA1, which are hashlib objects. (But test any .new() + # method that does exist.) + if self.hashmod.__name__ not in ("Cryptodome.Hash.MD5", "Cryptodome.Hash.SHA1") or hasattr(h, "new"): + h2 = h.new() + h2.update(self.input) + out5 = binascii.b2a_hex(h2.digest()) + self.assertEqual(self.expected, out5) class HashTestOID(unittest.TestCase): - def __init__(self, hashmod, oid, extra_params): - unittest.TestCase.__init__(self) - self.hashmod = hashmod - self.oid = oid - self.extra_params = extra_params + def __init__(self, hashmod, oid, extra_params): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + self.oid = oid + self.extra_params = extra_params - def runTest(self): - h = self.hashmod.new(**self.extra_params) - self.assertEqual(h.oid, self.oid) + def runTest(self): + h = self.hashmod.new(**self.extra_params) + self.assertEqual(h.oid, self.oid) class ByteArrayTest(unittest.TestCase): + def __init__(self, module, extra_params): + unittest.TestCase.__init__(self) + self.module = module + self.extra_params = extra_params - def __init__(self, module, extra_params): - unittest.TestCase.__init__(self) - self.module = module - self.extra_params = extra_params - - def runTest(self): - data = b("\x00\x01\x02") + def runTest(self): + data = b("\x00\x01\x02") - # Data can be a bytearray (during initialization) - ba = bytearray(data) + # Data can be a bytearray (during initialization) + ba = bytearray(data) - h1 = self.module.new(data, **self.extra_params) - h2 = self.module.new(ba, **self.extra_params) - ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = self.module.new(data, **self.extra_params) + h2 = self.module.new(ba, **self.extra_params) + ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a bytearray (during operation) - ba = bytearray(data) + # Data can be a bytearray (during operation) + ba = bytearray(data) - h1 = self.module.new(**self.extra_params) - h2 = self.module.new(**self.extra_params) + h1 = self.module.new(**self.extra_params) + h2 = self.module.new(**self.extra_params) - h1.update(data) - h2.update(ba) + h1.update(data) + h2.update(ba) - ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) class MemoryViewTest(unittest.TestCase): + def __init__(self, module, extra_params): + unittest.TestCase.__init__(self) + self.module = module + self.extra_params = extra_params - def __init__(self, module, extra_params): - unittest.TestCase.__init__(self) - self.module = module - self.extra_params = extra_params - - def runTest(self): - - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) + def runTest(self): + data = b"\x00\x01\x02" - def get_mv_rw(data): - return memoryview(bytearray(data)) + def get_mv_ro(data): + return memoryview(data) - for get_mv in get_mv_ro, get_mv_rw: + def get_mv_rw(data): + return memoryview(bytearray(data)) - # Data can be a memoryview (during initialization) - mv = get_mv(data) + for get_mv in get_mv_ro, get_mv_rw: + # Data can be a memoryview (during initialization) + mv = get_mv(data) - h1 = self.module.new(data, **self.extra_params) - h2 = self.module.new(mv, **self.extra_params) - if not mv.readonly: - mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = self.module.new(data, **self.extra_params) + h2 = self.module.new(mv, **self.extra_params) + if not mv.readonly: + mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a memoryview (during operation) - mv = get_mv(data) + # Data can be a memoryview (during operation) + mv = get_mv(data) - h1 = self.module.new(**self.extra_params) - h2 = self.module.new(**self.extra_params) - h1.update(data) - h2.update(mv) - if not mv.readonly: - mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = self.module.new(**self.extra_params) + h2 = self.module.new(**self.extra_params) + h1.update(data) + h2.update(mv) + if not mv.readonly: + mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) class MACSelfTest(unittest.TestCase): - - def __init__(self, module, description, result, data, key, params): - unittest.TestCase.__init__(self) - self.module = module - self.result = t2b(result) - self.data = t2b(data) - self.key = t2b(key) - self.params = params - self.description = description - - def shortDescription(self): - return self.description - - def runTest(self): - - result_hex = hexlify(self.result) - - # Verify result - h = self.module.new(self.key, **self.params) - h.update(self.data) - self.assertEqual(self.result, h.digest()) - self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest()) - - # Verify that correct MAC does not raise any exception - h.verify(self.result) - h.hexverify(result_hex) - - # Verify that incorrect MAC does raise ValueError exception - wrong_mac = strxor_c(self.result, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - # Verify again, with data passed to new() - h = self.module.new(self.key, self.data, **self.params) - self.assertEqual(self.result, h.digest()) - self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest()) - - # Test .copy() - try: - h = self.module.new(self.key, self.data, **self.params) - h2 = h.copy() - h3 = h.copy() - - # Verify that changing the copy does not change the original - h2.update(b"bla") - self.assertEqual(h3.digest(), self.result) - - # Verify that both can reach the same state - h.update(b"bla") - self.assertEqual(h.digest(), h2.digest()) - except NotImplementedError: - pass - - # PY3K: Check that hexdigest() returns str and digest() returns bytes - self.assertTrue(isinstance(h.digest(), type(b""))) - self.assertTrue(isinstance(h.hexdigest(), type(""))) - - # PY3K: Check that .hexverify() accepts bytes or str - h.hexverify(h.hexdigest()) - h.hexverify(h.hexdigest().encode('ascii')) - - -def make_hash_tests(module, module_name, test_data, digest_size, oid=None, - extra_params={}): - tests = [] - for i in range(len(test_data)): - row = test_data[i] - (expected, input) = map(tobytes,row[0:2]) - if len(row) < 3: - description = repr(input) - else: - description = row[2] - name = "%s #%d: %s" % (module_name, i+1, description) - tests.append(HashSelfTest(module, name, expected, input, extra_params)) - - name = "%s #%d: digest_size" % (module_name, len(test_data) + 1) - tests.append(HashDigestSizeSelfTest(module, name, digest_size, extra_params)) - - if oid is not None: - tests.append(HashTestOID(module, oid, extra_params)) - - tests.append(ByteArrayTest(module, extra_params)) - - tests.append(MemoryViewTest(module, extra_params)) - - return tests + def __init__(self, module, description, result, data, key, params): + unittest.TestCase.__init__(self) + self.module = module + self.result = t2b(result) + self.data = t2b(data) + self.key = t2b(key) + self.params = params + self.description = description + + def shortDescription(self): + return self.description + + def runTest(self): + result_hex = hexlify(self.result) + + # Verify result + h = self.module.new(self.key, **self.params) + h.update(self.data) + self.assertEqual(self.result, h.digest()) + self.assertEqual(hexlify(self.result).decode("ascii"), h.hexdigest()) + + # Verify that correct MAC does not raise any exception + h.verify(self.result) + h.hexverify(result_hex) + + # Verify that incorrect MAC does raise ValueError exception + wrong_mac = strxor_c(self.result, 255) + self.assertRaises(ValueError, h.verify, wrong_mac) + self.assertRaises(ValueError, h.hexverify, "4556") + + # Verify again, with data passed to new() + h = self.module.new(self.key, self.data, **self.params) + self.assertEqual(self.result, h.digest()) + self.assertEqual(hexlify(self.result).decode("ascii"), h.hexdigest()) + + # Test .copy() + try: + h = self.module.new(self.key, self.data, **self.params) + h2 = h.copy() + h3 = h.copy() + + # Verify that changing the copy does not change the original + h2.update(b"bla") + self.assertEqual(h3.digest(), self.result) + + # Verify that both can reach the same state + h.update(b"bla") + self.assertEqual(h.digest(), h2.digest()) + except NotImplementedError: + pass + + # PY3K: Check that hexdigest() returns str and digest() returns bytes + self.assertTrue(isinstance(h.digest(), type(b""))) + self.assertTrue(isinstance(h.hexdigest(), type(""))) + + # PY3K: Check that .hexverify() accepts bytes or str + h.hexverify(h.hexdigest()) + h.hexverify(h.hexdigest().encode("ascii")) + + +def make_hash_tests( + module, + module_name, + test_data, + digest_size, + oid=None, + extra_params={}, +): + tests = [] + for i in range(len(test_data)): + row = test_data[i] + (expected, input) = map(tobytes, row[0:2]) + if len(row) < 3: + description = repr(input) + else: + description = row[2] + name = "%s #%d: %s" % (module_name, i + 1, description) + tests.append(HashSelfTest(module, name, expected, input, extra_params)) + + name = "%s #%d: digest_size" % (module_name, len(test_data) + 1) + tests.append(HashDigestSizeSelfTest(module, name, digest_size, extra_params)) + + if oid is not None: + tests.append(HashTestOID(module, oid, extra_params)) + + tests.append(ByteArrayTest(module, extra_params)) + + tests.append(MemoryViewTest(module, extra_params)) + + return tests def make_mac_tests(module, module_name, test_data): - tests = [] - for i, row in enumerate(test_data): - if len(row) == 4: - (key, data, results, description, params) = list(row) + [ {} ] - else: - (key, data, results, description, params) = row - name = "%s #%d: %s" % (module_name, i+1, description) - tests.append(MACSelfTest(module, name, results, data, key, params)) - return tests + tests = [] + for i, row in enumerate(test_data): + if len(row) == 4: + (key, data, results, description, params) = list(row) + [{}] + else: + (key, data, results, description, params) = row + name = "%s #%d: %s" % (module_name, i + 1, description) + tests.append(MACSelfTest(module, name, results, data, key, params)) + return tests + # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_BLAKE2.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_BLAKE2.py index e5ed63b7..e4067eb1 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_BLAKE2.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_BLAKE2.py @@ -42,441 +42,454 @@ class Blake2Test(unittest.TestCase): + def test_new_positive(self): + h = self.BLAKE2.new(digest_bits=self.max_bits) + for new_func in self.BLAKE2.new, h.new: + for dbits in range(8, self.max_bits + 1, 8): + hobj = new_func(digest_bits=dbits) + self.assertEqual(hobj.digest_size, dbits // 8) + + for dbytes in range(1, self.max_bytes + 1): + hobj = new_func(digest_bytes=dbytes) + self.assertEqual(hobj.digest_size, dbytes) + + digest1 = new_func(data=b"\x90", digest_bytes=self.max_bytes).digest() + digest2 = new_func(digest_bytes=self.max_bytes).update(b"\x90").digest() + self.assertEqual(digest1, digest2) + + new_func(data=b"A", key=b"5", digest_bytes=self.max_bytes) + + hobj = h.new() + self.assertEqual(hobj.digest_size, self.max_bytes) + + def test_new_negative(self): + h = self.BLAKE2.new(digest_bits=self.max_bits) + for new_func in self.BLAKE2.new, h.new: + self.assertRaises( + TypeError, + new_func, + digest_bytes=self.max_bytes, + digest_bits=self.max_bits, + ) + self.assertRaises(ValueError, new_func, digest_bytes=0) + self.assertRaises( + ValueError, + new_func, + digest_bytes=self.max_bytes + 1, + ) + self.assertRaises(ValueError, new_func, digest_bits=7) + self.assertRaises(ValueError, new_func, digest_bits=15) + self.assertRaises( + ValueError, + new_func, + digest_bits=self.max_bits + 1, + ) + self.assertRaises( + TypeError, + new_func, + digest_bytes=self.max_bytes, + key="string", + ) + self.assertRaises( + TypeError, + new_func, + digest_bytes=self.max_bytes, + data="string", + ) + + def test_default_digest_size(self): + digest = self.BLAKE2.new(data=b"abc").digest() + self.assertEqual(len(digest), self.max_bytes) + + def test_update(self): + pieces = [b"\x0a" * 200, b"\x14" * 300] + h = self.BLAKE2.new(digest_bytes=self.max_bytes) + h.update(pieces[0]).update(pieces[1]) + digest = h.digest() + h = self.BLAKE2.new(digest_bytes=self.max_bytes) + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.digest(), digest) + + def test_update_negative(self): + h = self.BLAKE2.new(digest_bytes=self.max_bytes) + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = self.BLAKE2.new(digest_bytes=self.max_bytes) + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b"digest"))) + + def test_update_after_digest(self): + msg = b"rrrrttt" + + # Normally, update() cannot be done after digest() + h = self.BLAKE2.new(digest_bits=256, data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = self.BLAKE2.new(digest_bits=256, data=msg).digest() + + # With the proper flag, it is allowed + h = self.BLAKE2.new(digest_bits=256, data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) + + def test_hex_digest(self): + mac = self.BLAKE2.new(digest_bits=self.max_bits) + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_verify(self): + h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") + mac = h.digest() + h.verify(mac) + wrong_mac = strxor_c(mac, 255) + self.assertRaises(ValueError, h.verify, wrong_mac) + + def test_hexverify(self): + h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") + mac = h.hexdigest() + h.hexverify(mac) + self.assertRaises(ValueError, h.hexverify, "4556") + + def test_oid(self): + prefix = "1.3.6.1.4.1.1722.12.2." + self.oid_variant + "." + + for digest_bits in self.digest_bits_oid: + h = self.BLAKE2.new(digest_bits=digest_bits) + self.assertEqual(h.oid, prefix + str(digest_bits // 8)) + + h = self.BLAKE2.new(digest_bits=digest_bits, key=b"secret") + self.assertRaises(AttributeError, lambda: h.oid) + + for digest_bits in (8, self.max_bits): + if digest_bits in self.digest_bits_oid: + continue + self.assertRaises(AttributeError, lambda: h.oid) + + def test_bytearray(self): + key = b"0" * 16 + data = b"\x00\x01\x02" + + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(key) + data_ba = bytearray(data) + + h1 = self.BLAKE2.new(data=data, key=key) + h2 = self.BLAKE2.new(data=data_ba, key=key_ba) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + # Data can be a bytearray (during operation) + data_ba = bytearray(data) + + h1 = self.BLAKE2.new() + h2 = self.BLAKE2.new() + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + def test_memoryview(self): + key = b"0" * 16 + data = b"\x00\x01\x02" + + def get_mv_ro(data): + return memoryview(data) + + def get_mv_rw(data): + return memoryview(bytearray(data)) + + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(key) + data_mv = get_mv(data) + + h1 = self.BLAKE2.new(data=data, key=key) + h2 = self.BLAKE2.new(data=data_mv, key=key_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + key_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + # Data can be a memoryview (during operation) + data_mv = get_mv(data) - def test_new_positive(self): - - h = self.BLAKE2.new(digest_bits=self.max_bits) - for new_func in self.BLAKE2.new, h.new: - - for dbits in range(8, self.max_bits + 1, 8): - hobj = new_func(digest_bits=dbits) - self.assertEqual(hobj.digest_size, dbits // 8) - - for dbytes in range(1, self.max_bytes + 1): - hobj = new_func(digest_bytes=dbytes) - self.assertEqual(hobj.digest_size, dbytes) - - digest1 = new_func(data=b"\x90", digest_bytes=self.max_bytes).digest() - digest2 = new_func(digest_bytes=self.max_bytes).update(b"\x90").digest() - self.assertEqual(digest1, digest2) - - new_func(data=b"A", key=b"5", digest_bytes=self.max_bytes) - - hobj = h.new() - self.assertEqual(hobj.digest_size, self.max_bytes) - - def test_new_negative(self): - - h = self.BLAKE2.new(digest_bits=self.max_bits) - for new_func in self.BLAKE2.new, h.new: - self.assertRaises(TypeError, new_func, - digest_bytes=self.max_bytes, - digest_bits=self.max_bits) - self.assertRaises(ValueError, new_func, digest_bytes=0) - self.assertRaises(ValueError, new_func, - digest_bytes=self.max_bytes + 1) - self.assertRaises(ValueError, new_func, digest_bits=7) - self.assertRaises(ValueError, new_func, digest_bits=15) - self.assertRaises(ValueError, new_func, - digest_bits=self.max_bits + 1) - self.assertRaises(TypeError, new_func, - digest_bytes=self.max_bytes, - key=u"string") - self.assertRaises(TypeError, new_func, - digest_bytes=self.max_bytes, - data=u"string") - - def test_default_digest_size(self): - digest = self.BLAKE2.new(data=b'abc').digest() - self.assertEqual(len(digest), self.max_bytes) - - def test_update(self): - pieces = [b"\x0A" * 200, b"\x14" * 300] - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - h.update(pieces[0]).update(pieces[1]) - digest = h.digest() - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.digest(), digest) - - def test_update_negative(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg = b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = self.BLAKE2.new(digest_bits=256, data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = self.BLAKE2.new(digest_bits=256, data=msg).digest() - - # With the proper flag, it is allowed - h = self.BLAKE2.new(digest_bits=256, data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) - - def test_hex_digest(self): - mac = self.BLAKE2.new(digest_bits=self.max_bits) - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_verify(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") - mac = h.digest() - h.verify(mac) - wrong_mac = strxor_c(mac, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - - def test_hexverify(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") - mac = h.hexdigest() - h.hexverify(mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - def test_oid(self): - - prefix = "1.3.6.1.4.1.1722.12.2." + self.oid_variant + "." - - for digest_bits in self.digest_bits_oid: - h = self.BLAKE2.new(digest_bits=digest_bits) - self.assertEqual(h.oid, prefix + str(digest_bits // 8)) - - h = self.BLAKE2.new(digest_bits=digest_bits, key=b"secret") - self.assertRaises(AttributeError, lambda: h.oid) - - for digest_bits in (8, self.max_bits): - if digest_bits in self.digest_bits_oid: - continue - self.assertRaises(AttributeError, lambda: h.oid) - - def test_bytearray(self): - - key = b'0' * 16 - data = b"\x00\x01\x02" - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) - - h1 = self.BLAKE2.new(data=data, key=key) - h2 = self.BLAKE2.new(data=data_ba, key=key_ba) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' + h1 = self.BLAKE2.new() + h2 = self.BLAKE2.new() + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = self.BLAKE2.new() - h2 = self.BLAKE2.new() - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - key = b'0' * 16 - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) - - h1 = self.BLAKE2.new(data=data, key=key) - h2 = self.BLAKE2.new(data=data_mv, key=key_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - key_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = self.BLAKE2.new() - h2 = self.BLAKE2.new() - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) + self.assertEqual(h1.digest(), h2.digest()) class Blake2bTest(Blake2Test): - #: Module - BLAKE2 = BLAKE2b - #: Max output size (in bits) - max_bits = 512 - #: Max output size (in bytes) - max_bytes = 64 - #: Bit size of the digests for which an ASN OID exists - digest_bits_oid = (160, 256, 384, 512) - # http://tools.ietf.org/html/draft-saarinen-blake2-02 - oid_variant = "1" + #: Module + BLAKE2 = BLAKE2b + #: Max output size (in bits) + max_bits = 512 + #: Max output size (in bytes) + max_bytes = 64 + #: Bit size of the digests for which an ASN OID exists + digest_bits_oid = (160, 256, 384, 512) + # http://tools.ietf.org/html/draft-saarinen-blake2-02 + oid_variant = "1" class Blake2sTest(Blake2Test): - #: Module - BLAKE2 = BLAKE2s - #: Max output size (in bits) - max_bits = 256 - #: Max output size (in bytes) - max_bytes = 32 - #: Bit size of the digests for which an ASN OID exists - digest_bits_oid = (128, 160, 224, 256) - # http://tools.ietf.org/html/draft-saarinen-blake2-02 - oid_variant = "2" + #: Module + BLAKE2 = BLAKE2s + #: Max output size (in bits) + max_bits = 256 + #: Max output size (in bytes) + max_bytes = 32 + #: Bit size of the digests for which an ASN OID exists + digest_bits_oid = (128, 160, 224, 256) + # http://tools.ietf.org/html/draft-saarinen-blake2-02 + oid_variant = "2" class Blake2OfficialTestVector(unittest.TestCase): - - def _load_tests(self, test_vector_file): - expected = "in" - test_vectors = [] - with open(test_vector_file, "rt") as test_vector_fd: - for line_number, line in enumerate(test_vector_fd): - - if line.strip() == "" or line.startswith("#"): - continue - - res = re.match("%s:\t([0-9A-Fa-f]*)" % expected, line) - if not res: - raise ValueError("Incorrect test vector format (line %d)" - % line_number) - - if res.group(1): - bin_value = unhexlify(tobytes(res.group(1))) - else: - bin_value = b"" - if expected == "in": - input_data = bin_value - expected = "key" - elif expected == "key": - key = bin_value - expected = "hash" - else: - result = bin_value - expected = "in" - test_vectors.append((input_data, key, result)) - return test_vectors - - def setUp(self): - - dir_comps = ("Hash", self.name) - file_name = self.name.lower() + "-test.txt" - self.description = "%s tests" % self.name - - try: - import pycryptodome_test_vectors # type: ignore - except ImportError: - warnings.warn("Warning: skipping extended tests for %s" % self.name, - UserWarning) - self.test_vectors = [] - return - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - self.test_vectors = self._load_tests(full_file_name) - - def runTest(self): - for (input_data, key, result) in self.test_vectors: - mac = self.BLAKE2.new(key=key, digest_bytes=self.max_bytes) - mac.update(input_data) - self.assertEqual(mac.digest(), result) + def _load_tests(self, test_vector_file): + expected = "in" + test_vectors = [] + with open(test_vector_file, "rt") as test_vector_fd: + for line_number, line in enumerate(test_vector_fd): + if line.strip() == "" or line.startswith("#"): + continue + + res = re.match("%s:\t([0-9A-Fa-f]*)" % expected, line) + if not res: + raise ValueError( + "Incorrect test vector format (line %d)" % line_number, + ) + + if res.group(1): + bin_value = unhexlify(tobytes(res.group(1))) + else: + bin_value = b"" + if expected == "in": + input_data = bin_value + expected = "key" + elif expected == "key": + key = bin_value + expected = "hash" + else: + result = bin_value + expected = "in" + test_vectors.append((input_data, key, result)) + return test_vectors + + def setUp(self): + dir_comps = ("Hash", self.name) + file_name = self.name.lower() + "-test.txt" + self.description = "%s tests" % self.name + + try: + import pycryptodome_test_vectors # type: ignore + except ImportError: + warnings.warn( + "Warning: skipping extended tests for %s" % self.name, + UserWarning, + ) + self.test_vectors = [] + return + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + self.test_vectors = self._load_tests(full_file_name) + + def runTest(self): + for input_data, key, result in self.test_vectors: + mac = self.BLAKE2.new(key=key, digest_bytes=self.max_bytes) + mac.update(input_data) + self.assertEqual(mac.digest(), result) class Blake2bOfficialTestVector(Blake2OfficialTestVector): - #: Module - BLAKE2 = BLAKE2b - #: Hash name - name = "BLAKE2b" - #: Max digest size - max_bytes = 64 + #: Module + BLAKE2 = BLAKE2b + #: Hash name + name = "BLAKE2b" + #: Max digest size + max_bytes = 64 class Blake2sOfficialTestVector(Blake2OfficialTestVector): - #: Module - BLAKE2 = BLAKE2s - #: Hash name - name = "BLAKE2s" - #: Max digest size - max_bytes = 32 + #: Module + BLAKE2 = BLAKE2s + #: Hash name + name = "BLAKE2s" + #: Max digest size + max_bytes = 32 class Blake2TestVector1(unittest.TestCase): - - def _load_tests(self, test_vector_file): - test_vectors = [] - with open(test_vector_file, "rt") as test_vector_fd: - for line_number, line in enumerate(test_vector_fd): - if line.strip() == "" or line.startswith("#"): - continue - res = re.match("digest: ([0-9A-Fa-f]*)", line) - if not res: - raise ValueError("Incorrect test vector format (line %d)" - % line_number) - - test_vectors.append(unhexlify(tobytes(res.group(1)))) - return test_vectors - - def setUp(self): - dir_comps = ("Hash", self.name) - file_name = "tv1.txt" - self.description = "%s tests" % self.name - - try: - import pycryptodome_test_vectors - except ImportError: - warnings.warn("Warning: skipping extended tests for %s" % self.name, - UserWarning) - self.test_vectors = [] - return - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - self.test_vectors = self._load_tests(full_file_name) - - def runTest(self): - - for tv in self.test_vectors: - digest_bytes = len(tv) - next_data = b"" - for _ in range(100): - h = self.BLAKE2.new(digest_bytes=digest_bytes) - h.update(next_data) - next_data = h.digest() + next_data - self.assertEqual(h.digest(), tv) + def _load_tests(self, test_vector_file): + test_vectors = [] + with open(test_vector_file, "rt") as test_vector_fd: + for line_number, line in enumerate(test_vector_fd): + if line.strip() == "" or line.startswith("#"): + continue + res = re.match("digest: ([0-9A-Fa-f]*)", line) + if not res: + raise ValueError( + "Incorrect test vector format (line %d)" % line_number, + ) + + test_vectors.append(unhexlify(tobytes(res.group(1)))) + return test_vectors + + def setUp(self): + dir_comps = ("Hash", self.name) + file_name = "tv1.txt" + self.description = "%s tests" % self.name + + try: + import pycryptodome_test_vectors + except ImportError: + warnings.warn( + "Warning: skipping extended tests for %s" % self.name, + UserWarning, + ) + self.test_vectors = [] + return + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + self.test_vectors = self._load_tests(full_file_name) + + def runTest(self): + for tv in self.test_vectors: + digest_bytes = len(tv) + next_data = b"" + for _ in range(100): + h = self.BLAKE2.new(digest_bytes=digest_bytes) + h.update(next_data) + next_data = h.digest() + next_data + self.assertEqual(h.digest(), tv) class Blake2bTestVector1(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2b - #: Hash name - name = "BLAKE2b" + #: Module + BLAKE2 = BLAKE2b + #: Hash name + name = "BLAKE2b" class Blake2sTestVector1(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2s - #: Hash name - name = "BLAKE2s" + #: Module + BLAKE2 = BLAKE2s + #: Hash name + name = "BLAKE2s" class Blake2TestVector2(unittest.TestCase): - - def _load_tests(self, test_vector_file): - test_vectors = [] - with open(test_vector_file, "rt") as test_vector_fd: - for line_number, line in enumerate(test_vector_fd): - if line.strip() == "" or line.startswith("#"): - continue - res = re.match(r"digest\(([0-9]+)\): ([0-9A-Fa-f]*)", line) - if not res: - raise ValueError("Incorrect test vector format (line %d)" - % line_number) - key_size = int(res.group(1)) - result = unhexlify(tobytes(res.group(2))) - test_vectors.append((key_size, result)) - return test_vectors - - def setUp(self): - dir_comps = ("Hash", self.name) - file_name = "tv2.txt" - self.description = "%s tests" % self.name - - try: - import pycryptodome_test_vectors # type: ignore - except ImportError: - warnings.warn("Warning: skipping extended tests for %s" % self.name, - UserWarning) - self.test_vectors = [] - return - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - self.test_vectors = self._load_tests(full_file_name) - - def runTest(self): - - for key_size, result in self.test_vectors: - next_data = b"" - for _ in range(100): - h = self.BLAKE2.new(digest_bytes=self.max_bytes, - key=b"A" * key_size) - h.update(next_data) - next_data = h.digest() + next_data - self.assertEqual(h.digest(), result) + def _load_tests(self, test_vector_file): + test_vectors = [] + with open(test_vector_file, "rt") as test_vector_fd: + for line_number, line in enumerate(test_vector_fd): + if line.strip() == "" or line.startswith("#"): + continue + res = re.match(r"digest\(([0-9]+)\): ([0-9A-Fa-f]*)", line) + if not res: + raise ValueError( + "Incorrect test vector format (line %d)" % line_number, + ) + key_size = int(res.group(1)) + result = unhexlify(tobytes(res.group(2))) + test_vectors.append((key_size, result)) + return test_vectors + + def setUp(self): + dir_comps = ("Hash", self.name) + file_name = "tv2.txt" + self.description = "%s tests" % self.name + + try: + import pycryptodome_test_vectors # type: ignore + except ImportError: + warnings.warn( + "Warning: skipping extended tests for %s" % self.name, + UserWarning, + ) + self.test_vectors = [] + return + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + self.test_vectors = self._load_tests(full_file_name) + + def runTest(self): + for key_size, result in self.test_vectors: + next_data = b"" + for _ in range(100): + h = self.BLAKE2.new( + digest_bytes=self.max_bytes, + key=b"A" * key_size, + ) + h.update(next_data) + next_data = h.digest() + next_data + self.assertEqual(h.digest(), result) class Blake2bTestVector2(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2b - #: Hash name - name = "BLAKE2b" - #: Max digest size in bytes - max_bytes = 64 + #: Module + BLAKE2 = BLAKE2b + #: Hash name + name = "BLAKE2b" + #: Max digest size in bytes + max_bytes = 64 class Blake2sTestVector2(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2s - #: Hash name - name = "BLAKE2s" - #: Max digest size in bytes - max_bytes = 32 + #: Module + BLAKE2 = BLAKE2s + #: Hash name + name = "BLAKE2s" + #: Max digest size in bytes + max_bytes = 32 def get_tests(config={}): - tests = [] + tests = [] + + tests += list_test_cases(Blake2bTest) + tests.append(Blake2bOfficialTestVector()) + tests.append(Blake2bTestVector1()) + tests.append(Blake2bTestVector2()) + + tests += list_test_cases(Blake2sTest) + tests.append(Blake2sOfficialTestVector()) + tests.append(Blake2sTestVector1()) + tests.append(Blake2sTestVector2()) - tests += list_test_cases(Blake2bTest) - tests.append(Blake2bOfficialTestVector()) - tests.append(Blake2bTestVector1()) - tests.append(Blake2bTestVector2()) + return tests - tests += list_test_cases(Blake2sTest) - tests.append(Blake2sOfficialTestVector()) - tests.append(Blake2sTestVector1()) - tests.append(Blake2sTestVector2()) - return tests +if __name__ == "__main__": + import unittest + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - import unittest - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_CMAC.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_CMAC.py index f88f1cd8..98208bd4 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_CMAC.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_CMAC.py @@ -33,9 +33,7 @@ """Self-test suite for Cryptodome.Hash.CMAC""" -import json import unittest -from binascii import unhexlify from Cryptodome.Util.py3compat import tobytes @@ -43,406 +41,359 @@ from Cryptodome.Cipher import AES, DES3 from Cryptodome.Hash import SHAKE128 -from Cryptodome.Util.strxor import strxor from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.SelfTest.loader import load_test_vectors_wycheproof # This is a list of (key, data, result, description, module) tuples. test_data = [ - - ## Test vectors from RFC 4493 ## - ## The are also in NIST SP 800 38B D.2 ## - ( '2b7e151628aed2a6abf7158809cf4f3c', - '', - 'bb1d6929e95937287fa37d129b756746', - 'RFC 4493 #1', - AES - ), - - ( '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172a', - '070a16b46b4d4144f79bdd9dd04a287c', - 'RFC 4493 #2', - AES - ), - - ( '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411', - 'dfa66747de9ae63030ca32611497c827', - 'RFC 4493 #3', - AES - ), - - ( '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+ - 'f69f2445df4f9b17ad2b417be66c3710', - '51f0bebf7e3b9d92fc49741779363cfe', - 'RFC 4493 #4', - AES - ), - - ## The rest of Appendix D of NIST SP 800 38B - ## was not totally correct. - ## Values in Examples 14, 15, 18, and 19 were wrong. - ## The updated test values are published in: - ## http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '', - 'd17ddf46adaacde531cac483de7a9367', - 'NIST SP 800 38B D.2 Example 5', - AES - ), - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172a', - '9e99a7bf31e710900662f65e617c5184', - 'NIST SP 800 38B D.2 Example 6', - AES - ), - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411', - '8a1de5be2eb31aad089a82e6ee908b0e', - 'NIST SP 800 38B D.2 Example 7', - AES - ), - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+ - 'f69f2445df4f9b17ad2b417be66c3710', - 'a1d5df0eed790f794d77589659f39a11', - 'NIST SP 800 38B D.2 Example 8', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '', - '028962f61b7bf89efc6b551f4667d983', - 'NIST SP 800 38B D.3 Example 9', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '6bc1bee22e409f96e93d7e117393172a', - '28a7023f452e8f82bd4bf28d8c37c35c', - 'NIST SP 800 38B D.3 Example 10', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411', - 'aaf3d8f1de5640c232f5b169b9c911e6', - 'NIST SP 800 38B D.3 Example 11', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+ - 'f69f2445df4f9b17ad2b417be66c3710', - 'e1992190549f6ed5696a2c056c315410', - 'NIST SP 800 38B D.3 Example 12', - AES - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '', - 'b7a688e122ffaf95', - 'NIST SP 800 38B D.4 Example 13', - DES3 - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '6bc1bee22e409f96', - '8e8f293136283797', - 'NIST SP 800 38B D.4 Example 14', - DES3 - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a57', - '743ddbe0ce2dc2ed', - 'NIST SP 800 38B D.4 Example 15', - DES3 - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a571e03ac9c'+ - '9eb76fac45af8e51', - '33e6b1092400eae5', - 'NIST SP 800 38B D.4 Example 16', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '', - 'bd2ebf9a3ba00361', - 'NIST SP 800 38B D.7 Example 17', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '6bc1bee22e409f96', - '4ff2ab813c53ce83', - 'NIST SP 800 38B D.7 Example 18', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a57', - '62dd1b471902bd4e', - 'NIST SP 800 38B D.7 Example 19', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a571e03ac9c'+ - '9eb76fac45af8e51', - '31b1e431dabc4eb8', - 'NIST SP 800 38B D.7 Example 20', - DES3 - ), - + ## Test vectors from RFC 4493 ## + ## The are also in NIST SP 800 38B D.2 ## + ( + "2b7e151628aed2a6abf7158809cf4f3c", + "", + "bb1d6929e95937287fa37d129b756746", + "RFC 4493 #1", + AES, + ), + ( + "2b7e151628aed2a6abf7158809cf4f3c", + "6bc1bee22e409f96e93d7e117393172a", + "070a16b46b4d4144f79bdd9dd04a287c", + "RFC 4493 #2", + AES, + ), + ( + "2b7e151628aed2a6abf7158809cf4f3c", + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", + "dfa66747de9ae63030ca32611497c827", + "RFC 4493 #3", + AES, + ), + ( + "2b7e151628aed2a6abf7158809cf4f3c", + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "51f0bebf7e3b9d92fc49741779363cfe", + "RFC 4493 #4", + AES, + ), + ## The rest of Appendix D of NIST SP 800 38B + ## was not totally correct. + ## Values in Examples 14, 15, 18, and 19 were wrong. + ## The updated test values are published in: + ## http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf + ( + "8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b", + "", + "d17ddf46adaacde531cac483de7a9367", + "NIST SP 800 38B D.2 Example 5", + AES, + ), + ( + "8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b", + "6bc1bee22e409f96e93d7e117393172a", + "9e99a7bf31e710900662f65e617c5184", + "NIST SP 800 38B D.2 Example 6", + AES, + ), + ( + "8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b", + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", + "8a1de5be2eb31aad089a82e6ee908b0e", + "NIST SP 800 38B D.2 Example 7", + AES, + ), + ( + "8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b", + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "a1d5df0eed790f794d77589659f39a11", + "NIST SP 800 38B D.2 Example 8", + AES, + ), + ( + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + "", + "028962f61b7bf89efc6b551f4667d983", + "NIST SP 800 38B D.3 Example 9", + AES, + ), + ( + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + "6bc1bee22e409f96e93d7e117393172a", + "28a7023f452e8f82bd4bf28d8c37c35c", + "NIST SP 800 38B D.3 Example 10", + AES, + ), + ( + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", + "aaf3d8f1de5640c232f5b169b9c911e6", + "NIST SP 800 38B D.3 Example 11", + AES, + ), + ( + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "e1992190549f6ed5696a2c056c315410", + "NIST SP 800 38B D.3 Example 12", + AES, + ), + ( + "8aa83bf8cbda1062" + "0bc1bf19fbb6cd58" + "bc313d4a371ca8b5", + "", + "b7a688e122ffaf95", + "NIST SP 800 38B D.4 Example 13", + DES3, + ), + ( + "8aa83bf8cbda1062" + "0bc1bf19fbb6cd58" + "bc313d4a371ca8b5", + "6bc1bee22e409f96", + "8e8f293136283797", + "NIST SP 800 38B D.4 Example 14", + DES3, + ), + ( + "8aa83bf8cbda1062" + "0bc1bf19fbb6cd58" + "bc313d4a371ca8b5", + "6bc1bee22e409f96" + "e93d7e117393172a" + "ae2d8a57", + "743ddbe0ce2dc2ed", + "NIST SP 800 38B D.4 Example 15", + DES3, + ), + ( + "8aa83bf8cbda1062" + "0bc1bf19fbb6cd58" + "bc313d4a371ca8b5", + "6bc1bee22e409f96" + "e93d7e117393172a" + "ae2d8a571e03ac9c" + "9eb76fac45af8e51", + "33e6b1092400eae5", + "NIST SP 800 38B D.4 Example 16", + DES3, + ), + ( + "4cf15134a2850dd5" + "8a3d10ba80570d38", + "", + "bd2ebf9a3ba00361", + "NIST SP 800 38B D.7 Example 17", + DES3, + ), + ( + "4cf15134a2850dd5" + "8a3d10ba80570d38", + "6bc1bee22e409f96", + "4ff2ab813c53ce83", + "NIST SP 800 38B D.7 Example 18", + DES3, + ), + ( + "4cf15134a2850dd5" + "8a3d10ba80570d38", + "6bc1bee22e409f96" + "e93d7e117393172a" + "ae2d8a57", + "62dd1b471902bd4e", + "NIST SP 800 38B D.7 Example 19", + DES3, + ), + ( + "4cf15134a2850dd5" + "8a3d10ba80570d38", + "6bc1bee22e409f96" + "e93d7e117393172a" + "ae2d8a571e03ac9c" + "9eb76fac45af8e51", + "31b1e431dabc4eb8", + "NIST SP 800 38B D.7 Example 20", + DES3, + ), ] def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class TestCMAC(unittest.TestCase): - - def test_internal_caching(self): - """Verify that internal caching is implemented correctly""" - - data_to_mac = get_tag_random("data_to_mac", 128) - key = get_tag_random("key", 16) - ref_mac = CMAC.new(key, msg=data_to_mac, ciphermod=AES).digest() - - # Break up in chunks of different length - # The result must always be the same - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - chunks = [data_to_mac[i:i+chunk_length] for i in - range(0, len(data_to_mac), chunk_length)] - - mac = CMAC.new(key, ciphermod=AES) - for chunk in chunks: - mac.update(chunk) - self.assertEqual(ref_mac, mac.digest()) - - def test_update_after_digest(self): - msg = b"rrrrttt" - key = b"4" * 16 - - # Normally, update() cannot be done after digest() - h = CMAC.new(key, msg[:4], ciphermod=AES) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = CMAC.new(key, msg, ciphermod=AES).digest() - - # With the proper flag, it is allowed - h2 = CMAC.new(key, msg[:4], ciphermod=AES, update_after_digest=True) - self.assertEqual(h2.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h2.update(msg[4:]) - self.assertEqual(h2.digest(), dig2) + def test_internal_caching(self): + """Verify that internal caching is implemented correctly""" + + data_to_mac = get_tag_random("data_to_mac", 128) + key = get_tag_random("key", 16) + ref_mac = CMAC.new(key, msg=data_to_mac, ciphermod=AES).digest() + + # Break up in chunks of different length + # The result must always be the same + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + chunks = [data_to_mac[i : i + chunk_length] for i in range(0, len(data_to_mac), chunk_length)] + + mac = CMAC.new(key, ciphermod=AES) + for chunk in chunks: + mac.update(chunk) + self.assertEqual(ref_mac, mac.digest()) + + def test_update_after_digest(self): + msg = b"rrrrttt" + key = b"4" * 16 + + # Normally, update() cannot be done after digest() + h = CMAC.new(key, msg[:4], ciphermod=AES) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = CMAC.new(key, msg, ciphermod=AES).digest() + + # With the proper flag, it is allowed + h2 = CMAC.new(key, msg[:4], ciphermod=AES, update_after_digest=True) + self.assertEqual(h2.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h2.update(msg[4:]) + self.assertEqual(h2.digest(), dig2) class ByteArrayTests(unittest.TestCase): + def runTest(self): + key = b"0" * 16 + data = b"\x00\x01\x02" - def runTest(self): + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(key) + data_ba = bytearray(data) - key = b"0" * 16 - data = b"\x00\x01\x02" + h1 = CMAC.new(key, data, ciphermod=AES) + h2 = CMAC.new(key_ba, data_ba, ciphermod=AES) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) + # Data can be a bytearray (during operation) + key_ba = bytearray(key) + data_ba = bytearray(data) - h1 = CMAC.new(key, data, ciphermod=AES) - h2 = CMAC.new(key_ba, data_ba, ciphermod=AES) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = CMAC.new(key, ciphermod=AES) + h2 = CMAC.new(key, ciphermod=AES) + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a bytearray (during operation) - key_ba = bytearray(key) - data_ba = bytearray(data) - h1 = CMAC.new(key, ciphermod=AES) - h2 = CMAC.new(key, ciphermod=AES) - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) +class MemoryViewTests(unittest.TestCase): + def runTest(self): + key = b"0" * 16 + data = b"\x00\x01\x02" + def get_mv_ro(data): + return memoryview(data) -class MemoryViewTests(unittest.TestCase): + def get_mv_rw(data): + return memoryview(bytearray(data)) - def runTest(self): + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(key) + data_mv = get_mv(data) - key = b"0" * 16 - data = b"\x00\x01\x02" + h1 = CMAC.new(key, data, ciphermod=AES) + h2 = CMAC.new(key_mv, data_mv, ciphermod=AES) + if not data_mv.readonly: + key_mv[:1] = b"\xff" + data_mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - def get_mv_ro(data): - return memoryview(data) + # Data can be a memoryview (during operation) + data_mv = get_mv(data) - def get_mv_rw(data): - return memoryview(bytearray(data)) + h1 = CMAC.new(key, ciphermod=AES) + h2 = CMAC.new(key, ciphermod=AES) + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - for get_mv in (get_mv_ro, get_mv_rw): - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) +class TestVectorsWycheproof(unittest.TestCase): + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def setUp(self): + def filter_tag(group): + return group["tagSize"] // 8 + + self.tv = load_test_vectors_wycheproof( + ("Hash", "wycheproof"), + "aes_cmac_test.json", + "Wycheproof CMAC", + group_tag={"tag_size": filter_tag}, + ) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_create_mac(self, tv): + self._id = "Wycheproof MAC creation Test #" + str(tv.id) + + try: + tag = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size).digest() + except ValueError as e: + if len(tv.key) not in (16, 24, 32) and "key length" in str(e): + return + raise e + if tv.valid: + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_verify_mac(self, tv): + self._id = "Wycheproof MAC verification Test #" + str(tv.id) + + try: + mac = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size) + except ValueError as e: + if len(tv.key) not in (16, 24, 32) and "key length" in str(e): + return + raise e + try: + mac.verify(tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_create_mac(tv) + self.test_verify_mac(tv) - h1 = CMAC.new(key, data, ciphermod=AES) - h2 = CMAC.new(key_mv, data_mv, ciphermod=AES) - if not data_mv.readonly: - key_mv[:1] = b'\xFF' - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - # Data can be a memoryview (during operation) - data_mv = get_mv(data) +def get_tests(config={}): + global test_data + from .common import make_mac_tests - h1 = CMAC.new(key, ciphermod=AES) - h2 = CMAC.new(key, ciphermod=AES) - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + wycheproof_warnings = config.get("wycheproof_warnings") + # Add new() parameters to the back of each test vector + params_test_data = [] + for row in test_data: + t = list(row) + t[4] = dict(ciphermod=t[4]) + params_test_data.append(t) -class TestVectorsWycheproof(unittest.TestCase): + tests = make_mac_tests(CMAC, "CMAC", params_test_data) + tests.append(ByteArrayTests()) + tests.append(list_test_cases(TestCMAC)) + tests.append(MemoryViewTests()) + tests += [TestVectorsWycheproof(wycheproof_warnings)] + return tests - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def setUp(self): - - def filter_tag(group): - return group['tagSize'] // 8 - - self.tv = load_test_vectors_wycheproof(("Hash", "wycheproof"), - "aes_cmac_test.json", - "Wycheproof CMAC", - group_tag={'tag_size': filter_tag}) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_create_mac(self, tv): - self._id = "Wycheproof MAC creation Test #" + str(tv.id) - - try: - tag = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size).digest() - except ValueError as e: - if len(tv.key) not in (16, 24, 32) and "key length" in str(e): - return - raise e - if tv.valid: - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_verify_mac(self, tv): - self._id = "Wycheproof MAC verification Test #" + str(tv.id) - - try: - mac = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size) - except ValueError as e: - if len(tv.key) not in (16, 24, 32) and "key length" in str(e): - return - raise e - try: - mac.verify(tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - - for tv in self.tv: - self.test_create_mac(tv) - self.test_verify_mac(tv) +if __name__ == "__main__": + import unittest -def get_tests(config={}): - global test_data - import types - from .common import make_mac_tests - - wycheproof_warnings = config.get('wycheproof_warnings') - - # Add new() parameters to the back of each test vector - params_test_data = [] - for row in test_data: - t = list(row) - t[4] = dict(ciphermod=t[4]) - params_test_data.append(t) - - tests = make_mac_tests(CMAC, "CMAC", params_test_data) - tests.append(ByteArrayTests()) - tests.append(list_test_cases(TestCMAC)) - tests.append(MemoryViewTests()) - tests += [ TestVectorsWycheproof(wycheproof_warnings) ] - return tests - - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_HMAC.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_HMAC.py index ecec1a8f..612527ee 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_HMAC.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_HMAC.py @@ -28,521 +28,584 @@ from binascii import hexlify from Cryptodome.Util.py3compat import tostr, tobytes -from Cryptodome.Hash import (HMAC, MD5, SHA1, SHA256, - SHA224, SHA384, SHA512, - RIPEMD160, - SHA3_224, SHA3_256, SHA3_384, SHA3_512) - - -hash_modules = dict(MD5=MD5, SHA1=SHA1, SHA256=SHA256, - SHA224=SHA224, SHA384=SHA384, SHA512=SHA512, - RIPEMD160=RIPEMD160, - SHA3_224=SHA3_224, SHA3_256=SHA3_256, - SHA3_384=SHA3_384, SHA3_512=SHA3_512) +from Cryptodome.Hash import ( + HMAC, + MD5, + SHA1, + SHA256, + SHA224, + SHA384, + SHA512, + RIPEMD160, + SHA3_224, + SHA3_256, + SHA3_384, + SHA3_512, +) + + +hash_modules = dict( + MD5=MD5, + SHA1=SHA1, + SHA256=SHA256, + SHA224=SHA224, + SHA384=SHA384, + SHA512=SHA512, + RIPEMD160=RIPEMD160, + SHA3_224=SHA3_224, + SHA3_256=SHA3_256, + SHA3_384=SHA3_384, + SHA3_512=SHA3_512, +) default_hash = None + def xl(text): - return tostr(hexlify(tobytes(text))) + return tostr(hexlify(tobytes(text))) + # This is a list of (key, data, results, description) tuples. test_data = [ - ## Test vectors from RFC 2202 ## - # Test that the default hashmod is MD5 - ('0b' * 16, - '4869205468657265', - dict(default_hash='9294727a3638bb1c13f48ef8158bfc9d'), - 'default-is-MD5'), - - # Test case 1 (MD5) - ('0b' * 16, - '4869205468657265', - dict(MD5='9294727a3638bb1c13f48ef8158bfc9d'), - 'RFC 2202 #1-MD5 (HMAC-MD5)'), - - # Test case 1 (SHA1) - ('0b' * 20, - '4869205468657265', - dict(SHA1='b617318655057264e28bc0b6fb378c8ef146be00'), - 'RFC 2202 #1-SHA1 (HMAC-SHA1)'), - - # Test case 2 - ('4a656665', - '7768617420646f2079612077616e7420666f72206e6f7468696e673f', - dict(MD5='750c783e6ab0b503eaa86e310a5db738', - SHA1='effcdf6ae5eb2fa2d27416d5f184df9c259a7c79'), - 'RFC 2202 #2 (HMAC-MD5/SHA1)'), - - # Test case 3 (MD5) - ('aa' * 16, - 'dd' * 50, - dict(MD5='56be34521d144c88dbb8c733f0e8b3f6'), - 'RFC 2202 #3-MD5 (HMAC-MD5)'), - - # Test case 3 (SHA1) - ('aa' * 20, - 'dd' * 50, - dict(SHA1='125d7342b9ac11cd91a39af48aa17b4f63f175d3'), - 'RFC 2202 #3-SHA1 (HMAC-SHA1)'), - - # Test case 4 - ('0102030405060708090a0b0c0d0e0f10111213141516171819', - 'cd' * 50, - dict(MD5='697eaf0aca3a3aea3a75164746ffaa79', - SHA1='4c9007f4026250c6bc8414f9bf50c86c2d7235da'), - 'RFC 2202 #4 (HMAC-MD5/SHA1)'), - - # Test case 5 (MD5) - ('0c' * 16, - '546573742057697468205472756e636174696f6e', - dict(MD5='56461ef2342edc00f9bab995690efd4c'), - 'RFC 2202 #5-MD5 (HMAC-MD5)'), - - # Test case 5 (SHA1) - # NB: We do not implement hash truncation, so we only test the full hash here. - ('0c' * 20, - '546573742057697468205472756e636174696f6e', - dict(SHA1='4c1a03424b55e07fe7f27be1d58bb9324a9a5a04'), - 'RFC 2202 #5-SHA1 (HMAC-SHA1)'), - - # Test case 6 - ('aa' * 80, - '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' - + '65204b6579202d2048617368204b6579204669727374', - dict(MD5='6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd', - SHA1='aa4ae5e15272d00e95705637ce8a3b55ed402112'), - 'RFC 2202 #6 (HMAC-MD5/SHA1)'), - - # Test case 7 - ('aa' * 80, - '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' - + '65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d' - + '53697a652044617461', - dict(MD5='6f630fad67cda0ee1fb1f562db3aa53e', - SHA1='e8e99d0f45237d786d6bbaa7965c7808bbff1a91'), - 'RFC 2202 #7 (HMAC-MD5/SHA1)'), - - ## Test vectors from RFC 4231 ## - # 4.2. Test Case 1 - ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', - '4869205468657265', - dict(SHA256=''' + ## Test vectors from RFC 2202 ## + # Test that the default hashmod is MD5 + ( + "0b" * 16, + "4869205468657265", + dict(default_hash="9294727a3638bb1c13f48ef8158bfc9d"), + "default-is-MD5", + ), + # Test case 1 (MD5) + ( + "0b" * 16, + "4869205468657265", + dict(MD5="9294727a3638bb1c13f48ef8158bfc9d"), + "RFC 2202 #1-MD5 (HMAC-MD5)", + ), + # Test case 1 (SHA1) + ( + "0b" * 20, + "4869205468657265", + dict(SHA1="b617318655057264e28bc0b6fb378c8ef146be00"), + "RFC 2202 #1-SHA1 (HMAC-SHA1)", + ), + # Test case 2 + ( + "4a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + dict( + MD5="750c783e6ab0b503eaa86e310a5db738", + SHA1="effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", + ), + "RFC 2202 #2 (HMAC-MD5/SHA1)", + ), + # Test case 3 (MD5) + ( + "aa" * 16, + "dd" * 50, + dict(MD5="56be34521d144c88dbb8c733f0e8b3f6"), + "RFC 2202 #3-MD5 (HMAC-MD5)", + ), + # Test case 3 (SHA1) + ( + "aa" * 20, + "dd" * 50, + dict(SHA1="125d7342b9ac11cd91a39af48aa17b4f63f175d3"), + "RFC 2202 #3-SHA1 (HMAC-SHA1)", + ), + # Test case 4 + ( + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "cd" * 50, + dict( + MD5="697eaf0aca3a3aea3a75164746ffaa79", + SHA1="4c9007f4026250c6bc8414f9bf50c86c2d7235da", + ), + "RFC 2202 #4 (HMAC-MD5/SHA1)", + ), + # Test case 5 (MD5) + ( + "0c" * 16, + "546573742057697468205472756e636174696f6e", + dict(MD5="56461ef2342edc00f9bab995690efd4c"), + "RFC 2202 #5-MD5 (HMAC-MD5)", + ), + # Test case 5 (SHA1) + # NB: We do not implement hash truncation, so we only test the full hash here. + ( + "0c" * 20, + "546573742057697468205472756e636174696f6e", + dict(SHA1="4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"), + "RFC 2202 #5-SHA1 (HMAC-SHA1)", + ), + # Test case 6 + ( + "aa" * 80, + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + + "65204b6579202d2048617368204b6579204669727374", + dict( + MD5="6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd", + SHA1="aa4ae5e15272d00e95705637ce8a3b55ed402112", + ), + "RFC 2202 #6 (HMAC-MD5/SHA1)", + ), + # Test case 7 + ( + "aa" * 80, + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + + "65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d" + + "53697a652044617461", + dict( + MD5="6f630fad67cda0ee1fb1f562db3aa53e", + SHA1="e8e99d0f45237d786d6bbaa7965c7808bbff1a91", + ), + "RFC 2202 #7 (HMAC-MD5/SHA1)", + ), + ## Test vectors from RFC 4231 ## + # 4.2. Test Case 1 + ( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4869205468657265", + dict( + SHA256=""" b0344c61d8db38535ca8afceaf0bf12b 881dc200c9833da726e9376c2e32cff7 - '''), - 'RFC 4231 #1 (HMAC-SHA256)'), - - # 4.3. Test Case 2 - Test with a key shorter than the length of the HMAC - # output. - ('4a656665', - '7768617420646f2079612077616e7420666f72206e6f7468696e673f', - dict(SHA256=''' + """, + ), + "RFC 4231 #1 (HMAC-SHA256)", + ), + # 4.3. Test Case 2 - Test with a key shorter than the length of the HMAC + # output. + ( + "4a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + dict( + SHA256=""" 5bdcc146bf60754e6a042426089575c7 5a003f089d2739839dec58b964ec3843 - '''), - 'RFC 4231 #2 (HMAC-SHA256)'), - - # 4.4. Test Case 3 - Test with a combined length of key and data that is - # larger than 64 bytes (= block-size of SHA-224 and SHA-256). - ('aa' * 20, - 'dd' * 50, - dict(SHA256=''' + """, + ), + "RFC 4231 #2 (HMAC-SHA256)", + ), + # 4.4. Test Case 3 - Test with a combined length of key and data that is + # larger than 64 bytes (= block-size of SHA-224 and SHA-256). + ( + "aa" * 20, + "dd" * 50, + dict( + SHA256=""" 773ea91e36800e46854db8ebd09181a7 2959098b3ef8c122d9635514ced565fe - '''), - 'RFC 4231 #3 (HMAC-SHA256)'), - - # 4.5. Test Case 4 - Test with a combined length of key and data that is - # larger than 64 bytes (= block-size of SHA-224 and SHA-256). - ('0102030405060708090a0b0c0d0e0f10111213141516171819', - 'cd' * 50, - dict(SHA256=''' + """, + ), + "RFC 4231 #3 (HMAC-SHA256)", + ), + # 4.5. Test Case 4 - Test with a combined length of key and data that is + # larger than 64 bytes (= block-size of SHA-224 and SHA-256). + ( + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "cd" * 50, + dict( + SHA256=""" 82558a389a443c0ea4cc819899f2083a 85f0faa3e578f8077a2e3ff46729665b - '''), - 'RFC 4231 #4 (HMAC-SHA256)'), - - # 4.6. Test Case 5 - Test with a truncation of output to 128 bits. - # - # Not included because we do not implement hash truncation. - # - - # 4.7. Test Case 6 - Test with a key larger than 128 bytes (= block-size of - # SHA-384 and SHA-512). - ('aa' * 131, - '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' - + '65204b6579202d2048617368204b6579204669727374', - dict(SHA256=''' + """, + ), + "RFC 4231 #4 (HMAC-SHA256)", + ), + # 4.6. Test Case 5 - Test with a truncation of output to 128 bits. + # + # Not included because we do not implement hash truncation. + # + # 4.7. Test Case 6 - Test with a key larger than 128 bytes (= block-size of + # SHA-384 and SHA-512). + ( + "aa" * 131, + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + + "65204b6579202d2048617368204b6579204669727374", + dict( + SHA256=""" 60e431591ee0b67f0d8a26aacbf5b77f 8e0bc6213728c5140546040f0ee37f54 - '''), - 'RFC 4231 #6 (HMAC-SHA256)'), - - # 4.8. Test Case 7 - Test with a key and data that is larger than 128 bytes - # (= block-size of SHA-384 and SHA-512). - ('aa' * 131, - '5468697320697320612074657374207573696e672061206c6172676572207468' - + '616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074' - + '68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565' - + '647320746f20626520686173686564206265666f7265206265696e6720757365' - + '642062792074686520484d414320616c676f726974686d2e', - dict(SHA256=''' + """, + ), + "RFC 4231 #6 (HMAC-SHA256)", + ), + # 4.8. Test Case 7 - Test with a key and data that is larger than 128 bytes + # (= block-size of SHA-384 and SHA-512). + ( + "aa" * 131, + "5468697320697320612074657374207573696e672061206c6172676572207468" + + "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + + "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + + "647320746f20626520686173686564206265666f7265206265696e6720757365" + + "642062792074686520484d414320616c676f726974686d2e", + dict( + SHA256=""" 9b09ffa71b942fcb27635fbcd5b0e944 bfdc63644f0713938a7f51535c3a35e2 - '''), - 'RFC 4231 #7 (HMAC-SHA256)'), - - # Test case 8 (SHA224) - ('4a656665', - '7768617420646f2079612077616e74' - + '20666f72206e6f7468696e673f', - dict(SHA224='a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44'), - 'RFC 4634 8.4 SHA224 (HMAC-SHA224)'), - - # Test case 9 (SHA384) - ('4a656665', - '7768617420646f2079612077616e74' - + '20666f72206e6f7468696e673f', - dict(SHA384='af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649'), - 'RFC 4634 8.4 SHA384 (HMAC-SHA384)'), - - # Test case 10 (SHA512) - ('4a656665', - '7768617420646f2079612077616e74' - + '20666f72206e6f7468696e673f', - dict(SHA512='164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'), - 'RFC 4634 8.4 SHA512 (HMAC-SHA512)'), - - # Test case 11 (RIPEMD) - ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', - xl("Hi There"), - dict(RIPEMD160='24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668'), - 'RFC 2286 #1 (HMAC-RIPEMD)'), - - # Test case 12 (RIPEMD) - (xl("Jefe"), - xl("what do ya want for nothing?"), - dict(RIPEMD160='dda6c0213a485a9e24f4742064a7f033b43c4069'), - 'RFC 2286 #2 (HMAC-RIPEMD)'), - - # Test case 13 (RIPEMD) - ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'dd' * 50, - dict(RIPEMD160='b0b105360de759960ab4f35298e116e295d8e7c1'), - 'RFC 2286 #3 (HMAC-RIPEMD)'), - - # Test case 14 (RIPEMD) - ('0102030405060708090a0b0c0d0e0f10111213141516171819', - 'cd' * 50, - dict(RIPEMD160='d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4'), - 'RFC 2286 #4 (HMAC-RIPEMD)'), - - # Test case 15 (RIPEMD) - ('0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c', - xl("Test With Truncation"), - dict(RIPEMD160='7619693978f91d90539ae786500ff3d8e0518e39'), - 'RFC 2286 #5 (HMAC-RIPEMD)'), - - # Test case 16 (RIPEMD) - ('aa' * 80, - xl("Test Using Larger Than Block-Size Key - Hash Key First"), - dict(RIPEMD160='6466ca07ac5eac29e1bd523e5ada7605b791fd8b'), - 'RFC 2286 #6 (HMAC-RIPEMD)'), - - # Test case 17 (RIPEMD) - ('aa' * 80, - xl("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"), - dict(RIPEMD160='69ea60798d71616cce5fd0871e23754cd75d5a0a'), - 'RFC 2286 #7 (HMAC-RIPEMD)'), - - # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-224.pdf - ( - '000102030405060708090a0b0c0d0e0f' - '101112131415161718191a1b', - xl('Sample message for keylenblocklen'), - dict(SHA3_224='078695eecc227c636ad31d063a15dd05a7e819a66ec6d8de1e193e59'), - 'NIST CSRC Sample #3 (SHA3-224)' - ), - - # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-256.pdf - ( - '000102030405060708090a0b0c0d0e0f'\ - '101112131415161718191a1b1c1d1e1f', - xl('Sample message for keylenblocklen'), - dict(SHA3_256='9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258'), - 'NIST CSRC Sample #3 (SHA3-256)' - ), - - # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-384.pdf - ( - '000102030405060708090a0b0c0d0e0f'\ - '101112131415161718191a1b1c1d1e1f' - '202122232425262728292a2b2c2d2e2f', - xl('Sample message for keylenblocklen'), - dict(SHA3_384='e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac'), - 'NIST CSRC Sample #3 (SHA3-384)' - ), - - # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-512.pdf - ( - '000102030405060708090a0b0c0d0e0f'\ - '101112131415161718191a1b1c1d1e1f'\ - '202122232425262728292a2b2c2d2e2f'\ - '303132333435363738393a3b3c3d3e3f', - xl('Sample message for keylenblocklen'), - dict(SHA3_512='5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d46b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915'), - 'NIST CSRC Sample #3 (SHA3-512)' - ), - + """, + ), + "RFC 4231 #7 (HMAC-SHA256)", + ), + # Test case 8 (SHA224) + ( + "4a656665", + "7768617420646f2079612077616e74" + "20666f72206e6f7468696e673f", + dict(SHA224="a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44"), + "RFC 4634 8.4 SHA224 (HMAC-SHA224)", + ), + # Test case 9 (SHA384) + ( + "4a656665", + "7768617420646f2079612077616e74" + "20666f72206e6f7468696e673f", + dict( + SHA384="af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649" + ), + "RFC 4634 8.4 SHA384 (HMAC-SHA384)", + ), + # Test case 10 (SHA512) + ( + "4a656665", + "7768617420646f2079612077616e74" + "20666f72206e6f7468696e673f", + dict( + SHA512="164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737" + ), + "RFC 4634 8.4 SHA512 (HMAC-SHA512)", + ), + # Test case 11 (RIPEMD) + ( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + xl("Hi There"), + dict(RIPEMD160="24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668"), + "RFC 2286 #1 (HMAC-RIPEMD)", + ), + # Test case 12 (RIPEMD) + ( + xl("Jefe"), + xl("what do ya want for nothing?"), + dict(RIPEMD160="dda6c0213a485a9e24f4742064a7f033b43c4069"), + "RFC 2286 #2 (HMAC-RIPEMD)", + ), + # Test case 13 (RIPEMD) + ( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "dd" * 50, + dict(RIPEMD160="b0b105360de759960ab4f35298e116e295d8e7c1"), + "RFC 2286 #3 (HMAC-RIPEMD)", + ), + # Test case 14 (RIPEMD) + ( + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "cd" * 50, + dict(RIPEMD160="d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4"), + "RFC 2286 #4 (HMAC-RIPEMD)", + ), + # Test case 15 (RIPEMD) + ( + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + xl("Test With Truncation"), + dict(RIPEMD160="7619693978f91d90539ae786500ff3d8e0518e39"), + "RFC 2286 #5 (HMAC-RIPEMD)", + ), + # Test case 16 (RIPEMD) + ( + "aa" * 80, + xl("Test Using Larger Than Block-Size Key - Hash Key First"), + dict(RIPEMD160="6466ca07ac5eac29e1bd523e5ada7605b791fd8b"), + "RFC 2286 #6 (HMAC-RIPEMD)", + ), + # Test case 17 (RIPEMD) + ( + "aa" * 80, + xl("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"), + dict(RIPEMD160="69ea60798d71616cce5fd0871e23754cd75d5a0a"), + "RFC 2286 #7 (HMAC-RIPEMD)", + ), + # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-224.pdf + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b", + xl("Sample message for keylenblocklen"), + dict(SHA3_224="078695eecc227c636ad31d063a15dd05a7e819a66ec6d8de1e193e59"), + "NIST CSRC Sample #3 (SHA3-224)", + ), + # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-256.pdf + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + xl("Sample message for keylenblocklen"), + dict(SHA3_256="9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258"), + "NIST CSRC Sample #3 (SHA3-256)", + ), + # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-384.pdf + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + xl("Sample message for keylenblocklen"), + dict( + SHA3_384="e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac" + ), + "NIST CSRC Sample #3 (SHA3-384)", + ), + # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-512.pdf + ( + "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f", + xl("Sample message for keylenblocklen"), + dict( + SHA3_512="5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d46b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915" + ), + "NIST CSRC Sample #3 (SHA3-512)", + ), ] class HMAC_Module_and_Instance_Test(unittest.TestCase): - """Test the HMAC construction and verify that it does not - matter if you initialize it with a hash module or - with an hash instance. + """Test the HMAC construction and verify that it does not + matter if you initialize it with a hash module or + with an hash instance. - See https://bugs.launchpad.net/pycrypto/+bug/1209399 - """ + See https://bugs.launchpad.net/pycrypto/+bug/1209399 + """ - def __init__(self, hashmods): - """Initialize the test with a dictionary of hash modules - indexed by their names""" + def __init__(self, hashmods): + """Initialize the test with a dictionary of hash modules + indexed by their names""" - unittest.TestCase.__init__(self) - self.hashmods = hashmods - self.description = "" + unittest.TestCase.__init__(self) + self.hashmods = hashmods + self.description = "" - def shortDescription(self): - return self.description + def shortDescription(self): + return self.description - def runTest(self): - key = b"\x90\x91\x92\x93" * 4 - payload = b"\x00" * 100 + def runTest(self): + key = b"\x90\x91\x92\x93" * 4 + payload = b"\x00" * 100 - for hashname, hashmod in self.hashmods.items(): - if hashmod is None: - continue - self.description = "Test HMAC in combination with " + hashname - one = HMAC.new(key, payload, hashmod).digest() - two = HMAC.new(key, payload, hashmod.new()).digest() - self.assertEqual(one, two) + for hashname, hashmod in self.hashmods.items(): + if hashmod is None: + continue + self.description = "Test HMAC in combination with " + hashname + one = HMAC.new(key, payload, hashmod).digest() + two = HMAC.new(key, payload, hashmod.new()).digest() + self.assertEqual(one, two) class HMAC_None(unittest.TestCase): - - def runTest(self): - - key = b"\x04" * 20 - one = HMAC.new(key, b"", SHA1).digest() - two = HMAC.new(key, None, SHA1).digest() - self.assertEqual(one, two) + def runTest(self): + key = b"\x04" * 20 + one = HMAC.new(key, b"", SHA1).digest() + two = HMAC.new(key, None, SHA1).digest() + self.assertEqual(one, two) class ByteArrayTests(unittest.TestCase): + def runTest(self): + key = b"0" * 16 + data = b"\x00\x01\x02" - def runTest(self): - - key = b"0" * 16 - data = b"\x00\x01\x02" - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(key) + data_ba = bytearray(data) - h1 = HMAC.new(key, data) - h2 = HMAC.new(key_ba, data_ba) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = HMAC.new(key, data) + h2 = HMAC.new(key_ba, data_ba) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a bytearray (during operation) - key_ba = bytearray(key) - data_ba = bytearray(data) + # Data can be a bytearray (during operation) + key_ba = bytearray(key) + data_ba = bytearray(data) - h1 = HMAC.new(key) - h2 = HMAC.new(key) - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = HMAC.new(key) + h2 = HMAC.new(key) + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) class MemoryViewTests(unittest.TestCase): + def runTest(self): + key = b"0" * 16 + data = b"\x00\x01\x02" - def runTest(self): - - key = b"0" * 16 - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) + def get_mv_ro(data): + return memoryview(data) - for get_mv in (get_mv_ro, get_mv_rw): + def get_mv_rw(data): + return memoryview(bytearray(data)) - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(key) + data_mv = get_mv(data) - h1 = HMAC.new(key, data) - h2 = HMAC.new(key_mv, data_mv) - if not data_mv.readonly: - key_mv[:1] = b'\xFF' - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = HMAC.new(key, data) + h2 = HMAC.new(key_mv, data_mv) + if not data_mv.readonly: + key_mv[:1] = b"\xff" + data_mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a memoryview (during operation) - data_mv = get_mv(data) + # Data can be a memoryview (during operation) + data_mv = get_mv(data) - h1 = HMAC.new(key) - h2 = HMAC.new(key) - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = HMAC.new(key) + h2 = HMAC.new(key) + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) def get_tests(config={}): - global test_data - import types - from .common import make_mac_tests - - # A test vector contains multiple results, each one for a - # different hash algorithm. - # Here we expand each test vector into multiple ones, - # and add the relevant parameters that will be passed to new() - exp_test_data = [] - for row in test_data: - for modname in row[2].keys(): - t = list(row) - t[2] = row[2][modname] - t.append(dict(digestmod=globals()[modname])) - exp_test_data.append(t) - tests = make_mac_tests(HMAC, "HMAC", exp_test_data) - tests.append(HMAC_Module_and_Instance_Test(hash_modules)) - tests.append(HMAC_None()) - - tests.append(ByteArrayTests()) - tests.append(MemoryViewTests()) - - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + global test_data + from .common import make_mac_tests + + # A test vector contains multiple results, each one for a + # different hash algorithm. + # Here we expand each test vector into multiple ones, + # and add the relevant parameters that will be passed to new() + exp_test_data = [] + for row in test_data: + for modname in row[2].keys(): + t = list(row) + t[2] = row[2][modname] + t.append(dict(digestmod=globals()[modname])) + exp_test_data.append(t) + tests = make_mac_tests(HMAC, "HMAC", exp_test_data) + tests.append(HMAC_Module_and_Instance_Test(hash_modules)) + tests.append(HMAC_None()) + + tests.append(ByteArrayTests()) + tests.append(MemoryViewTests()) + + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_KMAC.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_KMAC.py index 0543a4c0..7f2b4e50 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_KMAC.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_KMAC.py @@ -9,338 +9,333 @@ class KMACTest(unittest.TestCase): + def new(self, *args, **kwargs): + return self.KMAC.new(key=b"X" * (self.minimum_key_bits // 8), *args, **kwargs) + + def test_new_positive(self): + key = b"X" * 32 + + h = self.new() + for new_func in self.KMAC.new, h.new: + for dbytes in range(self.minimum_bytes, 128 + 1): + hobj = new_func(key=key, mac_len=dbytes) + self.assertEqual(hobj.digest_size, dbytes) + + digest1 = new_func(key=key, data=b"\x90").digest() + digest2 = new_func(key=key).update(b"\x90").digest() + self.assertEqual(digest1, digest2) + + new_func(data=b"A", key=key, custom=b"g") + + hobj = h.new(key=key) + self.assertEqual(hobj.digest_size, self.default_bytes) + + def test_new_negative(self): + h = self.new() + for new_func in self.KMAC.new, h.new: + self.assertRaises( + ValueError, + new_func, + key=b"X" * 32, + mac_len=0, + ) + self.assertRaises( + ValueError, + new_func, + key=b"X" * 32, + mac_len=self.minimum_bytes - 1, + ) + self.assertRaises( + TypeError, + new_func, + key="string", + ) + self.assertRaises( + TypeError, + new_func, + data="string", + ) + + def test_default_digest_size(self): + digest = self.new(data=b"abc").digest() + self.assertEqual(len(digest), self.default_bytes) + + def test_update(self): + pieces = [b"\x0a" * 200, b"\x14" * 300] + h = self.new() + h.update(pieces[0]).update(pieces[1]) + digest = h.digest() + h = self.new() + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.digest(), digest) + + def test_update_negative(self): + h = self.new() + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = self.new() + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b"digest"))) + + def test_update_after_digest(self): + msg = b"rrrrttt" + + # Normally, update() cannot be done after digest() + h = self.new(mac_len=32, data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, dig1) + + def test_hex_digest(self): + mac = self.new() + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_verify(self): + h = self.new() + mac = h.digest() + h.verify(mac) + wrong_mac = strxor_c(mac, 255) + self.assertRaises(ValueError, h.verify, wrong_mac) + + def test_hexverify(self): + h = self.new() + mac = h.hexdigest() + h.hexverify(mac) + self.assertRaises(ValueError, h.hexverify, "4556") + + def test_oid(self): + oid = "2.16.840.1.101.3.4.2." + self.oid_variant + h = self.new() + self.assertEqual(h.oid, oid) + + def test_bytearray(self): + key = b"0" * 32 + data = b"\x00\x01\x02" + + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(key) + data_ba = bytearray(data) + + h1 = self.KMAC.new(data=data, key=key) + h2 = self.KMAC.new(data=data_ba, key=key_ba) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + # Data can be a bytearray (during operation) + data_ba = bytearray(data) + + h1 = self.new() + h2 = self.new() + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + def test_memoryview(self): + key = b"0" * 32 + data = b"\x00\x01\x02" + + def get_mv_ro(data): + return memoryview(data) + + def get_mv_rw(data): + return memoryview(bytearray(data)) + + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(key) + data_mv = get_mv(data) + + h1 = self.KMAC.new(data=data, key=key) + h2 = self.KMAC.new(data=data_mv, key=key_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + key_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) - def new(self, *args, **kwargs): - return self.KMAC.new(key=b'X' * (self.minimum_key_bits // 8), *args, **kwargs) - - def test_new_positive(self): - - key = b'X' * 32 - - h = self.new() - for new_func in self.KMAC.new, h.new: + # Data can be a memoryview (during operation) + data_mv = get_mv(data) - for dbytes in range(self.minimum_bytes, 128 + 1): - hobj = new_func(key=key, mac_len=dbytes) - self.assertEqual(hobj.digest_size, dbytes) - - digest1 = new_func(key=key, data=b"\x90").digest() - digest2 = new_func(key=key).update(b"\x90").digest() - self.assertEqual(digest1, digest2) - - new_func(data=b"A", key=key, custom=b"g") - - hobj = h.new(key=key) - self.assertEqual(hobj.digest_size, self.default_bytes) - - def test_new_negative(self): - - h = self.new() - for new_func in self.KMAC.new, h.new: - self.assertRaises(ValueError, new_func, key=b'X'*32, - mac_len=0) - self.assertRaises(ValueError, new_func, key=b'X'*32, - mac_len=self.minimum_bytes - 1) - self.assertRaises(TypeError, new_func, - key=u"string") - self.assertRaises(TypeError, new_func, - data=u"string") - - def test_default_digest_size(self): - digest = self.new(data=b'abc').digest() - self.assertEqual(len(digest), self.default_bytes) - - def test_update(self): - pieces = [b"\x0A" * 200, b"\x14" * 300] - h = self.new() - h.update(pieces[0]).update(pieces[1]) - digest = h.digest() - h = self.new() - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.digest(), digest) - - def test_update_negative(self): - h = self.new() - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = self.new() - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg = b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = self.new(mac_len=32, data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, dig1) - - def test_hex_digest(self): - mac = self.new() - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_verify(self): - h = self.new() - mac = h.digest() - h.verify(mac) - wrong_mac = strxor_c(mac, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - - def test_hexverify(self): - h = self.new() - mac = h.hexdigest() - h.hexverify(mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - def test_oid(self): - - oid = "2.16.840.1.101.3.4.2." + self.oid_variant - h = self.new() - self.assertEqual(h.oid, oid) - - def test_bytearray(self): - - key = b'0' * 32 - data = b"\x00\x01\x02" - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) - - h1 = self.KMAC.new(data=data, key=key) - h2 = self.KMAC.new(data=data_ba, key=key_ba) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = self.new() - h2 = self.new() - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - key = b'0' * 32 - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) - - h1 = self.KMAC.new(data=data, key=key) - h2 = self.KMAC.new(data=data_mv, key=key_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - key_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = self.new() - h2 = self.new() - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) + h1 = self.new() + h2 = self.new() + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) class KMAC128Test(KMACTest): + KMAC = KMAC128 - KMAC = KMAC128 - - minimum_key_bits = 128 + minimum_key_bits = 128 - minimum_bytes = 8 - default_bytes = 64 + minimum_bytes = 8 + default_bytes = 64 - oid_variant = "19" + oid_variant = "19" class KMAC256Test(KMACTest): + KMAC = KMAC256 - KMAC = KMAC256 + minimum_key_bits = 256 - minimum_key_bits = 256 + minimum_bytes = 8 + default_bytes = 64 - minimum_bytes = 8 - default_bytes = 64 - - oid_variant = "20" + oid_variant = "20" class NISTExampleTestVectors(unittest.TestCase): - - # https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf - test_data = [ - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03", - "", - "E5 78 0B 0D 3E A6 F7 D3 A4 29 C5 70 6A A4 3A 00" - "FA DB D7 D4 96 28 83 9E 31 87 24 3F 45 6E E1 4E", - "Sample #1 NIST", - KMAC128 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03", - "My Tagged Application", - "3B 1F BA 96 3C D8 B0 B5 9E 8C 1A 6D 71 88 8B 71" - "43 65 1A F8 BA 0A 70 70 C0 97 9E 28 11 32 4A A5", - "Sample #2 NIST", - KMAC128 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" - "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" - "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" - "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" - "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" - "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" - "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" - "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" - "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" - "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" - "C0 C1 C2 C3 C4 C5 C6 C7", - "My Tagged Application", - "1F 5B 4E 6C CA 02 20 9E 0D CB 5C A6 35 B8 9A 15" - "E2 71 EC C7 60 07 1D FD 80 5F AA 38 F9 72 92 30", - "Sample #3 NIST", - KMAC128 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03", - "My Tagged Application", - "20 C5 70 C3 13 46 F7 03 C9 AC 36 C6 1C 03 CB 64" - "C3 97 0D 0C FC 78 7E 9B 79 59 9D 27 3A 68 D2 F7" - "F6 9D 4C C3 DE 9D 10 4A 35 16 89 F2 7C F6 F5 95" - "1F 01 03 F3 3F 4F 24 87 10 24 D9 C2 77 73 A8 DD", - "Sample #4 NIST", - KMAC256 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" - "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" - "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" - "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" - "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" - "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" - "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" - "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" - "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" - "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" - "C0 C1 C2 C3 C4 C5 C6 C7", - "", - "75 35 8C F3 9E 41 49 4E 94 97 07 92 7C EE 0A F2" - "0A 3F F5 53 90 4C 86 B0 8F 21 CC 41 4B CF D6 91" - "58 9D 27 CF 5E 15 36 9C BB FF 8B 9A 4C 2E B1 78" - "00 85 5D 02 35 FF 63 5D A8 25 33 EC 6B 75 9B 69", - "Sample #5 NIST", - KMAC256 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" - "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" - "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" - "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" - "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" - "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" - "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" - "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" - "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" - "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" - "C0 C1 C2 C3 C4 C5 C6 C7", - "My Tagged Application", - "B5 86 18 F7 1F 92 E1 D5 6C 1B 8C 55 DD D7 CD 18" - "8B 97 B4 CA 4D 99 83 1E B2 69 9A 83 7D A2 E4 D9" - "70 FB AC FD E5 00 33 AE A5 85 F1 A2 70 85 10 C3" - "2D 07 88 08 01 BD 18 28 98 FE 47 68 76 FC 89 65", - "Sample #6 NIST", - KMAC256 - ), - ] - - def setUp(self): - td = [] - for key, data, custom, mac, text, module in self.test_data: - ni = ( - unhexlify(key.replace(" ", "")), - unhexlify(data.replace(" ", "")), - custom.encode(), - unhexlify(mac.replace(" ", "")), - text, - module - ) - td.append(ni) - self.test_data = td - - def runTest(self): - - for key, data, custom, mac, text, module in self.test_data: - h = module.new(data=data, key=key, custom=custom, mac_len=len(mac)) - mac_tag = h.digest() - self.assertEqual(mac_tag, mac, msg=text) + # https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf + test_data = [ + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03", + "", + "E5 78 0B 0D 3E A6 F7 D3 A4 29 C5 70 6A A4 3A 00FA DB D7 D4 96 28 83 9E 31 87 24 3F 45 6E E1 4E", + "Sample #1 NIST", + KMAC128, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03", + "My Tagged Application", + "3B 1F BA 96 3C D8 B0 B5 9E 8C 1A 6D 71 88 8B 7143 65 1A F8 BA 0A 70 70 C0 97 9E 28 11 32 4A A5", + "Sample #2 NIST", + KMAC128, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" + "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" + "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" + "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" + "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" + "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" + "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" + "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" + "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" + "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" + "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" + "C0 C1 C2 C3 C4 C5 C6 C7", + "My Tagged Application", + "1F 5B 4E 6C CA 02 20 9E 0D CB 5C A6 35 B8 9A 15E2 71 EC C7 60 07 1D FD 80 5F AA 38 F9 72 92 30", + "Sample #3 NIST", + KMAC128, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03", + "My Tagged Application", + "20 C5 70 C3 13 46 F7 03 C9 AC 36 C6 1C 03 CB 64" + "C3 97 0D 0C FC 78 7E 9B 79 59 9D 27 3A 68 D2 F7" + "F6 9D 4C C3 DE 9D 10 4A 35 16 89 F2 7C F6 F5 95" + "1F 01 03 F3 3F 4F 24 87 10 24 D9 C2 77 73 A8 DD", + "Sample #4 NIST", + KMAC256, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" + "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" + "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" + "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" + "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" + "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" + "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" + "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" + "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" + "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" + "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" + "C0 C1 C2 C3 C4 C5 C6 C7", + "", + "75 35 8C F3 9E 41 49 4E 94 97 07 92 7C EE 0A F2" + "0A 3F F5 53 90 4C 86 B0 8F 21 CC 41 4B CF D6 91" + "58 9D 27 CF 5E 15 36 9C BB FF 8B 9A 4C 2E B1 78" + "00 85 5D 02 35 FF 63 5D A8 25 33 EC 6B 75 9B 69", + "Sample #5 NIST", + KMAC256, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" + "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" + "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" + "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" + "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" + "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" + "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" + "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" + "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" + "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" + "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" + "C0 C1 C2 C3 C4 C5 C6 C7", + "My Tagged Application", + "B5 86 18 F7 1F 92 E1 D5 6C 1B 8C 55 DD D7 CD 18" + "8B 97 B4 CA 4D 99 83 1E B2 69 9A 83 7D A2 E4 D9" + "70 FB AC FD E5 00 33 AE A5 85 F1 A2 70 85 10 C3" + "2D 07 88 08 01 BD 18 28 98 FE 47 68 76 FC 89 65", + "Sample #6 NIST", + KMAC256, + ), + ] + + def setUp(self): + td = [] + for key, data, custom, mac, text, module in self.test_data: + ni = ( + unhexlify(key.replace(" ", "")), + unhexlify(data.replace(" ", "")), + custom.encode(), + unhexlify(mac.replace(" ", "")), + text, + module, + ) + td.append(ni) + self.test_data = td + + def runTest(self): + for key, data, custom, mac, text, module in self.test_data: + h = module.new(data=data, key=key, custom=custom, mac_len=len(mac)) + mac_tag = h.digest() + self.assertEqual(mac_tag, mac, msg=text) def get_tests(config={}): - tests = [] + tests = [] + + tests += list_test_cases(KMAC128Test) + tests += list_test_cases(KMAC256Test) + tests.append(NISTExampleTestVectors()) + + return tests - tests += list_test_cases(KMAC128Test) - tests += list_test_cases(KMAC256Test) - tests.append(NISTExampleTestVectors()) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_KangarooTwelve.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_KangarooTwelve.py index c9ad363e..59203e48 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_KangarooTwelve.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_KangarooTwelve.py @@ -36,332 +36,331 @@ class KangarooTwelveTest(unittest.TestCase): - - def test_length_encode(self): - self.assertEqual(K12._length_encode(0), b'\x00') - self.assertEqual(K12._length_encode(12), b'\x0C\x01') - self.assertEqual(K12._length_encode(65538), b'\x01\x00\x02\x03') - - def test_new_positive(self): - - xof1 = K12.new() - xof2 = K12.new(data=b("90")) - xof3 = K12.new().update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - xof1 = K12.new() - ref = xof1.read(10) - xof2 = K12.new(custom=b("")) - xof3 = K12.new(custom=b("foo")) - - self.assertEqual(ref, xof2.read(10)) - self.assertNotEqual(ref, xof3.read(10)) - - xof1 = K12.new(custom=b("foo")) - xof2 = K12.new(custom=b("foo"), data=b("90")) - xof3 = K12.new(custom=b("foo")).update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = K12.new() - h.update(pieces[0]).update(pieces[1]) - digest = h.read(10) - h = K12.new() - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.read(10), digest) - - def test_update_negative(self): - h = K12.new() - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = K12.new() - digest = h.read(90) - - # read returns a byte string of the right length - self.assertTrue(isinstance(digest, type(b("digest")))) - self.assertEqual(len(digest), 90) - - def test_update_after_read(self): - mac = K12.new() - mac.update(b("rrrr")) - mac.read(90) - self.assertRaises(TypeError, mac.update, b("ttt")) + def test_length_encode(self): + self.assertEqual(K12._length_encode(0), b"\x00") + self.assertEqual(K12._length_encode(12), b"\x0c\x01") + self.assertEqual(K12._length_encode(65538), b"\x01\x00\x02\x03") + + def test_new_positive(self): + xof1 = K12.new() + xof2 = K12.new(data=b("90")) + xof3 = K12.new().update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + xof1 = K12.new() + ref = xof1.read(10) + xof2 = K12.new(custom=b("")) + xof3 = K12.new(custom=b("foo")) + + self.assertEqual(ref, xof2.read(10)) + self.assertNotEqual(ref, xof3.read(10)) + + xof1 = K12.new(custom=b("foo")) + xof2 = K12.new(custom=b("foo"), data=b("90")) + xof3 = K12.new(custom=b("foo")).update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] + h = K12.new() + h.update(pieces[0]).update(pieces[1]) + digest = h.read(10) + h = K12.new() + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.read(10), digest) + + def test_update_negative(self): + h = K12.new() + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = K12.new() + digest = h.read(90) + + # read returns a byte string of the right length + self.assertTrue(isinstance(digest, type(b("digest")))) + self.assertEqual(len(digest), 90) + + def test_update_after_read(self): + mac = K12.new() + mac.update(b("rrrr")) + mac.read(90) + self.assertRaises(TypeError, mac.update, b("ttt")) def txt2bin(txt): - clean = txt.replace(" ", "").replace("\n", "").replace("\r", "") - return unhexlify(clean) + clean = txt.replace(" ", "").replace("\n", "").replace("\r", "") + return unhexlify(clean) def ptn(n): - res = bytearray(n) - pattern = b"".join([bchr(x) for x in range(0, 0xFB)]) - for base in range(0, n - 0xFB, 0xFB): - res[base:base + 0xFB] = pattern - remain = n % 0xFB - if remain: - base = (n // 0xFB) * 0xFB - res[base:] = pattern[:remain] - assert(len(res) == n) - return res + res = bytearray(n) + pattern = b"".join([bchr(x) for x in range(0, 0xFB)]) + for base in range(0, n - 0xFB, 0xFB): + res[base : base + 0xFB] = pattern + remain = n % 0xFB + if remain: + base = (n // 0xFB) * 0xFB + res[base:] = pattern[:remain] + assert len(res) == n + return res def chunked(source, size): - for i in range(0, len(source), size): - yield source[i:i+size] + for i in range(0, len(source), size): + yield source[i : i + size] class KangarooTwelveTV(unittest.TestCase): + # https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KangarooTwelve.txt - # https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KangarooTwelve.txt - - def test_zero_1(self): - tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51 + def test_zero_1(self): + tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51 3C 08 03 57 7A C7 16 7F 06 FE 2C E1 F0 EF 39 E5""" - btv = txt2bin(tv) - res = K12.new().read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new().read(32) + self.assertEqual(res, btv) - def test_zero_2(self): - tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51 + def test_zero_2(self): + tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51 3C 08 03 57 7A C7 16 7F 06 FE 2C E1 F0 EF 39 E5 42 69 C0 56 B8 C8 2E 48 27 60 38 B6 D2 92 96 6C C0 7A 3D 46 45 27 2E 31 FF 38 50 81 39 EB 0A 71""" - btv = txt2bin(tv) - res = K12.new().read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new().read(64) + self.assertEqual(res, btv) - def test_zero_3(self): - tv = """E8 DC 56 36 42 F7 22 8C 84 68 4C 89 84 05 D3 A8 + def test_zero_3(self): + tv = """E8 DC 56 36 42 F7 22 8C 84 68 4C 89 84 05 D3 A8 34 79 91 58 C0 79 B1 28 80 27 7A 1D 28 E2 FF 6D""" - btv = txt2bin(tv) - res = K12.new().read(10032) - self.assertEqual(res[-32:], btv) + btv = txt2bin(tv) + res = K12.new().read(10032) + self.assertEqual(res[-32:], btv) - def test_ptn_1(self): - tv = """2B DA 92 45 0E 8B 14 7F 8A 7C B6 29 E7 84 A0 58 + def test_ptn_1(self): + tv = """2B DA 92 45 0E 8B 14 7F 8A 7C B6 29 E7 84 A0 58 EF CA 7C F7 D8 21 8E 02 D3 45 DF AA 65 24 4A 1F""" - btv = txt2bin(tv) - res = K12.new(data=ptn(1)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=ptn(1)).read(32) + self.assertEqual(res, btv) - def test_ptn_17(self): - tv = """6B F7 5F A2 23 91 98 DB 47 72 E3 64 78 F8 E1 9B + def test_ptn_17(self): + tv = """6B F7 5F A2 23 91 98 DB 47 72 E3 64 78 F8 E1 9B 0F 37 12 05 F6 A9 A9 3A 27 3F 51 DF 37 12 28 88""" - btv = txt2bin(tv) - res = K12.new(data=ptn(17)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=ptn(17)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_2(self): - tv = """0C 31 5E BC DE DB F6 14 26 DE 7D CF 8F B7 25 D1 + def test_ptn_17_2(self): + tv = """0C 31 5E BC DE DB F6 14 26 DE 7D CF 8F B7 25 D1 E7 46 75 D7 F5 32 7A 50 67 F3 67 B1 08 EC B6 7C""" - btv = txt2bin(tv) - res = K12.new(data=ptn(17**2)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=ptn(17**2)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_3(self): - tv = """CB 55 2E 2E C7 7D 99 10 70 1D 57 8B 45 7D DF 77 + def test_ptn_17_3(self): + tv = """CB 55 2E 2E C7 7D 99 10 70 1D 57 8B 45 7D DF 77 2C 12 E3 22 E4 EE 7F E4 17 F9 2C 75 8F 0D 59 D0""" - btv = txt2bin(tv) - res = K12.new(data=ptn(17**3)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=ptn(17**3)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_4(self): - tv = """87 01 04 5E 22 20 53 45 FF 4D DA 05 55 5C BB 5C + def test_ptn_17_4(self): + tv = """87 01 04 5E 22 20 53 45 FF 4D DA 05 55 5C BB 5C 3A F1 A7 71 C2 B8 9B AE F3 7D B4 3D 99 98 B9 FE""" - btv = txt2bin(tv) - data = ptn(17**4) - - # All at once - res = K12.new(data=data).read(32) - self.assertEqual(res, btv) - - # Byte by byte - k12 = K12.new() - for x in data: - k12.update(bchr(x)) - res = k12.read(32) - self.assertEqual(res, btv) - - # Chunks of various prime sizes - for chunk_size in (13, 17, 19, 23, 31): - k12 = K12.new() - for x in chunked(data, chunk_size): - k12.update(x) - res = k12.read(32) - self.assertEqual(res, btv) - - def test_ptn_17_5(self): - tv = """84 4D 61 09 33 B1 B9 96 3C BD EB 5A E3 B6 B0 5C + btv = txt2bin(tv) + data = ptn(17**4) + + # All at once + res = K12.new(data=data).read(32) + self.assertEqual(res, btv) + + # Byte by byte + k12 = K12.new() + for x in data: + k12.update(bchr(x)) + res = k12.read(32) + self.assertEqual(res, btv) + + # Chunks of various prime sizes + for chunk_size in (13, 17, 19, 23, 31): + k12 = K12.new() + for x in chunked(data, chunk_size): + k12.update(x) + res = k12.read(32) + self.assertEqual(res, btv) + + def test_ptn_17_5(self): + tv = """84 4D 61 09 33 B1 B9 96 3C BD EB 5A E3 B6 B0 5C C7 CB D6 7C EE DF 88 3E B6 78 A0 A8 E0 37 16 82""" - btv = txt2bin(tv) - data = ptn(17**5) + btv = txt2bin(tv) + data = ptn(17**5) - # All at once - res = K12.new(data=data).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=data).read(32) + self.assertEqual(res, btv) - # Chunks - k12 = K12.new() - for chunk in chunked(data, 8192): - k12.update(chunk) - res = k12.read(32) - self.assertEqual(res, btv) + # Chunks + k12 = K12.new() + for chunk in chunked(data, 8192): + k12.update(chunk) + res = k12.read(32) + self.assertEqual(res, btv) - def test_ptn_17_6(self): - tv = """3C 39 07 82 A8 A4 E8 9F A6 36 7F 72 FE AA F1 32 + def test_ptn_17_6(self): + tv = """3C 39 07 82 A8 A4 E8 9F A6 36 7F 72 FE AA F1 32 55 C8 D9 58 78 48 1D 3C D8 CE 85 F5 8E 88 0A F8""" - btv = txt2bin(tv) - data = ptn(17**6) + btv = txt2bin(tv) + data = ptn(17**6) - # All at once - res = K12.new(data=data).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=data).read(32) + self.assertEqual(res, btv) - def test_ptn_c_1(self): - tv = """FA B6 58 DB 63 E9 4A 24 61 88 BF 7A F6 9A 13 30 + def test_ptn_c_1(self): + tv = """FA B6 58 DB 63 E9 4A 24 61 88 BF 7A F6 9A 13 30 45 F4 6E E9 84 C5 6E 3C 33 28 CA AF 1A A1 A5 83""" - btv = txt2bin(tv) - custom = ptn(1) + btv = txt2bin(tv) + custom = ptn(1) - # All at once - res = K12.new(custom=custom).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(custom=custom).read(32) + self.assertEqual(res, btv) - def test_ptn_c_41(self): - tv = """D8 48 C5 06 8C ED 73 6F 44 62 15 9B 98 67 FD 4C + def test_ptn_c_41(self): + tv = """D8 48 C5 06 8C ED 73 6F 44 62 15 9B 98 67 FD 4C 20 B8 08 AC C3 D5 BC 48 E0 B0 6B A0 A3 76 2E C4""" - btv = txt2bin(tv) - custom = ptn(41) + btv = txt2bin(tv) + custom = ptn(41) - # All at once - res = K12.new(data=b'\xFF', custom=custom).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=b"\xff", custom=custom).read(32) + self.assertEqual(res, btv) - def test_ptn_c_41_2(self): - tv = """C3 89 E5 00 9A E5 71 20 85 4C 2E 8C 64 67 0A C0 + def test_ptn_c_41_2(self): + tv = """C3 89 E5 00 9A E5 71 20 85 4C 2E 8C 64 67 0A C0 13 58 CF 4C 1B AF 89 44 7A 72 42 34 DC 7C ED 74""" - btv = txt2bin(tv) - custom = ptn(41**2) + btv = txt2bin(tv) + custom = ptn(41**2) - # All at once - res = K12.new(data=b'\xFF' * 3, custom=custom).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=b"\xff" * 3, custom=custom).read(32) + self.assertEqual(res, btv) - def test_ptn_c_41_3(self): - tv = """75 D2 F8 6A 2E 64 45 66 72 6B 4F BC FC 56 57 B9 + def test_ptn_c_41_3(self): + tv = """75 D2 F8 6A 2E 64 45 66 72 6B 4F BC FC 56 57 B9 DB CF 07 0C 7B 0D CA 06 45 0A B2 91 D7 44 3B CF""" - btv = txt2bin(tv) - custom = ptn(41**3) + btv = txt2bin(tv) + custom = ptn(41**3) - # All at once - res = K12.new(data=b'\xFF' * 7, custom=custom).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=b"\xff" * 7, custom=custom).read(32) + self.assertEqual(res, btv) - # https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/ + # https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/ - def test_ptn_8191(self): - tv = """1B 57 76 36 F7 23 64 3E 99 0C C7 D6 A6 59 83 74 + def test_ptn_8191(self): + tv = """1B 57 76 36 F7 23 64 3E 99 0C C7 D6 A6 59 83 74 36 FD 6A 10 36 26 60 0E B8 30 1C D1 DB E5 53 D6""" - btv = txt2bin(tv) + btv = txt2bin(tv) - # All at once - res = K12.new(data=ptn(8191)).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=ptn(8191)).read(32) + self.assertEqual(res, btv) - def test_ptn_8192(self): - tv = """48 F2 56 F6 77 2F 9E DF B6 A8 B6 61 EC 92 DC 93 + def test_ptn_8192(self): + tv = """48 F2 56 F6 77 2F 9E DF B6 A8 B6 61 EC 92 DC 93 B9 5E BD 05 A0 8A 17 B3 9A E3 49 08 70 C9 26 C3""" - btv = txt2bin(tv) + btv = txt2bin(tv) - # All at once - res = K12.new(data=ptn(8192)).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=ptn(8192)).read(32) + self.assertEqual(res, btv) - def test_ptn_8192_8189(self): - tv = """3E D1 2F 70 FB 05 DD B5 86 89 51 0A B3 E4 D2 3C + def test_ptn_8192_8189(self): + tv = """3E D1 2F 70 FB 05 DD B5 86 89 51 0A B3 E4 D2 3C 6C 60 33 84 9A A0 1E 1D 8C 22 0A 29 7F ED CD 0B""" - btv = txt2bin(tv) + btv = txt2bin(tv) - # All at once - res = K12.new(data=ptn(8192), custom=ptn(8189)).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=ptn(8192), custom=ptn(8189)).read(32) + self.assertEqual(res, btv) - def test_ptn_8192_8190(self): - tv = """6A 7C 1B 6A 5C D0 D8 C9 CA 94 3A 4A 21 6C C6 46 + def test_ptn_8192_8190(self): + tv = """6A 7C 1B 6A 5C D0 D8 C9 CA 94 3A 4A 21 6C C6 46 04 55 9A 2E A4 5F 78 57 0A 15 25 3D 67 BA 00 AE""" - btv = txt2bin(tv) + btv = txt2bin(tv) - # All at once - res = K12.new(data=ptn(8192), custom=ptn(8190)).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=ptn(8192), custom=ptn(8190)).read(32) + self.assertEqual(res, btv) - ### + ### - def test_1(self): - tv = "fd608f91d81904a9916e78a18f65c157a78d63f93d8f6367db0524526a5ea2bb" + def test_1(self): + tv = "fd608f91d81904a9916e78a18f65c157a78d63f93d8f6367db0524526a5ea2bb" - btv = txt2bin(tv) - res = K12.new(data=b'', custom=ptn(100)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=b"", custom=ptn(100)).read(32) + self.assertEqual(res, btv) - def test_2(self): - tv4 = "5a4ec9a649f81916d4ce1553492962f7868abf8dd1ceb2f0cb3682ea95cda6a6" - tv3 = "441688fe4fe4ae9425eb3105eb445eb2b3a6f67b66eff8e74ebfbc49371f6d4c" - tv2 = "17269a57759af0214c84a0fd9bc851f4d95f80554cfed4e7da8a6ee1ff080131" - tv1 = "33826990c09dc712ba7224f0d9be319e2720de95a4c1afbd2211507dae1c703a" - tv0 = "9f4d3aba908ddc096e4d3a71da954f917b9752f05052b9d26d916a6fbc75bf3e" + def test_2(self): + tv4 = "5a4ec9a649f81916d4ce1553492962f7868abf8dd1ceb2f0cb3682ea95cda6a6" + tv3 = "441688fe4fe4ae9425eb3105eb445eb2b3a6f67b66eff8e74ebfbc49371f6d4c" + tv2 = "17269a57759af0214c84a0fd9bc851f4d95f80554cfed4e7da8a6ee1ff080131" + tv1 = "33826990c09dc712ba7224f0d9be319e2720de95a4c1afbd2211507dae1c703a" + tv0 = "9f4d3aba908ddc096e4d3a71da954f917b9752f05052b9d26d916a6fbc75bf3e" - res = K12.new(data=b'A' * (8192 - 4), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv4)) + res = K12.new(data=b"A" * (8192 - 4), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv4)) - res = K12.new(data=b'A' * (8192 - 3), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv3)) + res = K12.new(data=b"A" * (8192 - 3), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv3)) - res = K12.new(data=b'A' * (8192 - 2), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv2)) + res = K12.new(data=b"A" * (8192 - 2), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv2)) - res = K12.new(data=b'A' * (8192 - 1), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv1)) + res = K12.new(data=b"A" * (8192 - 1), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv1)) - res = K12.new(data=b'A' * (8192 - 0), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv0)) + res = K12.new(data=b"A" * (8192 - 0), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv0)) def get_tests(config={}): - tests = [] - tests += list_test_cases(KangarooTwelveTest) - tests += list_test_cases(KangarooTwelveTV) - return tests + tests = [] + tests += list_test_cases(KangarooTwelveTest) + tests += list_test_cases(KangarooTwelveTV) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD2.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD2.py index beae38aa..0737ae8c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD2.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD2.py @@ -28,35 +28,46 @@ # This is a list of (expected_result, input[, description]) tuples. test_data = [ - # Test vectors from RFC 1319 - ('8350e5a3e24c153df2275c9f80692773', '', "'' (empty string)"), - ('32ec01ec4a6dac72c0ab96fb34c0b5d1', 'a'), - ('da853b0d3f88d99b30283a69e6ded6bb', 'abc'), - ('ab4f496bfb2a530b219ff33031fe06b0', 'message digest'), - - ('4e8ddff3650292ab5a4108c3aa47940b', 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - - ('da33def2a42df13975352846c30338cd', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), - - ('d5976f79d83d3a0dc9806c3c66f3efd8', - '1234567890123456789012345678901234567890123456' - + '7890123456789012345678901234567890', - "'1234567890' * 8"), + # Test vectors from RFC 1319 + ("8350e5a3e24c153df2275c9f80692773", "", "'' (empty string)"), + ("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a"), + ("da853b0d3f88d99b30283a69e6ded6bb", "abc"), + ("ab4f496bfb2a530b219ff33031fe06b0", "message digest"), + ( + "4e8ddff3650292ab5a4108c3aa47940b", + "abcdefghijklmnopqrstuvwxyz", + "a-z", + ), + ( + "da33def2a42df13975352846c30338cd", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "A-Z, a-z, 0-9", + ), + ( + "d5976f79d83d3a0dc9806c3c66f3efd8", + "1234567890123456789012345678901234567890123456" + "7890123456789012345678901234567890", + "'1234567890' * 8", + ), ] + def get_tests(config={}): - from Cryptodome.Hash import MD2 - from .common import make_hash_tests - return make_hash_tests(MD2, "MD2", test_data, - digest_size=16, - oid="1.2.840.113549.2.2") - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from Cryptodome.Hash import MD2 + from .common import make_hash_tests + + return make_hash_tests( + MD2, + "MD2", + test_data, + digest_size=16, + oid="1.2.840.113549.2.2", + ) + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD4.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD4.py index 41de9775..5d29626a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD4.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD4.py @@ -30,35 +30,46 @@ # This is a list of (expected_result, input[, description]) tuples. test_data = [ - # Test vectors from RFC 1320 - ('31d6cfe0d16ae931b73c59d7e0c089c0', '', "'' (empty string)"), - ('bde52cb31de33e46245e05fbdbd6fb24', 'a'), - ('a448017aaf21d8525fc10ae87aa6729d', 'abc'), - ('d9130a8164549fe818874806e1c7014b', 'message digest'), + # Test vectors from RFC 1320 + ("31d6cfe0d16ae931b73c59d7e0c089c0", "", "'' (empty string)"), + ("bde52cb31de33e46245e05fbdbd6fb24", "a"), + ("a448017aaf21d8525fc10ae87aa6729d", "abc"), + ("d9130a8164549fe818874806e1c7014b", "message digest"), + ( + "d79e1c308aa5bbcdeea8ed63df412da9", + "abcdefghijklmnopqrstuvwxyz", + "a-z", + ), + ( + "043f8582f241db351ce627e153e7f0e4", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "A-Z, a-z, 0-9", + ), + ( + "e33b4ddc9c38f2199c3e7b164fcc0536", + "1234567890123456789012345678901234567890123456" + "7890123456789012345678901234567890", + "'1234567890' * 8", + ), +] - ('d79e1c308aa5bbcdeea8ed63df412da9', 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - ('043f8582f241db351ce627e153e7f0e4', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), +def get_tests(config={}): + from Cryptodome.Hash import MD4 + from .common import make_hash_tests - ('e33b4ddc9c38f2199c3e7b164fcc0536', - '1234567890123456789012345678901234567890123456' - + '7890123456789012345678901234567890', - "'1234567890' * 8"), -] + return make_hash_tests( + MD4, + "MD4", + test_data, + digest_size=16, + oid="1.2.840.113549.2.4", + ) -def get_tests(config={}): - from Cryptodome.Hash import MD4 - from .common import make_hash_tests - return make_hash_tests(MD4, "MD4", test_data, - digest_size=16, - oid="1.2.840.113549.2.4") -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD5.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD5.py index 3f7a0057..7ba2db3f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD5.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_MD5.py @@ -26,69 +26,73 @@ from Cryptodome.Util.py3compat import * from Cryptodome.Hash import MD5 -from binascii import unhexlify import unittest -from Cryptodome.SelfTest.st_common import list_test_cases # This is a list of (expected_result, input[, description]) tuples. test_data = [ - # Test vectors from RFC 1321 - ('d41d8cd98f00b204e9800998ecf8427e', '', "'' (empty string)"), - ('0cc175b9c0f1b6a831c399e269772661', 'a'), - ('900150983cd24fb0d6963f7d28e17f72', 'abc'), - ('f96b697d7cb7938d525a2f31aaf161d0', 'message digest'), - - ('c3fcd3d76192e4007dfb496cca67e13b', 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - - ('d174ab98d277d9f5a5611c2c9f419d9f', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), - - ('57edf4a22be3c955ac49da2e2107b67a', - '1234567890123456789012345678901234567890123456' - + '7890123456789012345678901234567890', - "'1234567890' * 8"), - - # https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/md5/Md5-128.unverified.test-vectors - ('57EDF4A22BE3C955AC49DA2E2107B67A', '1234567890' * 8, 'Set 1, vector #7'), - ('7707D6AE4E027C70EEA2A935C2296F21', 'a'*1000000, 'Set 1, vector #8'), + # Test vectors from RFC 1321 + ("d41d8cd98f00b204e9800998ecf8427e", "", "'' (empty string)"), + ("0cc175b9c0f1b6a831c399e269772661", "a"), + ("900150983cd24fb0d6963f7d28e17f72", "abc"), + ("f96b697d7cb7938d525a2f31aaf161d0", "message digest"), + ( + "c3fcd3d76192e4007dfb496cca67e13b", + "abcdefghijklmnopqrstuvwxyz", + "a-z", + ), + ( + "d174ab98d277d9f5a5611c2c9f419d9f", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "A-Z, a-z, 0-9", + ), + ( + "57edf4a22be3c955ac49da2e2107b67a", + "1234567890123456789012345678901234567890123456" + "7890123456789012345678901234567890", + "'1234567890' * 8", + ), + # https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/md5/Md5-128.unverified.test-vectors + ("57EDF4A22BE3C955AC49DA2E2107B67A", "1234567890" * 8, "Set 1, vector #7"), + ("7707D6AE4E027C70EEA2A935C2296F21", "a" * 1000000, "Set 1, vector #8"), ] class Md5IterTest(unittest.TestCase): + def runTest(self): + message = b("\x00") * 16 + result1 = "4AE71336E44BF9BF79D2752E234818A5".lower() + result2 = "1A83F51285E4D89403D00C46EF8508FE".lower() - def runTest(self): - message = b("\x00") * 16 - result1 = "4AE71336E44BF9BF79D2752E234818A5".lower() - result2 = "1A83F51285E4D89403D00C46EF8508FE".lower() + h = MD5.new(message) + message = h.digest() + self.assertEqual(h.hexdigest(), result1) - h = MD5.new(message) - message = h.digest() - self.assertEqual(h.hexdigest(), result1) + for _ in range(99999): + h = MD5.new(message) + message = h.digest() - for _ in range(99999): - h = MD5.new(message) - message = h.digest() - - self.assertEqual(h.hexdigest(), result2) + self.assertEqual(h.hexdigest(), result2) def get_tests(config={}): - from .common import make_hash_tests + from .common import make_hash_tests + + tests = make_hash_tests( + MD5, + "MD5", + test_data, + digest_size=16, + oid="1.2.840.113549.2.5", + ) + if config.get("slow_tests"): + tests += [Md5IterTest()] + return tests - tests = make_hash_tests(MD5, "MD5", test_data, - digest_size=16, - oid="1.2.840.113549.2.5") - if config.get('slow_tests'): - tests += [ Md5IterTest() ] - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_Poly1305.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_Poly1305.py index 19cacb4d..80fb5468 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_Poly1305.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_Poly1305.py @@ -33,7 +33,6 @@ """Self-test suite for Cryptodome.Hash._Poly1305""" -import json import unittest from binascii import unhexlify, hexlify @@ -48,436 +47,430 @@ # This is a list of (r+s keypair, data, result, description, keywords) tuples. test_data_basic = [ - ( - "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b", - hexlify(b"Cryptographic Forum Research Group").decode(), - "a8061dc1305136c6c22b8baf0c0127a9", - "RFC7539" - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "0000000000000000000000000000000000000000000000000000000000000000", - "49ec78090e481ec6c26b33b91ccc0307", - "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 A", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "48656c6c6f20776f726c6421", - "a6f745008f81c916a20dcc74eef2b2f0", - "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 B", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "", - "6b657920666f7220506f6c7931333035", - "Generated with pure Python", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "FF", - "f7e4e0ef4c46d106219da3d1bdaeb3ff", - "Generated with pure Python", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "FF00", - "7471eceeb22988fc936da1d6e838b70e", - "Generated with pure Python", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "AA" * 17, - "32590bc07cb2afaccca3f67f122975fe", - "Generated with pure Python", - ), - ( - "00" * 32, - "00" * 64, - "00" * 16, - "RFC7539 A.3 #1", - ), - ( - "0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e", - hexlify( - b"Any submission t" - b"o the IETF inten" - b"ded by the Contr" - b"ibutor for publi" - b"cation as all or" - b" part of an IETF" - b" Internet-Draft " - b"or RFC and any s" - b"tatement made wi" - b"thin the context" - b" of an IETF acti" - b"vity is consider" - b"ed an \"IETF Cont" - b"ribution\". Such " - b"statements inclu" - b"de oral statemen" - b"ts in IETF sessi" - b"ons, as well as " - b"written and elec" - b"tronic communica" - b"tions made at an" - b"y time or place," - b" which are addre" - b"ssed to").decode(), - "36e5f6b5c5e06070f0efca96227a863e", - "RFC7539 A.3 #2", - ), - ( - "36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000", - hexlify( - b"Any submission t" - b"o the IETF inten" - b"ded by the Contr" - b"ibutor for publi" - b"cation as all or" - b" part of an IETF" - b" Internet-Draft " - b"or RFC and any s" - b"tatement made wi" - b"thin the context" - b" of an IETF acti" - b"vity is consider" - b"ed an \"IETF Cont" - b"ribution\". Such " - b"statements inclu" - b"de oral statemen" - b"ts in IETF sessi" - b"ons, as well as " - b"written and elec" - b"tronic communica" - b"tions made at an" - b"y time or place," - b" which are addre" - b"ssed to").decode(), - "f3477e7cd95417af89a6b8794c310cf0", - "RFC7539 A.3 #3", - ), - ( - "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", - "2754776173206272696c6c69672c2061" - "6e642074686520736c6974687920746f" - "7665730a446964206779726520616e64" - "2067696d626c6520696e207468652077" - "6162653a0a416c6c206d696d73792077" - "6572652074686520626f726f676f7665" - "732c0a416e6420746865206d6f6d6520" - "7261746873206f757467726162652e", - "4541669a7eaaee61e708dc7cbcc5eb62", - "RFC7539 A.3 #4", - ), - ( - "02" + "00" * 31, - "FF" * 16, - "03" + "00" * 15, - "RFC7539 A.3 #5", - ), - ( - "02" + "00" * 15 + "FF" * 16, - "02" + "00" * 15, - "03" + "00" * 15, - "RFC7539 A.3 #6", - ), - ( - "01" + "00" * 31, - "FF" * 16 + "F0" + "FF" * 15 + "11" + "00" * 15, - "05" + "00" * 15, - "RFC7539 A.3 #7", - ), - ( - "01" + "00" * 31, - "FF" * 16 + "FB" + "FE" * 15 + "01" * 16, - "00" * 16, - "RFC7539 A.3 #8", - ), - ( - "02" + "00" * 31, - "FD" + "FF" * 15, - "FA" + "FF" * 15, - "RFC7539 A.3 #9", - ), - ( - "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" - "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" - "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "14 00 00 00 00 00 00 00 55 00 00 00 00 00 00 00", - "RFC7539 A.3 #10", - ), - ( - "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" - "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "13" + "00" * 15, - "RFC7539 A.3 #11", - ), + ( + "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b", + hexlify(b"Cryptographic Forum Research Group").decode(), + "a8061dc1305136c6c22b8baf0c0127a9", + "RFC7539", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "0000000000000000000000000000000000000000000000000000000000000000", + "49ec78090e481ec6c26b33b91ccc0307", + "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 A", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "48656c6c6f20776f726c6421", + "a6f745008f81c916a20dcc74eef2b2f0", + "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 B", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "", + "6b657920666f7220506f6c7931333035", + "Generated with pure Python", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "FF", + "f7e4e0ef4c46d106219da3d1bdaeb3ff", + "Generated with pure Python", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "FF00", + "7471eceeb22988fc936da1d6e838b70e", + "Generated with pure Python", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "AA" * 17, + "32590bc07cb2afaccca3f67f122975fe", + "Generated with pure Python", + ), + ( + "00" * 32, + "00" * 64, + "00" * 16, + "RFC7539 A.3 #1", + ), + ( + "0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e", + hexlify( + b"Any submission t" + b"o the IETF inten" + b"ded by the Contr" + b"ibutor for publi" + b"cation as all or" + b" part of an IETF" + b" Internet-Draft " + b"or RFC and any s" + b"tatement made wi" + b"thin the context" + b" of an IETF acti" + b"vity is consider" + b'ed an "IETF Cont' + b'ribution". Such ' + b"statements inclu" + b"de oral statemen" + b"ts in IETF sessi" + b"ons, as well as " + b"written and elec" + b"tronic communica" + b"tions made at an" + b"y time or place," + b" which are addre" + b"ssed to", + ).decode(), + "36e5f6b5c5e06070f0efca96227a863e", + "RFC7539 A.3 #2", + ), + ( + "36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000", + hexlify( + b"Any submission t" + b"o the IETF inten" + b"ded by the Contr" + b"ibutor for publi" + b"cation as all or" + b" part of an IETF" + b" Internet-Draft " + b"or RFC and any s" + b"tatement made wi" + b"thin the context" + b" of an IETF acti" + b"vity is consider" + b'ed an "IETF Cont' + b'ribution". Such ' + b"statements inclu" + b"de oral statemen" + b"ts in IETF sessi" + b"ons, as well as " + b"written and elec" + b"tronic communica" + b"tions made at an" + b"y time or place," + b" which are addre" + b"ssed to", + ).decode(), + "f3477e7cd95417af89a6b8794c310cf0", + "RFC7539 A.3 #3", + ), + ( + "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "2754776173206272696c6c69672c2061" + "6e642074686520736c6974687920746f" + "7665730a446964206779726520616e64" + "2067696d626c6520696e207468652077" + "6162653a0a416c6c206d696d73792077" + "6572652074686520626f726f676f7665" + "732c0a416e6420746865206d6f6d6520" + "7261746873206f757467726162652e", + "4541669a7eaaee61e708dc7cbcc5eb62", + "RFC7539 A.3 #4", + ), + ( + "02" + "00" * 31, + "FF" * 16, + "03" + "00" * 15, + "RFC7539 A.3 #5", + ), + ( + "02" + "00" * 15 + "FF" * 16, + "02" + "00" * 15, + "03" + "00" * 15, + "RFC7539 A.3 #6", + ), + ( + "01" + "00" * 31, + "FF" * 16 + "F0" + "FF" * 15 + "11" + "00" * 15, + "05" + "00" * 15, + "RFC7539 A.3 #7", + ), + ( + "01" + "00" * 31, + "FF" * 16 + "FB" + "FE" * 15 + "01" * 16, + "00" * 16, + "RFC7539 A.3 #8", + ), + ( + "02" + "00" * 31, + "FD" + "FF" * 15, + "FA" + "FF" * 15, + "RFC7539 A.3 #9", + ), + ( + "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" + "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" + "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "14 00 00 00 00 00 00 00 55 00 00 00 00 00 00 00", + "RFC7539 A.3 #10", + ), + ( + "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" + "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "13" + "00" * 15, + "RFC7539 A.3 #11", + ), ] # This is a list of (key(k+r), data, result, description, keywords) tuples. test_data_aes = [ - ( - "ec074c835580741701425b623235add6851fc40c3467ac0be05cc20404f3f700", - "f3f6", - "f4c633c3044fc145f84f335cb81953de", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("fb447350c4e868c52ac3275cf9d4327e") } - ), - ( - "75deaa25c09f208e1dc4ce6b5cad3fbfa0f3080000f46400d0c7e9076c834403", - "", - "dd3fab2251f11ac759f0887129cc2ee7", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("61ee09218d29b0aaed7e154a2c5509cc") } - ), - ( - "6acb5f61a7176dd320c5c1eb2edcdc7448443d0bb0d21109c89a100b5ce2c208", - "663cea190ffb83d89593f3f476b6bc24" - "d7e679107ea26adb8caf6652d0656136", - "0ee1c16bb73f0f4fd19881753c01cdbe", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("ae212a55399729595dea458bc621ff0e") } - ), - ( - "e1a5668a4d5b66a5f68cc5424ed5982d12976a08c4426d0ce8a82407c4f48207", - "ab0812724a7f1e342742cbed374d94d1" - "36c6b8795d45b3819830f2c04491faf0" - "990c62e48b8018b2c3e4a0fa3134cb67" - "fa83e158c994d961c4cb21095c1bf9", - "5154ad0d2cb26e01274fc51148491f1b", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("9ae831e743978d3a23527c7128149e3a") } - ), + ( + "ec074c835580741701425b623235add6851fc40c3467ac0be05cc20404f3f700", + "f3f6", + "f4c633c3044fc145f84f335cb81953de", + "http://cr.yp.to/mac/poly1305-20050329.pdf", + {"cipher": AES, "nonce": unhexlify("fb447350c4e868c52ac3275cf9d4327e")}, + ), + ( + "75deaa25c09f208e1dc4ce6b5cad3fbfa0f3080000f46400d0c7e9076c834403", + "", + "dd3fab2251f11ac759f0887129cc2ee7", + "http://cr.yp.to/mac/poly1305-20050329.pdf", + {"cipher": AES, "nonce": unhexlify("61ee09218d29b0aaed7e154a2c5509cc")}, + ), + ( + "6acb5f61a7176dd320c5c1eb2edcdc7448443d0bb0d21109c89a100b5ce2c208", + "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136", + "0ee1c16bb73f0f4fd19881753c01cdbe", + "http://cr.yp.to/mac/poly1305-20050329.pdf", + {"cipher": AES, "nonce": unhexlify("ae212a55399729595dea458bc621ff0e")}, + ), + ( + "e1a5668a4d5b66a5f68cc5424ed5982d12976a08c4426d0ce8a82407c4f48207", + "ab0812724a7f1e342742cbed374d94d1" + "36c6b8795d45b3819830f2c04491faf0" + "990c62e48b8018b2c3e4a0fa3134cb67" + "fa83e158c994d961c4cb21095c1bf9", + "5154ad0d2cb26e01274fc51148491f1b", + "http://cr.yp.to/mac/poly1305-20050329.pdf", + {"cipher": AES, "nonce": unhexlify("9ae831e743978d3a23527c7128149e3a")}, + ), ] test_data_chacha20 = [ - ( - "00" * 32, - "FF" * 15, - "13cc5bbadc36b03a5163928f0bcb65aa", - "RFC7539 A.4 #1", - { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 12) } - ), - ( - "00" * 31 + "01", - "FF" * 15, - "0baf33c1d6df211bdd50a6767e98e00a", - "RFC7539 A.4 #2", - { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 11 + "02") } - ), - ( - "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0" - "47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", - "FF" * 15, - "e8b4c6db226cd8939e65e02eebf834ce", - "RFC7539 A.4 #3", - { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 11 + "02") } - ), - ( - "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0" - "47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", - "f3 33 88 86 00 00 00 00 00 00 4e 91 00 00 00 00" - "64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd" - "5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2" - "4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0" - "bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf" - "33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81" - "14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55" - "97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38" - "36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4" - "b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9" - "90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e" - "af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a" - "0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a" - "0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e" - "ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10" - "49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30" - "30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29" - "a6 ad 5c b4 02 2b 02 70 9b 00 00 00 00 00 00 00" - "0c 00 00 00 00 00 00 00 09 01 00 00 00 00 00 00", - "ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38", - "RFC7539 A.5", - { 'cipher':ChaCha20, 'nonce':unhexlify("000000000102030405060708") } - ), + ( + "00" * 32, + "FF" * 15, + "13cc5bbadc36b03a5163928f0bcb65aa", + "RFC7539 A.4 #1", + {"cipher": ChaCha20, "nonce": unhexlify("00" * 12)}, + ), + ( + "00" * 31 + "01", + "FF" * 15, + "0baf33c1d6df211bdd50a6767e98e00a", + "RFC7539 A.4 #2", + {"cipher": ChaCha20, "nonce": unhexlify("00" * 11 + "02")}, + ), + ( + "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f047 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", + "FF" * 15, + "e8b4c6db226cd8939e65e02eebf834ce", + "RFC7539 A.4 #3", + {"cipher": ChaCha20, "nonce": unhexlify("00" * 11 + "02")}, + ), + ( + "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f047 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", + "f3 33 88 86 00 00 00 00 00 00 4e 91 00 00 00 00" + "64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd" + "5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2" + "4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0" + "bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf" + "33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81" + "14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55" + "97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38" + "36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4" + "b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9" + "90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e" + "af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a" + "0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a" + "0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e" + "ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10" + "49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30" + "30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29" + "a6 ad 5c b4 02 2b 02 70 9b 00 00 00 00 00 00 00" + "0c 00 00 00 00 00 00 00 09 01 00 00 00 00 00 00", + "ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38", + "RFC7539 A.5", + {"cipher": ChaCha20, "nonce": unhexlify("000000000102030405060708")}, + ), ] class Poly1305Test_AES(unittest.TestCase): - - key = b'\x11' * 32 - - def test_new_positive(self): - - data = b'r' * 100 - - h1 = Poly1305.new(key=self.key, cipher=AES) - self.assertEqual(h1.digest_size, 16) - self.assertEqual(len(h1.nonce), 16) - d1 = h1.update(data).digest() - self.assertEqual(len(d1), 16) - - h2 = Poly1305.new(key=self.key, nonce=h1.nonce, data=data, cipher=AES) - d2 = h2.digest() - self.assertEqual(h1.nonce, h2.nonce) - self.assertEqual(d1, d2) - - def test_new_negative(self): - from Cryptodome.Cipher import DES3 - - self.assertRaises(ValueError, Poly1305.new, key=self.key[:31], cipher=AES) - self.assertRaises(ValueError, Poly1305.new, key=self.key, cipher=DES3) - self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b'1' * 15, cipher=AES) - self.assertRaises(TypeError, Poly1305.new, key=u"2" * 32, cipher=AES) - self.assertRaises(TypeError, Poly1305.new, key=self.key, data=u"2" * 100, cipher=AES) - - def test_update(self): - pieces = [b"\x0A" * 200, b"\x14" * 300] - h1 = Poly1305.new(key=self.key, cipher=AES) - h1.update(pieces[0]).update(pieces[1]) - d1 = h1.digest() - - h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) - h2.update(pieces[0] + pieces[1]) - d2 = h2.digest() - self.assertEqual(d1, d2) - - def test_update_negative(self): - h = Poly1305.new(key=self.key, cipher=AES) - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = Poly1305.new(key=self.key, cipher=AES) - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg=b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = Poly1305.new(key=self.key, data=msg[:4], cipher=AES) - h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - - def test_hex_digest(self): - mac = Poly1305.new(key=self.key, cipher=AES) - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_verify(self): - h = Poly1305.new(key=self.key, cipher=AES) - mac = h.digest() - h.verify(mac) - wrong_mac = strxor_c(mac, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - - def test_hexverify(self): - h = Poly1305.new(key=self.key, cipher=AES) - mac = h.hexdigest() - h.hexverify(mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - def test_bytearray(self): - - data = b"\x00\x01\x02" - h0 = Poly1305.new(key=self.key, data=data, cipher=AES) - d_ref = h0.digest() - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(self.key) - data_ba = bytearray(data) - - h1 = Poly1305.new(key=self.key, data=data, cipher=AES, nonce=h0.nonce) - h2 = Poly1305.new(key=key_ba, data=data_ba, cipher=AES, nonce=h0.nonce) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xEE' - - self.assertEqual(h1.digest(), d_ref) - self.assertEqual(h2.digest(), d_ref) - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = Poly1305.new(key=self.key, cipher=AES) - h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(self.key) - data_mv = get_mv(data) - - h1 = Poly1305.new(key=self.key, data=data, cipher=AES) - h2 = Poly1305.new(key=key_mv, data=data_mv, cipher=AES, - nonce=h1.nonce) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - key_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = Poly1305.new(key=self.key, cipher=AES) - h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) + key = b"\x11" * 32 + + def test_new_positive(self): + data = b"r" * 100 + + h1 = Poly1305.new(key=self.key, cipher=AES) + self.assertEqual(h1.digest_size, 16) + self.assertEqual(len(h1.nonce), 16) + d1 = h1.update(data).digest() + self.assertEqual(len(d1), 16) + + h2 = Poly1305.new(key=self.key, nonce=h1.nonce, data=data, cipher=AES) + d2 = h2.digest() + self.assertEqual(h1.nonce, h2.nonce) + self.assertEqual(d1, d2) + + def test_new_negative(self): + from Cryptodome.Cipher import DES3 + + self.assertRaises(ValueError, Poly1305.new, key=self.key[:31], cipher=AES) + self.assertRaises(ValueError, Poly1305.new, key=self.key, cipher=DES3) + self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b"1" * 15, cipher=AES) + self.assertRaises(TypeError, Poly1305.new, key="2" * 32, cipher=AES) + self.assertRaises(TypeError, Poly1305.new, key=self.key, data="2" * 100, cipher=AES) + + def test_update(self): + pieces = [b"\x0a" * 200, b"\x14" * 300] + h1 = Poly1305.new(key=self.key, cipher=AES) + h1.update(pieces[0]).update(pieces[1]) + d1 = h1.digest() + + h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) + h2.update(pieces[0] + pieces[1]) + d2 = h2.digest() + self.assertEqual(d1, d2) + + def test_update_negative(self): + h = Poly1305.new(key=self.key, cipher=AES) + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = Poly1305.new(key=self.key, cipher=AES) + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b"digest"))) + + def test_update_after_digest(self): + msg = b"rrrrttt" + + # Normally, update() cannot be done after digest() + h = Poly1305.new(key=self.key, data=msg[:4], cipher=AES) + h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + + def test_hex_digest(self): + mac = Poly1305.new(key=self.key, cipher=AES) + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_verify(self): + h = Poly1305.new(key=self.key, cipher=AES) + mac = h.digest() + h.verify(mac) + wrong_mac = strxor_c(mac, 255) + self.assertRaises(ValueError, h.verify, wrong_mac) + + def test_hexverify(self): + h = Poly1305.new(key=self.key, cipher=AES) + mac = h.hexdigest() + h.hexverify(mac) + self.assertRaises(ValueError, h.hexverify, "4556") + + def test_bytearray(self): + data = b"\x00\x01\x02" + h0 = Poly1305.new(key=self.key, data=data, cipher=AES) + d_ref = h0.digest() + + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(self.key) + data_ba = bytearray(data) + + h1 = Poly1305.new(key=self.key, data=data, cipher=AES, nonce=h0.nonce) + h2 = Poly1305.new(key=key_ba, data=data_ba, cipher=AES, nonce=h0.nonce) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xee" + + self.assertEqual(h1.digest(), d_ref) + self.assertEqual(h2.digest(), d_ref) + + # Data can be a bytearray (during operation) + data_ba = bytearray(data) + + h1 = Poly1305.new(key=self.key, cipher=AES) + h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + def test_memoryview(self): + data = b"\x00\x01\x02" + + def get_mv_ro(data): + return memoryview(data) + + def get_mv_rw(data): + return memoryview(bytearray(data)) + + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(self.key) + data_mv = get_mv(data) + + h1 = Poly1305.new(key=self.key, data=data, cipher=AES) + h2 = Poly1305.new( + key=key_mv, + data=data_mv, + cipher=AES, + nonce=h1.nonce, + ) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + key_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + # Data can be a memoryview (during operation) + data_mv = get_mv(data) + + h1 = Poly1305.new(key=self.key, cipher=AES) + h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) class Poly1305Test_ChaCha20(unittest.TestCase): + key = b"\x11" * 32 - key = b'\x11' * 32 + def test_new_positive(self): + data = b"r" * 100 - def test_new_positive(self): - data = b'r' * 100 + h1 = Poly1305.new(key=self.key, cipher=ChaCha20) + self.assertEqual(h1.digest_size, 16) + self.assertEqual(len(h1.nonce), 12) - h1 = Poly1305.new(key=self.key, cipher=ChaCha20) - self.assertEqual(h1.digest_size, 16) - self.assertEqual(len(h1.nonce), 12) - - h2 = Poly1305.new(key=self.key, cipher=ChaCha20, nonce = b'8' * 8) - self.assertEqual(len(h2.nonce), 8) - self.assertEqual(h2.nonce, b'8' * 8) + h2 = Poly1305.new(key=self.key, cipher=ChaCha20, nonce=b"8" * 8) + self.assertEqual(len(h2.nonce), 8) + self.assertEqual(h2.nonce, b"8" * 8) - def test_new_negative(self): - - self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b'1' * 7, cipher=ChaCha20) + def test_new_negative(self): + self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b"1" * 7, cipher=ChaCha20) # @@ -485,58 +478,55 @@ def test_new_negative(self): # **kwargs), and we need to adapt Poly1305's, as it only uses keywords # class Poly1305_New(object): - - @staticmethod - def new(key, *data, **kwds): - _kwds = dict(kwds) - if len(data) == 1: - _kwds['data'] = data[0] - _kwds['key'] = key - return Poly1305.new(**_kwds) + @staticmethod + def new(key, *data, **kwds): + _kwds = dict(kwds) + if len(data) == 1: + _kwds["data"] = data[0] + _kwds["key"] = key + return Poly1305.new(**_kwds) class Poly1305_Basic(object): + @staticmethod + def new(key, *data, **kwds): + from Cryptodome.Hash.Poly1305 import Poly1305_MAC - @staticmethod - def new(key, *data, **kwds): - from Cryptodome.Hash.Poly1305 import Poly1305_MAC + if len(data) == 1: + msg = data[0] + else: + msg = None - if len(data) == 1: - msg = data[0] - else: - msg = None - - return Poly1305_MAC(key[:16], key[16:], msg) + return Poly1305_MAC(key[:16], key[16:], msg) class Poly1305AES_MC(unittest.TestCase): + def runTest(self): + tag = unhexlify(b"fb447350c4e868c52ac3275cf9d4327e") - def runTest(self): - tag = unhexlify(b"fb447350c4e868c52ac3275cf9d4327e") - - msg = b'' - for msg_len in range(5000 + 1): - key = tag + strxor_c(tag, 0xFF) - nonce = tag[::-1] - if msg_len > 0: - msg = msg + tobytes(tag[0]) - auth = Poly1305.new(key=key, nonce=nonce, cipher=AES, data=msg) - tag = auth.digest() + msg = b"" + for msg_len in range(5000 + 1): + key = tag + strxor_c(tag, 0xFF) + nonce = tag[::-1] + if msg_len > 0: + msg = msg + tobytes(tag[0]) + auth = Poly1305.new(key=key, nonce=nonce, cipher=AES, data=msg) + tag = auth.digest() - # Compare against output of original DJB's poly1305aes-20050218 - self.assertEqual("CDFA436DDD629C7DC20E1128530BAED2", auth.hexdigest().upper()) + # Compare against output of original DJB's poly1305aes-20050218 + self.assertEqual("CDFA436DDD629C7DC20E1128530BAED2", auth.hexdigest().upper()) def get_tests(config={}): - tests = make_mac_tests(Poly1305_Basic, "Poly1305", test_data_basic) - tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_aes) - tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_chacha20) - tests += [ Poly1305AES_MC() ] - tests += list_test_cases(Poly1305Test_AES) - tests += list_test_cases(Poly1305Test_ChaCha20) - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = make_mac_tests(Poly1305_Basic, "Poly1305", test_data_basic) + tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_aes) + tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_chacha20) + tests += [Poly1305AES_MC()] + tests += list_test_cases(Poly1305Test_AES) + tests += list_test_cases(Poly1305Test_ChaCha20) + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_RIPEMD160.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_RIPEMD160.py index c05a8779..0f7b31a8 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_RIPEMD160.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_RIPEMD160.py @@ -22,50 +22,63 @@ # SOFTWARE. # =================================================================== -#"""Self-test suite for Cryptodome.Hash.RIPEMD160""" +# """Self-test suite for Cryptodome.Hash.RIPEMD160""" from Cryptodome.Util.py3compat import * # This is a list of (expected_result, input[, description]) tuples. test_data = [ - # Test vectors downloaded 2008-09-12 from - # http://homes.esat.kuleuven.be/~bosselae/ripemd160.html - ('9c1185a5c5e9fc54612808977ee8f548b2258d31', '', "'' (empty string)"), - ('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe', 'a'), - ('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc', 'abc'), - ('5d0689ef49d2fae572b881b123a85ffa21595f36', 'message digest'), + # Test vectors downloaded 2008-09-12 from + # http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + ("9c1185a5c5e9fc54612808977ee8f548b2258d31", "", "'' (empty string)"), + ("0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"), + ("8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"), + ("5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"), + ( + "f71c27109c692c1b56bbdceb5b9d2865b3708dbc", + "abcdefghijklmnopqrstuvwxyz", + "a-z", + ), + ( + "12a053384a9c0c88e405a06c27dcf49ada62eb2b", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "abcdbcd...pnopq", + ), + ( + "b0e20b6e3116640286ed3a87a5713079b21f5189", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "A-Z, a-z, 0-9", + ), + ( + "9b752e45573d4b39f4dbd3323cab82bf63326bfb", + "1234567890" * 8, + "'1234567890' * 8", + ), + ( + "52783243c1697bdbe16d37f97f68f08325dc1528", + "a" * 10**6, + '"a" * 10**6', + ), +] - ('f71c27109c692c1b56bbdceb5b9d2865b3708dbc', - 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - ('12a053384a9c0c88e405a06c27dcf49ada62eb2b', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', - 'abcdbcd...pnopq'), +def get_tests(config={}): + from Cryptodome.Hash import RIPEMD160 + from .common import make_hash_tests - ('b0e20b6e3116640286ed3a87a5713079b21f5189', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), + return make_hash_tests( + RIPEMD160, + "RIPEMD160", + test_data, + digest_size=20, + oid="1.3.36.3.2.1", + ) - ('9b752e45573d4b39f4dbd3323cab82bf63326bfb', - '1234567890' * 8, - "'1234567890' * 8"), - ('52783243c1697bdbe16d37f97f68f08325dc1528', - 'a' * 10**6, - '"a" * 10**6'), -] - -def get_tests(config={}): - from Cryptodome.Hash import RIPEMD160 - from .common import make_hash_tests - return make_hash_tests(RIPEMD160, "RIPEMD160", test_data, - digest_size=20, - oid="1.3.36.3.2.1") +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA1.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA1.py index a879e68c..364f559e 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA1.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA1.py @@ -31,54 +31,67 @@ # Test vectors from various sources # This is a list of (expected_result, input[, description]) tuples. test_data_various = [ - # FIPS PUB 180-2, A.1 - "One-Block Message" - ('a9993e364706816aba3e25717850c26c9cd0d89d', 'abc'), + # FIPS PUB 180-2, A.1 - "One-Block Message" + ("a9993e364706816aba3e25717850c26c9cd0d89d", "abc"), + # FIPS PUB 180-2, A.2 - "Multi-Block Message" + ( + "84983e441c3bd26ebaae4aa1f95129e5e54670f1", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + ), + # FIPS PUB 180-2, A.3 - "Long Message" + # ('34aa973cd4c4daa4f61eeb2bdbad27316534016f', + # 'a' * 10**6, + # '"a" * 10**6'), + # RFC 3174: Section 7.3, "TEST4" (multiple of 512 bits) + ( + "dea356a2cddd90c7a7ecedc5ebb563934f460452", + "01234567" * 80, + '"01234567" * 80', + ), +] - # FIPS PUB 180-2, A.2 - "Multi-Block Message" - ('84983e441c3bd26ebaae4aa1f95129e5e54670f1', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), - # FIPS PUB 180-2, A.3 - "Long Message" -# ('34aa973cd4c4daa4f61eeb2bdbad27316534016f', -# 'a' * 10**6, -# '"a" * 10**6'), +def get_tests(config={}): + from Cryptodome.Hash import SHA1 + from .common import make_hash_tests - # RFC 3174: Section 7.3, "TEST4" (multiple of 512 bits) - ('dea356a2cddd90c7a7ecedc5ebb563934f460452', - '01234567' * 80, - '"01234567" * 80'), -] + tests = [] -def get_tests(config={}): - from Cryptodome.Hash import SHA1 - from .common import make_hash_tests + test_vectors = ( + load_test_vectors( + ("Hash", "SHA1"), + "SHA1ShortMsg.rsp", + "KAT SHA-1", + {"len": lambda x: int(x)}, + ) + or [] + ) - tests = [] + test_data = test_data_various[:] + for tv in test_vectors: + try: + if tv.startswith("["): + continue + except AttributeError: + pass + if tv.len == 0: + tv.msg = b"" + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - test_vectors = load_test_vectors(("Hash", "SHA1"), - "SHA1ShortMsg.rsp", - "KAT SHA-1", - { "len" : lambda x: int(x) } ) or [] + tests = make_hash_tests( + SHA1, + "SHA1", + test_data, + digest_size=20, + oid="1.3.14.3.2.26", + ) + return tests - test_data = test_data_various[:] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - tests = make_hash_tests(SHA1, "SHA1", test_data, - digest_size=20, - oid="1.3.14.3.2.26") - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA224.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA224.py index da32423a..a45feb1b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA224.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA224.py @@ -27,37 +27,45 @@ # Test vectors from various sources # This is a list of (expected_result, input[, description]) tuples. test_data = [ + # RFC 3874: Section 3.1, "Test Vector #1 + ("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", "abc"), + # RFC 3874: Section 3.2, "Test Vector #2 + ( + "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + ), + # RFC 3874: Section 3.3, "Test Vector #3 + ("20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67", "a" * 10**6, "'a' * 10**6"), + # Examples from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", ""), + ( + "49b08defa65e644cbf8a2dd9270bdededabc741997d1dadd42026d7b", + "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), + ( + "58911e7fccf2971a7d07f93162d8bd13568e71aa8fc86fc1fe9043d1", + "Frank jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), +] - # RFC 3874: Section 3.1, "Test Vector #1 - ('23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7', 'abc'), - - # RFC 3874: Section 3.2, "Test Vector #2 - ('75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), - - # RFC 3874: Section 3.3, "Test Vector #3 - ('20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67', 'a' * 10**6, "'a' * 10**6"), - # Examples from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f', ''), +def get_tests(config={}): + from Cryptodome.Hash import SHA224 + from .common import make_hash_tests - ('49b08defa65e644cbf8a2dd9270bdededabc741997d1dadd42026d7b', - 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), + return make_hash_tests( + SHA224, + "SHA224", + test_data, + digest_size=28, + oid="2.16.840.1.101.3.4.2.4", + ) - ('58911e7fccf2971a7d07f93162d8bd13568e71aa8fc86fc1fe9043d1', - 'Frank jagt im komplett verwahrlosten Taxi quer durch Bayern'), -] +if __name__ == "__main__": + import unittest -def get_tests(config={}): - from Cryptodome.Hash import SHA224 - from .common import make_hash_tests - return make_hash_tests(SHA224, "SHA224", test_data, - digest_size=28, - oid='2.16.840.1.101.3.4.2.4') - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA256.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA256.py index 23d1145c..66d11707 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA256.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA256.py @@ -27,68 +27,87 @@ import unittest from Cryptodome.Util.py3compat import * + class LargeSHA256Test(unittest.TestCase): - def runTest(self): - """SHA256: 512/520 MiB test""" - from Cryptodome.Hash import SHA256 - zeros = bchr(0x00) * (1024*1024) + def runTest(self): + """SHA256: 512/520 MiB test""" + from Cryptodome.Hash import SHA256 + + zeros = bchr(0x00) * (1024 * 1024) + + h = SHA256.new(zeros) + for i in range(511): + h.update(zeros) - h = SHA256.new(zeros) - for i in range(511): - h.update(zeros) + # This test vector is from PyCrypto's old testdata.py file. + self.assertEqual( + "9acca8e8c22201155389f65abbf6bc9723edc7384ead80503839f49dcc56d767", h.hexdigest() + ) # 512 MiB - # This test vector is from PyCrypto's old testdata.py file. - self.assertEqual('9acca8e8c22201155389f65abbf6bc9723edc7384ead80503839f49dcc56d767', h.hexdigest()) # 512 MiB + for i in range(8): + h.update(zeros) - for i in range(8): - h.update(zeros) + # This test vector is from PyCrypto's old testdata.py file. + self.assertEqual( + "abf51ad954b246009dfe5a50ecd582fd5b8f1b8b27f30393853c3ef721e7fa6e", h.hexdigest() + ) # 520 MiB - # This test vector is from PyCrypto's old testdata.py file. - self.assertEqual('abf51ad954b246009dfe5a50ecd582fd5b8f1b8b27f30393853c3ef721e7fa6e', h.hexdigest()) # 520 MiB def get_tests(config={}): - # Test vectors from FIPS PUB 180-2 - # This is a list of (expected_result, input[, description]) tuples. - test_data = [ - # FIPS PUB 180-2, B.1 - "One-Block Message" - ('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', - 'abc'), - - # FIPS PUB 180-2, B.2 - "Multi-Block Message" - ('248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), - - # FIPS PUB 180-2, B.3 - "Long Message" - ('cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0', - 'a' * 10**6, - '"a" * 10**6'), - - # Test for an old PyCryptodome bug. - ('f7fd017a3c721ce7ff03f3552c0813adcc48b7f33f07e5e2ba71e23ea393d103', - 'This message is precisely 55 bytes long, to test a bug.', - 'Length = 55 (mod 64)'), - - # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', ''), - - ('d32b568cd1b96d459e7291ebf4b25d007f275c9f13149beeb782fac0716613f8', - 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), - ] - - from Cryptodome.Hash import SHA256 - from .common import make_hash_tests - tests = make_hash_tests(SHA256, "SHA256", test_data, - digest_size=32, - oid="2.16.840.1.101.3.4.2.1") - - if config.get('slow_tests'): - tests += [LargeSHA256Test()] - - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + # Test vectors from FIPS PUB 180-2 + # This is a list of (expected_result, input[, description]) tuples. + test_data = [ + # FIPS PUB 180-2, B.1 - "One-Block Message" + ( + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + "abc", + ), + # FIPS PUB 180-2, B.2 - "Multi-Block Message" + ( + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + ), + # FIPS PUB 180-2, B.3 - "Long Message" + ( + "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0", + "a" * 10**6, + '"a" * 10**6', + ), + # Test for an old PyCryptodome bug. + ( + "f7fd017a3c721ce7ff03f3552c0813adcc48b7f33f07e5e2ba71e23ea393d103", + "This message is precisely 55 bytes long, to test a bug.", + "Length = 55 (mod 64)", + ), + # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""), + ( + "d32b568cd1b96d459e7291ebf4b25d007f275c9f13149beeb782fac0716613f8", + "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), + ] + + from Cryptodome.Hash import SHA256 + from .common import make_hash_tests + + tests = make_hash_tests( + SHA256, + "SHA256", + test_data, + digest_size=32, + oid="2.16.840.1.101.3.4.2.1", + ) + + if config.get("slow_tests"): + tests += [LargeSHA256Test()] + + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA384.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA384.py index 5233d133..3dbf2eee 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA384.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA384.py @@ -27,35 +27,49 @@ # Test vectors from various sources # This is a list of (expected_result, input[, description]) tuples. test_data = [ + # RFC 4634: Section Page 8.4, "Test 1" + ( + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7", + "abc", + ), + # RFC 4634: Section Page 8.4, "Test 2.2" + ( + "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039", + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + ), + # RFC 4634: Section Page 8.4, "Test 3" + ( + "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985", + "a" * 10**6, + "'a' * 10**6", + ), + # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ("38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", ""), + # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ( + "71e8383a4cea32d6fd6877495db2ee353542f46fa44bc23100bca48f3366b84e809f0708e81041f427c6d5219a286677", + "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), +] - # RFC 4634: Section Page 8.4, "Test 1" - ('cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7', 'abc'), - # RFC 4634: Section Page 8.4, "Test 2.2" - ('09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'), +def get_tests(config={}): + from Cryptodome.Hash import SHA384 + from .common import make_hash_tests - # RFC 4634: Section Page 8.4, "Test 3" - ('9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985', 'a' * 10**6, "'a' * 10**6"), + return make_hash_tests( + SHA384, + "SHA384", + test_data, + digest_size=48, + oid="2.16.840.1.101.3.4.2.2", + ) - # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b', ''), - # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('71e8383a4cea32d6fd6877495db2ee353542f46fa44bc23100bca48f3366b84e809f0708e81041f427c6d5219a286677', - 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), +if __name__ == "__main__": + import unittest -] - -def get_tests(config={}): - from Cryptodome.Hash import SHA384 - from .common import make_hash_tests - return make_hash_tests(SHA384, "SHA384", test_data, - digest_size=48, - oid='2.16.840.1.101.3.4.2.2') - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_224.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_224.py index 3141880c..d52c0ce7 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_224.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_224.py @@ -32,48 +32,58 @@ class APITest(unittest.TestCase): + def test_update_after_digest(self): + msg = b("rrrrttt") - def test_update_after_digest(self): - msg=b("rrrrttt") + # Normally, update() cannot be done after digest() + h = SHA3.new(data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = SHA3.new(data=msg).digest() - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) + # With the proper flag, it is allowed + h = SHA3.new(data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-224.txt", - "KAT SHA-3 224", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests += make_hash_tests(SHA3, "SHA3_224", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.7") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from .common import make_hash_tests + + tests = [] + + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHA3-224.txt", + "KAT SHA-3 224", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + if tv.len == 0: + tv.msg = b("") + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests += make_hash_tests( + SHA3, + "SHA3_224", + test_data, + digest_size=SHA3.digest_size, + oid="2.16.840.1.101.3.4.2.7", + ) + tests += list_test_cases(APITest) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_256.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_256.py index 9dee5514..30152df8 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_256.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_256.py @@ -32,49 +32,58 @@ class APITest(unittest.TestCase): + def test_update_after_digest(self): + msg = b("rrrrttt") - def test_update_after_digest(self): - msg=b("rrrrttt") + # Normally, update() cannot be done after digest() + h = SHA3.new(data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = SHA3.new(data=msg).digest() - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) + # With the proper flag, it is allowed + h = SHA3.new(data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-256.txt", - "KAT SHA-3 256", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - - tests += make_hash_tests(SHA3, "SHA3_256", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.8") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from .common import make_hash_tests + + tests = [] + + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHA3-256.txt", + "KAT SHA-3 256", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + if tv.len == 0: + tv.msg = b("") + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests += make_hash_tests( + SHA3, + "SHA3_256", + test_data, + digest_size=SHA3.digest_size, + oid="2.16.840.1.101.3.4.2.8", + ) + tests += list_test_cases(APITest) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_384.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_384.py index c5030b56..485576cc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_384.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_384.py @@ -32,48 +32,58 @@ class APITest(unittest.TestCase): + def test_update_after_digest(self): + msg = b("rrrrttt") - def test_update_after_digest(self): - msg=b("rrrrttt") + # Normally, update() cannot be done after digest() + h = SHA3.new(data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = SHA3.new(data=msg).digest() - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) + # With the proper flag, it is allowed + h = SHA3.new(data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-384.txt", - "KAT SHA-3 384", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests += make_hash_tests(SHA3, "SHA3_384", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.9") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from .common import make_hash_tests + + tests = [] + + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHA3-384.txt", + "KAT SHA-3 384", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + if tv.len == 0: + tv.msg = b("") + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests += make_hash_tests( + SHA3, + "SHA3_384", + test_data, + digest_size=SHA3.digest_size, + oid="2.16.840.1.101.3.4.2.9", + ) + tests += list_test_cases(APITest) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_512.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_512.py index b7a57f8f..35f54db6 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_512.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA3_512.py @@ -32,48 +32,58 @@ class APITest(unittest.TestCase): + def test_update_after_digest(self): + msg = b("rrrrttt") - def test_update_after_digest(self): - msg=b("rrrrttt") + # Normally, update() cannot be done after digest() + h = SHA3.new(data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = SHA3.new(data=msg).digest() - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) + # With the proper flag, it is allowed + h = SHA3.new(data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-512.txt", - "KAT SHA-3 512", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests += make_hash_tests(SHA3, "SHA3_512", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.10") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from .common import make_hash_tests + + tests = [] + + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHA3-512.txt", + "KAT SHA-3 512", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + if tv.len == 0: + tv.msg = b("") + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests += make_hash_tests( + SHA3, + "SHA3_512", + test_data, + digest_size=SHA3.digest_size, + oid="2.16.840.1.101.3.4.2.10", + ) + tests += list_test_cases(APITest) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA512.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA512.py index e6c74b36..861812a3 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA512.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHA512.py @@ -33,108 +33,144 @@ # Test vectors from various sources # This is a list of (expected_result, input[, description]) tuples. test_data_512_other = [ - - # RFC 4634: Section Page 8.4, "Test 1" - ('ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', 'abc'), - - # RFC 4634: Section Page 8.4, "Test 2.1" - ('8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'), - - # RFC 4634: Section Page 8.4, "Test 3" - ('e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b', 'a' * 10**6, "'a' * 10**6"), - - # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', ''), - - ('af9ed2de700433b803240a552b41b5a472a6ef3fe1431a722b2063c75e9f07451f67a28e37d09cde769424c96aea6f8971389db9e1993d6c565c3c71b855723c', 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), + # RFC 4634: Section Page 8.4, "Test 1" + ( + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + "abc", + ), + # RFC 4634: Section Page 8.4, "Test 2.1" + ( + "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909", + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + ), + # RFC 4634: Section Page 8.4, "Test 3" + ( + "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b", + "a" * 10**6, + "'a' * 10**6", + ), + # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ( + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + "", + ), + ( + "af9ed2de700433b803240a552b41b5a472a6ef3fe1431a722b2063c75e9f07451f67a28e37d09cde769424c96aea6f8971389db9e1993d6c565c3c71b855723c", + "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), ] def get_tests_SHA512(): - - test_vectors = load_test_vectors(("Hash", "SHA2"), - "SHA512ShortMsg.rsp", - "KAT SHA-512", - {"len": lambda x: int(x)}) or [] - - test_data = test_data_512_other[:] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA512, "SHA512", test_data, - digest_size=64, - oid="2.16.840.1.101.3.4.2.3") - return tests + test_vectors = ( + load_test_vectors( + ("Hash", "SHA2"), + "SHA512ShortMsg.rsp", + "KAT SHA-512", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = test_data_512_other[:] + for tv in test_vectors: + try: + if tv.startswith("["): + continue + except AttributeError: + pass + if tv.len == 0: + tv.msg = b"" + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests = make_hash_tests( + SHA512, + "SHA512", + test_data, + digest_size=64, + oid="2.16.840.1.101.3.4.2.3", + ) + return tests def get_tests_SHA512_224(): - - test_vectors = load_test_vectors(("Hash", "SHA2"), - "SHA512_224ShortMsg.rsp", - "KAT SHA-512/224", - {"len": lambda x: int(x)}) or [] - - test_data = [] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA512, "SHA512/224", test_data, - digest_size=28, - oid="2.16.840.1.101.3.4.2.5", - extra_params={ "truncate" : "224" }) - return tests + test_vectors = ( + load_test_vectors( + ("Hash", "SHA2"), + "SHA512_224ShortMsg.rsp", + "KAT SHA-512/224", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + try: + if tv.startswith("["): + continue + except AttributeError: + pass + if tv.len == 0: + tv.msg = b"" + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests = make_hash_tests( + SHA512, + "SHA512/224", + test_data, + digest_size=28, + oid="2.16.840.1.101.3.4.2.5", + extra_params={"truncate": "224"}, + ) + return tests def get_tests_SHA512_256(): - - test_vectors = load_test_vectors(("Hash", "SHA2"), - "SHA512_256ShortMsg.rsp", - "KAT SHA-512/256", - {"len": lambda x: int(x)}) or [] - - test_data = [] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA512, "SHA512/256", test_data, - digest_size=32, - oid="2.16.840.1.101.3.4.2.6", - extra_params={ "truncate" : "256" }) - return tests + test_vectors = ( + load_test_vectors( + ("Hash", "SHA2"), + "SHA512_256ShortMsg.rsp", + "KAT SHA-512/256", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + try: + if tv.startswith("["): + continue + except AttributeError: + pass + if tv.len == 0: + tv.msg = b"" + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests = make_hash_tests( + SHA512, + "SHA512/256", + test_data, + digest_size=32, + oid="2.16.840.1.101.3.4.2.6", + extra_params={"truncate": "256"}, + ) + return tests def get_tests(config={}): + tests = [] + tests += get_tests_SHA512() + tests += get_tests_SHA512_224() + tests += get_tests_SHA512_256() + return tests + - tests = [] - tests += get_tests_SHA512() - tests += get_tests_SHA512_224() - tests += get_tests_SHA512_256() - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHAKE.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHAKE.py index 07965f62..d2284528 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHAKE.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_SHAKE.py @@ -31,121 +31,130 @@ """Self-test suite for Cryptodome.Hash.SHAKE128 and SHAKE256""" import unittest -from binascii import hexlify, unhexlify from Cryptodome.SelfTest.loader import load_test_vectors from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Hash import SHAKE128, SHAKE256 -from Cryptodome.Util.py3compat import b, bchr, bord, tobytes +from Cryptodome.Util.py3compat import b, bchr, tobytes -class SHAKETest(unittest.TestCase): - - def test_new_positive(self): - - xof1 = self.shake.new() - xof2 = self.shake.new(data=b("90")) - xof3 = self.shake.new().update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = self.shake.new() - h.update(pieces[0]).update(pieces[1]) - digest = h.read(10) - h = self.shake.new() - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.read(10), digest) - - def test_update_negative(self): - h = self.shake.new() - self.assertRaises(TypeError, h.update, u"string") - def test_digest(self): - h = self.shake.new() - digest = h.read(90) - - # read returns a byte string of the right length - self.assertTrue(isinstance(digest, type(b("digest")))) - self.assertEqual(len(digest), 90) - - def test_update_after_read(self): - mac = self.shake.new() - mac.update(b("rrrr")) - mac.read(90) - self.assertRaises(TypeError, mac.update, b("ttt")) - - def test_copy(self): - mac = self.shake.new() - mac.update(b("rrrr")) - mac2 = mac.copy() - x1 = mac.read(90) - x2 = mac2.read(90) - self.assertEqual(x1, x2) +class SHAKETest(unittest.TestCase): + def test_new_positive(self): + xof1 = self.shake.new() + xof2 = self.shake.new(data=b("90")) + xof3 = self.shake.new().update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] + h = self.shake.new() + h.update(pieces[0]).update(pieces[1]) + digest = h.read(10) + h = self.shake.new() + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.read(10), digest) + + def test_update_negative(self): + h = self.shake.new() + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = self.shake.new() + digest = h.read(90) + + # read returns a byte string of the right length + self.assertTrue(isinstance(digest, type(b("digest")))) + self.assertEqual(len(digest), 90) + + def test_update_after_read(self): + mac = self.shake.new() + mac.update(b("rrrr")) + mac.read(90) + self.assertRaises(TypeError, mac.update, b("ttt")) + + def test_copy(self): + mac = self.shake.new() + mac.update(b("rrrr")) + mac2 = mac.copy() + x1 = mac.read(90) + x2 = mac2.read(90) + self.assertEqual(x1, x2) class SHAKE128Test(SHAKETest): - shake = SHAKE128 + shake = SHAKE128 class SHAKE256Test(SHAKETest): - shake = SHAKE256 + shake = SHAKE256 class SHAKEVectors(unittest.TestCase): - pass + pass -test_vectors_128 = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHAKE128.txt", - "Short Messages KAT SHAKE128", - { "len" : lambda x: int(x) } ) or [] +test_vectors_128 = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHAKE128.txt", + "Short Messages KAT SHAKE128", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_128): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = SHAKE128.new(data=data) - digest = hobj.read(len(result)) - self.assertEqual(digest, result) + def new_test(self, data=data, result=tv.md): + hobj = SHAKE128.new(data=data) + digest = hobj.read(len(result)) + self.assertEqual(digest, result) - setattr(SHAKEVectors, "test_128_%d" % idx, new_test) + setattr(SHAKEVectors, "test_128_%d" % idx, new_test) -test_vectors_256 = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHAKE256.txt", - "Short Messages KAT SHAKE256", - { "len" : lambda x: int(x) } ) or [] +test_vectors_256 = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHAKE256.txt", + "Short Messages KAT SHAKE256", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_256): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = SHAKE256.new(data=data) - digest = hobj.read(len(result)) - self.assertEqual(digest, result) + def new_test(self, data=data, result=tv.md): + hobj = SHAKE256.new(data=data) + digest = hobj.read(len(result)) + self.assertEqual(digest, result) - setattr(SHAKEVectors, "test_256_%d" % idx, new_test) + setattr(SHAKEVectors, "test_256_%d" % idx, new_test) def get_tests(config={}): - tests = [] - tests += list_test_cases(SHAKE128Test) - tests += list_test_cases(SHAKE256Test) - tests += list_test_cases(SHAKEVectors) - return tests + tests = [] + tests += list_test_cases(SHAKE128Test) + tests += list_test_cases(SHAKE256Test) + tests += list_test_cases(SHAKEVectors) + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_TupleHash.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_TupleHash.py index 2f93d7b3..bcd25524 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_TupleHash.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_TupleHash.py @@ -8,295 +8,293 @@ class TupleHashTest(unittest.TestCase): - - def new(self, *args, **kwargs): - return self.TupleHash.new(*args, **kwargs) - - def test_new_positive(self): - - h = self.new() - for new_func in self.TupleHash.new, h.new: - - for dbits in range(64, 1024 + 1, 8): - hobj = new_func(digest_bits=dbits) - self.assertEqual(hobj.digest_size * 8, dbits) - - for dbytes in range(8, 128 + 1): - hobj = new_func(digest_bytes=dbytes) - self.assertEqual(hobj.digest_size, dbytes) - - hobj = h.new() - self.assertEqual(hobj.digest_size, self.default_bytes) - - def test_new_negative(self): - - h = self.new() - for new_func in self.TupleHash.new, h.new: - self.assertRaises(TypeError, new_func, - digest_bytes=self.minimum_bytes, - digest_bits=self.minimum_bits) - self.assertRaises(ValueError, new_func, digest_bytes=0) - self.assertRaises(ValueError, new_func, - digest_bits=self.minimum_bits + 7) - self.assertRaises(ValueError, new_func, - digest_bits=self.minimum_bits - 8) - self.assertRaises(ValueError, new_func, - digest_bits=self.minimum_bytes - 1) - - def test_default_digest_size(self): - digest = self.new().digest() - self.assertEqual(len(digest), self.default_bytes) - - def test_update(self): - h = self.new() - h.update(b'') - h.digest() - - h = self.new() - h.update(b'') - h.update(b'STRING1') - h.update(b'STRING2') - mac1 = h.digest() - - h = self.new() - h.update(b'STRING1') - h.update(b'STRING2') - mac2 = h.digest() - self.assertNotEqual(mac1, mac2) - - h = self.new() - h.update(b'STRING1', b'STRING2') - self.assertEqual(mac2, h.digest()) - - h = self.new() - t = b'STRING1', b'STRING2' - h.update(*t) - self.assertEqual(mac2, h.digest()) - - def test_update_negative(self): - h = self.new() - self.assertRaises(TypeError, h.update, u"string") - self.assertRaises(TypeError, h.update, None) - self.assertRaises(TypeError, h.update, (b'STRING1', b'STRING2')) - - def test_digest(self): - h = self.new() - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg = b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = self.new() - h.update(msg) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, dig1) - - def test_hex_digest(self): - mac = self.new() - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_bytearray(self): - - data = b"\x00\x01\x02" - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = self.new() - h2 = self.new() - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = self.new() - h2 = self.new() - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) + def new(self, *args, **kwargs): + return self.TupleHash.new(*args, **kwargs) + + def test_new_positive(self): + h = self.new() + for new_func in self.TupleHash.new, h.new: + for dbits in range(64, 1024 + 1, 8): + hobj = new_func(digest_bits=dbits) + self.assertEqual(hobj.digest_size * 8, dbits) + + for dbytes in range(8, 128 + 1): + hobj = new_func(digest_bytes=dbytes) + self.assertEqual(hobj.digest_size, dbytes) + + hobj = h.new() + self.assertEqual(hobj.digest_size, self.default_bytes) + + def test_new_negative(self): + h = self.new() + for new_func in self.TupleHash.new, h.new: + self.assertRaises( + TypeError, + new_func, + digest_bytes=self.minimum_bytes, + digest_bits=self.minimum_bits, + ) + self.assertRaises(ValueError, new_func, digest_bytes=0) + self.assertRaises( + ValueError, + new_func, + digest_bits=self.minimum_bits + 7, + ) + self.assertRaises( + ValueError, + new_func, + digest_bits=self.minimum_bits - 8, + ) + self.assertRaises( + ValueError, + new_func, + digest_bits=self.minimum_bytes - 1, + ) + + def test_default_digest_size(self): + digest = self.new().digest() + self.assertEqual(len(digest), self.default_bytes) + + def test_update(self): + h = self.new() + h.update(b"") + h.digest() + + h = self.new() + h.update(b"") + h.update(b"STRING1") + h.update(b"STRING2") + mac1 = h.digest() + + h = self.new() + h.update(b"STRING1") + h.update(b"STRING2") + mac2 = h.digest() + self.assertNotEqual(mac1, mac2) + + h = self.new() + h.update(b"STRING1", b"STRING2") + self.assertEqual(mac2, h.digest()) + + h = self.new() + t = b"STRING1", b"STRING2" + h.update(*t) + self.assertEqual(mac2, h.digest()) + + def test_update_negative(self): + h = self.new() + self.assertRaises(TypeError, h.update, "string") + self.assertRaises(TypeError, h.update, None) + self.assertRaises(TypeError, h.update, (b"STRING1", b"STRING2")) + + def test_digest(self): + h = self.new() + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b"digest"))) + + def test_update_after_digest(self): + msg = b"rrrrttt" + + # Normally, update() cannot be done after digest() + h = self.new() + h.update(msg) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, dig1) + + def test_hex_digest(self): + mac = self.new() + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_bytearray(self): + data = b"\x00\x01\x02" + + # Data can be a bytearray (during operation) + data_ba = bytearray(data) + + h1 = self.new() + h2 = self.new() + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + def test_memoryview(self): + data = b"\x00\x01\x02" + + def get_mv_ro(data): + return memoryview(data) + + def get_mv_rw(data): + return memoryview(bytearray(data)) + + for get_mv in (get_mv_ro, get_mv_rw): + # Data can be a memoryview (during operation) + data_mv = get_mv(data) + + h1 = self.new() + h2 = self.new() + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) class TupleHash128Test(TupleHashTest): + TupleHash = TupleHash128 - TupleHash = TupleHash128 - - minimum_bytes = 8 - default_bytes = 64 + minimum_bytes = 8 + default_bytes = 64 - minimum_bits = 64 - default_bits = 512 + minimum_bits = 64 + default_bits = 512 class TupleHash256Test(TupleHashTest): + TupleHash = TupleHash256 - TupleHash = TupleHash256 + minimum_bytes = 8 + default_bytes = 64 - minimum_bytes = 8 - default_bytes = 64 - - minimum_bits = 64 - default_bits = 512 + minimum_bits = 64 + default_bits = 512 class NISTExampleTestVectors(unittest.TestCase): + # http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TupleHash_samples.pdf + test_data = [ + ( + ( + "00 01 02", + "10 11 12 13 14 15", + ), + "", + "C5 D8 78 6C 1A FB 9B 82 11 1A B3 4B 65 B2 C0 048F A6 4E 6D 48 E2 63 26 4C E1 70 7D 3F FC 8E D1", + "KMAC128 Sample #1 NIST", + TupleHash128, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + ), + "My Tuple App", + "75 CD B2 0F F4 DB 11 54 E8 41 D7 58 E2 41 60 C54B AE 86 EB 8C 13 E7 F5 F4 0E B3 55 88 E9 6D FB", + "KMAC128 Sample #2 NIST", + TupleHash128, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + "20 21 22 23 24 25 26 27 28", + ), + "My Tuple App", + "E6 0F 20 2C 89 A2 63 1E DA 8D 4C 58 8C A5 FD 07F3 9E 51 51 99 8D EC CF 97 3A DB 38 04 BB 6E 84", + "KMAC128 Sample #3 NIST", + TupleHash128, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + ), + "", + "CF B7 05 8C AC A5 E6 68 F8 1A 12 A2 0A 21 95 CE" + "97 A9 25 F1 DB A3 E7 44 9A 56 F8 22 01 EC 60 73" + "11 AC 26 96 B1 AB 5E A2 35 2D F1 42 3B DE 7B D4" + "BB 78 C9 AE D1 A8 53 C7 86 72 F9 EB 23 BB E1 94", + "KMAC256 Sample #4 NIST", + TupleHash256, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + ), + "My Tuple App", + "14 7C 21 91 D5 ED 7E FD 98 DB D9 6D 7A B5 A1 16" + "92 57 6F 5F E2 A5 06 5F 3E 33 DE 6B BA 9F 3A A1" + "C4 E9 A0 68 A2 89 C6 1C 95 AA B3 0A EE 1E 41 0B" + "0B 60 7D E3 62 0E 24 A4 E3 BF 98 52 A1 D4 36 7E", + "KMAC256 Sample #5 NIST", + TupleHash256, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + "20 21 22 23 24 25 26 27 28", + ), + "My Tuple App", + "45 00 0B E6 3F 9B 6B FD 89 F5 47 17 67 0F 69 A9" + "BC 76 35 91 A4 F0 5C 50 D6 88 91 A7 44 BC C6 E7" + "D6 D5 B5 E8 2C 01 8D A9 99 ED 35 B0 BB 49 C9 67" + "8E 52 6A BD 8E 85 C1 3E D2 54 02 1D B9 E7 90 CE", + "KMAC256 Sample #6 NIST", + TupleHash256, + ), + ] + + def setUp(self): + td = [] + for tv_in in self.test_data: + tv_out = [None] * len(tv_in) + + tv_out[0] = [] + for string in tv_in[0]: + tv_out[0].append(unhexlify(string.replace(" ", ""))) + + tv_out[1] = tobytes(tv_in[1]) # Custom + tv_out[2] = unhexlify(tv_in[2].replace(" ", "")) + tv_out[3] = tv_in[3] + tv_out[4] = tv_in[4] + td.append(tv_out) + self.test_data = td + + def runTest(self): + for data, custom, digest, text, module in self.test_data: + hd1 = module.new(custom=custom, digest_bytes=len(digest)) + hd2 = module.new(custom=custom, digest_bytes=len(digest)) + + # Call update() for each element + for string in data: + hd1.update(string) + + # One single update for all elements + hd2.update(*data) + + self.assertEqual(hd1.digest(), digest, msg=text) + self.assertEqual(hd2.digest(), digest, msg=text) - # http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TupleHash_samples.pdf - test_data = [ - ( - ( - "00 01 02", - "10 11 12 13 14 15", - ), - "", - "C5 D8 78 6C 1A FB 9B 82 11 1A B3 4B 65 B2 C0 04" - "8F A6 4E 6D 48 E2 63 26 4C E1 70 7D 3F FC 8E D1", - "KMAC128 Sample #1 NIST", - TupleHash128 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - ), - "My Tuple App", - "75 CD B2 0F F4 DB 11 54 E8 41 D7 58 E2 41 60 C5" - "4B AE 86 EB 8C 13 E7 F5 F4 0E B3 55 88 E9 6D FB", - "KMAC128 Sample #2 NIST", - TupleHash128 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - "20 21 22 23 24 25 26 27 28", - ), - "My Tuple App", - "E6 0F 20 2C 89 A2 63 1E DA 8D 4C 58 8C A5 FD 07" - "F3 9E 51 51 99 8D EC CF 97 3A DB 38 04 BB 6E 84", - "KMAC128 Sample #3 NIST", - TupleHash128 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - ), - "", - "CF B7 05 8C AC A5 E6 68 F8 1A 12 A2 0A 21 95 CE" - "97 A9 25 F1 DB A3 E7 44 9A 56 F8 22 01 EC 60 73" - "11 AC 26 96 B1 AB 5E A2 35 2D F1 42 3B DE 7B D4" - "BB 78 C9 AE D1 A8 53 C7 86 72 F9 EB 23 BB E1 94", - "KMAC256 Sample #4 NIST", - TupleHash256 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - ), - "My Tuple App", - "14 7C 21 91 D5 ED 7E FD 98 DB D9 6D 7A B5 A1 16" - "92 57 6F 5F E2 A5 06 5F 3E 33 DE 6B BA 9F 3A A1" - "C4 E9 A0 68 A2 89 C6 1C 95 AA B3 0A EE 1E 41 0B" - "0B 60 7D E3 62 0E 24 A4 E3 BF 98 52 A1 D4 36 7E", - "KMAC256 Sample #5 NIST", - TupleHash256 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - "20 21 22 23 24 25 26 27 28", - ), - "My Tuple App", - "45 00 0B E6 3F 9B 6B FD 89 F5 47 17 67 0F 69 A9" - "BC 76 35 91 A4 F0 5C 50 D6 88 91 A7 44 BC C6 E7" - "D6 D5 B5 E8 2C 01 8D A9 99 ED 35 B0 BB 49 C9 67" - "8E 52 6A BD 8E 85 C1 3E D2 54 02 1D B9 E7 90 CE", - "KMAC256 Sample #6 NIST", - TupleHash256 - ), - - - - ] - - def setUp(self): - td = [] - for tv_in in self.test_data: - tv_out = [None] * len(tv_in) - - tv_out[0] = [] - for string in tv_in[0]: - tv_out[0].append(unhexlify(string.replace(" ", ""))) - - tv_out[1] = tobytes(tv_in[1]) # Custom - tv_out[2] = unhexlify(tv_in[2].replace(" ", "")) - tv_out[3] = tv_in[3] - tv_out[4] = tv_in[4] - td.append(tv_out) - self.test_data = td - - def runTest(self): - - for data, custom, digest, text, module in self.test_data: - hd1 = module.new(custom=custom, digest_bytes=len(digest)) - hd2 = module.new(custom=custom, digest_bytes=len(digest)) - - # Call update() for each element - for string in data: - hd1.update(string) - - # One single update for all elements - hd2.update(*data) - - self.assertEqual(hd1.digest(), digest, msg=text) - self.assertEqual(hd2.digest(), digest, msg=text) def get_tests(config={}): - tests = [] + tests = [] + + tests += list_test_cases(TupleHash128Test) + tests += list_test_cases(TupleHash256Test) + tests.append(NISTExampleTestVectors()) + + return tests - tests += list_test_cases(TupleHash128Test) - tests += list_test_cases(TupleHash256Test) - tests.append(NISTExampleTestVectors()) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_TurboSHAKE.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_TurboSHAKE.py index 7c13d1e6..3b253211 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_TurboSHAKE.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_TurboSHAKE.py @@ -10,459 +10,457 @@ class TurboSHAKETest(unittest.TestCase): + def test_new_positive(self): + xof1 = self.TurboSHAKE.new() + xof1.update(b"90") - def test_new_positive(self): + xof2 = self.TurboSHAKE.new(domain=0x1F) + xof2.update(b"90") - xof1 = self.TurboSHAKE.new() - xof1.update(b'90') + xof3 = self.TurboSHAKE.new(data=b"90") - xof2 = self.TurboSHAKE.new(domain=0x1F) - xof2.update(b'90') + out1 = xof1.read(128) + out2 = xof2.read(128) + out3 = xof3.read(128) - xof3 = self.TurboSHAKE.new(data=b'90') + self.assertEqual(out1, out2) + self.assertEqual(out1, out3) - out1 = xof1.read(128) - out2 = xof2.read(128) - out3 = xof3.read(128) + def test_new_domain(self): + xof1 = self.TurboSHAKE.new(domain=0x1D) + xof2 = self.TurboSHAKE.new(domain=0x20) + self.assertNotEqual(xof1.read(128), xof2.read(128)) - self.assertEqual(out1, out2) - self.assertEqual(out1, out3) + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] - def test_new_domain(self): - xof1 = self.TurboSHAKE.new(domain=0x1D) - xof2 = self.TurboSHAKE.new(domain=0x20) - self.assertNotEqual(xof1.read(128), xof2.read(128)) + xof1 = self.TurboSHAKE.new() + xof1.update(pieces[0]).update(pieces[1]) + digest1 = xof1.read(10) - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] + xof2 = self.TurboSHAKE.new() + xof2.update(pieces[0] + pieces[1]) + digest2 = xof2.read(10) - xof1 = self.TurboSHAKE.new() - xof1.update(pieces[0]).update(pieces[1]) - digest1 = xof1.read(10) + self.assertEqual(digest1, digest2) - xof2 = self.TurboSHAKE.new() - xof2.update(pieces[0] + pieces[1]) - digest2 = xof2.read(10) + def test_update_negative(self): + xof1 = self.TurboSHAKE.new() + self.assertRaises(TypeError, xof1.update, "string") - self.assertEqual(digest1, digest2) + def test_read(self): + xof1 = self.TurboSHAKE.new() + digest = xof1.read(90) - def test_update_negative(self): - xof1 = self.TurboSHAKE.new() - self.assertRaises(TypeError, xof1.update, u"string") + # read returns a byte string of the right length + self.assertTrue(isinstance(digest, bytes)) + self.assertEqual(len(digest), 90) - def test_read(self): - xof1 = self.TurboSHAKE.new() - digest = xof1.read(90) + def test_update_after_read(self): + xof1 = self.TurboSHAKE.new() + xof1.update(b"rrrr") + xof1.read(90) + self.assertRaises(TypeError, xof1.update, b"ttt") - # read returns a byte string of the right length - self.assertTrue(isinstance(digest, bytes)) - self.assertEqual(len(digest), 90) + def test_new(self): + xof1 = self.TurboSHAKE.new(domain=0x07) + xof1.update(b"90") + digest1 = xof1.read(100) - def test_update_after_read(self): - xof1 = self.TurboSHAKE.new() - xof1.update(b"rrrr") - xof1.read(90) - self.assertRaises(TypeError, xof1.update, b"ttt") + xof2 = xof1.new() + xof2.update(b"90") + digest2 = xof2.read(100) - def test_new(self): - xof1 = self.TurboSHAKE.new(domain=0x07) - xof1.update(b'90') - digest1 = xof1.read(100) + self.assertEqual(digest1, digest2) - xof2 = xof1.new() - xof2.update(b'90') - digest2 = xof2.read(100) - - self.assertEqual(digest1, digest2) - - self.assertRaises(TypeError, xof1.new, domain=0x07) + self.assertRaises(TypeError, xof1.new, domain=0x07) class TurboSHAKE128Test(TurboSHAKETest): - TurboSHAKE = TurboSHAKE128 + TurboSHAKE = TurboSHAKE128 class TurboSHAKE256Test(TurboSHAKETest): - TurboSHAKE = TurboSHAKE256 + TurboSHAKE = TurboSHAKE256 def txt2bin(txt): - clean = txt.replace(" ", "").replace("\n", "").replace("\r", "") - return unhexlify(clean) + clean = txt.replace(" ", "").replace("\n", "").replace("\r", "") + return unhexlify(clean) def ptn(n): - res = bytearray(n) - pattern = b"".join([bchr(x) for x in range(0, 0xFB)]) - for base in range(0, n - 0xFB, 0xFB): - res[base:base + 0xFB] = pattern - remain = n % 0xFB - if remain: - base = (n // 0xFB) * 0xFB - res[base:] = pattern[:remain] - assert len(res) == n - return res + res = bytearray(n) + pattern = b"".join([bchr(x) for x in range(0, 0xFB)]) + for base in range(0, n - 0xFB, 0xFB): + res[base : base + 0xFB] = pattern + remain = n % 0xFB + if remain: + base = (n // 0xFB) * 0xFB + res[base:] = pattern[:remain] + assert len(res) == n + return res def chunked(source, size): - for i in range(0, len(source), size): - yield source[i:i+size] + for i in range(0, len(source), size): + yield source[i : i + size] class TurboSHAKE128TV(unittest.TestCase): - - def test_zero_1(self): - tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53 + def test_zero_1(self): + tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53 8C D9 45 A3 97 DD EC 54 1F 1C E4 1A F2 C1 B7 4C""" - btv = txt2bin(tv) - res = TurboSHAKE128.new().read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new().read(32) + self.assertEqual(res, btv) - def test_zero_2(self): - tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53 + def test_zero_2(self): + tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53 8C D9 45 A3 97 DD EC 54 1F 1C E4 1A F2 C1 B7 4C 3E 8C CA E2 A4 DA E5 6C 84 A0 4C 23 85 C0 3C 15 E8 19 3B DF 58 73 73 63 32 16 91 C0 54 62 C8 DF""" - btv = txt2bin(tv) - res = TurboSHAKE128.new().read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new().read(64) + self.assertEqual(res, btv) - def test_zero_3(self): - tv = """A3 B9 B0 38 59 00 CE 76 1F 22 AE D5 48 E7 54 DA + def test_zero_3(self): + tv = """A3 B9 B0 38 59 00 CE 76 1F 22 AE D5 48 E7 54 DA 10 A5 24 2D 62 E8 C6 58 E3 F3 A9 23 A7 55 56 07""" - btv = txt2bin(tv) - res = TurboSHAKE128.new().read(10032)[-32:] - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new().read(10032)[-32:] + self.assertEqual(res, btv) - def test_ptn_1(self): - tv = """55 CE DD 6F 60 AF 7B B2 9A 40 42 AE 83 2E F3 F5 + def test_ptn_1(self): + tv = """55 CE DD 6F 60 AF 7B B2 9A 40 42 AE 83 2E F3 F5 8D B7 29 9F 89 3E BB 92 47 24 7D 85 69 58 DA A9""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=ptn(1)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=ptn(1)).read(32) + self.assertEqual(res, btv) - def test_ptn_17(self): - tv = """9C 97 D0 36 A3 BA C8 19 DB 70 ED E0 CA 55 4E C6 + def test_ptn_17(self): + tv = """9C 97 D0 36 A3 BA C8 19 DB 70 ED E0 CA 55 4E C6 E4 C2 A1 A4 FF BF D9 EC 26 9C A6 A1 11 16 12 33""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=ptn(17)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=ptn(17)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_2(self): - tv = """96 C7 7C 27 9E 01 26 F7 FC 07 C9 B0 7F 5C DA E1 + def test_ptn_17_2(self): + tv = """96 C7 7C 27 9E 01 26 F7 FC 07 C9 B0 7F 5C DA E1 E0 BE 60 BD BE 10 62 00 40 E7 5D 72 23 A6 24 D2""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=ptn(17**2)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=ptn(17**2)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_3(self): - tv = """D4 97 6E B5 6B CF 11 85 20 58 2B 70 9F 73 E1 D6 + def test_ptn_17_3(self): + tv = """D4 97 6E B5 6B CF 11 85 20 58 2B 70 9F 73 E1 D6 85 3E 00 1F DA F8 0E 1B 13 E0 D0 59 9D 5F B3 72""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=ptn(17**3)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=ptn(17**3)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_4(self): - tv = """DA 67 C7 03 9E 98 BF 53 0C F7 A3 78 30 C6 66 4E + def test_ptn_17_4(self): + tv = """DA 67 C7 03 9E 98 BF 53 0C F7 A3 78 30 C6 66 4E 14 CB AB 7F 54 0F 58 40 3B 1B 82 95 13 18 EE 5C""" - btv = txt2bin(tv) - data = ptn(17**4) - - # All at once - res = TurboSHAKE128.new(data=data).read(32) - self.assertEqual(res, btv) - - # Byte by byte - xof = TurboSHAKE128.new() - for x in data: - xof.update(bchr(x)) - res = xof.read(32) - self.assertEqual(res, btv) - - # Chunks of various prime sizes - for chunk_size in (13, 17, 19, 23, 31): - xof = TurboSHAKE128.new() - for x in chunked(data, chunk_size): - xof.update(x) - res = xof.read(32) - self.assertEqual(res, btv) - - def test_ptn_17_5(self): - tv = """B9 7A 90 6F BF 83 EF 7C 81 25 17 AB F3 B2 D0 AE + btv = txt2bin(tv) + data = ptn(17**4) + + # All at once + res = TurboSHAKE128.new(data=data).read(32) + self.assertEqual(res, btv) + + # Byte by byte + xof = TurboSHAKE128.new() + for x in data: + xof.update(bchr(x)) + res = xof.read(32) + self.assertEqual(res, btv) + + # Chunks of various prime sizes + for chunk_size in (13, 17, 19, 23, 31): + xof = TurboSHAKE128.new() + for x in chunked(data, chunk_size): + xof.update(x) + res = xof.read(32) + self.assertEqual(res, btv) + + def test_ptn_17_5(self): + tv = """B9 7A 90 6F BF 83 EF 7C 81 25 17 AB F3 B2 D0 AE A0 C4 F6 03 18 CE 11 CF 10 39 25 12 7F 59 EE CD""" - btv = txt2bin(tv) - data = ptn(17**5) + btv = txt2bin(tv) + data = ptn(17**5) - # All at once - res = TurboSHAKE128.new(data=data).read(32) - self.assertEqual(res, btv) + # All at once + res = TurboSHAKE128.new(data=data).read(32) + self.assertEqual(res, btv) - # Chunks - xof = TurboSHAKE128.new() - for chunk in chunked(data, 8192): - xof.update(chunk) - res = xof.read(32) - self.assertEqual(res, btv) + # Chunks + xof = TurboSHAKE128.new() + for chunk in chunked(data, 8192): + xof.update(chunk) + res = xof.read(32) + self.assertEqual(res, btv) - def test_ptn_17_6(self): - tv = """35 CD 49 4A DE DE D2 F2 52 39 AF 09 A7 B8 EF 0C + def test_ptn_17_6(self): + tv = """35 CD 49 4A DE DE D2 F2 52 39 AF 09 A7 B8 EF 0C 4D 1C A4 FE 2D 1A C3 70 FA 63 21 6F E7 B4 C2 B1""" - btv = txt2bin(tv) - data = ptn(17**6) + btv = txt2bin(tv) + data = ptn(17**6) - res = TurboSHAKE128.new(data=data).read(32) - self.assertEqual(res, btv) + res = TurboSHAKE128.new(data=data).read(32) + self.assertEqual(res, btv) - def test_ffffff_d01(self): - tv = """BF 32 3F 94 04 94 E8 8E E1 C5 40 FE 66 0B E8 A0 + def test_ffffff_d01(self): + tv = """BF 32 3F 94 04 94 E8 8E E1 C5 40 FE 66 0B E8 A0 C9 3F 43 D1 5E C0 06 99 84 62 FA 99 4E ED 5D AB""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b"\xff\xff\xff", domain=0x01).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff\xff\xff", domain=0x01).read(32) + self.assertEqual(res, btv) - def test_ff_d06(self): - tv = """8E C9 C6 64 65 ED 0D 4A 6C 35 D1 35 06 71 8D 68 + def test_ff_d06(self): + tv = """8E C9 C6 64 65 ED 0D 4A 6C 35 D1 35 06 71 8D 68 7A 25 CB 05 C7 4C CA 1E 42 50 1A BD 83 87 4A 67""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF', domain=0x06).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff", domain=0x06).read(32) + self.assertEqual(res, btv) - def test_ffffff_d07(self): - tv = """B6 58 57 60 01 CA D9 B1 E5 F3 99 A9 F7 77 23 BB + def test_ffffff_d07(self): + tv = """B6 58 57 60 01 CA D9 B1 E5 F3 99 A9 F7 77 23 BB A0 54 58 04 2D 68 20 6F 72 52 68 2D BA 36 63 ED""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF' * 3, domain=0x07).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff" * 3, domain=0x07).read(32) + self.assertEqual(res, btv) - def test_ffffffffffff_d0b(self): - tv = """8D EE AA 1A EC 47 CC EE 56 9F 65 9C 21 DF A8 E1 + def test_ffffffffffff_d0b(self): + tv = """8D EE AA 1A EC 47 CC EE 56 9F 65 9C 21 DF A8 E1 12 DB 3C EE 37 B1 81 78 B2 AC D8 05 B7 99 CC 37""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF' * 7, domain=0x0B).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff" * 7, domain=0x0B).read(32) + self.assertEqual(res, btv) - def test_ff_d30(self): - tv = """55 31 22 E2 13 5E 36 3C 32 92 BE D2 C6 42 1F A2 + def test_ff_d30(self): + tv = """55 31 22 E2 13 5E 36 3C 32 92 BE D2 C6 42 1F A2 32 BA B0 3D AA 07 C7 D6 63 66 03 28 65 06 32 5B""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF', domain=0x30).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff", domain=0x30).read(32) + self.assertEqual(res, btv) - def test_ffffff_d7f(self): - tv = """16 27 4C C6 56 D4 4C EF D4 22 39 5D 0F 90 53 BD + def test_ffffff_d7f(self): + tv = """16 27 4C C6 56 D4 4C EF D4 22 39 5D 0F 90 53 BD A6 D2 8E 12 2A BA 15 C7 65 E5 AD 0E 6E AF 26 F9""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF' * 3, domain=0x7F).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff" * 3, domain=0x7F).read(32) + self.assertEqual(res, btv) class TurboSHAKE256TV(unittest.TestCase): - - def test_zero_1(self): - tv = """36 7A 32 9D AF EA 87 1C 78 02 EC 67 F9 05 AE 13 + def test_zero_1(self): + tv = """36 7A 32 9D AF EA 87 1C 78 02 EC 67 F9 05 AE 13 C5 76 95 DC 2C 66 63 C6 10 35 F5 9A 18 F8 E7 DB 11 ED C0 E1 2E 91 EA 60 EB 6B 32 DF 06 DD 7F 00 2F BA FA BB 6E 13 EC 1C C2 0D 99 55 47 60 0D B0""" - btv = txt2bin(tv) - res = TurboSHAKE256.new().read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new().read(64) + self.assertEqual(res, btv) - def test_zero_2(self): - tv = """AB EF A1 16 30 C6 61 26 92 49 74 26 85 EC 08 2F + def test_zero_2(self): + tv = """AB EF A1 16 30 C6 61 26 92 49 74 26 85 EC 08 2F 20 72 65 DC CF 2F 43 53 4E 9C 61 BA 0C 9D 1D 75""" - btv = txt2bin(tv) - res = TurboSHAKE256.new().read(10032)[-32:] - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new().read(10032)[-32:] + self.assertEqual(res, btv) - def test_ptn_1(self): - tv = """3E 17 12 F9 28 F8 EA F1 05 46 32 B2 AA 0A 24 6E + def test_ptn_1(self): + tv = """3E 17 12 F9 28 F8 EA F1 05 46 32 B2 AA 0A 24 6E D8 B0 C3 78 72 8F 60 BC 97 04 10 15 5C 28 82 0E 90 CC 90 D8 A3 00 6A A2 37 2C 5C 5E A1 76 B0 68 2B F2 2B AE 74 67 AC 94 F7 4D 43 D3 9B 04 82 E2""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=ptn(1)).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=ptn(1)).read(64) + self.assertEqual(res, btv) - def test_ptn_17(self): - tv = """B3 BA B0 30 0E 6A 19 1F BE 61 37 93 98 35 92 35 + def test_ptn_17(self): + tv = """B3 BA B0 30 0E 6A 19 1F BE 61 37 93 98 35 92 35 78 79 4E A5 48 43 F5 01 10 90 FA 2F 37 80 A9 E5 CB 22 C5 9D 78 B4 0A 0F BF F9 E6 72 C0 FB E0 97 0B D2 C8 45 09 1C 60 44 D6 87 05 4D A5 D8 E9 C7""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=ptn(17)).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=ptn(17)).read(64) + self.assertEqual(res, btv) - def test_ptn_17_2(self): - tv = """66 B8 10 DB 8E 90 78 04 24 C0 84 73 72 FD C9 57 + def test_ptn_17_2(self): + tv = """66 B8 10 DB 8E 90 78 04 24 C0 84 73 72 FD C9 57 10 88 2F DE 31 C6 DF 75 BE B9 D4 CD 93 05 CF CA E3 5E 7B 83 E8 B7 E6 EB 4B 78 60 58 80 11 63 16 FE 2C 07 8A 09 B9 4A D7 B8 21 3C 0A 73 8B 65 C0""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=ptn(17**2)).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=ptn(17**2)).read(64) + self.assertEqual(res, btv) - def test_ptn_17_3(self): - tv = """C7 4E BC 91 9A 5B 3B 0D D1 22 81 85 BA 02 D2 9E + def test_ptn_17_3(self): + tv = """C7 4E BC 91 9A 5B 3B 0D D1 22 81 85 BA 02 D2 9E F4 42 D6 9D 3D 42 76 A9 3E FE 0B F9 A1 6A 7D C0 CD 4E AB AD AB 8C D7 A5 ED D9 66 95 F5 D3 60 AB E0 9E 2C 65 11 A3 EC 39 7D A3 B7 6B 9E 16 74 FB""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=ptn(17**3)).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=ptn(17**3)).read(64) + self.assertEqual(res, btv) - def test_ptn_17_4(self): - tv = """02 CC 3A 88 97 E6 F4 F6 CC B6 FD 46 63 1B 1F 52 + def test_ptn_17_4(self): + tv = """02 CC 3A 88 97 E6 F4 F6 CC B6 FD 46 63 1B 1F 52 07 B6 6C 6D E9 C7 B5 5B 2D 1A 23 13 4A 17 0A FD AC 23 4E AB A9 A7 7C FF 88 C1 F0 20 B7 37 24 61 8C 56 87 B3 62 C4 30 B2 48 CD 38 64 7F 84 8A 1D""" - btv = txt2bin(tv) - data = ptn(17**4) - - # All at once - res = TurboSHAKE256.new(data=data).read(64) - self.assertEqual(res, btv) - - # Byte by byte - xof = TurboSHAKE256.new() - for x in data: - xof.update(bchr(x)) - res = xof.read(64) - self.assertEqual(res, btv) - - # Chunks of various prime sizes - for chunk_size in (13, 17, 19, 23, 31): - xof = TurboSHAKE256.new() - for x in chunked(data, chunk_size): - xof.update(x) - res = xof.read(64) - self.assertEqual(res, btv) - - def test_ptn_17_5(self): - tv = """AD D5 3B 06 54 3E 58 4B 58 23 F6 26 99 6A EE 50 + btv = txt2bin(tv) + data = ptn(17**4) + + # All at once + res = TurboSHAKE256.new(data=data).read(64) + self.assertEqual(res, btv) + + # Byte by byte + xof = TurboSHAKE256.new() + for x in data: + xof.update(bchr(x)) + res = xof.read(64) + self.assertEqual(res, btv) + + # Chunks of various prime sizes + for chunk_size in (13, 17, 19, 23, 31): + xof = TurboSHAKE256.new() + for x in chunked(data, chunk_size): + xof.update(x) + res = xof.read(64) + self.assertEqual(res, btv) + + def test_ptn_17_5(self): + tv = """AD D5 3B 06 54 3E 58 4B 58 23 F6 26 99 6A EE 50 FE 45 ED 15 F2 02 43 A7 16 54 85 AC B4 AA 76 B4 FF DA 75 CE DF 6D 8C DC 95 C3 32 BD 56 F4 B9 86 B5 8B B1 7D 17 78 BF C1 B1 A9 75 45 CD F4 EC 9F""" - btv = txt2bin(tv) - data = ptn(17**5) + btv = txt2bin(tv) + data = ptn(17**5) - # All at once - res = TurboSHAKE256.new(data=data).read(64) - self.assertEqual(res, btv) + # All at once + res = TurboSHAKE256.new(data=data).read(64) + self.assertEqual(res, btv) - # Chunks - xof = TurboSHAKE256.new() - for chunk in chunked(data, 8192): - xof.update(chunk) - res = xof.read(64) - self.assertEqual(res, btv) + # Chunks + xof = TurboSHAKE256.new() + for chunk in chunked(data, 8192): + xof.update(chunk) + res = xof.read(64) + self.assertEqual(res, btv) - def test_ptn_17_6(self): - tv = """9E 11 BC 59 C2 4E 73 99 3C 14 84 EC 66 35 8E F7 + def test_ptn_17_6(self): + tv = """9E 11 BC 59 C2 4E 73 99 3C 14 84 EC 66 35 8E F7 1D B7 4A EF D8 4E 12 3F 78 00 BA 9C 48 53 E0 2C FE 70 1D 9E 6B B7 65 A3 04 F0 DC 34 A4 EE 3B A8 2C 41 0F 0D A7 0E 86 BF BD 90 EA 87 7C 2D 61 04""" - btv = txt2bin(tv) - data = ptn(17**6) + btv = txt2bin(tv) + data = ptn(17**6) - res = TurboSHAKE256.new(data=data).read(64) - self.assertEqual(res, btv) + res = TurboSHAKE256.new(data=data).read(64) + self.assertEqual(res, btv) - def test_ffffff_d01(self): - tv = """D2 1C 6F BB F5 87 FA 22 82 F2 9A EA 62 01 75 FB + def test_ffffff_d01(self): + tv = """D2 1C 6F BB F5 87 FA 22 82 F2 9A EA 62 01 75 FB 02 57 41 3A F7 8A 0B 1B 2A 87 41 9C E0 31 D9 33 AE 7A 4D 38 33 27 A8 A1 76 41 A3 4F 8A 1D 10 03 AD 7D A6 B7 2D BA 84 BB 62 FE F2 8F 62 F1 24 24""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b"\xff\xff\xff", domain=0x01).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff\xff\xff", domain=0x01).read(64) + self.assertEqual(res, btv) - def test_ff_d06(self): - tv = """73 8D 7B 4E 37 D1 8B 7F 22 AD 1B 53 13 E3 57 E3 + def test_ff_d06(self): + tv = """73 8D 7B 4E 37 D1 8B 7F 22 AD 1B 53 13 E3 57 E3 DD 7D 07 05 6A 26 A3 03 C4 33 FA 35 33 45 52 80 F4 F5 A7 D4 F7 00 EF B4 37 FE 6D 28 14 05 E0 7B E3 2A 0A 97 2E 22 E6 3A DC 1B 09 0D AE FE 00 4B""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF', domain=0x06).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff", domain=0x06).read(64) + self.assertEqual(res, btv) - def test_ffffff_d07(self): - tv = """18 B3 B5 B7 06 1C 2E 67 C1 75 3A 00 E6 AD 7E D7 + def test_ffffff_d07(self): + tv = """18 B3 B5 B7 06 1C 2E 67 C1 75 3A 00 E6 AD 7E D7 BA 1C 90 6C F9 3E FB 70 92 EA F2 7F BE EB B7 55 AE 6E 29 24 93 C1 10 E4 8D 26 00 28 49 2B 8E 09 B5 50 06 12 B8 F2 57 89 85 DE D5 35 7D 00 EC 67""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF' * 3, domain=0x07).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff" * 3, domain=0x07).read(64) + self.assertEqual(res, btv) - def test_ffffffffffff_d0b(self): - tv = """BB 36 76 49 51 EC 97 E9 D8 5F 7E E9 A6 7A 77 18 + def test_ffffffffffff_d0b(self): + tv = """BB 36 76 49 51 EC 97 E9 D8 5F 7E E9 A6 7A 77 18 FC 00 5C F4 25 56 BE 79 CE 12 C0 BD E5 0E 57 36 D6 63 2B 0D 0D FB 20 2D 1B BB 8F FE 3D D7 4C B0 08 34 FA 75 6C B0 34 71 BA B1 3A 1E 2C 16 B3 C0""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF' * 7, domain=0x0B).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff" * 7, domain=0x0B).read(64) + self.assertEqual(res, btv) - def test_ff_d30(self): - tv = """F3 FE 12 87 3D 34 BC BB 2E 60 87 79 D6 B7 0E 7F + def test_ff_d30(self): + tv = """F3 FE 12 87 3D 34 BC BB 2E 60 87 79 D6 B7 0E 7F 86 BE C7 E9 0B F1 13 CB D4 FD D0 C4 E2 F4 62 5E 14 8D D7 EE 1A 52 77 6C F7 7F 24 05 14 D9 CC FC 3B 5D DA B8 EE 25 5E 39 EE 38 90 72 96 2C 11 1A""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF', domain=0x30).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff", domain=0x30).read(64) + self.assertEqual(res, btv) - def test_ffffff_d7f(self): - tv = """AB E5 69 C1 F7 7E C3 40 F0 27 05 E7 D3 7C 9A B7 + def test_ffffff_d7f(self): + tv = """AB E5 69 C1 F7 7E C3 40 F0 27 05 E7 D3 7C 9A B7 E1 55 51 6E 4A 6A 15 00 21 D7 0B 6F AC 0B B4 0C 06 9F 9A 98 28 A0 D5 75 CD 99 F9 BA E4 35 AB 1A CF 7E D9 11 0B A9 7C E0 38 8D 07 4B AC 76 87 76""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF' * 3, domain=0x7F).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff" * 3, domain=0x7F).read(64) + self.assertEqual(res, btv) def get_tests(config={}): - tests = [] - tests += list_test_cases(TurboSHAKE128Test) - tests += list_test_cases(TurboSHAKE256Test) - tests += list_test_cases(TurboSHAKE128TV) - tests += list_test_cases(TurboSHAKE256TV) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(TurboSHAKE128Test) + tests += list_test_cases(TurboSHAKE256Test) + tests += list_test_cases(TurboSHAKE128TV) + tests += list_test_cases(TurboSHAKE256TV) + return tests + + +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_cSHAKE.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_cSHAKE.py index 67971608..393365ab 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_cSHAKE.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_cSHAKE.py @@ -36,143 +36,153 @@ class cSHAKETest(unittest.TestCase): - - def test_left_encode(self): - from Cryptodome.Hash.cSHAKE128 import _left_encode - self.assertEqual(_left_encode(0), b'\x01\x00') - self.assertEqual(_left_encode(1), b'\x01\x01') - self.assertEqual(_left_encode(256), b'\x02\x01\x00') - - def test_bytepad(self): - from Cryptodome.Hash.cSHAKE128 import _bytepad - self.assertEqual(_bytepad(b'', 4), b'\x01\x04\x00\x00') - self.assertEqual(_bytepad(b'A', 4), b'\x01\x04A\x00') - self.assertEqual(_bytepad(b'AA', 4), b'\x01\x04AA') - self.assertEqual(_bytepad(b'AAA', 4), b'\x01\x04AAA\x00\x00\x00') - self.assertEqual(_bytepad(b'AAAA', 4), b'\x01\x04AAAA\x00\x00') - self.assertEqual(_bytepad(b'AAAAA', 4), b'\x01\x04AAAAA\x00') - self.assertEqual(_bytepad(b'AAAAAA', 4), b'\x01\x04AAAAAA') - self.assertEqual(_bytepad(b'AAAAAAA', 4), b'\x01\x04AAAAAAA\x00\x00\x00') - - def test_new_positive(self): - - xof1 = self.cshake.new() - xof2 = self.cshake.new(data=b("90")) - xof3 = self.cshake.new().update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - xof1 = self.cshake.new() - ref = xof1.read(10) - xof2 = self.cshake.new(custom=b("")) - xof3 = self.cshake.new(custom=b("foo")) - - self.assertEqual(ref, xof2.read(10)) - self.assertNotEqual(ref, xof3.read(10)) - - xof1 = self.cshake.new(custom=b("foo")) - xof2 = self.cshake.new(custom=b("foo"), data=b("90")) - xof3 = self.cshake.new(custom=b("foo")).update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = self.cshake.new() - h.update(pieces[0]).update(pieces[1]) - digest = h.read(10) - h = self.cshake.new() - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.read(10), digest) - - def test_update_negative(self): - h = self.cshake.new() - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = self.cshake.new() - digest = h.read(90) - - # read returns a byte string of the right length - self.assertTrue(isinstance(digest, type(b("digest")))) - self.assertEqual(len(digest), 90) - - def test_update_after_read(self): - mac = self.cshake.new() - mac.update(b("rrrr")) - mac.read(90) - self.assertRaises(TypeError, mac.update, b("ttt")) - - def test_shake(self): - # When no customization string is passed, results must match SHAKE - for digest_len in range(64): - xof1 = self.cshake.new(b'TEST') - xof2 = self.shake.new(b'TEST') - self.assertEqual(xof1.read(digest_len), xof2.read(digest_len)) + def test_left_encode(self): + from Cryptodome.Hash.cSHAKE128 import _left_encode + + self.assertEqual(_left_encode(0), b"\x01\x00") + self.assertEqual(_left_encode(1), b"\x01\x01") + self.assertEqual(_left_encode(256), b"\x02\x01\x00") + + def test_bytepad(self): + from Cryptodome.Hash.cSHAKE128 import _bytepad + + self.assertEqual(_bytepad(b"", 4), b"\x01\x04\x00\x00") + self.assertEqual(_bytepad(b"A", 4), b"\x01\x04A\x00") + self.assertEqual(_bytepad(b"AA", 4), b"\x01\x04AA") + self.assertEqual(_bytepad(b"AAA", 4), b"\x01\x04AAA\x00\x00\x00") + self.assertEqual(_bytepad(b"AAAA", 4), b"\x01\x04AAAA\x00\x00") + self.assertEqual(_bytepad(b"AAAAA", 4), b"\x01\x04AAAAA\x00") + self.assertEqual(_bytepad(b"AAAAAA", 4), b"\x01\x04AAAAAA") + self.assertEqual(_bytepad(b"AAAAAAA", 4), b"\x01\x04AAAAAAA\x00\x00\x00") + + def test_new_positive(self): + xof1 = self.cshake.new() + xof2 = self.cshake.new(data=b("90")) + xof3 = self.cshake.new().update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + xof1 = self.cshake.new() + ref = xof1.read(10) + xof2 = self.cshake.new(custom=b("")) + xof3 = self.cshake.new(custom=b("foo")) + + self.assertEqual(ref, xof2.read(10)) + self.assertNotEqual(ref, xof3.read(10)) + + xof1 = self.cshake.new(custom=b("foo")) + xof2 = self.cshake.new(custom=b("foo"), data=b("90")) + xof3 = self.cshake.new(custom=b("foo")).update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] + h = self.cshake.new() + h.update(pieces[0]).update(pieces[1]) + digest = h.read(10) + h = self.cshake.new() + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.read(10), digest) + + def test_update_negative(self): + h = self.cshake.new() + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = self.cshake.new() + digest = h.read(90) + + # read returns a byte string of the right length + self.assertTrue(isinstance(digest, type(b("digest")))) + self.assertEqual(len(digest), 90) + + def test_update_after_read(self): + mac = self.cshake.new() + mac.update(b("rrrr")) + mac.read(90) + self.assertRaises(TypeError, mac.update, b("ttt")) + + def test_shake(self): + # When no customization string is passed, results must match SHAKE + for digest_len in range(64): + xof1 = self.cshake.new(b"TEST") + xof2 = self.shake.new(b"TEST") + self.assertEqual(xof1.read(digest_len), xof2.read(digest_len)) class cSHAKE128Test(cSHAKETest): - cshake = cSHAKE128 - shake = SHAKE128 + cshake = cSHAKE128 + shake = SHAKE128 class cSHAKE256Test(cSHAKETest): - cshake = cSHAKE256 - shake = SHAKE256 + cshake = cSHAKE256 + shake = SHAKE256 class cSHAKEVectors(unittest.TestCase): - pass + pass -vector_files = [("ShortMsgSamples_cSHAKE128.txt", "Short Message Samples cSHAKE128", "128_cshake", cSHAKE128), - ("ShortMsgSamples_cSHAKE256.txt", "Short Message Samples cSHAKE256", "256_cshake", cSHAKE256), - ("CustomMsgSamples_cSHAKE128.txt", "Custom Message Samples cSHAKE128", "custom_128_cshake", cSHAKE128), - ("CustomMsgSamples_cSHAKE256.txt", "Custom Message Samples cSHAKE256", "custom_256_cshake", cSHAKE256), - ] +vector_files = [ + ("ShortMsgSamples_cSHAKE128.txt", "Short Message Samples cSHAKE128", "128_cshake", cSHAKE128), + ("ShortMsgSamples_cSHAKE256.txt", "Short Message Samples cSHAKE256", "256_cshake", cSHAKE256), + ("CustomMsgSamples_cSHAKE128.txt", "Custom Message Samples cSHAKE128", "custom_128_cshake", cSHAKE128), + ("CustomMsgSamples_cSHAKE256.txt", "Custom Message Samples cSHAKE256", "custom_256_cshake", cSHAKE256), +] for file, descr, tag, test_class in vector_files: - - test_vectors = load_test_vectors(("Hash", "SHA3"), file, descr, - {"len": lambda x: int(x), - "nlen": lambda x: int(x), - "slen": lambda x: int(x)}) or [] - - for idx, tv in enumerate(test_vectors): - if getattr(tv, "len", 0) == 0: - data = b("") - else: - data = tobytes(tv.msg) - assert(tv.len == len(tv.msg)*8) - if getattr(tv, "nlen", 0) != 0: - raise ValueError("Unsupported cSHAKE test vector") - if getattr(tv, "slen", 0) == 0: - custom = b("") - else: - custom = tobytes(tv.s) - assert(tv.slen == len(tv.s)*8) - - def new_test(self, data=data, result=tv.md, custom=custom, test_class=test_class): - hobj = test_class.new(data=data, custom=custom) - digest = hobj.read(len(result)) - self.assertEqual(digest, result) - - setattr(cSHAKEVectors, "test_%s_%d" % (tag, idx), new_test) + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + file, + descr, + { + "len": lambda x: int(x), + "nlen": lambda x: int(x), + "slen": lambda x: int(x), + }, + ) + or [] + ) + + for idx, tv in enumerate(test_vectors): + if getattr(tv, "len", 0) == 0: + data = b("") + else: + data = tobytes(tv.msg) + assert tv.len == len(tv.msg) * 8 + if getattr(tv, "nlen", 0) != 0: + raise ValueError("Unsupported cSHAKE test vector") + if getattr(tv, "slen", 0) == 0: + custom = b("") + else: + custom = tobytes(tv.s) + assert tv.slen == len(tv.s) * 8 + + def new_test(self, data=data, result=tv.md, custom=custom, test_class=test_class): + hobj = test_class.new(data=data, custom=custom) + digest = hobj.read(len(result)) + self.assertEqual(digest, result) + + setattr(cSHAKEVectors, "test_%s_%d" % (tag, idx), new_test) def get_tests(config={}): - tests = [] - tests += list_test_cases(cSHAKE128Test) - tests += list_test_cases(cSHAKE256Test) - tests += list_test_cases(cSHAKEVectors) - return tests + tests = [] + tests += list_test_cases(cSHAKE128Test) + tests += list_test_cases(cSHAKE256Test) + tests += list_test_cases(cSHAKEVectors) + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_keccak.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_keccak.py index dcc0d137..00587e2c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_keccak.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Hash/test_keccak.py @@ -31,7 +31,7 @@ """Self-test suite for Cryptodome.Hash.keccak""" import unittest -from binascii import hexlify, unhexlify +from binascii import hexlify from Cryptodome.SelfTest.loader import load_test_vectors from Cryptodome.SelfTest.st_common import list_test_cases @@ -39,212 +39,253 @@ from Cryptodome.Hash import keccak from Cryptodome.Util.py3compat import b, tobytes, bchr -class KeccakTest(unittest.TestCase): - - def test_new_positive(self): - - for digest_bits in (224, 256, 384, 512): - hobj = keccak.new(digest_bits=digest_bits) - self.assertEqual(hobj.digest_size, digest_bits // 8) - - hobj2 = hobj.new() - self.assertEqual(hobj2.digest_size, digest_bits // 8) - - for digest_bytes in (28, 32, 48, 64): - hobj = keccak.new(digest_bytes=digest_bytes) - self.assertEqual(hobj.digest_size, digest_bytes) - - hobj2 = hobj.new() - self.assertEqual(hobj2.digest_size, digest_bytes) - - def test_new_positive2(self): - - digest1 = keccak.new(data=b("\x90"), digest_bytes=64).digest() - digest2 = keccak.new(digest_bytes=64).update(b("\x90")).digest() - self.assertEqual(digest1, digest2) - - def test_new_negative(self): - - # keccak.new needs digest size - self.assertRaises(TypeError, keccak.new) - - h = keccak.new(digest_bits=512) - - # Either bits or bytes can be specified - self.assertRaises(TypeError, keccak.new, - digest_bytes=64, - digest_bits=512) - - # Range - self.assertRaises(ValueError, keccak.new, digest_bytes=0) - self.assertRaises(ValueError, keccak.new, digest_bytes=1) - self.assertRaises(ValueError, keccak.new, digest_bytes=65) - self.assertRaises(ValueError, keccak.new, digest_bits=0) - self.assertRaises(ValueError, keccak.new, digest_bits=1) - self.assertRaises(ValueError, keccak.new, digest_bits=513) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = keccak.new(digest_bytes=64) - h.update(pieces[0]).update(pieces[1]) - digest = h.digest() - h = keccak.new(digest_bytes=64) - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.digest(), digest) - - def test_update_negative(self): - h = keccak.new(digest_bytes=64) - self.assertRaises(TypeError, h.update, u"string") - def test_digest(self): - h = keccak.new(digest_bytes=64) - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b("digest")))) - - def test_hex_digest(self): - mac = keccak.new(digest_bits=512) - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_update_after_digest(self): - msg=b("rrrrttt") - - # Normally, update() cannot be done after digest() - h = keccak.new(digest_bits=512, data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = keccak.new(digest_bits=512, data=msg).digest() - - # With the proper flag, it is allowed - h = keccak.new(digest_bits=512, data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) +class KeccakTest(unittest.TestCase): + def test_new_positive(self): + for digest_bits in (224, 256, 384, 512): + hobj = keccak.new(digest_bits=digest_bits) + self.assertEqual(hobj.digest_size, digest_bits // 8) + + hobj2 = hobj.new() + self.assertEqual(hobj2.digest_size, digest_bits // 8) + + for digest_bytes in (28, 32, 48, 64): + hobj = keccak.new(digest_bytes=digest_bytes) + self.assertEqual(hobj.digest_size, digest_bytes) + + hobj2 = hobj.new() + self.assertEqual(hobj2.digest_size, digest_bytes) + + def test_new_positive2(self): + digest1 = keccak.new(data=b("\x90"), digest_bytes=64).digest() + digest2 = keccak.new(digest_bytes=64).update(b("\x90")).digest() + self.assertEqual(digest1, digest2) + + def test_new_negative(self): + # keccak.new needs digest size + self.assertRaises(TypeError, keccak.new) + + h = keccak.new(digest_bits=512) + + # Either bits or bytes can be specified + self.assertRaises( + TypeError, + keccak.new, + digest_bytes=64, + digest_bits=512, + ) + + # Range + self.assertRaises(ValueError, keccak.new, digest_bytes=0) + self.assertRaises(ValueError, keccak.new, digest_bytes=1) + self.assertRaises(ValueError, keccak.new, digest_bytes=65) + self.assertRaises(ValueError, keccak.new, digest_bits=0) + self.assertRaises(ValueError, keccak.new, digest_bits=1) + self.assertRaises(ValueError, keccak.new, digest_bits=513) + + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] + h = keccak.new(digest_bytes=64) + h.update(pieces[0]).update(pieces[1]) + digest = h.digest() + h = keccak.new(digest_bytes=64) + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.digest(), digest) + + def test_update_negative(self): + h = keccak.new(digest_bytes=64) + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = keccak.new(digest_bytes=64) + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b("digest")))) + + def test_hex_digest(self): + mac = keccak.new(digest_bits=512) + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_update_after_digest(self): + msg = b("rrrrttt") + + # Normally, update() cannot be done after digest() + h = keccak.new(digest_bits=512, data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = keccak.new(digest_bits=512, data=msg).digest() + + # With the proper flag, it is allowed + h = keccak.new(digest_bits=512, data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) class KeccakVectors(unittest.TestCase): - pass - - # TODO: add ExtremelyLong tests - - -test_vectors_224 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_224.txt", - "Short Messages KAT 224", - {"len": lambda x: int(x)}) or [] - -test_vectors_224 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_224.txt", - "Long Messages KAT 224", - {"len": lambda x: int(x)}) or [] + pass + + # TODO: add ExtremelyLong tests + + +test_vectors_224 = ( + load_test_vectors( + ("Hash", "keccak"), + "ShortMsgKAT_224.txt", + "Short Messages KAT 224", + {"len": lambda x: int(x)}, + ) + or [] +) + +test_vectors_224 += ( + load_test_vectors( + ("Hash", "keccak"), + "LongMsgKAT_224.txt", + "Long Messages KAT 224", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_224): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=224, data=data) - self.assertEqual(hobj.digest(), result) + def new_test(self, data=data, result=tv.md): + hobj = keccak.new(digest_bits=224, data=data) + self.assertEqual(hobj.digest(), result) - setattr(KeccakVectors, "test_224_%d" % idx, new_test) + setattr(KeccakVectors, "test_224_%d" % idx, new_test) # --- -test_vectors_256 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_256.txt", - "Short Messages KAT 256", - { "len" : lambda x: int(x) } ) or [] - -test_vectors_256 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_256.txt", - "Long Messages KAT 256", - { "len" : lambda x: int(x) } ) or [] +test_vectors_256 = ( + load_test_vectors( + ("Hash", "keccak"), + "ShortMsgKAT_256.txt", + "Short Messages KAT 256", + {"len": lambda x: int(x)}, + ) + or [] +) + +test_vectors_256 += ( + load_test_vectors( + ("Hash", "keccak"), + "LongMsgKAT_256.txt", + "Long Messages KAT 256", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_256): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=256, data=data) - self.assertEqual(hobj.digest(), result) + def new_test(self, data=data, result=tv.md): + hobj = keccak.new(digest_bits=256, data=data) + self.assertEqual(hobj.digest(), result) - setattr(KeccakVectors, "test_256_%d" % idx, new_test) + setattr(KeccakVectors, "test_256_%d" % idx, new_test) # --- -test_vectors_384 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_384.txt", - "Short Messages KAT 384", - {"len": lambda x: int(x)}) or [] - -test_vectors_384 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_384.txt", - "Long Messages KAT 384", - {"len": lambda x: int(x)}) or [] +test_vectors_384 = ( + load_test_vectors( + ("Hash", "keccak"), + "ShortMsgKAT_384.txt", + "Short Messages KAT 384", + {"len": lambda x: int(x)}, + ) + or [] +) + +test_vectors_384 += ( + load_test_vectors( + ("Hash", "keccak"), + "LongMsgKAT_384.txt", + "Long Messages KAT 384", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_384): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=384, data=data) - self.assertEqual(hobj.digest(), result) + def new_test(self, data=data, result=tv.md): + hobj = keccak.new(digest_bits=384, data=data) + self.assertEqual(hobj.digest(), result) - setattr(KeccakVectors, "test_384_%d" % idx, new_test) + setattr(KeccakVectors, "test_384_%d" % idx, new_test) # --- -test_vectors_512 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_512.txt", - "Short Messages KAT 512", - {"len": lambda x: int(x)}) or [] - -test_vectors_512 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_512.txt", - "Long Messages KAT 512", - {"len": lambda x: int(x)}) or [] +test_vectors_512 = ( + load_test_vectors( + ("Hash", "keccak"), + "ShortMsgKAT_512.txt", + "Short Messages KAT 512", + {"len": lambda x: int(x)}, + ) + or [] +) + +test_vectors_512 += ( + load_test_vectors( + ("Hash", "keccak"), + "LongMsgKAT_512.txt", + "Long Messages KAT 512", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_512): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=512, data=data) - self.assertEqual(hobj.digest(), result) + def new_test(self, data=data, result=tv.md): + hobj = keccak.new(digest_bits=512, data=data) + self.assertEqual(hobj.digest(), result) - setattr(KeccakVectors, "test_512_%d" % idx, new_test) + setattr(KeccakVectors, "test_512_%d" % idx, new_test) def get_tests(config={}): - tests = [] - tests += list_test_cases(KeccakTest) - tests += list_test_cases(KeccakVectors) - return tests + tests = [] + tests += list_test_cases(KeccakTest) + tests += list_test_cases(KeccakVectors) + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/__init__.py index f15f1413..0c2fa3f2 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/__init__.py @@ -33,15 +33,20 @@ """Self-test for I/O""" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.IO import test_PKCS8; tests += test_PKCS8.get_tests(config=config) - from Cryptodome.SelfTest.IO import test_PBES; tests += test_PBES.get_tests(config=config) - return tests + tests = [] + from Cryptodome.SelfTest.IO import test_PKCS8 + + tests += test_PKCS8.get_tests(config=config) + from Cryptodome.SelfTest.IO import test_PBES + + tests += test_PBES.get_tests(config=config) + return tests -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/test_PBES.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/test_PBES.py index 19762f3a..d18a139a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/test_PBES.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/test_PBES.py @@ -39,80 +39,112 @@ class TestPBES2(unittest.TestCase): - - def setUp(self): - self.ref = b"Test data" - self.passphrase = b"Passphrase" - - def test1(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test2(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA224AndAES128-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test3(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA256AndAES192-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test4(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA384AndAES256-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test5(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA512AndAES128-GCM') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test6(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA512-224AndAES192-GCM') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test7(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA3-256AndAES256-GCM') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test8(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'scryptAndAES128-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test9(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'scryptAndAES192-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test10(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'scryptAndAES256-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) + def setUp(self): + self.ref = b"Test data" + self.passphrase = b"Passphrase" + + def test1(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test2(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA224AndAES128-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test3(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA256AndAES192-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test4(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA384AndAES256-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test5(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA512AndAES128-GCM", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test6(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA512-224AndAES192-GCM", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test7(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA3-256AndAES256-GCM", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test8(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "scryptAndAES128-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test9(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "scryptAndAES192-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test10(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "scryptAndAES256-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - listTests = [] - listTests += list_test_cases(TestPBES2) - return listTests + from Cryptodome.SelfTest.st_common import list_test_cases + + listTests = [] + listTests += list_test_cases(TestPBES2) + return listTests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/test_PKCS8.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/test_PKCS8.py index 718b69db..2b0d1f05 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/test_PKCS8.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/IO/test_PKCS8.py @@ -41,11 +41,11 @@ from Cryptodome.Util.asn1 import DerNull -oid_key = '1.2.840.113549.1.1.1' +oid_key = "1.2.840.113549.1.1.1" # Original RSA key (in DER format) # hexdump -v -e '32/1 "%02x" "\n"' key.der -clear_key=""" +clear_key = """ 308201ab020100025a00b94a7f7075ab9e79e8196f47be707781e80dd965cf16 0c951a870b71783b6aaabbd550c0e65e5a3dfe15b8620009f6d7e5efec42a3f0 6fe20faeebb0c356e79cdec6db4dd427e82d8ae4a5b90996227b8ba54ccfc4d2 @@ -66,7 +66,7 @@ # # openssl pkcs8 -topk8 -inform DER -nocrypt -in key.der -outform DER -out keyp8.der # hexdump -v -e '32/1 "%02x" "\n"' keyp8.der -wrapped_clear_key=""" +wrapped_clear_key = """ 308201c5020100300d06092a864886f70d0101010500048201af308201ab0201 00025a00b94a7f7075ab9e79e8196f47be707781e80dd965cf160c951a870b71 783b6aaabbd550c0e65e5a3dfe15b8620009f6d7e5efec42a3f06fe20faeebb0 @@ -102,12 +102,13 @@ # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -outform DER -out keyenc.der -v2 des3 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC', -2048, -"47EA7227D8B22E2F", # IV -"E3F7A838AB911A4D", # Salt -""" +wrapped_enc_keys.append( + ( + "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC", + 2048, + "47EA7227D8B22E2F", # IV + "E3F7A838AB911A4D", # Salt + """ 30820216304006092a864886f70d01050d3033301b06092a864886f70d01050c 300e0408e3f7a838ab911a4d02020800301406082a864886f70d0307040847ea 7227d8b22e2f048201d0ea388b374d2d0e4ceb7a5139f850fdff274884a6e6c0 @@ -125,19 +126,21 @@ 9c10c9e6efbe78430a61f71c89948aa32cdc3cc7338cf994147819ce7ab23450 c8f7d9b94c3bb377d17a3fa204b601526317824b142ff6bc843fa7815ece89c0 839573f234dac8d80cc571a045353d61db904a4398d8ef3df5ac -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -outform DER -out keyenc.der # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'skip encryption', # pbeWithMD5AndDES-CBC, only decoding is supported --1, -"", -"", -""" +wrapped_enc_keys.append( + ( + "skip encryption", # pbeWithMD5AndDES-CBC, only decoding is supported + -1, + "", + "", + """ 308201f1301b06092a864886f70d010503300e0408f9b990c89af1d41b020208 00048201d0c6267fe8592903891933d559e71a7ca68b2e39150f19daca0f7921 52f97e249d72f670d5140e9150433310ed7c7ee51927693fd39884cb9551cea5 @@ -154,20 +157,22 @@ a50e96a2264490aeabdc07c6e78e5dbf4fe3388726d0e2a228346bf3c2907d68 2a6276b22ae883fb30fa611f4e4193e7a08480fcd7db48308bacbd72bf4807aa 11fd394859f97d22982f7fe890b2e2a0f7e7ffb693 -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v1 PBE-SHA1-RC2-64 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'skip encryption', # pbeWithSHA1AndRC2-CBC, only decoding is supported --1, -"", -"", -""" +wrapped_enc_keys.append( + ( + "skip encryption", # pbeWithSHA1AndRC2-CBC, only decoding is supported + -1, + "", + "", + """ 308201f1301b06092a864886f70d01050b300e04083ee943bdae185008020208 00048201d0e4614d9371d3ff10ceabc2f6a7a13a0f449f9a714144e46518ea55 e3e6f0cde24031d01ef1f37ec40081449ef01914faf45983dde0d2bc496712de @@ -183,20 +188,22 @@ b16e27ae528db28593af9adcfccbebb3b9e1f2af5cd5531b51968389caa6c091 e7de1f1b96f0d258e54e540d961a7c0ef51fda45d6da5fddd33e9bbfd3a5f8d7 d7ab2e971de495cddbc86d38444fee9f0ac097b00adaf7802dabe0cff5b43b45 -4f26b7b547016f89be52676866189911c53e2f2477""" -)) +4f26b7b547016f89be52676866189911c53e2f2477""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v1 PBE-MD5-RC2-64 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'skip encryption', # pbeWithMD5AndRC2-CBC, only decoding is supported --1, -"", -"", -""" +wrapped_enc_keys.append( + ( + "skip encryption", # pbeWithMD5AndRC2-CBC, only decoding is supported + -1, + "", + "", + """ 308201f1301b06092a864886f70d010506300e0408f5cd2fee56d9b4b8020208 00048201d086454942d6166a19d6b108465bd111e7080911f573d54b1369c676 df28600e84936bfec04f91023ff16499e2e07178c340904f12ffa6886ab66228 @@ -212,20 +219,22 @@ b77d1db287b3a6264c466805be5a4fe85cfbca180699859280f2dd8e2c2c10b5 7a7d2ac670c6039d41952fbb0e4f99b560ebe1d020e1b96d02403283819c00cc 529c51f0b0101555e4c58002ba3c6e3c12e3fde1aec94382792e96d9666a2b33 -3dc397b22ecab67ee38a552fec29a1d4ff8719c748""" -)) +3dc397b22ecab67ee38a552fec29a1d4ff8719c748""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v1 PBE-SHA1-DES # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'skip encryption', # pbeWithSHA1AndDES-CBC, only decoding is supported --1, -"", -"", -""" +wrapped_enc_keys.append( + ( + "skip encryption", # pbeWithSHA1AndDES-CBC, only decoding is supported + -1, + "", + "", + """ 308201f1301b06092a864886f70d01050a300e04089bacc9cf1e8f734e020208 00048201d03e502f3ceafe8fd19ab2939576bfdded26d719b2441db1459688f5 9673218b41ec1f739edf1e460bd927bc28470c87b2d4fc8ea02ba17b47a63c49 @@ -242,20 +251,22 @@ 3a606f4e4b9b46eb13b57f2624b651859d3d2d5192b45dbd5a2ead14ff20ca76 48f321309aa56d8c0c4a192b580821cc6c70c75e6f19d1c5414da898ec4dd39d b0eb93d6ba387a80702dfd2db610757ba340f63230 -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v2 aes128 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndAES128-CBC', -2048, -"4F66EE5D3BCD531FE6EBF4B4E73016B8", # IV -"479F25156176C53A", # Salt -""" +wrapped_enc_keys.append( + ( + "PBKDF2WithHMAC-SHA1AndAES128-CBC", + 2048, + "4F66EE5D3BCD531FE6EBF4B4E73016B8", # IV + "479F25156176C53A", # Salt + """ 3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c 300e0408479f25156176c53a02020800301d060960864801650304010204104f 66ee5d3bcd531fe6ebf4b4e73016b8048201d0e33cfa560423f589d097d21533 @@ -274,20 +285,22 @@ d740e082b4a3bbb8bafdd34a0b3c5f2f3c2aceccccdccd092b78994b845bfa61 706c3b9df5165ed1dbcbf1244fe41fc9bf993f52f7658e2f87e1baaeacb0f562 9d905c -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v2 aes192 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndAES192-CBC', -2048, -"5CFC2A4FF7B63201A4A8A5B021148186", # IV -"D718541C264944CE", # Salt -""" +wrapped_enc_keys.append( + ( + "PBKDF2WithHMAC-SHA1AndAES192-CBC", + 2048, + "5CFC2A4FF7B63201A4A8A5B021148186", # IV + "D718541C264944CE", # Salt + """ 3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c 300e0408d718541c264944ce02020800301d060960864801650304011604105c fc2a4ff7b63201a4a8a5b021148186048201d08e74aaa21b8bcfb15b9790fe95 @@ -306,20 +319,22 @@ 0970ed34acd6e3e89d063987893b2b9570ddb8cc032b05a723bba9444933ebf3 c624204be72f4190e0245197d0cb772bec933fd8442445f9a28bd042d5a3a1e9 9a8a07 -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v2 aes192 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndAES256-CBC', -2048, -"323351F94462AC563E053A056252C2C4", # IV -"02A6CD0D12E727B5", # Salt -""" +wrapped_enc_keys.append( + ( + "PBKDF2WithHMAC-SHA1AndAES256-CBC", + 2048, + "323351F94462AC563E053A056252C2C4", # IV + "02A6CD0D12E727B5", # Salt + """ 3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c 300e040802a6cd0d12e727b502020800301d060960864801650304012a041032 3351f94462ac563e053a056252c2c4048201d07f4ef1c7be21aae738a20c5632 @@ -338,8 +353,9 @@ e8abd059f8e8ffea637c9c7721f817aaf0bb23403e26a0ef0ff0e2037da67d41 af728481f53443551a9bff4cea023164e9622b5441a309e1f4bff98e5bf76677 8d7cd9 -""" -)) +""", + ) +) # hexdump -v -e '32/1 "%02x" "\n"' botan_scrypt.der botan_scrypt = """ @@ -365,95 +381,106 @@ 996363f37032e10ac85afebb7cc1cbfc0e5d4c60a4c2 """ + def txt2bin(inputs): - s = b('').join([b(x) for x in inputs if not (x in '\n\r\t ')]) - return unhexlify(s) + s = b("").join([b(x) for x in inputs if x not in "\n\r\t "]) + return unhexlify(s) + class Rng: - def __init__(self, output): - self.output=output - self.idx=0 - def __call__(self, n): - output = self.output[self.idx:self.idx+n] - self.idx += n - return output + def __init__(self, output): + self.output = output + self.idx = 0 -class PKCS8_Decrypt(unittest.TestCase): + def __call__(self, n): + output = self.output[self.idx : self.idx + n] + self.idx += n + return output - def setUp(self): - self.oid_key = oid_key - self.clear_key = txt2bin(clear_key) - self.wrapped_clear_key = txt2bin(wrapped_clear_key) - self.wrapped_enc_keys = [] - for t in wrapped_enc_keys: - self.wrapped_enc_keys.append(( - t[0], - t[1], - txt2bin(t[2]), - txt2bin(t[3]), - txt2bin(t[4]) - )) - - ### NO ENCRYTION - - def test1(self): - """Verify unwrapping w/o encryption""" - res1, res2, res3 = PKCS8.unwrap(self.wrapped_clear_key) - self.assertEqual(res1, self.oid_key) - self.assertEqual(res2, self.clear_key) - - def test2(self): - """Verify wrapping w/o encryption""" - wrapped = PKCS8.wrap(self.clear_key, self.oid_key) - res1, res2, res3 = PKCS8.unwrap(wrapped) - self.assertEqual(res1, self.oid_key) - self.assertEqual(res2, self.clear_key) - - ## ENCRYPTION - - def test3(self): - """Verify unwrapping with encryption""" - - for t in self.wrapped_enc_keys: - res1, res2, res3 = PKCS8.unwrap(t[4], b"TestTest") - self.assertEqual(res1, self.oid_key) - self.assertEqual(res2, self.clear_key) - - def test4(self): - """Verify wrapping with encryption""" - - for t in self.wrapped_enc_keys: - if t[0] == 'skip encryption': - continue - rng = Rng(t[2]+t[3]) - params = { 'iteration_count':t[1] } - wrapped = PKCS8.wrap( - self.clear_key, - self.oid_key, - b("TestTest"), - protection=t[0], - prot_params=params, - key_params=DerNull(), - randfunc=rng) - self.assertEqual(wrapped, t[4]) - - def test_import_botan_keys(self): - botan_scrypt_der = txt2bin(botan_scrypt) - key1 = PKCS8.unwrap(botan_scrypt_der, - b'your_password') - botan_pbkdf2_der = txt2bin(botan_pbkdf2) - key2 = PKCS8.unwrap(botan_pbkdf2_der, - b'your_password') - self.assertEqual(key1, key2) + +class PKCS8_Decrypt(unittest.TestCase): + def setUp(self): + self.oid_key = oid_key + self.clear_key = txt2bin(clear_key) + self.wrapped_clear_key = txt2bin(wrapped_clear_key) + self.wrapped_enc_keys = [] + for t in wrapped_enc_keys: + self.wrapped_enc_keys.append( + ( + t[0], + t[1], + txt2bin(t[2]), + txt2bin(t[3]), + txt2bin(t[4]), + ) + ) + + ### NO ENCRYTION + + def test1(self): + """Verify unwrapping w/o encryption""" + res1, res2, res3 = PKCS8.unwrap(self.wrapped_clear_key) + self.assertEqual(res1, self.oid_key) + self.assertEqual(res2, self.clear_key) + + def test2(self): + """Verify wrapping w/o encryption""" + wrapped = PKCS8.wrap(self.clear_key, self.oid_key) + res1, res2, res3 = PKCS8.unwrap(wrapped) + self.assertEqual(res1, self.oid_key) + self.assertEqual(res2, self.clear_key) + + ## ENCRYPTION + + def test3(self): + """Verify unwrapping with encryption""" + + for t in self.wrapped_enc_keys: + res1, res2, res3 = PKCS8.unwrap(t[4], b"TestTest") + self.assertEqual(res1, self.oid_key) + self.assertEqual(res2, self.clear_key) + + def test4(self): + """Verify wrapping with encryption""" + + for t in self.wrapped_enc_keys: + if t[0] == "skip encryption": + continue + rng = Rng(t[2] + t[3]) + params = {"iteration_count": t[1]} + wrapped = PKCS8.wrap( + self.clear_key, + self.oid_key, + b("TestTest"), + protection=t[0], + prot_params=params, + key_params=DerNull(), + randfunc=rng, + ) + self.assertEqual(wrapped, t[4]) + + def test_import_botan_keys(self): + botan_scrypt_der = txt2bin(botan_scrypt) + key1 = PKCS8.unwrap( + botan_scrypt_der, + b"your_password", + ) + botan_pbkdf2_der = txt2bin(botan_pbkdf2) + key2 = PKCS8.unwrap( + botan_pbkdf2_der, + b"your_password", + ) + self.assertEqual(key1, key2) def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - listTests = [] - listTests += list_test_cases(PKCS8_Decrypt) - return listTests + from Cryptodome.SelfTest.st_common import list_test_cases + + listTests = [] + listTests += list_test_cases(PKCS8_Decrypt) + return listTests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/__init__.py index 9f732ba3..64e52df0 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/__init__.py @@ -33,19 +33,23 @@ """Self-test for Math""" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Math import test_Numbers - from Cryptodome.SelfTest.Math import test_Primality - from Cryptodome.SelfTest.Math import test_modexp - from Cryptodome.SelfTest.Math import test_modmult - tests += test_Numbers.get_tests(config=config) - tests += test_Primality.get_tests(config=config) - tests += test_modexp.get_tests(config=config) - tests += test_modmult.get_tests(config=config) - return tests + tests = [] + from Cryptodome.SelfTest.Math import test_Numbers + from Cryptodome.SelfTest.Math import test_Primality + from Cryptodome.SelfTest.Math import test_modexp + from Cryptodome.SelfTest.Math import test_modmult + + tests += test_Numbers.get_tests(config=config) + tests += test_Primality.get_tests(config=config) + tests += test_modexp.get_tests(config=config) + tests += test_modmult.get_tests(config=config) + return tests + + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_Numbers.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_Numbers.py index f974d5a0..d3871e34 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_Numbers.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_Numbers.py @@ -44,795 +44,1287 @@ class TestIntegerBase(unittest.TestCase): - - def setUp(self): - raise NotImplementedError("To be implemented") - - def Integers(self, *arg): - return map(self.Integer, arg) - - def test_init_and_equality(self): - Integer = self.Integer - - v1 = Integer(23) - v2 = Integer(v1) - v3 = Integer(-9) - self.assertRaises(ValueError, Integer, 1.0) - - v4 = Integer(10**10) - v5 = Integer(-10**10) - - v6 = Integer(0xFFFF) - v7 = Integer(0xFFFFFFFF) - v8 = Integer(0xFFFFFFFFFFFFFFFF) - - self.assertEqual(v1, v1) - self.assertEqual(v1, 23) - self.assertEqual(v1, v2) - self.assertEqual(v3, -9) - self.assertEqual(v4, 10 ** 10) - self.assertEqual(v5, -10 ** 10) - self.assertEqual(v6, 0xFFFF) - self.assertEqual(v7, 0xFFFFFFFF) - self.assertEqual(v8, 0xFFFFFFFFFFFFFFFF) - - self.assertFalse(v1 == v4) - - # Init and comparison between Integer's - v6 = Integer(v1) - self.assertEqual(v1, v6) - - self.assertFalse(Integer(0) == None) - - def test_conversion_to_int(self): - v1, v2 = self.Integers(-23, 2 ** 1000) - self.assertEqual(int(v1), -23) - self.assertEqual(int(v2), 2 ** 1000) - - def test_equality_with_ints(self): - v1, v2, v3 = self.Integers(23, -89, 2 ** 1000) - self.assertTrue(v1 == 23) - self.assertTrue(v2 == -89) - self.assertFalse(v1 == 24) - self.assertTrue(v3 == 2 ** 1000) - - def test_conversion_to_str(self): - v1, v2, v3, v4 = self.Integers(20, 0, -20, 2 ** 1000) - self.assertTrue(str(v1) == "20") - self.assertTrue(str(v2) == "0") - self.assertTrue(str(v3) == "-20") - self.assertTrue(str(v4) == "10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376") - - def test_repr(self): - v1, v2 = self.Integers(-1, 2**80) - self.assertEqual(repr(v1), "Integer(-1)") - self.assertEqual(repr(v2), "Integer(1208925819614629174706176)") - - def test_conversion_to_bytes(self): - Integer = self.Integer - - v0 = Integer(0) - self.assertEqual(b"\x00", v0.to_bytes()) - - v1 = Integer(0x17) - self.assertEqual(b"\x17", v1.to_bytes()) - - v2 = Integer(0xFFFE) - self.assertEqual(b"\xFF\xFE", v2.to_bytes()) - self.assertEqual(b"\x00\xFF\xFE", v2.to_bytes(3)) - self.assertRaises(ValueError, v2.to_bytes, 1) - - self.assertEqual(b"\xFE\xFF", v2.to_bytes(byteorder='little')) - self.assertEqual(b"\xFE\xFF\x00", v2.to_bytes(3, byteorder='little')) - - v3 = Integer(0xFF00AABBCCDDEE1122) - self.assertEqual(b"\xFF\x00\xAA\xBB\xCC\xDD\xEE\x11\x22", v3.to_bytes()) - self.assertEqual(b"\x22\x11\xEE\xDD\xCC\xBB\xAA\x00\xFF", - v3.to_bytes(byteorder='little')) - self.assertEqual(b"\x00\xFF\x00\xAA\xBB\xCC\xDD\xEE\x11\x22", - v3.to_bytes(10)) - self.assertEqual(b"\x22\x11\xEE\xDD\xCC\xBB\xAA\x00\xFF\x00", - v3.to_bytes(10, byteorder='little')) - self.assertRaises(ValueError, v3.to_bytes, 8) - - v4 = Integer(-90) - self.assertRaises(ValueError, v4.to_bytes) - self.assertRaises(ValueError, v4.to_bytes, byteorder='bittle') - - def test_conversion_from_bytes(self): - Integer = self.Integer - - v1 = Integer.from_bytes(b"\x00") - self.assertTrue(isinstance(v1, Integer)) - self.assertEqual(0, v1) - - v2 = Integer.from_bytes(b"\x00\x01") - self.assertEqual(1, v2) - - v3 = Integer.from_bytes(b"\xFF\xFF") - self.assertEqual(0xFFFF, v3) - - v4 = Integer.from_bytes(b"\x00\x01", 'big') - self.assertEqual(1, v4) - - v5 = Integer.from_bytes(b"\x00\x01", byteorder='big') - self.assertEqual(1, v5) - - v6 = Integer.from_bytes(b"\x00\x01", byteorder='little') - self.assertEqual(0x0100, v6) - - self.assertRaises(ValueError, Integer.from_bytes, b'\x09', 'bittle') - - def test_inequality(self): - # Test Integer!=Integer and Integer!=int - v1, v2, v3, v4 = self.Integers(89, 89, 90, -8) - self.assertTrue(v1 != v3) - self.assertTrue(v1 != 90) - self.assertFalse(v1 != v2) - self.assertFalse(v1 != 89) - self.assertTrue(v1 != v4) - self.assertTrue(v4 != v1) - self.assertTrue(self.Integer(0) != None) - - def test_less_than(self): - # Test IntegerInteger and Integer>int - v1, v2, v3, v4, v5 = self.Integers(13, 13, 14, -8, 2 ** 10) - self.assertTrue(v3 > v1) - self.assertTrue(v3 > 13) - self.assertFalse(v1 > v1) - self.assertFalse(v1 > v2) - self.assertFalse(v1 > 13) - self.assertTrue(v1 > v4) - self.assertFalse(v4 > v1) - self.assertTrue(v5 > v1) - self.assertFalse(v1 > v5) - - def test_more_than_or_equal(self): - # Test Integer>=Integer and Integer>=int - v1, v2, v3, v4 = self.Integers(13, 13, 14, -4) - self.assertTrue(v3 >= v1) - self.assertTrue(v3 >= 13) - self.assertTrue(v1 >= v2) - self.assertTrue(v1 >= v1) - self.assertTrue(v1 >= 13) - self.assertFalse(v4 >= v1) - - def test_bool(self): - v1, v2, v3, v4 = self.Integers(0, 10, -9, 2 ** 10) - self.assertFalse(v1) - self.assertFalse(bool(v1)) - self.assertTrue(v2) - self.assertTrue(bool(v2)) - self.assertTrue(v3) - self.assertTrue(v4) - - def test_is_negative(self): - v1, v2, v3, v4, v5 = self.Integers(-3 ** 100, -3, 0, 3, 3**100) - self.assertTrue(v1.is_negative()) - self.assertTrue(v2.is_negative()) - self.assertFalse(v4.is_negative()) - self.assertFalse(v5.is_negative()) - - def test_addition(self): - # Test Integer+Integer and Integer+int - v1, v2, v3 = self.Integers(7, 90, -7) - self.assertTrue(isinstance(v1 + v2, self.Integer)) - self.assertEqual(v1 + v2, 97) - self.assertEqual(v1 + 90, 97) - self.assertEqual(v1 + v3, 0) - self.assertEqual(v1 + (-7), 0) - self.assertEqual(v1 + 2 ** 10, 2 ** 10 + 7) - - def test_subtraction(self): - # Test Integer-Integer and Integer-int - v1, v2, v3 = self.Integers(7, 90, -7) - self.assertTrue(isinstance(v1 - v2, self.Integer)) - self.assertEqual(v2 - v1, 83) - self.assertEqual(v2 - 7, 83) - self.assertEqual(v2 - v3, 97) - self.assertEqual(v1 - (-7), 14) - self.assertEqual(v1 - 2 ** 10, 7 - 2 ** 10) - - def test_multiplication(self): - # Test Integer-Integer and Integer-int - v1, v2, v3, v4 = self.Integers(4, 5, -2, 2 ** 10) - self.assertTrue(isinstance(v1 * v2, self.Integer)) - self.assertEqual(v1 * v2, 20) - self.assertEqual(v1 * 5, 20) - self.assertEqual(v1 * -2, -8) - self.assertEqual(v1 * 2 ** 10, 4 * (2 ** 10)) - - def test_floor_div(self): - v1, v2, v3 = self.Integers(3, 8, 2 ** 80) - self.assertTrue(isinstance(v1 // v2, self.Integer)) - self.assertEqual(v2 // v1, 2) - self.assertEqual(v2 // 3, 2) - self.assertEqual(v2 // -3, -3) - self.assertEqual(v3 // 2 ** 79, 2) - self.assertRaises(ZeroDivisionError, lambda: v1 // 0) - - def test_remainder(self): - # Test Integer%Integer and Integer%int - v1, v2, v3 = self.Integers(23, 5, -4) - self.assertTrue(isinstance(v1 % v2, self.Integer)) - self.assertEqual(v1 % v2, 3) - self.assertEqual(v1 % 5, 3) - self.assertEqual(v3 % 5, 1) - self.assertEqual(v1 % 2 ** 10, 23) - self.assertRaises(ZeroDivisionError, lambda: v1 % 0) - self.assertRaises(ValueError, lambda: v1 % -6) - - def test_simple_exponentiation(self): - v1, v2, v3 = self.Integers(4, 3, -2) - self.assertTrue(isinstance(v1 ** v2, self.Integer)) - self.assertEqual(v1 ** v2, 64) - self.assertEqual(pow(v1, v2), 64) - self.assertEqual(v1 ** 3, 64) - self.assertEqual(pow(v1, 3), 64) - self.assertEqual(v3 ** 2, 4) - self.assertEqual(v3 ** 3, -8) - - self.assertRaises(ValueError, pow, v1, -3) - - def test_modular_exponentiation(self): - v1, v2, v3 = self.Integers(23, 5, 17) - - self.assertTrue(isinstance(pow(v1, v2, v3), self.Integer)) - self.assertEqual(pow(v1, v2, v3), 7) - self.assertEqual(pow(v1, 5, v3), 7) - self.assertEqual(pow(v1, v2, 17), 7) - self.assertEqual(pow(v1, 5, 17), 7) - self.assertEqual(pow(v1, 0, 17), 1) - self.assertEqual(pow(v1, 1, 2 ** 80), 23) - self.assertEqual(pow(v1, 2 ** 80, 89298), 17689) - - self.assertRaises(ZeroDivisionError, pow, v1, 5, 0) - self.assertRaises(ValueError, pow, v1, 5, -4) - self.assertRaises(ValueError, pow, v1, -3, 8) - - def test_inplace_exponentiation(self): - v1 = self.Integer(4) - v1.inplace_pow(2) - self.assertEqual(v1, 16) - - v1 = self.Integer(4) - v1.inplace_pow(2, 15) - self.assertEqual(v1, 1) - - def test_abs(self): - v1, v2, v3, v4, v5 = self.Integers(-2 ** 100, -2, 0, 2, 2 ** 100) - self.assertEqual(abs(v1), 2 ** 100) - self.assertEqual(abs(v2), 2) - self.assertEqual(abs(v3), 0) - self.assertEqual(abs(v4), 2) - self.assertEqual(abs(v5), 2 ** 100) - - def test_sqrt(self): - v1, v2, v3, v4 = self.Integers(-2, 0, 49, 10**100) - - self.assertRaises(ValueError, v1.sqrt) - self.assertEqual(v2.sqrt(), 0) - self.assertEqual(v3.sqrt(), 7) - self.assertEqual(v4.sqrt(), 10**50) - - def test_sqrt_module(self): - - # Invalid modulus (non positive) - self.assertRaises(ValueError, self.Integer(5).sqrt, 0) - self.assertRaises(ValueError, self.Integer(5).sqrt, -1) - - # Simple cases - assert self.Integer(0).sqrt(5) == 0 - assert self.Integer(1).sqrt(5) in (1, 4) - - # Test with all quadratic residues in several fields - for p in (11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53): - for i in range(0, p): - square = i**2 % p - res = self.Integer(square).sqrt(p) - assert res in (i, p - i) - - # 2 is a non-quadratic reside in Z_11 - self.assertRaises(ValueError, self.Integer(2).sqrt, 11) - - # 10 is not a prime - self.assertRaises(ValueError, self.Integer(4).sqrt, 10) - - # 5 is square residue of 4 and 7 - assert self.Integer(5 - 11).sqrt(11) in (4, 7) - assert self.Integer(5 + 11).sqrt(11) in (4, 7) - - def test_in_place_add(self): - v1, v2 = self.Integers(10, 20) - - v1 += v2 - self.assertEqual(v1, 30) - v1 += 10 - self.assertEqual(v1, 40) - v1 += -1 - self.assertEqual(v1, 39) - v1 += 2 ** 1000 - self.assertEqual(v1, 39 + 2 ** 1000) - - def test_in_place_sub(self): - v1, v2 = self.Integers(10, 20) - - v1 -= v2 - self.assertEqual(v1, -10) - v1 -= -100 - self.assertEqual(v1, 90) - v1 -= 90000 - self.assertEqual(v1, -89910) - v1 -= -100000 - self.assertEqual(v1, 10090) - - def test_in_place_mul(self): - v1, v2 = self.Integers(3, 5) - - v1 *= v2 - self.assertEqual(v1, 15) - v1 *= 2 - self.assertEqual(v1, 30) - v1 *= -2 - self.assertEqual(v1, -60) - v1 *= 2 ** 1000 - self.assertEqual(v1, -60 * (2 ** 1000)) - - def test_in_place_modulus(self): - v1, v2 = self.Integers(20, 7) - - v1 %= v2 - self.assertEqual(v1, 6) - v1 %= 2 ** 1000 - self.assertEqual(v1, 6) - v1 %= 2 - self.assertEqual(v1, 0) - def t(): - v3 = self.Integer(9) - v3 %= 0 - self.assertRaises(ZeroDivisionError, t) - - def test_and(self): - v1, v2, v3 = self.Integers(0xF4, 0x31, -0xF) - self.assertTrue(isinstance(v1 & v2, self.Integer)) - self.assertEqual(v1 & v2, 0x30) - self.assertEqual(v1 & 0x31, 0x30) - self.assertEqual(v1 & v3, 0xF0) - self.assertEqual(v1 & -0xF, 0xF0) - self.assertEqual(v3 & -0xF, -0xF) - self.assertEqual(v2 & (2 ** 1000 + 0x31), 0x31) - - def test_or(self): - v1, v2, v3 = self.Integers(0x40, 0x82, -0xF) - self.assertTrue(isinstance(v1 | v2, self.Integer)) - self.assertEqual(v1 | v2, 0xC2) - self.assertEqual(v1 | 0x82, 0xC2) - self.assertEqual(v2 | v3, -0xD) - self.assertEqual(v2 | 2 ** 1000, 2 ** 1000 + 0x82) - - def test_right_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - self.assertEqual(v1 >> 0, v1) - self.assertTrue(isinstance(v1 >> v2, self.Integer)) - self.assertEqual(v1 >> v2, 0x08) - self.assertEqual(v1 >> 1, 0x08) - self.assertRaises(ValueError, lambda: v1 >> -1) - self.assertEqual(v1 >> (2 ** 1000), 0) - - self.assertEqual(v3 >> 1, -0x08) - self.assertEqual(v3 >> (2 ** 1000), -1) - - def test_in_place_right_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - v1 >>= 0 - self.assertEqual(v1, 0x10) - v1 >>= 1 - self.assertEqual(v1, 0x08) - v1 >>= v2 - self.assertEqual(v1, 0x04) - v3 >>= 1 - self.assertEqual(v3, -0x08) - def l(): - v4 = self.Integer(0x90) - v4 >>= -1 - self.assertRaises(ValueError, l) - def m1(): - v4 = self.Integer(0x90) - v4 >>= 2 ** 1000 - return v4 - self.assertEqual(0, m1()) - def m2(): - v4 = self.Integer(-1) - v4 >>= 2 ** 1000 - return v4 - self.assertEqual(-1, m2()) - - def _test_left_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - self.assertEqual(v1 << 0, v1) - self.assertTrue(isinstance(v1 << v2, self.Integer)) - self.assertEqual(v1 << v2, 0x20) - self.assertEqual(v1 << 1, 0x20) - self.assertEqual(v3 << 1, -0x20) - self.assertRaises(ValueError, lambda: v1 << -1) - self.assertRaises(ValueError, lambda: v1 << (2 ** 1000)) - - def test_in_place_left_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - v1 <<= 0 - self.assertEqual(v1, 0x10) - v1 <<= 1 - self.assertEqual(v1, 0x20) - v1 <<= v2 - self.assertEqual(v1, 0x40) - v3 <<= 1 - self.assertEqual(v3, -0x20) - def l(): - v4 = self.Integer(0x90) - v4 <<= -1 - self.assertRaises(ValueError, l) - def m(): - v4 = self.Integer(0x90) - v4 <<= 2 ** 1000 - self.assertRaises(ValueError, m) - - - def test_get_bit(self): - v1, v2, v3 = self.Integers(0x102, -3, 1) - self.assertEqual(v1.get_bit(0), 0) - self.assertEqual(v1.get_bit(1), 1) - self.assertEqual(v1.get_bit(v3), 1) - self.assertEqual(v1.get_bit(8), 1) - self.assertEqual(v1.get_bit(9), 0) - - self.assertRaises(ValueError, v1.get_bit, -1) - self.assertEqual(v1.get_bit(2 ** 1000), 0) - - self.assertRaises(ValueError, v2.get_bit, -1) - self.assertRaises(ValueError, v2.get_bit, 0) - self.assertRaises(ValueError, v2.get_bit, 1) - self.assertRaises(ValueError, v2.get_bit, 2 * 1000) - - def test_odd_even(self): - v1, v2, v3, v4, v5 = self.Integers(0, 4, 17, -4, -17) - - self.assertTrue(v1.is_even()) - self.assertTrue(v2.is_even()) - self.assertFalse(v3.is_even()) - self.assertTrue(v4.is_even()) - self.assertFalse(v5.is_even()) - - self.assertFalse(v1.is_odd()) - self.assertFalse(v2.is_odd()) - self.assertTrue(v3.is_odd()) - self.assertFalse(v4.is_odd()) - self.assertTrue(v5.is_odd()) - - def test_size_in_bits(self): - v1, v2, v3, v4 = self.Integers(0, 1, 0x100, -90) - self.assertEqual(v1.size_in_bits(), 1) - self.assertEqual(v2.size_in_bits(), 1) - self.assertEqual(v3.size_in_bits(), 9) - self.assertRaises(ValueError, v4.size_in_bits) - - def test_size_in_bytes(self): - v1, v2, v3, v4, v5, v6 = self.Integers(0, 1, 0xFF, 0x1FF, 0x10000, -9) - self.assertEqual(v1.size_in_bytes(), 1) - self.assertEqual(v2.size_in_bytes(), 1) - self.assertEqual(v3.size_in_bytes(), 1) - self.assertEqual(v4.size_in_bytes(), 2) - self.assertEqual(v5.size_in_bytes(), 3) - self.assertRaises(ValueError, v6.size_in_bits) - - def test_perfect_square(self): - - self.assertFalse(self.Integer(-9).is_perfect_square()) - self.assertTrue(self.Integer(0).is_perfect_square()) - self.assertTrue(self.Integer(1).is_perfect_square()) - self.assertFalse(self.Integer(2).is_perfect_square()) - self.assertFalse(self.Integer(3).is_perfect_square()) - self.assertTrue(self.Integer(4).is_perfect_square()) - self.assertTrue(self.Integer(39*39).is_perfect_square()) - self.assertFalse(self.Integer(39*39+1).is_perfect_square()) - - for x in range(100, 1000): - self.assertFalse(self.Integer(x**2+1).is_perfect_square()) - self.assertTrue(self.Integer(x**2).is_perfect_square()) - - def test_fail_if_divisible_by(self): - v1, v2, v3 = self.Integers(12, -12, 4) - - # No failure expected - v1.fail_if_divisible_by(7) - v2.fail_if_divisible_by(7) - v2.fail_if_divisible_by(2 ** 80) - - # Failure expected - self.assertRaises(ValueError, v1.fail_if_divisible_by, 4) - self.assertRaises(ValueError, v1.fail_if_divisible_by, v3) - - def test_multiply_accumulate(self): - v1, v2, v3 = self.Integers(4, 3, 2) - v1.multiply_accumulate(v2, v3) - self.assertEqual(v1, 10) - v1.multiply_accumulate(v2, 2) - self.assertEqual(v1, 16) - v1.multiply_accumulate(3, v3) - self.assertEqual(v1, 22) - v1.multiply_accumulate(1, -2) - self.assertEqual(v1, 20) - v1.multiply_accumulate(-2, 1) - self.assertEqual(v1, 18) - v1.multiply_accumulate(1, 2 ** 1000) - self.assertEqual(v1, 18 + 2 ** 1000) - v1.multiply_accumulate(2 ** 1000, 1) - self.assertEqual(v1, 18 + 2 ** 1001) - - def test_set(self): - v1, v2 = self.Integers(3, 6) - v1.set(v2) - self.assertEqual(v1, 6) - v1.set(9) - self.assertEqual(v1, 9) - v1.set(-2) - self.assertEqual(v1, -2) - v1.set(2 ** 1000) - self.assertEqual(v1, 2 ** 1000) - - def test_inverse(self): - v1, v2, v3, v4, v5, v6 = self.Integers(2, 5, -3, 0, 723872, 3433) - - self.assertTrue(isinstance(v1.inverse(v2), self.Integer)) - self.assertEqual(v1.inverse(v2), 3) - self.assertEqual(v1.inverse(5), 3) - self.assertEqual(v3.inverse(5), 3) - self.assertEqual(v5.inverse(92929921), 58610507) - self.assertEqual(v6.inverse(9912), 5353) - - self.assertRaises(ValueError, v2.inverse, 10) - self.assertRaises(ValueError, v1.inverse, -3) - self.assertRaises(ValueError, v4.inverse, 10) - self.assertRaises(ZeroDivisionError, v2.inverse, 0) - - def test_inplace_inverse(self): - v1, v2 = self.Integers(2, 5) - - v1.inplace_inverse(v2) - self.assertEqual(v1, 3) - - def test_gcd(self): - v1, v2, v3, v4 = self.Integers(6, 10, 17, -2) - self.assertTrue(isinstance(v1.gcd(v2), self.Integer)) - self.assertEqual(v1.gcd(v2), 2) - self.assertEqual(v1.gcd(10), 2) - self.assertEqual(v1.gcd(v3), 1) - self.assertEqual(v1.gcd(-2), 2) - self.assertEqual(v4.gcd(6), 2) - - def test_lcm(self): - v1, v2, v3, v4, v5 = self.Integers(6, 10, 17, -2, 0) - self.assertTrue(isinstance(v1.lcm(v2), self.Integer)) - self.assertEqual(v1.lcm(v2), 30) - self.assertEqual(v1.lcm(10), 30) - self.assertEqual(v1.lcm(v3), 102) - self.assertEqual(v1.lcm(-2), 6) - self.assertEqual(v4.lcm(6), 6) - self.assertEqual(v1.lcm(0), 0) - self.assertEqual(v5.lcm(0), 0) - - def test_jacobi_symbol(self): - - data = ( - (1001, 1, 1), - (19, 45, 1), - (8, 21, -1), - (5, 21, 1), - (610, 987, -1), - (1001, 9907, -1), - (5, 3439601197, -1) - ) - - js = self.Integer.jacobi_symbol - - # Jacobi symbol is always 1 for k==1 or n==1 - for k in range(1, 30): - self.assertEqual(js(k, 1), 1) - for n in range(1, 30, 2): - self.assertEqual(js(1, n), 1) - - # Fail if n is not positive odd - self.assertRaises(ValueError, js, 6, -2) - self.assertRaises(ValueError, js, 6, -1) - self.assertRaises(ValueError, js, 6, 0) - self.assertRaises(ValueError, js, 0, 0) - self.assertRaises(ValueError, js, 6, 2) - self.assertRaises(ValueError, js, 6, 4) - self.assertRaises(ValueError, js, 6, 6) - self.assertRaises(ValueError, js, 6, 8) - - for tv in data: - self.assertEqual(js(tv[0], tv[1]), tv[2]) - self.assertEqual(js(self.Integer(tv[0]), tv[1]), tv[2]) - self.assertEqual(js(tv[0], self.Integer(tv[1])), tv[2]) - - def test_jacobi_symbol_wikipedia(self): - + def setUp(self): + raise NotImplementedError("To be implemented") + + def Integers(self, *arg): + return map(self.Integer, arg) + + def test_init_and_equality(self): + Integer = self.Integer + + v1 = Integer(23) + v2 = Integer(v1) + v3 = Integer(-9) + self.assertRaises(ValueError, Integer, 1.0) + + v4 = Integer(10**10) + v5 = Integer(-(10**10)) + + v6 = Integer(0xFFFF) + v7 = Integer(0xFFFFFFFF) + v8 = Integer(0xFFFFFFFFFFFFFFFF) + + self.assertEqual(v1, v1) + self.assertEqual(v1, 23) + self.assertEqual(v1, v2) + self.assertEqual(v3, -9) + self.assertEqual(v4, 10**10) + self.assertEqual(v5, -(10**10)) + self.assertEqual(v6, 0xFFFF) + self.assertEqual(v7, 0xFFFFFFFF) + self.assertEqual(v8, 0xFFFFFFFFFFFFFFFF) + + self.assertFalse(v1 == v4) + + # Init and comparison between Integer's + v6 = Integer(v1) + self.assertEqual(v1, v6) + + self.assertFalse(Integer(0) == None) + + def test_conversion_to_int(self): + v1, v2 = self.Integers(-23, 2**1000) + self.assertEqual(int(v1), -23) + self.assertEqual(int(v2), 2**1000) + + def test_equality_with_ints(self): + v1, v2, v3 = self.Integers(23, -89, 2**1000) + self.assertTrue(v1 == 23) + self.assertTrue(v2 == -89) + self.assertFalse(v1 == 24) + self.assertTrue(v3 == 2**1000) + + def test_conversion_to_str(self): + v1, v2, v3, v4 = self.Integers(20, 0, -20, 2**1000) + self.assertTrue(str(v1) == "20") + self.assertTrue(str(v2) == "0") + self.assertTrue(str(v3) == "-20") + self.assertTrue( + str(v4) + == "10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376" + ) + + def test_repr(self): + v1, v2 = self.Integers(-1, 2**80) + self.assertEqual(repr(v1), "Integer(-1)") + self.assertEqual(repr(v2), "Integer(1208925819614629174706176)") + + def test_conversion_to_bytes(self): + Integer = self.Integer + + v0 = Integer(0) + self.assertEqual(b"\x00", v0.to_bytes()) + + v1 = Integer(0x17) + self.assertEqual(b"\x17", v1.to_bytes()) + + v2 = Integer(0xFFFE) + self.assertEqual(b"\xff\xfe", v2.to_bytes()) + self.assertEqual(b"\x00\xff\xfe", v2.to_bytes(3)) + self.assertRaises(ValueError, v2.to_bytes, 1) + + self.assertEqual(b"\xfe\xff", v2.to_bytes(byteorder="little")) + self.assertEqual(b"\xfe\xff\x00", v2.to_bytes(3, byteorder="little")) + + v3 = Integer(0xFF00AABBCCDDEE1122) + self.assertEqual(b"\xff\x00\xaa\xbb\xcc\xdd\xee\x11\x22", v3.to_bytes()) + self.assertEqual( + b"\x22\x11\xee\xdd\xcc\xbb\xaa\x00\xff", + v3.to_bytes(byteorder="little"), + ) + self.assertEqual( + b"\x00\xff\x00\xaa\xbb\xcc\xdd\xee\x11\x22", + v3.to_bytes(10), + ) + self.assertEqual( + b"\x22\x11\xee\xdd\xcc\xbb\xaa\x00\xff\x00", + v3.to_bytes(10, byteorder="little"), + ) + self.assertRaises(ValueError, v3.to_bytes, 8) + + v4 = Integer(-90) + self.assertRaises(ValueError, v4.to_bytes) + self.assertRaises(ValueError, v4.to_bytes, byteorder="bittle") + + def test_conversion_from_bytes(self): + Integer = self.Integer + + v1 = Integer.from_bytes(b"\x00") + self.assertTrue(isinstance(v1, Integer)) + self.assertEqual(0, v1) + + v2 = Integer.from_bytes(b"\x00\x01") + self.assertEqual(1, v2) + + v3 = Integer.from_bytes(b"\xff\xff") + self.assertEqual(0xFFFF, v3) + + v4 = Integer.from_bytes(b"\x00\x01", "big") + self.assertEqual(1, v4) + + v5 = Integer.from_bytes(b"\x00\x01", byteorder="big") + self.assertEqual(1, v5) + + v6 = Integer.from_bytes(b"\x00\x01", byteorder="little") + self.assertEqual(0x0100, v6) + + self.assertRaises(ValueError, Integer.from_bytes, b"\x09", "bittle") + + def test_inequality(self): + # Test Integer!=Integer and Integer!=int + v1, v2, v3, v4 = self.Integers(89, 89, 90, -8) + self.assertTrue(v1 != v3) + self.assertTrue(v1 != 90) + self.assertFalse(v1 != v2) + self.assertFalse(v1 != 89) + self.assertTrue(v1 != v4) + self.assertTrue(v4 != v1) + self.assertTrue(self.Integer(0) != None) + + def test_less_than(self): + # Test IntegerInteger and Integer>int + v1, v2, v3, v4, v5 = self.Integers(13, 13, 14, -8, 2**10) + self.assertTrue(v3 > v1) + self.assertTrue(v3 > 13) + self.assertFalse(v1 > v1) + self.assertFalse(v1 > v2) + self.assertFalse(v1 > 13) + self.assertTrue(v1 > v4) + self.assertFalse(v4 > v1) + self.assertTrue(v5 > v1) + self.assertFalse(v1 > v5) + + def test_more_than_or_equal(self): + # Test Integer>=Integer and Integer>=int + v1, v2, v3, v4 = self.Integers(13, 13, 14, -4) + self.assertTrue(v3 >= v1) + self.assertTrue(v3 >= 13) + self.assertTrue(v1 >= v2) + self.assertTrue(v1 >= v1) + self.assertTrue(v1 >= 13) + self.assertFalse(v4 >= v1) + + def test_bool(self): + v1, v2, v3, v4 = self.Integers(0, 10, -9, 2**10) + self.assertFalse(v1) + self.assertFalse(bool(v1)) + self.assertTrue(v2) + self.assertTrue(bool(v2)) + self.assertTrue(v3) + self.assertTrue(v4) + + def test_is_negative(self): + v1, v2, v3, v4, v5 = self.Integers(-(3**100), -3, 0, 3, 3**100) + self.assertTrue(v1.is_negative()) + self.assertTrue(v2.is_negative()) + self.assertFalse(v4.is_negative()) + self.assertFalse(v5.is_negative()) + + def test_addition(self): + # Test Integer+Integer and Integer+int + v1, v2, v3 = self.Integers(7, 90, -7) + self.assertTrue(isinstance(v1 + v2, self.Integer)) + self.assertEqual(v1 + v2, 97) + self.assertEqual(v1 + 90, 97) + self.assertEqual(v1 + v3, 0) + self.assertEqual(v1 + (-7), 0) + self.assertEqual(v1 + 2**10, 2**10 + 7) + + def test_subtraction(self): + # Test Integer-Integer and Integer-int + v1, v2, v3 = self.Integers(7, 90, -7) + self.assertTrue(isinstance(v1 - v2, self.Integer)) + self.assertEqual(v2 - v1, 83) + self.assertEqual(v2 - 7, 83) + self.assertEqual(v2 - v3, 97) + self.assertEqual(v1 - (-7), 14) + self.assertEqual(v1 - 2**10, 7 - 2**10) + + def test_multiplication(self): + # Test Integer-Integer and Integer-int + v1, v2, v3, v4 = self.Integers(4, 5, -2, 2**10) + self.assertTrue(isinstance(v1 * v2, self.Integer)) + self.assertEqual(v1 * v2, 20) + self.assertEqual(v1 * 5, 20) + self.assertEqual(v1 * -2, -8) + self.assertEqual(v1 * 2**10, 4 * (2**10)) + + def test_floor_div(self): + v1, v2, v3 = self.Integers(3, 8, 2**80) + self.assertTrue(isinstance(v1 // v2, self.Integer)) + self.assertEqual(v2 // v1, 2) + self.assertEqual(v2 // 3, 2) + self.assertEqual(v2 // -3, -3) + self.assertEqual(v3 // 2**79, 2) + self.assertRaises(ZeroDivisionError, lambda: v1 // 0) + + def test_remainder(self): + # Test Integer%Integer and Integer%int + v1, v2, v3 = self.Integers(23, 5, -4) + self.assertTrue(isinstance(v1 % v2, self.Integer)) + self.assertEqual(v1 % v2, 3) + self.assertEqual(v1 % 5, 3) + self.assertEqual(v3 % 5, 1) + self.assertEqual(v1 % 2**10, 23) + self.assertRaises(ZeroDivisionError, lambda: v1 % 0) + self.assertRaises(ValueError, lambda: v1 % -6) + + def test_simple_exponentiation(self): + v1, v2, v3 = self.Integers(4, 3, -2) + self.assertTrue(isinstance(v1**v2, self.Integer)) + self.assertEqual(v1**v2, 64) + self.assertEqual(pow(v1, v2), 64) + self.assertEqual(v1**3, 64) + self.assertEqual(pow(v1, 3), 64) + self.assertEqual(v3**2, 4) + self.assertEqual(v3**3, -8) + + self.assertRaises(ValueError, pow, v1, -3) + + def test_modular_exponentiation(self): + v1, v2, v3 = self.Integers(23, 5, 17) + + self.assertTrue(isinstance(pow(v1, v2, v3), self.Integer)) + self.assertEqual(pow(v1, v2, v3), 7) + self.assertEqual(pow(v1, 5, v3), 7) + self.assertEqual(pow(v1, v2, 17), 7) + self.assertEqual(pow(v1, 5, 17), 7) + self.assertEqual(pow(v1, 0, 17), 1) + self.assertEqual(pow(v1, 1, 2**80), 23) + self.assertEqual(pow(v1, 2**80, 89298), 17689) + + self.assertRaises(ZeroDivisionError, pow, v1, 5, 0) + self.assertRaises(ValueError, pow, v1, 5, -4) + self.assertRaises(ValueError, pow, v1, -3, 8) + + def test_inplace_exponentiation(self): + v1 = self.Integer(4) + v1.inplace_pow(2) + self.assertEqual(v1, 16) + + v1 = self.Integer(4) + v1.inplace_pow(2, 15) + self.assertEqual(v1, 1) + + def test_abs(self): + v1, v2, v3, v4, v5 = self.Integers(-(2**100), -2, 0, 2, 2**100) + self.assertEqual(abs(v1), 2**100) + self.assertEqual(abs(v2), 2) + self.assertEqual(abs(v3), 0) + self.assertEqual(abs(v4), 2) + self.assertEqual(abs(v5), 2**100) + + def test_sqrt(self): + v1, v2, v3, v4 = self.Integers(-2, 0, 49, 10**100) + + self.assertRaises(ValueError, v1.sqrt) + self.assertEqual(v2.sqrt(), 0) + self.assertEqual(v3.sqrt(), 7) + self.assertEqual(v4.sqrt(), 10**50) + + def test_sqrt_module(self): + # Invalid modulus (non positive) + self.assertRaises(ValueError, self.Integer(5).sqrt, 0) + self.assertRaises(ValueError, self.Integer(5).sqrt, -1) + + # Simple cases + assert self.Integer(0).sqrt(5) == 0 + assert self.Integer(1).sqrt(5) in (1, 4) + + # Test with all quadratic residues in several fields + for p in (11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53): + for i in range(0, p): + square = i**2 % p + res = self.Integer(square).sqrt(p) + assert res in (i, p - i) + + # 2 is a non-quadratic reside in Z_11 + self.assertRaises(ValueError, self.Integer(2).sqrt, 11) + + # 10 is not a prime + self.assertRaises(ValueError, self.Integer(4).sqrt, 10) + + # 5 is square residue of 4 and 7 + assert self.Integer(5 - 11).sqrt(11) in (4, 7) + assert self.Integer(5 + 11).sqrt(11) in (4, 7) + + def test_in_place_add(self): + v1, v2 = self.Integers(10, 20) + + v1 += v2 + self.assertEqual(v1, 30) + v1 += 10 + self.assertEqual(v1, 40) + v1 += -1 + self.assertEqual(v1, 39) + v1 += 2**1000 + self.assertEqual(v1, 39 + 2**1000) + + def test_in_place_sub(self): + v1, v2 = self.Integers(10, 20) + + v1 -= v2 + self.assertEqual(v1, -10) + v1 -= -100 + self.assertEqual(v1, 90) + v1 -= 90000 + self.assertEqual(v1, -89910) + v1 -= -100000 + self.assertEqual(v1, 10090) + + def test_in_place_mul(self): + v1, v2 = self.Integers(3, 5) + + v1 *= v2 + self.assertEqual(v1, 15) + v1 *= 2 + self.assertEqual(v1, 30) + v1 *= -2 + self.assertEqual(v1, -60) + v1 *= 2**1000 + self.assertEqual(v1, -60 * (2**1000)) + + def test_in_place_modulus(self): + v1, v2 = self.Integers(20, 7) + + v1 %= v2 + self.assertEqual(v1, 6) + v1 %= 2**1000 + self.assertEqual(v1, 6) + v1 %= 2 + self.assertEqual(v1, 0) + + def t(): + v3 = self.Integer(9) + v3 %= 0 + + self.assertRaises(ZeroDivisionError, t) + + def test_and(self): + v1, v2, v3 = self.Integers(0xF4, 0x31, -0xF) + self.assertTrue(isinstance(v1 & v2, self.Integer)) + self.assertEqual(v1 & v2, 0x30) + self.assertEqual(v1 & 0x31, 0x30) + self.assertEqual(v1 & v3, 0xF0) + self.assertEqual(v1 & -0xF, 0xF0) + self.assertEqual(v3 & -0xF, -0xF) + self.assertEqual(v2 & (2**1000 + 0x31), 0x31) + + def test_or(self): + v1, v2, v3 = self.Integers(0x40, 0x82, -0xF) + self.assertTrue(isinstance(v1 | v2, self.Integer)) + self.assertEqual(v1 | v2, 0xC2) + self.assertEqual(v1 | 0x82, 0xC2) + self.assertEqual(v2 | v3, -0xD) + self.assertEqual(v2 | 2**1000, 2**1000 + 0x82) + + def test_right_shift(self): + v1, v2, v3 = self.Integers(0x10, 1, -0x10) + self.assertEqual(v1 >> 0, v1) + self.assertTrue(isinstance(v1 >> v2, self.Integer)) + self.assertEqual(v1 >> v2, 0x08) + self.assertEqual(v1 >> 1, 0x08) + self.assertRaises(ValueError, lambda: v1 >> -1) + self.assertEqual(v1 >> (2**1000), 0) + + self.assertEqual(v3 >> 1, -0x08) + self.assertEqual(v3 >> (2**1000), -1) + + def test_in_place_right_shift(self): + v1, v2, v3 = self.Integers(0x10, 1, -0x10) + v1 >>= 0 + self.assertEqual(v1, 0x10) + v1 >>= 1 + self.assertEqual(v1, 0x08) + v1 >>= v2 + self.assertEqual(v1, 0x04) + v3 >>= 1 + self.assertEqual(v3, -0x08) + + def l(): + v4 = self.Integer(0x90) + v4 >>= -1 + + self.assertRaises(ValueError, l) + + def m1(): + v4 = self.Integer(0x90) + v4 >>= 2**1000 + return v4 + + self.assertEqual(0, m1()) + + def m2(): + v4 = self.Integer(-1) + v4 >>= 2**1000 + return v4 + + self.assertEqual(-1, m2()) + + def _test_left_shift(self): + v1, v2, v3 = self.Integers(0x10, 1, -0x10) + self.assertEqual(v1 << 0, v1) + self.assertTrue(isinstance(v1 << v2, self.Integer)) + self.assertEqual(v1 << v2, 0x20) + self.assertEqual(v1 << 1, 0x20) + self.assertEqual(v3 << 1, -0x20) + self.assertRaises(ValueError, lambda: v1 << -1) + self.assertRaises(ValueError, lambda: v1 << (2**1000)) + + def test_in_place_left_shift(self): + v1, v2, v3 = self.Integers(0x10, 1, -0x10) + v1 <<= 0 + self.assertEqual(v1, 0x10) + v1 <<= 1 + self.assertEqual(v1, 0x20) + v1 <<= v2 + self.assertEqual(v1, 0x40) + v3 <<= 1 + self.assertEqual(v3, -0x20) + + def l(): + v4 = self.Integer(0x90) + v4 <<= -1 + + self.assertRaises(ValueError, l) + + def m(): + v4 = self.Integer(0x90) + v4 <<= 2**1000 + + self.assertRaises(ValueError, m) + + def test_get_bit(self): + v1, v2, v3 = self.Integers(0x102, -3, 1) + self.assertEqual(v1.get_bit(0), 0) + self.assertEqual(v1.get_bit(1), 1) + self.assertEqual(v1.get_bit(v3), 1) + self.assertEqual(v1.get_bit(8), 1) + self.assertEqual(v1.get_bit(9), 0) + + self.assertRaises(ValueError, v1.get_bit, -1) + self.assertEqual(v1.get_bit(2**1000), 0) + + self.assertRaises(ValueError, v2.get_bit, -1) + self.assertRaises(ValueError, v2.get_bit, 0) + self.assertRaises(ValueError, v2.get_bit, 1) + self.assertRaises(ValueError, v2.get_bit, 2 * 1000) + + def test_odd_even(self): + v1, v2, v3, v4, v5 = self.Integers(0, 4, 17, -4, -17) + + self.assertTrue(v1.is_even()) + self.assertTrue(v2.is_even()) + self.assertFalse(v3.is_even()) + self.assertTrue(v4.is_even()) + self.assertFalse(v5.is_even()) + + self.assertFalse(v1.is_odd()) + self.assertFalse(v2.is_odd()) + self.assertTrue(v3.is_odd()) + self.assertFalse(v4.is_odd()) + self.assertTrue(v5.is_odd()) + + def test_size_in_bits(self): + v1, v2, v3, v4 = self.Integers(0, 1, 0x100, -90) + self.assertEqual(v1.size_in_bits(), 1) + self.assertEqual(v2.size_in_bits(), 1) + self.assertEqual(v3.size_in_bits(), 9) + self.assertRaises(ValueError, v4.size_in_bits) + + def test_size_in_bytes(self): + v1, v2, v3, v4, v5, v6 = self.Integers(0, 1, 0xFF, 0x1FF, 0x10000, -9) + self.assertEqual(v1.size_in_bytes(), 1) + self.assertEqual(v2.size_in_bytes(), 1) + self.assertEqual(v3.size_in_bytes(), 1) + self.assertEqual(v4.size_in_bytes(), 2) + self.assertEqual(v5.size_in_bytes(), 3) + self.assertRaises(ValueError, v6.size_in_bits) + + def test_perfect_square(self): + self.assertFalse(self.Integer(-9).is_perfect_square()) + self.assertTrue(self.Integer(0).is_perfect_square()) + self.assertTrue(self.Integer(1).is_perfect_square()) + self.assertFalse(self.Integer(2).is_perfect_square()) + self.assertFalse(self.Integer(3).is_perfect_square()) + self.assertTrue(self.Integer(4).is_perfect_square()) + self.assertTrue(self.Integer(39 * 39).is_perfect_square()) + self.assertFalse(self.Integer(39 * 39 + 1).is_perfect_square()) + + for x in range(100, 1000): + self.assertFalse(self.Integer(x**2 + 1).is_perfect_square()) + self.assertTrue(self.Integer(x**2).is_perfect_square()) + + def test_fail_if_divisible_by(self): + v1, v2, v3 = self.Integers(12, -12, 4) + + # No failure expected + v1.fail_if_divisible_by(7) + v2.fail_if_divisible_by(7) + v2.fail_if_divisible_by(2**80) + + # Failure expected + self.assertRaises(ValueError, v1.fail_if_divisible_by, 4) + self.assertRaises(ValueError, v1.fail_if_divisible_by, v3) + + def test_multiply_accumulate(self): + v1, v2, v3 = self.Integers(4, 3, 2) + v1.multiply_accumulate(v2, v3) + self.assertEqual(v1, 10) + v1.multiply_accumulate(v2, 2) + self.assertEqual(v1, 16) + v1.multiply_accumulate(3, v3) + self.assertEqual(v1, 22) + v1.multiply_accumulate(1, -2) + self.assertEqual(v1, 20) + v1.multiply_accumulate(-2, 1) + self.assertEqual(v1, 18) + v1.multiply_accumulate(1, 2**1000) + self.assertEqual(v1, 18 + 2**1000) + v1.multiply_accumulate(2**1000, 1) + self.assertEqual(v1, 18 + 2**1001) + + def test_set(self): + v1, v2 = self.Integers(3, 6) + v1.set(v2) + self.assertEqual(v1, 6) + v1.set(9) + self.assertEqual(v1, 9) + v1.set(-2) + self.assertEqual(v1, -2) + v1.set(2**1000) + self.assertEqual(v1, 2**1000) + + def test_inverse(self): + v1, v2, v3, v4, v5, v6 = self.Integers(2, 5, -3, 0, 723872, 3433) + + self.assertTrue(isinstance(v1.inverse(v2), self.Integer)) + self.assertEqual(v1.inverse(v2), 3) + self.assertEqual(v1.inverse(5), 3) + self.assertEqual(v3.inverse(5), 3) + self.assertEqual(v5.inverse(92929921), 58610507) + self.assertEqual(v6.inverse(9912), 5353) + + self.assertRaises(ValueError, v2.inverse, 10) + self.assertRaises(ValueError, v1.inverse, -3) + self.assertRaises(ValueError, v4.inverse, 10) + self.assertRaises(ZeroDivisionError, v2.inverse, 0) + + def test_inplace_inverse(self): + v1, v2 = self.Integers(2, 5) + + v1.inplace_inverse(v2) + self.assertEqual(v1, 3) + + def test_gcd(self): + v1, v2, v3, v4 = self.Integers(6, 10, 17, -2) + self.assertTrue(isinstance(v1.gcd(v2), self.Integer)) + self.assertEqual(v1.gcd(v2), 2) + self.assertEqual(v1.gcd(10), 2) + self.assertEqual(v1.gcd(v3), 1) + self.assertEqual(v1.gcd(-2), 2) + self.assertEqual(v4.gcd(6), 2) + + def test_lcm(self): + v1, v2, v3, v4, v5 = self.Integers(6, 10, 17, -2, 0) + self.assertTrue(isinstance(v1.lcm(v2), self.Integer)) + self.assertEqual(v1.lcm(v2), 30) + self.assertEqual(v1.lcm(10), 30) + self.assertEqual(v1.lcm(v3), 102) + self.assertEqual(v1.lcm(-2), 6) + self.assertEqual(v4.lcm(6), 6) + self.assertEqual(v1.lcm(0), 0) + self.assertEqual(v5.lcm(0), 0) + + def test_jacobi_symbol(self): + data = ( + (1001, 1, 1), + (19, 45, 1), + (8, 21, -1), + (5, 21, 1), + (610, 987, -1), + (1001, 9907, -1), + (5, 3439601197, -1), + ) + + js = self.Integer.jacobi_symbol + + # Jacobi symbol is always 1 for k==1 or n==1 + for k in range(1, 30): + self.assertEqual(js(k, 1), 1) + for n in range(1, 30, 2): + self.assertEqual(js(1, n), 1) + + # Fail if n is not positive odd + self.assertRaises(ValueError, js, 6, -2) + self.assertRaises(ValueError, js, 6, -1) + self.assertRaises(ValueError, js, 6, 0) + self.assertRaises(ValueError, js, 0, 0) + self.assertRaises(ValueError, js, 6, 2) + self.assertRaises(ValueError, js, 6, 4) + self.assertRaises(ValueError, js, 6, 6) + self.assertRaises(ValueError, js, 6, 8) + + for tv in data: + self.assertEqual(js(tv[0], tv[1]), tv[2]) + self.assertEqual(js(self.Integer(tv[0]), tv[1]), tv[2]) + self.assertEqual(js(tv[0], self.Integer(tv[1])), tv[2]) + + def test_jacobi_symbol_wikipedia(self): # Test vectors from https://en.wikipedia.org/wiki/Jacobi_symbol - tv = [ - (3, [(1, 1), (2, -1), (3, 0), (4, 1), (5, -1), (6, 0), (7, 1), (8, -1), (9, 0), (10, 1), (11, -1), (12, 0), (13, 1), (14, -1), (15, 0), (16, 1), (17, -1), (18, 0), (19, 1), (20, -1), (21, 0), (22, 1), (23, -1), (24, 0), (25, 1), (26, -1), (27, 0), (28, 1), (29, -1), (30, 0)]), - (5, [(1, 1), (2, -1), (3, -1), (4, 1), (5, 0), (6, 1), (7, -1), (8, -1), (9, 1), (10, 0), (11, 1), (12, -1), (13, -1), (14, 1), (15, 0), (16, 1), (17, -1), (18, -1), (19, 1), (20, 0), (21, 1), (22, -1), (23, -1), (24, 1), (25, 0), (26, 1), (27, -1), (28, -1), (29, 1), (30, 0)]), - (7, [(1, 1), (2, 1), (3, -1), (4, 1), (5, -1), (6, -1), (7, 0), (8, 1), (9, 1), (10, -1), (11, 1), (12, -1), (13, -1), (14, 0), (15, 1), (16, 1), (17, -1), (18, 1), (19, -1), (20, -1), (21, 0), (22, 1), (23, 1), (24, -1), (25, 1), (26, -1), (27, -1), (28, 0), (29, 1), (30, 1)]), - (9, [(1, 1), (2, 1), (3, 0), (4, 1), (5, 1), (6, 0), (7, 1), (8, 1), (9, 0), (10, 1), (11, 1), (12, 0), (13, 1), (14, 1), (15, 0), (16, 1), (17, 1), (18, 0), (19, 1), (20, 1), (21, 0), (22, 1), (23, 1), (24, 0), (25, 1), (26, 1), (27, 0), (28, 1), (29, 1), (30, 0)]), - (11, [(1, 1), (2, -1), (3, 1), (4, 1), (5, 1), (6, -1), (7, -1), (8, -1), (9, 1), (10, -1), (11, 0), (12, 1), (13, -1), (14, 1), (15, 1), (16, 1), (17, -1), (18, -1), (19, -1), (20, 1), (21, -1), (22, 0), (23, 1), (24, -1), (25, 1), (26, 1), (27, 1), (28, -1), (29, -1), (30, -1)]), - (13, [(1, 1), (2, -1), (3, 1), (4, 1), (5, -1), (6, -1), (7, -1), (8, -1), (9, 1), (10, 1), (11, -1), (12, 1), (13, 0), (14, 1), (15, -1), (16, 1), (17, 1), (18, -1), (19, -1), (20, -1), (21, -1), (22, 1), (23, 1), (24, -1), (25, 1), (26, 0), (27, 1), (28, -1), (29, 1), (30, 1)]), - (15, [(1, 1), (2, 1), (3, 0), (4, 1), (5, 0), (6, 0), (7, -1), (8, 1), (9, 0), (10, 0), (11, -1), (12, 0), (13, -1), (14, -1), (15, 0), (16, 1), (17, 1), (18, 0), (19, 1), (20, 0), (21, 0), (22, -1), (23, 1), (24, 0), (25, 0), (26, -1), (27, 0), (28, -1), (29, -1), (30, 0)]), - (17, [(1, 1), (2, 1), (3, -1), (4, 1), (5, -1), (6, -1), (7, -1), (8, 1), (9, 1), (10, -1), (11, -1), (12, -1), (13, 1), (14, -1), (15, 1), (16, 1), (17, 0), (18, 1), (19, 1), (20, -1), (21, 1), (22, -1), (23, -1), (24, -1), (25, 1), (26, 1), (27, -1), (28, -1), (29, -1), (30, 1)]), - (19, [(1, 1), (2, -1), (3, -1), (4, 1), (5, 1), (6, 1), (7, 1), (8, -1), (9, 1), (10, -1), (11, 1), (12, -1), (13, -1), (14, -1), (15, -1), (16, 1), (17, 1), (18, -1), (19, 0), (20, 1), (21, -1), (22, -1), (23, 1), (24, 1), (25, 1), (26, 1), (27, -1), (28, 1), (29, -1), (30, 1)]), - (21, [(1, 1), (2, -1), (3, 0), (4, 1), (5, 1), (6, 0), (7, 0), (8, -1), (9, 0), (10, -1), (11, -1), (12, 0), (13, -1), (14, 0), (15, 0), (16, 1), (17, 1), (18, 0), (19, -1), (20, 1), (21, 0), (22, 1), (23, -1), (24, 0), (25, 1), (26, 1), (27, 0), (28, 0), (29, -1), (30, 0)]), - (23, [(1, 1), (2, 1), (3, 1), (4, 1), (5, -1), (6, 1), (7, -1), (8, 1), (9, 1), (10, -1), (11, -1), (12, 1), (13, 1), (14, -1), (15, -1), (16, 1), (17, -1), (18, 1), (19, -1), (20, -1), (21, -1), (22, -1), (23, 0), (24, 1), (25, 1), (26, 1), (27, 1), (28, -1), (29, 1), (30, -1)]), - (25, [(1, 1), (2, 1), (3, 1), (4, 1), (5, 0), (6, 1), (7, 1), (8, 1), (9, 1), (10, 0), (11, 1), (12, 1), (13, 1), (14, 1), (15, 0), (16, 1), (17, 1), (18, 1), (19, 1), (20, 0), (21, 1), (22, 1), (23, 1), (24, 1), (25, 0), (26, 1), (27, 1), (28, 1), (29, 1), (30, 0)]), - (27, [(1, 1), (2, -1), (3, 0), (4, 1), (5, -1), (6, 0), (7, 1), (8, -1), (9, 0), (10, 1), (11, -1), (12, 0), (13, 1), (14, -1), (15, 0), (16, 1), (17, -1), (18, 0), (19, 1), (20, -1), (21, 0), (22, 1), (23, -1), (24, 0), (25, 1), (26, -1), (27, 0), (28, 1), (29, -1), (30, 0)]), - (29, [(1, 1), (2, -1), (3, -1), (4, 1), (5, 1), (6, 1), (7, 1), (8, -1), (9, 1), (10, -1), (11, -1), (12, -1), (13, 1), (14, -1), (15, -1), (16, 1), (17, -1), (18, -1), (19, -1), (20, 1), (21, -1), (22, 1), (23, 1), (24, 1), (25, 1), (26, -1), (27, -1), (28, 1), (29, 0), (30, 1)]), - ] - - js = self.Integer.jacobi_symbol - - for n, kj in tv: - for k, j in kj: - self.assertEqual(js(k, n), j) - - def test_hex(self): - v1, = self.Integers(0x10) - self.assertEqual(hex(v1), "0x10") - - def test_mult_modulo_bytes(self): - modmult = self.Integer._mult_modulo_bytes - - res = modmult(4, 5, 19) - self.assertEqual(res, b'\x01') - - res = modmult(4 - 19, 5, 19) - self.assertEqual(res, b'\x01') - - res = modmult(4, 5 - 19, 19) - self.assertEqual(res, b'\x01') - - res = modmult(4 + 19, 5, 19) - self.assertEqual(res, b'\x01') - - res = modmult(4, 5 + 19, 19) - self.assertEqual(res, b'\x01') - - modulus = 2**512 - 1 # 64 bytes - t1 = 13**100 - t2 = 17**100 - expect = b"\xfa\xb2\x11\x87\xc3(y\x07\xf8\xf1n\xdepq\x0b\xca\xf3\xd3B,\xef\xf2\xfbf\xcc)\x8dZ*\x95\x98r\x96\xa8\xd5\xc3}\xe2q:\xa2'z\xf48\xde%\xef\t\x07\xbc\xc4[C\x8bUE2\x90\xef\x81\xaa:\x08" - self.assertEqual(expect, modmult(t1, t2, modulus)) - - self.assertRaises(ZeroDivisionError, modmult, 4, 5, 0) - self.assertRaises(ValueError, modmult, 4, 5, -1) - self.assertRaises(ValueError, modmult, 4, 5, 4) + tv = [ + ( + 3, + [ + (1, 1), + (2, -1), + (3, 0), + (4, 1), + (5, -1), + (6, 0), + (7, 1), + (8, -1), + (9, 0), + (10, 1), + (11, -1), + (12, 0), + (13, 1), + (14, -1), + (15, 0), + (16, 1), + (17, -1), + (18, 0), + (19, 1), + (20, -1), + (21, 0), + (22, 1), + (23, -1), + (24, 0), + (25, 1), + (26, -1), + (27, 0), + (28, 1), + (29, -1), + (30, 0), + ], + ), + ( + 5, + [ + (1, 1), + (2, -1), + (3, -1), + (4, 1), + (5, 0), + (6, 1), + (7, -1), + (8, -1), + (9, 1), + (10, 0), + (11, 1), + (12, -1), + (13, -1), + (14, 1), + (15, 0), + (16, 1), + (17, -1), + (18, -1), + (19, 1), + (20, 0), + (21, 1), + (22, -1), + (23, -1), + (24, 1), + (25, 0), + (26, 1), + (27, -1), + (28, -1), + (29, 1), + (30, 0), + ], + ), + ( + 7, + [ + (1, 1), + (2, 1), + (3, -1), + (4, 1), + (5, -1), + (6, -1), + (7, 0), + (8, 1), + (9, 1), + (10, -1), + (11, 1), + (12, -1), + (13, -1), + (14, 0), + (15, 1), + (16, 1), + (17, -1), + (18, 1), + (19, -1), + (20, -1), + (21, 0), + (22, 1), + (23, 1), + (24, -1), + (25, 1), + (26, -1), + (27, -1), + (28, 0), + (29, 1), + (30, 1), + ], + ), + ( + 9, + [ + (1, 1), + (2, 1), + (3, 0), + (4, 1), + (5, 1), + (6, 0), + (7, 1), + (8, 1), + (9, 0), + (10, 1), + (11, 1), + (12, 0), + (13, 1), + (14, 1), + (15, 0), + (16, 1), + (17, 1), + (18, 0), + (19, 1), + (20, 1), + (21, 0), + (22, 1), + (23, 1), + (24, 0), + (25, 1), + (26, 1), + (27, 0), + (28, 1), + (29, 1), + (30, 0), + ], + ), + ( + 11, + [ + (1, 1), + (2, -1), + (3, 1), + (4, 1), + (5, 1), + (6, -1), + (7, -1), + (8, -1), + (9, 1), + (10, -1), + (11, 0), + (12, 1), + (13, -1), + (14, 1), + (15, 1), + (16, 1), + (17, -1), + (18, -1), + (19, -1), + (20, 1), + (21, -1), + (22, 0), + (23, 1), + (24, -1), + (25, 1), + (26, 1), + (27, 1), + (28, -1), + (29, -1), + (30, -1), + ], + ), + ( + 13, + [ + (1, 1), + (2, -1), + (3, 1), + (4, 1), + (5, -1), + (6, -1), + (7, -1), + (8, -1), + (9, 1), + (10, 1), + (11, -1), + (12, 1), + (13, 0), + (14, 1), + (15, -1), + (16, 1), + (17, 1), + (18, -1), + (19, -1), + (20, -1), + (21, -1), + (22, 1), + (23, 1), + (24, -1), + (25, 1), + (26, 0), + (27, 1), + (28, -1), + (29, 1), + (30, 1), + ], + ), + ( + 15, + [ + (1, 1), + (2, 1), + (3, 0), + (4, 1), + (5, 0), + (6, 0), + (7, -1), + (8, 1), + (9, 0), + (10, 0), + (11, -1), + (12, 0), + (13, -1), + (14, -1), + (15, 0), + (16, 1), + (17, 1), + (18, 0), + (19, 1), + (20, 0), + (21, 0), + (22, -1), + (23, 1), + (24, 0), + (25, 0), + (26, -1), + (27, 0), + (28, -1), + (29, -1), + (30, 0), + ], + ), + ( + 17, + [ + (1, 1), + (2, 1), + (3, -1), + (4, 1), + (5, -1), + (6, -1), + (7, -1), + (8, 1), + (9, 1), + (10, -1), + (11, -1), + (12, -1), + (13, 1), + (14, -1), + (15, 1), + (16, 1), + (17, 0), + (18, 1), + (19, 1), + (20, -1), + (21, 1), + (22, -1), + (23, -1), + (24, -1), + (25, 1), + (26, 1), + (27, -1), + (28, -1), + (29, -1), + (30, 1), + ], + ), + ( + 19, + [ + (1, 1), + (2, -1), + (3, -1), + (4, 1), + (5, 1), + (6, 1), + (7, 1), + (8, -1), + (9, 1), + (10, -1), + (11, 1), + (12, -1), + (13, -1), + (14, -1), + (15, -1), + (16, 1), + (17, 1), + (18, -1), + (19, 0), + (20, 1), + (21, -1), + (22, -1), + (23, 1), + (24, 1), + (25, 1), + (26, 1), + (27, -1), + (28, 1), + (29, -1), + (30, 1), + ], + ), + ( + 21, + [ + (1, 1), + (2, -1), + (3, 0), + (4, 1), + (5, 1), + (6, 0), + (7, 0), + (8, -1), + (9, 0), + (10, -1), + (11, -1), + (12, 0), + (13, -1), + (14, 0), + (15, 0), + (16, 1), + (17, 1), + (18, 0), + (19, -1), + (20, 1), + (21, 0), + (22, 1), + (23, -1), + (24, 0), + (25, 1), + (26, 1), + (27, 0), + (28, 0), + (29, -1), + (30, 0), + ], + ), + ( + 23, + [ + (1, 1), + (2, 1), + (3, 1), + (4, 1), + (5, -1), + (6, 1), + (7, -1), + (8, 1), + (9, 1), + (10, -1), + (11, -1), + (12, 1), + (13, 1), + (14, -1), + (15, -1), + (16, 1), + (17, -1), + (18, 1), + (19, -1), + (20, -1), + (21, -1), + (22, -1), + (23, 0), + (24, 1), + (25, 1), + (26, 1), + (27, 1), + (28, -1), + (29, 1), + (30, -1), + ], + ), + ( + 25, + [ + (1, 1), + (2, 1), + (3, 1), + (4, 1), + (5, 0), + (6, 1), + (7, 1), + (8, 1), + (9, 1), + (10, 0), + (11, 1), + (12, 1), + (13, 1), + (14, 1), + (15, 0), + (16, 1), + (17, 1), + (18, 1), + (19, 1), + (20, 0), + (21, 1), + (22, 1), + (23, 1), + (24, 1), + (25, 0), + (26, 1), + (27, 1), + (28, 1), + (29, 1), + (30, 0), + ], + ), + ( + 27, + [ + (1, 1), + (2, -1), + (3, 0), + (4, 1), + (5, -1), + (6, 0), + (7, 1), + (8, -1), + (9, 0), + (10, 1), + (11, -1), + (12, 0), + (13, 1), + (14, -1), + (15, 0), + (16, 1), + (17, -1), + (18, 0), + (19, 1), + (20, -1), + (21, 0), + (22, 1), + (23, -1), + (24, 0), + (25, 1), + (26, -1), + (27, 0), + (28, 1), + (29, -1), + (30, 0), + ], + ), + ( + 29, + [ + (1, 1), + (2, -1), + (3, -1), + (4, 1), + (5, 1), + (6, 1), + (7, 1), + (8, -1), + (9, 1), + (10, -1), + (11, -1), + (12, -1), + (13, 1), + (14, -1), + (15, -1), + (16, 1), + (17, -1), + (18, -1), + (19, -1), + (20, 1), + (21, -1), + (22, 1), + (23, 1), + (24, 1), + (25, 1), + (26, -1), + (27, -1), + (28, 1), + (29, 0), + (30, 1), + ], + ), + ] + + js = self.Integer.jacobi_symbol + + for n, kj in tv: + for k, j in kj: + self.assertEqual(js(k, n), j) + + def test_hex(self): + (v1,) = self.Integers(0x10) + self.assertEqual(hex(v1), "0x10") + + def test_mult_modulo_bytes(self): + modmult = self.Integer._mult_modulo_bytes + + res = modmult(4, 5, 19) + self.assertEqual(res, b"\x01") + + res = modmult(4 - 19, 5, 19) + self.assertEqual(res, b"\x01") + + res = modmult(4, 5 - 19, 19) + self.assertEqual(res, b"\x01") + + res = modmult(4 + 19, 5, 19) + self.assertEqual(res, b"\x01") + + res = modmult(4, 5 + 19, 19) + self.assertEqual(res, b"\x01") + + modulus = 2**512 - 1 # 64 bytes + t1 = 13**100 + t2 = 17**100 + expect = b"\xfa\xb2\x11\x87\xc3(y\x07\xf8\xf1n\xdepq\x0b\xca\xf3\xd3B,\xef\xf2\xfbf\xcc)\x8dZ*\x95\x98r\x96\xa8\xd5\xc3}\xe2q:\xa2'z\xf48\xde%\xef\t\x07\xbc\xc4[C\x8bUE2\x90\xef\x81\xaa:\x08" + self.assertEqual(expect, modmult(t1, t2, modulus)) + + self.assertRaises(ZeroDivisionError, modmult, 4, 5, 0) + self.assertRaises(ValueError, modmult, 4, 5, -1) + self.assertRaises(ValueError, modmult, 4, 5, 4) class TestIntegerInt(TestIntegerBase): - - def setUp(self): - self.Integer = IntegerNative + def setUp(self): + self.Integer = IntegerNative class testIntegerRandom(unittest.TestCase): + def test_random_exact_bits(self): + for _ in range(1000): + a = IntegerNative.random(exact_bits=8) + self.assertFalse(a < 128) + self.assertFalse(a >= 256) + + for bits_value in range(1024, 1024 + 8): + a = IntegerNative.random(exact_bits=bits_value) + self.assertFalse(a < 2 ** (bits_value - 1)) + self.assertFalse(a >= 2**bits_value) + + def test_random_max_bits(self): + flag = False + for _ in range(1000): + a = IntegerNative.random(max_bits=8) + flag = flag or a < 128 + self.assertFalse(a >= 256) + self.assertTrue(flag) + + for bits_value in range(1024, 1024 + 8): + a = IntegerNative.random(max_bits=bits_value) + self.assertFalse(a >= 2**bits_value) + + def test_random_bits_custom_rng(self): + class CustomRNG(object): + def __init__(self): + self.counter = 0 + + def __call__(self, size): + self.counter += size + return bchr(0) * size + + custom_rng = CustomRNG() + a = IntegerNative.random(exact_bits=32, randfunc=custom_rng) + self.assertEqual(custom_rng.counter, 4) + + def test_random_range(self): + func = IntegerNative.random_range + + for x in range(200): + a = func(min_inclusive=1, max_inclusive=15) + self.assertTrue(1 <= a <= 15) + + for x in range(200): + a = func(min_inclusive=1, max_exclusive=15) + self.assertTrue(1 <= a < 15) + + self.assertRaises( + ValueError, + func, + min_inclusive=1, + max_inclusive=2, + max_exclusive=3, + ) + self.assertRaises(ValueError, func, max_inclusive=2, max_exclusive=3) - def test_random_exact_bits(self): - - for _ in range(1000): - a = IntegerNative.random(exact_bits=8) - self.assertFalse(a < 128) - self.assertFalse(a >= 256) - - for bits_value in range(1024, 1024 + 8): - a = IntegerNative.random(exact_bits=bits_value) - self.assertFalse(a < 2**(bits_value - 1)) - self.assertFalse(a >= 2**bits_value) - - def test_random_max_bits(self): - - flag = False - for _ in range(1000): - a = IntegerNative.random(max_bits=8) - flag = flag or a < 128 - self.assertFalse(a>=256) - self.assertTrue(flag) - - for bits_value in range(1024, 1024 + 8): - a = IntegerNative.random(max_bits=bits_value) - self.assertFalse(a >= 2**bits_value) - - def test_random_bits_custom_rng(self): - - class CustomRNG(object): - def __init__(self): - self.counter = 0 - - def __call__(self, size): - self.counter += size - return bchr(0) * size - - custom_rng = CustomRNG() - a = IntegerNative.random(exact_bits=32, randfunc=custom_rng) - self.assertEqual(custom_rng.counter, 4) - - def test_random_range(self): - - func = IntegerNative.random_range - - for x in range(200): - a = func(min_inclusive=1, max_inclusive=15) - self.assertTrue(1 <= a <= 15) - - for x in range(200): - a = func(min_inclusive=1, max_exclusive=15) - self.assertTrue(1 <= a < 15) - - self.assertRaises(ValueError, func, min_inclusive=1, max_inclusive=2, - max_exclusive=3) - self.assertRaises(ValueError, func, max_inclusive=2, max_exclusive=3) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestIntegerInt) + tests = [] + tests += list_test_cases(TestIntegerInt) + + try: + from Cryptodome.Math._IntegerGMP import IntegerGMP - try: - from Cryptodome.Math._IntegerGMP import IntegerGMP + class TestIntegerGMP(TestIntegerBase): + def setUp(self): + self.Integer = IntegerGMP - class TestIntegerGMP(TestIntegerBase): - def setUp(self): - self.Integer = IntegerGMP + tests += list_test_cases(TestIntegerGMP) + except (ImportError, OSError) as e: + if sys.platform == "win32": + sys.stdout.write("Skipping GMP tests on Windows\n") + else: + sys.stdout.write("Skipping GMP tests (%s)\n" % str(e)) - tests += list_test_cases(TestIntegerGMP) - except (ImportError, OSError) as e: - if sys.platform == "win32": - sys.stdout.write("Skipping GMP tests on Windows\n") - else: - sys.stdout.write("Skipping GMP tests (%s)\n" % str(e) ) + try: + from Cryptodome.Math._IntegerCustom import IntegerCustom - try: - from Cryptodome.Math._IntegerCustom import IntegerCustom + class TestIntegerCustomModexp(TestIntegerBase): + def setUp(self): + self.Integer = IntegerCustom - class TestIntegerCustomModexp(TestIntegerBase): - def setUp(self): - self.Integer = IntegerCustom + tests += list_test_cases(TestIntegerCustomModexp) + except (ImportError, OSError) as e: + sys.stdout.write("Skipping custom modexp tests (%s)\n" % str(e)) - tests += list_test_cases(TestIntegerCustomModexp) - except (ImportError, OSError) as e: - sys.stdout.write("Skipping custom modexp tests (%s)\n" % str(e) ) + tests += list_test_cases(testIntegerRandom) + return tests - tests += list_test_cases(testIntegerRandom) - return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_Primality.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_Primality.py index 475d1d4b..5b826506 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_Primality.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_Primality.py @@ -39,80 +39,117 @@ from Cryptodome.Util.py3compat import * -from Cryptodome.Math.Numbers import Integer from Cryptodome.Math.Primality import ( - PROBABLY_PRIME, COMPOSITE, - miller_rabin_test, lucas_test, - test_probable_prime, - generate_probable_prime, - generate_probable_safe_prime, - ) + PROBABLY_PRIME, + COMPOSITE, + miller_rabin_test, + lucas_test, + test_probable_prime, + generate_probable_prime, + generate_probable_safe_prime, +) class TestPrimality(unittest.TestCase): + primes = ( + 1, + 2, + 3, + 5, + 7, + 11, + 13, + 17, + 19, + 23, + 2**127 - 1, + 175637383534939453397801320455508570374088202376942372758907369518414308188137781042871856139027160010343454418881888953150175357127346872102307696660678617989191485418582475696230580407111841072614783095326672517315988762029036079794994990250662362650625650262324085116467511357592728695033227611029693067539, + ) + composites = ( + 0, + 4, + 6, + 8, + 9, + 10, + 12, + 14, + 15, + 16, + 18, + 20, + 21, + 7 * 23, + (2**19 - 1) * (2**67 - 1), + 9746347772161, + ) + + def test_miller_rabin(self): + for prime in self.primes: + self.assertEqual(miller_rabin_test(prime, 3), PROBABLY_PRIME) + for composite in self.composites: + self.assertEqual(miller_rabin_test(composite, 3), COMPOSITE) + self.assertRaises(ValueError, miller_rabin_test, -1, 3) + + def test_lucas(self): + for prime in self.primes: + res = lucas_test(prime) + self.assertEqual(res, PROBABLY_PRIME) + for composite in self.composites: + res = lucas_test(composite) + self.assertEqual(res, COMPOSITE) + self.assertRaises(ValueError, lucas_test, -1) + + def test_is_prime(self): + primes = ( + 170141183460469231731687303715884105727, + 19175002942688032928599, + 1363005552434666078217421284621279933627102780881053358473, + 2**521 - 1, + ) + for p in primes: + self.assertEqual(test_probable_prime(p), PROBABLY_PRIME) + + not_primes = ( + 4754868377601046732119933839981363081972014948522510826417784001, + 1334733877147062382486934807105197899496002201113849920496510541601, + 260849323075371835669784094383812120359260783810157225730623388382401, + ) + for np in not_primes: + self.assertEqual(test_probable_prime(np), COMPOSITE) + + from Cryptodome.Util.number import sieve_base + + for p in sieve_base[:100]: + res = test_probable_prime(p) + self.assertEqual(res, PROBABLY_PRIME) + + def test_generate_prime_bit_size(self): + p = generate_probable_prime(exact_bits=512) + self.assertEqual(p.size_in_bits(), 512) + + def test_generate_prime_filter(self): + def ending_with_one(number): + return number % 10 == 1 + + for x in range(20): + q = generate_probable_prime( + exact_bits=160, + prime_filter=ending_with_one, + ) + self.assertEqual(q % 10, 1) + + def test_generate_safe_prime(self): + p = generate_probable_safe_prime(exact_bits=161) + self.assertEqual(p.size_in_bits(), 161) - primes = (1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 2**127-1, 175637383534939453397801320455508570374088202376942372758907369518414308188137781042871856139027160010343454418881888953150175357127346872102307696660678617989191485418582475696230580407111841072614783095326672517315988762029036079794994990250662362650625650262324085116467511357592728695033227611029693067539) - composites = (0, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 7*23, (2**19-1)*(2**67-1), 9746347772161,) - - def test_miller_rabin(self): - for prime in self.primes: - self.assertEqual(miller_rabin_test(prime, 3), PROBABLY_PRIME) - for composite in self.composites: - self.assertEqual(miller_rabin_test(composite, 3), COMPOSITE) - self.assertRaises(ValueError, miller_rabin_test, -1, 3) - - def test_lucas(self): - for prime in self.primes: - res = lucas_test(prime) - self.assertEqual(res, PROBABLY_PRIME) - for composite in self.composites: - res = lucas_test(composite) - self.assertEqual(res, COMPOSITE) - self.assertRaises(ValueError, lucas_test, -1) - - def test_is_prime(self): - primes = (170141183460469231731687303715884105727, - 19175002942688032928599, - 1363005552434666078217421284621279933627102780881053358473, - 2 ** 521 - 1) - for p in primes: - self.assertEqual(test_probable_prime(p), PROBABLY_PRIME) - - not_primes = ( - 4754868377601046732119933839981363081972014948522510826417784001, - 1334733877147062382486934807105197899496002201113849920496510541601, - 260849323075371835669784094383812120359260783810157225730623388382401, - ) - for np in not_primes: - self.assertEqual(test_probable_prime(np), COMPOSITE) - - from Cryptodome.Util.number import sieve_base - for p in sieve_base[:100]: - res = test_probable_prime(p) - self.assertEqual(res, PROBABLY_PRIME) - - def test_generate_prime_bit_size(self): - p = generate_probable_prime(exact_bits=512) - self.assertEqual(p.size_in_bits(), 512) - - def test_generate_prime_filter(self): - def ending_with_one(number): - return number % 10 == 1 - - for x in range(20): - q = generate_probable_prime(exact_bits=160, - prime_filter=ending_with_one) - self.assertEqual(q % 10, 1) - - def test_generate_safe_prime(self): - p = generate_probable_safe_prime(exact_bits=161) - self.assertEqual(p.size_in_bits(), 161) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestPrimality) - return tests + tests = [] + tests += list_test_cases(TestPrimality) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_modexp.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_modexp.py index d63f43cf..e6952cb3 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_modexp.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_modexp.py @@ -41,11 +41,12 @@ from Cryptodome.Util.py3compat import * -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, - c_size_t, - c_ulonglong) +from Cryptodome.Util._raw_api import ( + create_string_buffer, + get_raw_buffer, + c_size_t, + c_ulonglong, +) from Cryptodome.Hash import SHAKE128 from Cryptodome.Math.Numbers import Integer @@ -55,147 +56,148 @@ def create_rng(tag): - rng = StrongRandom(SHAKE128.new(data=tag)) - return rng + rng = StrongRandom(SHAKE128.new(data=tag)) + return rng + class ExceptionModulus(ValueError): - pass + pass + def monty_pow(base, exp, modulus): - max_len = len(long_to_bytes(max(base, exp, modulus))) + max_len = len(long_to_bytes(max(base, exp, modulus))) - base_b, exp_b, modulus_b = [ long_to_bytes(x, max_len) for x in - (base, exp, modulus) ] + base_b, exp_b, modulus_b = [long_to_bytes(x, max_len) for x in (base, exp, modulus)] - out = create_string_buffer(max_len) - error = _raw_montgomery.monty_pow( - out, - base_b, - exp_b, - modulus_b, - c_size_t(max_len), - c_ulonglong(32) - ) + out = create_string_buffer(max_len) + error = _raw_montgomery.monty_pow( + out, + base_b, + exp_b, + modulus_b, + c_size_t(max_len), + c_ulonglong(32), + ) - if error == 17: - raise ExceptionModulus() - if error: - raise ValueError("monty_pow failed with error: %d" % error) + if error == 17: + raise ExceptionModulus() + if error: + raise ValueError("monty_pow failed with error: %d" % error) - result = bytes_to_long(get_raw_buffer(out)) - return result + result = bytes_to_long(get_raw_buffer(out)) + return result -exponent1 = 0x2ce0af628901460a419a08ef950d498b9fd6f271a1a52ac293b86fe5c60efe8e8ba93fa1ebe1eb3d614d2e7b328cb60a2591440e163441a190ecf101ceec245f600fffdcf3f5b3a17a7baeacb96a424db1d7ec985e8ec998bb479fecfffed6a75f9a90fc97062fd973303bce855ad7b8d8272a94025e8532be9aabd54a183f303538d2a7e621b4131d59e823a4625f39bd7d518d7784f7c3a8f19061da74974ff42fa1c063dec2db97d461e291a7d6e721708a5229de166c1246363372854e27f3f08ae274bc16bfd205b028a4d81386494433d516dfbb35f495acba5e4e1d1843cb3c3129b6642a85fc7244ce5845fac071c7f622e4ee12ac43fabeeaa0cd01 -modulus1 = 0xd66691b20071be4d66d4b71032b37fa007cfabf579fcb91e50bfc2753b3f0ce7be74e216aef7e26d4ae180bc20d7bd3ea88a6cbf6f87380e613c8979b5b043b200a8ff8856a3b12875e36e98a7569f3852d028e967551000b02c19e9fa52e83115b89309aabb1e1cf1e2cb6369d637d46775ce4523ea31f64ad2794cbc365dd8a35e007ed3b57695877fbf102dbeb8b3212491398e494314e93726926e1383f8abb5889bea954eb8c0ca1c62c8e9d83f41888095c5e645ed6d32515fe0c58c1368cad84694e18da43668c6f43e61d7c9bca633ddcda7aef5b79bc396d4a9f48e2a9abe0836cc455e435305357228e93d25aaed46b952defae0f57339bf26f5a9 +exponent1 = 0x2CE0AF628901460A419A08EF950D498B9FD6F271A1A52AC293B86FE5C60EFE8E8BA93FA1EBE1EB3D614D2E7B328CB60A2591440E163441A190ECF101CEEC245F600FFFDCF3F5B3A17A7BAEACB96A424DB1D7EC985E8EC998BB479FECFFFED6A75F9A90FC97062FD973303BCE855AD7B8D8272A94025E8532BE9AABD54A183F303538D2A7E621B4131D59E823A4625F39BD7D518D7784F7C3A8F19061DA74974FF42FA1C063DEC2DB97D461E291A7D6E721708A5229DE166C1246363372854E27F3F08AE274BC16BFD205B028A4D81386494433D516DFBB35F495ACBA5E4E1D1843CB3C3129B6642A85FC7244CE5845FAC071C7F622E4EE12AC43FABEEAA0CD01 +modulus1 = 0xD66691B20071BE4D66D4B71032B37FA007CFABF579FCB91E50BFC2753B3F0CE7BE74E216AEF7E26D4AE180BC20D7BD3EA88A6CBF6F87380E613C8979B5B043B200A8FF8856A3B12875E36E98A7569F3852D028E967551000B02C19E9FA52E83115B89309AABB1E1CF1E2CB6369D637D46775CE4523EA31F64AD2794CBC365DD8A35E007ED3B57695877FBF102DBEB8B3212491398E494314E93726926E1383F8ABB5889BEA954EB8C0CA1C62C8E9D83F41888095C5E645ED6D32515FE0C58C1368CAD84694E18DA43668C6F43E61D7C9BCA633DDCDA7AEF5B79BC396D4A9F48E2A9ABE0836CC455E435305357228E93D25AAED46B952DEFAE0F57339BF26F5A9 -class TestModExp(unittest.TestCase): - def test_small(self): - self.assertEqual(1, monty_pow(11,12,19)) - - def test_large_1(self): - base = 0xfffffffffffffffffffffffffffffffffffffffffffffffffff - expected = pow(base, exponent1, modulus1) - result = monty_pow(base, exponent1, modulus1) - self.assertEqual(result, expected) - - def test_zero_exp(self): - base = 0xfffffffffffffffffffffffffffffffffffffffffffffffffff - result = monty_pow(base, 0, modulus1) - self.assertEqual(result, 1) - - def test_zero_base(self): - result = monty_pow(0, exponent1, modulus1) - self.assertEqual(result, 0) - - def test_zero_modulus(self): - base = 0xfffffffffffffffffffffffffffffffffffffffffffffffff - self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, 0) - self.assertRaises(ExceptionModulus, monty_pow, 0, 0, 0) - - def test_larger_exponent(self): - base = modulus1 - 0xFFFFFFF - expected = pow(base, modulus1<<64, modulus1) - result = monty_pow(base, modulus1<<64, modulus1) - self.assertEqual(result, expected) - - def test_even_modulus(self): - base = modulus1 >> 4 - self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, modulus1-1) - - def test_several_lengths(self): - prng = SHAKE128.new().update(b('Test')) - for length in range(1, 100): - modulus2 = Integer.from_bytes(prng.read(length)) | 1 - base = Integer.from_bytes(prng.read(length)) % modulus2 - exponent2 = Integer.from_bytes(prng.read(length)) - - expected = pow(base, exponent2, modulus2) - result = monty_pow(base, exponent2, modulus2) - self.assertEqual(result, expected) - - def test_variable_exponent(self): - prng = create_rng(b('Test variable exponent')) - for i in range(20): - for j in range(7): - modulus = prng.getrandbits(8*30) | 1 - base = prng.getrandbits(8*30) % modulus - exponent = prng.getrandbits(i*8+j) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - exponent ^= (1 << (i*8+j)) - 1 - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - def test_stress_63(self): - prng = create_rng(b('Test 63')) - length = 63 - for _ in range(2000): - modulus = prng.getrandbits(8*length) | 1 - base = prng.getrandbits(8*length) % modulus - exponent = prng.getrandbits(8*length) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - def test_stress_64(self): - prng = create_rng(b('Test 64')) - length = 64 - for _ in range(2000): - modulus = prng.getrandbits(8*length) | 1 - base = prng.getrandbits(8*length) % modulus - exponent = prng.getrandbits(8*length) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - def test_stress_65(self): - prng = create_rng(b('Test 65')) - length = 65 - for _ in range(2000): - modulus = prng.getrandbits(8*length) | 1 - base = prng.getrandbits(8*length) % modulus - exponent = prng.getrandbits(8*length) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) +class TestModExp(unittest.TestCase): + def test_small(self): + self.assertEqual(1, monty_pow(11, 12, 19)) + + def test_large_1(self): + base = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + expected = pow(base, exponent1, modulus1) + result = monty_pow(base, exponent1, modulus1) + self.assertEqual(result, expected) + + def test_zero_exp(self): + base = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + result = monty_pow(base, 0, modulus1) + self.assertEqual(result, 1) + + def test_zero_base(self): + result = monty_pow(0, exponent1, modulus1) + self.assertEqual(result, 0) + + def test_zero_modulus(self): + base = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, 0) + self.assertRaises(ExceptionModulus, monty_pow, 0, 0, 0) + + def test_larger_exponent(self): + base = modulus1 - 0xFFFFFFF + expected = pow(base, modulus1 << 64, modulus1) + result = monty_pow(base, modulus1 << 64, modulus1) + self.assertEqual(result, expected) + + def test_even_modulus(self): + base = modulus1 >> 4 + self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, modulus1 - 1) + + def test_several_lengths(self): + prng = SHAKE128.new().update(b("Test")) + for length in range(1, 100): + modulus2 = Integer.from_bytes(prng.read(length)) | 1 + base = Integer.from_bytes(prng.read(length)) % modulus2 + exponent2 = Integer.from_bytes(prng.read(length)) + + expected = pow(base, exponent2, modulus2) + result = monty_pow(base, exponent2, modulus2) + self.assertEqual(result, expected) + + def test_variable_exponent(self): + prng = create_rng(b("Test variable exponent")) + for i in range(20): + for j in range(7): + modulus = prng.getrandbits(8 * 30) | 1 + base = prng.getrandbits(8 * 30) % modulus + exponent = prng.getrandbits(i * 8 + j) + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) + + exponent ^= (1 << (i * 8 + j)) - 1 + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) + + def test_stress_63(self): + prng = create_rng(b("Test 63")) + length = 63 + for _ in range(2000): + modulus = prng.getrandbits(8 * length) | 1 + base = prng.getrandbits(8 * length) % modulus + exponent = prng.getrandbits(8 * length) + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) + + def test_stress_64(self): + prng = create_rng(b("Test 64")) + length = 64 + for _ in range(2000): + modulus = prng.getrandbits(8 * length) | 1 + base = prng.getrandbits(8 * length) % modulus + exponent = prng.getrandbits(8 * length) + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) + + def test_stress_65(self): + prng = create_rng(b("Test 65")) + length = 65 + for _ in range(2000): + modulus = prng.getrandbits(8 * length) | 1 + base = prng.getrandbits(8 * length) % modulus + exponent = prng.getrandbits(8 * length) + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestModExp) - return tests + tests = [] + tests += list_test_cases(TestModExp) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_modmult.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_modmult.py index df794e4e..c30c491b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_modmult.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Math/test_modmult.py @@ -39,82 +39,84 @@ from Cryptodome.Util.number import long_to_bytes, bytes_to_long -from Cryptodome.Util._raw_api import (create_string_buffer, - get_raw_buffer, - c_size_t) +from Cryptodome.Util._raw_api import ( + create_string_buffer, + get_raw_buffer, + c_size_t, +) from Cryptodome.Math._IntegerCustom import _raw_montgomery class ExceptionModulus(ValueError): - pass + pass def monty_mult(term1, term2, modulus): + if term1 >= modulus: + term1 %= modulus + if term2 >= modulus: + term2 %= modulus - if term1 >= modulus: - term1 %= modulus - if term2 >= modulus: - term2 %= modulus + modulus_b = long_to_bytes(modulus) + numbers_len = len(modulus_b) + term1_b = long_to_bytes(term1, numbers_len) + term2_b = long_to_bytes(term2, numbers_len) - modulus_b = long_to_bytes(modulus) - numbers_len = len(modulus_b) - term1_b = long_to_bytes(term1, numbers_len) - term2_b = long_to_bytes(term2, numbers_len) + out = create_string_buffer(numbers_len) + error = _raw_montgomery.monty_multiply( + out, + term1_b, + term2_b, + modulus_b, + c_size_t(numbers_len), + ) - out = create_string_buffer(numbers_len) - error = _raw_montgomery.monty_multiply( - out, - term1_b, - term2_b, - modulus_b, - c_size_t(numbers_len) - ) + if error == 17: + raise ExceptionModulus() + if error: + raise ValueError("monty_multiply() failed with error: %d" % error) - if error == 17: - raise ExceptionModulus() - if error: - raise ValueError("monty_multiply() failed with error: %d" % error) + return get_raw_buffer(out) - return get_raw_buffer(out) - -modulus1 = 0xd66691b20071be4d66d4b71032b37fa007cfabf579fcb91e50bfc2753b3f0ce7be74e216aef7e26d4ae180bc20d7bd3ea88a6cbf6f87380e613c8979b5b043b200a8ff8856a3b12875e36e98a7569f3852d028e967551000b02c19e9fa52e83115b89309aabb1e1cf1e2cb6369d637d46775ce4523ea31f64ad2794cbc365dd8a35e007ed3b57695877fbf102dbeb8b3212491398e494314e93726926e1383f8abb5889bea954eb8c0ca1c62c8e9d83f41888095c5e645ed6d32515fe0c58c1368cad84694e18da43668c6f43e61d7c9bca633ddcda7aef5b79bc396d4a9f48e2a9abe0836cc455e435305357228e93d25aaed46b952defae0f57339bf26f5a9 +modulus1 = 0xD66691B20071BE4D66D4B71032B37FA007CFABF579FCB91E50BFC2753B3F0CE7BE74E216AEF7E26D4AE180BC20D7BD3EA88A6CBF6F87380E613C8979B5B043B200A8FF8856A3B12875E36E98A7569F3852D028E967551000B02C19E9FA52E83115B89309AABB1E1CF1E2CB6369D637D46775CE4523EA31F64AD2794CBC365DD8A35E007ED3B57695877FBF102DBEB8B3212491398E494314E93726926E1383F8ABB5889BEA954EB8C0CA1C62C8E9D83F41888095C5E645ED6D32515FE0C58C1368CAD84694E18DA43668C6F43E61D7C9BCA633DDCDA7AEF5B79BC396D4A9F48E2A9ABE0836CC455E435305357228E93D25AAED46B952DEFAE0F57339BF26F5A9 class TestModMultiply(unittest.TestCase): + def test_small(self): + self.assertEqual(b"\x01", monty_mult(5, 6, 29)) - def test_small(self): - self.assertEqual(b"\x01", monty_mult(5, 6, 29)) - - def test_large(self): - numbers_len = (modulus1.bit_length() + 7) // 8 + def test_large(self): + numbers_len = (modulus1.bit_length() + 7) // 8 - t1 = modulus1 // 2 - t2 = modulus1 - 90 - expect = b'\x00' * (numbers_len - 1) + b'\x2d' - self.assertEqual(expect, monty_mult(t1, t2, modulus1)) + t1 = modulus1 // 2 + t2 = modulus1 - 90 + expect = b"\x00" * (numbers_len - 1) + b"\x2d" + self.assertEqual(expect, monty_mult(t1, t2, modulus1)) - def test_zero_term(self): - numbers_len = (modulus1.bit_length() + 7) // 8 - expect = b'\x00' * numbers_len - self.assertEqual(expect, monty_mult(0x100, 0, modulus1)) - self.assertEqual(expect, monty_mult(0, 0x100, modulus1)) + def test_zero_term(self): + numbers_len = (modulus1.bit_length() + 7) // 8 + expect = b"\x00" * numbers_len + self.assertEqual(expect, monty_mult(0x100, 0, modulus1)) + self.assertEqual(expect, monty_mult(0, 0x100, modulus1)) - def test_larger_term(self): - t1 = 2**2047 - expect_int = 0x8edf4071f78e3d7ba622cdbbbef74612e301d69186776ae6bf87ff38c320d9aebaa64889c2f67de2324e6bccd2b10ad89e91fd21ba4bb523904d033eff5e70e62f01a84f41fa90a4f248ef249b82e1d2729253fdfc2a3b5b740198123df8bfbf7057d03e15244ad5f26eb9a099763b5c5972121ec076b0bf899f59bd95f7cc129abddccf24217bce52ca0f3a44c9ccc504765dbb89734205f3ae6a8cc560494a60ea84b27d8e00fa24bdd5b4f1d4232edb61e47d3d984c1fa50a3820a2e580fbc3fc8bc11e99df53b9efadf5a40ac75d384e400905aa6f1d88950cd53b1c54dc2222115ad84a27260fa4d978155c1434c551de1ee7361a17a2f79d4388f78a5d - res = bytes_to_long(monty_mult(t1, t1, modulus1)) - self.assertEqual(res, expect_int) + def test_larger_term(self): + t1 = 2**2047 + expect_int = 0x8EDF4071F78E3D7BA622CDBBBEF74612E301D69186776AE6BF87FF38C320D9AEBAA64889C2F67DE2324E6BCCD2B10AD89E91FD21BA4BB523904D033EFF5E70E62F01A84F41FA90A4F248EF249B82E1D2729253FDFC2A3B5B740198123DF8BFBF7057D03E15244AD5F26EB9A099763B5C5972121EC076B0BF899F59BD95F7CC129ABDDCCF24217BCE52CA0F3A44C9CCC504765DBB89734205F3AE6A8CC560494A60EA84B27D8E00FA24BDD5B4F1D4232EDB61E47D3D984C1FA50A3820A2E580FBC3FC8BC11E99DF53B9EFADF5A40AC75D384E400905AA6F1D88950CD53B1C54DC2222115AD84A27260FA4D978155C1434C551DE1EE7361A17A2F79D4388F78A5D + res = bytes_to_long(monty_mult(t1, t1, modulus1)) + self.assertEqual(res, expect_int) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestModMultiply) - return tests + tests = [] + tests += list_test_cases(TestModMultiply) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/__init__.py index e40f7725..b25c80a3 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/__init__.py @@ -24,22 +24,33 @@ """Self-test for Cryptodome.Protocol""" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Protocol import test_rfc1751; tests += test_rfc1751.get_tests(config=config) - from Cryptodome.SelfTest.Protocol import test_KDF; tests += test_KDF.get_tests(config=config) - from Cryptodome.SelfTest.Protocol import test_ecdh; tests += test_ecdh.get_tests(config=config) + tests = [] + from Cryptodome.SelfTest.Protocol import test_rfc1751 + + tests += test_rfc1751.get_tests(config=config) + from Cryptodome.SelfTest.Protocol import test_KDF + + tests += test_KDF.get_tests(config=config) + from Cryptodome.SelfTest.Protocol import test_ecdh + + tests += test_ecdh.get_tests(config=config) + + from Cryptodome.SelfTest.Protocol import test_SecretSharing + + tests += test_SecretSharing.get_tests(config=config) + + if sys.version_info >= (3, 9): + from Cryptodome.SelfTest.Protocol import test_HPKE + + tests += test_HPKE.get_tests(config=config) - from Cryptodome.SelfTest.Protocol import test_SecretSharing - tests += test_SecretSharing.get_tests(config=config) + return tests - if sys.version_info >= (3, 9): - from Cryptodome.SelfTest.Protocol import test_HPKE - tests += test_HPKE.get_tests(config=config) - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_HPKE.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_HPKE.py index d6339670..7671f38c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_HPKE.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_HPKE.py @@ -14,478 +14,542 @@ class HPKE_Tests(unittest.TestCase): + key1 = ECC.generate(curve="p256") + key2 = ECC.generate(curve="p256") + + # name, size of enc + curves = { + "p256": 65, + "p384": 97, + "p521": 133, + "curve25519": 32, + "curve448": 56, + } + + def round_trip(self, curve, aead_id): + key1 = ECC.generate(curve=curve) + aead_id = aead_id + + encryptor = HPKE.new( + receiver_key=key1.public_key(), + aead_id=aead_id, + ) + self.assertEqual(len(encryptor.enc), self.curves[curve]) + + # First message + ct = encryptor.seal(b"ABC", auth_data=b"DEF") + + decryptor = HPKE.new( + receiver_key=key1, + aead_id=aead_id, + enc=encryptor.enc, + ) + + pt = decryptor.unseal(ct, auth_data=b"DEF") + self.assertEqual(b"ABC", pt) + + # Second message + ct2 = encryptor.seal(b"GHI") + pt2 = decryptor.unseal(ct2) + self.assertEqual(b"GHI", pt2) + + def test_round_trip(self): + for curve in self.curves.keys(): + for aead_id in HPKE.AEAD: + self.round_trip(curve, aead_id) + + def test_psk(self): + aead_id = HPKE.AEAD.AES128_GCM + HPKE.new( + receiver_key=self.key1.public_key(), + aead_id=aead_id, + psk=(b"a", b"c" * 32), + ) + + def test_info(self): + aead_id = HPKE.AEAD.AES128_GCM + HPKE.new( + receiver_key=self.key1.public_key(), + aead_id=aead_id, + info=b"baba", + ) + + def test_neg_unsupported_curve(self): + key3 = ECC.generate(curve="p224") + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=key3.public_key(), + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("Unsupported curve", str(cm.exception)) + + def test_neg_too_many_private_keys(self): + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1, + sender_key=self.key2, + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("Exactly 1 private key", str(cm.exception)) + + def test_neg_curve_mismatch(self): + key3 = ECC.generate(curve="p384") + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + sender_key=key3, + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("but recipient key", str(cm.exception)) + + def test_neg_psk(self): + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + psk=(b"", b"G" * 32), + aead_id=HPKE.AEAD.AES128_GCM, + ) + + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + psk=(b"JJJ", b""), + aead_id=HPKE.AEAD.AES128_GCM, + ) + + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + psk=(b"JJJ", b"Y" * 31), + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("at least 32", str(cm.exception)) + + def test_neg_wrong_enc(self): + wrong_enc = b"\xff" + b"8" * 64 + with self.assertRaises(DeserializeError): + HPKE.new( + receiver_key=self.key1, + aead_id=HPKE.AEAD.AES128_GCM, + enc=wrong_enc, + ) + + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + enc=self.key1.public_key().export_key(format="raw"), + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("'enc' cannot be an input", str(cm.exception)) + + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1, + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("'enc' required", str(cm.exception)) + + def test_neg_unseal_wrong_ct(self): + decryptor = HPKE.new( + receiver_key=self.key1, + aead_id=HPKE.AEAD.CHACHA20_POLY1305, + enc=self.key2.public_key().export_key(format="raw"), + ) + + with self.assertRaises(ValueError): + decryptor.unseal(b"XYZ" * 20) + + def test_neg_unseal_no_auth_data(self): + aead_id = HPKE.AEAD.CHACHA20_POLY1305 + + encryptor = HPKE.new( + receiver_key=self.key1.public_key(), + aead_id=aead_id, + ) + + ct = encryptor.seal(b"ABC", auth_data=b"DEF") + + decryptor = HPKE.new( + receiver_key=self.key1, + aead_id=aead_id, + enc=encryptor.enc, + ) + + with self.assertRaises(ValueError): + decryptor.unseal(ct) + + def test_x25519_mode_0(self): + # RFC x9180, A.1.1.1, seq 0 and 1 + + keyR_hex = "4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8" + keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + + pt_hex = "4265617574792069732074727574682c20747275746820626561757479" + pt = bytes.fromhex(pt_hex) + + ct0_hex = "f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83d07bea87e13c512a" + ct0 = bytes.fromhex(ct0_hex) - key1 = ECC.generate(curve='p256') - key2 = ECC.generate(curve='p256') - - # name, size of enc - curves = { - 'p256': 65, - 'p384': 97, - 'p521': 133, - 'curve25519': 32, - 'curve448': 56, - } - - def round_trip(self, curve, aead_id): - key1 = ECC.generate(curve=curve) - aead_id = aead_id - - encryptor = HPKE.new(receiver_key=key1.public_key(), - aead_id=aead_id) - self.assertEqual(len(encryptor.enc), self.curves[curve]) - - # First message - ct = encryptor.seal(b'ABC', auth_data=b'DEF') - - decryptor = HPKE.new(receiver_key=key1, - aead_id=aead_id, - enc=encryptor.enc) - - pt = decryptor.unseal(ct, auth_data=b'DEF') - self.assertEqual(b'ABC', pt) - - # Second message - ct2 = encryptor.seal(b'GHI') - pt2 = decryptor.unseal(ct2) - self.assertEqual(b'GHI', pt2) - - def test_round_trip(self): - for curve in self.curves.keys(): - for aead_id in HPKE.AEAD: - self.round_trip(curve, aead_id) - - def test_psk(self): - aead_id = HPKE.AEAD.AES128_GCM - HPKE.new(receiver_key=self.key1.public_key(), - aead_id=aead_id, - psk=(b'a', b'c' * 32)) - - def test_info(self): - aead_id = HPKE.AEAD.AES128_GCM - HPKE.new(receiver_key=self.key1.public_key(), - aead_id=aead_id, - info=b'baba') - - def test_neg_unsupported_curve(self): - key3 = ECC.generate(curve='p224') - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=key3.public_key(), - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("Unsupported curve", str(cm.exception)) - - def test_neg_too_many_private_keys(self): - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1, - sender_key=self.key2, - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("Exactly 1 private key", str(cm.exception)) - - def test_neg_curve_mismatch(self): - key3 = ECC.generate(curve='p384') - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - sender_key=key3, - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("but recipient key", str(cm.exception)) - - def test_neg_psk(self): - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - psk=(b'', b'G' * 32), - aead_id=HPKE.AEAD.AES128_GCM) - - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - psk=(b'JJJ', b''), - aead_id=HPKE.AEAD.AES128_GCM) - - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - psk=(b'JJJ', b'Y' * 31), - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("at least 32", str(cm.exception)) - - def test_neg_wrong_enc(self): - wrong_enc = b'\xFF' + b'8' * 64 - with self.assertRaises(DeserializeError): - HPKE.new(receiver_key=self.key1, - aead_id=HPKE.AEAD.AES128_GCM, - enc=wrong_enc) + enc_hex = "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431" + enc = bytes.fromhex(enc_hex) - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - enc=self.key1.public_key().export_key(format='raw'), - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("'enc' cannot be an input", str(cm.exception)) - - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1, - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("'enc' required", str(cm.exception)) + aad0_hex = "436f756e742d30" + aad0 = bytes.fromhex(aad0_hex) - def test_neg_unseal_wrong_ct(self): - decryptor = HPKE.new(receiver_key=self.key1, - aead_id=HPKE.AEAD.CHACHA20_POLY1305, - enc=self.key2.public_key().export_key(format='raw')) + aad1_hex = "436f756e742d31" + aad1 = bytes.fromhex(aad1_hex) - with self.assertRaises(ValueError): - decryptor.unseal(b'XYZ' * 20) + info_hex = "4f6465206f6e2061204772656369616e2055726e" + info = bytes.fromhex(info_hex) - def test_neg_unseal_no_auth_data(self): - aead_id = HPKE.AEAD.CHACHA20_POLY1305 + ct1_hex = "af2d7e9ac9ae7e270f46ba1f975be53c09f8d875bdc8535458c2494e8a6eab251c03d0c22a56b8ca42c2063b84" + ct1 = bytes.fromhex(ct1_hex) - encryptor = HPKE.new(receiver_key=self.key1.public_key(), - aead_id=aead_id) + aead_id = HPKE.AEAD.AES128_GCM - ct = encryptor.seal(b'ABC', auth_data=b'DEF') + decryptor = HPKE.new( + receiver_key=keyR, + aead_id=aead_id, + info=info, + enc=enc, + ) - decryptor = HPKE.new(receiver_key=self.key1, - aead_id=aead_id, - enc=encryptor.enc) + pt_X0 = decryptor.unseal(ct0, aad0) + self.assertEqual(pt_X0, pt) - with self.assertRaises(ValueError): - decryptor.unseal(ct) + pt_X1 = decryptor.unseal(ct1, aad1) + self.assertEqual(pt_X1, pt) - def test_x25519_mode_0(self): - # RFC x9180, A.1.1.1, seq 0 and 1 + def test_x25519_mode_1(self): + # RFC x9180, A.1.2.1, seq 0 and 1 - keyR_hex = "4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8" - keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + keyR_hex = "c5eb01eb457fe6c6f57577c5413b931550a162c71a03ac8d196babbd4e5ce0fd" + keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) - pt_hex = "4265617574792069732074727574682c20747275746820626561757479" - pt = bytes.fromhex(pt_hex) + psk_id_hex = "456e6e796e20447572696e206172616e204d6f726961" + psk_id = bytes.fromhex(psk_id_hex) - ct0_hex = "f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83d07bea87e13c512a" - ct0 = bytes.fromhex(ct0_hex) + psk_hex = "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82" + psk = bytes.fromhex(psk_hex) - enc_hex = "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431" - enc = bytes.fromhex(enc_hex) + pt_hex = "4265617574792069732074727574682c20747275746820626561757479" + pt = bytes.fromhex(pt_hex) - aad0_hex = "436f756e742d30" - aad0 = bytes.fromhex(aad0_hex) + ct0_hex = "e52c6fed7f758d0cf7145689f21bc1be6ec9ea097fef4e959440012f4feb73fb611b946199e681f4cfc34db8ea" + ct0 = bytes.fromhex(ct0_hex) - aad1_hex = "436f756e742d31" - aad1 = bytes.fromhex(aad1_hex) + enc_hex = "0ad0950d9fb9588e59690b74f1237ecdf1d775cd60be2eca57af5a4b0471c91b" + enc = bytes.fromhex(enc_hex) - info_hex = "4f6465206f6e2061204772656369616e2055726e" - info = bytes.fromhex(info_hex) + aad0_hex = "436f756e742d30" + aad0 = bytes.fromhex(aad0_hex) - ct1_hex = "af2d7e9ac9ae7e270f46ba1f975be53c09f8d875bdc8535458c2494e8a6eab251c03d0c22a56b8ca42c2063b84" - ct1 = bytes.fromhex(ct1_hex) + aad1_hex = "436f756e742d31" + aad1 = bytes.fromhex(aad1_hex) - aead_id = HPKE.AEAD.AES128_GCM + info_hex = "4f6465206f6e2061204772656369616e2055726e" + info = bytes.fromhex(info_hex) - decryptor = HPKE.new(receiver_key=keyR, - aead_id=aead_id, - info=info, - enc=enc) + ct1_hex = "49f3b19b28a9ea9f43e8c71204c00d4a490ee7f61387b6719db765e948123b45b61633ef059ba22cd62437c8ba" + ct1 = bytes.fromhex(ct1_hex) - pt_X0 = decryptor.unseal(ct0, aad0) - self.assertEqual(pt_X0, pt) + aead_id = HPKE.AEAD.AES128_GCM - pt_X1 = decryptor.unseal(ct1, aad1) - self.assertEqual(pt_X1, pt) + decryptor = HPKE.new( + receiver_key=keyR, + aead_id=aead_id, + info=info, + psk=(psk_id, psk), + enc=enc, + ) - def test_x25519_mode_1(self): - # RFC x9180, A.1.2.1, seq 0 and 1 + pt_X0 = decryptor.unseal(ct0, aad0) + self.assertEqual(pt_X0, pt) - keyR_hex = "c5eb01eb457fe6c6f57577c5413b931550a162c71a03ac8d196babbd4e5ce0fd" - keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + pt_X1 = decryptor.unseal(ct1, aad1) + self.assertEqual(pt_X1, pt) - psk_id_hex = "456e6e796e20447572696e206172616e204d6f726961" - psk_id = bytes.fromhex(psk_id_hex) + def test_x25519_mode_2(self): + # RFC x9180, A.1.3.1, seq 0 and 1 - psk_hex = "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82" - psk = bytes.fromhex(psk_hex) + keyR_hex = "fdea67cf831f1ca98d8e27b1f6abeb5b7745e9d35348b80fa407ff6958f9137e" + keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) - pt_hex = "4265617574792069732074727574682c20747275746820626561757479" - pt = bytes.fromhex(pt_hex) + keyS_hex = "dc4a146313cce60a278a5323d321f051c5707e9c45ba21a3479fecdf76fc69dd" + keyS = DH.import_x25519_private_key(bytes.fromhex(keyS_hex)) - ct0_hex = "e52c6fed7f758d0cf7145689f21bc1be6ec9ea097fef4e959440012f4feb73fb611b946199e681f4cfc34db8ea" - ct0 = bytes.fromhex(ct0_hex) + pt_hex = "4265617574792069732074727574682c20747275746820626561757479" + pt = bytes.fromhex(pt_hex) - enc_hex = "0ad0950d9fb9588e59690b74f1237ecdf1d775cd60be2eca57af5a4b0471c91b" - enc = bytes.fromhex(enc_hex) + ct0_hex = "5fd92cc9d46dbf8943e72a07e42f363ed5f721212cd90bcfd072bfd9f44e06b80fd17824947496e21b680c141b" + ct0 = bytes.fromhex(ct0_hex) - aad0_hex = "436f756e742d30" - aad0 = bytes.fromhex(aad0_hex) + enc_hex = "23fb952571a14a25e3d678140cd0e5eb47a0961bb18afcf85896e5453c312e76" + enc = bytes.fromhex(enc_hex) - aad1_hex = "436f756e742d31" - aad1 = bytes.fromhex(aad1_hex) + aad0_hex = "436f756e742d30" + aad0 = bytes.fromhex(aad0_hex) - info_hex = "4f6465206f6e2061204772656369616e2055726e" - info = bytes.fromhex(info_hex) + aad1_hex = "436f756e742d31" + aad1 = bytes.fromhex(aad1_hex) - ct1_hex = "49f3b19b28a9ea9f43e8c71204c00d4a490ee7f61387b6719db765e948123b45b61633ef059ba22cd62437c8ba" - ct1 = bytes.fromhex(ct1_hex) + info_hex = "4f6465206f6e2061204772656369616e2055726e" + info = bytes.fromhex(info_hex) - aead_id = HPKE.AEAD.AES128_GCM + ct1_hex = "d3736bb256c19bfa93d79e8f80b7971262cb7c887e35c26370cfed62254369a1b52e3d505b79dd699f002bc8ed" + ct1 = bytes.fromhex(ct1_hex) - decryptor = HPKE.new(receiver_key=keyR, - aead_id=aead_id, - info=info, - psk=(psk_id, psk), - enc=enc) + aead_id = HPKE.AEAD.AES128_GCM - pt_X0 = decryptor.unseal(ct0, aad0) - self.assertEqual(pt_X0, pt) + decryptor = HPKE.new( + receiver_key=keyR, + sender_key=keyS.public_key(), + aead_id=aead_id, + info=info, + enc=enc, + ) - pt_X1 = decryptor.unseal(ct1, aad1) - self.assertEqual(pt_X1, pt) + pt_X0 = decryptor.unseal(ct0, aad0) + self.assertEqual(pt_X0, pt) - def test_x25519_mode_2(self): - # RFC x9180, A.1.3.1, seq 0 and 1 + pt_X1 = decryptor.unseal(ct1, aad1) + self.assertEqual(pt_X1, pt) - keyR_hex = "fdea67cf831f1ca98d8e27b1f6abeb5b7745e9d35348b80fa407ff6958f9137e" - keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + def test_x25519_mode_3(self): + # RFC x9180, A.1.4.1, seq 0 and 1 - keyS_hex = "dc4a146313cce60a278a5323d321f051c5707e9c45ba21a3479fecdf76fc69dd" - keyS = DH.import_x25519_private_key(bytes.fromhex(keyS_hex)) + keyR_hex = "cb29a95649dc5656c2d054c1aa0d3df0493155e9d5da6d7e344ed8b6a64a9423" + keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) - pt_hex = "4265617574792069732074727574682c20747275746820626561757479" - pt = bytes.fromhex(pt_hex) + keyS_hex = "fc1c87d2f3832adb178b431fce2ac77c7ca2fd680f3406c77b5ecdf818b119f4" + keyS = DH.import_x25519_private_key(bytes.fromhex(keyS_hex)) - ct0_hex = "5fd92cc9d46dbf8943e72a07e42f363ed5f721212cd90bcfd072bfd9f44e06b80fd17824947496e21b680c141b" - ct0 = bytes.fromhex(ct0_hex) + psk_id_hex = "456e6e796e20447572696e206172616e204d6f726961" + psk_id = bytes.fromhex(psk_id_hex) - enc_hex = "23fb952571a14a25e3d678140cd0e5eb47a0961bb18afcf85896e5453c312e76" - enc = bytes.fromhex(enc_hex) + psk_hex = "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82" + psk = bytes.fromhex(psk_hex) - aad0_hex = "436f756e742d30" - aad0 = bytes.fromhex(aad0_hex) + pt_hex = "4265617574792069732074727574682c20747275746820626561757479" + pt = bytes.fromhex(pt_hex) - aad1_hex = "436f756e742d31" - aad1 = bytes.fromhex(aad1_hex) + ct0_hex = "a84c64df1e11d8fd11450039d4fe64ff0c8a99fca0bd72c2d4c3e0400bc14a40f27e45e141a24001697737533e" + ct0 = bytes.fromhex(ct0_hex) - info_hex = "4f6465206f6e2061204772656369616e2055726e" - info = bytes.fromhex(info_hex) + enc_hex = "820818d3c23993492cc5623ab437a48a0a7ca3e9639c140fe1e33811eb844b7c" + enc = bytes.fromhex(enc_hex) - ct1_hex = "d3736bb256c19bfa93d79e8f80b7971262cb7c887e35c26370cfed62254369a1b52e3d505b79dd699f002bc8ed" - ct1 = bytes.fromhex(ct1_hex) + aad0_hex = "436f756e742d30" + aad0 = bytes.fromhex(aad0_hex) - aead_id = HPKE.AEAD.AES128_GCM + aad1_hex = "436f756e742d31" + aad1 = bytes.fromhex(aad1_hex) - decryptor = HPKE.new(receiver_key=keyR, - sender_key=keyS.public_key(), - aead_id=aead_id, - info=info, - enc=enc) + info_hex = "4f6465206f6e2061204772656369616e2055726e" + info = bytes.fromhex(info_hex) - pt_X0 = decryptor.unseal(ct0, aad0) - self.assertEqual(pt_X0, pt) + ct1_hex = "4d19303b848f424fc3c3beca249b2c6de0a34083b8e909b6aa4c3688505c05ffe0c8f57a0a4c5ab9da127435d9" + ct1 = bytes.fromhex(ct1_hex) - pt_X1 = decryptor.unseal(ct1, aad1) - self.assertEqual(pt_X1, pt) + aead_id = HPKE.AEAD.AES128_GCM - def test_x25519_mode_3(self): - # RFC x9180, A.1.4.1, seq 0 and 1 + decryptor = HPKE.new( + receiver_key=keyR, + sender_key=keyS.public_key(), + aead_id=aead_id, + psk=(psk_id, psk), + info=info, + enc=enc, + ) - keyR_hex = "cb29a95649dc5656c2d054c1aa0d3df0493155e9d5da6d7e344ed8b6a64a9423" - keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + pt_X0 = decryptor.unseal(ct0, aad0) + self.assertEqual(pt_X0, pt) - keyS_hex = "fc1c87d2f3832adb178b431fce2ac77c7ca2fd680f3406c77b5ecdf818b119f4" - keyS = DH.import_x25519_private_key(bytes.fromhex(keyS_hex)) - - psk_id_hex = "456e6e796e20447572696e206172616e204d6f726961" - psk_id = bytes.fromhex(psk_id_hex) - - psk_hex = "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82" - psk = bytes.fromhex(psk_hex) - - pt_hex = "4265617574792069732074727574682c20747275746820626561757479" - pt = bytes.fromhex(pt_hex) - - ct0_hex = "a84c64df1e11d8fd11450039d4fe64ff0c8a99fca0bd72c2d4c3e0400bc14a40f27e45e141a24001697737533e" - ct0 = bytes.fromhex(ct0_hex) - - enc_hex = "820818d3c23993492cc5623ab437a48a0a7ca3e9639c140fe1e33811eb844b7c" - enc = bytes.fromhex(enc_hex) - - aad0_hex = "436f756e742d30" - aad0 = bytes.fromhex(aad0_hex) - - aad1_hex = "436f756e742d31" - aad1 = bytes.fromhex(aad1_hex) - - info_hex = "4f6465206f6e2061204772656369616e2055726e" - info = bytes.fromhex(info_hex) - - ct1_hex = "4d19303b848f424fc3c3beca249b2c6de0a34083b8e909b6aa4c3688505c05ffe0c8f57a0a4c5ab9da127435d9" - ct1 = bytes.fromhex(ct1_hex) - - aead_id = HPKE.AEAD.AES128_GCM - - decryptor = HPKE.new(receiver_key=keyR, - sender_key=keyS.public_key(), - aead_id=aead_id, - psk=(psk_id, psk), - info=info, - enc=enc) - - pt_X0 = decryptor.unseal(ct0, aad0) - self.assertEqual(pt_X0, pt) - - pt_X1 = decryptor.unseal(ct1, aad1) - self.assertEqual(pt_X1, pt) + pt_X1 = decryptor.unseal(ct1, aad1) + self.assertEqual(pt_X1, pt) class HPKE_TestVectors(unittest.TestCase): - - def setUp(self): - self.vectors = [] - try: - import pycryptodome_test_vectors # type: ignore - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(init_dir, "Protocol", "wycheproof", "HPKE-test-vectors.json") - with open(full_file_name, "r") as f: - self.vectors = json.load(f) - except (FileNotFoundError, ImportError): - print("\nWarning: skipping extended tests for HPKE (install pycryptodome-test-vectors)") - - def import_private_key(self, key_hex, kem_id): - key_bin = unhexlify(key_hex) - if kem_id == 0x0010: - return ECC.construct(curve='p256', d=int.from_bytes(key_bin, - byteorder="big")) - elif kem_id == 0x0011: - return ECC.construct(curve='p384', d=int.from_bytes(key_bin, - byteorder="big")) - elif kem_id == 0x0012: - return ECC.construct(curve='p521', d=int.from_bytes(key_bin, - byteorder="big")) - elif kem_id == 0x0020: - return DH.import_x25519_private_key(key_bin) - elif kem_id == 0x0021: - return DH.import_x448_private_key(key_bin) - - def test_hpke_encap(self): - """Test HPKE encapsulation using test vectors.""" - - if not self.vectors: - self.skipTest("No test vectors available") - - for idx, vector in enumerate(self.vectors): - - kem_id = vector["kem_id"] - kdf_id = vector["kdf_id"] - aead_id = vector["aead_id"] - - # No export-only pseudo-cipher - if aead_id == 0xffff: - continue - - # We support only one KDF per curve - supported_combi = { - (0x10, 0x1): SHA256, - (0x11, 0x2): SHA384, - (0x12, 0x3): SHA512, - (0x20, 0x1): SHA256, - (0x21, 0x3): SHA512, - } - hashmod = supported_combi.get((kem_id, kdf_id)) - if hashmod is None: - continue - - with self.subTest(idx=idx, kem_id=kem_id, aead_id=aead_id): - - receiver_pub = self.import_private_key(vector["skRm"], - kem_id).public_key() - - sender_priv = None - if "skSm" in vector: - sender_priv = self.import_private_key(vector["skSm"], - kem_id) - - encap_key = self.import_private_key(vector["skEm"], kem_id) - - shared_secret, enc = HPKE.HPKE_Cipher._encap(receiver_pub, - kem_id, - hashmod, - sender_priv, - encap_key) - self.assertEqual(enc.hex(), vector["enc"]) - self.assertEqual(shared_secret, - unhexlify(vector["shared_secret"])) - - print(".", end="", flush=True) - - def test_hpke_unseal(self): - """Test HPKE encryption and decryption using test vectors.""" - - if not self.vectors: - self.skipTest("No test vectors available") - - for idx, vector in enumerate(self.vectors): - - kem_id = vector["kem_id"] - kdf_id = vector["kdf_id"] - aead_id = vector["aead_id"] - - # No export-only pseudo-cipher - if aead_id == 0xffff: - continue - - # We support only one KDF per curve - supported_combi = ( - (0x10, 0x1), - (0x11, 0x2), - (0x12, 0x3), - (0x20, 0x1), - (0x21, 0x3), - ) - if (kem_id, kdf_id) not in supported_combi: - continue - - with self.subTest(idx=idx, kem_id=kem_id, aead_id=aead_id): - - receiver_priv = self.import_private_key(vector["skRm"], - kem_id) - - sender_pub = None - if "skSm" in vector: - sender_priv = self.import_private_key(vector["skSm"], - kem_id) - sender_pub = sender_priv.public_key() - - encap_key = unhexlify(vector["enc"]) - - psk = None - if "psk_id" in vector: - psk = unhexlify(vector["psk_id"]), unhexlify(vector["psk"]) - - receiver_hpke = HPKE.new(receiver_key=receiver_priv, - aead_id=HPKE.AEAD(aead_id), - enc=encap_key, - sender_key=sender_pub, - psk=psk, - info=unhexlify(vector["info"])) - - for encryption in vector['encryptions']: - - plaintext = unhexlify(encryption["pt"]) - ciphertext = unhexlify(encryption["ct"]) - aad = unhexlify(encryption["aad"]) - - # Decrypt (unseal) - decrypted = receiver_hpke.unseal(ciphertext, aad) - self.assertEqual(decrypted, plaintext, "Decryption failed") - - print(".", end="", flush=True) + def setUp(self): + self.vectors = [] + try: + import pycryptodome_test_vectors # type: ignore + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(init_dir, "Protocol", "wycheproof", "HPKE-test-vectors.json") + with open(full_file_name, "r") as f: + self.vectors = json.load(f) + except (FileNotFoundError, ImportError): + print("\nWarning: skipping extended tests for HPKE (install pycryptodome-test-vectors)") + + def import_private_key(self, key_hex, kem_id): + key_bin = unhexlify(key_hex) + if kem_id == 0x0010: + return ECC.construct( + curve="p256", + d=int.from_bytes( + key_bin, + byteorder="big", + ), + ) + elif kem_id == 0x0011: + return ECC.construct( + curve="p384", + d=int.from_bytes( + key_bin, + byteorder="big", + ), + ) + elif kem_id == 0x0012: + return ECC.construct( + curve="p521", + d=int.from_bytes( + key_bin, + byteorder="big", + ), + ) + elif kem_id == 0x0020: + return DH.import_x25519_private_key(key_bin) + elif kem_id == 0x0021: + return DH.import_x448_private_key(key_bin) + + def test_hpke_encap(self): + """Test HPKE encapsulation using test vectors.""" + + if not self.vectors: + self.skipTest("No test vectors available") + + for idx, vector in enumerate(self.vectors): + kem_id = vector["kem_id"] + kdf_id = vector["kdf_id"] + aead_id = vector["aead_id"] + + # No export-only pseudo-cipher + if aead_id == 0xFFFF: + continue + + # We support only one KDF per curve + supported_combi = { + (0x10, 0x1): SHA256, + (0x11, 0x2): SHA384, + (0x12, 0x3): SHA512, + (0x20, 0x1): SHA256, + (0x21, 0x3): SHA512, + } + hashmod = supported_combi.get((kem_id, kdf_id)) + if hashmod is None: + continue + + with self.subTest(idx=idx, kem_id=kem_id, aead_id=aead_id): + receiver_pub = self.import_private_key( + vector["skRm"], + kem_id, + ).public_key() + + sender_priv = None + if "skSm" in vector: + sender_priv = self.import_private_key( + vector["skSm"], + kem_id, + ) + + encap_key = self.import_private_key(vector["skEm"], kem_id) + + shared_secret, enc = HPKE.HPKE_Cipher._encap( + receiver_pub, + kem_id, + hashmod, + sender_priv, + encap_key, + ) + self.assertEqual(enc.hex(), vector["enc"]) + self.assertEqual( + shared_secret, + unhexlify(vector["shared_secret"]), + ) + + print(".", end="", flush=True) + + def test_hpke_unseal(self): + """Test HPKE encryption and decryption using test vectors.""" + + if not self.vectors: + self.skipTest("No test vectors available") + + for idx, vector in enumerate(self.vectors): + kem_id = vector["kem_id"] + kdf_id = vector["kdf_id"] + aead_id = vector["aead_id"] + + # No export-only pseudo-cipher + if aead_id == 0xFFFF: + continue + + # We support only one KDF per curve + supported_combi = ( + (0x10, 0x1), + (0x11, 0x2), + (0x12, 0x3), + (0x20, 0x1), + (0x21, 0x3), + ) + if (kem_id, kdf_id) not in supported_combi: + continue + + with self.subTest(idx=idx, kem_id=kem_id, aead_id=aead_id): + receiver_priv = self.import_private_key( + vector["skRm"], + kem_id, + ) + + sender_pub = None + if "skSm" in vector: + sender_priv = self.import_private_key( + vector["skSm"], + kem_id, + ) + sender_pub = sender_priv.public_key() + + encap_key = unhexlify(vector["enc"]) + + psk = None + if "psk_id" in vector: + psk = unhexlify(vector["psk_id"]), unhexlify(vector["psk"]) + + receiver_hpke = HPKE.new( + receiver_key=receiver_priv, + aead_id=HPKE.AEAD(aead_id), + enc=encap_key, + sender_key=sender_pub, + psk=psk, + info=unhexlify(vector["info"]), + ) + + for encryption in vector["encryptions"]: + plaintext = unhexlify(encryption["pt"]) + ciphertext = unhexlify(encryption["ct"]) + aad = unhexlify(encryption["aad"]) + + # Decrypt (unseal) + decrypted = receiver_hpke.unseal(ciphertext, aad) + self.assertEqual(decrypted, plaintext, "Decryption failed") + + print(".", end="", flush=True) def get_tests(config={}): + tests = [] + tests += list_test_cases(HPKE_Tests) + + if config.get("slow_tests"): + tests += list_test_cases(HPKE_TestVectors) - tests = [] - tests += list_test_cases(HPKE_Tests) + return tests - if config.get('slow_tests'): - tests += list_test_cases(HPKE_TestVectors) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_KDF.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_KDF.py index eafe3499..8d971657 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_KDF.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_KDF.py @@ -31,779 +31,1202 @@ from Cryptodome.Hash import SHA1, HMAC, SHA256, MD5, SHA224, SHA384, SHA512 from Cryptodome.Cipher import AES, DES3 -from Cryptodome.Protocol.KDF import (PBKDF1, PBKDF2, _S2V, HKDF, scrypt, - bcrypt, bcrypt_check, - SP800_108_Counter) +from Cryptodome.Protocol.KDF import ( + PBKDF1, + PBKDF2, + _S2V, + HKDF, + scrypt, + bcrypt, + bcrypt_check, + SP800_108_Counter, +) from Cryptodome.Protocol.KDF import _bcrypt_decode def t2b(t): - if t is None: - return None - t2 = t.replace(" ", "").replace("\n", "") - return unhexlify(b(t2)) + if t is None: + return None + t2 = t.replace(" ", "").replace("\n", "") + return unhexlify(b(t2)) class TestVector(object): - pass + pass class PBKDF1_Tests(unittest.TestCase): - - # List of tuples with test data. - # Each tuple is made up by: - # Item #0: a pass phrase - # Item #1: salt (8 bytes encoded in hex) - # Item #2: output key length - # Item #3: iterations to use - # Item #4: expected result (encoded in hex) - _testData = ( - # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf - ("password", "78578E5A5D63CB06", 16, 1000, "DC19847E05C64D2FAF10EBFB4A3D2A20"), - ) - - def test1(self): - v = self._testData[0] - res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1) - self.assertEqual(res, t2b(v[4])) + # List of tuples with test data. + # Each tuple is made up by: + # Item #0: a pass phrase + # Item #1: salt (8 bytes encoded in hex) + # Item #2: output key length + # Item #3: iterations to use + # Item #4: expected result (encoded in hex) + _testData = ( + # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf + ("password", "78578E5A5D63CB06", 16, 1000, "DC19847E05C64D2FAF10EBFB4A3D2A20"), + ) + + def test1(self): + v = self._testData[0] + res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1) + self.assertEqual(res, t2b(v[4])) class PBKDF2_Tests(unittest.TestCase): - - # List of tuples with test data. - # Each tuple is made up by: - # Item #0: a pass phrase - # Item #1: salt (encoded in hex) - # Item #2: output key length - # Item #3: iterations to use - # Item #4: hash module - # Item #5: expected result (encoded in hex) - _testData = ( - # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf - ("password","78578E5A5D63CB06",24,2048, SHA1, "BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"), - # From RFC 6050 - ("password","73616c74", 20, 1, SHA1, "0c60c80f961f0e71f3a9b524af6012062fe037a6"), - ("password","73616c74", 20, 2, SHA1, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"), - ("password","73616c74", 20, 4096, SHA1, "4b007901b765489abead49d926f721d065a429c1"), - ("passwordPASSWORDpassword","73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74", - 25, 4096, SHA1, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"), - ( 'pass\x00word',"7361006c74",16,4096, SHA1, "56fa6aa75548099dcc37d7f03425e0c3"), - # From draft-josefsson-scrypt-kdf-01, Chapter 10 - ( 'passwd', '73616c74', 64, 1, SHA256, "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783"), - ( 'Password', '4e61436c', 64, 80000, SHA256, "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d"), - ) - - def test1(self): - # Test only for HMAC-SHA1 as PRF - - def prf_SHA1(p,s): - return HMAC.new(p,s,SHA1).digest() - - def prf_SHA256(p,s): - return HMAC.new(p,s,SHA256).digest() - - for i in range(len(self._testData)): - v = self._testData[i] - password = v[0] - salt = t2b(v[1]) - out_len = v[2] - iters = v[3] - hash_mod = v[4] - expected = t2b(v[5]) - - if hash_mod is SHA1: - res = PBKDF2(password, salt, out_len, iters) - self.assertEqual(res, expected) - - res = PBKDF2(password, salt, out_len, iters, prf_SHA1) - self.assertEqual(res, expected) - else: - res = PBKDF2(password, salt, out_len, iters, prf_SHA256) - self.assertEqual(res, expected) - - def test2(self): - # Verify that prf and hmac_hash_module are mutual exclusive - def prf_SHA1(p,s): - return HMAC.new(p,s,SHA1).digest() - - self.assertRaises(ValueError, PBKDF2, b("xxx"), b("yyy"), 16, 100, - prf=prf_SHA1, hmac_hash_module=SHA1) - - def test3(self): - # Verify that hmac_hash_module works like prf - - password = b("xxx") - salt = b("yyy") - - for hashmod in (MD5, SHA1, SHA224, SHA256, SHA384, SHA512): - - pr1 = PBKDF2(password, salt, 16, 100, - prf=lambda p, s: HMAC.new(p,s,hashmod).digest()) - pr2 = PBKDF2(password, salt, 16, 100, hmac_hash_module=hashmod) - - self.assertEqual(pr1, pr2) - - def test4(self): - # Verify that PBKDF2 can take bytes or strings as password or salt - k1 = PBKDF2("xxx", b("yyy"), 16, 10) - k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) - self.assertEqual(k1, k2) - - k1 = PBKDF2(b("xxx"), "yyy", 16, 10) - k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) - self.assertEqual(k1, k2) + # List of tuples with test data. + # Each tuple is made up by: + # Item #0: a pass phrase + # Item #1: salt (encoded in hex) + # Item #2: output key length + # Item #3: iterations to use + # Item #4: hash module + # Item #5: expected result (encoded in hex) + _testData = ( + # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf + ("password", "78578E5A5D63CB06", 24, 2048, SHA1, "BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"), + # From RFC 6050 + ("password", "73616c74", 20, 1, SHA1, "0c60c80f961f0e71f3a9b524af6012062fe037a6"), + ("password", "73616c74", 20, 2, SHA1, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"), + ("password", "73616c74", 20, 4096, SHA1, "4b007901b765489abead49d926f721d065a429c1"), + ( + "passwordPASSWORDpassword", + "73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74", + 25, + 4096, + SHA1, + "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038", + ), + ("pass\x00word", "7361006c74", 16, 4096, SHA1, "56fa6aa75548099dcc37d7f03425e0c3"), + # From draft-josefsson-scrypt-kdf-01, Chapter 10 + ( + "passwd", + "73616c74", + 64, + 1, + SHA256, + "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783", + ), + ( + "Password", + "4e61436c", + 64, + 80000, + SHA256, + "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d", + ), + ) + + def test1(self): + # Test only for HMAC-SHA1 as PRF + + def prf_SHA1(p, s): + return HMAC.new(p, s, SHA1).digest() + + def prf_SHA256(p, s): + return HMAC.new(p, s, SHA256).digest() + + for i in range(len(self._testData)): + v = self._testData[i] + password = v[0] + salt = t2b(v[1]) + out_len = v[2] + iters = v[3] + hash_mod = v[4] + expected = t2b(v[5]) + + if hash_mod is SHA1: + res = PBKDF2(password, salt, out_len, iters) + self.assertEqual(res, expected) + + res = PBKDF2(password, salt, out_len, iters, prf_SHA1) + self.assertEqual(res, expected) + else: + res = PBKDF2(password, salt, out_len, iters, prf_SHA256) + self.assertEqual(res, expected) + + def test2(self): + # Verify that prf and hmac_hash_module are mutual exclusive + def prf_SHA1(p, s): + return HMAC.new(p, s, SHA1).digest() + + self.assertRaises( + ValueError, + PBKDF2, + b("xxx"), + b("yyy"), + 16, + 100, + prf=prf_SHA1, + hmac_hash_module=SHA1, + ) + + def test3(self): + # Verify that hmac_hash_module works like prf + + password = b("xxx") + salt = b("yyy") + + for hashmod in (MD5, SHA1, SHA224, SHA256, SHA384, SHA512): + pr1 = PBKDF2( + password, + salt, + 16, + 100, + prf=lambda p, s: HMAC.new(p, s, hashmod).digest(), + ) + pr2 = PBKDF2(password, salt, 16, 100, hmac_hash_module=hashmod) + + self.assertEqual(pr1, pr2) + + def test4(self): + # Verify that PBKDF2 can take bytes or strings as password or salt + k1 = PBKDF2("xxx", b("yyy"), 16, 10) + k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) + self.assertEqual(k1, k2) + + k1 = PBKDF2(b("xxx"), "yyy", 16, 10) + k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) + self.assertEqual(k1, k2) class S2V_Tests(unittest.TestCase): - - # Sequence of test vectors. - # Each test vector is made up by: - # Item #0: a tuple of strings - # Item #1: an AES key - # Item #2: the result - # Item #3: the cipher module S2V is based on - # Everything is hex encoded - _testData = [ - - # RFC5297, A.1 - ( - ( '101112131415161718191a1b1c1d1e1f2021222324252627', - '112233445566778899aabbccddee' ), - 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0', - '85632d07c6e8f37f950acd320a2ecc93', - AES - ), - - # RFC5297, A.2 - ( - ( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddcc'+ - 'bbaa99887766554433221100', - '102030405060708090a0', - '09f911029d74e35bd84156c5635688c0', - '7468697320697320736f6d6520706c61'+ - '696e7465787420746f20656e63727970'+ - '74207573696e67205349562d414553'), - '7f7e7d7c7b7a79787776757473727170', - '7bdb6e3b432667eb06f4d14bff2fbd0f', - AES - ), - - ] - - def test1(self): - """Verify correctness of test vector""" - for tv in self._testData: - s2v = _S2V.new(t2b(tv[1]), tv[3]) - for s in tv[0]: - s2v.update(t2b(s)) - result = s2v.derive() - self.assertEqual(result, t2b(tv[2])) - - def test2(self): - """Verify that no more than 127(AES) and 63(TDES) - components are accepted.""" - key = bchr(0) * 8 + bchr(255) * 8 - for module in (AES, DES3): - s2v = _S2V.new(key, module) - max_comps = module.block_size*8-1 - for i in range(max_comps): - s2v.update(b("XX")) - self.assertRaises(TypeError, s2v.update, b("YY")) + # Sequence of test vectors. + # Each test vector is made up by: + # Item #0: a tuple of strings + # Item #1: an AES key + # Item #2: the result + # Item #3: the cipher module S2V is based on + # Everything is hex encoded + _testData = [ + # RFC5297, A.1 + ( + ( + "101112131415161718191a1b1c1d1e1f2021222324252627", + "112233445566778899aabbccddee", + ), + "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0", + "85632d07c6e8f37f950acd320a2ecc93", + AES, + ), + # RFC5297, A.2 + ( + ( + "00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddcc" + "bbaa99887766554433221100", + "102030405060708090a0", + "09f911029d74e35bd84156c5635688c0", + "7468697320697320736f6d6520706c61" + + "696e7465787420746f20656e63727970" + + "74207573696e67205349562d414553", + ), + "7f7e7d7c7b7a79787776757473727170", + "7bdb6e3b432667eb06f4d14bff2fbd0f", + AES, + ), + ] + + def test1(self): + """Verify correctness of test vector""" + for tv in self._testData: + s2v = _S2V.new(t2b(tv[1]), tv[3]) + for s in tv[0]: + s2v.update(t2b(s)) + result = s2v.derive() + self.assertEqual(result, t2b(tv[2])) + + def test2(self): + """Verify that no more than 127(AES) and 63(TDES) + components are accepted.""" + key = bchr(0) * 8 + bchr(255) * 8 + for module in (AES, DES3): + s2v = _S2V.new(key, module) + max_comps = module.block_size * 8 - 1 + for i in range(max_comps): + s2v.update(b("XX")) + self.assertRaises(TypeError, s2v.update, b("YY")) class HKDF_Tests(unittest.TestCase): - - # Test vectors from RFC5869, Appendix A - # Each tuple is made up by: - # Item #0: hash module - # Item #1: secret - # Item #2: salt - # Item #3: context - # Item #4: expected result - _test_vector = ( - ( - SHA256, - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - 42, - "3cb25f25faacd57a90434f64d0362f2a" + - "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + - "34007208d5b887185865" - ), - ( - SHA256, - "000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f" + - "404142434445464748494a4b4c4d4e4f", - "606162636465666768696a6b6c6d6e6f" + - "707172737475767778797a7b7c7d7e7f" + - "808182838485868788898a8b8c8d8e8f" + - "909192939495969798999a9b9c9d9e9f" + - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", - 82, - "b11e398dc80327a1c8e7f78c596a4934" + - "4f012eda2d4efad8a050cc4c19afa97c" + - "59045a99cac7827271cb41c65e590e09" + - "da3275600c2f09b8367793a9aca3db71" + - "cc30c58179ec3e87c14c01d5c1f3434f" + - "1d87" - ), - ( - SHA256, - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - None, - None, - 42, - "8da4e775a563c18f715f802a063c5a31" + - "b8a11f5c5ee1879ec3454e5f3c738d2d" + - "9d201395faa4b61a96c8" - ), - ( - SHA1, - "0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - 42, - "085a01ea1b10f36933068b56efa5ad81" + - "a4f14b822f5b091568a9cdd4f155fda2" + - "c22e422478d305f3f896" - ), - ( - SHA1, - "000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f" + - "404142434445464748494a4b4c4d4e4f", - "606162636465666768696a6b6c6d6e6f" + - "707172737475767778797a7b7c7d7e7f" + - "808182838485868788898a8b8c8d8e8f" + - "909192939495969798999a9b9c9d9e9f" + - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", - 82, - "0bd770a74d1160f7c9f12cd5912a06eb" + - "ff6adcae899d92191fe4305673ba2ffe" + - "8fa3f1a4e5ad79f3f334b3b202b2173c" + - "486ea37ce3d397ed034c7f9dfeb15c5e" + - "927336d0441f4c4300e2cff0d0900b52" + - "d3b4" - ), - ( - SHA1, - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "", - "", - 42, - "0ac1af7002b3d761d1e55298da9d0506" + - "b9ae52057220a306e07b6b87e8df21d0" + - "ea00033de03984d34918" - ), - ( - SHA1, - "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", - None, - "", - 42, - "2c91117204d745f3500d636a62f64f0a" + - "b3bae548aa53d423b0d1f27ebba6f5e5" + - "673a081d70cce7acfc48" - ) - ) - - def test1(self): - for tv in self._test_vector: - secret, salt, info, exp = [ t2b(tv[x]) for x in (1,2,3,5) ] - key_len, hashmod = [ tv[x] for x in (4,0) ] - - output = HKDF(secret, key_len, salt, hashmod, 1, info) - self.assertEqual(output, exp) - - def test2(self): - ref = HKDF(b("XXXXXX"), 12, b("YYYY"), SHA1) - - # Same output, but this time split over 2 keys - key1, key2 = HKDF(b("XXXXXX"), 6, b("YYYY"), SHA1, 2) - self.assertEqual((ref[:6], ref[6:]), (key1, key2)) - - # Same output, but this time split over 3 keys - key1, key2, key3 = HKDF(b("XXXXXX"), 4, b("YYYY"), SHA1, 3) - self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) + # Test vectors from RFC5869, Appendix A + # Each tuple is made up by: + # Item #0: hash module + # Item #1: secret + # Item #2: salt + # Item #3: context + # Item #4: expected result + _test_vector = ( + ( + SHA256, + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + 42, + "3cb25f25faacd57a90434f64d0362f2a" + "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + "34007208d5b887185865", + ), + ( + SHA256, + "000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f" + + "707172737475767778797a7b7c7d7e7f" + + "808182838485868788898a8b8c8d8e8f" + + "909192939495969798999a9b9c9d9e9f" + + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + 82, + "b11e398dc80327a1c8e7f78c596a4934" + + "4f012eda2d4efad8a050cc4c19afa97c" + + "59045a99cac7827271cb41c65e590e09" + + "da3275600c2f09b8367793a9aca3db71" + + "cc30c58179ec3e87c14c01d5c1f3434f" + + "1d87", + ), + ( + SHA256, + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + None, + None, + 42, + "8da4e775a563c18f715f802a063c5a31" + "b8a11f5c5ee1879ec3454e5f3c738d2d" + "9d201395faa4b61a96c8", + ), + ( + SHA1, + "0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + 42, + "085a01ea1b10f36933068b56efa5ad81" + "a4f14b822f5b091568a9cdd4f155fda2" + "c22e422478d305f3f896", + ), + ( + SHA1, + "000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f" + + "707172737475767778797a7b7c7d7e7f" + + "808182838485868788898a8b8c8d8e8f" + + "909192939495969798999a9b9c9d9e9f" + + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + 82, + "0bd770a74d1160f7c9f12cd5912a06eb" + + "ff6adcae899d92191fe4305673ba2ffe" + + "8fa3f1a4e5ad79f3f334b3b202b2173c" + + "486ea37ce3d397ed034c7f9dfeb15c5e" + + "927336d0441f4c4300e2cff0d0900b52" + + "d3b4", + ), + ( + SHA1, + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + 42, + "0ac1af7002b3d761d1e55298da9d0506" + "b9ae52057220a306e07b6b87e8df21d0" + "ea00033de03984d34918", + ), + ( + SHA1, + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + None, + "", + 42, + "2c91117204d745f3500d636a62f64f0a" + "b3bae548aa53d423b0d1f27ebba6f5e5" + "673a081d70cce7acfc48", + ), + ) + + def test1(self): + for tv in self._test_vector: + secret, salt, info, exp = [t2b(tv[x]) for x in (1, 2, 3, 5)] + key_len, hashmod = [tv[x] for x in (4, 0)] + + output = HKDF(secret, key_len, salt, hashmod, 1, info) + self.assertEqual(output, exp) + + def test2(self): + ref = HKDF(b("XXXXXX"), 12, b("YYYY"), SHA1) + + # Same output, but this time split over 2 keys + key1, key2 = HKDF(b("XXXXXX"), 6, b("YYYY"), SHA1, 2) + self.assertEqual((ref[:6], ref[6:]), (key1, key2)) + + # Same output, but this time split over 3 keys + key1, key2, key3 = HKDF(b("XXXXXX"), 4, b("YYYY"), SHA1, 3) + self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) class scrypt_Tests(unittest.TestCase): - - # Test vectors taken from - # https://tools.ietf.org/html/rfc7914 - # - password - # - salt - # - N - # - r - # - p - data = ( - ( - "", - "", - 16, # 2K - 1, - 1, - """ + # Test vectors taken from + # https://tools.ietf.org/html/rfc7914 + # - password + # - salt + # - N + # - r + # - p + data = ( + ( + "", + "", + 16, # 2K + 1, + 1, + """ 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06 - """ - ), - ( - "password", - "NaCl", - 1024, # 1M - 8, - 16, - """ + """, + ), + ( + "password", + "NaCl", + 1024, # 1M + 8, + 16, + """ fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40 - """ - ), - ( - "pleaseletmein", - "SodiumChloride", - 16384, # 16M - 8, - 1, - """ + """, + ), + ( + "pleaseletmein", + "SodiumChloride", + 16384, # 16M + 8, + 1, + """ 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87 - """ - ), - ( - "pleaseletmein", - "SodiumChloride", - 1048576, # 1G - 8, - 1, - """ + """, + ), + ( + "pleaseletmein", + "SodiumChloride", + 1048576, # 1G + 8, + 1, + """ 21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81 ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47 8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3 37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4 - """ - ), - ) - - def setUp(self): - new_test_vectors = [] - for tv in self.data: - new_tv = TestVector() - new_tv.P = b(tv[0]) - new_tv.S = b(tv[1]) - new_tv.N = tv[2] - new_tv.r = tv[3] - new_tv.p = tv[4] - new_tv.output = t2b(tv[5]) - new_tv.dkLen = len(new_tv.output) - new_test_vectors.append(new_tv) - self.data = new_test_vectors - - def test2(self): - - for tv in self.data: - try: - output = scrypt(tv.P, tv.S, tv.dkLen, tv.N, tv.r, tv.p) - except ValueError as e: - if " 2 " in str(e) and tv.N >= 1048576: - import warnings - warnings.warn("Not enough memory to unit test scrypt() with N=1048576", RuntimeWarning) - continue - else: - raise e - self.assertEqual(output, tv.output) - - def test3(self): - ref = scrypt(b("password"), b("salt"), 12, 16, 1, 1) - - # Same output, but this time split over 2 keys - key1, key2 = scrypt(b("password"), b("salt"), 6, 16, 1, 1, 2) - self.assertEqual((ref[:6], ref[6:]), (key1, key2)) - - # Same output, but this time split over 3 keys - key1, key2, key3 = scrypt(b("password"), b("salt"), 4, 16, 1, 1, 3) - self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) + """, + ), + ) + + def setUp(self): + new_test_vectors = [] + for tv in self.data: + new_tv = TestVector() + new_tv.P = b(tv[0]) + new_tv.S = b(tv[1]) + new_tv.N = tv[2] + new_tv.r = tv[3] + new_tv.p = tv[4] + new_tv.output = t2b(tv[5]) + new_tv.dkLen = len(new_tv.output) + new_test_vectors.append(new_tv) + self.data = new_test_vectors + + def test2(self): + for tv in self.data: + try: + output = scrypt(tv.P, tv.S, tv.dkLen, tv.N, tv.r, tv.p) + except ValueError as e: + if " 2 " in str(e) and tv.N >= 1048576: + import warnings + + warnings.warn("Not enough memory to unit test scrypt() with N=1048576", RuntimeWarning) + continue + else: + raise e + self.assertEqual(output, tv.output) + + def test3(self): + ref = scrypt(b("password"), b("salt"), 12, 16, 1, 1) + + # Same output, but this time split over 2 keys + key1, key2 = scrypt(b("password"), b("salt"), 6, 16, 1, 1, 2) + self.assertEqual((ref[:6], ref[6:]), (key1, key2)) + + # Same output, but this time split over 3 keys + key1, key2, key3 = scrypt(b("password"), b("salt"), 4, 16, 1, 1, 3) + self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) class bcrypt_Tests(unittest.TestCase): - - def test_negative_cases(self): - self.assertRaises(ValueError, bcrypt, b"1" * 73, 10) - self.assertRaises(ValueError, bcrypt, b"1" * 10, 3) - self.assertRaises(ValueError, bcrypt, b"1" * 10, 32) - self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"") - self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1") - self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1" * 17) - self.assertRaises(ValueError, bcrypt, b"1\x00" * 10, 4) - - def test_bytearray_mismatch(self): - ref = bcrypt("pwd", 4) - bcrypt_check("pwd", ref) - bref = bytearray(ref) - bcrypt_check("pwd", bref) - - wrong = ref[:-1] + bchr(bref[-1] ^ 0x01) - self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) - - wrong = b"x" + ref[1:] - self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) - - # https://github.com/patrickfav/bcrypt/wiki/Published-Test-Vectors - - def test_empty_password(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"", 4, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$04$zVHmKQtGGQob.b/Nc7l9NO8UlrYcW05FiuCj/SxsFO/ZtiN9.mNzy"), - (b"", 5, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$05$zVHmKQtGGQob.b/Nc7l9NOWES.1hkVBgy5IWImh9DOjKNU8atY4Iy"), - (b"", 6, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$06$zVHmKQtGGQob.b/Nc7l9NOjOl7l4oz3WSh5fJ6414Uw8IXRAUoiaO"), - (b"", 7, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$07$zVHmKQtGGQob.b/Nc7l9NOBsj1dQpBA1HYNGpIETIByoNX9jc.hOi"), - (b"", 8, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$08$zVHmKQtGGQob.b/Nc7l9NOiLTUh/9MDpX86/DLyEzyiFjqjBFePgO"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_random_password_and_salt_short_pw(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"<.S.2K(Zq'", 4, b"VYAclAMpaXY/oqAo9yUpku", b"$2a$04$VYAclAMpaXY/oqAo9yUpkuWmoYywaPzyhu56HxXpVltnBIfmO9tgu"), - (b"5.rApO%5jA", 5, b"kVNDrnYKvbNr5AIcxNzeIu", b"$2a$05$kVNDrnYKvbNr5AIcxNzeIuRcyIF5cZk6UrwHGxENbxP5dVv.WQM/G"), - (b"oW++kSrQW^", 6, b"QLKkRMH9Am6irtPeSKN5sO", b"$2a$06$QLKkRMH9Am6irtPeSKN5sObJGr3j47cO6Pdf5JZ0AsJXuze0IbsNm"), - (b"ggJ\\KbTnDG", 7, b"4H896R09bzjhapgCPS/LYu", b"$2a$07$4H896R09bzjhapgCPS/LYuMzAQluVgR5iu/ALF8L8Aln6lzzYXwbq"), - (b"49b0:;VkH/", 8, b"hfvO2retKrSrx5f2RXikWe", b"$2a$08$hfvO2retKrSrx5f2RXikWeFWdtSesPlbj08t/uXxCeZoHRWDz/xFe"), - (b">9N^5jc##'", 9, b"XZLvl7rMB3EvM0c1.JHivu", b"$2a$09$XZLvl7rMB3EvM0c1.JHivuIDPJWeNJPTVrpjZIEVRYYB/mF6cYgJK"), - (b"\\$ch)s4WXp", 10, b"aIjpMOLK5qiS9zjhcHR5TO", b"$2a$10$aIjpMOLK5qiS9zjhcHR5TOU7v2NFDmcsBmSFDt5EHOgp/jeTF3O/q"), - (b"RYoj\\_>2P7", 12, b"esIAHiQAJNNBrsr5V13l7.", b"$2a$12$esIAHiQAJNNBrsr5V13l7.RFWWJI2BZFtQlkFyiWXjou05GyuREZa"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_random_password_and_salt_long_pw(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"^Q&\"]A`%/A(BVGt>QaX0M-#1ghq_+\":Y0CRmY", 5, b"YuQvhokOGVnevctykUYpKu", b"$2a$05$YuQvhokOGVnevctykUYpKutZD2pWeGGYn3auyLOasguMY3/0BbIyq"), - (b"F%uN/j>[GuB7-jB'_Yj!Tnb7Y!u^6)", 6, b"5L3vpQ0tG9O7k5gQ8nAHAe", b"$2a$06$5L3vpQ0tG9O7k5gQ8nAHAe9xxQiOcOLh8LGcI0PLWhIznsDt.S.C6"), - (b"Z>BobP32ub\"Cfe*Q<-q-=tRSjOBh8\\mLNW.", 9, b"nArqOfdCsD9kIbVnAixnwe", b"$2a$09$nArqOfdCsD9kIbVnAixnwe6s8QvyPYWtQBpEXKir2OJF9/oNBsEFe"), - (b"/MH51`!BP&0tj3%YCA;Xk%e3S`o\\EI", 10, b"ePiAc.s.yoBi3B6p1iQUCe", b"$2a$10$ePiAc.s.yoBi3B6p1iQUCezn3mraLwpVJ5XGelVyYFKyp5FZn/y.u"), - (b"ptAP\"mcg6oH.\";c0U2_oll.OKi5?Ui\"^ai#iQH7ZFtNMfs3AROnIncE9\"BNNoEgO[[*Yk8;RQ(#S,;I+aT", - 5, b"wgkOlGNXIVE2fWkT3gyRoO", b"$2a$05$wgkOlGNXIVE2fWkT3gyRoOqWi4gbi1Wv2Q2Jx3xVs3apl1w.Wtj8C"), - (b"M.E1=dt<.L0Q&p;94NfGm_Oo23+Kpl@M5?WIAL.[@/:'S)W96G8N^AWb7_smmC]>7#fGoB", - 6, b"W9zTCl35nEvUukhhFzkKMe", b"$2a$06$W9zTCl35nEvUukhhFzkKMekjT9/pj7M0lihRVEZrX3m8/SBNZRX7i"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_increasing_password_length(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"a", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.l4WvgHIVg17ZawDIrDM2IjlE64GDNQS"), - (b"aa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.AyUxBk.ThHlsLvRTH7IqcG7yVHJ3SXq"), - (b"aaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.BxOVac5xPB6XFdRc/ZrzM9FgZkqmvbW"), - (b"aaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.Qbr209bpCtfl5hN7UQlG/L4xiD3AKau"), - (b"aaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.oWszihPjDZI0ypReKsaDOW1jBl7oOii"), - (b"aaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ./k.Xxn9YiqtV/sxh3EHbnOHd0Qsq27K"), - (b"aaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.PYJqRFQbgRbIjMd5VNKmdKS4sBVOyDe"), - (b"aaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ..VMYfzaw1wP/SGxowpLeGf13fxCCt.q"), - (b"aaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.5B0p054nO5WgAD1n04XslDY/bqY9RJi"), - (b"aaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.INBTgqm7sdlBJDg.J5mLMSRK25ri04y"), - (b"aaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.s3y7CdFD0OR5p6rsZw/eZ.Dla40KLfm"), - (b"aaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.Jx742Djra6Q7PqJWnTAS.85c28g.Siq"), - (b"aaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.oKMXW3EZcPHcUV0ib5vDBnh9HojXnLu"), - (b"aaaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.w6nIjWpDPNSH5pZUvLjC1q25ONEQpeS"), - (b"aaaaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.k1b2/r9A/hxdwKEKurg6OCn4MwMdiGq"), - (b"aaaaaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.3prCNHVX1Ws.7Hm2bJxFUnQOX9f7DFa"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_non_ascii_characters(self): - # password, cost, salt, bcrypt hash - tvs = [ - ("àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", 4, b"D3qS2aoTVyqM7z8v8crLm.", b"$2a$04$D3qS2aoTVyqM7z8v8crLm.3nKt4CzBZJbyFB.ZebmfCvRw7BGs.Xm"), - ("àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", 5, b"VA1FujiOCMPkUHQ8kF7IaO", b"$2a$05$VA1FujiOCMPkUHQ8kF7IaOg7NGaNvpxwWzSluQutxEVmbZItRTsAa"), - ("àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", 6, b"TXiaNrPeBSz5ugiQlehRt.", b"$2a$06$TXiaNrPeBSz5ugiQlehRt.gwpeDQnXWteQL4z2FulouBr6G7D9KUi"), - ("âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", 4, b"YTn1Qlvps8e1odqMn6G5x.", b"$2a$04$YTn1Qlvps8e1odqMn6G5x.85pqKql6w773EZJAExk7/BatYAI4tyO"), - ("âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", 5, b"C.8k5vJKD2NtfrRI9o17DO", b"$2a$05$C.8k5vJKD2NtfrRI9o17DOfIW0XnwItA529vJnh2jzYTb1QdoY0py"), - ("âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", 6, b"xqfRPj3RYAgwurrhcA6uRO", b"$2a$06$xqfRPj3RYAgwurrhcA6uROtGlXDp/U6/gkoDYHwlubtcVcNft5.vW"), - ("ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", 4, b"y8vGgMmr9EdyxP9rmMKjH.", b"$2a$04$y8vGgMmr9EdyxP9rmMKjH.wv2y3r7yRD79gykQtmb3N3zrwjKsyay"), - ("ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", 5, b"iYH4XIKAOOm/xPQs7xKP1u", b"$2a$05$iYH4XIKAOOm/xPQs7xKP1upD0cWyMn3Jf0ZWiizXbEkVpS41K1dcO"), - ("ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", 6, b"wCOob.D0VV8twafNDB2ape", b"$2a$06$wCOob.D0VV8twafNDB2apegiGD5nqF6Y1e6K95q6Y.R8C4QGd265q"), - ("ΔημοσιεύθηκεστηνΕφημερίδατης", 4, b"E5SQtS6P4568MDXW7cyUp.", b"$2a$04$E5SQtS6P4568MDXW7cyUp.18wfDisKZBxifnPZjAI1d/KTYMfHPYO"), - ("АБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмН", 4, b"03e26gQFHhQwRNf81/ww9.", b"$2a$04$03e26gQFHhQwRNf81/ww9.p1UbrNwxpzWjLuT.zpTLH4t/w5WhAhC"), - ("нОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮю", 4, b"PHNoJwpXCfe32nUtLv2Upu", b"$2a$04$PHNoJwpXCfe32nUtLv2UpuhJXOzd4k7IdFwnEpYwfJVCZ/f/.8Pje"), - ("電电電島岛島兔兔兎龜龟亀國国国區区区", 4, b"wU4/0i1TmNl2u.1jIwBX.u", b"$2a$04$wU4/0i1TmNl2u.1jIwBX.uZUaOL3Rc5ID7nlQRloQh6q5wwhV/zLW"), - ("诶比伊艾弗豆贝尔维吾艾尺开艾丝维贼德", 4, b"P4kreGLhCd26d4WIy7DJXu", b"$2a$04$P4kreGLhCd26d4WIy7DJXusPkhxLvBouzV6OXkL5EB0jux0osjsry"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_special_case_salt(self): - # password, cost, salt, bcrypt hash - tvs = [ - ("-O_=*N!2JP", 4, b"......................", b"$2a$04$......................JjuKLOX9OOwo5PceZZXSkaLDvdmgb82"), - ("7B[$Q<4b>U", 5, b"......................", b"$2a$05$......................DRiedDQZRL3xq5A5FL8y7/6NM8a2Y5W"), - (">d5-I_8^.h", 6, b"......................", b"$2a$06$......................5Mq1Ng8jgDY.uHNU4h5p/x6BedzNH2W"), - (")V`/UM/]1t", 4, b".OC/.OC/.OC/.OC/.OC/.O", b"$2a$04$.OC/.OC/.OC/.OC/.OC/.OQIvKRDAam.Hm5/IaV/.hc7P8gwwIbmi"), - (":@t2.bWuH]", 5, b".OC/.OC/.OC/.OC/.OC/.O", b"$2a$05$.OC/.OC/.OC/.OC/.OC/.ONDbUvdOchUiKmQORX6BlkPofa/QxW9e"), - ("b(#KljF5s\"", 6, b".OC/.OC/.OC/.OC/.OC/.O", b"$2a$06$.OC/.OC/.OC/.OC/.OC/.OHfTd9e7svOu34vi1PCvOcAEq07ST7.K"), - ("@3YaJ^Xs]*", 4, b"eGA.eGA.eGA.eGA.eGA.e.", b"$2a$04$eGA.eGA.eGA.eGA.eGA.e.stcmvh.R70m.0jbfSFVxlONdj1iws0C"), - ("'\"5\\!k*C(p", 5, b"eGA.eGA.eGA.eGA.eGA.e.", b"$2a$05$eGA.eGA.eGA.eGA.eGA.e.vR37mVSbfdHwu.F0sNMvgn8oruQRghy"), - ("edEu7C?$'W", 6, b"eGA.eGA.eGA.eGA.eGA.e.", b"$2a$06$eGA.eGA.eGA.eGA.eGA.e.tSq0FN8MWHQXJXNFnHTPQKtA.n2a..G"), - ("N7dHmg\\PI^", 4, b"999999999999999999999u", b"$2a$04$999999999999999999999uCZfA/pLrlyngNDMq89r1uUk.bQ9icOu"), - ("\"eJuHh!)7*", 5, b"999999999999999999999u", b"$2a$05$999999999999999999999uj8Pfx.ufrJFAoWFLjapYBS5vVEQQ/hK"), - ("ZeDRJ:_tu:", 6, b"999999999999999999999u", b"$2a$06$999999999999999999999u6RB0P9UmbdbQgjoQFEJsrvrKe.BoU6q"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) + def test_negative_cases(self): + self.assertRaises(ValueError, bcrypt, b"1" * 73, 10) + self.assertRaises(ValueError, bcrypt, b"1" * 10, 3) + self.assertRaises(ValueError, bcrypt, b"1" * 10, 32) + self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"") + self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1") + self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1" * 17) + self.assertRaises(ValueError, bcrypt, b"1\x00" * 10, 4) + + def test_bytearray_mismatch(self): + ref = bcrypt("pwd", 4) + bcrypt_check("pwd", ref) + bref = bytearray(ref) + bcrypt_check("pwd", bref) + + wrong = ref[:-1] + bchr(bref[-1] ^ 0x01) + self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) + + wrong = b"x" + ref[1:] + self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) + + # https://github.com/patrickfav/bcrypt/wiki/Published-Test-Vectors + + def test_empty_password(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + b"", + 4, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$04$zVHmKQtGGQob.b/Nc7l9NO8UlrYcW05FiuCj/SxsFO/ZtiN9.mNzy", + ), + ( + b"", + 5, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$05$zVHmKQtGGQob.b/Nc7l9NOWES.1hkVBgy5IWImh9DOjKNU8atY4Iy", + ), + ( + b"", + 6, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$06$zVHmKQtGGQob.b/Nc7l9NOjOl7l4oz3WSh5fJ6414Uw8IXRAUoiaO", + ), + ( + b"", + 7, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$07$zVHmKQtGGQob.b/Nc7l9NOBsj1dQpBA1HYNGpIETIByoNX9jc.hOi", + ), + ( + b"", + 8, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$08$zVHmKQtGGQob.b/Nc7l9NOiLTUh/9MDpX86/DLyEzyiFjqjBFePgO", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_random_password_and_salt_short_pw(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + b"<.S.2K(Zq'", + 4, + b"VYAclAMpaXY/oqAo9yUpku", + b"$2a$04$VYAclAMpaXY/oqAo9yUpkuWmoYywaPzyhu56HxXpVltnBIfmO9tgu", + ), + ( + b"5.rApO%5jA", + 5, + b"kVNDrnYKvbNr5AIcxNzeIu", + b"$2a$05$kVNDrnYKvbNr5AIcxNzeIuRcyIF5cZk6UrwHGxENbxP5dVv.WQM/G", + ), + ( + b"oW++kSrQW^", + 6, + b"QLKkRMH9Am6irtPeSKN5sO", + b"$2a$06$QLKkRMH9Am6irtPeSKN5sObJGr3j47cO6Pdf5JZ0AsJXuze0IbsNm", + ), + ( + b"ggJ\\KbTnDG", + 7, + b"4H896R09bzjhapgCPS/LYu", + b"$2a$07$4H896R09bzjhapgCPS/LYuMzAQluVgR5iu/ALF8L8Aln6lzzYXwbq", + ), + ( + b"49b0:;VkH/", + 8, + b"hfvO2retKrSrx5f2RXikWe", + b"$2a$08$hfvO2retKrSrx5f2RXikWeFWdtSesPlbj08t/uXxCeZoHRWDz/xFe", + ), + ( + b">9N^5jc##'", + 9, + b"XZLvl7rMB3EvM0c1.JHivu", + b"$2a$09$XZLvl7rMB3EvM0c1.JHivuIDPJWeNJPTVrpjZIEVRYYB/mF6cYgJK", + ), + ( + b"\\$ch)s4WXp", + 10, + b"aIjpMOLK5qiS9zjhcHR5TO", + b"$2a$10$aIjpMOLK5qiS9zjhcHR5TOU7v2NFDmcsBmSFDt5EHOgp/jeTF3O/q", + ), + ( + b"RYoj\\_>2P7", + 12, + b"esIAHiQAJNNBrsr5V13l7.", + b"$2a$12$esIAHiQAJNNBrsr5V13l7.RFWWJI2BZFtQlkFyiWXjou05GyuREZa", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_random_password_and_salt_long_pw(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + b'^Q&"]A`%/A(BVGt>QaX0M-#1ghq_+":Y0CRmY', + 5, + b"YuQvhokOGVnevctykUYpKu", + b"$2a$05$YuQvhokOGVnevctykUYpKutZD2pWeGGYn3auyLOasguMY3/0BbIyq", + ), + ( + b"F%uN/j>[GuB7-jB'_Yj!Tnb7Y!u^6)", + 6, + b"5L3vpQ0tG9O7k5gQ8nAHAe", + b"$2a$06$5L3vpQ0tG9O7k5gQ8nAHAe9xxQiOcOLh8LGcI0PLWhIznsDt.S.C6", + ), + ( + b'Z>BobP32ub"Cfe*Q<-q-=tRSjOBh8\\mLNW.", + 9, + b"nArqOfdCsD9kIbVnAixnwe", + b"$2a$09$nArqOfdCsD9kIbVnAixnwe6s8QvyPYWtQBpEXKir2OJF9/oNBsEFe", + ), + ( + b"/MH51`!BP&0tj3%YCA;Xk%e3S`o\\EI", + 10, + b"ePiAc.s.yoBi3B6p1iQUCe", + b"$2a$10$ePiAc.s.yoBi3B6p1iQUCezn3mraLwpVJ5XGelVyYFKyp5FZn/y.u", + ), + ( + b'ptAP"mcg6oH.";c0U2_oll.OKi5?Ui"^ai#iQH7ZFtNMfs3AROnIncE9"BNNoEgO[[*Yk8;RQ(#S,;I+aT', + 5, + b"wgkOlGNXIVE2fWkT3gyRoO", + b"$2a$05$wgkOlGNXIVE2fWkT3gyRoOqWi4gbi1Wv2Q2Jx3xVs3apl1w.Wtj8C", + ), + ( + b"M.E1=dt<.L0Q&p;94NfGm_Oo23+Kpl@M5?WIAL.[@/:'S)W96G8N^AWb7_smmC]>7#fGoB", + 6, + b"W9zTCl35nEvUukhhFzkKMe", + b"$2a$06$W9zTCl35nEvUukhhFzkKMekjT9/pj7M0lihRVEZrX3m8/SBNZRX7i", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_increasing_password_length(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + b"a", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.l4WvgHIVg17ZawDIrDM2IjlE64GDNQS", + ), + ( + b"aa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.AyUxBk.ThHlsLvRTH7IqcG7yVHJ3SXq", + ), + ( + b"aaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.BxOVac5xPB6XFdRc/ZrzM9FgZkqmvbW", + ), + ( + b"aaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.Qbr209bpCtfl5hN7UQlG/L4xiD3AKau", + ), + ( + b"aaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.oWszihPjDZI0ypReKsaDOW1jBl7oOii", + ), + ( + b"aaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ./k.Xxn9YiqtV/sxh3EHbnOHd0Qsq27K", + ), + ( + b"aaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.PYJqRFQbgRbIjMd5VNKmdKS4sBVOyDe", + ), + ( + b"aaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ..VMYfzaw1wP/SGxowpLeGf13fxCCt.q", + ), + ( + b"aaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.5B0p054nO5WgAD1n04XslDY/bqY9RJi", + ), + ( + b"aaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.INBTgqm7sdlBJDg.J5mLMSRK25ri04y", + ), + ( + b"aaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.s3y7CdFD0OR5p6rsZw/eZ.Dla40KLfm", + ), + ( + b"aaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.Jx742Djra6Q7PqJWnTAS.85c28g.Siq", + ), + ( + b"aaaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.oKMXW3EZcPHcUV0ib5vDBnh9HojXnLu", + ), + ( + b"aaaaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.w6nIjWpDPNSH5pZUvLjC1q25ONEQpeS", + ), + ( + b"aaaaaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.k1b2/r9A/hxdwKEKurg6OCn4MwMdiGq", + ), + ( + b"aaaaaaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.3prCNHVX1Ws.7Hm2bJxFUnQOX9f7DFa", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_non_ascii_characters(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", + 4, + b"D3qS2aoTVyqM7z8v8crLm.", + b"$2a$04$D3qS2aoTVyqM7z8v8crLm.3nKt4CzBZJbyFB.ZebmfCvRw7BGs.Xm", + ), + ( + "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", + 5, + b"VA1FujiOCMPkUHQ8kF7IaO", + b"$2a$05$VA1FujiOCMPkUHQ8kF7IaOg7NGaNvpxwWzSluQutxEVmbZItRTsAa", + ), + ( + "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", + 6, + b"TXiaNrPeBSz5ugiQlehRt.", + b"$2a$06$TXiaNrPeBSz5ugiQlehRt.gwpeDQnXWteQL4z2FulouBr6G7D9KUi", + ), + ( + "âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", + 4, + b"YTn1Qlvps8e1odqMn6G5x.", + b"$2a$04$YTn1Qlvps8e1odqMn6G5x.85pqKql6w773EZJAExk7/BatYAI4tyO", + ), + ( + "âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", + 5, + b"C.8k5vJKD2NtfrRI9o17DO", + b"$2a$05$C.8k5vJKD2NtfrRI9o17DOfIW0XnwItA529vJnh2jzYTb1QdoY0py", + ), + ( + "âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", + 6, + b"xqfRPj3RYAgwurrhcA6uRO", + b"$2a$06$xqfRPj3RYAgwurrhcA6uROtGlXDp/U6/gkoDYHwlubtcVcNft5.vW", + ), + ( + "ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", + 4, + b"y8vGgMmr9EdyxP9rmMKjH.", + b"$2a$04$y8vGgMmr9EdyxP9rmMKjH.wv2y3r7yRD79gykQtmb3N3zrwjKsyay", + ), + ( + "ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", + 5, + b"iYH4XIKAOOm/xPQs7xKP1u", + b"$2a$05$iYH4XIKAOOm/xPQs7xKP1upD0cWyMn3Jf0ZWiizXbEkVpS41K1dcO", + ), + ( + "ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", + 6, + b"wCOob.D0VV8twafNDB2ape", + b"$2a$06$wCOob.D0VV8twafNDB2apegiGD5nqF6Y1e6K95q6Y.R8C4QGd265q", + ), + ( + "ΔημοσιεύθηκεστηνΕφημερίδατης", + 4, + b"E5SQtS6P4568MDXW7cyUp.", + b"$2a$04$E5SQtS6P4568MDXW7cyUp.18wfDisKZBxifnPZjAI1d/KTYMfHPYO", + ), + ( + "АБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмН", + 4, + b"03e26gQFHhQwRNf81/ww9.", + b"$2a$04$03e26gQFHhQwRNf81/ww9.p1UbrNwxpzWjLuT.zpTLH4t/w5WhAhC", + ), + ( + "нОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮю", + 4, + b"PHNoJwpXCfe32nUtLv2Upu", + b"$2a$04$PHNoJwpXCfe32nUtLv2UpuhJXOzd4k7IdFwnEpYwfJVCZ/f/.8Pje", + ), + ( + "電电電島岛島兔兔兎龜龟亀國国国區区区", + 4, + b"wU4/0i1TmNl2u.1jIwBX.u", + b"$2a$04$wU4/0i1TmNl2u.1jIwBX.uZUaOL3Rc5ID7nlQRloQh6q5wwhV/zLW", + ), + ( + "诶比伊艾弗豆贝尔维吾艾尺开艾丝维贼德", + 4, + b"P4kreGLhCd26d4WIy7DJXu", + b"$2a$04$P4kreGLhCd26d4WIy7DJXusPkhxLvBouzV6OXkL5EB0jux0osjsry", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_special_case_salt(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + "-O_=*N!2JP", + 4, + b"......................", + b"$2a$04$......................JjuKLOX9OOwo5PceZZXSkaLDvdmgb82", + ), + ( + "7B[$Q<4b>U", + 5, + b"......................", + b"$2a$05$......................DRiedDQZRL3xq5A5FL8y7/6NM8a2Y5W", + ), + ( + ">d5-I_8^.h", + 6, + b"......................", + b"$2a$06$......................5Mq1Ng8jgDY.uHNU4h5p/x6BedzNH2W", + ), + ( + ")V`/UM/]1t", + 4, + b".OC/.OC/.OC/.OC/.OC/.O", + b"$2a$04$.OC/.OC/.OC/.OC/.OC/.OQIvKRDAam.Hm5/IaV/.hc7P8gwwIbmi", + ), + ( + ":@t2.bWuH]", + 5, + b".OC/.OC/.OC/.OC/.OC/.O", + b"$2a$05$.OC/.OC/.OC/.OC/.OC/.ONDbUvdOchUiKmQORX6BlkPofa/QxW9e", + ), + ( + 'b(#KljF5s"', + 6, + b".OC/.OC/.OC/.OC/.OC/.O", + b"$2a$06$.OC/.OC/.OC/.OC/.OC/.OHfTd9e7svOu34vi1PCvOcAEq07ST7.K", + ), + ( + "@3YaJ^Xs]*", + 4, + b"eGA.eGA.eGA.eGA.eGA.e.", + b"$2a$04$eGA.eGA.eGA.eGA.eGA.e.stcmvh.R70m.0jbfSFVxlONdj1iws0C", + ), + ( + "'\"5\\!k*C(p", + 5, + b"eGA.eGA.eGA.eGA.eGA.e.", + b"$2a$05$eGA.eGA.eGA.eGA.eGA.e.vR37mVSbfdHwu.F0sNMvgn8oruQRghy", + ), + ( + "edEu7C?$'W", + 6, + b"eGA.eGA.eGA.eGA.eGA.e.", + b"$2a$06$eGA.eGA.eGA.eGA.eGA.e.tSq0FN8MWHQXJXNFnHTPQKtA.n2a..G", + ), + ( + "N7dHmg\\PI^", + 4, + b"999999999999999999999u", + b"$2a$04$999999999999999999999uCZfA/pLrlyngNDMq89r1uUk.bQ9icOu", + ), + ( + '"eJuHh!)7*', + 5, + b"999999999999999999999u", + b"$2a$05$999999999999999999999uj8Pfx.ufrJFAoWFLjapYBS5vVEQQ/hK", + ), + ( + "ZeDRJ:_tu:", + 6, + b"999999999999999999999u", + b"$2a$06$999999999999999999999u6RB0P9UmbdbQgjoQFEJsrvrKe.BoU6q", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) class TestVectorsHKDFWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def add_tests(self, filename): - - def filter_algo(root): - algo_name = root['algorithm'] - if algo_name == "HKDF-SHA-1": - return SHA1 - elif algo_name == "HKDF-SHA-256": - return SHA256 - elif algo_name == "HKDF-SHA-384": - return SHA384 - elif algo_name == "HKDF-SHA-512": - return SHA512 - else: - raise ValueError("Unknown algorithm " + algo_name) - - def filter_size(unit): - return int(unit['size']) - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof HMAC (%s)" % filename, - root_tag={'hash_module': filter_algo}, - unit_tag={'size': filter_size}) - return result - - def setUp(self): - self.tv = [] - self.add_tests("hkdf_sha1_test.json") - self.add_tests("hkdf_sha256_test.json") - self.add_tests("hkdf_sha384_test.json") - self.add_tests("hkdf_sha512_test.json") - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof HKDF Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - - try: - key = HKDF(tv.ikm, tv.size, tv.salt, tv.hash_module, 1, tv.info) - except ValueError: - assert not tv.valid - else: - if key != tv.okm: - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def add_tests(self, filename): + def filter_algo(root): + algo_name = root["algorithm"] + if algo_name == "HKDF-SHA-1": + return SHA1 + elif algo_name == "HKDF-SHA-256": + return SHA256 + elif algo_name == "HKDF-SHA-384": + return SHA384 + elif algo_name == "HKDF-SHA-512": + return SHA512 + else: + raise ValueError("Unknown algorithm " + algo_name) + + def filter_size(unit): + return int(unit["size"]) + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof HMAC (%s)" % filename, + root_tag={"hash_module": filter_algo}, + unit_tag={"size": filter_size}, + ) + return result + + def setUp(self): + self.tv = [] + self.add_tests("hkdf_sha1_test.json") + self.add_tests("hkdf_sha256_test.json") + self.add_tests("hkdf_sha384_test.json") + self.add_tests("hkdf_sha512_test.json") + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof HKDF Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + + try: + key = HKDF(tv.ikm, tv.size, tv.salt, tv.hash_module, 1, tv.info) + except ValueError: + assert not tv.valid + else: + if key != tv.okm: + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) def load_hash_by_name(hash_name): - return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) + return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) class SP800_108_Counter_Tests(unittest.TestCase): - - def test_negative_zeroes(self): - def prf(s, x): - return HMAC.new(s, x, SHA256).digest() - - try: - _ = SP800_108_Counter(b'0' * 16, 1, prf, label=b'A\x00B') - except ValueError: - self.fail('SP800_108_Counter failed with zero in label') - self.assertRaises(ValueError, SP800_108_Counter, b'0' * 16, 1, prf, - context=b'A\x00B') - - def test_multiple_keys(self): - def prf(s, x): - return HMAC.new(s, x, SHA256).digest() - - key = b'0' * 16 - expected = SP800_108_Counter(key, 2*3*23, prf) - for r in (1, 2, 3, 23): - dks = SP800_108_Counter(key, r, prf, 138//r) - self.assertEqual(len(dks), 138//r) - self.assertEqual(len(dks[0]), r) - self.assertEqual(b''.join(dks), expected) + def test_negative_zeroes(self): + def prf(s, x): + return HMAC.new(s, x, SHA256).digest() + + try: + _ = SP800_108_Counter(b"0" * 16, 1, prf, label=b"A\x00B") + except ValueError: + self.fail("SP800_108_Counter failed with zero in label") + self.assertRaises( + ValueError, + SP800_108_Counter, + b"0" * 16, + 1, + prf, + context=b"A\x00B", + ) + + def test_multiple_keys(self): + def prf(s, x): + return HMAC.new(s, x, SHA256).digest() + + key = b"0" * 16 + expected = SP800_108_Counter(key, 2 * 3 * 23, prf) + for r in (1, 2, 3, 23): + dks = SP800_108_Counter(key, r, prf, 138 // r) + self.assertEqual(len(dks), 138 // r) + self.assertEqual(len(dks[0]), r) + self.assertEqual(b"".join(dks), expected) def add_tests_sp800_108_counter(cls): - - test_vectors_sp800_108_counter = load_test_vectors(("Protocol", ), - "KDF_SP800_108_COUNTER.txt", - "NIST SP 800 108 KDF Counter Mode", - {'count': lambda x: int(x)}, - ) or [] - - mac_type = None - for idx, tv in enumerate(test_vectors_sp800_108_counter): - - if isinstance(tv, str): - res = re.match(r"\[HMAC-(SHA-[0-9]+)\]", tv) - if res: - hash_name = res.group(1).replace("-", "") - hash_module = load_hash_by_name(hash_name) - mac_type = "hmac" - continue - res = re.match(r"\[CMAC-AES-128\]", tv) - if res: - mac_type = "cmac" - continue - assert res - - if mac_type == "hmac": - def prf(s, x, hash_module=hash_module): - return HMAC.new(s, x, hash_module).digest() - elif mac_type == "cmac": - def prf(s, x, hash_module=hash_module): - return CMAC.new(s, x, AES).digest() - continue - - def kdf_test(self, prf=prf, kin=tv.kin, label=tv.label, - context=tv.context, kout=tv.kout, count=tv.count): - result = SP800_108_Counter(kin, len(kout), prf, 1, label, context) - assert(len(result) == len(kout)) - self.assertEqual(result, kout) - - setattr(cls, "test_kdf_sp800_108_counter_%d" % idx, kdf_test) + test_vectors_sp800_108_counter = ( + load_test_vectors( + ("Protocol",), + "KDF_SP800_108_COUNTER.txt", + "NIST SP 800 108 KDF Counter Mode", + {"count": lambda x: int(x)}, + ) + or [] + ) + + mac_type = None + for idx, tv in enumerate(test_vectors_sp800_108_counter): + if isinstance(tv, str): + res = re.match(r"\[HMAC-(SHA-[0-9]+)\]", tv) + if res: + hash_name = res.group(1).replace("-", "") + hash_module = load_hash_by_name(hash_name) + mac_type = "hmac" + continue + res = re.match(r"\[CMAC-AES-128\]", tv) + if res: + mac_type = "cmac" + continue + assert res + + if mac_type == "hmac": + + def prf(s, x, hash_module=hash_module): + return HMAC.new(s, x, hash_module).digest() + elif mac_type == "cmac": + + def prf(s, x, hash_module=hash_module): + return CMAC.new(s, x, AES).digest() + + continue + + def kdf_test( + self, + prf=prf, + kin=tv.kin, + label=tv.label, + context=tv.context, + kout=tv.kout, + count=tv.count, + ): + result = SP800_108_Counter(kin, len(kout), prf, 1, label, context) + assert len(result) == len(kout) + self.assertEqual(result, kout) + + setattr(cls, "test_kdf_sp800_108_counter_%d" % idx, kdf_test) add_tests_sp800_108_counter(SP800_108_Counter_Tests) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") - if not config.get('slow_tests'): - PBKDF2_Tests._testData = PBKDF2_Tests._testData[:3] - scrypt_Tests.data = scrypt_Tests.data[:3] + if not config.get("slow_tests"): + PBKDF2_Tests._testData = PBKDF2_Tests._testData[:3] + scrypt_Tests.data = scrypt_Tests.data[:3] - tests = [] - tests += list_test_cases(PBKDF1_Tests) - tests += list_test_cases(PBKDF2_Tests) - tests += list_test_cases(S2V_Tests) - tests += list_test_cases(HKDF_Tests) - tests += [TestVectorsHKDFWycheproof(wycheproof_warnings)] - tests += list_test_cases(scrypt_Tests) - tests += list_test_cases(bcrypt_Tests) - tests += list_test_cases(SP800_108_Counter_Tests) + tests = [] + tests += list_test_cases(PBKDF1_Tests) + tests += list_test_cases(PBKDF2_Tests) + tests += list_test_cases(S2V_Tests) + tests += list_test_cases(HKDF_Tests) + tests += [TestVectorsHKDFWycheproof(wycheproof_warnings)] + tests += list_test_cases(scrypt_Tests) + tests += list_test_cases(bcrypt_Tests) + tests += list_test_cases(SP800_108_Counter_Tests) - return tests + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_SecretSharing.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_SecretSharing.py index afcbb231..f3694434 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_SecretSharing.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_SecretSharing.py @@ -32,259 +32,278 @@ # =================================================================== from unittest import main, TestCase, TestSuite -from binascii import unhexlify, hexlify +from binascii import unhexlify from Cryptodome.Util.py3compat import * from Cryptodome.Hash import SHAKE128 from Cryptodome.SelfTest.st_common import list_test_cases -from Cryptodome.Protocol.SecretSharing import Shamir, _Element, \ - _mult_gf2, _div_gf2 +from Cryptodome.Protocol.SecretSharing import Shamir, _Element, _mult_gf2, _div_gf2 class GF2_Tests(TestCase): + def test_mult_gf2(self): + # Prove mult by zero + x = _mult_gf2(0, 0) + self.assertEqual(x, 0) + + # Prove mult by unity + x = _mult_gf2(34, 1) + self.assertEqual(x, 34) + + z = 3 # (x+1) + y = _mult_gf2(z, z) + self.assertEqual(y, 5) # (x+1)^2 = x^2 + 1 + y = _mult_gf2(y, z) + self.assertEqual(y, 15) # (x+1)^3 = x^3 + x^2 + x + 1 + y = _mult_gf2(y, z) + self.assertEqual(y, 17) # (x+1)^4 = x^4 + 1 + + # Prove linearity works + comps = [1, 4, 128, 2**34] + sum_comps = 1 + 4 + 128 + 2**34 + y = 908 + z = _mult_gf2(sum_comps, y) + w = 0 + for x in comps: + w ^= _mult_gf2(x, y) + self.assertEqual(w, z) + + def test_div_gf2(self): + from Cryptodome.Util.number import size as deg + + x, y = _div_gf2(567, 7) + self.assertTrue(deg(y) < deg(7)) + + w = _mult_gf2(x, 7) ^ y + self.assertEqual(567, w) + + x, y = _div_gf2(7, 567) + self.assertEqual(x, 0) + self.assertEqual(y, 7) - def test_mult_gf2(self): - # Prove mult by zero - x = _mult_gf2(0,0) - self.assertEqual(x, 0) - - # Prove mult by unity - x = _mult_gf2(34, 1) - self.assertEqual(x, 34) - - z = 3 # (x+1) - y = _mult_gf2(z, z) - self.assertEqual(y, 5) # (x+1)^2 = x^2 + 1 - y = _mult_gf2(y, z) - self.assertEqual(y, 15) # (x+1)^3 = x^3 + x^2 + x + 1 - y = _mult_gf2(y, z) - self.assertEqual(y, 17) # (x+1)^4 = x^4 + 1 - - # Prove linearity works - comps = [1, 4, 128, 2**34] - sum_comps = 1+4+128+2**34 - y = 908 - z = _mult_gf2(sum_comps, y) - w = 0 - for x in comps: - w ^= _mult_gf2(x, y) - self.assertEqual(w, z) - - def test_div_gf2(self): - from Cryptodome.Util.number import size as deg - - x, y = _div_gf2(567, 7) - self.assertTrue(deg(y) < deg(7)) - - w = _mult_gf2(x, 7) ^ y - self.assertEqual(567, w) - - x, y = _div_gf2(7, 567) - self.assertEqual(x, 0) - self.assertEqual(y, 7) class Element_Tests(TestCase): + def test1(self): + # Test encondings + e = _Element(256) + self.assertEqual(int(e), 256) + self.assertEqual(e.encode(), bchr(0) * 14 + b("\x01\x00")) - def test1(self): - # Test encondings - e = _Element(256) - self.assertEqual(int(e), 256) - self.assertEqual(e.encode(), bchr(0)*14 + b("\x01\x00")) + e = _Element(bchr(0) * 14 + b("\x01\x10")) + self.assertEqual(int(e), 0x110) + self.assertEqual(e.encode(), bchr(0) * 14 + b("\x01\x10")) - e = _Element(bchr(0)*14 + b("\x01\x10")) - self.assertEqual(int(e), 0x110) - self.assertEqual(e.encode(), bchr(0)*14 + b("\x01\x10")) + # Only 16 byte string are a valid encoding + self.assertRaises(ValueError, _Element, bchr(0)) - # Only 16 byte string are a valid encoding - self.assertRaises(ValueError, _Element, bchr(0)) + def test2(self): + # Test addition + e = _Element(0x10) + f = _Element(0x0A) + self.assertEqual(int(e + f), 0x1A) - def test2(self): - # Test addition - e = _Element(0x10) - f = _Element(0x0A) - self.assertEqual(int(e+f), 0x1A) + def test3(self): + # Test multiplication + zero = _Element(0) + one = _Element(1) + two = _Element(2) - def test3(self): - # Test multiplication - zero = _Element(0) - one = _Element(1) - two = _Element(2) + x = _Element(6) * zero + self.assertEqual(int(x), 0) - x = _Element(6) * zero - self.assertEqual(int(x), 0) + x = _Element(6) * one + self.assertEqual(int(x), 6) - x = _Element(6) * one - self.assertEqual(int(x), 6) + x = _Element(2**127) * two + self.assertEqual(int(x), 1 + 2 + 4 + 128) - x = _Element(2**127) * two - self.assertEqual(int(x), 1 + 2 + 4 + 128) + def test4(self): + # Test inversion + one = _Element(1) - def test4(self): - # Test inversion - one = _Element(1) + x = one.inverse() + self.assertEqual(int(x), 1) - x = one.inverse() - self.assertEqual(int(x), 1) - - x = _Element(82323923) - y = x.inverse() - self.assertEqual(int(x * y), 1) + x = _Element(82323923) + y = x.inverse() + self.assertEqual(int(x * y), 1) class Shamir_Tests(TestCase): - - def test1(self): - # Test splitting - shares = Shamir.split(2, 3, bchr(90)*16) - self.assertEqual(len(shares), 3) - for index in range(3): - self.assertEqual(shares[index][0], index+1) - self.assertEqual(len(shares[index][1]), 16) - - def test2(self): - # Test recombine - from itertools import permutations - - # Generated by ssss (index, secret, shares) - # in hex mode, without "diffusion" mode - test_vectors = ( - (2, "d9fe73909bae28b3757854c0af7ad405", - "1-594ae8964294174d95c33756d2504170", - "2-d897459d29da574eb40e93ec552ffe6e", - "3-5823de9bf0e068b054b5f07a28056b1b", - "4-db2c1f8bff46d748f795da995bd080cb"), - (2, "bf4f902d9a7efafd1f3ffd9291fd5de9", - "1-557bd3b0748064b533469722d1cc7935", - "2-6b2717164783c66d47cd28f2119f14d0", - "3-8113548ba97d58256bb4424251ae300c", - "4-179e9e5a218483ddaeda57539139cf04"), - (3, "ec96aa5c14c9faa699354cf1da74e904", - "1-64579fbf1908d66f7239bf6e2b4e41e1", - "2-6cd9428df8017b52322561e8c672ae3e", - "3-e418776ef5c0579bd9299277374806dd", - "4-ab3f77a0107398d23b323e581bb43f5d", - "5-23fe42431db2b41bd03ecdc7ea8e97ac"), - (3, "44cf249b68b80fcdc27b47be60c2c145", - "1-d6515a3905cd755119b86e311c801e31", - "2-16693d9ac9f10c254036ced5f8917fa3", - "3-84f74338a48476b99bf5e75a84d3a0d1", - "4-3fe8878dc4a5d35811cf3cbcd33dbe52", - "5-ad76f92fa9d0a9c4ca0c1533af7f6132"), - (5, "5398717c982db935d968eebe53a47f5a", - "1-be7be2dd4c068e7ef576aaa1b1c11b01", - "2-f821f5848441cb98b3eb467e2733ee21", - "3-25ee52f53e203f6e29a0297b5ab486b5", - "4-fc9fb58ef74dab947fbf9acd9d5d83cd", - "5-b1949cce46d81552e65f248d3f74cc5c", - "6-d64797f59977c4d4a7956ad916da7699", - "7-ab608a6546a8b9af8820ff832b1135c7"), - (5, "4a78db90fbf35da5545d2fb728e87596", - "1-08daf9a25d8aa184cfbf02b30a0ed6a0", - "2-dda28261e36f0b14168c2cf153fb734e", - "3-e9fdec5505d674a57f9836c417c1ecaa", - "4-4dce5636ae06dee42d2c82e65f06c735", - "5-3963dc118afc2ba798fa1d452b28ef00", - "6-6dfe6ff5b09e94d2f84c382b12f42424", - "7-6faea9d4d4a4e201bf6c90b9000630c3"), - (10, "eccbf6d66d680b49b073c4f1ddf804aa", - "01-7d8ac32fe4ae209ead1f3220fda34466", - "02-f9144e76988aad647d2e61353a6e96d5", - "03-b14c3b80179203363922d60760271c98", - "04-770bb2a8c28f6cee89e00f4d5cc7f861", - "05-6e3d7073ea368334ef67467871c66799", - "06-248792bc74a98ce024477c13c8fb5f8d", - "07-fcea4640d2db820c0604851e293d2487", - "08-2776c36fb714bb1f8525a0be36fc7dba", - "09-6ee7ac8be773e473a4bf75ee5f065762", - "10-33657fc073354cf91d4a68c735aacfc8", - "11-7645c65094a5868bf225c516fdee2d0c", - "12-840485aacb8226631ecd9c70e3018086"), - (10, "377e63bdbb5f7d4dc58a483d035212bb", - "01-32c53260103be431c843b1a633afe3bd", - "02-0107eb16cb8695084d452d2cc50bc7d6", - "03-df1e5c66cd755287fb0446faccd72a06", - "04-361bbcd5d40797f49dfa1898652da197", - "05-160d3ad1512f7dec7fd9344aed318591", - "06-659af6d95df4f25beca4fb9bfee3b7e8", - "07-37f3b208977bad50b3724566b72bfa9d", - "08-6c1de2dfc69c2986142c26a8248eb316", - "09-5e19220837a396bd4bc8cd685ff314c3", - "10-86e7b864fb0f3d628e46d50c1ba92f1c", - "11-065d0082c80b1aea18f4abe0c49df72e", - "12-84a09430c1d20ea9f388f3123c3733a3"), - ) - - def get_share(p): - pos = p.find('-') - return int(p[:pos]), unhexlify(p[pos + 1:]) - - for tv in test_vectors: - k = tv[0] - secret = unhexlify(tv[1]) - max_perms = 10 - for perm, shares_idx in enumerate(permutations(range(2, len(tv)), k)): - if perm > max_perms: - break - shares = [ get_share(tv[x]) for x in shares_idx ] - result = Shamir.combine(shares, True) - self.assertEqual(secret, result) - - def test3(self): - # Loopback split/recombine - - rng = SHAKE128.new(b"test3") - - for _ in range(100): - - secret = rng.read(16) - - shares = Shamir.split(2, 3, secret) - - secret2 = Shamir.combine(shares[:2]) - self.assertEqual(secret, secret2) - - secret3 = Shamir.combine([ shares[0], shares[2] ]) - self.assertEqual(secret, secret3) - - def test4(self): - # Loopback split/recombine (SSSS) - - rng = SHAKE128.new(b"test4") - - for _ in range(10): - secret = rng.read(16) - - shares = Shamir.split(2, 3, secret, ssss=True) - - secret2 = Shamir.combine(shares[:2], ssss=True) - self.assertEqual(secret, secret2) - - for _ in range(10): - secret = rng.read(16) - - shares = Shamir.split(3, 7, secret, ssss=True) - - secret2 = Shamir.combine([shares[3], shares[4], shares[6]], ssss=True) - self.assertEqual(secret, secret2) - - - def test5(self): - # Detect duplicate shares - secret = unhexlify(b("000102030405060708090a0b0c0d0e0f")) - - shares = Shamir.split(2, 3, secret) - self.assertRaises(ValueError, Shamir.combine, (shares[0], shares[0])) + def test1(self): + # Test splitting + shares = Shamir.split(2, 3, bchr(90) * 16) + self.assertEqual(len(shares), 3) + for index in range(3): + self.assertEqual(shares[index][0], index + 1) + self.assertEqual(len(shares[index][1]), 16) + + def test2(self): + # Test recombine + from itertools import permutations + + # Generated by ssss (index, secret, shares) + # in hex mode, without "diffusion" mode + test_vectors = ( + ( + 2, + "d9fe73909bae28b3757854c0af7ad405", + "1-594ae8964294174d95c33756d2504170", + "2-d897459d29da574eb40e93ec552ffe6e", + "3-5823de9bf0e068b054b5f07a28056b1b", + "4-db2c1f8bff46d748f795da995bd080cb", + ), + ( + 2, + "bf4f902d9a7efafd1f3ffd9291fd5de9", + "1-557bd3b0748064b533469722d1cc7935", + "2-6b2717164783c66d47cd28f2119f14d0", + "3-8113548ba97d58256bb4424251ae300c", + "4-179e9e5a218483ddaeda57539139cf04", + ), + ( + 3, + "ec96aa5c14c9faa699354cf1da74e904", + "1-64579fbf1908d66f7239bf6e2b4e41e1", + "2-6cd9428df8017b52322561e8c672ae3e", + "3-e418776ef5c0579bd9299277374806dd", + "4-ab3f77a0107398d23b323e581bb43f5d", + "5-23fe42431db2b41bd03ecdc7ea8e97ac", + ), + ( + 3, + "44cf249b68b80fcdc27b47be60c2c145", + "1-d6515a3905cd755119b86e311c801e31", + "2-16693d9ac9f10c254036ced5f8917fa3", + "3-84f74338a48476b99bf5e75a84d3a0d1", + "4-3fe8878dc4a5d35811cf3cbcd33dbe52", + "5-ad76f92fa9d0a9c4ca0c1533af7f6132", + ), + ( + 5, + "5398717c982db935d968eebe53a47f5a", + "1-be7be2dd4c068e7ef576aaa1b1c11b01", + "2-f821f5848441cb98b3eb467e2733ee21", + "3-25ee52f53e203f6e29a0297b5ab486b5", + "4-fc9fb58ef74dab947fbf9acd9d5d83cd", + "5-b1949cce46d81552e65f248d3f74cc5c", + "6-d64797f59977c4d4a7956ad916da7699", + "7-ab608a6546a8b9af8820ff832b1135c7", + ), + ( + 5, + "4a78db90fbf35da5545d2fb728e87596", + "1-08daf9a25d8aa184cfbf02b30a0ed6a0", + "2-dda28261e36f0b14168c2cf153fb734e", + "3-e9fdec5505d674a57f9836c417c1ecaa", + "4-4dce5636ae06dee42d2c82e65f06c735", + "5-3963dc118afc2ba798fa1d452b28ef00", + "6-6dfe6ff5b09e94d2f84c382b12f42424", + "7-6faea9d4d4a4e201bf6c90b9000630c3", + ), + ( + 10, + "eccbf6d66d680b49b073c4f1ddf804aa", + "01-7d8ac32fe4ae209ead1f3220fda34466", + "02-f9144e76988aad647d2e61353a6e96d5", + "03-b14c3b80179203363922d60760271c98", + "04-770bb2a8c28f6cee89e00f4d5cc7f861", + "05-6e3d7073ea368334ef67467871c66799", + "06-248792bc74a98ce024477c13c8fb5f8d", + "07-fcea4640d2db820c0604851e293d2487", + "08-2776c36fb714bb1f8525a0be36fc7dba", + "09-6ee7ac8be773e473a4bf75ee5f065762", + "10-33657fc073354cf91d4a68c735aacfc8", + "11-7645c65094a5868bf225c516fdee2d0c", + "12-840485aacb8226631ecd9c70e3018086", + ), + ( + 10, + "377e63bdbb5f7d4dc58a483d035212bb", + "01-32c53260103be431c843b1a633afe3bd", + "02-0107eb16cb8695084d452d2cc50bc7d6", + "03-df1e5c66cd755287fb0446faccd72a06", + "04-361bbcd5d40797f49dfa1898652da197", + "05-160d3ad1512f7dec7fd9344aed318591", + "06-659af6d95df4f25beca4fb9bfee3b7e8", + "07-37f3b208977bad50b3724566b72bfa9d", + "08-6c1de2dfc69c2986142c26a8248eb316", + "09-5e19220837a396bd4bc8cd685ff314c3", + "10-86e7b864fb0f3d628e46d50c1ba92f1c", + "11-065d0082c80b1aea18f4abe0c49df72e", + "12-84a09430c1d20ea9f388f3123c3733a3", + ), + ) + + def get_share(p): + pos = p.find("-") + return int(p[:pos]), unhexlify(p[pos + 1 :]) + + for tv in test_vectors: + k = tv[0] + secret = unhexlify(tv[1]) + max_perms = 10 + for perm, shares_idx in enumerate(permutations(range(2, len(tv)), k)): + if perm > max_perms: + break + shares = [get_share(tv[x]) for x in shares_idx] + result = Shamir.combine(shares, True) + self.assertEqual(secret, result) + + def test3(self): + # Loopback split/recombine + + rng = SHAKE128.new(b"test3") + + for _ in range(100): + secret = rng.read(16) + + shares = Shamir.split(2, 3, secret) + + secret2 = Shamir.combine(shares[:2]) + self.assertEqual(secret, secret2) + + secret3 = Shamir.combine([shares[0], shares[2]]) + self.assertEqual(secret, secret3) + + def test4(self): + # Loopback split/recombine (SSSS) + + rng = SHAKE128.new(b"test4") + + for _ in range(10): + secret = rng.read(16) + + shares = Shamir.split(2, 3, secret, ssss=True) + + secret2 = Shamir.combine(shares[:2], ssss=True) + self.assertEqual(secret, secret2) + + for _ in range(10): + secret = rng.read(16) + + shares = Shamir.split(3, 7, secret, ssss=True) + + secret2 = Shamir.combine([shares[3], shares[4], shares[6]], ssss=True) + self.assertEqual(secret, secret2) + + def test5(self): + # Detect duplicate shares + secret = unhexlify(b("000102030405060708090a0b0c0d0e0f")) + + shares = Shamir.split(2, 3, secret) + self.assertRaises(ValueError, Shamir.combine, (shares[0], shares[0])) def get_tests(config={}): - tests = [] - tests += list_test_cases(GF2_Tests) - tests += list_test_cases(Element_Tests) - tests += list_test_cases(Shamir_Tests) - return tests + tests = [] + tests += list_test_cases(GF2_Tests) + tests += list_test_cases(Element_Tests) + tests += list_test_cases(Shamir_Tests) + return tests -if __name__ == '__main__': - suite = lambda: TestSuite(get_tests()) - main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: TestSuite(get_tests()) + main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_ecdh.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_ecdh.py index 8bea7876..4f11c1ac 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_ecdh.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_ecdh.py @@ -11,760 +11,845 @@ from Cryptodome.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof from Cryptodome.Protocol import DH -from Cryptodome.Protocol.DH import (key_agreement, - import_x25519_public_key, - import_x25519_private_key, - import_x448_public_key, - import_x448_private_key) +from Cryptodome.Protocol.DH import ( + key_agreement, + import_x25519_public_key, + import_x25519_private_key, + import_x448_public_key, + import_x448_private_key, +) class FIPS_ECDH_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_verify = load_test_vectors(("Protocol", ), - "KAS_ECC_CDH_PrimitiveTest.txt", - "ECC CDH Primitive (SP800-56A Section 5.7.1.2)", - { - 'qcavsx': lambda x: int(x, 16), - 'qcavsy': lambda x: int(x, 16), - 'diut': lambda x: int(x, 16), - 'qiutx': lambda x: int(x, 16), - 'qiuty': lambda x: int(x, 16), - }) or [] + pass + + +test_vectors_verify = ( + load_test_vectors( + ("Protocol",), + "KAS_ECC_CDH_PrimitiveTest.txt", + "ECC CDH Primitive (SP800-56A Section 5.7.1.2)", + { + "qcavsx": lambda x: int(x, 16), + "qcavsy": lambda x: int(x, 16), + "diut": lambda x: int(x, 16), + "qiutx": lambda x: int(x, 16), + "qiuty": lambda x: int(x, 16), + }, + ) + or [] +) for idx, tv in enumerate(test_vectors_verify): - - # Stand-alone header with curve name - if isinstance(tv, str): - res = re.match(r"\[([A-Za-z0-9-]+)\]", tv) - assert res - curve_name = res.group(1) - continue - - public_key = ECC.construct(curve=curve_name, - point_x=tv.qcavsx, - point_y=tv.qcavsy) - - private_key = ECC.construct(curve=curve_name, - d=tv.diut) - - exp_response = tv.ziut - - def ecdh_test(self, - public_key=public_key, - private_key=private_key, - exp_response=exp_response): - z = key_agreement( - static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - self.assertEqual(z, exp_response) - - def ecdh_test_rev(self, - public_key=public_key, - private_key=private_key, - exp_response=exp_response): - z = key_agreement( - static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - self.assertEqual(z, exp_response) - - setattr(FIPS_ECDH_Tests_KAT, "test_verify_positive_%d" % idx, ecdh_test) - if idx == 1: - setattr(FIPS_ECDH_Tests_KAT, "test_verify_positive_rev_%d" % idx, ecdh_test_rev) + # Stand-alone header with curve name + if isinstance(tv, str): + res = re.match(r"\[([A-Za-z0-9-]+)\]", tv) + assert res + curve_name = res.group(1) + continue + + public_key = ECC.construct( + curve=curve_name, + point_x=tv.qcavsx, + point_y=tv.qcavsy, + ) + + private_key = ECC.construct( + curve=curve_name, + d=tv.diut, + ) + + exp_response = tv.ziut + + def ecdh_test( + self, + public_key=public_key, + private_key=private_key, + exp_response=exp_response, + ): + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + self.assertEqual(z, exp_response) + + def ecdh_test_rev( + self, + public_key=public_key, + private_key=private_key, + exp_response=exp_response, + ): + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + self.assertEqual(z, exp_response) + + setattr(FIPS_ECDH_Tests_KAT, "test_verify_positive_%d" % idx, ecdh_test) + if idx == 1: + setattr(FIPS_ECDH_Tests_KAT, "test_verify_positive_rev_%d" % idx, ecdh_test_rev) class TestVectorsECDHWycheproof(unittest.TestCase): - - desc = "Wycheproof ECDH tests" - - def add_tests(self, filename): - - def curve(g): - return g['curve'] - - def private(u): - return int(u['private'], 16) - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'curve': curve}, - unit_tag={'private': private}, - ) - self.tv += result - - def setUp(self): - self.tv = [] - self.desc = None - - self.add_tests("ecdh_secp224r1_ecpoint_test.json") - self.add_tests("ecdh_secp256r1_ecpoint_test.json") - self.add_tests("ecdh_secp384r1_ecpoint_test.json") - self.add_tests("ecdh_secp521r1_ecpoint_test.json") - - self.add_tests("ecdh_secp224r1_test.json") - self.add_tests("ecdh_secp256r1_test.json") - self.add_tests("ecdh_secp384r1_test.json") - self.add_tests("ecdh_secp521r1_test.json") - - def shortDescription(self): - return self.desc - - def test_verify(self, tv): - - if len(tv.public) == 0: - return - - try: - if bord(tv.public[0]) == 4: # SEC1 - public_key = ECC.import_key(tv.public, curve_name=tv.curve) - else: - public_key = ECC.import_key(tv.public) - except ValueError: - assert tv.warning or not tv.valid - return - - private_key = ECC.construct(curve=tv.curve, d=tv.private) - - try: - z = key_agreement(static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - except ValueError: - assert not tv.valid - except TypeError as e: - assert not tv.valid - assert "incompatible curve" in str(e) - else: - self.assertEqual(z, tv.shared) - assert tv.valid - - def runTest(self): - for tv in self.tv: - self.desc = "Wycheproof ECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - self.test_verify(tv) + desc = "Wycheproof ECDH tests" + + def add_tests(self, filename): + def curve(g): + return g["curve"] + + def private(u): + return int(u["private"], 16) + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"curve": curve}, + unit_tag={"private": private}, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.desc = None + + self.add_tests("ecdh_secp224r1_ecpoint_test.json") + self.add_tests("ecdh_secp256r1_ecpoint_test.json") + self.add_tests("ecdh_secp384r1_ecpoint_test.json") + self.add_tests("ecdh_secp521r1_ecpoint_test.json") + + self.add_tests("ecdh_secp224r1_test.json") + self.add_tests("ecdh_secp256r1_test.json") + self.add_tests("ecdh_secp384r1_test.json") + self.add_tests("ecdh_secp521r1_test.json") + + def shortDescription(self): + return self.desc + + def test_verify(self, tv): + if len(tv.public) == 0: + return + + try: + if bord(tv.public[0]) == 4: # SEC1 + public_key = ECC.import_key(tv.public, curve_name=tv.curve) + else: + public_key = ECC.import_key(tv.public) + except ValueError: + assert tv.warning or not tv.valid + return + + private_key = ECC.construct(curve=tv.curve, d=tv.private) + + try: + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + except ValueError: + assert not tv.valid + except TypeError as e: + assert not tv.valid + assert "incompatible curve" in str(e) + else: + self.assertEqual(z, tv.shared) + assert tv.valid + + def runTest(self): + for tv in self.tv: + self.desc = "Wycheproof ECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + self.test_verify(tv) class ECDH_Tests(unittest.TestCase): - - static_priv = ECC.import_key('-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9VHFVKh2a1aVFifH\n+BiyNaRa2kttEg3165Ye/dJxJ7KhRANCAARImIEXro5ZOcyWU2mq/+d79FEZXtTA\nbKkz1aICQXihQdCMzRNbeNtC9LFLzhu1slRKJ2xsDAlw9r6w6vwtkRzr\n-----END PRIVATE KEY-----') - static_pub = ECC.import_key('-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgHhmv8zmZ+Nw8fsZd\ns8tlZflyfw2NE1CRS9DWr3Y3O46hRANCAAS3hZVUCbk+uk3w4S/YOraEVGG+WYpk\nNO/vrwzufUUks2GV2OnBQESe0EBk4Jq8gn4ij8Lvs3rZX2yT+XfeATYd\n-----END PRIVATE KEY-----').public_key() - - eph_priv = ECC.import_key('-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGPdJmFFFKzLPspIr\nE1T2cEjeIf4ajS9CpneP0e2b3AyhRANCAAQBexAA5BYDcXHs2KOksTYUsst4HhPt\nkp0zkgI2virc3OGJFNGPaCCPfFCQJHwLRaEpiq3SoQlgoBwSc8ZPsl3y\n-----END PRIVATE KEY-----') - - eph_pub = ECC.import_key('-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghaVZXElSEGEojFKF\nOU0JCpxWUWHvWQUR81gwWrOp76ShRANCAATi1Ib2K+YR3AckD8wxypWef7pw5PRw\ntBaB3RDPyE7IjHZC6yu1DbcXoCdtaw+F5DM+4zpl59n5ZaIy/Yl1BdIy\n-----END PRIVATE KEY-----') - - def test_1(self): - # C(0, 2s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - static_priv=self.static_priv) - self.assertEqual(hexlify(z), - b"3960a1101d1193cbaffef4cc7202ebff783c22c6d2e0d5d530ffc66dc197ea9c") - - def test_2(self): - # C(2e, 2s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - static_priv=self.static_priv, - eph_pub=self.eph_pub, - eph_priv=self.eph_priv) - self.assertEqual(hexlify(z), - b"7447b733d40c8fab2c633b3dc61e4a8c742f3a6af7e16fb0cc486f5bdb5d6ba2") - - def test_3(self): - # C(1e, 2s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - static_priv=self.static_priv, - eph_priv=self.eph_priv) - self.assertEqual(hexlify(z), - b"9e977ae45f33bf67f285d064d83e6632bcafe3a7d33fe571233bab4794ace759") - - def test_4(self): - # C(1e, 2s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - static_priv=self.static_priv, - eph_pub=self.eph_pub) - self.assertEqual(hexlify(z), - b"c9532df6aa7e9dbe5fe85da31ee25ff19c179c88691ec4b8328cc2036dcdadf2") - - def test_5(self): - # C(2e, 1s) is not supported - kdf = lambda x: SHA256.new(x).digest() - self.assertRaises(ValueError, - key_agreement, - kdf=kdf, - static_priv=self.static_priv, - eph_pub=self.eph_pub, - eph_priv=self.eph_priv) - - def test_6(self): - # C(2e, 1s) is not supported - kdf = lambda x: SHA256.new(x).digest() - self.assertRaises(ValueError, - key_agreement, - kdf=kdf, - static_pub=self.static_pub, - eph_pub=self.eph_pub, - eph_priv=self.eph_priv) - - def test_7(self): - # C(2e, 0) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - eph_pub=self.eph_pub, - eph_priv=self.eph_priv) - self.assertEqual(hexlify(z), - b"feb257ebe063078b1391aac07913283d7b642ad7df61b46dfc9cd6f420bb896a") - - def test_8(self): - # C(1e, 1s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_priv=self.static_priv, - eph_pub=self.eph_pub) - self.assertEqual(hexlify(z), - b"ee4dc995117476ed57fd17ff0ed44e9f0466d46b929443bc0db9380317583b04") - - def test_9(self): - # C(1e, 1s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - eph_priv=self.eph_priv) - self.assertEqual(hexlify(z), - b"2351cc2014f7c40468fa072b5d30f706eeaeef7507311cd8e59bab3b43f03c51") - - def test_10(self): - # No private (local) keys - kdf = lambda x: SHA256.new(x).digest() - self.assertRaises(ValueError, - key_agreement, - kdf=kdf, - static_pub=self.static_pub, - eph_pub=self.eph_pub) - - def test_11(self): - # No public (peer) keys - kdf = lambda x: SHA256.new(x).digest() - self.assertRaises(ValueError, - key_agreement, - kdf=kdf, - static_priv=self.static_priv, - eph_priv=self.eph_priv) - - def test_12(self): - # failure if kdf is missing - self.assertRaises(ValueError, - key_agreement, - static_pub=self.static_pub, - static_priv=self.static_priv) + static_priv = ECC.import_key( + "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9VHFVKh2a1aVFifH\n+BiyNaRa2kttEg3165Ye/dJxJ7KhRANCAARImIEXro5ZOcyWU2mq/+d79FEZXtTA\nbKkz1aICQXihQdCMzRNbeNtC9LFLzhu1slRKJ2xsDAlw9r6w6vwtkRzr\n-----END PRIVATE KEY-----" + ) + static_pub = ECC.import_key( + "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgHhmv8zmZ+Nw8fsZd\ns8tlZflyfw2NE1CRS9DWr3Y3O46hRANCAAS3hZVUCbk+uk3w4S/YOraEVGG+WYpk\nNO/vrwzufUUks2GV2OnBQESe0EBk4Jq8gn4ij8Lvs3rZX2yT+XfeATYd\n-----END PRIVATE KEY-----" + ).public_key() + + eph_priv = ECC.import_key( + "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGPdJmFFFKzLPspIr\nE1T2cEjeIf4ajS9CpneP0e2b3AyhRANCAAQBexAA5BYDcXHs2KOksTYUsst4HhPt\nkp0zkgI2virc3OGJFNGPaCCPfFCQJHwLRaEpiq3SoQlgoBwSc8ZPsl3y\n-----END PRIVATE KEY-----" + ) + + eph_pub = ECC.import_key( + "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghaVZXElSEGEojFKF\nOU0JCpxWUWHvWQUR81gwWrOp76ShRANCAATi1Ib2K+YR3AckD8wxypWef7pw5PRw\ntBaB3RDPyE7IjHZC6yu1DbcXoCdtaw+F5DM+4zpl59n5ZaIy/Yl1BdIy\n-----END PRIVATE KEY-----" + ) + + def test_1(self): + # C(0, 2s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + static_priv=self.static_priv, + ) + self.assertEqual( + hexlify(z), + b"3960a1101d1193cbaffef4cc7202ebff783c22c6d2e0d5d530ffc66dc197ea9c", + ) + + def test_2(self): + # C(2e, 2s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + static_priv=self.static_priv, + eph_pub=self.eph_pub, + eph_priv=self.eph_priv, + ) + self.assertEqual( + hexlify(z), + b"7447b733d40c8fab2c633b3dc61e4a8c742f3a6af7e16fb0cc486f5bdb5d6ba2", + ) + + def test_3(self): + # C(1e, 2s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + static_priv=self.static_priv, + eph_priv=self.eph_priv, + ) + self.assertEqual( + hexlify(z), + b"9e977ae45f33bf67f285d064d83e6632bcafe3a7d33fe571233bab4794ace759", + ) + + def test_4(self): + # C(1e, 2s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + static_priv=self.static_priv, + eph_pub=self.eph_pub, + ) + self.assertEqual( + hexlify(z), + b"c9532df6aa7e9dbe5fe85da31ee25ff19c179c88691ec4b8328cc2036dcdadf2", + ) + + def test_5(self): + # C(2e, 1s) is not supported + kdf = lambda x: SHA256.new(x).digest() + self.assertRaises( + ValueError, + key_agreement, + kdf=kdf, + static_priv=self.static_priv, + eph_pub=self.eph_pub, + eph_priv=self.eph_priv, + ) + + def test_6(self): + # C(2e, 1s) is not supported + kdf = lambda x: SHA256.new(x).digest() + self.assertRaises( + ValueError, + key_agreement, + kdf=kdf, + static_pub=self.static_pub, + eph_pub=self.eph_pub, + eph_priv=self.eph_priv, + ) + + def test_7(self): + # C(2e, 0) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + eph_pub=self.eph_pub, + eph_priv=self.eph_priv, + ) + self.assertEqual( + hexlify(z), + b"feb257ebe063078b1391aac07913283d7b642ad7df61b46dfc9cd6f420bb896a", + ) + + def test_8(self): + # C(1e, 1s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_priv=self.static_priv, + eph_pub=self.eph_pub, + ) + self.assertEqual( + hexlify(z), + b"ee4dc995117476ed57fd17ff0ed44e9f0466d46b929443bc0db9380317583b04", + ) + + def test_9(self): + # C(1e, 1s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + eph_priv=self.eph_priv, + ) + self.assertEqual( + hexlify(z), + b"2351cc2014f7c40468fa072b5d30f706eeaeef7507311cd8e59bab3b43f03c51", + ) + + def test_10(self): + # No private (local) keys + kdf = lambda x: SHA256.new(x).digest() + self.assertRaises( + ValueError, + key_agreement, + kdf=kdf, + static_pub=self.static_pub, + eph_pub=self.eph_pub, + ) + + def test_11(self): + # No public (peer) keys + kdf = lambda x: SHA256.new(x).digest() + self.assertRaises( + ValueError, + key_agreement, + kdf=kdf, + static_priv=self.static_priv, + eph_priv=self.eph_priv, + ) + + def test_12(self): + # failure if kdf is missing + self.assertRaises( + ValueError, + key_agreement, + static_pub=self.static_pub, + static_priv=self.static_priv, + ) class X25519_Tests(unittest.TestCase): - - def test_rfc7748_1(self): - tvs = ( - ("a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", - "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", - "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"), - ("4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", - "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", - "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957"), - ) - - for tv1, tv2, tv3 in tvs: - priv_key = DH.import_x25519_private_key(unhexlify(tv1)) - pub_key = DH.import_x25519_public_key(unhexlify(tv2)) - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - self.assertEqual(result, unhexlify(tv3)) - - def test_rfc7748_2(self): - k = unhexlify("0900000000000000000000000000000000000000000000000000000000000000") - - priv_key = DH.import_x25519_private_key(k) - pub_key = DH.import_x25519_public_key(k) - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - self.assertEqual( - result, - unhexlify("422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079") - ) - - for _ in range(999): - priv_key = DH.import_x25519_private_key(result) - pub_key = DH.import_x25519_public_key(k) - k = result - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - - self.assertEqual( - result, - unhexlify("684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51") - ) - - def test_rfc7748_3(self): - tv1 = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a" - tv2 = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a" - tv3 = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb" - tv4 = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f" - tv5 = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" - - alice_priv_key = DH.import_x25519_private_key(unhexlify(tv1)) - alice_pub_key = DH.import_x25519_public_key(unhexlify(tv2)) - bob_priv_key = DH.import_x25519_private_key(unhexlify(tv3)) - bob_pub_key = DH.import_x25519_public_key(unhexlify(tv4)) - secret = unhexlify(tv5) - - result1 = key_agreement(static_pub=alice_pub_key, - static_priv=bob_priv_key, - kdf=lambda x: x) - result2 = key_agreement(static_pub=bob_pub_key, - static_priv=alice_priv_key, - kdf=lambda x: x) - self.assertEqual(result1, secret) - self.assertEqual(result2, secret) - - def test_weak(self): - - weak_keys = ( - "0000000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800", - "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157", - "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - # The implementation will accept these value, but only because - # it will set the MSB to zero (as required by RFC7748, Section 5), - # therefore leading to another public key (and to a point which is - # not of low order anymore). - # "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880", - # "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7", - # "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - # "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - # "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - ) - - for x in weak_keys: - self.assertRaises(ValueError, - DH.import_x25519_public_key, - unhexlify(x)) + def test_rfc7748_1(self): + tvs = ( + ( + "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", + "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", + "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552", + ), + ( + "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", + "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", + "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957", + ), + ) + + for tv1, tv2, tv3 in tvs: + priv_key = DH.import_x25519_private_key(unhexlify(tv1)) + pub_key = DH.import_x25519_public_key(unhexlify(tv2)) + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + self.assertEqual(result, unhexlify(tv3)) + + def test_rfc7748_2(self): + k = unhexlify("0900000000000000000000000000000000000000000000000000000000000000") + + priv_key = DH.import_x25519_private_key(k) + pub_key = DH.import_x25519_public_key(k) + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + self.assertEqual( + result, + unhexlify("422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079"), + ) + + for _ in range(999): + priv_key = DH.import_x25519_private_key(result) + pub_key = DH.import_x25519_public_key(k) + k = result + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + + self.assertEqual( + result, + unhexlify("684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51"), + ) + + def test_rfc7748_3(self): + tv1 = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a" + tv2 = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a" + tv3 = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb" + tv4 = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f" + tv5 = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" + + alice_priv_key = DH.import_x25519_private_key(unhexlify(tv1)) + alice_pub_key = DH.import_x25519_public_key(unhexlify(tv2)) + bob_priv_key = DH.import_x25519_private_key(unhexlify(tv3)) + bob_pub_key = DH.import_x25519_public_key(unhexlify(tv4)) + secret = unhexlify(tv5) + + result1 = key_agreement( + static_pub=alice_pub_key, + static_priv=bob_priv_key, + kdf=lambda x: x, + ) + result2 = key_agreement( + static_pub=bob_pub_key, + static_priv=alice_priv_key, + kdf=lambda x: x, + ) + self.assertEqual(result1, secret) + self.assertEqual(result2, secret) + + def test_weak(self): + weak_keys = ( + "0000000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800", + "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + # The implementation will accept these value, but only because + # it will set the MSB to zero (as required by RFC7748, Section 5), + # therefore leading to another public key (and to a point which is + # not of low order anymore). + # "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880", + # "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7", + # "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + # "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + # "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ) + + for x in weak_keys: + self.assertRaises( + ValueError, + DH.import_x25519_public_key, + unhexlify(x), + ) class X448_Tests(unittest.TestCase): - - def test_rfc7748_1(self): - tvs = ( - ("3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", - "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", - "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f"), - ("203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", - "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", - "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d"), - ) - - for tv1, tv2, tv3 in tvs: - priv_key = DH.import_x448_private_key(unhexlify(tv1)) - pub_key = DH.import_x448_public_key(unhexlify(tv2)) - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - self.assertEqual(result, unhexlify(tv3)) - - def test_rfc7748_2(self): - k = unhexlify("0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") - - priv_key = DH.import_x448_private_key(k) - pub_key = DH.import_x448_public_key(k) - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - self.assertEqual( - result, - unhexlify("3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113") - ) - - for _ in range(999): - priv_key = DH.import_x448_private_key(result) - pub_key = DH.import_x448_public_key(k) - k = result - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - - self.assertEqual( - result, - unhexlify("aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38") - ) - - def test_rfc7748_3(self): - tv1 = "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b" - tv2 = "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0" - tv3 = "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d" - tv4 = "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609" - tv5 = "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d" - - alice_priv_key = DH.import_x448_private_key(unhexlify(tv1)) - alice_pub_key = DH.import_x448_public_key(unhexlify(tv2)) - bob_priv_key = DH.import_x448_private_key(unhexlify(tv3)) - bob_pub_key = DH.import_x448_public_key(unhexlify(tv4)) - secret = unhexlify(tv5) - - result1 = key_agreement(static_pub=alice_pub_key, - static_priv=bob_priv_key, - kdf=lambda x: x) - result2 = key_agreement(static_pub=bob_pub_key, - static_priv=alice_priv_key, - kdf=lambda x: x) - self.assertEqual(result1, secret) - self.assertEqual(result2, secret) - - def test_weak(self): - - weak_keys = ( - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - ) - - for x in weak_keys: - self.assertRaises(ValueError, - DH.import_x448_public_key, - unhexlify(x)) + def test_rfc7748_1(self): + tvs = ( + ( + "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", + "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", + "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f", + ), + ( + "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", + "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", + "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d", + ), + ) + + for tv1, tv2, tv3 in tvs: + priv_key = DH.import_x448_private_key(unhexlify(tv1)) + pub_key = DH.import_x448_public_key(unhexlify(tv2)) + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + self.assertEqual(result, unhexlify(tv3)) + + def test_rfc7748_2(self): + k = unhexlify( + "0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ) + + priv_key = DH.import_x448_private_key(k) + pub_key = DH.import_x448_public_key(k) + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + self.assertEqual( + result, + unhexlify( + "3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113" + ), + ) + + for _ in range(999): + priv_key = DH.import_x448_private_key(result) + pub_key = DH.import_x448_public_key(k) + k = result + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + + self.assertEqual( + result, + unhexlify( + "aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38" + ), + ) + + def test_rfc7748_3(self): + tv1 = "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b" + tv2 = "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0" + tv3 = "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d" + tv4 = "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609" + tv5 = "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d" + + alice_priv_key = DH.import_x448_private_key(unhexlify(tv1)) + alice_pub_key = DH.import_x448_public_key(unhexlify(tv2)) + bob_priv_key = DH.import_x448_private_key(unhexlify(tv3)) + bob_pub_key = DH.import_x448_public_key(unhexlify(tv4)) + secret = unhexlify(tv5) + + result1 = key_agreement( + static_pub=alice_pub_key, + static_priv=bob_priv_key, + kdf=lambda x: x, + ) + result2 = key_agreement( + static_pub=bob_pub_key, + static_priv=alice_priv_key, + kdf=lambda x: x, + ) + self.assertEqual(result1, secret) + self.assertEqual(result2, secret) + + def test_weak(self): + weak_keys = ( + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ) + + for x in weak_keys: + self.assertRaises( + ValueError, + DH.import_x448_public_key, + unhexlify(x), + ) class TestVectorsX25519Wycheproof(unittest.TestCase): - - desc = "Wycheproof X25519 tests" - - def add_tests_hex(self, filename): - - def encoding(g): - return g['type'] - - def private(u): - return unhexlify(u['private']) - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'encoding': encoding}, - unit_tag={'private': private} - ) - self.tv += result - - def add_tests_ascii(self, filename): - - def encoding(g): - return g['type'] - - def public(u): - return u['public'] - - def private(u): - return u['private'] - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'encoding': encoding}, - unit_tag={'public': public, - 'private': private} - ) - self.tv += result - - def setUp(self): - self.tv = [] - self.desc = None - - self.add_tests_hex("x25519_test.json") - self.add_tests_hex("x25519_asn_test.json") - self.add_tests_ascii("x25519_pem_test.json") - self.add_tests_ascii("x25519_jwk_test.json") - - def shortDescription(self): - return self.desc - - def test_verify(self, tv): - - if tv.encoding == "XdhComp": - try: - public_key = import_x25519_public_key(tv.public) - except ValueError as e: - assert tv.valid - assert tv.warning - assert "LowOrderPublic" in tv.flags - assert "Invalid Curve25519" in str(e) - return - private_key = import_x25519_private_key(tv.private) - elif tv.encoding in ("XdhAsnComp", "XdhPemComp"): - try: - public_key = ECC.import_key(tv.public) - private_key = ECC.import_key(tv.private) - except ECC.UnsupportedEccFeature as e: - assert not tv.valid - assert "Unsupported ECC" in str(e) - return - except ValueError: - assert tv.valid - assert tv.warning - assert "LowOrderPublic" in tv.flags - return - elif tv.encoding == "XdhJwkComp": - - if 'y' in tv.public: - return - if 'x' not in tv.public: - return - if 'x' not in tv.private: - return - if tv.public.get('kty') != 'OKP': - return - if tv.public.get('crv') != 'X25519': - return - if tv.private.get('crv') != 'X25519': - return - - def base64url_decode(input_str): - input_str = input_str.replace('-', '+').replace('_', '/') - padding = 4 - (len(input_str) % 4) - if padding != 4: - input_str += '=' * padding - decoded_bytes = base64.b64decode(input_str) - return decoded_bytes - - jwk_public = base64url_decode(tv.public['x']) - jwk_private = base64url_decode(tv.private['d']) - - try: - public_key = import_x25519_public_key(jwk_public) - private_key = import_x25519_private_key(jwk_private) - except ValueError as e: - if tv.valid: - assert tv.warning - assert "LowOrderPublic" in tv.flags - assert "Invalid Curve25519" in str(e) - return - else: - assert "Incorrect length" in str(e) - return - except ValueError: - assert tv.valid - else: - raise ValueError("Unknown encoding", tv.encoding) - - try: - z = key_agreement(static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - except ValueError: - assert not tv.valid - except TypeError as e: - assert not tv.valid - assert "incompatible curve" in str(e) - else: - self.assertEqual(z, tv.shared) - assert tv.valid - - def runTest(self): - for tv in self.tv: - self.desc = "Wycheproof XECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - self.test_verify(tv) + desc = "Wycheproof X25519 tests" + + def add_tests_hex(self, filename): + def encoding(g): + return g["type"] + + def private(u): + return unhexlify(u["private"]) + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"encoding": encoding}, + unit_tag={"private": private}, + ) + self.tv += result + + def add_tests_ascii(self, filename): + def encoding(g): + return g["type"] + + def public(u): + return u["public"] + + def private(u): + return u["private"] + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"encoding": encoding}, + unit_tag={ + "public": public, + "private": private, + }, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.desc = None + + self.add_tests_hex("x25519_test.json") + self.add_tests_hex("x25519_asn_test.json") + self.add_tests_ascii("x25519_pem_test.json") + self.add_tests_ascii("x25519_jwk_test.json") + + def shortDescription(self): + return self.desc + + def test_verify(self, tv): + if tv.encoding == "XdhComp": + try: + public_key = import_x25519_public_key(tv.public) + except ValueError as e: + assert tv.valid + assert tv.warning + assert "LowOrderPublic" in tv.flags + assert "Invalid Curve25519" in str(e) + return + private_key = import_x25519_private_key(tv.private) + elif tv.encoding in ("XdhAsnComp", "XdhPemComp"): + try: + public_key = ECC.import_key(tv.public) + private_key = ECC.import_key(tv.private) + except ECC.UnsupportedEccFeature as e: + assert not tv.valid + assert "Unsupported ECC" in str(e) + return + except ValueError: + assert tv.valid + assert tv.warning + assert "LowOrderPublic" in tv.flags + return + elif tv.encoding == "XdhJwkComp": + if "y" in tv.public: + return + if "x" not in tv.public: + return + if "x" not in tv.private: + return + if tv.public.get("kty") != "OKP": + return + if tv.public.get("crv") != "X25519": + return + if tv.private.get("crv") != "X25519": + return + + def base64url_decode(input_str): + input_str = input_str.replace("-", "+").replace("_", "/") + padding = 4 - (len(input_str) % 4) + if padding != 4: + input_str += "=" * padding + decoded_bytes = base64.b64decode(input_str) + return decoded_bytes + + jwk_public = base64url_decode(tv.public["x"]) + jwk_private = base64url_decode(tv.private["d"]) + + try: + public_key = import_x25519_public_key(jwk_public) + private_key = import_x25519_private_key(jwk_private) + except ValueError as e: + if tv.valid: + assert tv.warning + assert "LowOrderPublic" in tv.flags + assert "Invalid Curve25519" in str(e) + return + else: + assert "Incorrect length" in str(e) + return + except ValueError: + assert tv.valid + else: + raise ValueError("Unknown encoding", tv.encoding) + + try: + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + except ValueError: + assert not tv.valid + except TypeError as e: + assert not tv.valid + assert "incompatible curve" in str(e) + else: + self.assertEqual(z, tv.shared) + assert tv.valid + + def runTest(self): + for tv in self.tv: + self.desc = "Wycheproof XECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + self.test_verify(tv) class TestVectorsX448Wycheproof(unittest.TestCase): - - desc = "Wycheproof X448 tests" - - def add_tests_hex(self, filename): - - def encoding(g): - return g['type'] - - def private(u): - return unhexlify(u['private']) - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'encoding': encoding}, - unit_tag={'private': private} - ) - self.tv += result - - def add_tests_ascii(self, filename): - - def encoding(g): - return g['type'] - - def public(u): - return u['public'] - - def private(u): - return u['private'] - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'encoding': encoding}, - unit_tag={'public': public, - 'private': private} - ) - self.tv += result - - def setUp(self): - self.tv = [] - self.desc = None - - self.add_tests_hex("x448_test.json") - self.add_tests_hex("x448_asn_test.json") - self.add_tests_ascii("x448_pem_test.json") - self.add_tests_ascii("x448_jwk_test.json") - - def shortDescription(self): - return self.desc - - def test_verify(self, tv): - - if tv.encoding == "XdhComp": - try: - public_key = import_x448_public_key(tv.public) - except ValueError as e: - assert tv.valid - assert tv.warning - if len(tv.public) == 56: - assert "LowOrderPublic" in tv.flags - assert "Invalid Curve448" in str(e) - else: - assert "Incorrect Curve448" in str(e) - return - private_key = import_x448_private_key(tv.private) - elif tv.encoding in ("XdhAsnComp", "XdhPemComp"): - try: - public_key = ECC.import_key(tv.public) - private_key = ECC.import_key(tv.private) - except ECC.UnsupportedEccFeature as e: - assert not tv.valid - assert "Unsupported ECC" in str(e) - return - except ValueError as e: - assert tv.valid - assert tv.warning - assert "LowOrderPublic" in tv.flags or "NonCanonicalPublic" in tv.flags - return - elif tv.encoding == "XdhJwkComp": - - if 'y' in tv.public: - return - if 'x' not in tv.public: - return - if 'x' not in tv.private: - return - if tv.public.get('kty') != 'OKP': - return - if tv.public.get('crv') != 'X448': - return - if tv.private.get('crv') != 'X448': - return - - def base64url_decode(input_str): - input_str = input_str.replace('-', '+').replace('_', '/') - padding = 4 - (len(input_str) % 4) - if padding != 4: - input_str += '=' * padding - decoded_bytes = base64.b64decode(input_str) - return decoded_bytes - - jwk_public = base64url_decode(tv.public['x']) - jwk_private = base64url_decode(tv.private['d']) - - try: - public_key = import_x448_public_key(jwk_public) - private_key = import_x448_private_key(jwk_private) - except ValueError as e: - if tv.valid: - assert tv.warning - if len(tv.public['x']) == 75: - assert "LowOrderPublic" in tv.flags or \ - "NonCanonicalPublic" in tv.flags - assert "Invalid Curve448" in str(e) - else: - assert "Incorrect Curve448" in str(e) - return - else: - assert "Incorrect length" in str(e) - return - except ValueError: - assert tv.valid - else: - raise ValueError("Unknown encoding", tv.encoding) - - try: - z = key_agreement(static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - except ValueError: - assert not tv.valid - except TypeError as e: - assert not tv.valid - assert "incompatible curve" in str(e) - else: - self.assertEqual(z, tv.shared) - assert tv.valid - - def runTest(self): - for tv in self.tv: - self.desc = "Wycheproof XECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - self.test_verify(tv) + desc = "Wycheproof X448 tests" + + def add_tests_hex(self, filename): + def encoding(g): + return g["type"] + + def private(u): + return unhexlify(u["private"]) + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"encoding": encoding}, + unit_tag={"private": private}, + ) + self.tv += result + + def add_tests_ascii(self, filename): + def encoding(g): + return g["type"] + + def public(u): + return u["public"] + + def private(u): + return u["private"] + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"encoding": encoding}, + unit_tag={ + "public": public, + "private": private, + }, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.desc = None + + self.add_tests_hex("x448_test.json") + self.add_tests_hex("x448_asn_test.json") + self.add_tests_ascii("x448_pem_test.json") + self.add_tests_ascii("x448_jwk_test.json") + + def shortDescription(self): + return self.desc + + def test_verify(self, tv): + if tv.encoding == "XdhComp": + try: + public_key = import_x448_public_key(tv.public) + except ValueError as e: + assert tv.valid + assert tv.warning + if len(tv.public) == 56: + assert "LowOrderPublic" in tv.flags + assert "Invalid Curve448" in str(e) + else: + assert "Incorrect Curve448" in str(e) + return + private_key = import_x448_private_key(tv.private) + elif tv.encoding in ("XdhAsnComp", "XdhPemComp"): + try: + public_key = ECC.import_key(tv.public) + private_key = ECC.import_key(tv.private) + except ECC.UnsupportedEccFeature as e: + assert not tv.valid + assert "Unsupported ECC" in str(e) + return + except ValueError: + assert tv.valid + assert tv.warning + assert "LowOrderPublic" in tv.flags or "NonCanonicalPublic" in tv.flags + return + elif tv.encoding == "XdhJwkComp": + if "y" in tv.public: + return + if "x" not in tv.public: + return + if "x" not in tv.private: + return + if tv.public.get("kty") != "OKP": + return + if tv.public.get("crv") != "X448": + return + if tv.private.get("crv") != "X448": + return + + def base64url_decode(input_str): + input_str = input_str.replace("-", "+").replace("_", "/") + padding = 4 - (len(input_str) % 4) + if padding != 4: + input_str += "=" * padding + decoded_bytes = base64.b64decode(input_str) + return decoded_bytes + + jwk_public = base64url_decode(tv.public["x"]) + jwk_private = base64url_decode(tv.private["d"]) + + try: + public_key = import_x448_public_key(jwk_public) + private_key = import_x448_private_key(jwk_private) + except ValueError as e: + if tv.valid: + assert tv.warning + if len(tv.public["x"]) == 75: + assert "LowOrderPublic" in tv.flags or "NonCanonicalPublic" in tv.flags + assert "Invalid Curve448" in str(e) + else: + assert "Incorrect Curve448" in str(e) + return + else: + assert "Incorrect length" in str(e) + return + except ValueError: + assert tv.valid + else: + raise ValueError("Unknown encoding", tv.encoding) + + try: + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + except ValueError: + assert not tv.valid + except TypeError as e: + assert not tv.valid + assert "incompatible curve" in str(e) + else: + self.assertEqual(z, tv.shared) + assert tv.valid + + def runTest(self): + for tv in self.tv: + self.desc = "Wycheproof XECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + self.test_verify(tv) def get_tests(config={}): + tests = [] + tests += list_test_cases(FIPS_ECDH_Tests_KAT) + tests += [TestVectorsECDHWycheproof()] + tests += list_test_cases(ECDH_Tests) + tests += list_test_cases(X25519_Tests) + tests += list_test_cases(X448_Tests) + tests += [TestVectorsX25519Wycheproof()] + tests += [TestVectorsX448Wycheproof()] + + slow_tests = config.get("slow_tests") + if slow_tests: + pass - tests = [] - tests += list_test_cases(FIPS_ECDH_Tests_KAT) - tests += [TestVectorsECDHWycheproof()] - tests += list_test_cases(ECDH_Tests) - tests += list_test_cases(X25519_Tests) - tests += list_test_cases(X448_Tests) - tests += [TestVectorsX25519Wycheproof()] - tests += [TestVectorsX448Wycheproof()] + return tests - slow_tests = config.get('slow_tests') - if slow_tests: - pass - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_rfc1751.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_rfc1751.py index a79769c2..a42f94bc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_rfc1751.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Protocol/test_rfc1751.py @@ -30,33 +30,41 @@ from Cryptodome.Util import RFC1751 from Cryptodome.Util.py3compat import * -test_data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), - ('CCAC2AED591056BE4F90FD441C534766', - 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), - ('EFF81F9BFBC65350920CDD7416DE8009', - 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') - ] +test_data = [ + ("EB33F77EE73D4053", "TIDE ITCH SLOW REIN RULE MOT"), + ( + "CCAC2AED591056BE4F90FD441C534766", + "RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE", + ), + ( + "EFF81F9BFBC65350920CDD7416DE8009", + "TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL", + ), +] -class RFC1751Test_k2e (unittest.TestCase): - def runTest (self): - "Check converting keys to English" - for key, words in test_data: - key=binascii.a2b_hex(b(key)) - self.assertEqual(RFC1751.key_to_english(key), words) +class RFC1751Test_k2e(unittest.TestCase): + def runTest(self): + "Check converting keys to English" + for key, words in test_data: + key = binascii.a2b_hex(b(key)) + self.assertEqual(RFC1751.key_to_english(key), words) -class RFC1751Test_e2k (unittest.TestCase): - def runTest (self): - "Check converting English strings to keys" - for key, words in test_data: - key=binascii.a2b_hex(b(key)) - self.assertEqual(RFC1751.english_to_key(words), key) +class RFC1751Test_e2k(unittest.TestCase): + def runTest(self): + "Check converting English strings to keys" + for key, words in test_data: + key = binascii.a2b_hex(b(key)) + self.assertEqual(RFC1751.english_to_key(words), key) + # class RFC1751Test + def get_tests(config={}): - return [RFC1751Test_k2e(), RFC1751Test_e2k()] + return [RFC1751Test_k2e(), RFC1751Test_e2k()] + if __name__ == "__main__": - unittest.main() + unittest.main() diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/__init__.py index f16a6ff1..e8e4b80d 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/__init__.py @@ -25,39 +25,46 @@ """Self-test for public-key crypto""" import unittest -from Cryptodome.SelfTest.PublicKey import (test_DSA, test_RSA, - test_ECC_NIST, - test_ECC_Ed25519, - test_ECC_Curve25519, - test_ECC_Ed448, - test_ECC_Curve448, - test_import_DSA, test_import_RSA, - test_import_ECC, test_ElGamal, - test_import_Curve25519, - test_import_Curve448) +from Cryptodome.SelfTest.PublicKey import ( + test_DSA, + test_RSA, + test_ECC_NIST, + test_ECC_Ed25519, + test_ECC_Curve25519, + test_ECC_Ed448, + test_ECC_Curve448, + test_import_DSA, + test_import_RSA, + test_import_ECC, + test_ElGamal, + test_import_Curve25519, + test_import_Curve448, +) def get_tests(config={}): - tests = [] - tests += test_DSA.get_tests(config=config) - tests += test_RSA.get_tests(config=config) - tests += test_ECC_NIST.get_tests(config=config) - tests += test_ECC_Ed25519.get_tests(config=config) - tests += test_ECC_Curve25519.get_tests(config=config) - tests += test_ECC_Ed448.get_tests(config=config) - tests += test_ECC_Curve448.get_tests(config=config) - - tests += test_import_DSA.get_tests(config=config) - tests += test_import_RSA.get_tests(config=config) - tests += test_import_ECC.get_tests(config=config) - tests += test_import_Curve25519.get_tests(config=config) - tests += test_import_Curve448.get_tests(config=config) - - tests += test_ElGamal.get_tests(config=config) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += test_DSA.get_tests(config=config) + tests += test_RSA.get_tests(config=config) + tests += test_ECC_NIST.get_tests(config=config) + tests += test_ECC_Ed25519.get_tests(config=config) + tests += test_ECC_Curve25519.get_tests(config=config) + tests += test_ECC_Ed448.get_tests(config=config) + tests += test_ECC_Curve448.get_tests(config=config) + + tests += test_import_DSA.get_tests(config=config) + tests += test_import_RSA.get_tests(config=config) + tests += test_import_ECC.get_tests(config=config) + tests += test_import_Curve25519.get_tests(config=config) + tests += test_import_Curve448.get_tests(config=config) + + tests += test_ElGamal.get_tests(config=config) + return tests + + +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_DSA.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_DSA.py index 160d8820..b8b3c05d 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_DSA.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_DSA.py @@ -24,224 +24,224 @@ """Self-test suite for Cryptodome.PublicKey.DSA""" -import os from Cryptodome.Util.py3compat import * import unittest from Cryptodome.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex + def _sws(s): - """Remove whitespace from a text or byte string""" - if isinstance(s,str): - return "".join(s.split()) - else: - return b("").join(s.split()) + """Remove whitespace from a text or byte string""" + if isinstance(s, str): + return "".join(s.split()) + else: + return b("").join(s.split()) + class DSATest(unittest.TestCase): - # Test vector from "Appendix 5. Example of the DSA" of - # "Digital Signature Standard (DSS)", - # U.S. Department of Commerce/National Institute of Standards and Technology - # FIPS 186-2 (+Change Notice), 2000 January 27. - # http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf + # Test vector from "Appendix 5. Example of the DSA" of + # "Digital Signature Standard (DSS)", + # U.S. Department of Commerce/National Institute of Standards and Technology + # FIPS 186-2 (+Change Notice), 2000 January 27. + # http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf - y = _sws("""19131871 d75b1612 a819f29d 78d1b0d7 346f7aa7 7bb62a85 + y = _sws("""19131871 d75b1612 a819f29d 78d1b0d7 346f7aa7 7bb62a85 9bfd6c56 75da9d21 2d3a36ef 1672ef66 0b8c7c25 5cc0ec74 858fba33 f44c0669 9630a76b 030ee333""") - g = _sws("""626d0278 39ea0a13 413163a5 5b4cb500 299d5522 956cefcb + g = _sws("""626d0278 39ea0a13 413163a5 5b4cb500 299d5522 956cefcb 3bff10f3 99ce2c2e 71cb9de5 fa24babf 58e5b795 21925c9c c42e9f6f 464b088c c572af53 e6d78802""") - p = _sws("""8df2a494 492276aa 3d25759b b06869cb eac0d83a fb8d0cf7 + p = _sws("""8df2a494 492276aa 3d25759b b06869cb eac0d83a fb8d0cf7 cbb8324f 0d7882e5 d0762fc5 b7210eaf c2e9adac 32ab7aac 49693dfb f83724c2 ec0736ee 31c80291""") - q = _sws("""c773218c 737ec8ee 993b4f2d ed30f48e dace915f""") - - x = _sws("""2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614""") - - k = _sws("""358dad57 1462710f 50e254cf 1a376b2b deaadfbf""") - k_inverse = _sws("""0d516729 8202e49b 4116ac10 4fc3f415 ae52f917""") - m = b2a_hex(b("abc")) - m_hash = _sws("""a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d""") - r = _sws("""8bac1ab6 6410435c b7181f95 b16ab97c 92b341c0""") - s = _sws("""41e2345f 1f56df24 58f426d1 55b4ba2d b6dcd8c8""") - - def setUp(self): - global DSA, Random, bytes_to_long, size - from Cryptodome.PublicKey import DSA - from Cryptodome import Random - from Cryptodome.Util.number import bytes_to_long, inverse, size - - self.dsa = DSA - - def test_generate_1arg(self): - """DSA (default implementation) generated key (1 argument)""" - dsaObj = self.dsa.generate(1024) - self._check_private_key(dsaObj) - pub = dsaObj.public_key() - self._check_public_key(pub) - - def test_generate_2arg(self): - """DSA (default implementation) generated key (2 arguments)""" - dsaObj = self.dsa.generate(1024, Random.new().read) - self._check_private_key(dsaObj) - pub = dsaObj.public_key() - self._check_public_key(pub) - - def test_construct_4tuple(self): - """DSA (default implementation) constructed key (4-tuple)""" - (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] - dsaObj = self.dsa.construct((y, g, p, q)) - self._test_verification(dsaObj) - - def test_construct_5tuple(self): - """DSA (default implementation) constructed key (5-tuple)""" - (y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)] - dsaObj = self.dsa.construct((y, g, p, q, x)) - self._test_signing(dsaObj) - self._test_verification(dsaObj) - - def test_construct_bad_key4(self): - (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] - tup = (y, g, p+1, q) - self.assertRaises(ValueError, self.dsa.construct, tup) - - tup = (y, g, p, q+1) - self.assertRaises(ValueError, self.dsa.construct, tup) - - tup = (y, 1, p, q) - self.assertRaises(ValueError, self.dsa.construct, tup) - - def test_construct_bad_key5(self): - (y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)] - tup = (y, g, p, q, x+1) - self.assertRaises(ValueError, self.dsa.construct, tup) - - tup = (y, g, p, q, q+10) - self.assertRaises(ValueError, self.dsa.construct, tup) - - def _check_private_key(self, dsaObj): - # Check capabilities - self.assertEqual(1, dsaObj.has_private()) - self.assertEqual(1, dsaObj.can_sign()) - self.assertEqual(0, dsaObj.can_encrypt()) - - # Sanity check key data - self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q - self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits - self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 - self.assertEqual(dsaObj.y, pow(dsaObj.g, dsaObj.x, dsaObj.p)) # y == g**x mod p - self.assertEqual(1, 0 < dsaObj.x < dsaObj.q) # 0 < x < q - - def _check_public_key(self, dsaObj): - k = bytes_to_long(a2b_hex(self.k)) - m_hash = bytes_to_long(a2b_hex(self.m_hash)) - - # Check capabilities - self.assertEqual(0, dsaObj.has_private()) - self.assertEqual(1, dsaObj.can_sign()) - self.assertEqual(0, dsaObj.can_encrypt()) - - # Check that private parameters are all missing - self.assertEqual(0, hasattr(dsaObj, 'x')) - - # Sanity check key data - self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q - self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits - self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 - - # Public-only key objects should raise an error when .sign() is called - self.assertRaises(TypeError, dsaObj._sign, m_hash, k) - - # Check __eq__ and __ne__ - self.assertEqual(dsaObj.public_key() == dsaObj.public_key(),True) # assert_ - self.assertEqual(dsaObj.public_key() != dsaObj.public_key(),False) # assertFalse - - self.assertEqual(dsaObj.public_key(), dsaObj.publickey()) - - def _test_signing(self, dsaObj): - k = bytes_to_long(a2b_hex(self.k)) - m_hash = bytes_to_long(a2b_hex(self.m_hash)) - r = bytes_to_long(a2b_hex(self.r)) - s = bytes_to_long(a2b_hex(self.s)) - (r_out, s_out) = dsaObj._sign(m_hash, k) - self.assertEqual((r, s), (r_out, s_out)) - - def _test_verification(self, dsaObj): - m_hash = bytes_to_long(a2b_hex(self.m_hash)) - r = bytes_to_long(a2b_hex(self.r)) - s = bytes_to_long(a2b_hex(self.s)) - self.assertTrue(dsaObj._verify(m_hash, (r, s))) - self.assertFalse(dsaObj._verify(m_hash + 1, (r, s))) - - def test_repr(self): - (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] - dsaObj = self.dsa.construct((y, g, p, q)) - repr(dsaObj) + q = _sws("""c773218c 737ec8ee 993b4f2d ed30f48e dace915f""") + + x = _sws("""2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614""") + + k = _sws("""358dad57 1462710f 50e254cf 1a376b2b deaadfbf""") + k_inverse = _sws("""0d516729 8202e49b 4116ac10 4fc3f415 ae52f917""") + m = b2a_hex(b("abc")) + m_hash = _sws("""a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d""") + r = _sws("""8bac1ab6 6410435c b7181f95 b16ab97c 92b341c0""") + s = _sws("""41e2345f 1f56df24 58f426d1 55b4ba2d b6dcd8c8""") + + def setUp(self): + global DSA, Random, bytes_to_long, size + from Cryptodome.PublicKey import DSA + from Cryptodome import Random + from Cryptodome.Util.number import bytes_to_long, size + + self.dsa = DSA + + def test_generate_1arg(self): + """DSA (default implementation) generated key (1 argument)""" + dsaObj = self.dsa.generate(1024) + self._check_private_key(dsaObj) + pub = dsaObj.public_key() + self._check_public_key(pub) + + def test_generate_2arg(self): + """DSA (default implementation) generated key (2 arguments)""" + dsaObj = self.dsa.generate(1024, Random.new().read) + self._check_private_key(dsaObj) + pub = dsaObj.public_key() + self._check_public_key(pub) + + def test_construct_4tuple(self): + """DSA (default implementation) constructed key (4-tuple)""" + (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] + dsaObj = self.dsa.construct((y, g, p, q)) + self._test_verification(dsaObj) + + def test_construct_5tuple(self): + """DSA (default implementation) constructed key (5-tuple)""" + (y, g, p, q, x) = [ + bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x) + ] + dsaObj = self.dsa.construct((y, g, p, q, x)) + self._test_signing(dsaObj) + self._test_verification(dsaObj) + + def test_construct_bad_key4(self): + (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] + tup = (y, g, p + 1, q) + self.assertRaises(ValueError, self.dsa.construct, tup) + + tup = (y, g, p, q + 1) + self.assertRaises(ValueError, self.dsa.construct, tup) + + tup = (y, 1, p, q) + self.assertRaises(ValueError, self.dsa.construct, tup) + + def test_construct_bad_key5(self): + (y, g, p, q, x) = [ + bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x) + ] + tup = (y, g, p, q, x + 1) + self.assertRaises(ValueError, self.dsa.construct, tup) + + tup = (y, g, p, q, q + 10) + self.assertRaises(ValueError, self.dsa.construct, tup) + + def _check_private_key(self, dsaObj): + # Check capabilities + self.assertEqual(1, dsaObj.has_private()) + self.assertEqual(1, dsaObj.can_sign()) + self.assertEqual(0, dsaObj.can_encrypt()) + + # Sanity check key data + self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q + self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits + self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 + self.assertEqual(dsaObj.y, pow(dsaObj.g, dsaObj.x, dsaObj.p)) # y == g**x mod p + self.assertEqual(1, 0 < dsaObj.x < dsaObj.q) # 0 < x < q + + def _check_public_key(self, dsaObj): + k = bytes_to_long(a2b_hex(self.k)) + m_hash = bytes_to_long(a2b_hex(self.m_hash)) + + # Check capabilities + self.assertEqual(0, dsaObj.has_private()) + self.assertEqual(1, dsaObj.can_sign()) + self.assertEqual(0, dsaObj.can_encrypt()) + + # Check that private parameters are all missing + self.assertEqual(0, hasattr(dsaObj, "x")) + + # Sanity check key data + self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q + self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits + self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 + + # Public-only key objects should raise an error when .sign() is called + self.assertRaises(TypeError, dsaObj._sign, m_hash, k) + + # Check __eq__ and __ne__ + self.assertEqual(dsaObj.public_key() == dsaObj.public_key(), True) # assert_ + self.assertEqual(dsaObj.public_key() != dsaObj.public_key(), False) # assertFalse + + self.assertEqual(dsaObj.public_key(), dsaObj.publickey()) + + def _test_signing(self, dsaObj): + k = bytes_to_long(a2b_hex(self.k)) + m_hash = bytes_to_long(a2b_hex(self.m_hash)) + r = bytes_to_long(a2b_hex(self.r)) + s = bytes_to_long(a2b_hex(self.s)) + (r_out, s_out) = dsaObj._sign(m_hash, k) + self.assertEqual((r, s), (r_out, s_out)) + + def _test_verification(self, dsaObj): + m_hash = bytes_to_long(a2b_hex(self.m_hash)) + r = bytes_to_long(a2b_hex(self.r)) + s = bytes_to_long(a2b_hex(self.s)) + self.assertTrue(dsaObj._verify(m_hash, (r, s))) + self.assertFalse(dsaObj._verify(m_hash + 1, (r, s))) + + def test_repr(self): + (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] + dsaObj = self.dsa.construct((y, g, p, q)) + repr(dsaObj) class DSADomainTest(unittest.TestCase): + def test_domain1(self): + """Verify we can generate new keys in a given domain""" + dsa_key_1 = DSA.generate(1024) + domain_params = dsa_key_1.domain() - def test_domain1(self): - """Verify we can generate new keys in a given domain""" - dsa_key_1 = DSA.generate(1024) - domain_params = dsa_key_1.domain() - - dsa_key_2 = DSA.generate(1024, domain=domain_params) - self.assertEqual(dsa_key_1.p, dsa_key_2.p) - self.assertEqual(dsa_key_1.q, dsa_key_2.q) - self.assertEqual(dsa_key_1.g, dsa_key_2.g) - - self.assertEqual(dsa_key_1.domain(), dsa_key_2.domain()) + dsa_key_2 = DSA.generate(1024, domain=domain_params) + self.assertEqual(dsa_key_1.p, dsa_key_2.p) + self.assertEqual(dsa_key_1.q, dsa_key_2.q) + self.assertEqual(dsa_key_1.g, dsa_key_2.g) - def _get_weak_domain(self): + self.assertEqual(dsa_key_1.domain(), dsa_key_2.domain()) - from Cryptodome.Math.Numbers import Integer - from Cryptodome.Math import Primality + def _get_weak_domain(self): + from Cryptodome.Math.Numbers import Integer + from Cryptodome.Math import Primality - p = Integer(4) - while p.size_in_bits() != 1024 or Primality.test_probable_prime(p) != Primality.PROBABLY_PRIME: - q1 = Integer.random(exact_bits=80) - q2 = Integer.random(exact_bits=80) - q = q1 * q2 - z = Integer.random(exact_bits=1024-160) - p = z * q + 1 + p = Integer(4) + while p.size_in_bits() != 1024 or Primality.test_probable_prime(p) != Primality.PROBABLY_PRIME: + q1 = Integer.random(exact_bits=80) + q2 = Integer.random(exact_bits=80) + q = q1 * q2 + z = Integer.random(exact_bits=1024 - 160) + p = z * q + 1 - h = Integer(2) - g = 1 - while g == 1: - g = pow(h, z, p) - h += 1 + h = Integer(2) + g = 1 + while g == 1: + g = pow(h, z, p) + h += 1 - return (p, q, g) + return (p, q, g) + def test_generate_error_weak_domain(self): + """Verify that domain parameters with composite q are rejected""" - def test_generate_error_weak_domain(self): - """Verify that domain parameters with composite q are rejected""" + domain_params = self._get_weak_domain() + self.assertRaises(ValueError, DSA.generate, 1024, domain=domain_params) - domain_params = self._get_weak_domain() - self.assertRaises(ValueError, DSA.generate, 1024, domain=domain_params) + def test_construct_error_weak_domain(self): + """Verify that domain parameters with composite q are rejected""" + p, q, g = self._get_weak_domain() + y = pow(g, 89, p) + self.assertRaises(ValueError, DSA.construct, (y, g, p, q)) - def test_construct_error_weak_domain(self): - """Verify that domain parameters with composite q are rejected""" - from Cryptodome.Math.Numbers import Integer - - p, q, g = self._get_weak_domain() - y = pow(g, 89, p) - self.assertRaises(ValueError, DSA.construct, (y, g, p, q)) +def get_tests(config={}): + tests = [] + tests += list_test_cases(DSATest) + tests += list_test_cases(DSADomainTest) + return tests -def get_tests(config={}): - tests = [] - tests += list_test_cases(DSATest) - tests += list_test_cases(DSADomainTest) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Curve25519.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Curve25519.py index 8defd001..f1cf1f4c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Curve25519.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Curve25519.py @@ -43,241 +43,290 @@ # The order is 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed # Each tuple is (exponent, X-coordinate) scalar_base9_test = [ - (1, 9), - (2, 0x20d342d51873f1b7d9750c687d1571148f3f5ced1e350b5c5cae469cdd684efb), - (3, 0x1c12bc1a6d57abe645534d91c21bba64f8824e67621c0859c00a03affb713c12), - (4, 0x79ce98b7e0689d7de7d1d074a15b315ffe1805dfcd5d2a230fee85e4550013ef), - (6, 0x26954ccdc99ebf34f8f1dde5e6bb080685fec73640494c28f9fe0bfa8c794531), - (9, 0x192b929197d07748db44600da41bab7499b1c2e6e2f87c6f0e337980668164ba), - (129, 0x7332096a738900085e721103fce2cbf13aee50fef0788ea0d669008eb09ceab7), - (255, 0x1534582fc2b1cea45e8cb776547e209da4fd54a9e473b50c5b8c6b0ae023a9b3), - (256, 0x4300017536976a742ec8747f7505cd6bc80e610d669acab1a1eed36f680d98e8), - (257, 0x6c410611cb484c9016adfb884d37a0e682e075daca1d46f45bb7a4afed10b125), - (0x10101, 0xa679e9d7e043bf76c03362576e2c88abe9093c5d4f6b4a202c64a8397467cf), - (0xAA55CC, 0x2cc02f84c067e3586f4278326689be163e606d69ccae505bb09488e11f295887), - (0x1B29A0E579E0A000567, 0x50c38a72d7bfd7864c8b9083fa123e8d359068e6b491a019a885036e073f6604), - (0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed + 1, 9), + (1, 9), + (2, 0x20D342D51873F1B7D9750C687D1571148F3F5CED1E350B5C5CAE469CDD684EFB), + (3, 0x1C12BC1A6D57ABE645534D91C21BBA64F8824E67621C0859C00A03AFFB713C12), + (4, 0x79CE98B7E0689D7DE7D1D074A15B315FFE1805DFCD5D2A230FEE85E4550013EF), + (6, 0x26954CCDC99EBF34F8F1DDE5E6BB080685FEC73640494C28F9FE0BFA8C794531), + (9, 0x192B929197D07748DB44600DA41BAB7499B1C2E6E2F87C6F0E337980668164BA), + (129, 0x7332096A738900085E721103FCE2CBF13AEE50FEF0788EA0D669008EB09CEAB7), + (255, 0x1534582FC2B1CEA45E8CB776547E209DA4FD54A9E473B50C5B8C6B0AE023A9B3), + (256, 0x4300017536976A742EC8747F7505CD6BC80E610D669ACAB1A1EED36F680D98E8), + (257, 0x6C410611CB484C9016ADFB884D37A0E682E075DACA1D46F45BB7A4AFED10B125), + (0x10101, 0xA679E9D7E043BF76C03362576E2C88ABE9093C5D4F6B4A202C64A8397467CF), + (0xAA55CC, 0x2CC02F84C067E3586F4278326689BE163E606D69CCAE505BB09488E11F295887), + (0x1B29A0E579E0A000567, 0x50C38A72D7BFD7864C8B9083FA123E8D359068E6B491A019A885036E073F6604), + (0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED + 1, 9), ] class TestEccPoint_Curve25519(unittest.TestCase): + v1 = 0x09FA78B39B00A72930BCD8039BE789A0997830BB99F79AEEB93493715390B4E8 + v2 = 0x15210F12786811D3F4B7959D0538AE2C31DBE7106FC03C3EFC4CD549C715A493 - v1 = 0x09fa78b39b00a72930bcd8039be789a0997830bb99f79aeeb93493715390b4e8 - v2 = 0x15210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493 + def test_init(self): + EccXPoint(9, "curve25519") + EccXPoint(2**255 - 19 + 5, "curve25519") - def test_init(self): - EccXPoint(9, "curve25519") - EccXPoint(2**255 - 19 + 5, "curve25519") + def test_curve_attribute(self): + point = EccXPoint(9, "curve25519") + self.assertEqual(point.curve, "Curve25519") - def test_curve_attribute(self): - point = EccXPoint(9, "curve25519") - self.assertEqual(point.curve, "Curve25519") + def test_init_fail(self): + self.assertRaises(ValueError, EccXPoint, 3 * (2**255 - 19), "curve25519") + self.assertRaises(ValueError, EccXPoint, 9, "curve25518") - def test_init_fail(self): - self.assertRaises(ValueError, EccXPoint, 3*(2**255 - 19), "curve25519") - self.assertRaises(ValueError, EccXPoint, 9, "curve25518") + def test_equal_set(self): + point1 = EccXPoint(self.v1, "curve25519") + point2 = EccXPoint(self.v2, "curve25519") - def test_equal_set(self): - point1 = EccXPoint(self.v1, "curve25519") - point2 = EccXPoint(self.v2, "curve25519") + self.assertEqual(point1, point1) + self.assertNotEqual(point1, point2) - self.assertEqual(point1, point1) - self.assertNotEqual(point1, point2) + point2.set(point1) + self.assertEqual(point1.x, point2.x) - point2.set(point1) - self.assertEqual(point1.x, point2.x) + def test_copy(self): + point1 = EccXPoint(self.v1, "curve25519") + point2 = point1.copy() + self.assertEqual(point1.x, point2.x) - def test_copy(self): - point1 = EccXPoint(self.v1, "curve25519") - point2 = point1.copy() - self.assertEqual(point1.x, point2.x) + def test_pai(self): + point1 = EccXPoint(self.v1, "curve25519") + pai = point1.point_at_infinity() + self.assertTrue(pai.point_at_infinity()) - def test_pai(self): - point1 = EccXPoint(self.v1, "curve25519") - pai = point1.point_at_infinity() - self.assertTrue(pai.point_at_infinity()) + point2 = EccXPoint(None, "curve25519") + self.assertTrue(point2.point_at_infinity()) - point2 = EccXPoint(None, "curve25519") - self.assertTrue(point2.point_at_infinity()) + def test_scalar_multiply(self): + base = EccXPoint(9, "curve25519") - def test_scalar_multiply(self): - base = EccXPoint(9, "curve25519") + pointH = 0 * base + self.assertTrue(pointH.point_at_infinity()) - pointH = 0 * base - self.assertTrue(pointH.point_at_infinity()) + pointH = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED * base + self.assertTrue(pointH.point_at_infinity()) - pointH = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed * base - self.assertTrue(pointH.point_at_infinity()) + pointH = base * 1 + self.assertEqual(pointH.x, 9) - pointH = base * 1 - self.assertEqual(pointH.x, 9) + for d, result in scalar_base9_test: + pointH = d * base + self.assertEqual(pointH.x, result) - for d, result in scalar_base9_test: - pointH = d * base - self.assertEqual(pointH.x, result) - - def test_sizes(self): - point = EccXPoint(9, "curve25519") - self.assertEqual(point.size_in_bits(), 255) - self.assertEqual(point.size_in_bytes(), 32) + def test_sizes(self): + point = EccXPoint(9, "curve25519") + self.assertEqual(point.size_in_bits(), 255) + self.assertEqual(point.size_in_bytes(), 32) class TestEccKey_Curve25519(unittest.TestCase): - - def test_private_key(self): - # RFC7748 Section 6.1 - Alice - alice_priv = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") - alice_pub = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a") - alice_pub_x = Integer.from_bytes(alice_pub, byteorder='little') - - key = EccKey(curve="Curve25519", seed=alice_priv) - self.assertEqual(key.seed, alice_priv) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, alice_pub_x) - - # RFC7748 Section 6.1 - Bob - bob_priv = unhexlify("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb") - bob_pub = unhexlify("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f") - bob_pub_x = Integer.from_bytes(bob_pub, byteorder='little') - - key = EccKey(curve="Curve25519", seed=bob_priv) - self.assertEqual(key.seed, bob_priv) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, bob_pub_x) - - # Other names - key = EccKey(curve="curve25519", seed=alice_priv) - - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="curve25519", d=1) - - def test_public_key(self): - point = EccXPoint(_curves['curve25519'].Gx, - curve='curve25519') - key = EccKey(curve="curve25519", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - priv_key = EccKey(curve="curve25519", seed=b'H'*32) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_seed(self): - self.assertRaises(ValueError, lambda: EccKey(curve="curve25519", seed=b'H' * 31)) - - def test_equality(self): - private_key = ECC.construct(seed=b'H'*32, curve="Curve25519") - private_key2 = ECC.construct(seed=b'H'*32, curve="curve25519") - private_key3 = ECC.construct(seed=b'C'*32, curve="Curve25519") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='curve25519') - self.assertIn("curve='Curve25519'", repr(key)) - self.assertEqual(key.curve, 'Curve25519') - self.assertEqual(key.public_key().curve, 'Curve25519') + def test_private_key(self): + # RFC7748 Section 6.1 - Alice + alice_priv = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") + alice_pub = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a") + alice_pub_x = Integer.from_bytes(alice_pub, byteorder="little") + + key = EccKey(curve="Curve25519", seed=alice_priv) + self.assertEqual(key.seed, alice_priv) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, alice_pub_x) + + # RFC7748 Section 6.1 - Bob + bob_priv = unhexlify("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb") + bob_pub = unhexlify("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f") + bob_pub_x = Integer.from_bytes(bob_pub, byteorder="little") + + key = EccKey(curve="Curve25519", seed=bob_priv) + self.assertEqual(key.seed, bob_priv) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, bob_pub_x) + + # Other names + key = EccKey(curve="curve25519", seed=alice_priv) + + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="curve25519", d=1) + + def test_public_key(self): + point = EccXPoint( + _curves["curve25519"].Gx, + curve="curve25519", + ) + key = EccKey(curve="curve25519", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="curve25519", seed=b"H" * 32) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_seed(self): + self.assertRaises(ValueError, lambda: EccKey(curve="curve25519", seed=b"H" * 31)) + + def test_equality(self): + private_key = ECC.construct(seed=b"H" * 32, curve="Curve25519") + private_key2 = ECC.construct(seed=b"H" * 32, curve="curve25519") + private_key3 = ECC.construct(seed=b"C" * 32, curve="Curve25519") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="curve25519") + self.assertIn("curve='Curve25519'", repr(key)) + self.assertEqual(key.curve, "Curve25519") + self.assertEqual(key.public_key().curve, "Curve25519") class TestEccModule_Curve25519(unittest.TestCase): - - def test_generate(self): - key = ECC.generate(curve="Curve25519") - self.assertTrue(key.has_private()) - point = EccXPoint(_curves['Curve25519'].Gx, curve="Curve25519") * key.d - self.assertEqual(key.pointQ, point) - - # Always random - key2 = ECC.generate(curve="Curve25519") - self.assertNotEqual(key, key2) - - # Other names - ECC.generate(curve="curve25519") - - # Random source - key1 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read) - key2 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read) - self.assertEqual(key1, key2) - - def test_construct(self): - seed = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") - point_hex = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a") - Px = Integer.from_bytes(point_hex, byteorder='little') - point = EccXPoint(Px, curve="Curve25519") - - # Private key only - key = ECC.construct(curve="Curve25519", seed=seed) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Public key only - key = ECC.construct(curve="Curve25519", point_x=Px) - self.assertEqual(key.pointQ, point) - self.assertFalse(key.has_private()) - - # Private and public key - key = ECC.construct(curve="Curve25519", seed=seed, point_x=Px) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Other names - key = ECC.construct(curve="curve25519", seed=seed) - - def test_negative_construct(self): - coordG = dict(point_x=_curves['curve25519'].Gx) - - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", d=2, **coordG) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", seed=b'H'*31) - - # Verify you cannot construct weak keys (small-order points) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=0) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=1) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=325606250916557431795983626356110631294008115727848805560023387167927233504) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=39382357235489614581723060781553021112529911719440698176882885853963445705823) - p = 2**255 - 19 - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p-1) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p+1) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p+325606250916557431795983626356110631294008115727848805560023387167927233504) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p+39382357235489614581723060781553021112529911719440698176882885853963445705823) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p*2-1) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p*2) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p*2+1) + def test_generate(self): + key = ECC.generate(curve="Curve25519") + self.assertTrue(key.has_private()) + point = EccXPoint(_curves["Curve25519"].Gx, curve="Curve25519") * key.d + self.assertEqual(key.pointQ, point) + + # Always random + key2 = ECC.generate(curve="Curve25519") + self.assertNotEqual(key, key2) + + # Other names + ECC.generate(curve="curve25519") + + # Random source + key1 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read) + key2 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read) + self.assertEqual(key1, key2) + + def test_construct(self): + seed = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") + point_hex = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a") + Px = Integer.from_bytes(point_hex, byteorder="little") + point = EccXPoint(Px, curve="Curve25519") + + # Private key only + key = ECC.construct(curve="Curve25519", seed=seed) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Public key only + key = ECC.construct(curve="Curve25519", point_x=Px) + self.assertEqual(key.pointQ, point) + self.assertFalse(key.has_private()) + + # Private and public key + key = ECC.construct(curve="Curve25519", seed=seed, point_x=Px) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Other names + key = ECC.construct(curve="curve25519", seed=seed) + + def test_negative_construct(self): + coordG = dict(point_x=_curves["curve25519"].Gx) + + self.assertRaises(ValueError, ECC.construct, curve="Curve25519", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="Curve25519", seed=b"H" * 31) + + # Verify you cannot construct weak keys (small-order points) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=0, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=325606250916557431795983626356110631294008115727848805560023387167927233504, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=39382357235489614581723060781553021112529911719440698176882885853963445705823, + ) + p = 2**255 - 19 + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p - 1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p + 1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p + 325606250916557431795983626356110631294008115727848805560023387167927233504, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p + 39382357235489614581723060781553021112529911719440698176882885853963445705823, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p * 2 - 1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p * 2, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p * 2 + 1, + ) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint_Curve25519) - tests += list_test_cases(TestEccKey_Curve25519) - tests += list_test_cases(TestEccModule_Curve25519) - return tests + tests = [] + tests += list_test_cases(TestEccPoint_Curve25519) + tests += list_test_cases(TestEccKey_Curve25519) + tests += list_test_cases(TestEccModule_Curve25519) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Curve448.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Curve448.py index 6a05a9bc..bd5f4d89 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Curve448.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Curve448.py @@ -12,235 +12,318 @@ from Cryptodome.PublicKey.ECC import EccKey, EccXPoint, _curves CURVE448_P = 2**448 - 2**224 - 1 -CURVE448_ORDER = 2**446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d +CURVE448_ORDER = 2**446 - 0x8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D # Test vectors for scalar multiplication using point with X=5 as base # Each tuple is (exponent, X-coordinate) scalar_base5_test = [ - (1, 5), - (2, 0x6391322257cae3d49aef4665d8bd5cccac9abefb511e83d75f3c766616266fc1bf3747f1da00ed7125e8f0255a1208087d32a4bc1c743cb6), - (3, 0x1fbe4b3584cab86170c14b9325840b8a2429b61fb93c42492c002a2807a4e7ea63138ea59bf95652ce9a7d13d0321c7511e3314d0553f34c), - (4, 0x93b44a7b78726ba8d0b048bd7144074f8bdad24ef9d0a6c8264f6c00b135ffcea11545e80d18364acc8ebfbcc45358e0da5fd5e5146e2b1), - (6, 0x693d165f453bd62871e5e53845f33e9e5b18b24d79c1f9102608aa7ba6f18ac24864012171d64c90b698f5ce5631cd02cee4e4336b1ad88c), - (9, 0xb970d576e7d9aa427dbf7cb9b7dd65170721d04ee060c9ea8d499dc361d4cfde1ceb19068eae853bac8f5d92827bdbf3d94c22de2fb42dae), - (129, 0x9fbdb50a1450438fe656aa32aa1bb2548d077d5c3a5d327689093a2996a4f94eacd1fb4f90315edb2afe41908a759f0d6db83fa791df80db), - (255, 0x31bc3e9385dfd12e1238927061eb0c911466da394e459bf058ba3b08260a258a3c392b0f85ddbd23828657137b88577a85b83774139fab9e), - (256, 0x735c7f30e6872e5e4215c0147c8a112d697f668c9bd0f92f5f1e4e6badc128a0b654e697cd4bae2144d54e726b54c1fa63a09b00dd3c17f), - (257, 0x95c1b0ce01286dc047aeb5922a5e62b3effb5b9296273a5004eb456f592728dd494a6fb5996a2ea7011ae6423874a48c2927bfa62d8ce8b0), - (0x10101, 0x113bb172c9dc52ab45bd665dd9751ed44e33b8596f943c6cb2f8dd329160ece802960b3eb0d2c21ef3a3ac12c20fccbc2a271fc2f061c1b2), - (0xAA55CC, 0xcf42585d2e0b1e45c0bfd601c91af4b137d7faf139fc761178c7ded432417c307ee1759af2deec6a14dbaf6b868eb13a6039fbdde4b61898), - (0x1B29A0E579E0A000567, 0x7bd9ec9775a664f4d860d82d6be60895113a7c36f92db25583dbba5dc17f09c136ec27e14857bfd6a705311327030aa657dd036325fad330), - (CURVE448_ORDER + 1, 5), + (1, 5), + ( + 2, + 0x6391322257CAE3D49AEF4665D8BD5CCCAC9ABEFB511E83D75F3C766616266FC1BF3747F1DA00ED7125E8F0255A1208087D32A4BC1C743CB6, + ), + ( + 3, + 0x1FBE4B3584CAB86170C14B9325840B8A2429B61FB93C42492C002A2807A4E7EA63138EA59BF95652CE9A7D13D0321C7511E3314D0553F34C, + ), + ( + 4, + 0x93B44A7B78726BA8D0B048BD7144074F8BDAD24EF9D0A6C8264F6C00B135FFCEA11545E80D18364ACC8EBFBCC45358E0DA5FD5E5146E2B1, + ), + ( + 6, + 0x693D165F453BD62871E5E53845F33E9E5B18B24D79C1F9102608AA7BA6F18AC24864012171D64C90B698F5CE5631CD02CEE4E4336B1AD88C, + ), + ( + 9, + 0xB970D576E7D9AA427DBF7CB9B7DD65170721D04EE060C9EA8D499DC361D4CFDE1CEB19068EAE853BAC8F5D92827BDBF3D94C22DE2FB42DAE, + ), + ( + 129, + 0x9FBDB50A1450438FE656AA32AA1BB2548D077D5C3A5D327689093A2996A4F94EACD1FB4F90315EDB2AFE41908A759F0D6DB83FA791DF80DB, + ), + ( + 255, + 0x31BC3E9385DFD12E1238927061EB0C911466DA394E459BF058BA3B08260A258A3C392B0F85DDBD23828657137B88577A85B83774139FAB9E, + ), + ( + 256, + 0x735C7F30E6872E5E4215C0147C8A112D697F668C9BD0F92F5F1E4E6BADC128A0B654E697CD4BAE2144D54E726B54C1FA63A09B00DD3C17F, + ), + ( + 257, + 0x95C1B0CE01286DC047AEB5922A5E62B3EFFB5B9296273A5004EB456F592728DD494A6FB5996A2EA7011AE6423874A48C2927BFA62D8CE8B0, + ), + ( + 0x10101, + 0x113BB172C9DC52AB45BD665DD9751ED44E33B8596F943C6CB2F8DD329160ECE802960B3EB0D2C21EF3A3AC12C20FCCBC2A271FC2F061C1B2, + ), + ( + 0xAA55CC, + 0xCF42585D2E0B1E45C0BFD601C91AF4B137D7FAF139FC761178C7DED432417C307EE1759AF2DEEC6A14DBAF6B868EB13A6039FBDDE4B61898, + ), + ( + 0x1B29A0E579E0A000567, + 0x7BD9EC9775A664F4D860D82D6BE60895113A7C36F92DB25583DBBA5DC17F09C136EC27E14857BFD6A705311327030AA657DD036325FAD330, + ), + (CURVE448_ORDER + 1, 5), ] class TestEccPoint_Curve448(unittest.TestCase): + v1 = 0x09FA78B39B00A72930BCD8039BE789A0997830BB99F79AEEB93493715390B4E8 + v2 = 0x15210F12786811D3F4B7959D0538AE2C31DBE7106FC03C3EFC4CD549C715A493 - v1 = 0x09fa78b39b00a72930bcd8039be789a0997830bb99f79aeeb93493715390b4e8 - v2 = 0x15210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493 + def test_init(self): + EccXPoint(5, "curve448") + EccXPoint(CURVE448_P - 5, "curve448") - def test_init(self): - EccXPoint(5, "curve448") - EccXPoint(CURVE448_P - 5, "curve448") + def test_curve_attribute(self): + point = EccXPoint(5, "curve448") + self.assertEqual(point.curve, "Curve448") - def test_curve_attribute(self): - point = EccXPoint(5, "curve448") - self.assertEqual(point.curve, "Curve448") + def test_init_fail(self): + self.assertRaises(ValueError, EccXPoint, 3 * CURVE448_P, "curve448") + self.assertRaises(ValueError, EccXPoint, 3, "curve449") - def test_init_fail(self): - self.assertRaises(ValueError, EccXPoint, 3*CURVE448_P, "curve448") - self.assertRaises(ValueError, EccXPoint, 3, "curve449") + def test_equal_set(self): + point1 = EccXPoint(self.v1, "curve448") + point2 = EccXPoint(self.v2, "curve448") - def test_equal_set(self): - point1 = EccXPoint(self.v1, "curve448") - point2 = EccXPoint(self.v2, "curve448") + self.assertEqual(point1, point1) + self.assertNotEqual(point1, point2) - self.assertEqual(point1, point1) - self.assertNotEqual(point1, point2) + point2.set(point1) + self.assertEqual(point1.x, point2.x) - point2.set(point1) - self.assertEqual(point1.x, point2.x) + def test_copy(self): + point1 = EccXPoint(self.v1, "curve448") + point2 = point1.copy() + self.assertEqual(point1.x, point2.x) - def test_copy(self): - point1 = EccXPoint(self.v1, "curve448") - point2 = point1.copy() - self.assertEqual(point1.x, point2.x) + def test_pai(self): + point1 = EccXPoint(self.v1, "curve448") + pai = point1.point_at_infinity() + self.assertTrue(pai.point_at_infinity()) - def test_pai(self): - point1 = EccXPoint(self.v1, "curve448") - pai = point1.point_at_infinity() - self.assertTrue(pai.point_at_infinity()) + point2 = EccXPoint(None, "curve448") + self.assertTrue(point2.point_at_infinity()) - point2 = EccXPoint(None, "curve448") - self.assertTrue(point2.point_at_infinity()) + def test_scalar_multiply(self): + base = EccXPoint(5, "curve448") - def test_scalar_multiply(self): - base = EccXPoint(5, "curve448") + pointH = 0 * base + self.assertTrue(pointH.point_at_infinity()) - pointH = 0 * base - self.assertTrue(pointH.point_at_infinity()) + pointH = CURVE448_ORDER * base + self.assertTrue(pointH.point_at_infinity()) - pointH = CURVE448_ORDER * base - self.assertTrue(pointH.point_at_infinity()) + pointH = base * 1 + self.assertEqual(pointH.x, 5) - pointH = base * 1 - self.assertEqual(pointH.x, 5) + for d, result in scalar_base5_test: + pointH = d * base + self.assertEqual(pointH.x, result) - for d, result in scalar_base5_test: - pointH = d * base - self.assertEqual(pointH.x, result) - - def test_sizes(self): - point = EccXPoint(5, "curve448") - self.assertEqual(point.size_in_bits(), 448) - self.assertEqual(point.size_in_bytes(), 56) + def test_sizes(self): + point = EccXPoint(5, "curve448") + self.assertEqual(point.size_in_bits(), 448) + self.assertEqual(point.size_in_bytes(), 56) class TestEccKey_Curve448(unittest.TestCase): - - def test_private_key(self): - # RFC7748 Section 6.2 - Alice - alice_priv = unhexlify("9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b") - alice_pub = unhexlify("9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0") - alice_pub_x = Integer.from_bytes(alice_pub, byteorder='little') - - key = EccKey(curve="Curve448", seed=alice_priv) - self.assertEqual(key.seed, alice_priv) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, alice_pub_x) - - # RFC7748 Section 6.2 - Bob - bob_priv = unhexlify("1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d") - bob_pub = unhexlify("3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609") - bob_pub_x = Integer.from_bytes(bob_pub, byteorder='little') - - key = EccKey(curve="Curve448", seed=bob_priv) - self.assertEqual(key.seed, bob_priv) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, bob_pub_x) - - # Other names - key = EccKey(curve="curve448", seed=alice_priv) - - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="curve448", d=1) - - def test_public_key(self): - point = EccXPoint(_curves['curve448'].Gx, - curve='curve448') - key = EccKey(curve="curve448", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - priv_key = EccKey(curve="curve448", seed=b'H'*56) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_seed(self): - self.assertRaises(ValueError, lambda: EccKey(curve="curve448", - seed=b'H' * 55)) - - def test_equality(self): - private_key = ECC.construct(seed=b'H'*56, curve="Curve448") - private_key2 = ECC.construct(seed=b'H'*56, curve="curve448") - private_key3 = ECC.construct(seed=b'C'*56, curve="Curve448") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='curve448') - self.assertIn("curve='Curve448'", repr(key)) - self.assertEqual(key.curve, 'Curve448') - self.assertEqual(key.public_key().curve, 'Curve448') + def test_private_key(self): + # RFC7748 Section 6.2 - Alice + alice_priv = unhexlify( + "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b" + ) + alice_pub = unhexlify( + "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0" + ) + alice_pub_x = Integer.from_bytes(alice_pub, byteorder="little") + + key = EccKey(curve="Curve448", seed=alice_priv) + self.assertEqual(key.seed, alice_priv) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, alice_pub_x) + + # RFC7748 Section 6.2 - Bob + bob_priv = unhexlify( + "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d" + ) + bob_pub = unhexlify( + "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609" + ) + bob_pub_x = Integer.from_bytes(bob_pub, byteorder="little") + + key = EccKey(curve="Curve448", seed=bob_priv) + self.assertEqual(key.seed, bob_priv) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, bob_pub_x) + + # Other names + key = EccKey(curve="curve448", seed=alice_priv) + + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="curve448", d=1) + + def test_public_key(self): + point = EccXPoint( + _curves["curve448"].Gx, + curve="curve448", + ) + key = EccKey(curve="curve448", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="curve448", seed=b"H" * 56) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_seed(self): + self.assertRaises( + ValueError, + lambda: EccKey( + curve="curve448", + seed=b"H" * 55, + ), + ) + + def test_equality(self): + private_key = ECC.construct(seed=b"H" * 56, curve="Curve448") + private_key2 = ECC.construct(seed=b"H" * 56, curve="curve448") + private_key3 = ECC.construct(seed=b"C" * 56, curve="Curve448") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="curve448") + self.assertIn("curve='Curve448'", repr(key)) + self.assertEqual(key.curve, "Curve448") + self.assertEqual(key.public_key().curve, "Curve448") class TestEccModule_Curve448(unittest.TestCase): - - def test_generate(self): - key = ECC.generate(curve="Curve448") - self.assertTrue(key.has_private()) - point = EccXPoint(_curves['Curve448'].Gx, curve="Curve448") * key.d - self.assertEqual(key.pointQ, point) - - # Always random - key2 = ECC.generate(curve="Curve448") - self.assertNotEqual(key, key2) - - # Other names - ECC.generate(curve="curve448") - - # Random source - key1 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read) - key2 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read) - self.assertEqual(key1, key2) - - def test_construct(self): - seed = unhexlify("9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b") - point_hex = unhexlify("9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0") - Px = Integer.from_bytes(point_hex, byteorder='little') - point = EccXPoint(Px, curve="Curve448") - - # Private key only - key = ECC.construct(curve="Curve448", seed=seed) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Public key only - key = ECC.construct(curve="Curve448", point_x=Px) - self.assertEqual(key.pointQ, point) - self.assertFalse(key.has_private()) - - # Private and public key - key = ECC.construct(curve="Curve448", seed=seed, point_x=Px) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Other names - key = ECC.construct(curve="curve448", seed=seed) - - def test_negative_construct(self): - coordG = dict(point_x=_curves['curve448'].Gx) - - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - d=2, **coordG) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - seed=b'H'*55) - - # Verify you cannot construct weak keys (small-order points) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=0) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=1) - p = 2**448 - 2**224 - 1 - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=p-1) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=p) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=p+1) + def test_generate(self): + key = ECC.generate(curve="Curve448") + self.assertTrue(key.has_private()) + point = EccXPoint(_curves["Curve448"].Gx, curve="Curve448") * key.d + self.assertEqual(key.pointQ, point) + + # Always random + key2 = ECC.generate(curve="Curve448") + self.assertNotEqual(key, key2) + + # Other names + ECC.generate(curve="curve448") + + # Random source + key1 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read) + key2 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read) + self.assertEqual(key1, key2) + + def test_construct(self): + seed = unhexlify( + "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b" + ) + point_hex = unhexlify( + "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0" + ) + Px = Integer.from_bytes(point_hex, byteorder="little") + point = EccXPoint(Px, curve="Curve448") + + # Private key only + key = ECC.construct(curve="Curve448", seed=seed) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Public key only + key = ECC.construct(curve="Curve448", point_x=Px) + self.assertEqual(key.pointQ, point) + self.assertFalse(key.has_private()) + + # Private and public key + key = ECC.construct(curve="Curve448", seed=seed, point_x=Px) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Other names + key = ECC.construct(curve="curve448", seed=seed) + + def test_negative_construct(self): + coordG = dict(point_x=_curves["curve448"].Gx) + + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + d=2, + **coordG, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + seed=b"H" * 55, + ) + + # Verify you cannot construct weak keys (small-order points) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=0, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=1, + ) + p = 2**448 - 2**224 - 1 + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=p - 1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=p, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=p + 1, + ) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint_Curve448) - tests += list_test_cases(TestEccKey_Curve448) - tests += list_test_cases(TestEccModule_Curve448) - return tests + tests = [] + tests += list_test_cases(TestEccPoint_Curve448) + tests += list_test_cases(TestEccKey_Curve448) + tests += list_test_cases(TestEccModule_Curve448) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Ed25519.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Ed25519.py index 5018552c..03b72f9d 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Ed25519.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Ed25519.py @@ -32,310 +32,339 @@ from binascii import unhexlify from Cryptodome.SelfTest.st_common import list_test_cases -from Cryptodome.SelfTest.loader import load_test_vectors from Cryptodome.PublicKey import ECC from Cryptodome.PublicKey.ECC import EccPoint, _curves, EccKey -from Cryptodome.Math.Numbers import Integer from Cryptodome.Hash import SHAKE128 class TestEccPoint_Ed25519(unittest.TestCase): - - Gxy = {"x": 15112221349535400772501151409588531511454012693041857206046113283949847762202, - "y": 46316835694926478169428394003475163141307993866256225615783033603165251855960} - - G2xy = {"x": 24727413235106541002554574571675588834622768167397638456726423682521233608206, - "y": 15549675580280190176352668710449542251549572066445060580507079593062643049417} - - G3xy = {"x": 46896733464454938657123544595386787789046198280132665686241321779790909858396, - "y": 8324843778533443976490377120369201138301417226297555316741202210403726505172} - - pointG = EccPoint(Gxy['x'], Gxy['y'], curve="ed25519") - pointG2 = EccPoint(G2xy['x'], G2xy['y'], curve="ed25519") - pointG3 = EccPoint(G3xy['x'], G3xy['y'], curve="ed25519") - - def test_curve_attribute(self): - self.assertEqual(self.pointG.curve, "Ed25519") - - def test_init_xy(self): - EccPoint(self.Gxy['x'], self.Gxy['y'], curve="Ed25519") - - # Neutral point - pai = EccPoint(0, 1, curve="Ed25519") - self.assertEqual(pai.x, 0) - self.assertEqual(pai.y, 1) - self.assertEqual(pai.xy, (0, 1)) - - # G - bp = self.pointG.copy() - self.assertEqual(bp.x, 15112221349535400772501151409588531511454012693041857206046113283949847762202) - self.assertEqual(bp.y, 46316835694926478169428394003475163141307993866256225615783033603165251855960) - self.assertEqual(bp.xy, (bp.x, bp.y)) - - # 2G - bp2 = self.pointG2.copy() - self.assertEqual(bp2.x, 24727413235106541002554574571675588834622768167397638456726423682521233608206) - self.assertEqual(bp2.y, 15549675580280190176352668710449542251549572066445060580507079593062643049417) - self.assertEqual(bp2.xy, (bp2.x, bp2.y)) - - # 5G - EccPoint(x=33467004535436536005251147249499675200073690106659565782908757308821616914995, - y=43097193783671926753355113395909008640284023746042808659097434958891230611693, - curve="Ed25519") - - # Catch if point is not on the curve - self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed25519") - - def test_set(self): - pointW = EccPoint(0, 1, curve="Ed25519") - pointW.set(self.pointG) - self.assertEqual(pointW.x, self.pointG.x) - self.assertEqual(pointW.y, self.pointG.y) - - def test_copy(self): - pointW = self.pointG.copy() - self.assertEqual(pointW.x, self.pointG.x) - self.assertEqual(pointW.y, self.pointG.y) - - def test_equal(self): - pointH = self.pointG.copy() - pointI = self.pointG2.copy() - self.assertEqual(self.pointG, pointH) - self.assertNotEqual(self.pointG, pointI) - - def test_pai(self): - pai = EccPoint(0, 1, curve="Ed25519") - self.assertTrue(pai.is_point_at_infinity()) - self.assertEqual(pai, pai.point_at_infinity()) - - def test_negate(self): - negG = -self.pointG - G100 = self.pointG * 100 - sum_zero = G100 + negG * 100 - self.assertTrue(sum_zero.is_point_at_infinity()) - - sum_99 = G100 + negG - expected = self.pointG * 99 - self.assertEqual(sum_99, expected) - - def test_addition(self): - self.assertEqual(self.pointG + self.pointG2, self.pointG3) - self.assertEqual(self.pointG2 + self.pointG, self.pointG3) - self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2) - self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2) - - G5 = self.pointG2 + self.pointG3 - self.assertEqual(G5.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995) - self.assertEqual(G5.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693) - - def test_inplace_addition(self): - pointH = self.pointG.copy() - pointH += self.pointG - self.assertEqual(pointH, self.pointG2) - pointH += self.pointG - self.assertEqual(pointH, self.pointG3) - pointH += self.pointG.point_at_infinity() - self.assertEqual(pointH, self.pointG3) - - def test_doubling(self): - pointH = self.pointG.copy() - pointH.double() - self.assertEqual(pointH.x, self.pointG2.x) - self.assertEqual(pointH.y, self.pointG2.y) - - # 2*0 - pai = self.pointG.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - def test_scalar_multiply(self): - d = 0 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0) - self.assertEqual(pointH.y, 1) - - d = 1 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG.x) - self.assertEqual(pointH.y, self.pointG.y) - - d = 2 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG2.x) - self.assertEqual(pointH.y, self.pointG2.y) - - d = 3 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG3.x) - self.assertEqual(pointH.y, self.pointG3.y) - - d = 4 - pointH = d * self.pointG - self.assertEqual(pointH.x, 14582954232372986451776170844943001818709880559417862259286374126315108956272) - self.assertEqual(pointH.y, 32483318716863467900234833297694612235682047836132991208333042722294373421359) - - d = 5 - pointH = d * self.pointG - self.assertEqual(pointH.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995) - self.assertEqual(pointH.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693) - - d = 10 - pointH = d * self.pointG - self.assertEqual(pointH.x, 43500613248243327786121022071801015118933854441360174117148262713429272820047) - self.assertEqual(pointH.y, 45005105423099817237495816771148012388779685712352441364231470781391834741548) - - d = 20 - pointH = d * self.pointG - self.assertEqual(pointH.x, 46694936775300686710656303283485882876784402425210400817529601134760286812591) - self.assertEqual(pointH.y, 8786390172762935853260670851718824721296437982862763585171334833968259029560) - - d = 255 - pointH = d * self.pointG - self.assertEqual(pointH.x, 36843863416400016952258312492144504209624961884991522125275155377549541182230) - self.assertEqual(pointH.y, 22327030283879720808995671630924669697661065034121040761798775626517750047180) - - d = 256 - pointH = d * self.pointG - self.assertEqual(pointH.x, 42740085206947573681423002599456489563927820004573071834350074001818321593686) - self.assertEqual(pointH.y, 6935684722522267618220753829624209639984359598320562595061366101608187623111) - - def test_sizes(self): - self.assertEqual(self.pointG.size_in_bits(), 255) - self.assertEqual(self.pointG.size_in_bytes(), 32) + Gxy = { + "x": 15112221349535400772501151409588531511454012693041857206046113283949847762202, + "y": 46316835694926478169428394003475163141307993866256225615783033603165251855960, + } + + G2xy = { + "x": 24727413235106541002554574571675588834622768167397638456726423682521233608206, + "y": 15549675580280190176352668710449542251549572066445060580507079593062643049417, + } + + G3xy = { + "x": 46896733464454938657123544595386787789046198280132665686241321779790909858396, + "y": 8324843778533443976490377120369201138301417226297555316741202210403726505172, + } + + pointG = EccPoint(Gxy["x"], Gxy["y"], curve="ed25519") + pointG2 = EccPoint(G2xy["x"], G2xy["y"], curve="ed25519") + pointG3 = EccPoint(G3xy["x"], G3xy["y"], curve="ed25519") + + def test_curve_attribute(self): + self.assertEqual(self.pointG.curve, "Ed25519") + + def test_init_xy(self): + EccPoint(self.Gxy["x"], self.Gxy["y"], curve="Ed25519") + + # Neutral point + pai = EccPoint(0, 1, curve="Ed25519") + self.assertEqual(pai.x, 0) + self.assertEqual(pai.y, 1) + self.assertEqual(pai.xy, (0, 1)) + + # G + bp = self.pointG.copy() + self.assertEqual(bp.x, 15112221349535400772501151409588531511454012693041857206046113283949847762202) + self.assertEqual(bp.y, 46316835694926478169428394003475163141307993866256225615783033603165251855960) + self.assertEqual(bp.xy, (bp.x, bp.y)) + + # 2G + bp2 = self.pointG2.copy() + self.assertEqual(bp2.x, 24727413235106541002554574571675588834622768167397638456726423682521233608206) + self.assertEqual(bp2.y, 15549675580280190176352668710449542251549572066445060580507079593062643049417) + self.assertEqual(bp2.xy, (bp2.x, bp2.y)) + + # 5G + EccPoint( + x=33467004535436536005251147249499675200073690106659565782908757308821616914995, + y=43097193783671926753355113395909008640284023746042808659097434958891230611693, + curve="Ed25519", + ) + + # Catch if point is not on the curve + self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed25519") + + def test_set(self): + pointW = EccPoint(0, 1, curve="Ed25519") + pointW.set(self.pointG) + self.assertEqual(pointW.x, self.pointG.x) + self.assertEqual(pointW.y, self.pointG.y) + + def test_copy(self): + pointW = self.pointG.copy() + self.assertEqual(pointW.x, self.pointG.x) + self.assertEqual(pointW.y, self.pointG.y) + + def test_equal(self): + pointH = self.pointG.copy() + pointI = self.pointG2.copy() + self.assertEqual(self.pointG, pointH) + self.assertNotEqual(self.pointG, pointI) + + def test_pai(self): + pai = EccPoint(0, 1, curve="Ed25519") + self.assertTrue(pai.is_point_at_infinity()) + self.assertEqual(pai, pai.point_at_infinity()) + + def test_negate(self): + negG = -self.pointG + G100 = self.pointG * 100 + sum_zero = G100 + negG * 100 + self.assertTrue(sum_zero.is_point_at_infinity()) + + sum_99 = G100 + negG + expected = self.pointG * 99 + self.assertEqual(sum_99, expected) + + def test_addition(self): + self.assertEqual(self.pointG + self.pointG2, self.pointG3) + self.assertEqual(self.pointG2 + self.pointG, self.pointG3) + self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2) + self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2) + + G5 = self.pointG2 + self.pointG3 + self.assertEqual(G5.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995) + self.assertEqual(G5.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693) + + def test_inplace_addition(self): + pointH = self.pointG.copy() + pointH += self.pointG + self.assertEqual(pointH, self.pointG2) + pointH += self.pointG + self.assertEqual(pointH, self.pointG3) + pointH += self.pointG.point_at_infinity() + self.assertEqual(pointH, self.pointG3) + + def test_doubling(self): + pointH = self.pointG.copy() + pointH.double() + self.assertEqual(pointH.x, self.pointG2.x) + self.assertEqual(pointH.y, self.pointG2.y) + + # 2*0 + pai = self.pointG.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + def test_scalar_multiply(self): + d = 0 + pointH = d * self.pointG + self.assertEqual(pointH.x, 0) + self.assertEqual(pointH.y, 1) + + d = 1 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG.x) + self.assertEqual(pointH.y, self.pointG.y) + + d = 2 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG2.x) + self.assertEqual(pointH.y, self.pointG2.y) + + d = 3 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG3.x) + self.assertEqual(pointH.y, self.pointG3.y) + + d = 4 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 14582954232372986451776170844943001818709880559417862259286374126315108956272 + ) + self.assertEqual( + pointH.y, 32483318716863467900234833297694612235682047836132991208333042722294373421359 + ) + + d = 5 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995 + ) + self.assertEqual( + pointH.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693 + ) + + d = 10 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 43500613248243327786121022071801015118933854441360174117148262713429272820047 + ) + self.assertEqual( + pointH.y, 45005105423099817237495816771148012388779685712352441364231470781391834741548 + ) + + d = 20 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 46694936775300686710656303283485882876784402425210400817529601134760286812591 + ) + self.assertEqual( + pointH.y, 8786390172762935853260670851718824721296437982862763585171334833968259029560 + ) + + d = 255 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 36843863416400016952258312492144504209624961884991522125275155377549541182230 + ) + self.assertEqual( + pointH.y, 22327030283879720808995671630924669697661065034121040761798775626517750047180 + ) + + d = 256 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 42740085206947573681423002599456489563927820004573071834350074001818321593686 + ) + self.assertEqual( + pointH.y, 6935684722522267618220753829624209639984359598320562595061366101608187623111 + ) + + def test_sizes(self): + self.assertEqual(self.pointG.size_in_bits(), 255) + self.assertEqual(self.pointG.size_in_bytes(), 32) class TestEccKey_Ed25519(unittest.TestCase): + def test_private_key(self): + seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") + Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046 + Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807 - def test_private_key(self): - seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") - Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046 - Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807 - - key = EccKey(curve="Ed25519", seed=seed) - self.assertEqual(key.seed, seed) - self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, Px) - self.assertEqual(key.pointQ.y, Py) + key = EccKey(curve="Ed25519", seed=seed) + self.assertEqual(key.seed, seed) + self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, Px) + self.assertEqual(key.pointQ.y, Py) - point = EccPoint(Px, Py, "ed25519") - key = EccKey(curve="Ed25519", seed=seed, point=point) - self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) + point = EccPoint(Px, Py, "ed25519") + key = EccKey(curve="Ed25519", seed=seed, point=point) + self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) - # Other names - key = EccKey(curve="ed25519", seed=seed) + # Other names + key = EccKey(curve="ed25519", seed=seed) - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="ed25519", d=1) + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="ed25519", d=1) - def test_public_key(self): - point = EccPoint(_curves['ed25519'].Gx, _curves['ed25519'].Gy, curve='ed25519') - key = EccKey(curve="ed25519", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) + def test_public_key(self): + point = EccPoint(_curves["ed25519"].Gx, _curves["ed25519"].Gy, curve="ed25519") + key = EccKey(curve="ed25519", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) - def test_public_key_derived(self): - priv_key = EccKey(curve="ed25519", seed=b'H'*32) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) + def test_public_key_derived(self): + priv_key = EccKey(curve="ed25519", seed=b"H" * 32) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) - def test_invalid_seed(self): - self.assertRaises(ValueError, lambda: EccKey(curve="ed25519", seed=b'H' * 31)) + def test_invalid_seed(self): + self.assertRaises(ValueError, lambda: EccKey(curve="ed25519", seed=b"H" * 31)) - def test_equality(self): - private_key = ECC.construct(seed=b'H'*32, curve="Ed25519") - private_key2 = ECC.construct(seed=b'H'*32, curve="ed25519") - private_key3 = ECC.construct(seed=b'C'*32, curve="Ed25519") + def test_equality(self): + private_key = ECC.construct(seed=b"H" * 32, curve="Ed25519") + private_key2 = ECC.construct(seed=b"H" * 32, curve="ed25519") + private_key3 = ECC.construct(seed=b"C" * 32, curve="Ed25519") - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) - self.assertNotEqual(public_key, private_key) + self.assertNotEqual(public_key, private_key) - def test_name_consistency(self): - key = ECC.generate(curve='ed25519') - self.assertIn("curve='Ed25519'", repr(key)) - self.assertEqual(key.curve, 'Ed25519') - self.assertEqual(key.public_key().curve, 'Ed25519') + def test_name_consistency(self): + key = ECC.generate(curve="ed25519") + self.assertIn("curve='Ed25519'", repr(key)) + self.assertEqual(key.curve, "Ed25519") + self.assertEqual(key.public_key().curve, "Ed25519") class TestEccModule_Ed25519(unittest.TestCase): + def test_generate(self): + key = ECC.generate(curve="Ed25519") + self.assertTrue(key.has_private()) + point = EccPoint(_curves["Ed25519"].Gx, _curves["Ed25519"].Gy, curve="Ed25519") * key.d + self.assertEqual(key.pointQ, point) + + # Always random + key2 = ECC.generate(curve="Ed25519") + self.assertNotEqual(key, key2) + + # Other names + ECC.generate(curve="Ed25519") + + # Random source + key1 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read) + key2 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read) + self.assertEqual(key1, key2) + + def test_construct(self): + seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") + Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046 + Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807 + d = 36144925721603087658594284515452164870581325872720374094707712194495455132720 + point = EccPoint(Px, Py, curve="Ed25519") + + # Private key only + key = ECC.construct(curve="Ed25519", seed=seed) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Public key only + key = ECC.construct(curve="Ed25519", point_x=Px, point_y=Py) + self.assertEqual(key.pointQ, point) + self.assertFalse(key.has_private()) + + # Private and public key + key = ECC.construct(curve="Ed25519", seed=seed, point_x=Px, point_y=Py) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Other names + key = ECC.construct(curve="ed25519", seed=seed) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["ed25519"].Gx, point_y=_curves["ed25519"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="Ed25519", **coord) + self.assertRaises(ValueError, ECC.construct, curve="Ed25519", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="Ed25519", seed=b"H" * 31) - def test_generate(self): - key = ECC.generate(curve="Ed25519") - self.assertTrue(key.has_private()) - point = EccPoint(_curves['Ed25519'].Gx, _curves['Ed25519'].Gy, curve="Ed25519") * key.d - self.assertEqual(key.pointQ, point) - - # Always random - key2 = ECC.generate(curve="Ed25519") - self.assertNotEqual(key, key2) - - # Other names - ECC.generate(curve="Ed25519") - - # Random source - key1 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read) - key2 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read) - self.assertEqual(key1, key2) - - def test_construct(self): - seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") - Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046 - Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807 - d = 36144925721603087658594284515452164870581325872720374094707712194495455132720 - point = EccPoint(Px, Py, curve="Ed25519") - - # Private key only - key = ECC.construct(curve="Ed25519", seed=seed) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - # Public key only - key = ECC.construct(curve="Ed25519", point_x=Px, point_y=Py) - self.assertEqual(key.pointQ, point) - self.assertFalse(key.has_private()) - - # Private and public key - key = ECC.construct(curve="Ed25519", seed=seed, point_x=Px, point_y=Py) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Other names - key = ECC.construct(curve="ed25519", seed=seed) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['ed25519'].Gx, point_y=_curves['ed25519'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="Ed25519", **coord) - self.assertRaises(ValueError, ECC.construct, curve="Ed25519", d=2, **coordG) - self.assertRaises(ValueError, ECC.construct, curve="Ed25519", seed=b'H'*31) +def get_tests(config={}): + tests = [] + tests += list_test_cases(TestEccPoint_Ed25519) + tests += list_test_cases(TestEccKey_Ed25519) + tests += list_test_cases(TestEccModule_Ed25519) + return tests -def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint_Ed25519) - tests += list_test_cases(TestEccKey_Ed25519) - tests += list_test_cases(TestEccModule_Ed25519) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Ed448.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Ed448.py index 3a7b0eb8..4b0212c9 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Ed448.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_Ed448.py @@ -32,305 +32,374 @@ from binascii import unhexlify from Cryptodome.SelfTest.st_common import list_test_cases -from Cryptodome.SelfTest.loader import load_test_vectors from Cryptodome.PublicKey import ECC from Cryptodome.PublicKey.ECC import EccPoint, _curves, EccKey -from Cryptodome.Math.Numbers import Integer from Cryptodome.Hash import SHAKE128 class TestEccPoint_Ed448(unittest.TestCase): - - Gxy = {"x": 0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e, - "y": 0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14} - - G2xy = {"x": 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555, - "y": 0xae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed} - - G3xy = {"x": 0x865886b9108af6455bd64316cb6943332241b8b8cda82c7e2ba077a4a3fcfe8daa9cbf7f6271fd6e862b769465da8575728173286ff2f8f, - "y": 0xe005a8dbd5125cf706cbda7ad43aa6449a4a8d952356c3b9fce43c82ec4e1d58bb3a331bdb6767f0bffa9a68fed02dafb822ac13588ed6fc} - - pointG = EccPoint(Gxy['x'], Gxy['y'], curve="ed448") - pointG2 = EccPoint(G2xy['x'], G2xy['y'], curve="ed448") - pointG3 = EccPoint(G3xy['x'], G3xy['y'], curve="ed448") - - def test_curve_attribute(self): - self.assertEqual(self.pointG.curve, "Ed448") - - def test_init_xy(self): - EccPoint(self.Gxy['x'], self.Gxy['y'], curve="Ed448") - - # Neutral point - pai = EccPoint(0, 1, curve="Ed448") - self.assertEqual(pai.x, 0) - self.assertEqual(pai.y, 1) - self.assertEqual(pai.xy, (0, 1)) - - # G - bp = self.pointG.copy() - self.assertEqual(bp.x, 0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e) - self.assertEqual(bp.y, 0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14) - self.assertEqual(bp.xy, (bp.x, bp.y)) - - # 2G - bp2 = self.pointG2.copy() - self.assertEqual(bp2.x, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555) - self.assertEqual(bp2.y, 0xae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed) - self.assertEqual(bp2.xy, (bp2.x, bp2.y)) - - # 5G - EccPoint(x=0x7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034, - y=0xadfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb, - curve="Ed448") - - # Catch if point is not on the curve - self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed448") - - def test_set(self): - pointW = EccPoint(0, 1, curve="Ed448") - pointW.set(self.pointG) - self.assertEqual(pointW.x, self.pointG.x) - self.assertEqual(pointW.y, self.pointG.y) - - def test_copy(self): - pointW = self.pointG.copy() - self.assertEqual(pointW.x, self.pointG.x) - self.assertEqual(pointW.y, self.pointG.y) - - def test_equal(self): - pointH = self.pointG.copy() - pointI = self.pointG2.copy() - self.assertEqual(self.pointG, pointH) - self.assertNotEqual(self.pointG, pointI) - - def test_pai(self): - pai = EccPoint(0, 1, curve="Ed448") - self.assertTrue(pai.is_point_at_infinity()) - self.assertEqual(pai, pai.point_at_infinity()) - - def test_negate(self): - negG = -self.pointG - sum = self.pointG + negG - self.assertTrue(sum.is_point_at_infinity()) - - def test_addition(self): - self.assertEqual(self.pointG + self.pointG2, self.pointG3) - self.assertEqual(self.pointG2 + self.pointG, self.pointG3) - self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2) - self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2) - - G5 = self.pointG2 + self.pointG3 - self.assertEqual(G5.x, 0x7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034) - self.assertEqual(G5.y, 0xadfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb) - - def test_inplace_addition(self): - pointH = self.pointG.copy() - pointH += self.pointG - self.assertEqual(pointH, self.pointG2) - pointH += self.pointG - self.assertEqual(pointH, self.pointG3) - pointH += self.pointG.point_at_infinity() - self.assertEqual(pointH, self.pointG3) - - def test_doubling(self): - pointH = self.pointG.copy() - pointH.double() - self.assertEqual(pointH.x, self.pointG2.x) - self.assertEqual(pointH.y, self.pointG2.y) - - # 2*0 - pai = self.pointG.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - def test_scalar_multiply(self): - d = 0 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0) - self.assertEqual(pointH.y, 1) - - d = 1 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG.x) - self.assertEqual(pointH.y, self.pointG.y) - - d = 2 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG2.x) - self.assertEqual(pointH.y, self.pointG2.y) - - d = 3 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG3.x) - self.assertEqual(pointH.y, self.pointG3.y) - - d = 4 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0x49dcbc5c6c0cce2c1419a17226f929ea255a09cf4e0891c693fda4be70c74cc301b7bdf1515dd8ba21aee1798949e120e2ce42ac48ba7f30) - self.assertEqual(pointH.y, 0xd49077e4accde527164b33a5de021b979cb7c02f0457d845c90dc3227b8a5bc1c0d8f97ea1ca9472b5d444285d0d4f5b32e236f86de51839) - - d = 5 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0x7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034) - self.assertEqual(pointH.y, 0xadfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb) - - d = 10 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0x77486f9d19f6411cdd35d30d1c3235f71936452c787e5c034134d3e8172278aca61622bc805761ce3dab65118a0122d73b403165d0ed303d) - self.assertEqual(pointH.y, 0x4d2fea0b026be11024f1f0fe7e94e618e8ac17381ada1d1bf7ee293a68ff5d0bf93c1997dc1aabdc0c7e6381428d85b6b1954a89e4cddf67) - - d = 20 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0x3c236422354600fe6763defcc1503737e4ed89e262d0de3ec1e552020f2a56fe3b9e1e012d021072598c3c2821e18268bb8fb8339c0d1216) - self.assertEqual(pointH.y, 0xb555b9721f630ccb05fc466de4c74d3d2781e69eca88e1b040844f04cab39fd946f91c688fa42402bb38fb9c3e61231017020b219b4396e1) - - d = 255 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0xbeb7f8388b05cd9c1aa2e3c0dcf31e2b563659361826225390e7748654f627d5c36cbe627e9019936b56d15d4dad7c337c09bac64ff4197f) - self.assertEqual(pointH.y, 0x1e37312b2dd4e9440c43c6e7725fc4fa3d11e582d4863f1d018e28f50c0efdb1f53f9b01ada7c87fa162b1f0d72401015d57613d25f1ad53) - - d = 256 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0xf19c34feb56730e3e2be761ac0a2a2b24853b281dda019fc35a5ab58e3696beb39609ae756b0d20fb7ccf0d79aaf5f3bca2e4fdb25bfac1c) - self.assertEqual(pointH.y, 0x3beb69cc9111bffcaddc61d363ce6fe5dd44da4aadce78f52e92e985d5442344ced72c4611ed0daac9f4f5661eab73d7a12d25ce8a30241e) - - def test_sizes(self): - self.assertEqual(self.pointG.size_in_bits(), 448) - self.assertEqual(self.pointG.size_in_bytes(), 56) + Gxy = { + "x": 0x4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E, + "y": 0x693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14, + } + + G2xy = { + "x": 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA955555555555555555555555555555555555555555555555555555555, + "y": 0xAE05E9634AD7048DB359D6205086C2B0036ED7A035884DD7B7E36D728AD8C4B80D6565833A2A3098BBBCB2BED1CDA06BDAEAFBCDEA9386ED, + } + + G3xy = { + "x": 0x865886B9108AF6455BD64316CB6943332241B8B8CDA82C7E2BA077A4A3FCFE8DAA9CBF7F6271FD6E862B769465DA8575728173286FF2F8F, + "y": 0xE005A8DBD5125CF706CBDA7AD43AA6449A4A8D952356C3B9FCE43C82EC4E1D58BB3A331BDB6767F0BFFA9A68FED02DAFB822AC13588ED6FC, + } + + pointG = EccPoint(Gxy["x"], Gxy["y"], curve="ed448") + pointG2 = EccPoint(G2xy["x"], G2xy["y"], curve="ed448") + pointG3 = EccPoint(G3xy["x"], G3xy["y"], curve="ed448") + + def test_curve_attribute(self): + self.assertEqual(self.pointG.curve, "Ed448") + + def test_init_xy(self): + EccPoint(self.Gxy["x"], self.Gxy["y"], curve="Ed448") + + # Neutral point + pai = EccPoint(0, 1, curve="Ed448") + self.assertEqual(pai.x, 0) + self.assertEqual(pai.y, 1) + self.assertEqual(pai.xy, (0, 1)) + + # G + bp = self.pointG.copy() + self.assertEqual( + bp.x, + 0x4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E, + ) + self.assertEqual( + bp.y, + 0x693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14, + ) + self.assertEqual(bp.xy, (bp.x, bp.y)) + + # 2G + bp2 = self.pointG2.copy() + self.assertEqual( + bp2.x, + 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA955555555555555555555555555555555555555555555555555555555, + ) + self.assertEqual( + bp2.y, + 0xAE05E9634AD7048DB359D6205086C2B0036ED7A035884DD7B7E36D728AD8C4B80D6565833A2A3098BBBCB2BED1CDA06BDAEAFBCDEA9386ED, + ) + self.assertEqual(bp2.xy, (bp2.x, bp2.y)) + + # 5G + EccPoint( + x=0x7A9F9335A48DCB0E2BA7601EEDB50DEF80CBCF728562ADA756D761E8958812808BC0D57A920C3C96F07B2D8CEFC6F950D0A99D1092030034, + y=0xADFD751A2517EDD3B9109CE4FD580ADE260CA1823AB18FCED86551F7B698017127D7A4EE59D2B33C58405512881F225443B4731472F435EB, + curve="Ed448", + ) + + # Catch if point is not on the curve + self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed448") + + def test_set(self): + pointW = EccPoint(0, 1, curve="Ed448") + pointW.set(self.pointG) + self.assertEqual(pointW.x, self.pointG.x) + self.assertEqual(pointW.y, self.pointG.y) + + def test_copy(self): + pointW = self.pointG.copy() + self.assertEqual(pointW.x, self.pointG.x) + self.assertEqual(pointW.y, self.pointG.y) + + def test_equal(self): + pointH = self.pointG.copy() + pointI = self.pointG2.copy() + self.assertEqual(self.pointG, pointH) + self.assertNotEqual(self.pointG, pointI) + + def test_pai(self): + pai = EccPoint(0, 1, curve="Ed448") + self.assertTrue(pai.is_point_at_infinity()) + self.assertEqual(pai, pai.point_at_infinity()) + + def test_negate(self): + negG = -self.pointG + sum = self.pointG + negG + self.assertTrue(sum.is_point_at_infinity()) + + def test_addition(self): + self.assertEqual(self.pointG + self.pointG2, self.pointG3) + self.assertEqual(self.pointG2 + self.pointG, self.pointG3) + self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2) + self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2) + + G5 = self.pointG2 + self.pointG3 + self.assertEqual( + G5.x, + 0x7A9F9335A48DCB0E2BA7601EEDB50DEF80CBCF728562ADA756D761E8958812808BC0D57A920C3C96F07B2D8CEFC6F950D0A99D1092030034, + ) + self.assertEqual( + G5.y, + 0xADFD751A2517EDD3B9109CE4FD580ADE260CA1823AB18FCED86551F7B698017127D7A4EE59D2B33C58405512881F225443B4731472F435EB, + ) + + def test_inplace_addition(self): + pointH = self.pointG.copy() + pointH += self.pointG + self.assertEqual(pointH, self.pointG2) + pointH += self.pointG + self.assertEqual(pointH, self.pointG3) + pointH += self.pointG.point_at_infinity() + self.assertEqual(pointH, self.pointG3) + + def test_doubling(self): + pointH = self.pointG.copy() + pointH.double() + self.assertEqual(pointH.x, self.pointG2.x) + self.assertEqual(pointH.y, self.pointG2.y) + + # 2*0 + pai = self.pointG.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + def test_scalar_multiply(self): + d = 0 + pointH = d * self.pointG + self.assertEqual(pointH.x, 0) + self.assertEqual(pointH.y, 1) + + d = 1 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG.x) + self.assertEqual(pointH.y, self.pointG.y) + + d = 2 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG2.x) + self.assertEqual(pointH.y, self.pointG2.y) + + d = 3 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG3.x) + self.assertEqual(pointH.y, self.pointG3.y) + + d = 4 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0x49DCBC5C6C0CCE2C1419A17226F929EA255A09CF4E0891C693FDA4BE70C74CC301B7BDF1515DD8BA21AEE1798949E120E2CE42AC48BA7F30, + ) + self.assertEqual( + pointH.y, + 0xD49077E4ACCDE527164B33A5DE021B979CB7C02F0457D845C90DC3227B8A5BC1C0D8F97EA1CA9472B5D444285D0D4F5B32E236F86DE51839, + ) + + d = 5 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0x7A9F9335A48DCB0E2BA7601EEDB50DEF80CBCF728562ADA756D761E8958812808BC0D57A920C3C96F07B2D8CEFC6F950D0A99D1092030034, + ) + self.assertEqual( + pointH.y, + 0xADFD751A2517EDD3B9109CE4FD580ADE260CA1823AB18FCED86551F7B698017127D7A4EE59D2B33C58405512881F225443B4731472F435EB, + ) + + d = 10 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0x77486F9D19F6411CDD35D30D1C3235F71936452C787E5C034134D3E8172278ACA61622BC805761CE3DAB65118A0122D73B403165D0ED303D, + ) + self.assertEqual( + pointH.y, + 0x4D2FEA0B026BE11024F1F0FE7E94E618E8AC17381ADA1D1BF7EE293A68FF5D0BF93C1997DC1AABDC0C7E6381428D85B6B1954A89E4CDDF67, + ) + + d = 20 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0x3C236422354600FE6763DEFCC1503737E4ED89E262D0DE3EC1E552020F2A56FE3B9E1E012D021072598C3C2821E18268BB8FB8339C0D1216, + ) + self.assertEqual( + pointH.y, + 0xB555B9721F630CCB05FC466DE4C74D3D2781E69ECA88E1B040844F04CAB39FD946F91C688FA42402BB38FB9C3E61231017020B219B4396E1, + ) + + d = 255 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0xBEB7F8388B05CD9C1AA2E3C0DCF31E2B563659361826225390E7748654F627D5C36CBE627E9019936B56D15D4DAD7C337C09BAC64FF4197F, + ) + self.assertEqual( + pointH.y, + 0x1E37312B2DD4E9440C43C6E7725FC4FA3D11E582D4863F1D018E28F50C0EFDB1F53F9B01ADA7C87FA162B1F0D72401015D57613D25F1AD53, + ) + + d = 256 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0xF19C34FEB56730E3E2BE761AC0A2A2B24853B281DDA019FC35A5AB58E3696BEB39609AE756B0D20FB7CCF0D79AAF5F3BCA2E4FDB25BFAC1C, + ) + self.assertEqual( + pointH.y, + 0x3BEB69CC9111BFFCADDC61D363CE6FE5DD44DA4AADCE78F52E92E985D5442344CED72C4611ED0DAAC9F4F5661EAB73D7A12D25CE8A30241E, + ) + + def test_sizes(self): + self.assertEqual(self.pointG.size_in_bits(), 448) + self.assertEqual(self.pointG.size_in_bytes(), 56) class TestEccKey_Ed448(unittest.TestCase): - - def test_private_key(self): - seed = unhexlify("4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9") - Px = 0x72a01eea003a35f9ac44231dc4aae2a382f351d80bf32508175b0855edcf389aa2bbf308dd961ce361a6e7c2091bc78957f6ebcf3002a617 - Py = 0x9e0d08d84586e9aeefecacb41d049b831f1a3ee0c3eada63e34557b30702b50ab59fb372feff7c30b8cbb7dd51afbe88444ec56238722ec1 - - key = EccKey(curve="Ed448", seed=seed) - self.assertEqual(key.seed, seed) - self.assertEqual(key.d, 0xb07cf179604f83433186e5178760c759c15125ee54ff6f8dcde46e872b709ac82ed0bd0a4e036d774034dcb18a9fb11894657a1485895f80) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, Px) - self.assertEqual(key.pointQ.y, Py) - - point = EccPoint(Px, Py, "ed448") - key = EccKey(curve="Ed448", seed=seed, point=point) - self.assertEqual(key.d, 0xb07cf179604f83433186e5178760c759c15125ee54ff6f8dcde46e872b709ac82ed0bd0a4e036d774034dcb18a9fb11894657a1485895f80) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="ed448", seed=seed) - - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="ed448", d=1) - - def test_public_key(self): - point = EccPoint(_curves['ed448'].Gx, _curves['ed448'].Gy, curve='ed448') - key = EccKey(curve="ed448", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - priv_key = EccKey(curve="ed448", seed=b'H'*57) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_seed(self): - self.assertRaises(ValueError, lambda: EccKey(curve="ed448", seed=b'H' * 56)) - - def test_equality(self): - private_key = ECC.construct(seed=b'H'*57, curve="Ed448") - private_key2 = ECC.construct(seed=b'H'*57, curve="ed448") - private_key3 = ECC.construct(seed=b'C'*57, curve="Ed448") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='ed448') - self.assertIn("curve='Ed448'", repr(key)) - self.assertEqual(key.curve, 'Ed448') - self.assertEqual(key.public_key().curve, 'Ed448') + def test_private_key(self): + seed = unhexlify( + "4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9" + ) + Px = 0x72A01EEA003A35F9AC44231DC4AAE2A382F351D80BF32508175B0855EDCF389AA2BBF308DD961CE361A6E7C2091BC78957F6EBCF3002A617 + Py = 0x9E0D08D84586E9AEEFECACB41D049B831F1A3EE0C3EADA63E34557B30702B50AB59FB372FEFF7C30B8CBB7DD51AFBE88444EC56238722EC1 + + key = EccKey(curve="Ed448", seed=seed) + self.assertEqual(key.seed, seed) + self.assertEqual( + key.d, + 0xB07CF179604F83433186E5178760C759C15125EE54FF6F8DCDE46E872B709AC82ED0BD0A4E036D774034DCB18A9FB11894657A1485895F80, + ) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, Px) + self.assertEqual(key.pointQ.y, Py) + + point = EccPoint(Px, Py, "ed448") + key = EccKey(curve="Ed448", seed=seed, point=point) + self.assertEqual( + key.d, + 0xB07CF179604F83433186E5178760C759C15125EE54FF6F8DCDE46E872B709AC82ED0BD0A4E036D774034DCB18A9FB11894657A1485895F80, + ) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="ed448", seed=seed) + + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="ed448", d=1) + + def test_public_key(self): + point = EccPoint(_curves["ed448"].Gx, _curves["ed448"].Gy, curve="ed448") + key = EccKey(curve="ed448", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="ed448", seed=b"H" * 57) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_seed(self): + self.assertRaises(ValueError, lambda: EccKey(curve="ed448", seed=b"H" * 56)) + + def test_equality(self): + private_key = ECC.construct(seed=b"H" * 57, curve="Ed448") + private_key2 = ECC.construct(seed=b"H" * 57, curve="ed448") + private_key3 = ECC.construct(seed=b"C" * 57, curve="Ed448") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="ed448") + self.assertIn("curve='Ed448'", repr(key)) + self.assertEqual(key.curve, "Ed448") + self.assertEqual(key.public_key().curve, "Ed448") class TestEccModule_Ed448(unittest.TestCase): + def test_generate(self): + key = ECC.generate(curve="Ed448") + self.assertTrue(key.has_private()) + point = EccPoint(_curves["Ed448"].Gx, _curves["Ed448"].Gy, curve="Ed448") * key.d + self.assertEqual(key.pointQ, point) + + # Always random + key2 = ECC.generate(curve="Ed448") + self.assertNotEqual(key, key2) + + # Other names + ECC.generate(curve="Ed448") + + # Random source + key1 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read) + key2 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read) + self.assertEqual(key1, key2) + + def test_construct(self): + seed = unhexlify( + "4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9" + ) + Px = 0x72A01EEA003A35F9AC44231DC4AAE2A382F351D80BF32508175B0855EDCF389AA2BBF308DD961CE361A6E7C2091BC78957F6EBCF3002A617 + Py = 0x9E0D08D84586E9AEEFECACB41D049B831F1A3EE0C3EADA63E34557B30702B50AB59FB372FEFF7C30B8CBB7DD51AFBE88444EC56238722EC1 + d = 0xB07CF179604F83433186E5178760C759C15125EE54FF6F8DCDE46E872B709AC82ED0BD0A4E036D774034DCB18A9FB11894657A1485895F80 + point = EccPoint(Px, Py, curve="Ed448") + + # Private key only + key = ECC.construct(curve="Ed448", seed=seed) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Public key only + key = ECC.construct(curve="Ed448", point_x=Px, point_y=Py) + self.assertEqual(key.pointQ, point) + self.assertFalse(key.has_private()) + + # Private and public key + key = ECC.construct(curve="Ed448", seed=seed, point_x=Px, point_y=Py) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Other names + key = ECC.construct(curve="ed448", seed=seed) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["ed448"].Gx, point_y=_curves["ed448"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="Ed448", **coord) + self.assertRaises(ValueError, ECC.construct, curve="Ed448", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="Ed448", seed=b"H" * 58) - def test_generate(self): - key = ECC.generate(curve="Ed448") - self.assertTrue(key.has_private()) - point = EccPoint(_curves['Ed448'].Gx, _curves['Ed448'].Gy, curve="Ed448") * key.d - self.assertEqual(key.pointQ, point) - - # Always random - key2 = ECC.generate(curve="Ed448") - self.assertNotEqual(key, key2) - - # Other names - ECC.generate(curve="Ed448") - - # Random source - key1 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read) - key2 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read) - self.assertEqual(key1, key2) - - def test_construct(self): - seed = unhexlify("4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9") - Px = 0x72a01eea003a35f9ac44231dc4aae2a382f351d80bf32508175b0855edcf389aa2bbf308dd961ce361a6e7c2091bc78957f6ebcf3002a617 - Py = 0x9e0d08d84586e9aeefecacb41d049b831f1a3ee0c3eada63e34557b30702b50ab59fb372feff7c30b8cbb7dd51afbe88444ec56238722ec1 - d = 0xb07cf179604f83433186e5178760c759c15125ee54ff6f8dcde46e872b709ac82ed0bd0a4e036d774034dcb18a9fb11894657a1485895f80 - point = EccPoint(Px, Py, curve="Ed448") - - # Private key only - key = ECC.construct(curve="Ed448", seed=seed) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - # Public key only - key = ECC.construct(curve="Ed448", point_x=Px, point_y=Py) - self.assertEqual(key.pointQ, point) - self.assertFalse(key.has_private()) - - # Private and public key - key = ECC.construct(curve="Ed448", seed=seed, point_x=Px, point_y=Py) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Other names - key = ECC.construct(curve="ed448", seed=seed) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['ed448'].Gx, point_y=_curves['ed448'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="Ed448", **coord) - self.assertRaises(ValueError, ECC.construct, curve="Ed448", d=2, **coordG) - self.assertRaises(ValueError, ECC.construct, curve="Ed448", seed=b'H'*58) +def get_tests(config={}): + tests = [] + tests += list_test_cases(TestEccPoint_Ed448) + tests += list_test_cases(TestEccKey_Ed448) + tests += list_test_cases(TestEccModule_Ed448) + return tests -def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint_Ed448) - tests += list_test_cases(TestEccKey_Ed448) - tests += list_test_cases(TestEccModule_Ed448) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_NIST.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_NIST.py index ae790b14..0b4a5210 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_NIST.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ECC_NIST.py @@ -29,7 +29,6 @@ # =================================================================== import unittest -from binascii import unhexlify from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.SelfTest.loader import load_test_vectors @@ -41,1400 +40,1481 @@ class TestEccPoint(unittest.TestCase): - - def test_mix(self): - - p1 = ECC.generate(curve='P-256').pointQ - p2 = ECC.generate(curve='P-384').pointQ - - try: - p1 + p2 - assert(False) - except ValueError as e: - assert "not on the same curve" in str(e) - - try: - p1 += p2 - assert(False) - except ValueError as e: - assert "not on the same curve" in str(e) - - class OtherKeyType: - pass - - self.assertFalse(p1 == OtherKeyType()) - self.assertTrue(p1 != OtherKeyType()) - - def test_repr(self): - p1 = ECC.construct(curve='P-256', - d=75467964919405407085864614198393977741148485328036093939970922195112333446269, - point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, - point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389) - self.assertEqual(repr(p1), "EccKey(curve='NIST P-256', point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389, d=75467964919405407085864614198393977741148485328036093939970922195112333446269)") + def test_mix(self): + p1 = ECC.generate(curve="P-256").pointQ + p2 = ECC.generate(curve="P-384").pointQ + + try: + p1 + p2 + assert False + except ValueError as e: + assert "not on the same curve" in str(e) + + try: + p1 += p2 + assert False + except ValueError as e: + assert "not on the same curve" in str(e) + + class OtherKeyType: + pass + + self.assertFalse(p1 == OtherKeyType()) + self.assertTrue(p1 != OtherKeyType()) + + def test_repr(self): + p1 = ECC.construct( + curve="P-256", + d=75467964919405407085864614198393977741148485328036093939970922195112333446269, + point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, + point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389, + ) + self.assertEqual( + repr(p1), + "EccKey(curve='NIST P-256', point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389, d=75467964919405407085864614198393977741148485328036093939970922195112333446269)", + ) class TestEccPoint_NIST_P192(unittest.TestCase): - """Tests defined in section 4.1 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0xd458e7d127ae671b0c330266d246769353a012073e97acf8, - 0x325930500d851f336bddc050cf7fb11b5673a1645086df3b, - curve='p192') - - pointT = EccPoint( - 0xf22c4395213e9ebe67ddecdd87fdbd01be16fb059b9753a4, - 0x264424096af2b3597796db48f8dfb41fa9cecc97691a9c79, - curve='p192') - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-192") - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x48e1e4096b9b8e5ca9d0f1f077b8abf58e843894de4d0290 - pointRy = 0x408fa77c797cd7dbfb16aa48a3648d3d63c94117d7b6aa4b - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x48e1e4096b9b8e5ca9d0f1f077b8abf58e843894de4d0290 - pointRy = 0x408fa77c797cd7dbfb16aa48a3648d3d63c94117d7b6aa4b - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x30c5bc6b8c7da25354b373dc14dd8a0eba42d25a3f6e6962 - pointRy = 0x0dde14bc4249a721c407aedbf011e2ddbbcb2968c9d889cf - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xa78a236d60baec0c5dd41b33a542463a8255391af64c74ee - pointRx = 0x1faee4205a4f669d2d0a8f25e3bcec9a62a6952965bf6d31 - pointRy = 0x5ff2cdfa508a2581892367087c696f179e7a4d7e8260fb06 - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - # Reverse order - pointR = d * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pointR = Integer(d) * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_joint_scalar_multiply(self): - d = 0xa78a236d60baec0c5dd41b33a542463a8255391af64c74ee - e = 0xc4be3d53ec3089e71e4de8ceab7cce889bc393cd85b972bc - pointRx = 0x019f64eed8fa9b72b7dfea82c17c9bfa60ecb9e1778b5bde - pointRy = 0x16590c5fcd8655fa4ced33fb800e2a7e3c61f35d83503644 - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 192) - self.assertEqual(self.pointS.size_in_bytes(), 24) + """Tests defined in section 4.1 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0xD458E7D127AE671B0C330266D246769353A012073E97ACF8, + 0x325930500D851F336BDDC050CF7FB11B5673A1645086DF3B, + curve="p192", + ) + + pointT = EccPoint( + 0xF22C4395213E9EBE67DDECDD87FDBD01BE16FB059B9753A4, + 0x264424096AF2B3597796DB48F8DFB41FA9CECC97691A9C79, + curve="p192", + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-192") + + def test_set(self): + pointW = EccPoint(0, 0) + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = 0x48E1E4096B9B8E5CA9D0F1F077B8ABF58E843894DE4D0290 + pointRy = 0x408FA77C797CD7DBFB16AA48A3648D3D63C94117D7B6AA4B + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def test_inplace_addition(self): + pointRx = 0x48E1E4096B9B8E5CA9D0F1F077B8ABF58E843894DE4D0290 + pointRy = 0x408FA77C797CD7DBFB16AA48A3648D3D63C94117D7B6AA4B + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = 0x30C5BC6B8C7DA25354B373DC14DD8A0EBA42D25A3F6E6962 + pointRy = 0x0DDE14BC4249A721C407AEDBF011E2DDBBCB2968C9D889CF + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0xA78A236D60BAEC0C5DD41B33A542463A8255391AF64C74EE + pointRx = 0x1FAEE4205A4F669D2D0A8F25E3BCEC9A62A6952965BF6D31 + pointRy = 0x5FF2CDFA508A2581892367087C696F179E7A4D7E8260FB06 + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + # Reverse order + pointR = d * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pointR = Integer(d) * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_joint_scalar_multiply(self): + d = 0xA78A236D60BAEC0C5DD41B33A542463A8255391AF64C74EE + e = 0xC4BE3D53EC3089E71E4DE8CEAB7CCE889BC393CD85B972BC + pointRx = 0x019F64EED8FA9B72B7DFEA82C17C9BFA60ECB9E1778B5BDE + pointRy = 0x16590C5FCD8655FA4CED33FB800E2A7E3C61F35D83503644 + + pointR = self.pointS * d + self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 192) + self.assertEqual(self.pointS.size_in_bytes(), 24) class TestEccPoint_NIST_P224(unittest.TestCase): - """Tests defined in section 4.2 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0x6eca814ba59a930843dc814edd6c97da95518df3c6fdf16e9a10bb5b, - 0xef4b497f0963bc8b6aec0ca0f259b89cd80994147e05dc6b64d7bf22, - curve='p224') - - pointT = EccPoint( - 0xb72b25aea5cb03fb88d7e842002969648e6ef23c5d39ac903826bd6d, - 0xc42a8a4d34984f0b71b5b4091af7dceb33ea729c1a2dc8b434f10c34, - curve='p224') - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-224") - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x236f26d9e84c2f7d776b107bd478ee0a6d2bcfcaa2162afae8d2fd15 - pointRy = 0xe53cc0a7904ce6c3746f6a97471297a0b7d5cdf8d536ae25bb0fda70 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x236f26d9e84c2f7d776b107bd478ee0a6d2bcfcaa2162afae8d2fd15 - pointRy = 0xe53cc0a7904ce6c3746f6a97471297a0b7d5cdf8d536ae25bb0fda70 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0xa9c96f2117dee0f27ca56850ebb46efad8ee26852f165e29cb5cdfc7 - pointRy = 0xadf18c84cf77ced4d76d4930417d9579207840bf49bfbf5837dfdd7d - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xa78ccc30eaca0fcc8e36b2dd6fbb03df06d37f52711e6363aaf1d73b - pointRx = 0x96a7625e92a8d72bff1113abdb95777e736a14c6fdaacc392702bca4 - pointRy = 0x0f8e5702942a3c5e13cd2fd5801915258b43dfadc70d15dbada3ed10 - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - # Reverse order - pointR = d * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pointR = Integer(d) * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_joing_scalar_multiply(self): - d = 0xa78ccc30eaca0fcc8e36b2dd6fbb03df06d37f52711e6363aaf1d73b - e = 0x54d549ffc08c96592519d73e71e8e0703fc8177fa88aa77a6ed35736 - pointRx = 0xdbfe2958c7b2cda1302a67ea3ffd94c918c5b350ab838d52e288c83e - pointRy = 0x2f521b83ac3b0549ff4895abcc7f0c5a861aacb87acbc5b8147bb18b - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 224) - self.assertEqual(self.pointS.size_in_bytes(), 28) + """Tests defined in section 4.2 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0x6ECA814BA59A930843DC814EDD6C97DA95518DF3C6FDF16E9A10BB5B, + 0xEF4B497F0963BC8B6AEC0CA0F259B89CD80994147E05DC6B64D7BF22, + curve="p224", + ) + + pointT = EccPoint( + 0xB72B25AEA5CB03FB88D7E842002969648E6EF23C5D39AC903826BD6D, + 0xC42A8A4D34984F0B71B5B4091AF7DCEB33EA729C1A2DC8B434F10C34, + curve="p224", + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-224") + + def test_set(self): + pointW = EccPoint(0, 0) + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = 0x236F26D9E84C2F7D776B107BD478EE0A6D2BCFCAA2162AFAE8D2FD15 + pointRy = 0xE53CC0A7904CE6C3746F6A97471297A0B7D5CDF8D536AE25BB0FDA70 + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def test_inplace_addition(self): + pointRx = 0x236F26D9E84C2F7D776B107BD478EE0A6D2BCFCAA2162AFAE8D2FD15 + pointRy = 0xE53CC0A7904CE6C3746F6A97471297A0B7D5CDF8D536AE25BB0FDA70 + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = 0xA9C96F2117DEE0F27CA56850EBB46EFAD8EE26852F165E29CB5CDFC7 + pointRy = 0xADF18C84CF77CED4D76D4930417D9579207840BF49BFBF5837DFDD7D + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0xA78CCC30EACA0FCC8E36B2DD6FBB03DF06D37F52711E6363AAF1D73B + pointRx = 0x96A7625E92A8D72BFF1113ABDB95777E736A14C6FDAACC392702BCA4 + pointRy = 0x0F8E5702942A3C5E13CD2FD5801915258B43DFADC70D15DBADA3ED10 + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + # Reverse order + pointR = d * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pointR = Integer(d) * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_joing_scalar_multiply(self): + d = 0xA78CCC30EACA0FCC8E36B2DD6FBB03DF06D37F52711E6363AAF1D73B + e = 0x54D549FFC08C96592519D73E71E8E0703FC8177FA88AA77A6ED35736 + pointRx = 0xDBFE2958C7B2CDA1302A67EA3FFD94C918C5B350AB838D52E288C83E + pointRy = 0x2F521B83AC3B0549FF4895ABCC7F0C5A861AACB87ACBC5B8147BB18B + + pointR = self.pointS * d + self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 224) + self.assertEqual(self.pointS.size_in_bytes(), 28) class TestEccPoint_NIST_P256(unittest.TestCase): - """Tests defined in section 4.3 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0xde2444bebc8d36e682edd27e0f271508617519b3221a8fa0b77cab3989da97c9, - 0xc093ae7ff36e5380fc01a5aad1e66659702de80f53cec576b6350b243042a256) - - pointT = EccPoint( - 0x55a8b00f8da1d44e62f6b3b25316212e39540dc861c89575bb8cf92e35e0986b, - 0x5421c3209c2d6c704835d82ac4c3dd90f61a8a52598b9e7ab656e9d8c8b24316) - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-256") - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e - pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e - pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x7669e6901606ee3ba1a8eef1e0024c33df6c22f3b17481b82a860ffcdb6127b0 - pointRy = 0xfa878162187a54f6c39f6ee0072f33de389ef3eecd03023de10ca2c1db61d0c7 - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd - pointRx = 0x51d08d5f2d4278882946d88d83c97d11e62becc3cfc18bedacc89ba34eeca03f - pointRy = 0x75ee68eb8bf626aa5b673ab51f6e744e06f8fcf8a6c0cf3035beca956a7b41d5 - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - # Reverse order - pointR = d * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pointR = Integer(d) * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_joing_scalar_multiply(self): - d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd - e = 0xd37f628ece72a462f0145cbefe3f0b355ee8332d37acdd83a358016aea029db7 - pointRx = 0xd867b4679221009234939221b8046245efcf58413daacbeff857b8588341f6b8 - pointRy = 0xf2504055c03cede12d22720dad69c745106b6607ec7e50dd35d54bd80f615275 - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 256) - self.assertEqual(self.pointS.size_in_bytes(), 32) + """Tests defined in section 4.3 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0xDE2444BEBC8D36E682EDD27E0F271508617519B3221A8FA0B77CAB3989DA97C9, + 0xC093AE7FF36E5380FC01A5AAD1E66659702DE80F53CEC576B6350B243042A256, + ) + + pointT = EccPoint( + 0x55A8B00F8DA1D44E62F6B3B25316212E39540DC861C89575BB8CF92E35E0986B, + 0x5421C3209C2D6C704835D82AC4C3DD90F61A8A52598B9E7AB656E9D8C8B24316, + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-256") + + def test_set(self): + pointW = EccPoint(0, 0) + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = 0x72B13DD4354B6B81745195E98CC5BA6970349191AC476BD4553CF35A545A067E + pointRy = 0x8D585CBB2E1327D75241A8A122D7620DC33B13315AA5C9D46D013011744AC264 + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def test_inplace_addition(self): + pointRx = 0x72B13DD4354B6B81745195E98CC5BA6970349191AC476BD4553CF35A545A067E + pointRy = 0x8D585CBB2E1327D75241A8A122D7620DC33B13315AA5C9D46D013011744AC264 + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = 0x7669E6901606EE3BA1A8EEF1E0024C33DF6C22F3B17481B82A860FFCDB6127B0 + pointRy = 0xFA878162187A54F6C39F6EE0072F33DE389EF3EECD03023DE10CA2C1DB61D0C7 + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0xC51E4753AFDEC1E6B6C6A5B992F43F8DD0C7A8933072708B6522468B2FFB06FD + pointRx = 0x51D08D5F2D4278882946D88D83C97D11E62BECC3CFC18BEDACC89BA34EECA03F + pointRy = 0x75EE68EB8BF626AA5B673AB51F6E744E06F8FCF8A6C0CF3035BECA956A7B41D5 + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + # Reverse order + pointR = d * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pointR = Integer(d) * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_joing_scalar_multiply(self): + d = 0xC51E4753AFDEC1E6B6C6A5B992F43F8DD0C7A8933072708B6522468B2FFB06FD + e = 0xD37F628ECE72A462F0145CBEFE3F0B355EE8332D37ACDD83A358016AEA029DB7 + pointRx = 0xD867B4679221009234939221B8046245EFCF58413DAACBEFF857B8588341F6B8 + pointRy = 0xF2504055C03CEDE12D22720DAD69C745106B6607EC7E50DD35D54BD80F615275 + + pointR = self.pointS * d + self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 256) + self.assertEqual(self.pointS.size_in_bytes(), 32) class TestEccPoint_NIST_P384(unittest.TestCase): - """Tests defined in section 4.4 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0xfba203b81bbd23f2b3be971cc23997e1ae4d89e69cb6f92385dda82768ada415ebab4167459da98e62b1332d1e73cb0e, - 0x5ffedbaefdeba603e7923e06cdb5d0c65b22301429293376d5c6944e3fa6259f162b4788de6987fd59aed5e4b5285e45, - "p384") - - pointT = EccPoint( - 0xaacc05202e7fda6fc73d82f0a66220527da8117ee8f8330ead7d20ee6f255f582d8bd38c5a7f2b40bcdb68ba13d81051, - 0x84009a263fefba7c2c57cffa5db3634d286131afc0fca8d25afa22a7b5dce0d9470da89233cee178592f49b6fecb5092, - "p384") - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-384") - - def test_set(self): - pointW = EccPoint(0, 0, "p384") - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x12dc5ce7acdfc5844d939f40b4df012e68f865b89c3213ba97090a247a2fc009075cf471cd2e85c489979b65ee0b5eed - pointRy = 0x167312e58fe0c0afa248f2854e3cddcb557f983b3189b67f21eee01341e7e9fe67f6ee81b36988efa406945c8804a4b0 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def _test_inplace_addition(self): - pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e - pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x2a2111b1e0aa8b2fc5a1975516bc4d58017ff96b25e1bdff3c229d5fac3bacc319dcbec29f9478f42dee597b4641504c - pointRy = 0xfa2e3d9dc84db8954ce8085ef28d7184fddfd1344b4d4797343af9b5f9d837520b450f726443e4114bd4e5bdb2f65ddd - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xa4ebcae5a665983493ab3e626085a24c104311a761b5a8fdac052ed1f111a5c44f76f45659d2d111a61b5fdd97583480 - pointRx = 0xe4f77e7ffeb7f0958910e3a680d677a477191df166160ff7ef6bb5261f791aa7b45e3e653d151b95dad3d93ca0290ef2 - pointRy = 0xac7dee41d8c5f4a7d5836960a773cfc1376289d3373f8cf7417b0c6207ac32e913856612fc9ff2e357eb2ee05cf9667f - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - def test_joing_scalar_multiply(self): - d = 0xa4ebcae5a665983493ab3e626085a24c104311a761b5a8fdac052ed1f111a5c44f76f45659d2d111a61b5fdd97583480 - e = 0xafcf88119a3a76c87acbd6008e1349b29f4ba9aa0e12ce89bcfcae2180b38d81ab8cf15095301a182afbc6893e75385d - pointRx = 0x917ea28bcd641741ae5d18c2f1bd917ba68d34f0f0577387dc81260462aea60e2417b8bdc5d954fc729d211db23a02dc - pointRy = 0x1a29f7ce6d074654d77b40888c73e92546c8f16a5ff6bcbd307f758d4aee684beff26f6742f597e2585c86da908f7186 - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 384) - self.assertEqual(self.pointS.size_in_bytes(), 48) + """Tests defined in section 4.4 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0xFBA203B81BBD23F2B3BE971CC23997E1AE4D89E69CB6F92385DDA82768ADA415EBAB4167459DA98E62B1332D1E73CB0E, + 0x5FFEDBAEFDEBA603E7923E06CDB5D0C65B22301429293376D5C6944E3FA6259F162B4788DE6987FD59AED5E4B5285E45, + "p384", + ) + + pointT = EccPoint( + 0xAACC05202E7FDA6FC73D82F0A66220527DA8117EE8F8330EAD7D20EE6F255F582D8BD38C5A7F2B40BCDB68BA13D81051, + 0x84009A263FEFBA7C2C57CFFA5DB3634D286131AFC0FCA8D25AFA22A7B5DCE0D9470DA89233CEE178592F49B6FECB5092, + "p384", + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-384") + + def test_set(self): + pointW = EccPoint(0, 0, "p384") + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = ( + 0x12DC5CE7ACDFC5844D939F40B4DF012E68F865B89C3213BA97090A247A2FC009075CF471CD2E85C489979B65EE0B5EED + ) + pointRy = ( + 0x167312E58FE0C0AFA248F2854E3CDDCB557F983B3189B67F21EEE01341E7E9FE67F6EE81B36988EFA406945C8804A4B0 + ) + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def _test_inplace_addition(self): + pointRx = 0x72B13DD4354B6B81745195E98CC5BA6970349191AC476BD4553CF35A545A067E + pointRy = 0x8D585CBB2E1327D75241A8A122D7620DC33B13315AA5C9D46D013011744AC264 + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = ( + 0x2A2111B1E0AA8B2FC5A1975516BC4D58017FF96B25E1BDFF3C229D5FAC3BACC319DCBEC29F9478F42DEE597B4641504C + ) + pointRy = ( + 0xFA2E3D9DC84DB8954CE8085EF28D7184FDDFD1344B4D4797343AF9B5F9D837520B450F726443E4114BD4E5BDB2F65DDD + ) + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0xA4EBCAE5A665983493AB3E626085A24C104311A761B5A8FDAC052ED1F111A5C44F76F45659D2D111A61B5FDD97583480 + pointRx = ( + 0xE4F77E7FFEB7F0958910E3A680D677A477191DF166160FF7EF6BB5261F791AA7B45E3E653D151B95DAD3D93CA0290EF2 + ) + pointRy = ( + 0xAC7DEE41D8C5F4A7D5836960A773CFC1376289D3373F8CF7417B0C6207AC32E913856612FC9FF2E357EB2EE05CF9667F + ) + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + def test_joing_scalar_multiply(self): + d = 0xA4EBCAE5A665983493AB3E626085A24C104311A761B5A8FDAC052ED1F111A5C44F76F45659D2D111A61B5FDD97583480 + e = 0xAFCF88119A3A76C87ACBD6008E1349B29F4BA9AA0E12CE89BCFCAE2180B38D81AB8CF15095301A182AFBC6893E75385D + pointRx = ( + 0x917EA28BCD641741AE5D18C2F1BD917BA68D34F0F0577387DC81260462AEA60E2417B8BDC5D954FC729D211DB23A02DC + ) + pointRy = ( + 0x1A29F7CE6D074654D77B40888C73E92546C8F16A5FF6BCBD307F758D4AEE684BEFF26F6742F597E2585C86DA908F7186 + ) + + pointR = self.pointS * d + self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 384) + self.assertEqual(self.pointS.size_in_bytes(), 48) class TestEccPoint_NIST_P521(unittest.TestCase): - """Tests defined in section 4.5 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0x000001d5c693f66c08ed03ad0f031f937443458f601fd098d3d0227b4bf62873af50740b0bb84aa157fc847bcf8dc16a8b2b8bfd8e2d0a7d39af04b089930ef6dad5c1b4, - 0x00000144b7770963c63a39248865ff36b074151eac33549b224af5c8664c54012b818ed037b2b7c1a63ac89ebaa11e07db89fcee5b556e49764ee3fa66ea7ae61ac01823, - "p521") - - pointT = EccPoint( - 0x000000f411f2ac2eb971a267b80297ba67c322dba4bb21cec8b70073bf88fc1ca5fde3ba09e5df6d39acb2c0762c03d7bc224a3e197feaf760d6324006fe3be9a548c7d5, - 0x000001fdf842769c707c93c630df6d02eff399a06f1b36fb9684f0b373ed064889629abb92b1ae328fdb45534268384943f0e9222afe03259b32274d35d1b9584c65e305, - "p521") - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-521") - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x000001264ae115ba9cbc2ee56e6f0059e24b52c8046321602c59a339cfb757c89a59c358a9a8e1f86d384b3f3b255ea3f73670c6dc9f45d46b6a196dc37bbe0f6b2dd9e9 - pointRy = 0x00000062a9c72b8f9f88a271690bfa017a6466c31b9cadc2fc544744aeb817072349cfddc5ad0e81b03f1897bd9c8c6efbdf68237dc3bb00445979fb373b20c9a967ac55 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x000001264ae115ba9cbc2ee56e6f0059e24b52c8046321602c59a339cfb757c89a59c358a9a8e1f86d384b3f3b255ea3f73670c6dc9f45d46b6a196dc37bbe0f6b2dd9e9 - pointRy = 0x00000062a9c72b8f9f88a271690bfa017a6466c31b9cadc2fc544744aeb817072349cfddc5ad0e81b03f1897bd9c8c6efbdf68237dc3bb00445979fb373b20c9a967ac55 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x0000012879442f2450c119e7119a5f738be1f1eba9e9d7c6cf41b325d9ce6d643106e9d61124a91a96bcf201305a9dee55fa79136dc700831e54c3ca4ff2646bd3c36bc6 - pointRy = 0x0000019864a8b8855c2479cbefe375ae553e2393271ed36fadfc4494fc0583f6bd03598896f39854abeae5f9a6515a021e2c0eef139e71de610143f53382f4104dccb543 - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0x000001eb7f81785c9629f136a7e8f8c674957109735554111a2a866fa5a166699419bfa9936c78b62653964df0d6da940a695c7294d41b2d6600de6dfcf0edcfc89fdcb1 - pointRx = 0x00000091b15d09d0ca0353f8f96b93cdb13497b0a4bb582ae9ebefa35eee61bf7b7d041b8ec34c6c00c0c0671c4ae063318fb75be87af4fe859608c95f0ab4774f8c95bb - pointRy = 0x00000130f8f8b5e1abb4dd94f6baaf654a2d5810411e77b7423965e0c7fd79ec1ae563c207bd255ee9828eb7a03fed565240d2cc80ddd2cecbb2eb50f0951f75ad87977f - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - def test_joing_scalar_multiply(self): - d = 0x000001eb7f81785c9629f136a7e8f8c674957109735554111a2a866fa5a166699419bfa9936c78b62653964df0d6da940a695c7294d41b2d6600de6dfcf0edcfc89fdcb1 - e = 0x00000137e6b73d38f153c3a7575615812608f2bab3229c92e21c0d1c83cfad9261dbb17bb77a63682000031b9122c2f0cdab2af72314be95254de4291a8f85f7c70412e3 - pointRx = 0x0000009d3802642b3bea152beb9e05fba247790f7fc168072d363340133402f2585588dc1385d40ebcb8552f8db02b23d687cae46185b27528adb1bf9729716e4eba653d - pointRy = 0x0000000fe44344e79da6f49d87c1063744e5957d9ac0a505bafa8281c9ce9ff25ad53f8da084a2deb0923e46501de5797850c61b229023dd9cf7fc7f04cd35ebb026d89d - - pointR = self.pointS * d - pointR += self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 521) - self.assertEqual(self.pointS.size_in_bytes(), 66) + """Tests defined in section 4.5 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0x000001D5C693F66C08ED03AD0F031F937443458F601FD098D3D0227B4BF62873AF50740B0BB84AA157FC847BCF8DC16A8B2B8BFD8E2D0A7D39AF04B089930EF6DAD5C1B4, + 0x00000144B7770963C63A39248865FF36B074151EAC33549B224AF5C8664C54012B818ED037B2B7C1A63AC89EBAA11E07DB89FCEE5B556E49764EE3FA66EA7AE61AC01823, + "p521", + ) + + pointT = EccPoint( + 0x000000F411F2AC2EB971A267B80297BA67C322DBA4BB21CEC8B70073BF88FC1CA5FDE3BA09E5DF6D39ACB2C0762C03D7BC224A3E197FEAF760D6324006FE3BE9A548C7D5, + 0x000001FDF842769C707C93C630DF6D02EFF399A06F1B36FB9684F0B373ED064889629ABB92B1AE328FDB45534268384943F0E9222AFE03259B32274D35D1B9584C65E305, + "p521", + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-521") + + def test_set(self): + pointW = EccPoint(0, 0) + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = 0x000001264AE115BA9CBC2EE56E6F0059E24B52C8046321602C59A339CFB757C89A59C358A9A8E1F86D384B3F3B255EA3F73670C6DC9F45D46B6A196DC37BBE0F6B2DD9E9 + pointRy = 0x00000062A9C72B8F9F88A271690BFA017A6466C31B9CADC2FC544744AEB817072349CFDDC5AD0E81B03F1897BD9C8C6EFBDF68237DC3BB00445979FB373B20C9A967AC55 + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def test_inplace_addition(self): + pointRx = 0x000001264AE115BA9CBC2EE56E6F0059E24B52C8046321602C59A339CFB757C89A59C358A9A8E1F86D384B3F3B255EA3F73670C6DC9F45D46B6A196DC37BBE0F6B2DD9E9 + pointRy = 0x00000062A9C72B8F9F88A271690BFA017A6466C31B9CADC2FC544744AEB817072349CFDDC5AD0E81B03F1897BD9C8C6EFBDF68237DC3BB00445979FB373B20C9A967AC55 + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = 0x0000012879442F2450C119E7119A5F738BE1F1EBA9E9D7C6CF41B325D9CE6D643106E9D61124A91A96BCF201305A9DEE55FA79136DC700831E54C3CA4FF2646BD3C36BC6 + pointRy = 0x0000019864A8B8855C2479CBEFE375AE553E2393271ED36FADFC4494FC0583F6BD03598896F39854ABEAE5F9A6515A021E2C0EEF139E71DE610143F53382F4104DCCB543 + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0x000001EB7F81785C9629F136A7E8F8C674957109735554111A2A866FA5A166699419BFA9936C78B62653964DF0D6DA940A695C7294D41B2D6600DE6DFCF0EDCFC89FDCB1 + pointRx = 0x00000091B15D09D0CA0353F8F96B93CDB13497B0A4BB582AE9EBEFA35EEE61BF7B7D041B8EC34C6C00C0C0671C4AE063318FB75BE87AF4FE859608C95F0AB4774F8C95BB + pointRy = 0x00000130F8F8B5E1ABB4DD94F6BAAF654A2D5810411E77B7423965E0C7FD79EC1AE563C207BD255EE9828EB7A03FED565240D2CC80DDD2CECBB2EB50F0951F75AD87977F + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + def test_joing_scalar_multiply(self): + d = 0x000001EB7F81785C9629F136A7E8F8C674957109735554111A2A866FA5A166699419BFA9936C78B62653964DF0D6DA940A695C7294D41B2D6600DE6DFCF0EDCFC89FDCB1 + e = 0x00000137E6B73D38F153C3A7575615812608F2BAB3229C92E21C0D1C83CFAD9261DBB17BB77A63682000031B9122C2F0CDAB2AF72314BE95254DE4291A8F85F7C70412E3 + pointRx = 0x0000009D3802642B3BEA152BEB9E05FBA247790F7FC168072D363340133402F2585588DC1385D40EBCB8552F8DB02B23D687CAE46185B27528ADB1BF9729716E4EBA653D + pointRy = 0x0000000FE44344E79DA6F49D87C1063744E5957D9AC0A505BAFA8281C9CE9FF25AD53F8DA084A2DEB0923E46501DE5797850C61B229023DD9CF7FC7F04CD35EBB026D89D + + pointR = self.pointS * d + pointR += self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 521) + self.assertEqual(self.pointS.size_in_bytes(), 66) class TestEccPoint_PAI_P192(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" - - curve = _curves['p192'] - pointG = EccPoint(curve.Gx, curve.Gy, "p192") - - -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P192.txt", - "P-192 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p192"] + pointG = EccPoint(curve.Gx, curve.Gy, "p192") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P192.txt", + "P-192 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P192, "test_%d" % tv.count, new_test) - -class TestEccPoint_PAI_P224(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) - curve = _curves['p224'] - pointG = EccPoint(curve.Gx, curve.Gy, "p224") + setattr(TestEccPoint_PAI_P192, "test_%d" % tv.count, new_test) -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P224.txt", - "P-224 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] +class TestEccPoint_PAI_P224(unittest.TestCase): + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p224"] + pointG = EccPoint(curve.Gx, curve.Gy, "p224") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P224.txt", + "P-224 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P224, "test_%d" % tv.count, new_test) + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) -class TestEccPoint_PAI_P256(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" - - curve = _curves['p256'] - pointG = EccPoint(curve.Gx, curve.Gy, "p256") + setattr(TestEccPoint_PAI_P224, "test_%d" % tv.count, new_test) -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P256.txt", - "P-256 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] +class TestEccPoint_PAI_P256(unittest.TestCase): + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p256"] + pointG = EccPoint(curve.Gx, curve.Gy, "p256") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P256.txt", + "P-256 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P256, "test_%d" % tv.count, new_test) + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) -class TestEccPoint_PAI_P384(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + setattr(TestEccPoint_PAI_P256, "test_%d" % tv.count, new_test) - curve = _curves['p384'] - pointG = EccPoint(curve.Gx, curve.Gy, "p384") - -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P384.txt", - "P-384 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] +class TestEccPoint_PAI_P384(unittest.TestCase): + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p384"] + pointG = EccPoint(curve.Gx, curve.Gy, "p384") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P384.txt", + "P-384 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P384, "test_%d" % tv.count, new_test) + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) -class TestEccPoint_PAI_P521(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" - - curve = _curves['p521'] - pointG = EccPoint(curve.Gx, curve.Gy, "p521") + setattr(TestEccPoint_PAI_P384, "test_%d" % tv.count, new_test) -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P521.txt", - "P-521 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] +class TestEccPoint_PAI_P521(unittest.TestCase): + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p521"] + pointG = EccPoint(curve.Gx, curve.Gy, "p521") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P521.txt", + "P-521 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P521, "test_%d" % tv.count, new_test) - - -class TestEccKey_P192(unittest.TestCase): - - def test_private_key(self): - - key = EccKey(curve="P-192", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, _curves['p192'].Gx) - self.assertEqual(key.pointQ.y, _curves['p192'].Gy) - - point = EccPoint(_curves['p192'].Gx, _curves['p192'].Gy, curve='P-192') - key = EccKey(curve="P-192", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="secp192r1", d=1) - key = EccKey(curve="prime192v1", d=1) - - def test_public_key(self): - - point = EccPoint(_curves['p192'].Gx, _curves['p192'].Gy, curve='P-192') - key = EccKey(curve="P-192", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-192", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-193", d=1)) + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-192", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-192", - d=_curves['p192'].order)) + setattr(TestEccPoint_PAI_P521, "test_%d" % tv.count, new_test) - def test_equality(self): - private_key = ECC.construct(d=3, curve="P-192") - private_key2 = ECC.construct(d=3, curve="P-192") - private_key3 = ECC.construct(d=4, curve="P-192") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p192') - self.assertIn("curve='NIST P-192'", repr(key)) - self.assertEqual(key.curve, 'NIST P-192') - self.assertEqual(key.public_key().curve, 'NIST P-192') +class TestEccKey_P192(unittest.TestCase): + def test_private_key(self): + key = EccKey(curve="P-192", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, _curves["p192"].Gx) + self.assertEqual(key.pointQ.y, _curves["p192"].Gy) + + point = EccPoint(_curves["p192"].Gx, _curves["p192"].Gy, curve="P-192") + key = EccKey(curve="P-192", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="secp192r1", d=1) + key = EccKey(curve="prime192v1", d=1) + + def test_public_key(self): + point = EccPoint(_curves["p192"].Gx, _curves["p192"].Gy, curve="P-192") + key = EccKey(curve="P-192", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="P-192", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-193", d=1)) + + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-192", d=0)) + self.assertRaises( + ValueError, + lambda: EccKey( + curve="P-192", + d=_curves["p192"].order, + ), + ) + + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-192") + private_key2 = ECC.construct(d=3, curve="P-192") + private_key3 = ECC.construct(d=4, curve="P-192") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="p192") + self.assertIn("curve='NIST P-192'", repr(key)) + self.assertEqual(key.curve, "NIST P-192") + self.assertEqual(key.public_key().curve, "NIST P-192") class TestEccKey_P224(unittest.TestCase): - - def test_private_key(self): - - key = EccKey(curve="P-224", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, _curves['p224'].Gx) - self.assertEqual(key.pointQ.y, _curves['p224'].Gy) - - point = EccPoint(_curves['p224'].Gx, _curves['p224'].Gy, curve='P-224') - key = EccKey(curve="P-224", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="secp224r1", d=1) - key = EccKey(curve="prime224v1", d=1) - - def test_public_key(self): - - point = EccPoint(_curves['p224'].Gx, _curves['p224'].Gy, curve='P-224') - key = EccKey(curve="P-224", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-224", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-225", d=1)) - - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-224", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-224", - d=_curves['p224'].order)) - - def test_equality(self): - - private_key = ECC.construct(d=3, curve="P-224") - private_key2 = ECC.construct(d=3, curve="P-224") - private_key3 = ECC.construct(d=4, curve="P-224") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p224') - self.assertIn("curve='NIST P-224'", repr(key)) - self.assertEqual(key.curve, 'NIST P-224') - self.assertEqual(key.public_key().curve, 'NIST P-224') + def test_private_key(self): + key = EccKey(curve="P-224", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, _curves["p224"].Gx) + self.assertEqual(key.pointQ.y, _curves["p224"].Gy) + + point = EccPoint(_curves["p224"].Gx, _curves["p224"].Gy, curve="P-224") + key = EccKey(curve="P-224", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="secp224r1", d=1) + key = EccKey(curve="prime224v1", d=1) + + def test_public_key(self): + point = EccPoint(_curves["p224"].Gx, _curves["p224"].Gy, curve="P-224") + key = EccKey(curve="P-224", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="P-224", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-225", d=1)) + + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-224", d=0)) + self.assertRaises( + ValueError, + lambda: EccKey( + curve="P-224", + d=_curves["p224"].order, + ), + ) + + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-224") + private_key2 = ECC.construct(d=3, curve="P-224") + private_key3 = ECC.construct(d=4, curve="P-224") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="p224") + self.assertIn("curve='NIST P-224'", repr(key)) + self.assertEqual(key.curve, "NIST P-224") + self.assertEqual(key.public_key().curve, "NIST P-224") class TestEccKey_P256(unittest.TestCase): + def test_private_key(self): + key = EccKey(curve="P-256", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, _curves["p256"].Gx) + self.assertEqual(key.pointQ.y, _curves["p256"].Gy) - def test_private_key(self): - - key = EccKey(curve="P-256", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, _curves['p256'].Gx) - self.assertEqual(key.pointQ.y, _curves['p256'].Gy) + point = EccPoint(_curves["p256"].Gx, _curves["p256"].Gy) + key = EccKey(curve="P-256", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) - point = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy) - key = EccKey(curve="P-256", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) + # Other names + key = EccKey(curve="secp256r1", d=1) + key = EccKey(curve="prime256v1", d=1) - # Other names - key = EccKey(curve="secp256r1", d=1) - key = EccKey(curve="prime256v1", d=1) + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="p256", seed=b"H" * 32) - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="p256", seed=b'H'*32) + def test_public_key(self): + point = EccPoint(_curves["p256"].Gx, _curves["p256"].Gy) + key = EccKey(curve="P-256", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) - def test_public_key(self): + def test_public_key_derived(self): + priv_key = EccKey(curve="P-256", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) - point = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy) - key = EccKey(curve="P-256", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-257", d=1)) - def test_public_key_derived(self): + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=0)) + self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=_curves["p256"].order)) - priv_key = EccKey(curve="P-256", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-256") + private_key2 = ECC.construct(d=3, curve="P-256") + private_key3 = ECC.construct(d=4, curve="P-256") - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-257", d=1)) + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=_curves['p256'].order)) + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) - def test_equality(self): + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) - private_key = ECC.construct(d=3, curve="P-256") - private_key2 = ECC.construct(d=3, curve="P-256") - private_key3 = ECC.construct(d=4, curve="P-256") + self.assertNotEqual(public_key, private_key) - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p256') - self.assertIn("curve='NIST P-256'", repr(key)) - self.assertEqual(key.curve, 'NIST P-256') - self.assertEqual(key.public_key().curve, 'NIST P-256') + def test_name_consistency(self): + key = ECC.generate(curve="p256") + self.assertIn("curve='NIST P-256'", repr(key)) + self.assertEqual(key.curve, "NIST P-256") + self.assertEqual(key.public_key().curve, "NIST P-256") class TestEccKey_P384(unittest.TestCase): - - def test_private_key(self): - - p384 = _curves['p384'] - - key = EccKey(curve="P-384", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, p384.Gx) - self.assertEqual(key.pointQ.y, p384.Gy) - - point = EccPoint(p384.Gx, p384.Gy, "p384") - key = EccKey(curve="P-384", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="p384", d=1) - key = EccKey(curve="secp384r1", d=1) - key = EccKey(curve="prime384v1", d=1) - - def test_public_key(self): - - p384 = _curves['p384'] - point = EccPoint(p384.Gx, p384.Gy, 'p384') - key = EccKey(curve="P-384", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-384", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-385", d=1)) - - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-384", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-384", - d=_curves['p384'].order)) - - def test_equality(self): - - private_key = ECC.construct(d=3, curve="P-384") - private_key2 = ECC.construct(d=3, curve="P-384") - private_key3 = ECC.construct(d=4, curve="P-384") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p384') - self.assertIn("curve='NIST P-384'", repr(key)) - self.assertEqual(key.curve, 'NIST P-384') - self.assertEqual(key.public_key().curve, 'NIST P-384') + def test_private_key(self): + p384 = _curves["p384"] + + key = EccKey(curve="P-384", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, p384.Gx) + self.assertEqual(key.pointQ.y, p384.Gy) + + point = EccPoint(p384.Gx, p384.Gy, "p384") + key = EccKey(curve="P-384", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="p384", d=1) + key = EccKey(curve="secp384r1", d=1) + key = EccKey(curve="prime384v1", d=1) + + def test_public_key(self): + p384 = _curves["p384"] + point = EccPoint(p384.Gx, p384.Gy, "p384") + key = EccKey(curve="P-384", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="P-384", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-385", d=1)) + + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-384", d=0)) + self.assertRaises( + ValueError, + lambda: EccKey( + curve="P-384", + d=_curves["p384"].order, + ), + ) + + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-384") + private_key2 = ECC.construct(d=3, curve="P-384") + private_key3 = ECC.construct(d=4, curve="P-384") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="p384") + self.assertIn("curve='NIST P-384'", repr(key)) + self.assertEqual(key.curve, "NIST P-384") + self.assertEqual(key.public_key().curve, "NIST P-384") class TestEccKey_P521(unittest.TestCase): - - def test_private_key(self): - - p521 = _curves['p521'] - - key = EccKey(curve="P-521", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, p521.Gx) - self.assertEqual(key.pointQ.y, p521.Gy) - - point = EccPoint(p521.Gx, p521.Gy, "p521") - key = EccKey(curve="P-521", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="p521", d=1) - key = EccKey(curve="secp521r1", d=1) - key = EccKey(curve="prime521v1", d=1) - - def test_public_key(self): - - p521 = _curves['p521'] - point = EccPoint(p521.Gx, p521.Gy, 'p521') - key = EccKey(curve="P-384", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-521", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-522", d=1)) - - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-521", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-521", - d=_curves['p521'].order)) - - def test_equality(self): - - private_key = ECC.construct(d=3, curve="P-521") - private_key2 = ECC.construct(d=3, curve="P-521") - private_key3 = ECC.construct(d=4, curve="P-521") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p521') - self.assertIn("curve='NIST P-521'", repr(key)) - self.assertEqual(key.curve, 'NIST P-521') - self.assertEqual(key.public_key().curve, 'NIST P-521') + def test_private_key(self): + p521 = _curves["p521"] + + key = EccKey(curve="P-521", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, p521.Gx) + self.assertEqual(key.pointQ.y, p521.Gy) + + point = EccPoint(p521.Gx, p521.Gy, "p521") + key = EccKey(curve="P-521", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="p521", d=1) + key = EccKey(curve="secp521r1", d=1) + key = EccKey(curve="prime521v1", d=1) + + def test_public_key(self): + p521 = _curves["p521"] + point = EccPoint(p521.Gx, p521.Gy, "p521") + key = EccKey(curve="P-384", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="P-521", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-522", d=1)) + + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-521", d=0)) + self.assertRaises( + ValueError, + lambda: EccKey( + curve="P-521", + d=_curves["p521"].order, + ), + ) + + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-521") + private_key2 = ECC.construct(d=3, curve="P-521") + private_key3 = ECC.construct(d=4, curve="P-521") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="p521") + self.assertIn("curve='NIST P-521'", repr(key)) + self.assertEqual(key.curve, "NIST P-521") + self.assertEqual(key.public_key().curve, "NIST P-521") class TestEccModule_P192(unittest.TestCase): - - def test_generate(self): - - key = ECC.generate(curve="P-192") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(_curves['p192'].Gx, - _curves['p192'].Gy, - "P-192") * key.d, - "p192") - - # Other names - ECC.generate(curve="secp192r1") - ECC.generate(curve="prime192v1") - - def test_construct(self): - - key = ECC.construct(curve="P-192", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p192'].G) - - key = ECC.construct(curve="P-192", point_x=_curves['p192'].Gx, - point_y=_curves['p192'].Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, _curves['p192'].G) - - # Other names - ECC.construct(curve="p192", d=1) - ECC.construct(curve="secp192r1", d=1) - ECC.construct(curve="prime192v1", d=1) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p192'].Gx, point_y=_curves['p192'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-192", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-192", d=2, **coordG) + def test_generate(self): + key = ECC.generate(curve="P-192") + self.assertTrue(key.has_private()) + self.assertEqual( + key.pointQ, + EccPoint( + _curves["p192"].Gx, + _curves["p192"].Gy, + "P-192", + ) + * key.d, + "p192", + ) + + # Other names + ECC.generate(curve="secp192r1") + ECC.generate(curve="prime192v1") + + def test_construct(self): + key = ECC.construct(curve="P-192", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p192"].G) + + key = ECC.construct( + curve="P-192", + point_x=_curves["p192"].Gx, + point_y=_curves["p192"].Gy, + ) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, _curves["p192"].G) + + # Other names + ECC.construct(curve="p192", d=1) + ECC.construct(curve="secp192r1", d=1) + ECC.construct(curve="prime192v1", d=1) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p192"].Gx, point_y=_curves["p192"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="P-192", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-192", d=2, **coordG) class TestEccModule_P224(unittest.TestCase): - - def test_generate(self): - - key = ECC.generate(curve="P-224") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(_curves['p224'].Gx, - _curves['p224'].Gy, - "P-224") * key.d, - "p224") - - # Other names - ECC.generate(curve="secp224r1") - ECC.generate(curve="prime224v1") - - def test_construct(self): - - key = ECC.construct(curve="P-224", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p224'].G) - - key = ECC.construct(curve="P-224", point_x=_curves['p224'].Gx, - point_y=_curves['p224'].Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, _curves['p224'].G) - - # Other names - ECC.construct(curve="p224", d=1) - ECC.construct(curve="secp224r1", d=1) - ECC.construct(curve="prime224v1", d=1) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p224'].Gx, point_y=_curves['p224'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-224", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-224", d=2, **coordG) + def test_generate(self): + key = ECC.generate(curve="P-224") + self.assertTrue(key.has_private()) + self.assertEqual( + key.pointQ, + EccPoint( + _curves["p224"].Gx, + _curves["p224"].Gy, + "P-224", + ) + * key.d, + "p224", + ) + + # Other names + ECC.generate(curve="secp224r1") + ECC.generate(curve="prime224v1") + + def test_construct(self): + key = ECC.construct(curve="P-224", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p224"].G) + + key = ECC.construct( + curve="P-224", + point_x=_curves["p224"].Gx, + point_y=_curves["p224"].Gy, + ) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, _curves["p224"].G) + + # Other names + ECC.construct(curve="p224", d=1) + ECC.construct(curve="secp224r1", d=1) + ECC.construct(curve="prime224v1", d=1) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p224"].Gx, point_y=_curves["p224"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="P-224", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-224", d=2, **coordG) class TestEccModule_P256(unittest.TestCase): - - def test_generate(self): - - key = ECC.generate(curve="P-256") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(_curves['p256'].Gx, - _curves['p256'].Gy) * key.d, - "p256") - - # Other names - ECC.generate(curve="secp256r1") - ECC.generate(curve="prime256v1") - - def test_construct(self): - - key = ECC.construct(curve="P-256", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p256'].G) - - key = ECC.construct(curve="P-256", point_x=_curves['p256'].Gx, - point_y=_curves['p256'].Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, _curves['p256'].G) - - # Other names - ECC.construct(curve="p256", d=1) - ECC.construct(curve="secp256r1", d=1) - ECC.construct(curve="prime256v1", d=1) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p256'].Gx, point_y=_curves['p256'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-256", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-256", d=2, **coordG) + def test_generate(self): + key = ECC.generate(curve="P-256") + self.assertTrue(key.has_private()) + self.assertEqual( + key.pointQ, + EccPoint( + _curves["p256"].Gx, + _curves["p256"].Gy, + ) + * key.d, + "p256", + ) + + # Other names + ECC.generate(curve="secp256r1") + ECC.generate(curve="prime256v1") + + def test_construct(self): + key = ECC.construct(curve="P-256", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p256"].G) + + key = ECC.construct( + curve="P-256", + point_x=_curves["p256"].Gx, + point_y=_curves["p256"].Gy, + ) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, _curves["p256"].G) + + # Other names + ECC.construct(curve="p256", d=1) + ECC.construct(curve="secp256r1", d=1) + ECC.construct(curve="prime256v1", d=1) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p256"].Gx, point_y=_curves["p256"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="P-256", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-256", d=2, **coordG) class TestEccModule_P384(unittest.TestCase): + def test_generate(self): + curve = _curves["p384"] + key = ECC.generate(curve="P-384") + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p384") * key.d) - def test_generate(self): - - curve = _curves['p384'] - key = ECC.generate(curve="P-384") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p384") * key.d) - - # Other names - ECC.generate(curve="secp384r1") - ECC.generate(curve="prime384v1") + # Other names + ECC.generate(curve="secp384r1") + ECC.generate(curve="prime384v1") - def test_construct(self): + def test_construct(self): + curve = _curves["p384"] + key = ECC.construct(curve="P-384", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p384"].G) - curve = _curves['p384'] - key = ECC.construct(curve="P-384", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p384'].G) + key = ECC.construct(curve="P-384", point_x=curve.Gx, point_y=curve.Gy) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, curve.G) - key = ECC.construct(curve="P-384", point_x=curve.Gx, point_y=curve.Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, curve.G) + # Other names + ECC.construct(curve="p384", d=1) + ECC.construct(curve="secp384r1", d=1) + ECC.construct(curve="prime384v1", d=1) - # Other names - ECC.construct(curve="p384", d=1) - ECC.construct(curve="secp384r1", d=1) - ECC.construct(curve="prime384v1", d=1) + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p384"].Gx, point_y=_curves["p384"].Gy) - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p384'].Gx, point_y=_curves['p384'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-384", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-384", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="P-384", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-384", d=2, **coordG) class TestEccModule_P521(unittest.TestCase): + def test_generate(self): + curve = _curves["p521"] + key = ECC.generate(curve="P-521") + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p521") * key.d) - def test_generate(self): - - curve = _curves['p521'] - key = ECC.generate(curve="P-521") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p521") * key.d) - - # Other names - ECC.generate(curve="secp521r1") - ECC.generate(curve="prime521v1") - - def test_construct(self): + # Other names + ECC.generate(curve="secp521r1") + ECC.generate(curve="prime521v1") - curve = _curves['p521'] - key = ECC.construct(curve="P-521", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p521'].G) + def test_construct(self): + curve = _curves["p521"] + key = ECC.construct(curve="P-521", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p521"].G) - key = ECC.construct(curve="P-521", point_x=curve.Gx, point_y=curve.Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, curve.G) + key = ECC.construct(curve="P-521", point_x=curve.Gx, point_y=curve.Gy) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, curve.G) - # Other names - ECC.construct(curve="p521", d=1) - ECC.construct(curve="secp521r1", d=1) - ECC.construct(curve="prime521v1", d=1) + # Other names + ECC.construct(curve="p521", d=1) + ECC.construct(curve="secp521r1", d=1) + ECC.construct(curve="prime521v1", d=1) - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p521'].Gx, point_y=_curves['p521'].Gy) + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p521"].Gx, point_y=_curves["p521"].Gy) - self.assertRaises(ValueError, ECC.construct, curve="P-521", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-521", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="P-521", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-521", d=2, **coordG) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint) - tests += list_test_cases(TestEccPoint_NIST_P192) - tests += list_test_cases(TestEccPoint_NIST_P224) - tests += list_test_cases(TestEccPoint_NIST_P256) - tests += list_test_cases(TestEccPoint_NIST_P384) - tests += list_test_cases(TestEccPoint_NIST_P521) - tests += list_test_cases(TestEccPoint_PAI_P192) - tests += list_test_cases(TestEccPoint_PAI_P224) - tests += list_test_cases(TestEccPoint_PAI_P256) - tests += list_test_cases(TestEccPoint_PAI_P384) - tests += list_test_cases(TestEccPoint_PAI_P521) - tests += list_test_cases(TestEccKey_P192) - tests += list_test_cases(TestEccKey_P224) - tests += list_test_cases(TestEccKey_P256) - tests += list_test_cases(TestEccKey_P384) - tests += list_test_cases(TestEccKey_P521) - tests += list_test_cases(TestEccModule_P192) - tests += list_test_cases(TestEccModule_P224) - tests += list_test_cases(TestEccModule_P256) - tests += list_test_cases(TestEccModule_P384) - tests += list_test_cases(TestEccModule_P521) - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(TestEccPoint) + tests += list_test_cases(TestEccPoint_NIST_P192) + tests += list_test_cases(TestEccPoint_NIST_P224) + tests += list_test_cases(TestEccPoint_NIST_P256) + tests += list_test_cases(TestEccPoint_NIST_P384) + tests += list_test_cases(TestEccPoint_NIST_P521) + tests += list_test_cases(TestEccPoint_PAI_P192) + tests += list_test_cases(TestEccPoint_PAI_P224) + tests += list_test_cases(TestEccPoint_PAI_P256) + tests += list_test_cases(TestEccPoint_PAI_P384) + tests += list_test_cases(TestEccPoint_PAI_P521) + tests += list_test_cases(TestEccKey_P192) + tests += list_test_cases(TestEccKey_P224) + tests += list_test_cases(TestEccKey_P256) + tests += list_test_cases(TestEccKey_P384) + tests += list_test_cases(TestEccKey_P521) + tests += list_test_cases(TestEccModule_P192) + tests += list_test_cases(TestEccModule_P224) + tests += list_test_cases(TestEccModule_P256) + tests += list_test_cases(TestEccModule_P384) + tests += list_test_cases(TestEccModule_P521) + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ElGamal.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ElGamal.py index 67d2e0b2..63a0184a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ElGamal.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_ElGamal.py @@ -25,193 +25,191 @@ __revision__ = "$Id$" import unittest -from Cryptodome.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex +from Cryptodome.SelfTest.st_common import list_test_cases, a2b_hex from Cryptodome import Random from Cryptodome.PublicKey import ElGamal from Cryptodome.Util.number import bytes_to_long from Cryptodome.Util.py3compat import * + class ElGamalTest(unittest.TestCase): + # + # Test vectors + # + # There seem to be no real ElGamal test vectors available in the + # public domain. The following test vectors have been generated + # with libgcrypt 1.5.0. + # + # Encryption + tve = [ + { + # 256 bits + "p": "BA4CAEAAED8CBE952AFD2126C63EB3B345D65C2A0A73D2A3AD4138B6D09BD933", + "g": "05", + "y": "60D063600ECED7C7C55146020E7A31C4476E9793BEAED420FEC9E77604CAE4EF", + "x": "1D391BA2EE3C37FE1BA175A69B2C73A11238AD77675932", + "k": "F5893C5BAB4131264066F57AB3D8AD89E391A0B68A68A1", + "pt": "48656C6C6F207468657265", + "ct1": "32BFD5F487966CEA9E9356715788C491EC515E4ED48B58F0F00971E93AAA5EC7", + "ct2": "7BE8FBFF317C93E82FCEF9BD515284BA506603FEA25D01C0CB874A31F315EE68", + }, + { + # 512 bits + "p": "F1B18AE9F7B4E08FDA9A04832F4E919D89462FD31BF12F92791A93519F75076D6CE3942689CDFF2F344CAFF0F82D01864F69F3AECF566C774CBACF728B81A227", + "g": "07", + "y": "688628C676E4F05D630E1BE39D0066178CA7AA83836B645DE5ADD359B4825A12B02EF4252E4E6FA9BEC1DB0BE90F6D7C8629CABB6E531F472B2664868156E20C", + "x": "14E60B1BDFD33436C0DA8A22FDC14A2CCDBBED0627CE68", + "k": "38DBF14E1F319BDA9BAB33EEEADCAF6B2EA5250577ACE7", + "pt": "48656C6C6F207468657265", + "ct1": "290F8530C2CC312EC46178724F196F308AD4C523CEABB001FACB0506BFED676083FE0F27AC688B5C749AB3CB8A80CD6F7094DBA421FB19442F5A413E06A9772B", + "ct2": "1D69AAAD1DC50493FB1B8E8721D621D683F3BF1321BE21BC4A43E11B40C9D4D9C80DE3AAC2AB60D31782B16B61112E68220889D53C4C3136EE6F6CE61F8A23A0", + }, + ] + + # Signature + tvs = [ + { + # 256 bits + "p": "D2F3C41EA66530838A704A48FFAC9334F4701ECE3A97CEE4C69DD01AE7129DD7", + "g": "05", + "y": "C3F9417DC0DAFEA6A05C1D2333B7A95E63B3F4F28CC962254B3256984D1012E7", + "x": "165E4A39BE44D5A2D8B1332D416BC559616F536BC735BB", + "k": "C7F0C794A7EAD726E25A47FF8928013680E73C51DD3D7D99BFDA8F492585928F", + "h": "48656C6C6F207468657265", + "sig1": "35CA98133779E2073EF31165AFCDEB764DD54E96ADE851715495F9C635E1E7C2", + "sig2": "0135B88B1151279FE5D8078D4FC685EE81177EE9802AB123A73925FC1CB059A7", + }, + { + # 512 bits + "p": "E24CF3A4B8A6AF749DCA6D714282FE4AABEEE44A53BB6ED15FBE32B5D3C3EF9CC4124A2ECA331F3C1C1B667ACA3766825217E7B5F9856648D95F05330C6A19CF", + "g": "0B", + "y": "2AD3A1049CA5D4ED207B2431C79A8719BB4073D4A94E450EA6CEE8A760EB07ADB67C0D52C275EE85D7B52789061EE45F2F37D9B2AE522A51C28329766BFE68AC", + "x": "16CBB4F46D9ECCF24FF9F7E63CAA3BD8936341555062AB", + "k": "8A3D89A4E429FD2476D7D717251FB79BF900FFE77444E6BB8299DC3F84D0DD57ABAB50732AE158EA52F5B9E7D8813E81FD9F79470AE22F8F1CF9AEC820A78C69", + "h": "48656C6C6F207468657265", + "sig1": "BE001AABAFFF976EC9016198FBFEA14CBEF96B000CCC0063D3324016F9E91FE80D8F9325812ED24DDB2B4D4CF4430B169880B3CE88313B53255BD4EC0378586F", + "sig2": "5E266F3F837BA204E3BBB6DBECC0611429D96F8C7CE8F4EFDF9D4CB681C2A954468A357BF4242CEC7418B51DFC081BCD21299EF5B5A0DDEF3A139A1817503DDE", + }, + ] + + def test_generate_180(self): + self._test_random_key(180) + + def test_encryption(self): + for tv in self.tve: + d = self.convert_tv(tv, True) + key = ElGamal.construct(d["key"]) + ct = key._encrypt(d["pt"], d["k"]) + self.assertEqual(ct[0], d["ct1"]) + self.assertEqual(ct[1], d["ct2"]) + + def test_decryption(self): + for tv in self.tve: + d = self.convert_tv(tv, True) + key = ElGamal.construct(d["key"]) + pt = key._decrypt((d["ct1"], d["ct2"])) + self.assertEqual(pt, d["pt"]) + + def test_signing(self): + for tv in self.tvs: + d = self.convert_tv(tv, True) + key = ElGamal.construct(d["key"]) + sig1, sig2 = key._sign(d["h"], d["k"]) + self.assertEqual(sig1, d["sig1"]) + self.assertEqual(sig2, d["sig2"]) + + def test_verification(self): + for tv in self.tvs: + d = self.convert_tv(tv, True) + key = ElGamal.construct(d["key"]) + # Positive test + res = key._verify(d["h"], (d["sig1"], d["sig2"])) + self.assertTrue(res) + # Negative test + res = key._verify(d["h"], (d["sig1"] + 1, d["sig2"])) + self.assertFalse(res) + + def test_bad_key3(self): + tup = tup0 = list(self.convert_tv(self.tvs[0], 1)["key"])[:3] + tup[0] += 1 # p += 1 (not prime) + self.assertRaises(ValueError, ElGamal.construct, tup) + + tup = tup0 + tup[1] = 1 # g = 1 + self.assertRaises(ValueError, ElGamal.construct, tup) + + tup = tup0 + tup[2] = tup[0] * 2 # y = 2*p + self.assertRaises(ValueError, ElGamal.construct, tup) + + def test_bad_key4(self): + tup = tup0 = list(self.convert_tv(self.tvs[0], 1)["key"]) + tup[3] += 1 # x += 1 + self.assertRaises(ValueError, ElGamal.construct, tup) + + def convert_tv(self, tv, as_longs=0): + """Convert a test vector from textual form (hexadecimal ascii + to either integers or byte strings.""" + key_comps = "p", "g", "y", "x" + tv2 = {} + for c in tv.keys(): + tv2[c] = a2b_hex(tv[c]) + if as_longs or c in key_comps or c in ("sig1", "sig2"): + tv2[c] = bytes_to_long(tv2[c]) + tv2["key"] = [] + for c in key_comps: + tv2["key"] += [tv2[c]] + del tv2[c] + return tv2 + + def _test_random_key(self, bits): + elgObj = ElGamal.generate(bits, Random.new().read) + self._check_private_key(elgObj) + self._exercise_primitive(elgObj) + pub = elgObj.publickey() + self._check_public_key(pub) + self._exercise_public_primitive(elgObj) + + def _check_private_key(self, elgObj): + # Check capabilities + self.assertTrue(elgObj.has_private()) + + # Sanity check key data + self.assertTrue(1 < elgObj.g < (elgObj.p - 1)) + self.assertEqual(pow(elgObj.g, elgObj.p - 1, elgObj.p), 1) + self.assertTrue(1 < elgObj.x < (elgObj.p - 1)) + self.assertEqual(pow(elgObj.g, elgObj.x, elgObj.p), elgObj.y) + + def _check_public_key(self, elgObj): + # Check capabilities + self.assertFalse(elgObj.has_private()) + + # Sanity check key data + self.assertTrue(1 < elgObj.g < (elgObj.p - 1)) + self.assertEqual(pow(elgObj.g, elgObj.p - 1, elgObj.p), 1) + + def _exercise_primitive(self, elgObj): + # Test encryption/decryption + plaintext = 127218 + ciphertext = elgObj._encrypt(plaintext, 123456789) + plaintextP = elgObj._decrypt(ciphertext) + self.assertEqual(plaintext, plaintextP) + + # Test signature/verification + signature = elgObj._sign(plaintext, 987654321) + elgObj._verify(plaintext, signature) + + def _exercise_public_primitive(self, elgObj): + plaintext = 92987276 + ciphertext = elgObj._encrypt(plaintext, 123456789) - # - # Test vectors - # - # There seem to be no real ElGamal test vectors available in the - # public domain. The following test vectors have been generated - # with libgcrypt 1.5.0. - # - # Encryption - tve=[ - { - # 256 bits - 'p' :'BA4CAEAAED8CBE952AFD2126C63EB3B345D65C2A0A73D2A3AD4138B6D09BD933', - 'g' :'05', - 'y' :'60D063600ECED7C7C55146020E7A31C4476E9793BEAED420FEC9E77604CAE4EF', - 'x' :'1D391BA2EE3C37FE1BA175A69B2C73A11238AD77675932', - 'k' :'F5893C5BAB4131264066F57AB3D8AD89E391A0B68A68A1', - 'pt' :'48656C6C6F207468657265', - 'ct1':'32BFD5F487966CEA9E9356715788C491EC515E4ED48B58F0F00971E93AAA5EC7', - 'ct2':'7BE8FBFF317C93E82FCEF9BD515284BA506603FEA25D01C0CB874A31F315EE68' - }, - - { - # 512 bits - 'p' :'F1B18AE9F7B4E08FDA9A04832F4E919D89462FD31BF12F92791A93519F75076D6CE3942689CDFF2F344CAFF0F82D01864F69F3AECF566C774CBACF728B81A227', - 'g' :'07', - 'y' :'688628C676E4F05D630E1BE39D0066178CA7AA83836B645DE5ADD359B4825A12B02EF4252E4E6FA9BEC1DB0BE90F6D7C8629CABB6E531F472B2664868156E20C', - 'x' :'14E60B1BDFD33436C0DA8A22FDC14A2CCDBBED0627CE68', - 'k' :'38DBF14E1F319BDA9BAB33EEEADCAF6B2EA5250577ACE7', - 'pt' :'48656C6C6F207468657265', - 'ct1':'290F8530C2CC312EC46178724F196F308AD4C523CEABB001FACB0506BFED676083FE0F27AC688B5C749AB3CB8A80CD6F7094DBA421FB19442F5A413E06A9772B', - 'ct2':'1D69AAAD1DC50493FB1B8E8721D621D683F3BF1321BE21BC4A43E11B40C9D4D9C80DE3AAC2AB60D31782B16B61112E68220889D53C4C3136EE6F6CE61F8A23A0' - } - ] - - # Signature - tvs=[ - { - # 256 bits - 'p' :'D2F3C41EA66530838A704A48FFAC9334F4701ECE3A97CEE4C69DD01AE7129DD7', - 'g' :'05', - 'y' :'C3F9417DC0DAFEA6A05C1D2333B7A95E63B3F4F28CC962254B3256984D1012E7', - 'x' :'165E4A39BE44D5A2D8B1332D416BC559616F536BC735BB', - 'k' :'C7F0C794A7EAD726E25A47FF8928013680E73C51DD3D7D99BFDA8F492585928F', - 'h' :'48656C6C6F207468657265', - 'sig1':'35CA98133779E2073EF31165AFCDEB764DD54E96ADE851715495F9C635E1E7C2', - 'sig2':'0135B88B1151279FE5D8078D4FC685EE81177EE9802AB123A73925FC1CB059A7', - }, - { - # 512 bits - 'p' :'E24CF3A4B8A6AF749DCA6D714282FE4AABEEE44A53BB6ED15FBE32B5D3C3EF9CC4124A2ECA331F3C1C1B667ACA3766825217E7B5F9856648D95F05330C6A19CF', - 'g' :'0B', - 'y' :'2AD3A1049CA5D4ED207B2431C79A8719BB4073D4A94E450EA6CEE8A760EB07ADB67C0D52C275EE85D7B52789061EE45F2F37D9B2AE522A51C28329766BFE68AC', - 'x' :'16CBB4F46D9ECCF24FF9F7E63CAA3BD8936341555062AB', - 'k' :'8A3D89A4E429FD2476D7D717251FB79BF900FFE77444E6BB8299DC3F84D0DD57ABAB50732AE158EA52F5B9E7D8813E81FD9F79470AE22F8F1CF9AEC820A78C69', - 'h' :'48656C6C6F207468657265', - 'sig1':'BE001AABAFFF976EC9016198FBFEA14CBEF96B000CCC0063D3324016F9E91FE80D8F9325812ED24DDB2B4D4CF4430B169880B3CE88313B53255BD4EC0378586F', - 'sig2':'5E266F3F837BA204E3BBB6DBECC0611429D96F8C7CE8F4EFDF9D4CB681C2A954468A357BF4242CEC7418B51DFC081BCD21299EF5B5A0DDEF3A139A1817503DDE', - } - ] - - def test_generate_180(self): - self._test_random_key(180) - - def test_encryption(self): - for tv in self.tve: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - ct = key._encrypt(d['pt'], d['k']) - self.assertEqual(ct[0], d['ct1']) - self.assertEqual(ct[1], d['ct2']) - - def test_decryption(self): - for tv in self.tve: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - pt = key._decrypt((d['ct1'], d['ct2'])) - self.assertEqual(pt, d['pt']) - - def test_signing(self): - for tv in self.tvs: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - sig1, sig2 = key._sign(d['h'], d['k']) - self.assertEqual(sig1, d['sig1']) - self.assertEqual(sig2, d['sig2']) - - def test_verification(self): - for tv in self.tvs: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - # Positive test - res = key._verify( d['h'], (d['sig1'],d['sig2']) ) - self.assertTrue(res) - # Negative test - res = key._verify( d['h'], (d['sig1']+1,d['sig2']) ) - self.assertFalse(res) - - def test_bad_key3(self): - tup = tup0 = list(self.convert_tv(self.tvs[0], 1)['key'])[:3] - tup[0] += 1 # p += 1 (not prime) - self.assertRaises(ValueError, ElGamal.construct, tup) - - tup = tup0 - tup[1] = 1 # g = 1 - self.assertRaises(ValueError, ElGamal.construct, tup) - - tup = tup0 - tup[2] = tup[0]*2 # y = 2*p - self.assertRaises(ValueError, ElGamal.construct, tup) - - def test_bad_key4(self): - tup = tup0 = list(self.convert_tv(self.tvs[0], 1)['key']) - tup[3] += 1 # x += 1 - self.assertRaises(ValueError, ElGamal.construct, tup) - - def convert_tv(self, tv, as_longs=0): - """Convert a test vector from textual form (hexadecimal ascii - to either integers or byte strings.""" - key_comps = 'p','g','y','x' - tv2 = {} - for c in tv.keys(): - tv2[c] = a2b_hex(tv[c]) - if as_longs or c in key_comps or c in ('sig1','sig2'): - tv2[c] = bytes_to_long(tv2[c]) - tv2['key']=[] - for c in key_comps: - tv2['key'] += [tv2[c]] - del tv2[c] - return tv2 - - def _test_random_key(self, bits): - elgObj = ElGamal.generate(bits, Random.new().read) - self._check_private_key(elgObj) - self._exercise_primitive(elgObj) - pub = elgObj.publickey() - self._check_public_key(pub) - self._exercise_public_primitive(elgObj) - - def _check_private_key(self, elgObj): - - # Check capabilities - self.assertTrue(elgObj.has_private()) - - # Sanity check key data - self.assertTrue(1 1) # p > 1 - self.assertEqual(1, rsaObj.q > 1) # q > 1 - self.assertEqual(1, rsaObj.e > 1) # e > 1 - self.assertEqual(1, rsaObj.d > 1) # d > 1 - - self.assertEqual(rsaObj.u, rsaObj.invp) - self.assertEqual(1, rsaObj.q * rsaObj.invq % rsaObj.p) - - def _check_public_key(self, rsaObj): - ciphertext = a2b_hex(self.ciphertext) + def setUp(self): + global RSA, Random, bytes_to_long + from Cryptodome.PublicKey import RSA + from Cryptodome import Random + from Cryptodome.Util.number import bytes_to_long, inverse + + self.n = bytes_to_long(a2b_hex(self.modulus)) + self.p = bytes_to_long(a2b_hex(self.prime_factor)) + + # Compute q, d, and u from n, e, and p + self.q = self.n // self.p + self.d = inverse(self.e, (self.p - 1) * (self.q - 1)) + self.u = inverse(self.p, self.q) # u = e**-1 (mod q) + + self.rsa = RSA + + def test_generate_1arg(self): + """RSA (default implementation) generated key (1 argument)""" + rsaObj = self.rsa.generate(1024) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.public_key() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + + def test_generate_2arg(self): + """RSA (default implementation) generated key (2 arguments)""" + rsaObj = self.rsa.generate(1024, Random.new().read) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.public_key() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + + def test_generate_3args(self): + rsaObj = self.rsa.generate(1024, Random.new().read, e=65537) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.public_key() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + self.assertEqual(65537, rsaObj.e) + + def test_construct_2tuple(self): + """RSA (default implementation) constructed key (2-tuple)""" + pub = self.rsa.construct((self.n, self.e)) + self._check_public_key(pub) + self._check_encryption(pub) + + def test_construct_3tuple(self): + """RSA (default implementation) constructed key (3-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d)) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + + def test_construct_4tuple(self): + """RSA (default implementation) constructed key (4-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p)) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + + def test_construct_5tuple(self): + """RSA (default implementation) constructed key (5-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q)) + self._check_private_key(rsaObj) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + + def test_construct_6tuple(self): + """RSA (default implementation) constructed key (6-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q, self.u)) + self._check_private_key(rsaObj) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + + def test_construct_bad_key2(self): + tup = (self.n, 1) + self.assertRaises(ValueError, self.rsa.construct, tup) + + # An even modulus is wrong + tup = (self.n + 1, self.e) + self.assertRaises(ValueError, self.rsa.construct, tup) + + def test_construct_bad_key3(self): + tup = (self.n, self.e, self.d + 1) + self.assertRaises(ValueError, self.rsa.construct, tup) + + def test_construct_bad_key5(self): + tup = (self.n, self.e, self.d, self.p, self.p) + self.assertRaises(ValueError, self.rsa.construct, tup) + + tup = (self.p * self.p, self.e, self.p, self.p) + self.assertRaises(ValueError, self.rsa.construct, tup) + + tup = (self.p * self.p, 3, self.p, self.q) + self.assertRaises(ValueError, self.rsa.construct, tup) + + def test_construct_bad_key6(self): + tup = (self.n, self.e, self.d, self.p, self.q, 10) + self.assertRaises(ValueError, self.rsa.construct, tup) + + from Cryptodome.Util.number import inverse + + tup = (self.n, self.e, self.d, self.p, self.q, inverse(self.q, self.p)) + self.assertRaises(ValueError, self.rsa.construct, tup) + + def test_factoring(self): + rsaObj = self.rsa.construct([self.n, self.e, self.d]) + self.assertTrue(rsaObj.p == self.p or rsaObj.p == self.q) + self.assertTrue(rsaObj.q == self.p or rsaObj.q == self.q) + self.assertTrue(rsaObj.q * rsaObj.p == self.n) + + self.assertRaises(ValueError, self.rsa.construct, [self.n, self.e, self.n - 1]) + + def test_repr(self): + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q)) + repr(rsaObj) + + def test_serialization(self): + """RSA keys are unpickable""" + + rsa_key = self.rsa.generate(1024) + self.assertRaises(PicklingError, pickle.dumps, rsa_key) + + def test_raw_rsa_boundary(self): + # The argument of every RSA raw operation (encrypt/decrypt) must be + # non-negative and no larger than the modulus + rsa_obj = self.rsa.generate(1024) + + self.assertRaises(ValueError, rsa_obj._decrypt, rsa_obj.n) + self.assertRaises(ValueError, rsa_obj._decrypt_to_bytes, rsa_obj.n) + self.assertRaises(ValueError, rsa_obj._encrypt, rsa_obj.n) + + self.assertRaises(ValueError, rsa_obj._decrypt, -1) + self.assertRaises(ValueError, rsa_obj._decrypt_to_bytes, -1) + self.assertRaises(ValueError, rsa_obj._encrypt, -1) + + def test_size(self): + pub = self.rsa.construct((self.n, self.e)) + self.assertEqual(pub.size_in_bits(), 1024) + self.assertEqual(pub.size_in_bytes(), 128) + + def _check_private_key(self, rsaObj): + from Cryptodome.Math.Numbers import Integer + + # Check capabilities + self.assertEqual(1, rsaObj.has_private()) + + # Sanity check key data + self.assertEqual(rsaObj.n, rsaObj.p * rsaObj.q) # n = pq + lcm = int(Integer(rsaObj.p - 1).lcm(rsaObj.q - 1)) + self.assertEqual(1, rsaObj.d * rsaObj.e % lcm) # ed = 1 (mod LCM(p-1, q-1)) + self.assertEqual(1, rsaObj.p * rsaObj.u % rsaObj.q) # pu = 1 (mod q) + self.assertEqual(1, rsaObj.p > 1) # p > 1 + self.assertEqual(1, rsaObj.q > 1) # q > 1 + self.assertEqual(1, rsaObj.e > 1) # e > 1 + self.assertEqual(1, rsaObj.d > 1) # d > 1 + + self.assertEqual(rsaObj.u, rsaObj.invp) + self.assertEqual(1, rsaObj.q * rsaObj.invq % rsaObj.p) - # Check capabilities - self.assertEqual(0, rsaObj.has_private()) + def _check_public_key(self, rsaObj): + ciphertext = a2b_hex(self.ciphertext) - # Check rsaObj.[ne] -> rsaObj.[ne] mapping - self.assertEqual(rsaObj.n, rsaObj.n) - self.assertEqual(rsaObj.e, rsaObj.e) + # Check capabilities + self.assertEqual(0, rsaObj.has_private()) - # Check that private parameters are all missing - self.assertEqual(0, hasattr(rsaObj, 'd')) - self.assertEqual(0, hasattr(rsaObj, 'p')) - self.assertEqual(0, hasattr(rsaObj, 'q')) - self.assertEqual(0, hasattr(rsaObj, 'u')) + # Check rsaObj.[ne] -> rsaObj.[ne] mapping + self.assertEqual(rsaObj.n, rsaObj.n) + self.assertEqual(rsaObj.e, rsaObj.e) - # Sanity check key data - self.assertEqual(1, rsaObj.e > 1) # e > 1 + # Check that private parameters are all missing + self.assertEqual(0, hasattr(rsaObj, "d")) + self.assertEqual(0, hasattr(rsaObj, "p")) + self.assertEqual(0, hasattr(rsaObj, "q")) + self.assertEqual(0, hasattr(rsaObj, "u")) - # Public keys should not be able to sign or decrypt - self.assertRaises(TypeError, rsaObj._decrypt, - bytes_to_long(ciphertext)) - self.assertRaises(TypeError, rsaObj._decrypt_to_bytes, - bytes_to_long(ciphertext)) + # Sanity check key data + self.assertEqual(1, rsaObj.e > 1) # e > 1 - # Check __eq__ and __ne__ - self.assertEqual(rsaObj.public_key() == rsaObj.public_key(),True) # assert_ - self.assertEqual(rsaObj.public_key() != rsaObj.public_key(),False) # assertFalse + # Public keys should not be able to sign or decrypt + self.assertRaises( + TypeError, + rsaObj._decrypt, + bytes_to_long(ciphertext), + ) + self.assertRaises( + TypeError, + rsaObj._decrypt_to_bytes, + bytes_to_long(ciphertext), + ) - self.assertEqual(rsaObj.publickey(), rsaObj.public_key()) + # Check __eq__ and __ne__ + self.assertEqual(rsaObj.public_key() == rsaObj.public_key(), True) # assert_ + self.assertEqual(rsaObj.public_key() != rsaObj.public_key(), False) # assertFalse - def _exercise_primitive(self, rsaObj): - # Since we're using a randomly-generated key, we can't check the test - # vector, but we can make sure encryption and decryption are inverse - # operations. - ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) + self.assertEqual(rsaObj.publickey(), rsaObj.public_key()) - # Test decryption - plaintext = rsaObj._decrypt(ciphertext) + def _exercise_primitive(self, rsaObj): + # Since we're using a randomly-generated key, we can't check the test + # vector, but we can make sure encryption and decryption are inverse + # operations. + ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) - # Test encryption (2 arguments) - new_ciphertext2 = rsaObj._encrypt(plaintext) - self.assertEqual(ciphertext, new_ciphertext2) + # Test decryption + plaintext = rsaObj._decrypt(ciphertext) + + # Test encryption (2 arguments) + new_ciphertext2 = rsaObj._encrypt(plaintext) + self.assertEqual(ciphertext, new_ciphertext2) - def _exercise_public_primitive(self, rsaObj): - plaintext = a2b_hex(self.plaintext) + def _exercise_public_primitive(self, rsaObj): + plaintext = a2b_hex(self.plaintext) - # Test encryption (2 arguments) - new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) + # Test encryption (2 arguments) + new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) - def _check_encryption(self, rsaObj): - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) + def _check_encryption(self, rsaObj): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) - # Test encryption - new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) - self.assertEqual(bytes_to_long(ciphertext), new_ciphertext2) + # Test encryption + new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) + self.assertEqual(bytes_to_long(ciphertext), new_ciphertext2) + + def _check_decryption(self, rsaObj): + plaintext = bytes_to_long(a2b_hex(self.plaintext)) + ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) - def _check_decryption(self, rsaObj): - plaintext = bytes_to_long(a2b_hex(self.plaintext)) - ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) - - # Test plain decryption - new_plaintext = rsaObj._decrypt(ciphertext) - self.assertEqual(plaintext, new_plaintext) + # Test plain decryption + new_plaintext = rsaObj._decrypt(ciphertext) + self.assertEqual(plaintext, new_plaintext) def get_tests(config={}): - tests = [] - tests += list_test_cases(RSATest) - return tests + tests = [] + tests += list_test_cases(RSATest) + return tests + -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_Curve25519.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_Curve25519.py index 2401eace..600650c5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_Curve25519.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_Curve25519.py @@ -43,343 +43,381 @@ from Cryptodome.PublicKey import ECC try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False def load_file(file_name, mode="rb"): - results = None + results = None - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) - dir_comps = ("PublicKey", "ECC") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() + dir_comps = ("PublicKey", "ECC") + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name, mode) as file_in: + results = file_in.read() - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for ECC", - UserWarning, - stacklevel=2) + except FileNotFoundError: + warnings.warn( + "Warning: skipping extended tests for ECC", + UserWarning, + stacklevel=2, + ) - if results is None: - raise SkipTest("Missing %s" % file_name) + if results is None: + raise SkipTest("Missing %s" % file_name) - return results + return results def compact(lines): - ext = b"".join(lines) - return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) + ext = b"".join(lines) + return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) def create_ref_keys_x25519(): - key_lines = load_file("ecc_x25519.txt").splitlines() - seed = compact(key_lines[5:8]) - key = ECC.construct(curve="Curve25519", seed=seed) - return (key, key.public_key()) + key_lines = load_file("ecc_x25519.txt").splitlines() + seed = compact(key_lines[5:8]) + key = ECC.construct(curve="Curve25519", seed=seed) + return (key, key.public_key()) def get_fixed_prng(): - return SHAKE128.new().update(b"SEED").read + return SHAKE128.new().update(b"SEED").read def extract_bitstring_from_spki(data): - seq = DerSequence() - seq.decode(data) - bs = DerBitString() - bs.decode(seq[1]) - return bs.value + seq = DerSequence() + seq.decode(data) + bs = DerBitString() + bs.decode(seq[1]) + return bs.value class TestImport(unittest.TestCase): + def test_empty(self): + self.assertRaises(ValueError, ECC.import_key, b"") - def test_empty(self): - self.assertRaises(ValueError, ECC.import_key, b"") - - def test_mismatch(self): - # Private key with X448 Object ID but X25519 key - mismatch_hex = "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79" - mismatch = unhexlify(mismatch_hex) - self.assertRaises(ValueError, ECC.import_key, mismatch) + def test_mismatch(self): + # Private key with X448 Object ID but X25519 key + mismatch_hex = ( + "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79" + ) + mismatch = unhexlify(mismatch_hex) + self.assertRaises(ValueError, ECC.import_key, mismatch) class TestImport_Curve25519(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_Curve25519, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_x25519() - def __init__(self, *args, **kwargs): - super(TestImport_Curve25519, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_x25519() - - def test_import_public_der(self): - key_file = load_file("ecc_x25519_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_x25519_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_pkcs8_der(self): - key_file = load_file("ecc_x25519_private.der") + def test_import_pkcs8_der(self): + key_file = load_file("ecc_x25519_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_x25519_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_x25519_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_x25519_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_x25519_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_x25519_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_x25519_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_x25519_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_x25519_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_x25519_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_x25519_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_x25519_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_x25519_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256": - key_file = load_file("ecc_x25519_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256": + key_file = load_file("ecc_x25519_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_x25519_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_x25519_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) class TestExport_Curve25519(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestExport_Curve25519, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_x25519() - - def test_export_public_der(self): - key_file = load_file("ecc_x25519_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(True) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_x25519_private.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - self.assertRaises(ValueError, self.ref_private.export_key, - format="DER", use_pkcs8=False) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", - prot_params={'iteration_count': 123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_public_pem(self): - key_file_ref = load_file("ecc_x25519_public.pem", "rt").strip() - key_file = self.ref_public.export_key(format="PEM").strip() - self.assertEqual(key_file_ref, key_file) - - def test_export_private_pem_clear(self): - key_file = load_file("ecc_x25519_private.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM").strip() - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_raw(self): - encoded = self.ref_public.export_key(format='raw') - self.assertEqual(len(encoded), 32) - self.assertEqual(encoded, unhexlify(b'ff7561ef60c9c8a757f6d6372ec14142c9be208d0e719136d8d3c715dfcf7e15')) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="secret") - - # Empty password - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="", - use_pkcs8=False) - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, - self.ref_private.export_key, - format="OpenSSH", - passphrase="secret") + def __init__(self, *args, **kwargs): + super(TestExport_Curve25519, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_x25519() + + def test_export_public_der(self): + key_file = load_file("ecc_x25519_public.der") + + encoded = self.ref_public._export_subjectPublicKeyInfo(True) + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_x25519_private.der") + + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) + + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + use_pkcs8=False, + ) + + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_public_pem(self): + key_file_ref = load_file("ecc_x25519_public.pem", "rt").strip() + key_file = self.ref_public.export_key(format="PEM").strip() + self.assertEqual(key_file_ref, key_file) + + def test_export_private_pem_clear(self): + key_file = load_file("ecc_x25519_private.pem", "rt").strip() + encoded = self.ref_private.export_key(format="PEM").strip() + self.assertEqual(key_file, encoded) + + def test_export_private_pem_encrypted(self): + encoded = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_raw(self): + encoded = self.ref_public.export_key(format="raw") + self.assertEqual(len(encoded), 32) + self.assertEqual( + encoded, unhexlify(b"ff7561ef60c9c8a757f6d6372ec14142c9be208d0e719136d8d3c715dfcf7e15") + ) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) class TestImport_Curve25519_Weak(unittest.TestCase): + def test_weak_pem(self): + p = 2**255 - 19 + weak_x = ( + 0, + 1, + 325606250916557431795983626356110631294008115727848805560023387167927233504, + 39382357235489614581723060781553021112529911719440698176882885853963445705823, + p - 1, + p, + p + 1, + p + 325606250916557431795983626356110631294008115727848805560023387167927233504, + p + 39382357235489614581723060781553021112529911719440698176882885853963445705823, + p * 2 - 1, + p * 2, + p * 2 + 1, + ) + + for x in weak_x: + low_order_point = ECC.EccXPoint(x, "curve25519") + weak_key = ECC.EccKey(point=low_order_point, curve="curve25519") + encoded = weak_key.export_key(format="PEM") + + self.assertRaises( + ValueError, + ECC.import_key, + encoded, + ) - def test_weak_pem(self): - p = 2**255 - 19 - weak_x = (0, - 1, - 325606250916557431795983626356110631294008115727848805560023387167927233504, - 39382357235489614581723060781553021112529911719440698176882885853963445705823, - p - 1, - p, - p + 1, - p + 325606250916557431795983626356110631294008115727848805560023387167927233504, - p + 39382357235489614581723060781553021112529911719440698176882885853963445705823, - p * 2 - 1, - p * 2, - p * 2 + 1) +def get_tests(config={}): + tests = [] + try: + tests += list_test_cases(TestImport) + tests += list_test_cases(TestImport_Curve25519) + tests += list_test_cases(TestExport_Curve25519) + tests += list_test_cases(TestImport_Curve25519_Weak) + except SkipTest: + pass + return tests - for x in weak_x: - low_order_point = ECC.EccXPoint(x, "curve25519") - weak_key = ECC.EccKey(point=low_order_point, curve="curve25519") - encoded = weak_key.export_key(format="PEM") - self.assertRaises(ValueError, - ECC.import_key, - encoded) +if __name__ == "__main__": + def suit(): + return unittest.TestSuite(get_tests()) -def get_tests(config={}): - tests = [] - try: - tests += list_test_cases(TestImport) - tests += list_test_cases(TestImport_Curve25519) - tests += list_test_cases(TestExport_Curve25519) - tests += list_test_cases(TestImport_Curve25519_Weak) - except SkipTest: - pass - return tests - - -if __name__ == '__main__': - def suit(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_Curve448.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_Curve448.py index e1b343b4..9147b4e7 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_Curve448.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_Curve448.py @@ -16,336 +16,377 @@ from Cryptodome.PublicKey import ECC try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False def load_file(file_name, mode="rb"): - results = None + results = None - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) - dir_comps = ("PublicKey", "ECC") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() + dir_comps = ("PublicKey", "ECC") + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name, mode) as file_in: + results = file_in.read() - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for ECC", - UserWarning, - stacklevel=2) + except FileNotFoundError: + warnings.warn( + "Warning: skipping extended tests for ECC", + UserWarning, + stacklevel=2, + ) - if results is None: - raise SkipTest("Missing %s" % file_name) + if results is None: + raise SkipTest("Missing %s" % file_name) - return results + return results def compact(lines): - ext = b"".join(lines) - return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) + ext = b"".join(lines) + return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) def create_ref_keys_x448(): - key_lines = load_file("ecc_x448.txt").splitlines() - seed = compact(key_lines[6:10]) - key = ECC.construct(curve="Curve448", seed=seed) - return (key, key.public_key()) + key_lines = load_file("ecc_x448.txt").splitlines() + seed = compact(key_lines[6:10]) + key = ECC.construct(curve="Curve448", seed=seed) + return (key, key.public_key()) def get_fixed_prng(): - return SHAKE128.new().update(b"SEED").read + return SHAKE128.new().update(b"SEED").read def extract_bitstring_from_spki(data): - seq = DerSequence() - seq.decode(data) - bs = DerBitString() - bs.decode(seq[1]) - return bs.value + seq = DerSequence() + seq.decode(data) + bs = DerBitString() + bs.decode(seq[1]) + return bs.value class TestImport(unittest.TestCase): + def test_empty(self): + self.assertRaises(ValueError, ECC.import_key, b"") - def test_empty(self): - self.assertRaises(ValueError, ECC.import_key, b"") - - def test_mismatch(self): - # Private key with X448 Object ID but X448 key - mismatch_hex = "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79" - mismatch = unhexlify(mismatch_hex) - self.assertRaises(ValueError, ECC.import_key, mismatch) + def test_mismatch(self): + # Private key with X448 Object ID but X448 key + mismatch_hex = ( + "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79" + ) + mismatch = unhexlify(mismatch_hex) + self.assertRaises(ValueError, ECC.import_key, mismatch) class TestImport_Curve448(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_Curve448, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_x448() - def __init__(self, *args, **kwargs): - super(TestImport_Curve448, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_x448() - - def test_import_public_der(self): - key_file = load_file("ecc_x448_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_x448_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_pkcs8_der(self): - key_file = load_file("ecc_x448_private.der") + def test_import_pkcs8_der(self): + key_file = load_file("ecc_x448_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_x448_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_x448_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_x448_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_x448_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_x448_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_x448_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_x448_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_x448_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_x448_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_x448_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_x448_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_x448_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256": - key_file = load_file("ecc_x448_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256": + key_file = load_file("ecc_x448_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_x448_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_x448_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) class TestExport_Curve448(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestExport_Curve448, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_x448() - - def test_export_public_der(self): - key_file = load_file("ecc_x448_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(True) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_x448_private.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - self.assertRaises(ValueError, self.ref_private.export_key, - format="DER", use_pkcs8=False) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", - prot_params={'iteration_count': 123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_public_pem(self): - key_file_ref = load_file("ecc_x448_public.pem", "rt").strip() - key_file = self.ref_public.export_key(format="PEM").strip() - self.assertEqual(key_file_ref, key_file) - - def test_export_private_pem_clear(self): - key_file = load_file("ecc_x448_private.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM").strip() - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_raw(self): - encoded = self.ref_public.export_key(format='raw') - self.assertEqual(len(encoded), 56) - self.assertEqual(encoded, unhexlify(b'e2abae24ab8f65b01969e61f84fee615b525f413a90e3d727f71d0ffe60fb1d0a1a0285f2a7fd88789206e0aa4f3e9fcb9e4ba5d644e691e')) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="secret") - - # Empty password - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="", - use_pkcs8=False) - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, - self.ref_private.export_key, - format="OpenSSH", - passphrase="secret") + def __init__(self, *args, **kwargs): + super(TestExport_Curve448, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_x448() + + def test_export_public_der(self): + key_file = load_file("ecc_x448_public.der") + + encoded = self.ref_public._export_subjectPublicKeyInfo(True) + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_x448_private.der") + + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) + + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + use_pkcs8=False, + ) + + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_public_pem(self): + key_file_ref = load_file("ecc_x448_public.pem", "rt").strip() + key_file = self.ref_public.export_key(format="PEM").strip() + self.assertEqual(key_file_ref, key_file) + + def test_export_private_pem_clear(self): + key_file = load_file("ecc_x448_private.pem", "rt").strip() + encoded = self.ref_private.export_key(format="PEM").strip() + self.assertEqual(key_file, encoded) + + def test_export_private_pem_encrypted(self): + encoded = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_raw(self): + encoded = self.ref_public.export_key(format="raw") + self.assertEqual(len(encoded), 56) + self.assertEqual( + encoded, + unhexlify( + b"e2abae24ab8f65b01969e61f84fee615b525f413a90e3d727f71d0ffe60fb1d0a1a0285f2a7fd88789206e0aa4f3e9fcb9e4ba5d644e691e" + ), + ) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) class TestImport_Curve448_Weak(unittest.TestCase): + def test_weak_pem(self): + p = 2**448 - 2**224 - 1 + weak_x = ( + 0, + 1, + p - 1, + p, + p + 1, + ) + + for x in weak_x: + low_order_point = ECC.EccXPoint(x, "curve448") + weak_key = ECC.EccKey(point=low_order_point, curve="curve448") + encoded = weak_key.export_key(format="PEM") + + self.assertRaises( + ValueError, + ECC.import_key, + encoded, + ) - def test_weak_pem(self): - p = 2**448 - 2**224 - 1 - weak_x = (0, - 1, - p - 1, - p, - p + 1) +def get_tests(config={}): + tests = [] + try: + tests += list_test_cases(TestImport) + tests += list_test_cases(TestImport_Curve448) + tests += list_test_cases(TestExport_Curve448) + tests += list_test_cases(TestImport_Curve448_Weak) + except SkipTest: + pass + return tests - for x in weak_x: - low_order_point = ECC.EccXPoint(x, "curve448") - weak_key = ECC.EccKey(point=low_order_point, curve="curve448") - encoded = weak_key.export_key(format="PEM") - self.assertRaises(ValueError, - ECC.import_key, - encoded) +if __name__ == "__main__": + def suit(): + return unittest.TestSuite(get_tests()) -def get_tests(config={}): - tests = [] - try: - tests += list_test_cases(TestImport) - tests += list_test_cases(TestImport_Curve448) - tests += list_test_cases(TestExport_Curve448) - tests += list_test_cases(TestImport_Curve448_Weak) - except SkipTest: - pass - return tests - - -if __name__ == '__main__': - def suit(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_DSA.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_DSA.py index 5ff01135..a3397267 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_DSA.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_DSA.py @@ -29,58 +29,58 @@ from binascii import unhexlify -class ImportKeyTests(unittest.TestCase): - y = 92137165128186062214622779787483327510946462589285775188003362705875131352591574106484271700740858696583623951844732128165434284507709057439633739849986759064015013893156866539696757799934634945787496920169462601722830899660681779448742875054459716726855443681559131362852474817534616736104831095601710736729 - p = 162452170958135306109773853318304545923250830605675936228618290525164105310663722368377131295055868997377338797580997938253236213714988311430600065853662861806894003694743806769284131194035848116051021923956699231855223389086646903420682639786976554552864568460372266462812137447840653688476258666833303658691 - q = 988791743931120302950649732173330531512663554851 - g = 85583152299197514738065570254868711517748965097380456700369348466136657764813442044039878840094809620913085570225318356734366886985903212775602770761953571967834823306046501307810937486758039063386311593890777319935391363872375452381836756832784184928202587843258855704771836753434368484556809100537243908232 - x = 540873410045082450874416847965843801027716145253 - - def setUp(self): - - # It is easier to write test vectors in text form, - # and convert them to byte strigs dynamically here - for mname, mvalue in ImportKeyTests.__dict__.items(): - if mname[:4] in ('der_', 'pem_', 'ssh_'): - if mname[:4] == 'der_': - mvalue = unhexlify(tobytes(mvalue)) - mvalue = tobytes(mvalue) - setattr(self, mname, mvalue) - - # 1. SubjectPublicKeyInfo - der_public=\ - '308201b73082012b06072a8648ce3804013082011e02818100e756ee1717f4b6'+\ - '794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a2757695ec91'+\ - '5697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8b81b47'+\ - '9a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656cecb4c'+\ - '8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad32f48c'+\ - 'd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb7eaeae'+\ - '3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466cf444f3'+\ - '4b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b92370040a'+\ - 'ca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074b41c56'+\ - 'ae43fd300d89262e4efd89943f99a651b03888038185000281810083352a69a1'+\ - '32f34843d2a0eb995bff4e2f083a73f0049d2c91ea2f0ce43d144abda48199e4'+\ - 'b003c570a8af83303d45105f606c5c48d925a40ed9c2630c2fa4cdbf838539de'+\ - 'b9a29f919085f2046369f627ca84b2cb1e2c7940564b670f963ab1164d4e2ca2'+\ - 'bf6ffd39f12f548928bf4d2d1b5e6980b4f1be4c92a91986fba559' - - def testImportKey1(self): - key_obj = DSA.importKey(self.der_public) - self.assertFalse(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def testExportKey1(self): - tup = (self.y, self.g, self.p, self.q) - key = DSA.construct(tup) - encoded = key.export_key('DER') - self.assertEqual(self.der_public, encoded) - - # 2. - pem_public="""\ +class ImportKeyTests(unittest.TestCase): + y = 92137165128186062214622779787483327510946462589285775188003362705875131352591574106484271700740858696583623951844732128165434284507709057439633739849986759064015013893156866539696757799934634945787496920169462601722830899660681779448742875054459716726855443681559131362852474817534616736104831095601710736729 + p = 162452170958135306109773853318304545923250830605675936228618290525164105310663722368377131295055868997377338797580997938253236213714988311430600065853662861806894003694743806769284131194035848116051021923956699231855223389086646903420682639786976554552864568460372266462812137447840653688476258666833303658691 + q = 988791743931120302950649732173330531512663554851 + g = 85583152299197514738065570254868711517748965097380456700369348466136657764813442044039878840094809620913085570225318356734366886985903212775602770761953571967834823306046501307810937486758039063386311593890777319935391363872375452381836756832784184928202587843258855704771836753434368484556809100537243908232 + x = 540873410045082450874416847965843801027716145253 + + def setUp(self): + # It is easier to write test vectors in text form, + # and convert them to byte strigs dynamically here + for mname, mvalue in ImportKeyTests.__dict__.items(): + if mname[:4] in ("der_", "pem_", "ssh_"): + if mname[:4] == "der_": + mvalue = unhexlify(tobytes(mvalue)) + mvalue = tobytes(mvalue) + setattr(self, mname, mvalue) + + # 1. SubjectPublicKeyInfo + der_public = ( + "308201b73082012b06072a8648ce3804013082011e02818100e756ee1717f4b6" + + "794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a2757695ec91" + + "5697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8b81b47" + + "9a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656cecb4c" + + "8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad32f48c" + + "d3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb7eaeae" + + "3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466cf444f3" + + "4b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b92370040a" + + "ca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074b41c56" + + "ae43fd300d89262e4efd89943f99a651b03888038185000281810083352a69a1" + + "32f34843d2a0eb995bff4e2f083a73f0049d2c91ea2f0ce43d144abda48199e4" + + "b003c570a8af83303d45105f606c5c48d925a40ed9c2630c2fa4cdbf838539de" + + "b9a29f919085f2046369f627ca84b2cb1e2c7940564b670f963ab1164d4e2ca2" + + "bf6ffd39f12f548928bf4d2d1b5e6980b4f1be4c92a91986fba559" + ) + + def testImportKey1(self): + key_obj = DSA.importKey(self.der_public) + self.assertFalse(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + + def testExportKey1(self): + tup = (self.y, self.g, self.p, self.q) + key = DSA.construct(tup) + encoded = key.export_key("DER") + self.assertEqual(self.der_public, encoded) + + # 2. + pem_public = """\ -----BEGIN PUBLIC KEY----- MIIBtzCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/ j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtH @@ -94,55 +94,56 @@ def testExportKey1(self): tPG+TJKpGYb7pVk= -----END PUBLIC KEY-----""" - def testImportKey2(self): - for pem in (self.pem_public, tostr(self.pem_public)): - key_obj = DSA.importKey(pem) - self.assertFalse(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def testExportKey2(self): - tup = (self.y, self.g, self.p, self.q) - key = DSA.construct(tup) - encoded = key.export_key('PEM') - self.assertEqual(self.pem_public, encoded) - - # 3. OpenSSL/OpenSSH format - der_private=\ - '308201bb02010002818100e756ee1717f4b6794c7c214724a19763742c45572b'+\ - '4b3f8ff3b44f3be9f44ce039a2757695ec915697da74ef914fcd1b05660e2419'+\ - 'c761d639f45d2d79b802dbd23e7ab8b81b479a380e1f30932584ba2a0b955032'+\ - '342ebc83cb5ca906e7b0d7cd6fe656cecb4c8b5a77123a8c6750a481e3b06057'+\ - 'aff6aa6eba620b832d60c3021500ad32f48cd3ae0c45a198a61fa4b5e2032076'+\ - '3b2302818079dfdc3d614fe635fceb7eaeae3718dc2efefb45282993ac6749dc'+\ - '83c223d8c1887296316b3b0b54466cf444f34b82e3554d0b90a778faaf1306f0'+\ - '25dae6a3e36c7f93dd5bac4052b92370040aca70b8d5820599711900efbc9618'+\ - '12c355dd9beffe0981da85c5548074b41c56ae43fd300d89262e4efd89943f99'+\ - 'a651b038880281810083352a69a132f34843d2a0eb995bff4e2f083a73f0049d'+\ - '2c91ea2f0ce43d144abda48199e4b003c570a8af83303d45105f606c5c48d925'+\ - 'a40ed9c2630c2fa4cdbf838539deb9a29f919085f2046369f627ca84b2cb1e2c'+\ - '7940564b670f963ab1164d4e2ca2bf6ffd39f12f548928bf4d2d1b5e6980b4f1'+\ - 'be4c92a91986fba55902145ebd9a3f0b82069d98420986b314215025756065' - - def testImportKey3(self): - key_obj = DSA.importKey(self.der_private) - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey3(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('DER', pkcs8=False) - self.assertEqual(self.der_private, encoded) - - # 4. - pem_private="""\ + def testImportKey2(self): + for pem in (self.pem_public, tostr(self.pem_public)): + key_obj = DSA.importKey(pem) + self.assertFalse(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + + def testExportKey2(self): + tup = (self.y, self.g, self.p, self.q) + key = DSA.construct(tup) + encoded = key.export_key("PEM") + self.assertEqual(self.pem_public, encoded) + + # 3. OpenSSL/OpenSSH format + der_private = ( + "308201bb02010002818100e756ee1717f4b6794c7c214724a19763742c45572b" + + "4b3f8ff3b44f3be9f44ce039a2757695ec915697da74ef914fcd1b05660e2419" + + "c761d639f45d2d79b802dbd23e7ab8b81b479a380e1f30932584ba2a0b955032" + + "342ebc83cb5ca906e7b0d7cd6fe656cecb4c8b5a77123a8c6750a481e3b06057" + + "aff6aa6eba620b832d60c3021500ad32f48cd3ae0c45a198a61fa4b5e2032076" + + "3b2302818079dfdc3d614fe635fceb7eaeae3718dc2efefb45282993ac6749dc" + + "83c223d8c1887296316b3b0b54466cf444f34b82e3554d0b90a778faaf1306f0" + + "25dae6a3e36c7f93dd5bac4052b92370040aca70b8d5820599711900efbc9618" + + "12c355dd9beffe0981da85c5548074b41c56ae43fd300d89262e4efd89943f99" + + "a651b038880281810083352a69a132f34843d2a0eb995bff4e2f083a73f0049d" + + "2c91ea2f0ce43d144abda48199e4b003c570a8af83303d45105f606c5c48d925" + + "a40ed9c2630c2fa4cdbf838539deb9a29f919085f2046369f627ca84b2cb1e2c" + + "7940564b670f963ab1164d4e2ca2bf6ffd39f12f548928bf4d2d1b5e6980b4f1" + + "be4c92a91986fba55902145ebd9a3f0b82069d98420986b314215025756065" + ) + + def testImportKey3(self): + key_obj = DSA.importKey(self.der_private) + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey3(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("DER", pkcs8=False) + self.assertEqual(self.der_private, encoded) + + # 4. + pem_private = """\ -----BEGIN DSA PRIVATE KEY----- MIIBuwIBAAKBgQDnVu4XF/S2eUx8IUckoZdjdCxFVytLP4/ztE876fRM4DmidXaV 7JFWl9p075FPzRsFZg4kGcdh1jn0XS15uALb0j56uLgbR5o4Dh8wkyWEuioLlVAy @@ -156,55 +157,56 @@ def testExportKey3(self): ggadmEIJhrMUIVAldWBl -----END DSA PRIVATE KEY-----""" - def testImportKey4(self): - for pem in (self.pem_private, tostr(self.pem_private)): - key_obj = DSA.importKey(pem) - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey4(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('PEM', pkcs8=False) - self.assertEqual(self.pem_private, encoded) - - # 5. PKCS8 (unencrypted) - der_pkcs8=\ - '3082014a0201003082012b06072a8648ce3804013082011e02818100e756ee17'+\ - '17f4b6794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a27576'+\ - '95ec915697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8'+\ - 'b81b479a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656'+\ - 'cecb4c8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad'+\ - '32f48cd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb'+\ - '7eaeae3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466c'+\ - 'f444f34b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b923'+\ - '70040aca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074'+\ - 'b41c56ae43fd300d89262e4efd89943f99a651b03888041602145ebd9a3f0b82'+\ - '069d98420986b314215025756065' - - def testImportKey5(self): - key_obj = DSA.importKey(self.der_pkcs8) - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey5(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('DER') - self.assertEqual(self.der_pkcs8, encoded) - encoded = key.export_key('DER', pkcs8=True) - self.assertEqual(self.der_pkcs8, encoded) - - # 6. - pem_pkcs8="""\ + def testImportKey4(self): + for pem in (self.pem_private, tostr(self.pem_private)): + key_obj = DSA.importKey(pem) + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey4(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("PEM", pkcs8=False) + self.assertEqual(self.pem_private, encoded) + + # 5. PKCS8 (unencrypted) + der_pkcs8 = ( + "3082014a0201003082012b06072a8648ce3804013082011e02818100e756ee17" + + "17f4b6794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a27576" + + "95ec915697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8" + + "b81b479a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656" + + "cecb4c8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad" + + "32f48cd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb" + + "7eaeae3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466c" + + "f444f34b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b923" + + "70040aca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074" + + "b41c56ae43fd300d89262e4efd89943f99a651b03888041602145ebd9a3f0b82" + + "069d98420986b314215025756065" + ) + + def testImportKey5(self): + key_obj = DSA.importKey(self.der_pkcs8) + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey5(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("DER") + self.assertEqual(self.der_pkcs8, encoded) + encoded = key.export_key("DER", pkcs8=True) + self.assertEqual(self.der_pkcs8, encoded) + + # 6. + pem_pkcs8 = """\ -----BEGIN PRIVATE KEY----- MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVX K0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4 @@ -215,44 +217,44 @@ def testExportKey5(self): tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAQWAhRevZo/C4IGnZhCCYazFCFQJXVgZQ== -----END PRIVATE KEY-----""" - def testImportKey6(self): - for pem in (self.pem_pkcs8, tostr(self.pem_pkcs8)): - key_obj = DSA.importKey(pem) - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey6(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('PEM') - self.assertEqual(self.pem_pkcs8, encoded) - encoded = key.export_key('PEM', pkcs8=True) - self.assertEqual(self.pem_pkcs8, encoded) - - # 7. OpenSSH/RFC4253 - ssh_pub="""ssh-dss AAAAB3NzaC1kc3MAAACBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2qm66YguDLWDDAAAAFQCtMvSM064MRaGYph+kteIDIHY7IwAAAIB539w9YU/mNfzrfq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAAAAIEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVk=""" - - def testImportKey7(self): - for ssh in (self.ssh_pub, tostr(self.ssh_pub)): - key_obj = DSA.importKey(ssh) - self.assertFalse(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def testExportKey7(self): - tup = (self.y, self.g, self.p, self.q) - key = DSA.construct(tup) - encoded = key.export_key('OpenSSH') - self.assertEqual(self.ssh_pub, encoded) - - # 8. Encrypted OpenSSL/OpenSSH - pem_private_encrypted="""\ + def testImportKey6(self): + for pem in (self.pem_pkcs8, tostr(self.pem_pkcs8)): + key_obj = DSA.importKey(pem) + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey6(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("PEM") + self.assertEqual(self.pem_pkcs8, encoded) + encoded = key.export_key("PEM", pkcs8=True) + self.assertEqual(self.pem_pkcs8, encoded) + + # 7. OpenSSH/RFC4253 + ssh_pub = """ssh-dss AAAAB3NzaC1kc3MAAACBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2qm66YguDLWDDAAAAFQCtMvSM064MRaGYph+kteIDIHY7IwAAAIB539w9YU/mNfzrfq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAAAAIEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVk=""" + + def testImportKey7(self): + for ssh in (self.ssh_pub, tostr(self.ssh_pub)): + key_obj = DSA.importKey(ssh) + self.assertFalse(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + + def testExportKey7(self): + tup = (self.y, self.g, self.p, self.q) + key = DSA.construct(tup) + encoded = key.export_key("OpenSSH") + self.assertEqual(self.ssh_pub, encoded) + + # 8. Encrypted OpenSSL/OpenSSH + pem_private_encrypted = """\ -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,70B6908939D65E9F2EB999E8729788CE @@ -269,30 +271,30 @@ def testExportKey7(self): xVJtxaV37m3aXxtCsPnbBg== -----END DSA PRIVATE KEY-----""" - def testImportKey8(self): - for pem in (self.pem_private_encrypted, tostr(self.pem_private_encrypted)): - key_obj = DSA.importKey(pem, "PWDTEST") - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey8(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('PEM', pkcs8=False, passphrase="PWDTEST") - key = DSA.importKey(encoded, "PWDTEST") - self.assertEqual(self.y, key.y) - self.assertEqual(self.p, key.p) - self.assertEqual(self.q, key.q) - self.assertEqual(self.g, key.g) - self.assertEqual(self.x, key.x) - - # 9. Encrypted PKCS8 - # pbeWithMD5AndDES-CBC - pem_pkcs8_encrypted="""\ + def testImportKey8(self): + for pem in (self.pem_private_encrypted, tostr(self.pem_private_encrypted)): + key_obj = DSA.importKey(pem, "PWDTEST") + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey8(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("PEM", pkcs8=False, passphrase="PWDTEST") + key = DSA.importKey(encoded, "PWDTEST") + self.assertEqual(self.y, key.y) + self.assertEqual(self.p, key.p) + self.assertEqual(self.q, key.q) + self.assertEqual(self.g, key.g) + self.assertEqual(self.x, key.x) + + # 9. Encrypted PKCS8 + # pbeWithMD5AndDES-CBC + pem_pkcs8_encrypted = """\ -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBcTAbBgkqhkiG9w0BBQMwDgQI0GC3BJ/jSw8CAggABIIBUHc1cXZpExIE9tC7 7ryiW+5ihtF2Ekurq3e408GYSAu5smJjN2bvQXmzRFBz8W38K8eMf1sbWroZ4+zn @@ -304,88 +306,86 @@ def testExportKey8(self): eZ4k+NQDbEL8GiHmFxzDWQAuPPZKJWEEEV2p/To+WOh+kSDHQw== -----END ENCRYPTED PRIVATE KEY-----""" - def testImportKey9(self): - for pem in (self.pem_pkcs8_encrypted, tostr(self.pem_pkcs8_encrypted)): - key_obj = DSA.importKey(pem, "PWDTEST") - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - # 10. Encrypted PKCS8 - # pkcs5PBES2 / - # pkcs5PBKDF2 (rounds=1000, salt=D725BF1B6B8239F4) / - # des-EDE3-CBC (iv=27A1C66C42AFEECE) - # - der_pkcs8_encrypted=\ - '30820196304006092a864886f70d01050d3033301b06092a864886f70d01050c'+\ - '300e0408d725bf1b6b8239f4020203e8301406082a864886f70d0307040827a1'+\ - 'c66c42afeece048201505cacfde7bf8edabb3e0d387950dc872662ea7e9b1ed4'+\ - '400d2e7e6186284b64668d8d0328c33a9d9397e6f03df7cb68268b0a06b4e22f'+\ - '7d132821449ecf998a8b696dbc6dd2b19e66d7eb2edfeb4153c1771d49702395'+\ - '4f36072868b5fcccf93413a5ac4b2eb47d4b3f681c6bd67ae363ed776f45ae47'+\ - '174a00098a7c930a50f820b227ddf50f9742d8e950d02586ff2dac0e3c372248'+\ - 'e5f9b6a7a02f4004f20c87913e0f7b52bccc209b95d478256a890b31d4c9adec'+\ - '21a4d157a179a93a3dad06f94f3ce486b46dfa7fc15fd852dd7680bbb2f17478'+\ - '7e71bd8dbaf81eca7518d76c1d26256e95424864ba45ca5d47d7c5a421be02fa'+\ - 'b94ab01e18593f66cf9094eb5c94b9ecf3aa08b854a195cf87612fbe5e96c426'+\ - '2b0d573e52dc71ba3f5e468c601e816c49b7d32c698b22175e89aaef0c443770'+\ - '5ef2f88a116d99d8e2869a4fd09a771b84b49e4ccb79aadcb1c9' - - def testImportKey10(self): - key_obj = DSA.importKey(self.der_pkcs8_encrypted, "PWDTEST") - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey10(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - randfunc = BytesIO(unhexlify(b("27A1C66C42AFEECE") + b("D725BF1B6B8239F4"))).read - encoded = key.export_key('DER', pkcs8=True, passphrase="PWDTEST", randfunc=randfunc) - self.assertEqual(self.der_pkcs8_encrypted, encoded) - - # ---- - - def testImportError1(self): - self.assertRaises(ValueError, DSA.importKey, self.der_pkcs8_encrypted, "wrongpwd") - - def testExportError2(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - self.assertRaises(ValueError, key.export_key, 'DER', pkcs8=False, passphrase="PWDTEST") - - def test_import_key(self): - """Verify importKey is an alias to import_key""" - - key_obj = DSA.import_key(self.der_public) - self.assertFalse(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def test_exportKey(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - self.assertEqual(key.exportKey(), key.export_key()) - - - def test_import_empty(self): - self.assertRaises(ValueError, DSA.import_key, b'') + def testImportKey9(self): + for pem in (self.pem_pkcs8_encrypted, tostr(self.pem_pkcs8_encrypted)): + key_obj = DSA.importKey(pem, "PWDTEST") + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + # 10. Encrypted PKCS8 + # pkcs5PBES2 / + # pkcs5PBKDF2 (rounds=1000, salt=D725BF1B6B8239F4) / + # des-EDE3-CBC (iv=27A1C66C42AFEECE) + # + der_pkcs8_encrypted = ( + "30820196304006092a864886f70d01050d3033301b06092a864886f70d01050c" + + "300e0408d725bf1b6b8239f4020203e8301406082a864886f70d0307040827a1" + + "c66c42afeece048201505cacfde7bf8edabb3e0d387950dc872662ea7e9b1ed4" + + "400d2e7e6186284b64668d8d0328c33a9d9397e6f03df7cb68268b0a06b4e22f" + + "7d132821449ecf998a8b696dbc6dd2b19e66d7eb2edfeb4153c1771d49702395" + + "4f36072868b5fcccf93413a5ac4b2eb47d4b3f681c6bd67ae363ed776f45ae47" + + "174a00098a7c930a50f820b227ddf50f9742d8e950d02586ff2dac0e3c372248" + + "e5f9b6a7a02f4004f20c87913e0f7b52bccc209b95d478256a890b31d4c9adec" + + "21a4d157a179a93a3dad06f94f3ce486b46dfa7fc15fd852dd7680bbb2f17478" + + "7e71bd8dbaf81eca7518d76c1d26256e95424864ba45ca5d47d7c5a421be02fa" + + "b94ab01e18593f66cf9094eb5c94b9ecf3aa08b854a195cf87612fbe5e96c426" + + "2b0d573e52dc71ba3f5e468c601e816c49b7d32c698b22175e89aaef0c443770" + + "5ef2f88a116d99d8e2869a4fd09a771b84b49e4ccb79aadcb1c9" + ) + + def testImportKey10(self): + key_obj = DSA.importKey(self.der_pkcs8_encrypted, "PWDTEST") + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey10(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + randfunc = BytesIO(unhexlify(b("27A1C66C42AFEECE") + b("D725BF1B6B8239F4"))).read + encoded = key.export_key("DER", pkcs8=True, passphrase="PWDTEST", randfunc=randfunc) + self.assertEqual(self.der_pkcs8_encrypted, encoded) + + # ---- + + def testImportError1(self): + self.assertRaises(ValueError, DSA.importKey, self.der_pkcs8_encrypted, "wrongpwd") + + def testExportError2(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + self.assertRaises(ValueError, key.export_key, "DER", pkcs8=False, passphrase="PWDTEST") + + def test_import_key(self): + """Verify importKey is an alias to import_key""" + + key_obj = DSA.import_key(self.der_public) + self.assertFalse(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + + def test_exportKey(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + self.assertEqual(key.exportKey(), key.export_key()) + + def test_import_empty(self): + self.assertRaises(ValueError, DSA.import_key, b"") class ImportKeyFromX509Cert(unittest.TestCase): - - def test_x509v1(self): - - # Sample V1 certificate with a 1024 bit DSA key - x509_v1_cert = """ + def test_x509v1(self): + # Sample V1 certificate with a 1024 bit DSA key + x509_v1_cert = """ -----BEGIN CERTIFICATE----- MIIDUjCCArsCAQIwDQYJKoZIhvcNAQEFBQAwfjENMAsGA1UEChMEQWNtZTELMAkG A1UECxMCUkQxHDAaBgkqhkiG9w0BCQEWDXNwYW1AYWNtZS5vcmcxEzARBgNVBAcT @@ -408,8 +408,8 @@ def test_x509v1(self): -----END CERTIFICATE----- """.strip() - # DSA public key as dumped by openssl - y_str = """ + # DSA public key as dumped by openssl + y_str = """ 2a:88:ab:3c:07:dc:a7:5a:db:6e:5e:32:d8:51:40: 22:4b:5f:5b:c7:f8:f9:3e:dd:da:22:92:83:bd:da: 89:57:ee:8e:13:4e:b7:56:73:d6:57:c2:d0:d2:36: @@ -420,7 +420,7 @@ def test_x509v1(self): c8:77:c6:31:f1:78:d0:c5:4d:e3:6d:b6:cc:a7:86: a7:bc:61:33:40:8d:88:25 """ - p_str = """ + p_str = """ 00:ce:ac:de:0e:c7:8f:ad:dd:3e:b0:29:e1:df:87: 30:2b:85:ca:cd:10:53:10:e1:2b:3e:e0:f2:0a:ca: 29:83:cb:d0:67:eb:85:8f:90:bd:41:ff:d7:6f:60: @@ -431,11 +431,11 @@ def test_x509v1(self): 7f:95:4d:33:c3:7f:2a:c9:31:80:a4:87:4a:c9:01: f0:8f:fb:9c:6b:98:f3:5e:b7 """ - q_str = """ + q_str = """ 00:bb:57:60:e5:75:ca:84:6b:cc:9d:90:33:9b:84: 8e:27:47:e8:68:99 """ - g_str = """ + g_str = """ 7d:4a:80:d5:20:26:e6:0e:54:eb:c4:88:2c:c5:57: f6:5e:6b:ab:43:a9:07:4c:1a:04:ca:49:43:7d:7f: 47:fc:97:34:3a:a8:73:78:06:59:94:ce:24:55:38: @@ -447,17 +447,16 @@ def test_x509v1(self): 2c:62:a9:58:dd:ff:9b:c9 """ - key = DSA.importKey(x509_v1_cert) - for comp_name in ('y', 'p', 'q', 'g'): - comp_str = locals()[comp_name + "_str"] - comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) - self.assertEqual(getattr(key, comp_name), comp) - self.assertFalse(key.has_private()) - - def test_x509v3(self): + key = DSA.importKey(x509_v1_cert) + for comp_name in ("y", "p", "q", "g"): + comp_str = locals()[comp_name + "_str"] + comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) + self.assertEqual(getattr(key, comp_name), comp) + self.assertFalse(key.has_private()) - # Sample V3 certificate with a 1024 bit DSA key - x509_v3_cert = """ + def test_x509v3(self): + # Sample V3 certificate with a 1024 bit DSA key + x509_v3_cert = """ -----BEGIN CERTIFICATE----- MIIFhjCCA26gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL MAkGA1UECAwCTUQxEjAQBgNVBAcMCUJhbHRpbW9yZTEQMA4GA1UEAwwHVGVzdCBD @@ -492,8 +491,8 @@ def test_x509v3(self): -----END CERTIFICATE----- """.strip() - # DSA public key as dumped by openssl - y_str = """ + # DSA public key as dumped by openssl + y_str = """ 72:95:68:d6:4a:72:87:13:c9:87:c7:50:39:9b:fd: 06:43:1e:b1:9e:15:88:7b:7f:8c:24:09:c4:85:11: b1:03:62:78:48:2b:1f:59:4d:0e:c2:09:48:41:3a: @@ -504,7 +503,7 @@ def test_x509v3(self): 62:29:e4:85:05:f1:67:a0:ca:8b:f9:d7:7d:19:bd: d0:3d:94:a5:94:17:15:0f """ - p_str = """ + p_str = """ 00:b7:dd:f2:0c:84:a5:53:c0:d1:92:3a:f4:aa:77: 9f:22:5c:bb:93:74:65:9d:ca:d4:af:61:95:e4:0b: 36:a2:84:71:93:a1:ed:af:c2:d8:9d:53:3d:d9:87: @@ -515,11 +514,11 @@ def test_x509v3(self): 62:3d:f3:99:97:58:32:86:bd:d3:81:75:68:35:ab: f8:3c:50:23:a0:d5:0b:7f:db """ - q_str = """ + q_str = """ 00:86:a5:cc:08:9e:9f:40:ad:c6:d8:ef:52:df:f0: 82:ff:25:59:5c:2b """ - g_str = """ + g_str = """ 51:5d:13:a5:dd:1d:a4:85:7e:e5:d7:42:d0:8c:31: 20:a3:70:75:23:38:d7:53:f8:cf:31:c3:01:97:a5: ce:fa:70:49:5f:1a:ff:b1:c6:ea:f0:08:e2:bf:b2: @@ -531,24 +530,25 @@ def test_x509v3(self): 07:c6:cb:a8:ee:89:c0:6f """ - key = DSA.importKey(x509_v3_cert) - for comp_name in ('y', 'p', 'q', 'g'): - comp_str = locals()[comp_name + "_str"] - comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) - self.assertEqual(getattr(key, comp_name), comp) - self.assertFalse(key.has_private()) + key = DSA.importKey(x509_v3_cert) + for comp_name in ("y", "p", "q", "g"): + comp_str = locals()[comp_name + "_str"] + comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) + self.assertEqual(getattr(key, comp_name), comp) + self.assertFalse(key.has_private()) + +if __name__ == "__main__": + unittest.main() -if __name__ == '__main__': - unittest.main() def get_tests(config={}): - tests = [] - tests += list_test_cases(ImportKeyTests) - tests += list_test_cases(ImportKeyFromX509Cert) - return tests + tests = [] + tests += list_test_cases(ImportKeyTests) + tests += list_test_cases(ImportKeyFromX509Cert) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_ECC.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_ECC.py index ee80000d..88e8f660 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_ECC.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_ECC.py @@ -45,2215 +45,2465 @@ from Cryptodome.PublicKey.ECC import _import_rfc5915_der try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False class MissingTestVectorException(ValueError): - pass + pass def load_file(file_name, mode="rb"): - results = None + results = None - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) - dir_comps = ("PublicKey", "ECC") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() + dir_comps = ("PublicKey", "ECC") + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name, mode) as file_in: + results = file_in.read() - except FileNotFoundError: - warnings.warn("Skipping extended tests for ECC", - UserWarning, - stacklevel=2) + except FileNotFoundError: + warnings.warn( + "Skipping extended tests for ECC", + UserWarning, + stacklevel=2, + ) - if results is None: - raise MissingTestVectorException("Missing %s" % file_name) + if results is None: + raise MissingTestVectorException("Missing %s" % file_name) - return results + return results def compact(lines): - ext = b"".join(lines) - return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) + ext = b"".join(lines) + return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) def create_ref_keys_p192(): - key_len = 24 - key_lines = load_file("ecc_p192.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:4])) - public_key_xy = compact(key_lines[5:9]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 24 + key_lines = load_file("ecc_p192.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:4])) + public_key_xy = compact(key_lines[5:9]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-192", d=private_key_d), - ECC.construct(curve="P-192", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-192", d=private_key_d), + ECC.construct(curve="P-192", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_p224(): - key_len = 28 - key_lines = load_file("ecc_p224.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:4])) - public_key_xy = compact(key_lines[5:9]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 28 + key_lines = load_file("ecc_p224.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:4])) + public_key_xy = compact(key_lines[5:9]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-224", d=private_key_d), - ECC.construct(curve="P-224", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-224", d=private_key_d), + ECC.construct(curve="P-224", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_p256(): - key_len = 32 - key_lines = load_file("ecc_p256.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:5])) - public_key_xy = compact(key_lines[6:11]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 32 + key_lines = load_file("ecc_p256.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:5])) + public_key_xy = compact(key_lines[6:11]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-256", d=private_key_d), - ECC.construct(curve="P-256", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-256", d=private_key_d), + ECC.construct(curve="P-256", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_p384(): - key_len = 48 - key_lines = load_file("ecc_p384.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:6])) - public_key_xy = compact(key_lines[7:14]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 48 + key_lines = load_file("ecc_p384.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:6])) + public_key_xy = compact(key_lines[7:14]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-384", d=private_key_d), - ECC.construct(curve="P-384", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-384", d=private_key_d), + ECC.construct(curve="P-384", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_p521(): - key_len = 66 - key_lines = load_file("ecc_p521.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:7])) - public_key_xy = compact(key_lines[8:17]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 66 + key_lines = load_file("ecc_p521.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:7])) + public_key_xy = compact(key_lines[8:17]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-521", d=private_key_d), - ECC.construct(curve="P-521", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-521", d=private_key_d), + ECC.construct(curve="P-521", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_ed25519(): - key_lines = load_file("ecc_ed25519.txt").splitlines() - seed = compact(key_lines[5:8]) - key = ECC.construct(curve="Ed25519", seed=seed) - return (key, key.public_key()) + key_lines = load_file("ecc_ed25519.txt").splitlines() + seed = compact(key_lines[5:8]) + key = ECC.construct(curve="Ed25519", seed=seed) + return (key, key.public_key()) def create_ref_keys_ed448(): - key_lines = load_file("ecc_ed448.txt").splitlines() - seed = compact(key_lines[6:10]) - key = ECC.construct(curve="Ed448", seed=seed) - return (key, key.public_key()) + key_lines = load_file("ecc_ed448.txt").splitlines() + seed = compact(key_lines[6:10]) + key = ECC.construct(curve="Ed448", seed=seed) + return (key, key.public_key()) # Create reference key pair # ref_private, ref_public = create_ref_keys_p521() + def get_fixed_prng(): - return SHAKE128.new().update(b"SEED").read + return SHAKE128.new().update(b"SEED").read def extract_bitstring_from_spki(data): - seq = DerSequence() - seq.decode(data) - bs = DerBitString() - bs.decode(seq[1]) - return bs.value + seq = DerSequence() + seq.decode(data) + bs = DerBitString() + bs.decode(seq[1]) + return bs.value class TestImport(unittest.TestCase): + def test_empty(self): + self.assertRaises(ValueError, ECC.import_key, b"") - def test_empty(self): - self.assertRaises(ValueError, ECC.import_key, b"") - - def test_mismatch(self): - # The private key does not match the public key - mismatch = """-----BEGIN PRIVATE KEY----- + def test_mismatch(self): + # The private key does not match the public key + mismatch = """-----BEGIN PRIVATE KEY----- MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJChZANiAAQarFRaqflo I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXk= -----END PRIVATE KEY-----""" - self.assertRaises(ValueError, ECC.import_key, mismatch) - - def test_import_private_rfc5915_none(self): - # ECPrivateKey with a P256 private key, without [0] and [1] - data_hex = "302502010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052" - key = _import_rfc5915_der(unhexlify(data_hex), None, "1.2.840.10045.3.1.7") - self.assertEqual(key.d, 0x5c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052) - - def test_import_private_rfc5915_only_0(self): - # ECPrivateKey with a P256 private key, with [0] only - data_hex = "303102010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052a00a06082a8648ce3d030107" - key = _import_rfc5915_der(unhexlify(data_hex), None) - self.assertEqual(key.d, 0x5c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052) - - def test_import_private_rfc5915_only_1(self): - # ECPrivateKey with a P256 private key, with [1] only - data_hex = "306b02010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052a14403420004a40ad59a2050ebe92479bd5fb16bb2e45b6465eb3cb2b1effe423fabe6cb7424db8219ef0bab80acf26fd70595b61fe4760d33eed80dd03d2fd0dfb27b8ce75c" - key = _import_rfc5915_der(unhexlify(data_hex), None, "1.2.840.10045.3.1.7") - self.assertEqual(key.d, 0x5c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052) + self.assertRaises(ValueError, ECC.import_key, mismatch) -class TestImport_P192(unittest.TestCase): + def test_import_private_rfc5915_none(self): + # ECPrivateKey with a P256 private key, without [0] and [1] + data_hex = "302502010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052" + key = _import_rfc5915_der(unhexlify(data_hex), None, "1.2.840.10045.3.1.7") + self.assertEqual(key.d, 0x5C4E4320EF260F91ED9FC597AEE98C8236B60E0CED692CC7A057D5E45798A052) - def __init__(self, *args, **kwargs): - super(TestImport_P192, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p192() + def test_import_private_rfc5915_only_0(self): + # ECPrivateKey with a P256 private key, with [0] only + data_hex = "303102010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052a00a06082a8648ce3d030107" + key = _import_rfc5915_der(unhexlify(data_hex), None) + self.assertEqual(key.d, 0x5C4E4320EF260F91ED9FC597AEE98C8236B60E0CED692CC7A057D5E45798A052) - def test_import_public_der(self): - key_file = load_file("ecc_p192_public.der") + def test_import_private_rfc5915_only_1(self): + # ECPrivateKey with a P256 private key, with [1] only + data_hex = "306b02010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052a14403420004a40ad59a2050ebe92479bd5fb16bb2e45b6465eb3cb2b1effe423fabe6cb7424db8219ef0bab80acf26fd70595b61fe4760d33eed80dd03d2fd0dfb27b8ce75c" + key = _import_rfc5915_der(unhexlify(data_hex), None, "1.2.840.10045.3.1.7") + self.assertEqual(key.d, 0x5C4E4320EF260F91ED9FC597AEE98C8236B60E0CED692CC7A057D5E45798A052) - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) +class TestImport_P192(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P192, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p192() - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_public_der(self): + key_file = load_file("ecc_p192_public.der") - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p192_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P192') - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p192_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P192') - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p192_private.der") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p192_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P192") + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p192_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P192") + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p192_private.der") - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p192_private_p8_clear.der") + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p192_private_p8_clear.pem") + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p192_private_p8_clear.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p192_private_p8.der") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p192_private_p8_clear.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p192_private_p8.pem") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p192_private_p8.der") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_p192_x509.der") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p192_private_p8.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_public_pem(self): - key_file = load_file("ecc_p192_public.pem") + def test_import_x509_der(self): + key_file = load_file("ecc_p192_x509.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_p192_private.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_public_pem(self): + key_file = load_file("ecc_p192_public.pem") - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p192_private_enc_%s.pem" % algo) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pem(self): + key_file = load_file("ecc_p192_private.pem") - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_p192_x509.pem") + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p192_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) -class TestImport_P224(unittest.TestCase): + def test_import_x509_pem(self): + key_file = load_file("ecc_p192_x509.pem") - def __init__(self, *args, **kwargs): - super(TestImport_P224, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p224() + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_der(self): - key_file = load_file("ecc_p224_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) +class TestImport_P224(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P224, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p224() - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + def test_import_public_der(self): + key_file = load_file("ecc_p224_public.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p224_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P224') - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p224_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P224') - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p224_private.der") + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p224_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P224") + self.assertEqual(self.ref_public, key) - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p224_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P224") + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p224_private.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p224_private_p8_clear.der") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p224_private_p8_clear.der") - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p224_private_p8_clear.pem") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p224_private_p8.der") + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p224_private_p8_clear.pem") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p224_private_p8.der") - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p224_private_p8.pem") + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_p224_private_p8_2.der") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p224_private_p8.pem") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_p224_private_p8_2.der") - def test_import_x509_der(self): - key_file = load_file("ecc_p224_x509.der") + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_x509_der(self): + key_file = load_file("ecc_p224_x509.der") - def test_import_public_pem(self): - key_file = load_file("ecc_p224_public.pem") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_p224_private.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_p224_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p224_private_enc_%s.pem" % algo) + def test_import_private_pem(self): + key_file = load_file("ecc_p224_private.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p224_private_enc_%s.pem" % algo) - def test_import_x509_pem(self): - key_file = load_file("ecc_p224_x509.pem") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) + def test_import_x509_pem(self): + key_file = load_file("ecc_p224_x509.pem") -class TestImport_P256(unittest.TestCase): + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def __init__(self, *args, **kwargs): - super(TestImport_P256, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p256() - def test_import_public_der(self): - key_file = load_file("ecc_p256_public.der") +class TestImport_P256(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P256, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p256() - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + def test_import_public_der(self): + key_file = load_file("ecc_p256_public.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p256_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P256') - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p256_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P256') - self.assertEqual(self.ref_public, key) + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p256_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P256") + self.assertEqual(self.ref_public, key) - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p256_private.der") + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p256_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P256") + self.assertEqual(self.ref_public, key) - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p256_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p256_private_p8_clear.der") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p256_private_p8_clear.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p256_private_p8_clear.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p256_private_p8_clear.pem") - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p256_private_p8.der") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p256_private_p8.der") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p256_private_p8.pem") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p256_private_p8.pem") - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_p256_private_p8_2.der") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_p256_private_p8_2.der") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_p256_x509.der") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + def test_import_x509_der(self): + key_file = load_file("ecc_p256_x509.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_p256_public.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_public_pem(self): + key_file = load_file("ecc_p256_public.pem") - def test_import_private_pem(self): - key_file = load_file("ecc_p256_private.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pem(self): + key_file = load_file("ecc_p256_private.pem") - def test_import_private_pem_with_ecparams(self): - key_file = load_file("ecc_p256_private_ecparams.pem") - key = ECC.import_key(key_file) - # We just check if the import succeeds + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p256_private_enc_%s.pem" % algo) + def test_import_private_pem_with_ecparams(self): + key_file = load_file("ecc_p256_private_ecparams.pem") + key = ECC.import_key(key_file) + # We just check if the import succeeds - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p256_private_enc_%s.pem" % algo) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_p256_x509.pem") + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_x509_pem(self): + key_file = load_file("ecc_p256_x509.pem") - def test_import_openssh_public(self): - key_file = load_file("ecc_p256_public_openssh.txt") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_openssh_public(key_file) - self.assertEqual(self.ref_public, key) + def test_import_openssh_public(self): + key_file = load_file("ecc_p256_public_openssh.txt") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_openssh_public(key_file) + self.assertEqual(self.ref_public, key) - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_p256_private_openssh.pem") - key_file_old = load_file("ecc_p256_private_openssh_old.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + def test_import_openssh_private_clear(self): + key_file = load_file("ecc_p256_private_openssh.pem") + key_file_old = load_file("ecc_p256_private_openssh_old.pem") - def test_import_openssh_private_password(self): - key_file = load_file("ecc_p256_private_openssh_pwd.pem") - key_file_old = load_file("ecc_p256_private_openssh_pwd_old.pem") + key = ECC.import_key(key_file) + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) - key = ECC.import_key(key_file, b"password") - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + def test_import_openssh_private_password(self): + key_file = load_file("ecc_p256_private_openssh_pwd.pem") + key_file_old = load_file("ecc_p256_private_openssh_pwd_old.pem") + key = ECC.import_key(key_file, b"password") + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) -class TestImport_P384(unittest.TestCase): - def __init__(self, *args, **kwargs): - super(TestImport_P384, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p384() +class TestImport_P384(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P384, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p384() - def test_import_public_der(self): - key_file = load_file("ecc_p384_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_p384_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p384_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P384') - self.assertEqual(self.ref_public, key) + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p384_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P384") + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p384_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P384') - self.assertEqual(self.ref_public, key) + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p384_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P384") + self.assertEqual(self.ref_public, key) - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p384_private.der") + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p384_private.der") - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p384_private_p8_clear.der") + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p384_private_p8_clear.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p384_private_p8_clear.pem") + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p384_private_p8_clear.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p384_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p384_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p384_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p384_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_p384_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_p384_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_p384_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_p384_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_p384_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_p384_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_p384_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_p384_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p384_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p384_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_p384_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_p384_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_openssh_public(self): - key_file = load_file("ecc_p384_public_openssh.txt") + def test_import_openssh_public(self): + key_file = load_file("ecc_p384_public_openssh.txt") - key = ECC._import_openssh_public(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_openssh_public(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_p384_private_openssh.pem") - key_file_old = load_file("ecc_p384_private_openssh_old.pem") + def test_import_openssh_private_clear(self): + key_file = load_file("ecc_p384_private_openssh.pem") + key_file_old = load_file("ecc_p384_private_openssh_old.pem") - key = ECC.import_key(key_file) - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + key = ECC.import_key(key_file) + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) - def test_import_openssh_private_password(self): - key_file = load_file("ecc_p384_private_openssh_pwd.pem") - key_file_old = load_file("ecc_p384_private_openssh_pwd_old.pem") + def test_import_openssh_private_password(self): + key_file = load_file("ecc_p384_private_openssh_pwd.pem") + key_file_old = load_file("ecc_p384_private_openssh_pwd_old.pem") - key = ECC.import_key(key_file, b"password") - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + key = ECC.import_key(key_file, b"password") + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) class TestImport_P521(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P521, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p521() - def __init__(self, *args, **kwargs): - super(TestImport_P521, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p521() + def test_import_public_der(self): + key_file = load_file("ecc_p521_public.der") - def test_import_public_der(self): - key_file = load_file("ecc_p521_public.der") + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p521_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P521") + self.assertEqual(self.ref_public, key) - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p521_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P521') - self.assertEqual(self.ref_public, key) + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p521_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P521") + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p521_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P521') - self.assertEqual(self.ref_public, key) + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p521_private.der") - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p521_private.der") + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p521_private_p8_clear.der") - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p521_private_p8_clear.der") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p521_private_p8_clear.pem") - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p521_private_p8_clear.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p521_private_p8.der") - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p521_private_p8.der") + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p521_private_p8.pem") - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p521_private_p8.pem") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_p521_private_p8_2.der") - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_p521_private_p8_2.der") + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_x509_der(self): + key_file = load_file("ecc_p521_x509.der") - def test_import_x509_der(self): - key_file = load_file("ecc_p521_x509.der") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_public_pem(self): + key_file = load_file("ecc_p521_public.pem") - def test_import_public_pem(self): - key_file = load_file("ecc_p521_public.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_private_pem(self): + key_file = load_file("ecc_p521_private.pem") - def test_import_private_pem(self): - key_file = load_file("ecc_p521_private.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p521_private_enc_%s.pem" % algo) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p521_private_enc_%s.pem" % algo) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + def test_import_x509_pem(self): + key_file = load_file("ecc_p521_x509.pem") - def test_import_x509_pem(self): - key_file = load_file("ecc_p521_x509.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_openssh_public(self): + key_file = load_file("ecc_p521_public_openssh.txt") - def test_import_openssh_public(self): - key_file = load_file("ecc_p521_public_openssh.txt") + key = ECC._import_openssh_public(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_openssh_public(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_openssh_private_clear(self): + key_file = load_file("ecc_p521_private_openssh.pem") + key_file_old = load_file("ecc_p521_private_openssh_old.pem") - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_p521_private_openssh.pem") - key_file_old = load_file("ecc_p521_private_openssh_old.pem") + key = ECC.import_key(key_file) + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) - key = ECC.import_key(key_file) - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + def test_import_openssh_private_password(self): + key_file = load_file("ecc_p521_private_openssh_pwd.pem") + key_file_old = load_file("ecc_p521_private_openssh_pwd_old.pem") - def test_import_openssh_private_password(self): - key_file = load_file("ecc_p521_private_openssh_pwd.pem") - key_file_old = load_file("ecc_p521_private_openssh_pwd_old.pem") - - key = ECC.import_key(key_file, b"password") - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + key = ECC.import_key(key_file, b"password") + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) class TestExport_P192(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P192, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p192() - def __init__(self, *args, **kwargs): - super(TestExport_P192, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p192() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p192_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p192_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p192_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p192_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p192_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p192_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p192_public.der") - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p192_private.der") + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p192_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p192_private_p8_clear.der") + key_file_compressed_ref = load_file("ecc_p192_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p192_public.der") + value = extract_bitstring_from_spki(key_file) - # --- + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p192_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + key_file_compressed_ref = load_file("ecc_p192_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p192_private.der") - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - # --- + # --- - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - # --- + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p192_private_p8_clear.der") - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA224AndAES192-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p192_public.pem", "rt").strip() + # --- - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - # --- + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p192_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + # --- - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p192_public_compressed.pem", "rt").strip() + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - self.assertEqual(key_file_compressed, key_file_compressed_ref) + # --- - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p192_private.pem", "rt").strip() + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA224AndAES192-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p192_public.pem", "rt").strip() - # --- + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + # --- - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - assert "EC PRIVATE KEY" in encoded + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p192_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p192_public_compressed.pem", "rt").strip() - # --- + self.assertEqual(key_file_compressed, key_file_compressed_ref) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p192_private.pem", "rt").strip() - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p192_private_p8_clear.pem", "rt").strip() + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + # --- - # --- + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - def test_compressed_curve(self): - - # Compressed P-192 curve (Y-point is even) - pem1 = """-----BEGIN EC PRIVATE KEY----- + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "EC PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p192_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + def test_compressed_curve(self): + # Compressed P-192 curve (Y-point is even) + pem1 = """-----BEGIN EC PRIVATE KEY----- MF8CAQEEGHvhXmIW95JxZYfd4AUPu9BwknjuvS36aqAKBggqhkjOPQMBAaE0AzIA BLJZCyTu35DQIlqvMlBynn3k1Ig+dWfg/brRhHecxptrbloqFSP8ITw0CwbGF+2X 5g== -----END EC PRIVATE KEY-----""" - # Compressed P-192 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-192 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MF8CAQEEGA3rAotUaWl7d47eX6tz9JmLzOMJwl13XaAKBggqhkjOPQMBAaE0AzIA BG4tHlTBBBGokcWmGm2xubVB0NvPC/Ou5AYwivs+3iCxmEjsymVAj6iiuX2Lxr6g /Q== -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x97E6) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0x97E6) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0xA0FD) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0xA0FD) class TestExport_P224(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P224, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p224() - def __init__(self, *args, **kwargs): - super(TestExport_P224, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p224() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p224_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p224_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p224_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p224_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p224_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p224_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) - - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p224_private.der") + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p224_public.der") - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p224_private_p8_clear.der") + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p224_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + key_file_compressed_ref = load_file("ecc_p224_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - # --- + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p224_public.der") + value = extract_bitstring_from_spki(key_file) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p224_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + key_file_compressed_ref = load_file("ecc_p224_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p224_private.der") - # --- + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA512-224AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # --- - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p224_public.pem", "rt").strip() + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p224_private_p8_clear.der") - # --- + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + # --- - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p224_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p224_public_compressed.pem", "rt").strip() + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - self.assertEqual(key_file_compressed, key_file_compressed_ref) + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p224_private.pem", "rt").strip() + # --- - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA512-224AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # --- + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p224_public.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + # --- - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - assert "EC PRIVATE KEY" in encoded + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p224_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - # --- + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p224_public_compressed.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + self.assertEqual(key_file_compressed, key_file_compressed_ref) - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p224_private_p8_clear.pem", "rt").strip() + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p224_private.pem", "rt").strip() - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - # --- + # --- - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - def test_compressed_curve(self): - - # Compressed P-224 curve (Y-point is even) - pem1 = """-----BEGIN EC PRIVATE KEY----- + assert "EC PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p224_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + def test_compressed_curve(self): + # Compressed P-224 curve (Y-point is even) + pem1 = """-----BEGIN EC PRIVATE KEY----- MGgCAQEEHPYicBNI9nd6wDKAX2l+f3A0Q+KWUQeMqSt5GoOgBwYFK4EEACGhPAM6 AATCL6rUIDT14zXKoS5GQUMDP/tpc+1iI/FyEZikt2roKDkhU5q08srmqaysbfJN eUr7Xf1lnCVGag== -----END EC PRIVATE KEY-----""" - # Compressed P-224 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-224 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MGgCAQEEHEFjbaVPLJ3ngZyCibCvT0RLUqSlHjC5Z3e0FtugBwYFK4EEACGhPAM6 AAT5IvL2V6m48y1JLMGr6ZbnOqNKP9hMf9mxyVkk6/SaRoBoJVkXrNIpYL0P7DS7 QF8E/OGeZRwvow== -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x466A) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0x466A) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0x2FA3) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0x2FA3) class TestExport_P256(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P256, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p256() - def __init__(self, *args, **kwargs): - super(TestExport_P256, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p256() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p256_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p256_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p256_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p256_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p256_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p256_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) - - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p256_private.der") - - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p256_public.der") - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p256_private_p8_clear.der") + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p256_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + key_file_compressed_ref = load_file("ecc_p256_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p256_public.der") + value = extract_bitstring_from_spki(key_file) - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - # --- + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p256_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + key_file_compressed_ref = load_file("ecc_p256_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - # --- + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p256_private.der") - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA512-256AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p256_public.pem", "rt").strip() + # --- - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - # --- + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p256_private_p8_clear.der") - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + # --- - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p256_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p256_public_compressed.pem", "rt").strip() + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - self.assertEqual(key_file_compressed, key_file_compressed_ref) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p256_private.pem", "rt").strip() + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + # --- - # --- + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + # --- - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA512-256AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p256_public.pem", "rt").strip() - assert "EC PRIVATE KEY" in encoded + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # --- - # --- + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p256_private_p8_clear.pem", "rt").strip() + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p256_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p256_public_compressed.pem", "rt").strip() - # --- + self.assertEqual(key_file_compressed, key_file_compressed_ref) - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p256_private.pem", "rt").strip() - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + # --- - assert "ENCRYPTED PRIVATE KEY" in encoded + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") - # --- + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + assert "EC PRIVATE KEY" in encoded - def test_export_openssh_uncompressed(self): - key_file = load_file("ecc_p256_public_openssh.txt", "rt") + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_public._export_openssh(False) - self.assertEqual(key_file, encoded) + # --- - # --- + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_public.export_key(format="OpenSSH") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="OpenSSH", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_openssh_compressed(self): - key_file = load_file("ecc_p256_public_openssh.txt", "rt") - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) - assert len(key_file) > len(key_file_compressed) - self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") - - - def test_compressed_curve(self): - - # Compressed P-256 curve (Y-point is even) - pem1 = """-----BEGIN EC PRIVATE KEY----- + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p256_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh_uncompressed(self): + key_file = load_file("ecc_p256_public_openssh.txt", "rt") + + encoded = self.ref_public._export_openssh(False) + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_public.export_key(format="OpenSSH") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="OpenSSH", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_openssh_compressed(self): + key_file = load_file("ecc_p256_public_openssh.txt", "rt") + pub_key = ECC.import_key(key_file) + + key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) + assert len(key_file) > len(key_file_compressed) + self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) + + def test_compressed_curve(self): + # Compressed P-256 curve (Y-point is even) + pem1 = """-----BEGIN EC PRIVATE KEY----- MFcCAQEEIHTuc09jC51xXomV6MVCDN+DpAAvSmaJWZPTEHM6D5H1oAoGCCqGSM49 AwEHoSQDIgACWFuGbHe8yJ43rir7PMTE9w8vHz0BSpXHq90Xi7/s+a0= -----END EC PRIVATE KEY-----""" - # Compressed P-256 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-256 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MFcCAQEEIFggiPN9SQP+FAPTCPp08fRUz7rHp2qNBRcBJ1DXhb3ZoAoGCCqGSM49 AwEHoSQDIgADLpph1trTIlVfa8NJvlMUPyWvL+wP+pW3BJITUL/wj9A= -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0xA6FC) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0xA6FC) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0x6E57) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0x6E57) class TestExport_P384(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P384, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p384() - def __init__(self, *args, **kwargs): - super(TestExport_P384, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p384() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p384_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p384_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p384_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p384_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p384_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p384_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) - - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p384_private.der") - - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p384_private_p8_clear.der") + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p384_public.der") - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p384_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + key_file_compressed_ref = load_file("ecc_p384_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p384_public.der") + value = extract_bitstring_from_spki(key_file) - # --- + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p384_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - # --- + key_file_compressed_ref = load_file("ecc_p384_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA384AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p384_private.der") - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p384_public.pem", "rt").strip() + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + # --- - # --- + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p384_private_p8_clear.der") - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p384_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + # --- - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p384_public_compressed.pem", "rt").strip() + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - self.assertEqual(key_file_compressed, key_file_compressed_ref) + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p384_private.pem", "rt").strip() + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # --- + # --- - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + # --- - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA384AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - assert "EC PRIVATE KEY" in encoded + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p384_public.pem", "rt").strip() - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - # --- + # --- - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p384_private_p8_clear.pem", "rt").strip() + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p384_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - # --- + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p384_public_compressed.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) + self.assertEqual(key_file_compressed, key_file_compressed_ref) - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p384_private.pem", "rt").strip() - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - assert "ENCRYPTED PRIVATE KEY" in encoded + # --- - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - # --- + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) - def test_export_openssh_uncompressed(self): - key_file = load_file("ecc_p384_public_openssh.txt", "rt") + assert "EC PRIVATE KEY" in encoded - encoded = self.ref_public._export_openssh(False) - self.assertEqual(key_file, encoded) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # --- + # --- - encoded = self.ref_public.export_key(format="OpenSSH") - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_public.export_key(format="OpenSSH", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_openssh_compressed(self): - key_file = load_file("ecc_p384_public_openssh.txt", "rt") - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) - assert len(key_file) > len(key_file_compressed) - self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") - - def test_compressed_curve(self): - - # Compressed P-384 curve (Y-point is even) - # openssl ecparam -name secp384p1 -genkey -noout -conv_form compressed -out /tmp/a.pem - # openssl ec -in /tmp/a.pem -text -noout - pem1 = """-----BEGIN EC PRIVATE KEY----- + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p384_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh_uncompressed(self): + key_file = load_file("ecc_p384_public_openssh.txt", "rt") + + encoded = self.ref_public._export_openssh(False) + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_public.export_key(format="OpenSSH") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="OpenSSH", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_openssh_compressed(self): + key_file = load_file("ecc_p384_public_openssh.txt", "rt") + pub_key = ECC.import_key(key_file) + + key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) + assert len(key_file) > len(key_file_compressed) + self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) + + def test_compressed_curve(self): + # Compressed P-384 curve (Y-point is even) + # openssl ecparam -name secp384p1 -genkey -noout -conv_form compressed -out /tmp/a.pem + # openssl ec -in /tmp/a.pem -text -noout + pem1 = """-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDAM0lEIhvXuekK2SWtdbgOcZtBaxa9TxfpO/GcDFZLCJ3JVXaTgwken QT+C+XLtD6WgBwYFK4EEACKhZANiAATs0kZMhFDu8DoBC21jrSDPyAUn4aXZ/DM4 ylhDfWmb4LEbeszXceIzfhIUaaGs5y1xXaqf5KXTiAAYx2pKUzAAM9lcGUHCGKJG k4AgUmVJON29XoUilcFrzjDmuye3B6Q= -----END EC PRIVATE KEY-----""" - # Compressed P-384 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-384 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDDHPFTslYLltE16fHdSDTtE/2HTmd3M8mqy5MttAm4wZ833KXiGS9oe kFdx9sNV0KygBwYFK4EEACKhZANiAASLIE5RqVMtNhtBH/u/p/ifqOAlKnK/+RrQ YC46ZRsnKNayw3wATdPjgja7L/DSII3nZK0G6KOOVwJBznT/e+zudUJYhZKaBLRx /bgXyxUtYClOXxb1Y/5N7txLstYRyP0= -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x07a4) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0x07A4) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0xc8fd) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0xC8FD) class TestExport_P521(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P521, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p521() - def __init__(self, *args, **kwargs): - super(TestExport_P521, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p521() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p521_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p521_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p521_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p521_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - encoded = self.ref_public.export_key(format="raw") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p521_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p521_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) - - encoded = self.ref_public.export_key(format="raw", compress=True) - self.assertEqual(value, encoded) - - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p521_private.der") - - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p521_public.der") - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p521_private_p8_clear.der") + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p521_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + key_file_compressed_ref = load_file("ecc_p521_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p521_public.der") + value = extract_bitstring_from_spki(key_file) - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - # --- + encoded = self.ref_public.export_key(format="raw") + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p521_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - # --- + key_file_compressed_ref = load_file("ecc_p521_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="raw", compress=True) + self.assertEqual(value, encoded) - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p521_public.pem", "rt").strip() + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p521_private.der") - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - # --- + # --- - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p521_private_p8_clear.der") - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p521_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p521_public_compressed.pem", "rt").strip() + # --- - self.assertEqual(key_file_compressed, key_file_compressed_ref) + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p521_private.pem", "rt").strip() + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - # --- + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + # --- - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + # --- - assert "EC PRIVATE KEY" in encoded + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p521_public.pem", "rt").strip() - # --- + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # --- - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p521_private_p8_clear.pem", "rt").strip() + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - # --- + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p521_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p521_public_compressed.pem", "rt").strip() - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p521_private.pem", "rt").strip() - assert "ENCRYPTED PRIVATE KEY" in encoded + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # --- - # --- + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") - def test_export_openssh_uncompressed(self): - key_file = load_file("ecc_p521_public_openssh.txt", "rt") + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) - encoded = self.ref_public._export_openssh(False) - self.assertEqual(key_file, encoded) + assert "EC PRIVATE KEY" in encoded - # --- + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_public.export_key(format="OpenSSH") - self.assertEqual(key_file, encoded) + # --- - encoded = self.ref_public.export_key(format="OpenSSH", compress=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - def test_export_openssh_compressed(self): - key_file = load_file("ecc_p521_public_openssh.txt", "rt") - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) - assert len(key_file) > len(key_file_compressed) - self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") - - def test_compressed_curve(self): - - # Compressed P-521 curve (Y-point is even) - # openssl ecparam -name secp521r1 -genkey -noout -conv_form compressed -out /tmp/a.pem - # openssl ec -in /tmp/a.pem -text -noout - pem1 = """-----BEGIN EC PRIVATE KEY----- + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p521_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh_uncompressed(self): + key_file = load_file("ecc_p521_public_openssh.txt", "rt") + + encoded = self.ref_public._export_openssh(False) + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_public.export_key(format="OpenSSH") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="OpenSSH", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_openssh_compressed(self): + key_file = load_file("ecc_p521_public_openssh.txt", "rt") + pub_key = ECC.import_key(key_file) + + key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) + assert len(key_file) > len(key_file_compressed) + self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) + + def test_compressed_curve(self): + # Compressed P-521 curve (Y-point is even) + # openssl ecparam -name secp521r1 -genkey -noout -conv_form compressed -out /tmp/a.pem + # openssl ec -in /tmp/a.pem -text -noout + pem1 = """-----BEGIN EC PRIVATE KEY----- MIHcAgEBBEIAnm1CEjVjvNfXEN730p+D6su5l+mOztdc5XmTEoti+s2R4GQ4mAv3 0zYLvyklvOHw0+yy8d0cyGEJGb8T3ZVKmg2gBwYFK4EEACOhgYkDgYYABAHzjTI1 ckxQ3Togi0LAxiG0PucdBBBs5oIy3df95xv6SInp70z+4qQ2EltEmdNMssH8eOrl @@ -2261,8 +2511,8 @@ def test_compressed_curve(self): uGxO8tM6r3w89/qzpG2SvFM/fvv3mIR30wSZDD84qA== -----END EC PRIVATE KEY-----""" - # Compressed P-521 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-521 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MIHcAgEBBEIB84OfhJluLBRLn3+cC/RQ37C2SfQVP/t0gQK2tCsTf5avRcWYRrOJ PmX9lNnkC0Hobd75QFRmdxrB0Wd1/M4jZOWgBwYFK4EEACOhgYkDgYYABAAMZcdJ 1YLCGHt3bHCEzdidVy6+brlJIbv1aQ9fPQLF7WKNv4c8w3H8d5a2+SDZilBOsk5c @@ -2270,513 +2520,589 @@ def test_compressed_curve(self): vv6oYkMIIi7r5oQWAiQDrR2mlrrFDL9V7GH/r8SWQw== -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x38a8) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0x38A8) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0x9643) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0x9643) class TestImport_Ed25519(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_Ed25519, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_ed25519() - def __init__(self, *args, **kwargs): - super(TestImport_Ed25519, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_ed25519() - - def test_import_public_der(self): - key_file = load_file("ecc_ed25519_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_ed25519_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_pkcs8_der(self): - key_file = load_file("ecc_ed25519_private.der") + def test_import_pkcs8_der(self): + key_file = load_file("ecc_ed25519_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_ed25519_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_ed25519_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_ed25519_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_ed25519_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_ed25519_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_ed25519_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_ed25519_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_ed25519_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_ed25519_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_ed25519_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_ed25519_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_ed25519_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256": - key_file = load_file("ecc_ed25519_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256": + key_file = load_file("ecc_ed25519_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_ed25519_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_ed25519_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_openssh_public(self): - key_file = load_file("ecc_ed25519_public_openssh.txt") - key = ECC._import_openssh_public(key_file) - self.assertFalse(key.has_private()) - key = ECC.import_key(key_file) - self.assertFalse(key.has_private()) + def test_import_openssh_public(self): + key_file = load_file("ecc_ed25519_public_openssh.txt") + key = ECC._import_openssh_public(key_file) + self.assertFalse(key.has_private()) + key = ECC.import_key(key_file) + self.assertFalse(key.has_private()) - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_ed25519_private_openssh.pem") - key = ECC.import_key(key_file) + def test_import_openssh_private_clear(self): + key_file = load_file("ecc_ed25519_private_openssh.pem") + key = ECC.import_key(key_file) - def test_import_openssh_private_password(self): - key_file = load_file("ecc_ed25519_private_openssh_pwd.pem") - key = ECC.import_key(key_file, b"password") + def test_import_openssh_private_password(self): + key_file = load_file("ecc_ed25519_private_openssh_pwd.pem") + key = ECC.import_key(key_file, b"password") class TestExport_Ed25519(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_Ed25519, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_ed25519() - def __init__(self, *args, **kwargs): - super(TestExport_Ed25519, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_ed25519() - - def test_export_public_der(self): - key_file = load_file("ecc_ed25519_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(True) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_sec1(self): - self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1") - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_ed25519_private.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - self.assertRaises(ValueError, self.ref_private.export_key, - format="DER", use_pkcs8=False) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- + def test_export_public_der(self): + key_file = load_file("ecc_ed25519_public.der") - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public._export_subjectPublicKeyInfo(True) + self.assertEqual(key_file, encoded) - def test_export_public_pem(self): - key_file_ref = load_file("ecc_ed25519_public.pem", "rt").strip() - key_file = self.ref_public.export_key(format="PEM").strip() - self.assertEqual(key_file_ref, key_file) + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_ed25519_private.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM").strip() - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_openssh(self): - key_file = load_file("ecc_ed25519_public_openssh.txt", "rt") - public_key = ECC.import_key(key_file) - key_file = " ".join(key_file.split(' ')[:2]) # remove comment - - encoded = public_key._export_openssh(False) - self.assertEqual(key_file, encoded.strip()) - - encoded = public_key.export_key(format="OpenSSH") - self.assertEqual(key_file, encoded.strip()) - - def test_export_raw(self): - encoded = self.ref_public.export_key(format='raw') - self.assertEqual(encoded, unhexlify(b'bc85b8cf585d20a4de47e84d1cb6183f63d9ba96223fcbc886e363ffdea20cff')) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_public_sec1(self): + self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1") + + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_ed25519_private.der") + + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) + + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + use_pkcs8=False, + ) + + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_public_pem(self): + key_file_ref = load_file("ecc_ed25519_public.pem", "rt").strip() + key_file = self.ref_public.export_key(format="PEM").strip() + self.assertEqual(key_file_ref, key_file) + + def test_export_private_pem_clear(self): + key_file = load_file("ecc_ed25519_private.pem", "rt").strip() + encoded = self.ref_private.export_key(format="PEM").strip() + self.assertEqual(key_file, encoded) + + def test_export_private_pem_encrypted(self): + encoded = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh(self): + key_file = load_file("ecc_ed25519_public_openssh.txt", "rt") + public_key = ECC.import_key(key_file) + key_file = " ".join(key_file.split(" ")[:2]) # remove comment + + encoded = public_key._export_openssh(False) + self.assertEqual(key_file, encoded.strip()) + + encoded = public_key.export_key(format="OpenSSH") + self.assertEqual(key_file, encoded.strip()) + + def test_export_raw(self): + encoded = self.ref_public.export_key(format="raw") + self.assertEqual( + encoded, unhexlify(b"bc85b8cf585d20a4de47e84d1cb6183f63d9ba96223fcbc886e363ffdea20cff") + ) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) class TestImport_Ed448(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_Ed448, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_ed448() - def __init__(self, *args, **kwargs): - super(TestImport_Ed448, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_ed448() - - def test_import_public_der(self): - key_file = load_file("ecc_ed448_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_ed448_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_pkcs8_der(self): - key_file = load_file("ecc_ed448_private.der") + def test_import_pkcs8_der(self): + key_file = load_file("ecc_ed448_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_ed448_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_ed448_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_ed448_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_ed448_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_ed448_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_ed448_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_ed448_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_ed448_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_ed448_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_ed448_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_ed448_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_ed448_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256": - key_file = load_file("ecc_ed448_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256": + key_file = load_file("ecc_ed448_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_ed448_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_ed448_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) class TestExport_Ed448(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestExport_Ed448, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_ed448() - - def test_export_public_der(self): - key_file = load_file("ecc_ed448_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(True) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_sec1(self): - self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1") - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_ed448_private.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - self.assertRaises(ValueError, self.ref_private.export_key, - format="DER", use_pkcs8=False) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA384AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - - def test_export_public_pem(self): - key_file_ref = load_file("ecc_ed448_public.pem", "rt").strip() - key_file = self.ref_public.export_key(format="PEM").strip() - self.assertEqual(key_file_ref, key_file) - - def test_export_private_pem_clear(self): - key_file = load_file("ecc_ed448_private.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM").strip() - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_openssh(self): - # Not supported - self.assertRaises(ValueError, self.ref_public.export_key, format="OpenSSH") - - def test_export_raw(self): - encoded = self.ref_public.export_key(format='raw') - self.assertEqual(encoded, unhexlify(b'899014ddc0a0e1260cfc1085afdf952019e9fd63372e3e366e26dad32b176624884330a14617237e3081febd9d1a15069e7499433d2f55dd80')) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") + def __init__(self, *args, **kwargs): + super(TestExport_Ed448, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_ed448() + + def test_export_public_der(self): + key_file = load_file("ecc_ed448_public.der") + + encoded = self.ref_public._export_subjectPublicKeyInfo(True) + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_public_sec1(self): + self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1") + + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_ed448_private.der") + + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) + + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + use_pkcs8=False, + ) + + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA384AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_public_pem(self): + key_file_ref = load_file("ecc_ed448_public.pem", "rt").strip() + key_file = self.ref_public.export_key(format="PEM").strip() + self.assertEqual(key_file_ref, key_file) + + def test_export_private_pem_clear(self): + key_file = load_file("ecc_ed448_private.pem", "rt").strip() + encoded = self.ref_private.export_key(format="PEM").strip() + self.assertEqual(key_file, encoded) + + def test_export_private_pem_encrypted(self): + encoded = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh(self): + # Not supported + self.assertRaises(ValueError, self.ref_public.export_key, format="OpenSSH") + + def test_export_raw(self): + encoded = self.ref_public.export_key(format="raw") + self.assertEqual( + encoded, + unhexlify( + b"899014ddc0a0e1260cfc1085afdf952019e9fd63372e3e366e26dad32b176624884330a14617237e3081febd9d1a15069e7499433d2f55dd80" + ), + ) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestImport) - try: - tests += list_test_cases(TestImport_P192) - tests += list_test_cases(TestImport_P224) - tests += list_test_cases(TestImport_P256) - tests += list_test_cases(TestImport_P384) - tests += list_test_cases(TestImport_P521) - tests += list_test_cases(TestImport_Ed25519) - tests += list_test_cases(TestImport_Ed448) - - tests += list_test_cases(TestExport_P192) - tests += list_test_cases(TestExport_P224) - tests += list_test_cases(TestExport_P256) - tests += list_test_cases(TestExport_P384) - tests += list_test_cases(TestExport_P521) - tests += list_test_cases(TestExport_Ed25519) - tests += list_test_cases(TestExport_Ed448) - - except MissingTestVectorException: - pass - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(TestImport) + try: + tests += list_test_cases(TestImport_P192) + tests += list_test_cases(TestImport_P224) + tests += list_test_cases(TestImport_P256) + tests += list_test_cases(TestImport_P384) + tests += list_test_cases(TestImport_P521) + tests += list_test_cases(TestImport_Ed25519) + tests += list_test_cases(TestImport_Ed448) + + tests += list_test_cases(TestExport_P192) + tests += list_test_cases(TestExport_P224) + tests += list_test_cases(TestExport_P256) + tests += list_test_cases(TestExport_P384) + tests += list_test_cases(TestExport_P521) + tests += list_test_cases(TestExport_Ed25519) + tests += list_test_cases(TestExport_Ed448) + + except MissingTestVectorException: + pass + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_RSA.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_RSA.py index b57676d0..ed976015 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_RSA.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/PublicKey/test_import_RSA.py @@ -35,50 +35,56 @@ from Cryptodome.Util import asn1 try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False def load_file(file_name, mode="rb"): - results = None + results = None + + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) + dir_comps = ("PublicKey", "RSA") + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name, mode) as file_in: + results = file_in.read() - dir_comps = ("PublicKey", "RSA") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() + except FileNotFoundError: + warnings.warn( + "Skipping tests for RSA based on %s" % file_name, + UserWarning, + stacklevel=2, + ) - except FileNotFoundError: - warnings.warn("Skipping tests for RSA based on %s" % file_name, - UserWarning, - stacklevel=2) + if results is None: + raise SkipTest("Missing %s" % file_name) - if results is None: - raise SkipTest("Missing %s" % file_name) + return results - return results +def der2pem(der, text="PUBLIC"): + import binascii -def der2pem(der, text='PUBLIC'): - import binascii - chunks = [binascii.b2a_base64(der[i:i+48]) for i in range(0, len(der), 48)] - pem = b('-----BEGIN %s KEY-----\n' % text) - pem += b('').join(chunks) - pem += b('-----END %s KEY-----' % text) - return pem + chunks = [binascii.b2a_base64(der[i : i + 48]) for i in range(0, len(der), 48)] + pem = b("-----BEGIN %s KEY-----\n" % text) + pem += b("").join(chunks) + pem += b("-----END %s KEY-----" % text) + return pem class ImportKeyTests(unittest.TestCase): - # 512-bit RSA key generated with openssl - rsaKeyPEM = u'''-----BEGIN RSA PRIVATE KEY----- + # 512-bit RSA key generated with openssl + rsaKeyPEM = """-----BEGIN RSA PRIVATE KEY----- MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8 Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI @@ -86,10 +92,10 @@ class ImportKeyTests(unittest.TestCase): +rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9 n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ== ------END RSA PRIVATE KEY-----''' +-----END RSA PRIVATE KEY-----""" - # As above, but this is actually an unencrypted PKCS#8 key - rsaKeyPEM8 = u'''-----BEGIN PRIVATE KEY----- + # As above, but this is actually an unencrypted PKCS#8 key + rsaKeyPEM8 = """-----BEGIN PRIVATE KEY----- MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvx4nkAqgiyNRGlwS ga5tkzEsPv6RP5MuvtSS8S0WtGEMMoy24girX0WsvilQgzKY8xIsGfeEkt7fQPDj wZAzhQIDAQABAkAJRIMSnxFN7fZ+2rwjAbxaiOXmYB3XAWIg6tn9S/xv3rdYk4mK @@ -98,14 +104,15 @@ class ImportKeyTests(unittest.TestCase): NwIhAIe+HDApUEvPNOxxPYd5R0R4EyiJdcokAICvewlAkbEhAiBqtGn6bVZIpXUx yLAxpM6dtTvDEWz0M/Wm9rvqVgHOBQIhAL2fQKdkInohlipK3Qfk3v5D7ZGjrie7 BX85JB8zqwHB ------END PRIVATE KEY-----''' - - # The same RSA private key as in rsaKeyPEM, but now encrypted - rsaKeyEncryptedPEM = ( - - # PEM encryption - # With DES and passphrase 'test' - ('test', u'''-----BEGIN RSA PRIVATE KEY----- +-----END PRIVATE KEY-----""" + + # The same RSA private key as in rsaKeyPEM, but now encrypted + rsaKeyEncryptedPEM = ( + # PEM encryption + # With DES and passphrase 'test' + ( + "test", + """-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-CBC,AF8F9A40BD2FA2FC @@ -116,10 +123,12 @@ class ImportKeyTests(unittest.TestCase): 9bMbdb/1PSvsSzPsqW7KSSrTw6MgJAFJg6lzIYvR5F4poTVBxwBX3+EyEmShiaNY IRX3TgQI0IjrVuLmvlZKbGWP18FXj7I7k9tSsNOOzllTTdq3ny5vgM3A+ynfAaxp dysKznQ6P+IoqML1WxAID4aGRMWka+uArOJ148Rbj9s= ------END RSA PRIVATE KEY-----'''), - - # PKCS8 encryption - ('winter', u'''-----BEGIN ENCRYPTED PRIVATE KEY----- +-----END RSA PRIVATE KEY-----""", + ), + # PKCS8 encryption + ( + "winter", + """-----BEGIN ENCRYPTED PRIVATE KEY----- MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeZIsbW3O+JcCAggA MBQGCCqGSIb3DQMHBAgSM2p0D8FilgSCAWBhFyP2tiGKVpGj3mO8qIBzinU60ApR 3unvP+N6j7LVgnV2lFGaXbJ6a1PbQXe+2D6DUyBLo8EMXrKKVLqOMGkFMHc0UaV6 @@ -129,21 +138,23 @@ class ImportKeyTests(unittest.TestCase): ntvgJwnCn2XR1h6LA8Wp+0ghDTsL2NhJpWd78zClGhyU4r3hqu1XDjoXa7YCXCix jCV15+ViDJzlNCwg+W6lRg18sSLkCT7alviIE0U5tHc6UPbbHwT5QqAxAABaP+nZ CGqJGyiwBzrKebjgSm/KRd4C91XqcsysyH2kKPfT51MLAoD4xelOURBP ------END ENCRYPTED PRIVATE KEY-----''' - ), - ) +-----END ENCRYPTED PRIVATE KEY-----""", + ), + ) - rsaPublicKeyPEM = u'''-----BEGIN PUBLIC KEY----- + rsaPublicKeyPEM = """-----BEGIN PUBLIC KEY----- MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+T Lr7UkvEtFrRhDDKMtuIIq19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQ== ------END PUBLIC KEY-----''' +-----END PUBLIC KEY-----""" - # Obtained using 'ssh-keygen -i -m PKCS8 -f rsaPublicKeyPEM' - rsaPublicKeyOpenSSH = b('''ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQC/HieQCqCLI1EaXBKBrm2TMSw+/pE/ky6+1JLxLRa0YQwyjLbiCKtfRay+KVCDMpjzEiwZ94SS3t9A8OPBkDOF comment\n''') + # Obtained using 'ssh-keygen -i -m PKCS8 -f rsaPublicKeyPEM' + rsaPublicKeyOpenSSH = b( + """ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQC/HieQCqCLI1EaXBKBrm2TMSw+/pE/ky6+1JLxLRa0YQwyjLbiCKtfRay+KVCDMpjzEiwZ94SS3t9A8OPBkDOF comment\n""" + ) - # The private key, in PKCS#1 format encoded with DER - rsaKeyDER = a2b_hex( - '''3082013b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe + # The private key, in PKCS#1 format encoded with DER + rsaKeyDER = a2b_hex( + """3082013b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe 913f932ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f312 2c19f78492dedf40f0e3c190338502030100010240094483129f114dedf6 7edabc2301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c @@ -154,11 +165,12 @@ class ImportKeyTests(unittest.TestCase): 240080af7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53b c3116cf433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07 e4defe43ed91a3ae27bb057f39241f33ab01c1 - '''.replace(" ","")) + """.replace(" ", ""), + ) - # The private key, in unencrypted PKCS#8 format encoded with DER - rsaKeyDER8 = a2b_hex( - '''30820155020100300d06092a864886f70d01010105000482013f3082013 + # The private key, in unencrypted PKCS#8 format encoded with DER + rsaKeyDER8 = a2b_hex( + """30820155020100300d06092a864886f70d01010105000482013f3082013 b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe913f932 ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f3122c19f78 492dedf40f0e3c190338502030100010240094483129f114dedf67edabc2 @@ -170,308 +182,340 @@ class ImportKeyTests(unittest.TestCase): f7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53bc3116cf 433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07e4defe4 3ed91a3ae27bb057f39241f33ab01c1 - '''.replace(" ","")) + """.replace(" ", ""), + ) - rsaPublicKeyDER = a2b_hex( - '''305c300d06092a864886f70d0101010500034b003048024100bf1e27900a + rsaPublicKeyDER = a2b_hex( + """305c300d06092a864886f70d0101010500034b003048024100bf1e27900a a08b23511a5c1281ae6d93312c3efe913f932ebed492f12d16b4610c328c b6e208ab5f45acbe2950833298f3122c19f78492dedf40f0e3c190338502 03010001 - '''.replace(" ","")) - - n = int('BF 1E 27 90 0A A0 8B 23 51 1A 5C 12 81 AE 6D 93 31 2C 3E FE 91 3F 93 2E BE D4 92 F1 2D 16 B4 61 0C 32 8C B6 E2 08 AB 5F 45 AC BE 29 50 83 32 98 F3 12 2C 19 F7 84 92 DE DF 40 F0 E3 C1 90 33 85'.replace(" ",""),16) - e = 65537 - d = int('09 44 83 12 9F 11 4D ED F6 7E DA BC 23 01 BC 5A 88 E5 E6 60 1D D7 01 62 20 EA D9 FD 4B FC 6F DE B7 58 93 89 8A E4 1C 54 DD BD BF 15 39 F8 CC BD 18 F6 7B 44 0D E1 AC 30 44 02 81 D4 0C FA C8 39'.replace(" ",""),16) - p = int('00 F2 0F 2F 3E 1D A6 18 83 F6 29 80 92 2B D8 DF 54 5C E4 07 C7 26 24 11 03 B5 E2 C5 37 23 12 4A 23'.replace(" ",""),16) - q = int('00 CA 1F E9 24 79 2C FC C9 6B FA B7 4F 34 4A 68 B4 18 DF 57 83 38 06 48 06 00 0F E2 A5 C9 9A 02 37'.replace(" ",""),16) - - # This is q^{-1} mod p). fastmath and slowmath use pInv (p^{-1} - # mod q) instead! - qInv = int('00 BD 9F 40 A7 64 22 7A 21 96 2A 4A DD 07 E4 DE FE 43 ED 91 A3 AE 27 BB 05 7F 39 24 1F 33 AB 01 C1'.replace(" ",""),16) - pInv = inverse(p,q) - - def testImportKey1(self): - """Verify import of RSAPrivateKey DER SEQUENCE""" - key = RSA.importKey(self.rsaKeyDER) - self.assertTrue(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey2(self): - """Verify import of SubjectPublicKeyInfo DER SEQUENCE""" - key = RSA.importKey(self.rsaPublicKeyDER) - self.assertFalse(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey3unicode(self): - """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" - key = RSA.importKey(self.rsaKeyPEM) - self.assertEqual(key.has_private(),True) # assert_ - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey3bytes(self): - """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as byte string""" - key = RSA.importKey(b(self.rsaKeyPEM)) - self.assertEqual(key.has_private(),True) # assert_ - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey4unicode(self): - """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" - key = RSA.importKey(self.rsaPublicKeyPEM) - self.assertEqual(key.has_private(),False) # assertFalse - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey4bytes(self): - """Verify import of SubjectPublicKeyInfo DER SEQUENCE, encoded with PEM as byte string""" - key = RSA.importKey(b(self.rsaPublicKeyPEM)) - self.assertEqual(key.has_private(),False) # assertFalse - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey5(self): - """Verifies that the imported key is still a valid RSA pair""" - key = RSA.importKey(self.rsaKeyPEM) - idem = key._encrypt(key._decrypt(89)) - self.assertEqual(idem, 89) - - def testImportKey6(self): - """Verifies that the imported key is still a valid RSA pair""" - key = RSA.importKey(self.rsaKeyDER) - idem = key._encrypt(key._decrypt(65)) - self.assertEqual(idem, 65) - - def testImportKey7(self): - """Verify import of OpenSSH public key""" - key = RSA.importKey(self.rsaPublicKeyOpenSSH) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey8(self): - """Verify import of encrypted PrivateKeyInfo DER SEQUENCE""" - for t in self.rsaKeyEncryptedPEM: - key = RSA.importKey(t[1], t[0]) - self.assertTrue(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey9(self): - """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE""" - key = RSA.importKey(self.rsaKeyDER8) - self.assertTrue(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey10(self): - """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE, encoded with PEM""" - key = RSA.importKey(self.rsaKeyPEM8) - self.assertTrue(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey11(self): - """Verify import of RSAPublicKey DER SEQUENCE""" - der = asn1.DerSequence([17, 3]).encode() - key = RSA.importKey(der) - self.assertEqual(key.n, 17) - self.assertEqual(key.e, 3) - - def testImportKey12(self): - """Verify import of RSAPublicKey DER SEQUENCE, encoded with PEM""" - der = asn1.DerSequence([17, 3]).encode() - pem = der2pem(der) - key = RSA.importKey(pem) - self.assertEqual(key.n, 17) - self.assertEqual(key.e, 3) - - def test_import_key_windows_cr_lf(self): - pem_cr_lf = "\r\n".join(self.rsaKeyPEM.splitlines()) - key = RSA.importKey(pem_cr_lf) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def test_import_empty(self): - self.assertRaises(ValueError, RSA.import_key, b"") - - ### - def testExportKey1(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - derKey = key.export_key("DER") - self.assertEqual(derKey, self.rsaKeyDER) - - def testExportKey2(self): - key = RSA.construct([self.n, self.e]) - derKey = key.export_key("DER") - self.assertEqual(derKey, self.rsaPublicKeyDER) - - def testExportKey3(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - pemKey = key.export_key("PEM") - self.assertEqual(pemKey, b(self.rsaKeyPEM)) - - def testExportKey4(self): - key = RSA.construct([self.n, self.e]) - pemKey = key.export_key("PEM") - self.assertEqual(pemKey, b(self.rsaPublicKeyPEM)) - - def testExportKey5(self): - key = RSA.construct([self.n, self.e]) - openssh_1 = key.export_key("OpenSSH").split() - openssh_2 = self.rsaPublicKeyOpenSSH.split() - self.assertEqual(openssh_1[0], openssh_2[0]) - self.assertEqual(openssh_1[1], openssh_2[1]) - - def testExportKey7(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - derKey = key.export_key("DER", pkcs=8) - self.assertEqual(derKey, self.rsaKeyDER8) - - def testExportKey8(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - pemKey = key.export_key("PEM", pkcs=8) - self.assertEqual(pemKey, b(self.rsaKeyPEM8)) - - def testExportKey9(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - self.assertRaises(ValueError, key.export_key, "invalid-format") - - def testExportKey10(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#1, old PEM encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test') - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')!=-1) - self.assertTrue(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey11(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#1, old PEM encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=1) - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')!=-1) - self.assertTrue(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey12(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#8, old PEM encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=8) - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')!=-1) - self.assertTrue(tostr(outkey).find('BEGIN PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey13(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#8, PKCS#8 encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=8, - protection='PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC') - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')==-1) - self.assertTrue(tostr(outkey).find('BEGIN ENCRYPTED PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey14(self): - # Export and re-import the encrypted key. It must match. - # DER envelope, PKCS#8, PKCS#8 encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('DER', 'test', pkcs=8) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey15(self): - # Verify that that error an condition is detected when trying to - # use a password with DER encoding and PKCS#1. - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - self.assertRaises(ValueError, key.export_key, 'DER', 'test', 1) - - def testExportKey16(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#8, PKCS#8 encryption with parameters - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=8, - protection='PBKDF2WithHMAC-SHA512AndAES256-CBC', - prot_params={'iteration_count':123} - ) - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')==-1) - self.assertTrue(tostr(outkey).find('BEGIN ENCRYPTED PRIVATE KEY')!=-1) - - # Verify the iteration count - der = PEM.decode(tostr(outkey))[0] - seq1 = asn1.DerSequence().decode(der) - seq2 = asn1.DerSequence().decode(seq1[0]) - seq3 = asn1.DerSequence().decode(seq2[1]) - seq4 = asn1.DerSequence().decode(seq3[0]) - seq5 = asn1.DerSequence().decode(seq4[1]) - self.assertEqual(seq5[1], 123) - - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def test_import_key(self): - """Verify that import_key is an alias to importKey""" - key = RSA.import_key(self.rsaPublicKeyDER) - self.assertFalse(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def test_import_key_ba_mv(self): - """Verify that import_key can be used on bytearrays and memoryviews""" - key = RSA.import_key(bytearray(self.rsaPublicKeyDER)) - key = RSA.import_key(memoryview(self.rsaPublicKeyDER)) - - def test_exportKey(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - self.assertEqual(key.export_key(), key.exportKey()) + """.replace(" ", ""), + ) + + n = int( + "BF 1E 27 90 0A A0 8B 23 51 1A 5C 12 81 AE 6D 93 31 2C 3E FE 91 3F 93 2E BE D4 92 F1 2D 16 B4 61 0C 32 8C B6 E2 08 AB 5F 45 AC BE 29 50 83 32 98 F3 12 2C 19 F7 84 92 DE DF 40 F0 E3 C1 90 33 85".replace( + " ", "" + ), + 16, + ) + e = 65537 + d = int( + "09 44 83 12 9F 11 4D ED F6 7E DA BC 23 01 BC 5A 88 E5 E6 60 1D D7 01 62 20 EA D9 FD 4B FC 6F DE B7 58 93 89 8A E4 1C 54 DD BD BF 15 39 F8 CC BD 18 F6 7B 44 0D E1 AC 30 44 02 81 D4 0C FA C8 39".replace( + " ", "" + ), + 16, + ) + p = int( + "00 F2 0F 2F 3E 1D A6 18 83 F6 29 80 92 2B D8 DF 54 5C E4 07 C7 26 24 11 03 B5 E2 C5 37 23 12 4A 23".replace( + " ", "" + ), + 16, + ) + q = int( + "00 CA 1F E9 24 79 2C FC C9 6B FA B7 4F 34 4A 68 B4 18 DF 57 83 38 06 48 06 00 0F E2 A5 C9 9A 02 37".replace( + " ", "" + ), + 16, + ) + + # This is q^{-1} mod p). fastmath and slowmath use pInv (p^{-1} + # mod q) instead! + qInv = int( + "00 BD 9F 40 A7 64 22 7A 21 96 2A 4A DD 07 E4 DE FE 43 ED 91 A3 AE 27 BB 05 7F 39 24 1F 33 AB 01 C1".replace( + " ", "" + ), + 16, + ) + pInv = inverse(p, q) + + def testImportKey1(self): + """Verify import of RSAPrivateKey DER SEQUENCE""" + key = RSA.importKey(self.rsaKeyDER) + self.assertTrue(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey2(self): + """Verify import of SubjectPublicKeyInfo DER SEQUENCE""" + key = RSA.importKey(self.rsaPublicKeyDER) + self.assertFalse(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey3unicode(self): + """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" + key = RSA.importKey(self.rsaKeyPEM) + self.assertEqual(key.has_private(), True) # assert_ + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey3bytes(self): + """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as byte string""" + key = RSA.importKey(b(self.rsaKeyPEM)) + self.assertEqual(key.has_private(), True) # assert_ + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey4unicode(self): + """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" + key = RSA.importKey(self.rsaPublicKeyPEM) + self.assertEqual(key.has_private(), False) # assertFalse + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey4bytes(self): + """Verify import of SubjectPublicKeyInfo DER SEQUENCE, encoded with PEM as byte string""" + key = RSA.importKey(b(self.rsaPublicKeyPEM)) + self.assertEqual(key.has_private(), False) # assertFalse + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey5(self): + """Verifies that the imported key is still a valid RSA pair""" + key = RSA.importKey(self.rsaKeyPEM) + idem = key._encrypt(key._decrypt(89)) + self.assertEqual(idem, 89) + + def testImportKey6(self): + """Verifies that the imported key is still a valid RSA pair""" + key = RSA.importKey(self.rsaKeyDER) + idem = key._encrypt(key._decrypt(65)) + self.assertEqual(idem, 65) + + def testImportKey7(self): + """Verify import of OpenSSH public key""" + key = RSA.importKey(self.rsaPublicKeyOpenSSH) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey8(self): + """Verify import of encrypted PrivateKeyInfo DER SEQUENCE""" + for t in self.rsaKeyEncryptedPEM: + key = RSA.importKey(t[1], t[0]) + self.assertTrue(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey9(self): + """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE""" + key = RSA.importKey(self.rsaKeyDER8) + self.assertTrue(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey10(self): + """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE, encoded with PEM""" + key = RSA.importKey(self.rsaKeyPEM8) + self.assertTrue(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey11(self): + """Verify import of RSAPublicKey DER SEQUENCE""" + der = asn1.DerSequence([17, 3]).encode() + key = RSA.importKey(der) + self.assertEqual(key.n, 17) + self.assertEqual(key.e, 3) + + def testImportKey12(self): + """Verify import of RSAPublicKey DER SEQUENCE, encoded with PEM""" + der = asn1.DerSequence([17, 3]).encode() + pem = der2pem(der) + key = RSA.importKey(pem) + self.assertEqual(key.n, 17) + self.assertEqual(key.e, 3) + + def test_import_key_windows_cr_lf(self): + pem_cr_lf = "\r\n".join(self.rsaKeyPEM.splitlines()) + key = RSA.importKey(pem_cr_lf) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def test_import_empty(self): + self.assertRaises(ValueError, RSA.import_key, b"") + + ### + def testExportKey1(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + derKey = key.export_key("DER") + self.assertEqual(derKey, self.rsaKeyDER) + + def testExportKey2(self): + key = RSA.construct([self.n, self.e]) + derKey = key.export_key("DER") + self.assertEqual(derKey, self.rsaPublicKeyDER) + + def testExportKey3(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + pemKey = key.export_key("PEM") + self.assertEqual(pemKey, b(self.rsaKeyPEM)) + + def testExportKey4(self): + key = RSA.construct([self.n, self.e]) + pemKey = key.export_key("PEM") + self.assertEqual(pemKey, b(self.rsaPublicKeyPEM)) + + def testExportKey5(self): + key = RSA.construct([self.n, self.e]) + openssh_1 = key.export_key("OpenSSH").split() + openssh_2 = self.rsaPublicKeyOpenSSH.split() + self.assertEqual(openssh_1[0], openssh_2[0]) + self.assertEqual(openssh_1[1], openssh_2[1]) + + def testExportKey7(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + derKey = key.export_key("DER", pkcs=8) + self.assertEqual(derKey, self.rsaKeyDER8) + + def testExportKey8(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + pemKey = key.export_key("PEM", pkcs=8) + self.assertEqual(pemKey, b(self.rsaKeyPEM8)) + + def testExportKey9(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + self.assertRaises(ValueError, key.export_key, "invalid-format") + + def testExportKey10(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#1, old PEM encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key("PEM", "test") + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") != -1) + self.assertTrue(tostr(outkey).find("BEGIN RSA PRIVATE KEY") != -1) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey11(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#1, old PEM encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key("PEM", "test", pkcs=1) + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") != -1) + self.assertTrue(tostr(outkey).find("BEGIN RSA PRIVATE KEY") != -1) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey12(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#8, old PEM encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key("PEM", "test", pkcs=8) + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") != -1) + self.assertTrue(tostr(outkey).find("BEGIN PRIVATE KEY") != -1) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey13(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#8, PKCS#8 encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key( + "PEM", + "test", + pkcs=8, + protection="PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC", + ) + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") == -1) + self.assertTrue(tostr(outkey).find("BEGIN ENCRYPTED PRIVATE KEY") != -1) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey14(self): + # Export and re-import the encrypted key. It must match. + # DER envelope, PKCS#8, PKCS#8 encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key("DER", "test", pkcs=8) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey15(self): + # Verify that that error an condition is detected when trying to + # use a password with DER encoding and PKCS#1. + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + self.assertRaises(ValueError, key.export_key, "DER", "test", 1) + + def testExportKey16(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#8, PKCS#8 encryption with parameters + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key( + "PEM", + "test", + pkcs=8, + protection="PBKDF2WithHMAC-SHA512AndAES256-CBC", + prot_params={"iteration_count": 123}, + ) + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") == -1) + self.assertTrue(tostr(outkey).find("BEGIN ENCRYPTED PRIVATE KEY") != -1) + + # Verify the iteration count + der = PEM.decode(tostr(outkey))[0] + seq1 = asn1.DerSequence().decode(der) + seq2 = asn1.DerSequence().decode(seq1[0]) + seq3 = asn1.DerSequence().decode(seq2[1]) + seq4 = asn1.DerSequence().decode(seq3[0]) + seq5 = asn1.DerSequence().decode(seq4[1]) + self.assertEqual(seq5[1], 123) + + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def test_import_key(self): + """Verify that import_key is an alias to importKey""" + key = RSA.import_key(self.rsaPublicKeyDER) + self.assertFalse(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def test_import_key_ba_mv(self): + """Verify that import_key can be used on bytearrays and memoryviews""" + key = RSA.import_key(bytearray(self.rsaPublicKeyDER)) + key = RSA.import_key(memoryview(self.rsaPublicKeyDER)) + + def test_exportKey(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + self.assertEqual(key.export_key(), key.exportKey()) class ImportKeyFromX509Cert(unittest.TestCase): - - def test_x509v1(self): - - # Sample V1 certificate with a 1024 bit RSA key - x509_v1_cert = """ + def test_x509v1(self): + # Sample V1 certificate with a 1024 bit RSA key + x509_v1_cert = """ -----BEGIN CERTIFICATE----- MIICOjCCAaMCAQEwDQYJKoZIhvcNAQEEBQAwfjENMAsGA1UEChMEQWNtZTELMAkG A1UECxMCUkQxHDAaBgkqhkiG9w0BCQEWDXNwYW1AYWNtZS5vcmcxEzARBgNVBAcT @@ -488,9 +532,9 @@ def test_x509v1(self): -----END CERTIFICATE----- """.strip() - # RSA public key as dumped by openssl - exponent = 65537 - modulus_str = """ + # RSA public key as dumped by openssl + exponent = 65537 + modulus_str = """ 00:c8:6f:a4:ca:d7:51:8f:74:c5:6d:19:87:0d:8a: 77:4d:7b:a0:55:0f:35:72:17:b0:d2:a7:8e:c5:95: 8e:cf:cd:08:8e:d5:a9:81:d3:9a:0a:f2:96:34:2b: @@ -501,17 +545,16 @@ def test_x509v1(self): a3:18:d0:da:95:9f:05:d6:99:37:db:e0:81:b3:c8: 75:c4:dc:79:0f:2c:6e:10:75 """ - modulus = int(re.sub("[^0-9a-f]","", modulus_str), 16) - - key = RSA.importKey(x509_v1_cert) - self.assertEqual(key.e, exponent) - self.assertEqual(key.n, modulus) - self.assertFalse(key.has_private()) + modulus = int(re.sub("[^0-9a-f]", "", modulus_str), 16) - def test_x509v3(self): + key = RSA.importKey(x509_v1_cert) + self.assertEqual(key.e, exponent) + self.assertEqual(key.n, modulus) + self.assertFalse(key.has_private()) - # Sample V3 certificate with a 1024 bit RSA key - x509_v3_cert = """ + def test_x509v3(self): + # Sample V3 certificate with a 1024 bit RSA key + x509_v3_cert = """ -----BEGIN CERTIFICATE----- MIIEcjCCAlqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL MAkGA1UECAwCTUQxEjAQBgNVBAcMCUJhbHRpbW9yZTEQMA4GA1UEAwwHVGVzdCBD @@ -540,9 +583,9 @@ def test_x509v3(self): -----END CERTIFICATE----- """.strip() - # RSA public key as dumped by openssl - exponent = 65537 - modulus_str = """ + # RSA public key as dumped by openssl + exponent = 65537 + modulus_str = """ 00:fd:2e:c6:25:5d:8e:70:57:72:34:c4:38:2b:be: 4a:ad:81:6d:30:49:f7:56:71:05:74:f1:da:8f:24: b7:ed:79:4c:c5:28:74:a1:2e:06:79:31:95:50:22: @@ -553,84 +596,85 @@ def test_x509v3(self): eb:3d:0f:fb:78:07:5d:cc:a5:2b:cf:06:9c:55:b9: d6:fa:d8:36:42:d4:97:29:17 """ - modulus = int(re.sub("[^0-9a-f]","", modulus_str), 16) + modulus = int(re.sub("[^0-9a-f]", "", modulus_str), 16) - key = RSA.importKey(x509_v3_cert) - self.assertEqual(key.e, exponent) - self.assertEqual(key.n, modulus) - self.assertFalse(key.has_private()) + key = RSA.importKey(x509_v3_cert) + self.assertEqual(key.e, exponent) + self.assertEqual(key.n, modulus) + self.assertFalse(key.has_private()) class TestImport_2048(unittest.TestCase): + def test_import_pss(self): + pub_key_file = load_file("rsa2048_pss_public.pem") + pub_key = RSA.import_key(pub_key_file) - def test_import_pss(self): - pub_key_file = load_file("rsa2048_pss_public.pem") - pub_key = RSA.import_key(pub_key_file) - - priv_key_file = load_file("rsa2048_pss_private.pem") - priv_key = RSA.import_key(priv_key_file) + priv_key_file = load_file("rsa2048_pss_private.pem") + priv_key = RSA.import_key(priv_key_file) - self.assertEqual(pub_key.n, priv_key.n) + self.assertEqual(pub_key.n, priv_key.n) - def test_import_openssh_public(self): - key_file_ref = load_file("rsa2048_private.pem") - key_file = load_file("rsa2048_public_openssh.txt") + def test_import_openssh_public(self): + key_file_ref = load_file("rsa2048_private.pem") + key_file = load_file("rsa2048_public_openssh.txt") - # Skip test if test vectors are not installed - if None in (key_file_ref, key_file): - return + # Skip test if test vectors are not installed + if None in (key_file_ref, key_file): + return - key_ref = RSA.import_key(key_file_ref).public_key() - key = RSA.import_key(key_file) - self.assertEqual(key_ref, key) + key_ref = RSA.import_key(key_file_ref).public_key() + key = RSA.import_key(key_file) + self.assertEqual(key_ref, key) - def test_import_openssh_private_clear(self): - key_file = load_file("rsa2048_private_openssh.pem") - key_file_old = load_file("rsa2048_private_openssh_old.pem") + def test_import_openssh_private_clear(self): + key_file = load_file("rsa2048_private_openssh.pem") + key_file_old = load_file("rsa2048_private_openssh_old.pem") - # Skip test if test vectors are not installed - if None in (key_file_old, key_file): - return + # Skip test if test vectors are not installed + if None in (key_file_old, key_file): + return - key = RSA.import_key(key_file) - key_old = RSA.import_key(key_file_old) + key = RSA.import_key(key_file) + key_old = RSA.import_key(key_file_old) - self.assertEqual(key, key_old) + self.assertEqual(key, key_old) - def test_import_openssh_private_password(self): - key_file = load_file("rsa2048_private_openssh_pwd.pem") - key_file_old = load_file("rsa2048_private_openssh_pwd_old.pem") + def test_import_openssh_private_password(self): + key_file = load_file("rsa2048_private_openssh_pwd.pem") + key_file_old = load_file("rsa2048_private_openssh_pwd_old.pem") - # Skip test if test vectors are not installed - if None in (key_file_old, key_file): - return + # Skip test if test vectors are not installed + if None in (key_file_old, key_file): + return - key = RSA.import_key(key_file, b"password") - key_old = RSA.import_key(key_file_old) - self.assertEqual(key, key_old) + key = RSA.import_key(key_file, b"password") + key_old = RSA.import_key(key_file_old) + self.assertEqual(key, key_old) - def test_import_pkcs8_private(self): - key_file_ref = load_file("rsa2048_private.pem") - key_file = load_file("rsa2048_private_p8.der") + def test_import_pkcs8_private(self): + key_file_ref = load_file("rsa2048_private.pem") + key_file = load_file("rsa2048_private_p8.der") - # Skip test if test vectors are not installed - if None in (key_file_ref, key_file): - return + # Skip test if test vectors are not installed + if None in (key_file_ref, key_file): + return - key_ref = RSA.import_key(key_file_ref) - key = RSA.import_key(key_file, b'secret') - self.assertEqual(key_ref, key) + key_ref = RSA.import_key(key_file_ref) + key = RSA.import_key(key_file, b"secret") + self.assertEqual(key_ref, key) def get_tests(config={}): - tests = [] - tests += list_test_cases(ImportKeyTests) - tests += list_test_cases(ImportKeyFromX509Cert) - tests += list_test_cases(TestImport_2048) - return tests + tests = [] + tests += list_test_cases(ImportKeyTests) + tests += list_test_cases(ImportKeyFromX509Cert) + tests += list_test_cases(TestImport_2048) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Random/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Random/__init__.py index 763ee9c4..492a0fef 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Random/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Random/__init__.py @@ -26,14 +26,19 @@ __revision__ = "$Id$" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Random import test_random; tests += test_random.get_tests(config=config) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + from Cryptodome.SelfTest.Random import test_random + + tests += test_random.get_tests(config=config) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Random/test_random.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Random/test_random.py index 30e9194e..6422fb69 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Random/test_random.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Random/test_random.py @@ -28,140 +28,145 @@ import unittest from Cryptodome.Util.py3compat import b + class SimpleTest(unittest.TestCase): - def runTest(self): - """Cryptodome.Random.new()""" - # Import the Random module and try to use it - from Cryptodome import Random - randobj = Random.new() - x = randobj.read(16) - y = randobj.read(16) - self.assertNotEqual(x, y) - z = Random.get_random_bytes(16) - self.assertNotEqual(x, z) - self.assertNotEqual(y, z) - # Test the Random.random module, which - # implements a subset of Python's random API - # Not implemented: - # seed(), getstate(), setstate(), jumpahead() - # random(), uniform(), triangular(), betavariate() - # expovariate(), gammavariate(), gauss(), - # longnormvariate(), normalvariate(), - # vonmisesvariate(), paretovariate() - # weibullvariate() - # WichmannHill(), whseed(), SystemRandom() - from Cryptodome.Random import random - x = random.getrandbits(16*8) - y = random.getrandbits(16*8) - self.assertNotEqual(x, y) - # Test randrange - if x>y: - start = y - stop = x - else: - start = x - stop = y - for step in range(1,10): - x = random.randrange(start,stop,step) - y = random.randrange(start,stop,step) - self.assertNotEqual(x, y) - self.assertEqual(start <= x < stop, True) - self.assertEqual(start <= y < stop, True) - self.assertEqual((x - start) % step, 0) - self.assertEqual((y - start) % step, 0) - for i in range(10): - self.assertEqual(random.randrange(1,2), 1) - self.assertRaises(ValueError, random.randrange, start, start) - self.assertRaises(ValueError, random.randrange, stop, start, step) - self.assertRaises(TypeError, random.randrange, start, stop, step, step) - self.assertRaises(TypeError, random.randrange, start, stop, "1") - self.assertRaises(TypeError, random.randrange, "1", stop, step) - self.assertRaises(TypeError, random.randrange, 1, "2", step) - self.assertRaises(ValueError, random.randrange, start, stop, 0) - # Test randint - x = random.randint(start,stop) - y = random.randint(start,stop) - self.assertNotEqual(x, y) - self.assertEqual(start <= x <= stop, True) - self.assertEqual(start <= y <= stop, True) - for i in range(10): - self.assertEqual(random.randint(1,1), 1) - self.assertRaises(ValueError, random.randint, stop, start) - self.assertRaises(TypeError, random.randint, start, stop, step) - self.assertRaises(TypeError, random.randint, "1", stop) - self.assertRaises(TypeError, random.randint, 1, "2") - # Test choice - seq = range(10000) - x = random.choice(seq) - y = random.choice(seq) - self.assertNotEqual(x, y) - self.assertEqual(x in seq, True) - self.assertEqual(y in seq, True) - for i in range(10): - self.assertEqual(random.choice((1,2,3)) in (1,2,3), True) - self.assertEqual(random.choice([1,2,3]) in [1,2,3], True) - if sys.version_info[0] == 3: - self.assertEqual(random.choice(bytearray(b('123'))) in bytearray(b('123')), True) - self.assertEqual(1, random.choice([1])) - self.assertRaises(IndexError, random.choice, []) - self.assertRaises(TypeError, random.choice, 1) - # Test shuffle. Lacks random parameter to specify function. - # Make copies of seq - seq = range(500) - x = list(seq) - y = list(seq) - random.shuffle(x) - random.shuffle(y) - self.assertNotEqual(x, y) - self.assertEqual(len(seq), len(x)) - self.assertEqual(len(seq), len(y)) - for i in range(len(seq)): - self.assertEqual(x[i] in seq, True) - self.assertEqual(y[i] in seq, True) - self.assertEqual(seq[i] in x, True) - self.assertEqual(seq[i] in y, True) - z = [1] - random.shuffle(z) - self.assertEqual(z, [1]) - if sys.version_info[0] == 3: - z = bytearray(b('12')) - random.shuffle(z) - self.assertEqual(b('1') in z, True) - self.assertRaises(TypeError, random.shuffle, b('12')) - self.assertRaises(TypeError, random.shuffle, 1) - self.assertRaises(TypeError, random.shuffle, "11") - self.assertRaises(TypeError, random.shuffle, (1,2)) - # 2to3 wraps a list() around it, alas - but I want to shoot - # myself in the foot here! :D - # if sys.version_info[0] == 3: - # self.assertRaises(TypeError, random.shuffle, range(3)) - # Test sample - x = random.sample(seq, 20) - y = random.sample(seq, 20) - self.assertNotEqual(x, y) - for i in range(20): - self.assertEqual(x[i] in seq, True) - self.assertEqual(y[i] in seq, True) - z = random.sample([1], 1) - self.assertEqual(z, [1]) - z = random.sample((1,2,3), 1) - self.assertEqual(z[0] in (1,2,3), True) - z = random.sample("123", 1) - self.assertEqual(z[0] in "123", True) - z = random.sample(range(3), 1) - self.assertEqual(z[0] in range(3), True) - if sys.version_info[0] == 3: - z = random.sample(b("123"), 1) - self.assertEqual(z[0] in b("123"), True) - z = random.sample(bytearray(b("123")), 1) - self.assertEqual(z[0] in bytearray(b("123")), True) - self.assertRaises(TypeError, random.sample, 1) + def runTest(self): + """Cryptodome.Random.new()""" + # Import the Random module and try to use it + from Cryptodome import Random + + randobj = Random.new() + x = randobj.read(16) + y = randobj.read(16) + self.assertNotEqual(x, y) + z = Random.get_random_bytes(16) + self.assertNotEqual(x, z) + self.assertNotEqual(y, z) + # Test the Random.random module, which + # implements a subset of Python's random API + # Not implemented: + # seed(), getstate(), setstate(), jumpahead() + # random(), uniform(), triangular(), betavariate() + # expovariate(), gammavariate(), gauss(), + # longnormvariate(), normalvariate(), + # vonmisesvariate(), paretovariate() + # weibullvariate() + # WichmannHill(), whseed(), SystemRandom() + from Cryptodome.Random import random + + x = random.getrandbits(16 * 8) + y = random.getrandbits(16 * 8) + self.assertNotEqual(x, y) + # Test randrange + if x > y: + start = y + stop = x + else: + start = x + stop = y + for step in range(1, 10): + x = random.randrange(start, stop, step) + y = random.randrange(start, stop, step) + self.assertNotEqual(x, y) + self.assertEqual(start <= x < stop, True) + self.assertEqual(start <= y < stop, True) + self.assertEqual((x - start) % step, 0) + self.assertEqual((y - start) % step, 0) + for i in range(10): + self.assertEqual(random.randrange(1, 2), 1) + self.assertRaises(ValueError, random.randrange, start, start) + self.assertRaises(ValueError, random.randrange, stop, start, step) + self.assertRaises(TypeError, random.randrange, start, stop, step, step) + self.assertRaises(TypeError, random.randrange, start, stop, "1") + self.assertRaises(TypeError, random.randrange, "1", stop, step) + self.assertRaises(TypeError, random.randrange, 1, "2", step) + self.assertRaises(ValueError, random.randrange, start, stop, 0) + # Test randint + x = random.randint(start, stop) + y = random.randint(start, stop) + self.assertNotEqual(x, y) + self.assertEqual(start <= x <= stop, True) + self.assertEqual(start <= y <= stop, True) + for i in range(10): + self.assertEqual(random.randint(1, 1), 1) + self.assertRaises(ValueError, random.randint, stop, start) + self.assertRaises(TypeError, random.randint, start, stop, step) + self.assertRaises(TypeError, random.randint, "1", stop) + self.assertRaises(TypeError, random.randint, 1, "2") + # Test choice + seq = range(10000) + x = random.choice(seq) + y = random.choice(seq) + self.assertNotEqual(x, y) + self.assertEqual(x in seq, True) + self.assertEqual(y in seq, True) + for i in range(10): + self.assertEqual(random.choice((1, 2, 3)) in (1, 2, 3), True) + self.assertEqual(random.choice([1, 2, 3]) in [1, 2, 3], True) + if sys.version_info[0] == 3: + self.assertEqual(random.choice(bytearray(b("123"))) in bytearray(b("123")), True) + self.assertEqual(1, random.choice([1])) + self.assertRaises(IndexError, random.choice, []) + self.assertRaises(TypeError, random.choice, 1) + # Test shuffle. Lacks random parameter to specify function. + # Make copies of seq + seq = range(500) + x = list(seq) + y = list(seq) + random.shuffle(x) + random.shuffle(y) + self.assertNotEqual(x, y) + self.assertEqual(len(seq), len(x)) + self.assertEqual(len(seq), len(y)) + for i in range(len(seq)): + self.assertEqual(x[i] in seq, True) + self.assertEqual(y[i] in seq, True) + self.assertEqual(seq[i] in x, True) + self.assertEqual(seq[i] in y, True) + z = [1] + random.shuffle(z) + self.assertEqual(z, [1]) + if sys.version_info[0] == 3: + z = bytearray(b("12")) + random.shuffle(z) + self.assertEqual(b("1") in z, True) + self.assertRaises(TypeError, random.shuffle, b("12")) + self.assertRaises(TypeError, random.shuffle, 1) + self.assertRaises(TypeError, random.shuffle, "11") + self.assertRaises(TypeError, random.shuffle, (1, 2)) + # 2to3 wraps a list() around it, alas - but I want to shoot + # myself in the foot here! :D + # if sys.version_info[0] == 3: + # self.assertRaises(TypeError, random.shuffle, range(3)) + # Test sample + x = random.sample(seq, 20) + y = random.sample(seq, 20) + self.assertNotEqual(x, y) + for i in range(20): + self.assertEqual(x[i] in seq, True) + self.assertEqual(y[i] in seq, True) + z = random.sample([1], 1) + self.assertEqual(z, [1]) + z = random.sample((1, 2, 3), 1) + self.assertEqual(z[0] in (1, 2, 3), True) + z = random.sample("123", 1) + self.assertEqual(z[0] in "123", True) + z = random.sample(range(3), 1) + self.assertEqual(z[0] in range(3), True) + if sys.version_info[0] == 3: + z = random.sample(b("123"), 1) + self.assertEqual(z[0] in b("123"), True) + z = random.sample(bytearray(b("123")), 1) + self.assertEqual(z[0] in bytearray(b("123")), True) + self.assertRaises(TypeError, random.sample, 1) + def get_tests(config={}): - return [SimpleTest()] + return [SimpleTest()] + -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/__init__.py index 83cf0f39..90eff314 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/__init__.py @@ -27,15 +27,17 @@ def get_tests(config={}): - tests = [] - tests += test_pkcs1_15.get_tests(config=config) - tests += test_pss.get_tests(config=config) - tests += test_dss.get_tests(config=config) - tests += test_eddsa.get_tests(config=config) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += test_pkcs1_15.get_tests(config=config) + tests += test_pss.get_tests(config=config) + tests += test_dss.get_tests(config=config) + tests += test_eddsa.get_tests(config=config) + return tests + + +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_dss.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_dss.py index 156ee67a..70aba52b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_dss.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_dss.py @@ -37,8 +37,17 @@ from Cryptodome.Util.py3compat import tobytes, bord, bchr -from Cryptodome.Hash import (SHA1, SHA224, SHA256, SHA384, SHA512, - SHA3_224, SHA3_256, SHA3_384, SHA3_512) +from Cryptodome.Hash import ( + SHA1, + SHA224, + SHA256, + SHA384, + SHA512, + SHA3_224, + SHA3_256, + SHA3_384, + SHA3_512, +) from Cryptodome.Signature import DSS from Cryptodome.PublicKey import DSA, ECC from Cryptodome.SelfTest.st_common import list_test_cases @@ -47,364 +56,386 @@ def t2b(hexstring): - ws = hexstring.replace(" ", "").replace("\n", "") - return unhexlify(tobytes(ws)) + ws = hexstring.replace(" ", "").replace("\n", "") + return unhexlify(tobytes(ws)) def t2l(hexstring): - ws = hexstring.replace(" ", "").replace("\n", "") - return int(ws, 16) + ws = hexstring.replace(" ", "").replace("\n", "") + return int(ws, 16) def load_hash_by_name(hash_name): - return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) + return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) class StrRNG: + def __init__(self, randomness): + length = len(randomness) + self._idx = 0 + # Fix required to get the right K (see how randint() works!) + self._randomness = long_to_bytes(bytes_to_long(randomness) - 1, length) - def __init__(self, randomness): - length = len(randomness) - self._idx = 0 - # Fix required to get the right K (see how randint() works!) - self._randomness = long_to_bytes(bytes_to_long(randomness) - 1, length) - - def __call__(self, n): - out = self._randomness[self._idx:self._idx + n] - self._idx += n - return out + def __call__(self, n): + out = self._randomness[self._idx : self._idx + n] + self._idx += n + return out class FIPS_DSA_Tests(unittest.TestCase): + # 1st 1024 bit key from SigGen.txt + P = 0xA8F9CD201E5E35D892F85F80E4DB2599A5676A3B1D4F190330ED3256B26D0E80A0E49A8FFFAAAD2A24F472D2573241D4D6D6C7480C80B4C67BB4479C15ADA7EA8424D2502FA01472E760241713DAB025AE1B02E1703A1435F62DDF4EE4C1B664066EB22F2E3BF28BB70A2A76E4FD5EBE2D1229681B5B06439AC9C7E9D8BDE283 + Q = 0xF85F0F83AC4DF7EA0CDF8F469BFEEAEA14156495 + G = 0x2B3152FF6C62F14622B8F48E59F8AF46883B38E79B8C74DEEAE9DF131F8B856E3AD6C8455DAB87CC0DA8AC973417CE4F7878557D6CDF40B35B4A0CA3EB310C6A95D68CE284AD4E25EA28591611EE08B8444BD64B25F3F7C572410DDFB39CC728B9C936F85F419129869929CDB909A6A3A99BBE089216368171BD0BA81DE4FE33 + X = 0xC53EAE6D45323164C7D07AF5715703744A63FC3A + Y = 0x313FD9EBCA91574E1C2EEBE1517C57E0C21B0209872140C5328761BBB2450B33F1B18B409CE9AB7C4CD8FDA3391E8E34868357C199E16A6B2EBA06D6749DEF791D79E95D3A4D09B24C392AD89DBF100995AE19C01062056BB14BCE005E8731EFDE175F95B975089BDCDAEA562B32786D96F5A31AEDF75364008AD4FFFEBB970B - # 1st 1024 bit key from SigGen.txt - P = 0xa8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed3256b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b02e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd5ebe2d1229681b5b06439ac9c7e9d8bde283 - Q = 0xf85f0f83ac4df7ea0cdf8f469bfeeaea14156495 - G = 0x2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df131f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909a6a3a99bbe089216368171bd0ba81de4fe33 - X = 0xc53eae6d45323164c7d07af5715703744a63fc3a - Y = 0x313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761bbb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae19c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32786d96f5a31aedf75364008ad4fffebb970b - - key_pub = DSA.construct((Y, G, P, Q)) - key_priv = DSA.construct((Y, G, P, Q, X)) + key_pub = DSA.construct((Y, G, P, Q)) + key_priv = DSA.construct((Y, G, P, Q, X)) - def shortDescription(self): - return "FIPS DSA Tests" + def shortDescription(self): + return "FIPS DSA Tests" - def test_loopback(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv, 'fips-186-3') - signature = signer.sign(hashed_msg) + def test_loopback(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv, "fips-186-3") + signature = signer.sign(hashed_msg) - verifier = DSS.new(self.key_pub, 'fips-186-3') - verifier.verify(hashed_msg, signature) + verifier = DSS.new(self.key_pub, "fips-186-3") + verifier.verify(hashed_msg, signature) - def test_negative_unapproved_hashes(self): - """Verify that unapproved hashes are rejected""" + def test_negative_unapproved_hashes(self): + """Verify that unapproved hashes are rejected""" - from Cryptodome.Hash import RIPEMD160 + from Cryptodome.Hash import RIPEMD160 - self.description = "Unapproved hash (RIPEMD160) test" - hash_obj = RIPEMD160.new() - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertRaises(ValueError, signer.sign, hash_obj) - self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) + self.description = "Unapproved hash (RIPEMD160) test" + hash_obj = RIPEMD160.new() + signer = DSS.new(self.key_priv, "fips-186-3") + self.assertRaises(ValueError, signer.sign, hash_obj) + self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) - def test_negative_unknown_modes_encodings(self): - """Verify that unknown modes/encodings are rejected""" + def test_negative_unknown_modes_encodings(self): + """Verify that unknown modes/encodings are rejected""" - self.description = "Unknown mode test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-0') + self.description = "Unknown mode test" + self.assertRaises(ValueError, DSS.new, self.key_priv, "fips-186-0") - self.description = "Unknown encoding test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-3', 'xml') + self.description = "Unknown encoding test" + self.assertRaises(ValueError, DSS.new, self.key_priv, "fips-186-3", "xml") - def test_asn1_encoding(self): - """Verify ASN.1 encoding""" + def test_asn1_encoding(self): + """Verify ASN.1 encoding""" - self.description = "ASN.1 encoding test" - hash_obj = SHA1.new() - signer = DSS.new(self.key_priv, 'fips-186-3', 'der') - signature = signer.sign(hash_obj) + self.description = "ASN.1 encoding test" + hash_obj = SHA1.new() + signer = DSS.new(self.key_priv, "fips-186-3", "der") + signature = signer.sign(hash_obj) - # Verify that output looks like a DER SEQUENCE - self.assertEqual(bord(signature[0]), 48) - signer.verify(hash_obj, signature) + # Verify that output looks like a DER SEQUENCE + self.assertEqual(bord(signature[0]), 48) + signer.verify(hash_obj, signature) - # Verify that ASN.1 parsing fails as expected - signature = bchr(7) + signature[1:] - self.assertRaises(ValueError, signer.verify, hash_obj, signature) + # Verify that ASN.1 parsing fails as expected + signature = bchr(7) + signature[1:] + self.assertRaises(ValueError, signer.verify, hash_obj, signature) - def test_sign_verify(self): - """Verify public/private method""" + def test_sign_verify(self): + """Verify public/private method""" - self.description = "can_sign() test" - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertTrue(signer.can_sign()) + self.description = "can_sign() test" + signer = DSS.new(self.key_priv, "fips-186-3") + self.assertTrue(signer.can_sign()) - signer = DSS.new(self.key_pub, 'fips-186-3') - self.assertFalse(signer.can_sign()) + signer = DSS.new(self.key_pub, "fips-186-3") + self.assertFalse(signer.can_sign()) - try: - signer.sign(SHA256.new(b'xyz')) - except TypeError as e: - msg = str(e) - else: - msg = "" - self.assertTrue("Private key is needed" in msg) + try: + signer.sign(SHA256.new(b"xyz")) + except TypeError as e: + msg = str(e) + else: + msg = "" + self.assertTrue("Private key is needed" in msg) class FIPS_DSA_Tests_KAT(unittest.TestCase): - pass + pass -test_vectors_verify = load_test_vectors(("Signature", "DSA"), - "FIPS_186_3_SigVer.rsp", - "Signature Verification 186-3", - {'result': lambda x: x}) or [] +test_vectors_verify = ( + load_test_vectors( + ("Signature", "DSA"), + "FIPS_186_3_SigVer.rsp", + "Signature Verification 186-3", + {"result": lambda x: x}, + ) + or [] +) for idx, tv in enumerate(test_vectors_verify): - - if isinstance(tv, str): - res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) - assert(res) - hash_name = res.group(3).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue - - if hasattr(tv, "p"): - modulus = tv.p - generator = tv.g - suborder = tv.q - continue - - hash_obj = hash_module.new(tv.msg) - - comps = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder)] - key = DSA.construct(comps, False) # type: ignore - verifier = DSS.new(key, 'fips-186-3') - - def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result == 'p': - setattr(FIPS_DSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) - else: - setattr(FIPS_DSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) - - -test_vectors_sign = load_test_vectors(("Signature", "DSA"), - "FIPS_186_3_SigGen.txt", - "Signature Creation 186-3", - {}) or [] + if isinstance(tv, str): + res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) + assert res + hash_name = res.group(3).replace("-", "") + hash_module = load_hash_by_name(hash_name) + continue + + if hasattr(tv, "p"): + modulus = tv.p + generator = tv.g + suborder = tv.q + continue + + hash_obj = hash_module.new(tv.msg) + + comps = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder)] + key = DSA.construct(comps, False) # type: ignore + verifier = DSS.new(key, "fips-186-3") + + def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r + tv.s): + verifier.verify(hash_obj, signature) + + def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r + tv.s): + self.assertRaises(ValueError, verifier.verify, hash_obj, signature) + + if tv.result == "p": + setattr(FIPS_DSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) + else: + setattr(FIPS_DSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) + + +test_vectors_sign = ( + load_test_vectors( + ("Signature", "DSA"), + "FIPS_186_3_SigGen.txt", + "Signature Creation 186-3", + {}, + ) + or [] +) for idx, tv in enumerate(test_vectors_sign): + if isinstance(tv, str): + res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) + assert res + hash_name = res.group(3).replace("-", "") + hash_module = load_hash_by_name(hash_name) + continue - if isinstance(tv, str): - res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) - assert(res) - hash_name = res.group(3).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue + if hasattr(tv, "p"): + modulus = tv.p + generator = tv.g + suborder = tv.q + continue - if hasattr(tv, "p"): - modulus = tv.p - generator = tv.g - suborder = tv.q - continue + hash_obj = hash_module.new(tv.msg) + comps_dsa = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder, tv.x)] + key = DSA.construct(comps_dsa, False) # type: ignore + signer = DSS.new(key, "fips-186-3", randfunc=StrRNG(tv.k)) - hash_obj = hash_module.new(tv.msg) - comps_dsa = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder, tv.x)] - key = DSA.construct(comps_dsa, False) # type: ignore - signer = DSS.new(key, 'fips-186-3', randfunc=StrRNG(tv.k)) + def new_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r + tv.s): + self.assertEqual(signer.sign(hash_obj), signature) - def new_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertEqual(signer.sign(hash_obj), signature) - setattr(FIPS_DSA_Tests_KAT, "test_sign_%d" % idx, new_test) + setattr(FIPS_DSA_Tests_KAT, "test_sign_%d" % idx, new_test) class FIPS_ECDSA_Tests(unittest.TestCase): + key_priv = ECC.generate(curve="P-256") + key_pub = key_priv.public_key() - key_priv = ECC.generate(curve="P-256") - key_pub = key_priv.public_key() - - def shortDescription(self): - return "FIPS ECDSA Tests" + def shortDescription(self): + return "FIPS ECDSA Tests" - def test_loopback(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv, 'fips-186-3') - signature = signer.sign(hashed_msg) + def test_loopback(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv, "fips-186-3") + signature = signer.sign(hashed_msg) - verifier = DSS.new(self.key_pub, 'fips-186-3') - verifier.verify(hashed_msg, signature) + verifier = DSS.new(self.key_pub, "fips-186-3") + verifier.verify(hashed_msg, signature) - def test_negative_unapproved_hashes(self): - """Verify that unapproved hashes are rejected""" + def test_negative_unapproved_hashes(self): + """Verify that unapproved hashes are rejected""" - from Cryptodome.Hash import SHA1 + from Cryptodome.Hash import SHA1 - self.description = "Unapproved hash (SHA-1) test" - hash_obj = SHA1.new() - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertRaises(ValueError, signer.sign, hash_obj) - self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) + self.description = "Unapproved hash (SHA-1) test" + hash_obj = SHA1.new() + signer = DSS.new(self.key_priv, "fips-186-3") + self.assertRaises(ValueError, signer.sign, hash_obj) + self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) - def test_negative_eddsa_key(self): - key = ECC.generate(curve="ed25519") - self.assertRaises(ValueError, DSS.new, key, 'fips-186-3') + def test_negative_eddsa_key(self): + key = ECC.generate(curve="ed25519") + self.assertRaises(ValueError, DSS.new, key, "fips-186-3") - def test_sign_verify(self): - """Verify public/private method""" + def test_sign_verify(self): + """Verify public/private method""" - self.description = "can_sign() test" - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertTrue(signer.can_sign()) + self.description = "can_sign() test" + signer = DSS.new(self.key_priv, "fips-186-3") + self.assertTrue(signer.can_sign()) - signer = DSS.new(self.key_pub, 'fips-186-3') - self.assertFalse(signer.can_sign()) - self.assertRaises(TypeError, signer.sign, SHA256.new(b'xyz')) + signer = DSS.new(self.key_pub, "fips-186-3") + self.assertFalse(signer.can_sign()) + self.assertRaises(TypeError, signer.sign, SHA256.new(b"xyz")) - try: - signer.sign(SHA256.new(b'xyz')) - except TypeError as e: - msg = str(e) - else: - msg = "" - self.assertTrue("Private key is needed" in msg) + try: + signer.sign(SHA256.new(b"xyz")) + except TypeError as e: + msg = str(e) + else: + msg = "" + self.assertTrue("Private key is needed" in msg) - def test_negative_unknown_modes_encodings(self): - """Verify that unknown modes/encodings are rejected""" + def test_negative_unknown_modes_encodings(self): + """Verify that unknown modes/encodings are rejected""" - self.description = "Unknown mode test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-0') + self.description = "Unknown mode test" + self.assertRaises(ValueError, DSS.new, self.key_priv, "fips-186-0") - self.description = "Unknown encoding test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-3', 'xml') + self.description = "Unknown encoding test" + self.assertRaises(ValueError, DSS.new, self.key_priv, "fips-186-3", "xml") - def test_asn1_encoding(self): - """Verify ASN.1 encoding""" + def test_asn1_encoding(self): + """Verify ASN.1 encoding""" - self.description = "ASN.1 encoding test" - hash_obj = SHA256.new() - signer = DSS.new(self.key_priv, 'fips-186-3', 'der') - signature = signer.sign(hash_obj) + self.description = "ASN.1 encoding test" + hash_obj = SHA256.new() + signer = DSS.new(self.key_priv, "fips-186-3", "der") + signature = signer.sign(hash_obj) - # Verify that output looks like a DER SEQUENCE - self.assertEqual(bord(signature[0]), 48) - signer.verify(hash_obj, signature) + # Verify that output looks like a DER SEQUENCE + self.assertEqual(bord(signature[0]), 48) + signer.verify(hash_obj, signature) - # Verify that ASN.1 parsing fails as expected - signature = bchr(7) + signature[1:] - self.assertRaises(ValueError, signer.verify, hash_obj, signature) + # Verify that ASN.1 parsing fails as expected + signature = bchr(7) + signature[1:] + self.assertRaises(ValueError, signer.verify, hash_obj, signature) class FIPS_ECDSA_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_verify = load_test_vectors(("Signature", "ECDSA"), - "SigVer.rsp", - "ECDSA Signature Verification 186-3", - {'result': lambda x: x, - 'qx': lambda x: int(x, 16), - 'qy': lambda x: int(x, 16), - }) or [] -test_vectors_verify += load_test_vectors(("Signature", "ECDSA"), - "SigVer_TruncatedSHAs.rsp", - "ECDSA Signature Verification 186-3", - {'result': lambda x: x, - 'qx': lambda x: int(x, 16), - 'qy': lambda x: int(x, 16), - }) or [] + pass + + +test_vectors_verify = ( + load_test_vectors( + ("Signature", "ECDSA"), + "SigVer.rsp", + "ECDSA Signature Verification 186-3", + { + "result": lambda x: x, + "qx": lambda x: int(x, 16), + "qy": lambda x: int(x, 16), + }, + ) + or [] +) +test_vectors_verify += ( + load_test_vectors( + ("Signature", "ECDSA"), + "SigVer_TruncatedSHAs.rsp", + "ECDSA Signature Verification 186-3", + { + "result": lambda x: x, + "qx": lambda x: int(x, 16), + "qy": lambda x: int(x, 16), + }, + ) + or [] +) for idx, tv in enumerate(test_vectors_verify): - - if isinstance(tv, str): - res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) - assert res - curve_name = res.group(1) - hash_name = res.group(2).replace("-", "") - if hash_name in ("SHA512224", "SHA512256"): - truncate = hash_name[-3:] - hash_name = hash_name[:-3] - else: - truncate = None - hash_module = load_hash_by_name(hash_name) - continue - - if truncate is None: - hash_obj = hash_module.new(tv.msg) - else: - hash_obj = hash_module.new(tv.msg, truncate=truncate) - ecc_key = ECC.construct(curve=curve_name, point_x=tv.qx, point_y=tv.qy) - verifier = DSS.new(ecc_key, 'fips-186-3') - - def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result.startswith('p'): - setattr(FIPS_ECDSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) - else: - setattr(FIPS_ECDSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) - - -test_vectors_sign = load_test_vectors(("Signature", "ECDSA"), - "SigGen.txt", - "ECDSA Signature Verification 186-3", - {'d': lambda x: int(x, 16)}) or [] + if isinstance(tv, str): + res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) + assert res + curve_name = res.group(1) + hash_name = res.group(2).replace("-", "") + if hash_name in ("SHA512224", "SHA512256"): + truncate = hash_name[-3:] + hash_name = hash_name[:-3] + else: + truncate = None + hash_module = load_hash_by_name(hash_name) + continue + + if truncate is None: + hash_obj = hash_module.new(tv.msg) + else: + hash_obj = hash_module.new(tv.msg, truncate=truncate) + ecc_key = ECC.construct(curve=curve_name, point_x=tv.qx, point_y=tv.qy) + verifier = DSS.new(ecc_key, "fips-186-3") + + def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r + tv.s): + verifier.verify(hash_obj, signature) + + def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r + tv.s): + self.assertRaises(ValueError, verifier.verify, hash_obj, signature) + + if tv.result.startswith("p"): + setattr(FIPS_ECDSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) + else: + setattr(FIPS_ECDSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) + + +test_vectors_sign = ( + load_test_vectors( + ("Signature", "ECDSA"), + "SigGen.txt", + "ECDSA Signature Verification 186-3", + {"d": lambda x: int(x, 16)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_sign): + if isinstance(tv, str): + res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) + assert res + curve_name = res.group(1) + hash_name = res.group(2).replace("-", "") + hash_module = load_hash_by_name(hash_name) + continue - if isinstance(tv, str): - res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) - assert res - curve_name = res.group(1) - hash_name = res.group(2).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue + hash_obj = hash_module.new(tv.msg) + ecc_key = ECC.construct(curve=curve_name, d=tv.d) + signer = DSS.new(ecc_key, "fips-186-3", randfunc=StrRNG(tv.k)) - hash_obj = hash_module.new(tv.msg) - ecc_key = ECC.construct(curve=curve_name, d=tv.d) - signer = DSS.new(ecc_key, 'fips-186-3', randfunc=StrRNG(tv.k)) + def sign_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r + tv.s): + self.assertEqual(signer.sign(hash_obj), signature) - def sign_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertEqual(signer.sign(hash_obj), signature) - setattr(FIPS_ECDSA_Tests_KAT, "test_sign_%d" % idx, sign_test) + setattr(FIPS_ECDSA_Tests_KAT, "test_sign_%d" % idx, sign_test) class Det_DSA_Tests(unittest.TestCase): - """Tests from rfc6979""" + """Tests from rfc6979""" - # Each key is (p, q, g, x, y, desc) - keys = [ - ( - """ + # Each key is (p, q, g, x, y, desc) + keys = [ + ( + """ 86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447 E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88 73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C 881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779""", - "996F967F6C8E388D9E28D01E205FBA957A5698B1", - """ + "996F967F6C8E388D9E28D01E205FBA957A5698B1", + """ 07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D 89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD 87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4 17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD""", - "411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", - """ + "411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", + """ 5DF5E01DED31D0297E274E1691C192FE5868FEF9E19A84776454B100CF16F653 92195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D 4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E6 82F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B""", - "DSA1024" - ), - ( - """ + "DSA1024", + ), + ( + """ 9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48 C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5 @@ -413,8 +444,8 @@ class Det_DSA_Tests(unittest.TestCase): F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE 92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15 3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B""", - "F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", - """ + "F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", + """ 5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613 D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4 6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472 @@ -423,8 +454,8 @@ class Det_DSA_Tests(unittest.TestCase): 3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71 BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0 DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7""", - "69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC", - """ + "69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC", + """ 667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD94 9F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA61 1728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADE @@ -433,937 +464,961 @@ class Det_DSA_Tests(unittest.TestCase): 687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D1 23AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA 74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF""", - "DSA2048" - ), - ] - - # This is a sequence of items: - # message, k, r, s, hash module - signatures = [ - ( - "sample", - "7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B", - "2E1A0C2562B2912CAAF89186FB0F42001585DA55", - "29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5", - SHA1, - 'DSA1024' - ), - ( - "sample", - "562097C06782D60C3037BA7BE104774344687649", - "4BC3B686AEA70145856814A6F1BB53346F02101E", - "410697B92295D994D21EDD2F4ADA85566F6F94C1", - SHA224, - 'DSA1024' - ), - ( - "sample", - "519BA0546D0C39202A7D34D7DFA5E760B318BCFB", - "81F2F5850BE5BC123C43F71A3033E9384611C545", - "4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89", - SHA256, - 'DSA1024' - ), - ( - "sample", - "95897CD7BBB944AA932DBC579C1C09EB6FCFC595", - "07F2108557EE0E3921BC1774F1CA9B410B4CE65A", - "54DF70456C86FAC10FAB47C1949AB83F2C6F7595", - SHA384, - 'DSA1024' - ), - ( - "sample", - "09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B", - "16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", - "02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C", - SHA512, - 'DSA1024' - ), - ( - "test", - "5C842DF4F9E344EE09F056838B42C7A17F4A6433", - "42AB2052FD43E123F0607F115052A67DCD9C5C77", - "183916B0230D45B9931491D4C6B0BD2FB4AAF088", - SHA1, - 'DSA1024' - ), - ( - "test", - "4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297", - "6868E9964E36C1689F6037F91F28D5F2C30610F2", - "49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F", - SHA224, - 'DSA1024' - ), - ( - "test", - "5A67592E8128E03A417B0484410FB72C0B630E1A", - "22518C127299B0F6FDC9872B282B9E70D0790812", - "6837EC18F150D55DE95B5E29BE7AF5D01E4FE160", - SHA256, - 'DSA1024' - ), - ( - "test", - "220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89", - "854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", - "91D0E0F53E22F898D158380676A871A157CDA622", - SHA384, - 'DSA1024' - ), - ( - "test", - "65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C", - "8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", - "7C670C7AD72B6C050C109E1790008097125433E8", - SHA512, - 'DSA1024' - ), - ( - "sample", - "888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E", - "3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", - "D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF", - SHA1, - 'DSA2048' - ), - ( - "sample", - "BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806", - "DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", - "A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC", - SHA224, - 'DSA2048' - ), - ( - "sample", - "8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52", - "EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", - "7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53", - SHA256, - 'DSA2048' - ), - ( - "sample", - "C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920", - "B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", - "19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B", - SHA384, - 'DSA2048' - ), - ( - "sample", - "5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC", - "2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", - "D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351", - SHA512, - 'DSA2048' - ), - ( - "test", - "6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F", - "C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", - "414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA", - SHA1, - 'DSA2048' - ), - ( - "test", - "06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670", - "272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", - "E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806", - SHA224, - 'DSA2048' - ), - ( - "test", - "1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7", - "8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", - "7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E", - SHA256, - 'DSA2048' - ), - ( - "test", - "206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C", - "239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", - "6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961", - SHA384, - 'DSA2048' - ), - ( - "test", - "AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA", - "89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", - "C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1", - SHA512, - 'DSA2048' - ) - ] - - def setUp(self): - # Convert DSA key components from hex strings to integers - # Each key is (p, q, g, x, y, desc) - - from collections import namedtuple - - TestKey = namedtuple('TestKey', 'p q g x y') - new_keys = {} - for k in self.keys: - tk = TestKey(*[t2l(y) for y in k[:-1]]) - new_keys[k[-1]] = tk - self.keys = new_keys - - # Convert signature encoding - TestSig = namedtuple('TestSig', 'message nonce result module test_key') - new_signatures = [] - for message, nonce, r, s, module, test_key in self.signatures: - tsig = TestSig( - tobytes(message), - t2l(nonce), - t2b(r) + t2b(s), - module, - self.keys[test_key] - ) - new_signatures.append(tsig) - self.signatures = new_signatures - - def test1(self): - q = 0x4000000000000000000020108A2E0CC0D99F8A5EF - x = 0x09A4D6792295A7F730FC3F2B49CBC0F62E862272F - p = 2 * q + 1 - y = pow(2, x, p) - key = DSA.construct([pow(y, 2, p), 2, p, q, x], False) - signer = DSS.new(key, 'deterministic-rfc6979') - - # Test _int2octets - self.assertEqual(hexlify(signer._int2octets(x)), - b'009a4d6792295a7f730fc3f2b49cbc0f62e862272f') - - # Test _bits2octets - h1 = SHA256.new(b"sample").digest() - self.assertEqual(hexlify(signer._bits2octets(h1)), - b'01795edf0d54db760f156d0dac04c0322b3a204224') - - def test2(self): - - for sig in self.signatures: - tk = sig.test_key - key = DSA.construct([tk.y, tk.g, tk.p, tk.q, tk.x], False) - signer = DSS.new(key, 'deterministic-rfc6979') - - hash_obj = sig.module.new(sig.message) - result = signer.sign(hash_obj) - self.assertEqual(sig.result, result) + "DSA2048", + ), + ] + + # This is a sequence of items: + # message, k, r, s, hash module + signatures = [ + ( + "sample", + "7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B", + "2E1A0C2562B2912CAAF89186FB0F42001585DA55", + "29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5", + SHA1, + "DSA1024", + ), + ( + "sample", + "562097C06782D60C3037BA7BE104774344687649", + "4BC3B686AEA70145856814A6F1BB53346F02101E", + "410697B92295D994D21EDD2F4ADA85566F6F94C1", + SHA224, + "DSA1024", + ), + ( + "sample", + "519BA0546D0C39202A7D34D7DFA5E760B318BCFB", + "81F2F5850BE5BC123C43F71A3033E9384611C545", + "4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89", + SHA256, + "DSA1024", + ), + ( + "sample", + "95897CD7BBB944AA932DBC579C1C09EB6FCFC595", + "07F2108557EE0E3921BC1774F1CA9B410B4CE65A", + "54DF70456C86FAC10FAB47C1949AB83F2C6F7595", + SHA384, + "DSA1024", + ), + ( + "sample", + "09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B", + "16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", + "02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C", + SHA512, + "DSA1024", + ), + ( + "test", + "5C842DF4F9E344EE09F056838B42C7A17F4A6433", + "42AB2052FD43E123F0607F115052A67DCD9C5C77", + "183916B0230D45B9931491D4C6B0BD2FB4AAF088", + SHA1, + "DSA1024", + ), + ( + "test", + "4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297", + "6868E9964E36C1689F6037F91F28D5F2C30610F2", + "49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F", + SHA224, + "DSA1024", + ), + ( + "test", + "5A67592E8128E03A417B0484410FB72C0B630E1A", + "22518C127299B0F6FDC9872B282B9E70D0790812", + "6837EC18F150D55DE95B5E29BE7AF5D01E4FE160", + SHA256, + "DSA1024", + ), + ( + "test", + "220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89", + "854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", + "91D0E0F53E22F898D158380676A871A157CDA622", + SHA384, + "DSA1024", + ), + ( + "test", + "65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C", + "8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", + "7C670C7AD72B6C050C109E1790008097125433E8", + SHA512, + "DSA1024", + ), + ( + "sample", + "888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E", + "3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", + "D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF", + SHA1, + "DSA2048", + ), + ( + "sample", + "BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806", + "DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", + "A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC", + SHA224, + "DSA2048", + ), + ( + "sample", + "8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52", + "EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", + "7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53", + SHA256, + "DSA2048", + ), + ( + "sample", + "C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920", + "B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", + "19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B", + SHA384, + "DSA2048", + ), + ( + "sample", + "5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC", + "2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", + "D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351", + SHA512, + "DSA2048", + ), + ( + "test", + "6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F", + "C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", + "414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA", + SHA1, + "DSA2048", + ), + ( + "test", + "06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670", + "272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", + "E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806", + SHA224, + "DSA2048", + ), + ( + "test", + "1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7", + "8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", + "7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E", + SHA256, + "DSA2048", + ), + ( + "test", + "206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C", + "239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", + "6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961", + SHA384, + "DSA2048", + ), + ( + "test", + "AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA", + "89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", + "C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1", + SHA512, + "DSA2048", + ), + ] + + def setUp(self): + # Convert DSA key components from hex strings to integers + # Each key is (p, q, g, x, y, desc) + + from collections import namedtuple + + TestKey = namedtuple("TestKey", "p q g x y") + new_keys = {} + for k in self.keys: + tk = TestKey(*[t2l(y) for y in k[:-1]]) + new_keys[k[-1]] = tk + self.keys = new_keys + + # Convert signature encoding + TestSig = namedtuple("TestSig", "message nonce result module test_key") + new_signatures = [] + for message, nonce, r, s, module, test_key in self.signatures: + tsig = TestSig( + tobytes(message), + t2l(nonce), + t2b(r) + t2b(s), + module, + self.keys[test_key], + ) + new_signatures.append(tsig) + self.signatures = new_signatures + + def test1(self): + q = 0x4000000000000000000020108A2E0CC0D99F8A5EF + x = 0x09A4D6792295A7F730FC3F2B49CBC0F62E862272F + p = 2 * q + 1 + y = pow(2, x, p) + key = DSA.construct([pow(y, 2, p), 2, p, q, x], False) + signer = DSS.new(key, "deterministic-rfc6979") + + # Test _int2octets + self.assertEqual( + hexlify(signer._int2octets(x)), + b"009a4d6792295a7f730fc3f2b49cbc0f62e862272f", + ) + + # Test _bits2octets + h1 = SHA256.new(b"sample").digest() + self.assertEqual( + hexlify(signer._bits2octets(h1)), + b"01795edf0d54db760f156d0dac04c0322b3a204224", + ) + + def test2(self): + for sig in self.signatures: + tk = sig.test_key + key = DSA.construct([tk.y, tk.g, tk.p, tk.q, tk.x], False) + signer = DSS.new(key, "deterministic-rfc6979") + + hash_obj = sig.module.new(sig.message) + result = signer.sign(hash_obj) + self.assertEqual(sig.result, result) class Det_ECDSA_Tests(unittest.TestCase): - - key_priv_p192 = ECC.construct(curve="P-192", d=0x6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4) - key_pub_p192 = key_priv_p192.public_key() - - key_priv_p224 = ECC.construct(curve="P-224", d=0xF220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1) - key_pub_p224 = key_priv_p224.public_key() - - key_priv_p256 = ECC.construct(curve="P-256", d=0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721) - key_pub_p256 = key_priv_p256.public_key() - - key_priv_p384 = ECC.construct(curve="P-384", d=0x6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5) - key_pub_p384 = key_priv_p384.public_key() - - key_priv_p521 = ECC.construct(curve="P-521", d=0x0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538) - key_pub_p521 = key_priv_p521.public_key() - - # This is a sequence of items: - # message, k, r, s, hash module - # taken from RFC6979 - signatures_p192_ = ( - ( - "sample", - "37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", - "98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", - "57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64", - SHA1 - ), - ( - "sample", - "4381526B3FC1E7128F202E194505592F01D5FF4C5AF015D8", - "A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", - "E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A", - SHA224 - ), - ( - "sample", - "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", - "4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", - "CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85", - SHA256 - ), - ( - "sample", - "4730005C4FCB01834C063A7B6760096DBE284B8252EF4311", - "DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", - "C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E", - SHA384 - ), - ( - "sample", - "A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", - "4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", - "3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67", - SHA512 - ), - ( - "test", - "D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", - "0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", - "EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7", - SHA1 - ), - ( - "test", - "F5DC805F76EF851800700CCE82E7B98D8911B7D510059FBE", - "6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", - "B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293", - SHA224 - ), - ( - "test", - "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", - "3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", - "5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F", - SHA256 - ), - ( - "test", - "5AFEFB5D3393261B828DB6C91FBC68C230727B030C975693", - "B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", - "7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A", - SHA384 - ), - ( - "test", - "0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", - "FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", - "74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290", - SHA512 - ) - ) - - signatures_p224_ = ( - ( - "sample", - "7EEFADD91110D8DE6C2C470831387C50D3357F7F4D477054B8B426BC", - "22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC", - "66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69", - SHA1 - ), - ( - "sample", - "C1D1F2F10881088301880506805FEB4825FE09ACB6816C36991AA06D", - "1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E", - "A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC", - SHA224 - ), - ( - "sample", - "AD3029E0278F80643DE33917CE6908C70A8FF50A411F06E41DEDFCDC", - "61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", - "BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101", - SHA256 - ), - ( - "sample", - "52B40F5A9D3D13040F494E83D3906C6079F29981035C7BD51E5CAC40", - "0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953", - "830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D", - SHA384 - ), - ( - "sample", - "9DB103FFEDEDF9CFDBA05184F925400C1653B8501BAB89CEA0FBEC14", - "074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397", - "A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084", - SHA512 - ), - ( - "test", - "2519178F82C3F0E4F87ED5883A4E114E5B7A6E374043D8EFD329C253", - "DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C", - "95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2", - SHA1 - ), - ( - "test", - "DF8B38D40DCA3E077D0AC520BF56B6D565134D9B5F2EAE0D34900524", - "C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019", - "902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4", - SHA224 - ), - ( - "test", - "FF86F57924DA248D6E44E8154EB69F0AE2AEBAEE9931D0B5A969F904", - "AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", - "178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD", - SHA256 - ), - ( - "test", - "7046742B839478C1B5BD31DB2E862AD868E1A45C863585B5F22BDC2D", - "389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4", - "414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB", - SHA384 - ), - ( - "test", - "E39C2AA4EA6BE2306C72126D40ED77BF9739BB4D6EF2BBB1DCB6169D", - "049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C", - "077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF", - SHA512 - ) - ) - - signatures_p256_ = ( - ( - "sample", - "882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4", - "61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", - "6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB", - SHA1 - ), - ( - "sample", - "103F90EE9DC52E5E7FB5132B7033C63066D194321491862059967C715985D473", - "53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", - "B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C", - SHA224 - ), - ( - "sample", - "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60", - "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", - "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8", - SHA256 - ), - ( - "sample", - "09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4", - "0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", - "4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954", - SHA384 - ), - ( - "sample", - "5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5", - "8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", - "2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE", - SHA512 - ), - ( - "test", - "8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E", - "0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", - "01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1", - SHA1 - ), - ( - "test", - "669F4426F2688B8BE0DB3A6BD1989BDAEFFF84B649EEB84F3DD26080F667FAA7", - "C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", - "C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D", - SHA224 - ), - ( - "test", - "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0", - "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", - "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083", - SHA256 - ), - ( - "test", - "16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8", - "83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", - "8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C", - SHA384 - ), - ( - "test", - "6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F", - "461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", - "39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55", - SHA512 - ) - ) - - signatures_p384_ = ( - ( - "sample", - "4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB096630F29E5938D25106C3C340045A2DB01A7", - "EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2", - "A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443", - SHA1 - ), - ( - "sample", - "A4E4D2F0E729EB786B31FC20AD5D849E304450E0AE8E3E341134A5C1AFA03CAB8083EE4E3C45B06A5899EA56C51B5879", - "42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE060122", - "9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D", - SHA224 - ), - ( - "sample", - "180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E375572342863C899F9F2EDF9747A9B60", - "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD", - "F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0", - SHA256 - ), - ( - "sample", - "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9", - "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46", - "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8", - SHA384 - ), - ( - "sample", - "92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331A4E966532593A52980D0E3AAA5E10EC3", - "ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD7882433709", - "512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5", - SHA512 - ), - ( - "test", - "66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47EC3727F3A3C186C15054492E30698497", - "4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7", - "D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282", - SHA1 - ), - ( - "test", - "18FA39DB95AA5F561F30FA3591DC59C0FA3653A80DAFFA0B48D1A4C6DFCBFF6E3D33BE4DC5EB8886A8ECD093F2935726", - "E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E72", - "07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66", - SHA224 - ), - ( - "test", - "0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FAA48DD070BA79921A3457ABFF2D630AD7", - "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B", - "2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265", - SHA256 - ), - ( - "test", - "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA", - "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB", - "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5", - SHA384 - ), - ( - "test", - "3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE0E2CC8A136036DC4B9C00E6888F66B6C", - "A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277", - "976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736", - SHA512 - ), - ) - - signatures_p521_ = ( - ( - "sample", - "0089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9", - "00343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D", - "00E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16", - SHA1 - ), - ( - "sample", - "0121415EC2CD7726330A61F7F3FA5DE14BE9436019C4DB8CB4041F3B54CF31BE0493EE3F427FB906393D895A19C9523F3A1D54BB8702BD4AA9C99DAB2597B92113F3", - "01776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E", - "0050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F", - SHA224 - ), - ( - "sample", - "00EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0", - "01511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7", - "004A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC", - SHA256 - ), - ( - "sample", - "01546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FFAD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4211", - "01EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67451", - "01F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61", - SHA384 - ), - ( - "sample", - "01DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3", - "00C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA", - "00617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A", - SHA512 - ), - ( - "test", - "00BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DDBA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B222", - "013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0367", - "01E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF", - SHA1 - ), - ( - "test", - "0040D09FCF3C8A5F62CF4FB223CBBB2B9937F6B0577C27020A99602C25A01136987E452988781484EDBBCF1C47E554E7FC901BC3085E5206D9F619CFF07E73D6F706", - "01C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB", - "0177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4", - SHA224 - ), - ( - "test", - "001DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E843841AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909258", - "000E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8", - "00CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86", - SHA256 - ), - ( - "test", - "01F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5DCEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0C88", - "014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C", - "0133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979", - SHA384 - ), - ( - "test", - "016200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D", - "013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D", - "01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3", - SHA512 - ), - ) - - signatures_p192 = [] - for a, b, c, d, e in signatures_p192_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p192.append(new_tv) - - signatures_p224 = [] - for a, b, c, d, e in signatures_p224_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p224.append(new_tv) - - signatures_p256 = [] - for a, b, c, d, e in signatures_p256_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p256.append(new_tv) - - signatures_p384 = [] - for a, b, c, d, e in signatures_p384_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p384.append(new_tv) - - signatures_p521 = [] - for a, b, c, d, e in signatures_p521_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p521.append(new_tv) - - def shortDescription(self): - return "Deterministic ECDSA Tests" - - def test_loopback_p192(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p192, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p192, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p224(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p224, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p224, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p256(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p256, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p256, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p384(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p384, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p384, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p521(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p521, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p521, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_data_rfc6979_p192(self): - signer = DSS.new(self.key_priv_p192, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p192: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p224(self): - signer = DSS.new(self.key_priv_p224, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p224: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p256(self): - signer = DSS.new(self.key_priv_p256, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p256: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p384(self): - signer = DSS.new(self.key_priv_p384, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p384: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p521(self): - signer = DSS.new(self.key_priv_p521, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p521: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) + key_priv_p192 = ECC.construct(curve="P-192", d=0x6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4) + key_pub_p192 = key_priv_p192.public_key() + + key_priv_p224 = ECC.construct(curve="P-224", d=0xF220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1) + key_pub_p224 = key_priv_p224.public_key() + + key_priv_p256 = ECC.construct( + curve="P-256", d=0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721 + ) + key_pub_p256 = key_priv_p256.public_key() + + key_priv_p384 = ECC.construct( + curve="P-384", + d=0x6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5, + ) + key_pub_p384 = key_priv_p384.public_key() + + key_priv_p521 = ECC.construct( + curve="P-521", + d=0x0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538, + ) + key_pub_p521 = key_priv_p521.public_key() + + # This is a sequence of items: + # message, k, r, s, hash module + # taken from RFC6979 + signatures_p192_ = ( + ( + "sample", + "37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", + "98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", + "57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64", + SHA1, + ), + ( + "sample", + "4381526B3FC1E7128F202E194505592F01D5FF4C5AF015D8", + "A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", + "E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A", + SHA224, + ), + ( + "sample", + "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", + "4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", + "CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85", + SHA256, + ), + ( + "sample", + "4730005C4FCB01834C063A7B6760096DBE284B8252EF4311", + "DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", + "C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E", + SHA384, + ), + ( + "sample", + "A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", + "4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", + "3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67", + SHA512, + ), + ( + "test", + "D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", + "0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", + "EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7", + SHA1, + ), + ( + "test", + "F5DC805F76EF851800700CCE82E7B98D8911B7D510059FBE", + "6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", + "B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293", + SHA224, + ), + ( + "test", + "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", + "3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", + "5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F", + SHA256, + ), + ( + "test", + "5AFEFB5D3393261B828DB6C91FBC68C230727B030C975693", + "B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", + "7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A", + SHA384, + ), + ( + "test", + "0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", + "FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", + "74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290", + SHA512, + ), + ) + + signatures_p224_ = ( + ( + "sample", + "7EEFADD91110D8DE6C2C470831387C50D3357F7F4D477054B8B426BC", + "22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC", + "66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69", + SHA1, + ), + ( + "sample", + "C1D1F2F10881088301880506805FEB4825FE09ACB6816C36991AA06D", + "1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E", + "A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC", + SHA224, + ), + ( + "sample", + "AD3029E0278F80643DE33917CE6908C70A8FF50A411F06E41DEDFCDC", + "61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", + "BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101", + SHA256, + ), + ( + "sample", + "52B40F5A9D3D13040F494E83D3906C6079F29981035C7BD51E5CAC40", + "0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953", + "830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D", + SHA384, + ), + ( + "sample", + "9DB103FFEDEDF9CFDBA05184F925400C1653B8501BAB89CEA0FBEC14", + "074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397", + "A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084", + SHA512, + ), + ( + "test", + "2519178F82C3F0E4F87ED5883A4E114E5B7A6E374043D8EFD329C253", + "DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C", + "95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2", + SHA1, + ), + ( + "test", + "DF8B38D40DCA3E077D0AC520BF56B6D565134D9B5F2EAE0D34900524", + "C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019", + "902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4", + SHA224, + ), + ( + "test", + "FF86F57924DA248D6E44E8154EB69F0AE2AEBAEE9931D0B5A969F904", + "AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", + "178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD", + SHA256, + ), + ( + "test", + "7046742B839478C1B5BD31DB2E862AD868E1A45C863585B5F22BDC2D", + "389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4", + "414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB", + SHA384, + ), + ( + "test", + "E39C2AA4EA6BE2306C72126D40ED77BF9739BB4D6EF2BBB1DCB6169D", + "049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C", + "077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF", + SHA512, + ), + ) + + signatures_p256_ = ( + ( + "sample", + "882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4", + "61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", + "6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB", + SHA1, + ), + ( + "sample", + "103F90EE9DC52E5E7FB5132B7033C63066D194321491862059967C715985D473", + "53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", + "B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C", + SHA224, + ), + ( + "sample", + "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60", + "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", + "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8", + SHA256, + ), + ( + "sample", + "09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4", + "0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", + "4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954", + SHA384, + ), + ( + "sample", + "5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5", + "8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", + "2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE", + SHA512, + ), + ( + "test", + "8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E", + "0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", + "01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1", + SHA1, + ), + ( + "test", + "669F4426F2688B8BE0DB3A6BD1989BDAEFFF84B649EEB84F3DD26080F667FAA7", + "C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", + "C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D", + SHA224, + ), + ( + "test", + "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0", + "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", + "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083", + SHA256, + ), + ( + "test", + "16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8", + "83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", + "8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C", + SHA384, + ), + ( + "test", + "6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F", + "461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", + "39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55", + SHA512, + ), + ) + + signatures_p384_ = ( + ( + "sample", + "4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB096630F29E5938D25106C3C340045A2DB01A7", + "EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2", + "A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443", + SHA1, + ), + ( + "sample", + "A4E4D2F0E729EB786B31FC20AD5D849E304450E0AE8E3E341134A5C1AFA03CAB8083EE4E3C45B06A5899EA56C51B5879", + "42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE060122", + "9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D", + SHA224, + ), + ( + "sample", + "180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E375572342863C899F9F2EDF9747A9B60", + "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD", + "F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0", + SHA256, + ), + ( + "sample", + "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9", + "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46", + "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8", + SHA384, + ), + ( + "sample", + "92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331A4E966532593A52980D0E3AAA5E10EC3", + "ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD7882433709", + "512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5", + SHA512, + ), + ( + "test", + "66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47EC3727F3A3C186C15054492E30698497", + "4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7", + "D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282", + SHA1, + ), + ( + "test", + "18FA39DB95AA5F561F30FA3591DC59C0FA3653A80DAFFA0B48D1A4C6DFCBFF6E3D33BE4DC5EB8886A8ECD093F2935726", + "E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E72", + "07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66", + SHA224, + ), + ( + "test", + "0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FAA48DD070BA79921A3457ABFF2D630AD7", + "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B", + "2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265", + SHA256, + ), + ( + "test", + "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA", + "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB", + "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5", + SHA384, + ), + ( + "test", + "3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE0E2CC8A136036DC4B9C00E6888F66B6C", + "A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277", + "976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736", + SHA512, + ), + ) + + signatures_p521_ = ( + ( + "sample", + "0089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9", + "00343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D", + "00E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16", + SHA1, + ), + ( + "sample", + "0121415EC2CD7726330A61F7F3FA5DE14BE9436019C4DB8CB4041F3B54CF31BE0493EE3F427FB906393D895A19C9523F3A1D54BB8702BD4AA9C99DAB2597B92113F3", + "01776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E", + "0050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F", + SHA224, + ), + ( + "sample", + "00EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0", + "01511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7", + "004A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC", + SHA256, + ), + ( + "sample", + "01546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FFAD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4211", + "01EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67451", + "01F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61", + SHA384, + ), + ( + "sample", + "01DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3", + "00C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA", + "00617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A", + SHA512, + ), + ( + "test", + "00BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DDBA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B222", + "013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0367", + "01E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF", + SHA1, + ), + ( + "test", + "0040D09FCF3C8A5F62CF4FB223CBBB2B9937F6B0577C27020A99602C25A01136987E452988781484EDBBCF1C47E554E7FC901BC3085E5206D9F619CFF07E73D6F706", + "01C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB", + "0177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4", + SHA224, + ), + ( + "test", + "001DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E843841AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909258", + "000E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8", + "00CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86", + SHA256, + ), + ( + "test", + "01F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5DCEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0C88", + "014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C", + "0133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979", + SHA384, + ), + ( + "test", + "016200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D", + "013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D", + "01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3", + SHA512, + ), + ) + + signatures_p192 = [] + for a, b, c, d, e in signatures_p192_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p192.append(new_tv) + + signatures_p224 = [] + for a, b, c, d, e in signatures_p224_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p224.append(new_tv) + + signatures_p256 = [] + for a, b, c, d, e in signatures_p256_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p256.append(new_tv) + + signatures_p384 = [] + for a, b, c, d, e in signatures_p384_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p384.append(new_tv) + + signatures_p521 = [] + for a, b, c, d, e in signatures_p521_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p521.append(new_tv) + + def shortDescription(self): + return "Deterministic ECDSA Tests" + + def test_loopback_p192(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p192, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p192, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_loopback_p224(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p224, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p224, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_loopback_p256(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p256, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p256, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_loopback_p384(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p384, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p384, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_loopback_p521(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p521, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p521, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_data_rfc6979_p192(self): + signer = DSS.new(self.key_priv_p192, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p192: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) + + def test_data_rfc6979_p224(self): + signer = DSS.new(self.key_priv_p224, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p224: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) + + def test_data_rfc6979_p256(self): + signer = DSS.new(self.key_priv_p256, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p256: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) + + def test_data_rfc6979_p384(self): + signer = DSS.new(self.key_priv_p384, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p384: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) + + def test_data_rfc6979_p521(self): + signer = DSS.new(self.key_priv_p521, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p521: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) def get_hash_module(hash_name): - if hash_name == "SHA-512": - hash_module = SHA512 - elif hash_name == "SHA-512/224": - hash_module = SHA512.new(truncate="224") - elif hash_name == "SHA-512/256": - hash_module = SHA512.new(truncate="256") - elif hash_name == "SHA-384": - hash_module = SHA384 - elif hash_name == "SHA-256": - hash_module = SHA256 - elif hash_name == "SHA-224": - hash_module = SHA224 - elif hash_name == "SHA-1": - hash_module = SHA1 - elif hash_name == "SHA3-224": - hash_module = SHA3_224 - elif hash_name == "SHA3-256": - hash_module = SHA3_256 - elif hash_name == "SHA3-384": - hash_module = SHA3_384 - elif hash_name == "SHA3-512": - hash_module = SHA3_512 - else: - raise ValueError("Unknown hash algorithm: " + hash_name) - return hash_module + if hash_name == "SHA-512": + hash_module = SHA512 + elif hash_name == "SHA-512/224": + hash_module = SHA512.new(truncate="224") + elif hash_name == "SHA-512/256": + hash_module = SHA512.new(truncate="256") + elif hash_name == "SHA-384": + hash_module = SHA384 + elif hash_name == "SHA-256": + hash_module = SHA256 + elif hash_name == "SHA-224": + hash_module = SHA224 + elif hash_name == "SHA-1": + hash_module = SHA1 + elif hash_name == "SHA3-224": + hash_module = SHA3_224 + elif hash_name == "SHA3-256": + hash_module = SHA3_256 + elif hash_name == "SHA3-384": + hash_module = SHA3_384 + elif hash_name == "SHA3-512": + hash_module = SHA3_512 + else: + raise ValueError("Unknown hash algorithm: " + hash_name) + return hash_module class TestVectorsDSAWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._slow_tests = slow_tests - self._id = "None" - self.tv = [] - - def setUp(self): - - def filter_dsa(group): - return DSA.import_key(group['keyPem']) - - def filter_sha(group): - return get_hash_module(group['sha']) - - def filter_type(group): - sig_type = group['type'] - if sig_type != 'DsaVerify': - raise ValueError("Unknown signature type " + sig_type) - return sig_type - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - "dsa_test.json", - "Wycheproof DSA signature", - group_tag={'key': filter_dsa, - 'hash_module': filter_sha, - 'sig_type': filter_type}) - self.tv += result - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof DSA Test #" + str(tv.id) - - hashed_msg = tv.hash_module.new(tv.msg) - signer = DSS.new(tv.key, 'fips-186-3', encoding='der') - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings, slow_tests): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._slow_tests = slow_tests + self._id = "None" + self.tv = [] + + def setUp(self): + def filter_dsa(group): + return DSA.import_key(group["keyPem"]) + + def filter_sha(group): + return get_hash_module(group["sha"]) + + def filter_type(group): + sig_type = group["type"] + if sig_type != "DsaVerify": + raise ValueError("Unknown signature type " + sig_type) + return sig_type + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + "dsa_test.json", + "Wycheproof DSA signature", + group_tag={ + "key": filter_dsa, + "hash_module": filter_sha, + "sig_type": filter_type, + }, + ) + self.tv += result + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof DSA Test #" + str(tv.id) + + hashed_msg = tv.hash_module.new(tv.msg) + signer = DSS.new(tv.key, "fips-186-3", encoding="der") + try: + signature = signer.verify(hashed_msg, tv.sig) + except ValueError: + if tv.warning: + return + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) class TestVectorsECDSAWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._slow_tests = slow_tests - self._id = "None" - - def add_tests(self, filename): - - def filter_ecc(group): - # These are the only curves we accept to skip - if group['key']['curve'] in ('secp224k1', 'secp256k1', - 'brainpoolP224r1', 'brainpoolP224t1', - 'brainpoolP256r1', 'brainpoolP256t1', - 'brainpoolP320r1', 'brainpoolP320t1', - 'brainpoolP384r1', 'brainpoolP384t1', - 'brainpoolP512r1', 'brainpoolP512t1', - ): - return None - return ECC.import_key(group['keyPem']) - - def filter_sha(group): - return get_hash_module(group['sha']) - - def filter_encoding(group): - encoding_name = group['type'] - if encoding_name == "EcdsaVerify": - return "der" - elif encoding_name == "EcdsaP1363Verify": - return "binary" - else: - raise ValueError("Unknown signature type " + encoding_name) - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof ECDSA signature (%s)" % filename, - group_tag={'key': filter_ecc, - 'hash_module': filter_sha, - 'encoding': filter_encoding, - }) - self.tv += result - - def setUp(self): - self.tv = [] - self.add_tests("ecdsa_secp224r1_sha224_p1363_test.json") - self.add_tests("ecdsa_secp224r1_sha224_test.json") - if self._slow_tests: - self.add_tests("ecdsa_secp224r1_sha256_p1363_test.json") - self.add_tests("ecdsa_secp224r1_sha256_test.json") - self.add_tests("ecdsa_secp224r1_sha3_224_test.json") - self.add_tests("ecdsa_secp224r1_sha3_256_test.json") - self.add_tests("ecdsa_secp224r1_sha3_512_test.json") - self.add_tests("ecdsa_secp224r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp224r1_sha512_test.json") - self.add_tests("ecdsa_secp256r1_sha256_p1363_test.json") - self.add_tests("ecdsa_secp256r1_sha256_test.json") - self.add_tests("ecdsa_secp256r1_sha3_256_test.json") - self.add_tests("ecdsa_secp256r1_sha3_512_test.json") - self.add_tests("ecdsa_secp256r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp256r1_sha512_test.json") - if self._slow_tests: - self.add_tests("ecdsa_secp384r1_sha3_384_test.json") - self.add_tests("ecdsa_secp384r1_sha3_512_test.json") - self.add_tests("ecdsa_secp384r1_sha384_p1363_test.json") - self.add_tests("ecdsa_secp384r1_sha384_test.json") - self.add_tests("ecdsa_secp384r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp384r1_sha512_test.json") - if self._slow_tests: - self.add_tests("ecdsa_secp521r1_sha3_512_test.json") - self.add_tests("ecdsa_secp521r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp521r1_sha512_test.json") - self.add_tests("ecdsa_test.json") - self.add_tests("ecdsa_webcrypto_test.json") - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof ECDSA Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - - # Skip tests with unsupported curves - if tv.key is None: - return - - hashed_msg = tv.hash_module.new(tv.msg) - signer = DSS.new(tv.key, 'fips-186-3', encoding=tv.encoding) - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - if tv.comment == "k*G has a large x-coordinate": - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings, slow_tests): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._slow_tests = slow_tests + self._id = "None" + + def add_tests(self, filename): + def filter_ecc(group): + # These are the only curves we accept to skip + if group["key"]["curve"] in ( + "secp224k1", + "secp256k1", + "brainpoolP224r1", + "brainpoolP224t1", + "brainpoolP256r1", + "brainpoolP256t1", + "brainpoolP320r1", + "brainpoolP320t1", + "brainpoolP384r1", + "brainpoolP384t1", + "brainpoolP512r1", + "brainpoolP512t1", + ): + return None + return ECC.import_key(group["keyPem"]) + + def filter_sha(group): + return get_hash_module(group["sha"]) + + def filter_encoding(group): + encoding_name = group["type"] + if encoding_name == "EcdsaVerify": + return "der" + elif encoding_name == "EcdsaP1363Verify": + return "binary" + else: + raise ValueError("Unknown signature type " + encoding_name) + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + filename, + "Wycheproof ECDSA signature (%s)" % filename, + group_tag={ + "key": filter_ecc, + "hash_module": filter_sha, + "encoding": filter_encoding, + }, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.add_tests("ecdsa_secp224r1_sha224_p1363_test.json") + self.add_tests("ecdsa_secp224r1_sha224_test.json") + if self._slow_tests: + self.add_tests("ecdsa_secp224r1_sha256_p1363_test.json") + self.add_tests("ecdsa_secp224r1_sha256_test.json") + self.add_tests("ecdsa_secp224r1_sha3_224_test.json") + self.add_tests("ecdsa_secp224r1_sha3_256_test.json") + self.add_tests("ecdsa_secp224r1_sha3_512_test.json") + self.add_tests("ecdsa_secp224r1_sha512_p1363_test.json") + self.add_tests("ecdsa_secp224r1_sha512_test.json") + self.add_tests("ecdsa_secp256r1_sha256_p1363_test.json") + self.add_tests("ecdsa_secp256r1_sha256_test.json") + self.add_tests("ecdsa_secp256r1_sha3_256_test.json") + self.add_tests("ecdsa_secp256r1_sha3_512_test.json") + self.add_tests("ecdsa_secp256r1_sha512_p1363_test.json") + self.add_tests("ecdsa_secp256r1_sha512_test.json") + if self._slow_tests: + self.add_tests("ecdsa_secp384r1_sha3_384_test.json") + self.add_tests("ecdsa_secp384r1_sha3_512_test.json") + self.add_tests("ecdsa_secp384r1_sha384_p1363_test.json") + self.add_tests("ecdsa_secp384r1_sha384_test.json") + self.add_tests("ecdsa_secp384r1_sha512_p1363_test.json") + self.add_tests("ecdsa_secp384r1_sha512_test.json") + if self._slow_tests: + self.add_tests("ecdsa_secp521r1_sha3_512_test.json") + self.add_tests("ecdsa_secp521r1_sha512_p1363_test.json") + self.add_tests("ecdsa_secp521r1_sha512_test.json") + self.add_tests("ecdsa_test.json") + self.add_tests("ecdsa_webcrypto_test.json") + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof ECDSA Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + + # Skip tests with unsupported curves + if tv.key is None: + return + + hashed_msg = tv.hash_module.new(tv.msg) + signer = DSS.new(tv.key, "fips-186-3", encoding=tv.encoding) + try: + signature = signer.verify(hashed_msg, tv.sig) + except ValueError: + if tv.warning: + return + if tv.comment == "k*G has a large x-coordinate": + return + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(FIPS_DSA_Tests) + tests += list_test_cases(FIPS_ECDSA_Tests) + tests += list_test_cases(Det_DSA_Tests) + tests += list_test_cases(Det_ECDSA_Tests) + + slow_tests = config.get("slow_tests") + if slow_tests: + tests += list_test_cases(FIPS_DSA_Tests_KAT) + tests += list_test_cases(FIPS_ECDSA_Tests_KAT) - tests = [] - tests += list_test_cases(FIPS_DSA_Tests) - tests += list_test_cases(FIPS_ECDSA_Tests) - tests += list_test_cases(Det_DSA_Tests) - tests += list_test_cases(Det_ECDSA_Tests) + tests += [TestVectorsDSAWycheproof(wycheproof_warnings, slow_tests)] + tests += [TestVectorsECDSAWycheproof(wycheproof_warnings, slow_tests)] - slow_tests = config.get('slow_tests') - if slow_tests: - tests += list_test_cases(FIPS_DSA_Tests_KAT) - tests += list_test_cases(FIPS_ECDSA_Tests_KAT) + return tests - tests += [TestVectorsDSAWycheproof(wycheproof_warnings, slow_tests)] - tests += [TestVectorsECDSAWycheproof(wycheproof_warnings, slow_tests)] - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_eddsa.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_eddsa.py index 3215bbca..87859247 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_eddsa.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_eddsa.py @@ -38,567 +38,554 @@ from Cryptodome.Util.number import bytes_to_long rfc8032_tv_str = ( - # 7.1 Ed25519 - ( - "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", - "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", - "", - None, - "", - "e5564300c360ac729086e2cc806e828a" - "84877f1eb8e5d974d873e06522490155" - "5fb8821590a33bacc61e39701cf9b46b" - "d25bf5f0595bbe24655141438e7a100b" - ), - ( - "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", - "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", - "72", - None, - "", - "92a009a9f0d4cab8720e820b5f642540" - "a2b27b5416503f8fb3762223ebdb69da" - "085ac1e43e15996e458f3613d0f11d8c" - "387b2eaeb4302aeeb00d291612bb0c00" - ), - ( - "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", - "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", - "af82", - None, - "", - "6291d657deec24024827e69c3abe01a3" - "0ce548a284743a445e3680d7db5ac3ac" - "18ff9b538d16f290ae67f760984dc659" - "4a7c15e9716ed28dc027beceea1ec40a" - ), - ( - "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5", - "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", - "08b8b2b733424243760fe426a4b54908" - "632110a66c2f6591eabd3345e3e4eb98" - "fa6e264bf09efe12ee50f8f54e9f77b1" - "e355f6c50544e23fb1433ddf73be84d8" - "79de7c0046dc4996d9e773f4bc9efe57" - "38829adb26c81b37c93a1b270b20329d" - "658675fc6ea534e0810a4432826bf58c" - "941efb65d57a338bbd2e26640f89ffbc" - "1a858efcb8550ee3a5e1998bd177e93a" - "7363c344fe6b199ee5d02e82d522c4fe" - "ba15452f80288a821a579116ec6dad2b" - "3b310da903401aa62100ab5d1a36553e" - "06203b33890cc9b832f79ef80560ccb9" - "a39ce767967ed628c6ad573cb116dbef" - "efd75499da96bd68a8a97b928a8bbc10" - "3b6621fcde2beca1231d206be6cd9ec7" - "aff6f6c94fcd7204ed3455c68c83f4a4" - "1da4af2b74ef5c53f1d8ac70bdcb7ed1" - "85ce81bd84359d44254d95629e9855a9" - "4a7c1958d1f8ada5d0532ed8a5aa3fb2" - "d17ba70eb6248e594e1a2297acbbb39d" - "502f1a8c6eb6f1ce22b3de1a1f40cc24" - "554119a831a9aad6079cad88425de6bd" - "e1a9187ebb6092cf67bf2b13fd65f270" - "88d78b7e883c8759d2c4f5c65adb7553" - "878ad575f9fad878e80a0c9ba63bcbcc" - "2732e69485bbc9c90bfbd62481d9089b" - "eccf80cfe2df16a2cf65bd92dd597b07" - "07e0917af48bbb75fed413d238f5555a" - "7a569d80c3414a8d0859dc65a46128ba" - "b27af87a71314f318c782b23ebfe808b" - "82b0ce26401d2e22f04d83d1255dc51a" - "ddd3b75a2b1ae0784504df543af8969b" - "e3ea7082ff7fc9888c144da2af58429e" - "c96031dbcad3dad9af0dcbaaaf268cb8" - "fcffead94f3c7ca495e056a9b47acdb7" - "51fb73e666c6c655ade8297297d07ad1" - "ba5e43f1bca32301651339e22904cc8c" - "42f58c30c04aafdb038dda0847dd988d" - "cda6f3bfd15c4b4c4525004aa06eeff8" - "ca61783aacec57fb3d1f92b0fe2fd1a8" - "5f6724517b65e614ad6808d6f6ee34df" - "f7310fdc82aebfd904b01e1dc54b2927" - "094b2db68d6f903b68401adebf5a7e08" - "d78ff4ef5d63653a65040cf9bfd4aca7" - "984a74d37145986780fc0b16ac451649" - "de6188a7dbdf191f64b5fc5e2ab47b57" - "f7f7276cd419c17a3ca8e1b939ae49e4" - "88acba6b965610b5480109c8b17b80e1" - "b7b750dfc7598d5d5011fd2dcc5600a3" - "2ef5b52a1ecc820e308aa342721aac09" - "43bf6686b64b2579376504ccc493d97e" - "6aed3fb0f9cd71a43dd497f01f17c0e2" - "cb3797aa2a2f256656168e6c496afc5f" - "b93246f6b1116398a346f1a641f3b041" - "e989f7914f90cc2c7fff357876e506b5" - "0d334ba77c225bc307ba537152f3f161" - "0e4eafe595f6d9d90d11faa933a15ef1" - "369546868a7f3a45a96768d40fd9d034" - "12c091c6315cf4fde7cb68606937380d" - "b2eaaa707b4c4185c32eddcdd306705e" - "4dc1ffc872eeee475a64dfac86aba41c" - "0618983f8741c5ef68d3a101e8a3b8ca" - "c60c905c15fc910840b94c00a0b9d0", - None, - "", - "0aab4c900501b3e24d7cdf4663326a3a" - "87df5e4843b2cbdb67cbf6e460fec350" - "aa5371b1508f9f4528ecea23c436d94b" - "5e8fcd4f681e30a6ac00a9704a188a03" - ), - # 7.2 Ed25519ctx - ( - "0305334e381af78f141cb666f6199f57" - "bc3495335a256a95bd2a55bf546663f6", - "dfc9425e4f968f7f0c29f0259cf5f9ae" - "d6851c2bb4ad8bfb860cfee0ab248292", - "f726936d19c800494e3fdaff20b276a8", - None, - "666f6f", - "55a4cc2f70a54e04288c5f4cd1e45a7b" - "b520b36292911876cada7323198dd87a" - "8b36950b95130022907a7fb7c4e9b2d5" - "f6cca685a587b4b21f4b888e4e7edb0d" - ), - ( - "0305334e381af78f141cb666f6199f57" - "bc3495335a256a95bd2a55bf546663f6", - "dfc9425e4f968f7f0c29f0259cf5f9ae" - "d6851c2bb4ad8bfb860cfee0ab248292", - "f726936d19c800494e3fdaff20b276a8", - None, - "626172", - "fc60d5872fc46b3aa69f8b5b4351d580" - "8f92bcc044606db097abab6dbcb1aee3" - "216c48e8b3b66431b5b186d1d28f8ee1" - "5a5ca2df6668346291c2043d4eb3e90d" - ), - ( - "0305334e381af78f141cb666f6199f57" - "bc3495335a256a95bd2a55bf546663f6", - "dfc9425e4f968f7f0c29f0259cf5f9ae" - "d6851c2bb4ad8bfb860cfee0ab248292", - "508e9e6882b979fea900f62adceaca35", - None, - "666f6f", - "8b70c1cc8310e1de20ac53ce28ae6e72" - "07f33c3295e03bb5c0732a1d20dc6490" - "8922a8b052cf99b7c4fe107a5abb5b2c" - "4085ae75890d02df26269d8945f84b0b" - ), - ( - "ab9c2853ce297ddab85c993b3ae14bca" - "d39b2c682beabc27d6d4eb20711d6560", - "0f1d1274943b91415889152e893d80e9" - "3275a1fc0b65fd71b4b0dda10ad7d772", - "f726936d19c800494e3fdaff20b276a8", - None, - "666f6f", - "21655b5f1aa965996b3f97b3c849eafb" - "a922a0a62992f73b3d1b73106a84ad85" - "e9b86a7b6005ea868337ff2d20a7f5fb" - "d4cd10b0be49a68da2b2e0dc0ad8960f" - ), - # 7.3 Ed25519ph - ( - "833fe62409237b9d62ec77587520911e" - "9a759cec1d19755b7da901b96dca3d42", - "ec172b93ad5e563bf4932c70e1245034" - "c35467ef2efd4d64ebf819683467e2bf", - "616263", - SHA512, - "", - "98a70222f0b8121aa9d30f813d683f80" - "9e462b469c7ff87639499bb94e6dae41" - "31f85042463c2a355a2003d062adf5aa" - "a10b8c61e636062aaad11c2a26083406" - ), - # 7.4 Ed448 - ( - "6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3" - "528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b", - "5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778" - "edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180", - "", - None, - "", - "533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f" - "2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a" - "9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4db" - "b61149f05a7363268c71d95808ff2e652600" - ), - ( - "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463a" - "fbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e", - "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c086" - "6aea01eb00742802b8438ea4cb82169c235160627b4c3a9480", - "03", - None, - "", - "26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f435" - "2541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cb" - "cee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0f" - "f3348ab21aa4adafd1d234441cf807c03a00", - ), - ( - "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463a" - "fbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e", - "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c086" - "6aea01eb00742802b8438ea4cb82169c235160627b4c3a9480", - "03", - None, - "666f6f", - "d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2" - "151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da" - "1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d" - "5428407e85dcbc98a49155c13764e66c3c00", - ), - ( - "cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffd" - "f60500553abc0e05cd02184bdb89c4ccd67e187951267eb328", - "dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e3" - "65fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400", - "0c3e544074ec63b0265e0c", - None, - "", - "1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d3" - "89dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b05" - "1068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5" - "028961c9bf8ffd973fe5d5c206492b140e00", - ), - ( - "258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d93" - "9f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b", - "3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc" - "24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580", - "64a65f3cdedcdd66811e2915", - None, - "", - "7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4a" - "e90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457e" - "b1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861" - "e72003cbae6d6b8b827e4e6c143064ff3c00", - ), - ( - "7ef4e84544236752fbb56b8f31a23a10e42814f5f55ca037cdcc11c64c9a3b29" - "49c1bb60700314611732a6c2fea98eebc0266a11a93970100e", - "b3da079b0aa493a5772029f0467baebee5a8112d9d3a22532361da294f7bb381" - "5c5dc59e176b4d9f381ca0938e13c6c07b174be65dfa578e80", - "64a65f3cdedcdd66811e2915e7", - None, - "", - "6a12066f55331b6c22acd5d5bfc5d71228fbda80ae8dec26bdd306743c5027cb" - "4890810c162c027468675ecf645a83176c0d7323a2ccde2d80efe5a1268e8aca" - "1d6fbc194d3f77c44986eb4ab4177919ad8bec33eb47bbb5fc6e28196fd1caf5" - "6b4e7e0ba5519234d047155ac727a1053100", - ), - ( - "d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bf" - "f21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01", - "df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a" - "39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00", - "bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5" - "512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944", - None, - "", - "554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b1" - "8dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722e" - "f552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba" - "5f30e88e36ec2703b349ca229c2670833900", - ), - ( - "2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d3756" - "9b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5", - "79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9b" - "fe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00", - "15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567c" - "fa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89" - "e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072f" - "c1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a60" - "39c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b5" - "90316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce0" - "12d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409" - "a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11", - None, - "", - "c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f" - "00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a" - "61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc6" - "0987fd08527c1a8e80d5823e65cafe2a3d00", - ), - ( - "872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec" - "44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8", - "a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799d" - "a08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400", - "6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412" - "a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd" - "86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc" - "3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e9" - "72660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9" - "b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd32321" - "9b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab79717" - "2b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813" - "a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0" - "596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f520" - "96cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1" - "526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998" - "d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee" - "85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6" - "155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4" - "c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db9" - "77025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f041" - "0a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456" - "f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab" - "0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3" - "120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535" - "aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf969614" - "9e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67" - "a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a605" - "9d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263" - "be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d" - "02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c" - "392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e" - "79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd" - "7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4" - "b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695" - "568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87", - None, - "", - "e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bd" - "df7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d" - "76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed57" - "3603ce30d8bb761785dc30dbc320869e1a00" - ), - # 7.5 Ed448ph - ( - "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42" - "ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49", - "259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743" - "c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880", - "616263", - SHAKE256, - "", - "822f6901f7480f3d5f562c592994d9693602875614483256505600bbc281ae38" - "1f54d6bce2ea911574932f52a4e6cadd78769375ec3ffd1b801a0d9b3f4030cd" - "433964b6457ea39476511214f97469b57dd32dbc560a9a94d00bff07620464a3" - "ad203df7dc7ce360c3cd3696d9d9fab90f00" - ), - ( - "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42" - "ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49", - "259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743" - "c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880", - "616263", - SHAKE256, - "666f6f", - "c32299d46ec8ff02b54540982814dce9a05812f81962b649d528095916a2aa48" - "1065b1580423ef927ecf0af5888f90da0f6a9a85ad5dc3f280d91224ba9911a3" - "653d00e484e2ce232521481c8658df304bb7745a73514cdb9bf3e15784ab7128" - "4f8d0704a608c54a6b62d97beb511d132100", - ), + # 7.1 Ed25519 + ( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", + "", + None, + "", + "e5564300c360ac729086e2cc806e828a" + "84877f1eb8e5d974d873e06522490155" + "5fb8821590a33bacc61e39701cf9b46b" + "d25bf5f0595bbe24655141438e7a100b", + ), + ( + "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", + "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", + "72", + None, + "", + "92a009a9f0d4cab8720e820b5f642540" + "a2b27b5416503f8fb3762223ebdb69da" + "085ac1e43e15996e458f3613d0f11d8c" + "387b2eaeb4302aeeb00d291612bb0c00", + ), + ( + "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", + "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", + "af82", + None, + "", + "6291d657deec24024827e69c3abe01a3" + "0ce548a284743a445e3680d7db5ac3ac" + "18ff9b538d16f290ae67f760984dc659" + "4a7c15e9716ed28dc027beceea1ec40a", + ), + ( + "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5", + "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", + "08b8b2b733424243760fe426a4b54908" + "632110a66c2f6591eabd3345e3e4eb98" + "fa6e264bf09efe12ee50f8f54e9f77b1" + "e355f6c50544e23fb1433ddf73be84d8" + "79de7c0046dc4996d9e773f4bc9efe57" + "38829adb26c81b37c93a1b270b20329d" + "658675fc6ea534e0810a4432826bf58c" + "941efb65d57a338bbd2e26640f89ffbc" + "1a858efcb8550ee3a5e1998bd177e93a" + "7363c344fe6b199ee5d02e82d522c4fe" + "ba15452f80288a821a579116ec6dad2b" + "3b310da903401aa62100ab5d1a36553e" + "06203b33890cc9b832f79ef80560ccb9" + "a39ce767967ed628c6ad573cb116dbef" + "efd75499da96bd68a8a97b928a8bbc10" + "3b6621fcde2beca1231d206be6cd9ec7" + "aff6f6c94fcd7204ed3455c68c83f4a4" + "1da4af2b74ef5c53f1d8ac70bdcb7ed1" + "85ce81bd84359d44254d95629e9855a9" + "4a7c1958d1f8ada5d0532ed8a5aa3fb2" + "d17ba70eb6248e594e1a2297acbbb39d" + "502f1a8c6eb6f1ce22b3de1a1f40cc24" + "554119a831a9aad6079cad88425de6bd" + "e1a9187ebb6092cf67bf2b13fd65f270" + "88d78b7e883c8759d2c4f5c65adb7553" + "878ad575f9fad878e80a0c9ba63bcbcc" + "2732e69485bbc9c90bfbd62481d9089b" + "eccf80cfe2df16a2cf65bd92dd597b07" + "07e0917af48bbb75fed413d238f5555a" + "7a569d80c3414a8d0859dc65a46128ba" + "b27af87a71314f318c782b23ebfe808b" + "82b0ce26401d2e22f04d83d1255dc51a" + "ddd3b75a2b1ae0784504df543af8969b" + "e3ea7082ff7fc9888c144da2af58429e" + "c96031dbcad3dad9af0dcbaaaf268cb8" + "fcffead94f3c7ca495e056a9b47acdb7" + "51fb73e666c6c655ade8297297d07ad1" + "ba5e43f1bca32301651339e22904cc8c" + "42f58c30c04aafdb038dda0847dd988d" + "cda6f3bfd15c4b4c4525004aa06eeff8" + "ca61783aacec57fb3d1f92b0fe2fd1a8" + "5f6724517b65e614ad6808d6f6ee34df" + "f7310fdc82aebfd904b01e1dc54b2927" + "094b2db68d6f903b68401adebf5a7e08" + "d78ff4ef5d63653a65040cf9bfd4aca7" + "984a74d37145986780fc0b16ac451649" + "de6188a7dbdf191f64b5fc5e2ab47b57" + "f7f7276cd419c17a3ca8e1b939ae49e4" + "88acba6b965610b5480109c8b17b80e1" + "b7b750dfc7598d5d5011fd2dcc5600a3" + "2ef5b52a1ecc820e308aa342721aac09" + "43bf6686b64b2579376504ccc493d97e" + "6aed3fb0f9cd71a43dd497f01f17c0e2" + "cb3797aa2a2f256656168e6c496afc5f" + "b93246f6b1116398a346f1a641f3b041" + "e989f7914f90cc2c7fff357876e506b5" + "0d334ba77c225bc307ba537152f3f161" + "0e4eafe595f6d9d90d11faa933a15ef1" + "369546868a7f3a45a96768d40fd9d034" + "12c091c6315cf4fde7cb68606937380d" + "b2eaaa707b4c4185c32eddcdd306705e" + "4dc1ffc872eeee475a64dfac86aba41c" + "0618983f8741c5ef68d3a101e8a3b8ca" + "c60c905c15fc910840b94c00a0b9d0", + None, + "", + "0aab4c900501b3e24d7cdf4663326a3a" + "87df5e4843b2cbdb67cbf6e460fec350" + "aa5371b1508f9f4528ecea23c436d94b" + "5e8fcd4f681e30a6ac00a9704a188a03", + ), + # 7.2 Ed25519ctx + ( + "0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6", + "dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292", + "f726936d19c800494e3fdaff20b276a8", + None, + "666f6f", + "55a4cc2f70a54e04288c5f4cd1e45a7b" + "b520b36292911876cada7323198dd87a" + "8b36950b95130022907a7fb7c4e9b2d5" + "f6cca685a587b4b21f4b888e4e7edb0d", + ), + ( + "0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6", + "dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292", + "f726936d19c800494e3fdaff20b276a8", + None, + "626172", + "fc60d5872fc46b3aa69f8b5b4351d580" + "8f92bcc044606db097abab6dbcb1aee3" + "216c48e8b3b66431b5b186d1d28f8ee1" + "5a5ca2df6668346291c2043d4eb3e90d", + ), + ( + "0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6", + "dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292", + "508e9e6882b979fea900f62adceaca35", + None, + "666f6f", + "8b70c1cc8310e1de20ac53ce28ae6e72" + "07f33c3295e03bb5c0732a1d20dc6490" + "8922a8b052cf99b7c4fe107a5abb5b2c" + "4085ae75890d02df26269d8945f84b0b", + ), + ( + "ab9c2853ce297ddab85c993b3ae14bcad39b2c682beabc27d6d4eb20711d6560", + "0f1d1274943b91415889152e893d80e93275a1fc0b65fd71b4b0dda10ad7d772", + "f726936d19c800494e3fdaff20b276a8", + None, + "666f6f", + "21655b5f1aa965996b3f97b3c849eafb" + "a922a0a62992f73b3d1b73106a84ad85" + "e9b86a7b6005ea868337ff2d20a7f5fb" + "d4cd10b0be49a68da2b2e0dc0ad8960f", + ), + # 7.3 Ed25519ph + ( + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42", + "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf", + "616263", + SHA512, + "", + "98a70222f0b8121aa9d30f813d683f80" + "9e462b469c7ff87639499bb94e6dae41" + "31f85042463c2a355a2003d062adf5aa" + "a10b8c61e636062aaad11c2a26083406", + ), + # 7.4 Ed448 + ( + "6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3" + "528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b", + "5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778" + "edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180", + "", + None, + "", + "533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f" + "2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a" + "9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4db" + "b61149f05a7363268c71d95808ff2e652600", + ), + ( + "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463a" + "fbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e", + "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c086" + "6aea01eb00742802b8438ea4cb82169c235160627b4c3a9480", + "03", + None, + "", + "26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f435" + "2541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cb" + "cee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0f" + "f3348ab21aa4adafd1d234441cf807c03a00", + ), + ( + "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463a" + "fbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e", + "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c086" + "6aea01eb00742802b8438ea4cb82169c235160627b4c3a9480", + "03", + None, + "666f6f", + "d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2" + "151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da" + "1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d" + "5428407e85dcbc98a49155c13764e66c3c00", + ), + ( + "cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffd" + "f60500553abc0e05cd02184bdb89c4ccd67e187951267eb328", + "dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e3" + "65fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400", + "0c3e544074ec63b0265e0c", + None, + "", + "1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d3" + "89dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b05" + "1068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5" + "028961c9bf8ffd973fe5d5c206492b140e00", + ), + ( + "258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d93" + "9f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b", + "3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc" + "24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580", + "64a65f3cdedcdd66811e2915", + None, + "", + "7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4a" + "e90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457e" + "b1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861" + "e72003cbae6d6b8b827e4e6c143064ff3c00", + ), + ( + "7ef4e84544236752fbb56b8f31a23a10e42814f5f55ca037cdcc11c64c9a3b29" + "49c1bb60700314611732a6c2fea98eebc0266a11a93970100e", + "b3da079b0aa493a5772029f0467baebee5a8112d9d3a22532361da294f7bb381" + "5c5dc59e176b4d9f381ca0938e13c6c07b174be65dfa578e80", + "64a65f3cdedcdd66811e2915e7", + None, + "", + "6a12066f55331b6c22acd5d5bfc5d71228fbda80ae8dec26bdd306743c5027cb" + "4890810c162c027468675ecf645a83176c0d7323a2ccde2d80efe5a1268e8aca" + "1d6fbc194d3f77c44986eb4ab4177919ad8bec33eb47bbb5fc6e28196fd1caf5" + "6b4e7e0ba5519234d047155ac727a1053100", + ), + ( + "d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bf" + "f21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01", + "df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a" + "39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00", + "bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5" + "512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944", + None, + "", + "554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b1" + "8dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722e" + "f552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba" + "5f30e88e36ec2703b349ca229c2670833900", + ), + ( + "2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d3756" + "9b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5", + "79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9b" + "fe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00", + "15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567c" + "fa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89" + "e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072f" + "c1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a60" + "39c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b5" + "90316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce0" + "12d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409" + "a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11", + None, + "", + "c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f" + "00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a" + "61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc6" + "0987fd08527c1a8e80d5823e65cafe2a3d00", + ), + ( + "872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec" + "44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8", + "a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799d" + "a08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400", + "6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412" + "a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd" + "86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc" + "3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e9" + "72660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9" + "b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd32321" + "9b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab79717" + "2b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813" + "a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0" + "596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f520" + "96cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1" + "526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998" + "d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee" + "85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6" + "155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4" + "c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db9" + "77025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f041" + "0a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456" + "f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab" + "0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3" + "120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535" + "aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf969614" + "9e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67" + "a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a605" + "9d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263" + "be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d" + "02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c" + "392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e" + "79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd" + "7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4" + "b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695" + "568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87", + None, + "", + "e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bd" + "df7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d" + "76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed57" + "3603ce30d8bb761785dc30dbc320869e1a00", + ), + # 7.5 Ed448ph + ( + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42" + "ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49", + "259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743" + "c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880", + "616263", + SHAKE256, + "", + "822f6901f7480f3d5f562c592994d9693602875614483256505600bbc281ae38" + "1f54d6bce2ea911574932f52a4e6cadd78769375ec3ffd1b801a0d9b3f4030cd" + "433964b6457ea39476511214f97469b57dd32dbc560a9a94d00bff07620464a3" + "ad203df7dc7ce360c3cd3696d9d9fab90f00", + ), + ( + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42" + "ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49", + "259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743" + "c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880", + "616263", + SHAKE256, + "666f6f", + "c32299d46ec8ff02b54540982814dce9a05812f81962b649d528095916a2aa48" + "1065b1580423ef927ecf0af5888f90da0f6a9a85ad5dc3f280d91224ba9911a3" + "653d00e484e2ce232521481c8658df304bb7745a73514cdb9bf3e15784ab7128" + "4f8d0704a608c54a6b62d97beb511d132100", + ), ) rfc8032_tv_bytes = [] for tv_str in rfc8032_tv_str: - rfc8032_tv_bytes.append([unhexlify(i) if isinstance(i, str) else i for i in tv_str]) + rfc8032_tv_bytes.append([unhexlify(i) if isinstance(i, str) else i for i in tv_str]) class TestEdDSA(unittest.TestCase): - - def test_sign(self): - for sk, _, msg, hashmod, ctx, exp_signature in rfc8032_tv_bytes: - key = eddsa.import_private_key(sk) - signer = eddsa.new(key, 'rfc8032', context=ctx) - if hashmod is None: - # PureEdDSA - signature = signer.sign(msg) - else: - # HashEdDSA - hashobj = hashmod.new(msg) - signature = signer.sign(hashobj) - self.assertEqual(exp_signature, signature) - - def test_verify(self): - for _, pk, msg, hashmod, ctx, exp_signature in rfc8032_tv_bytes: - key = eddsa.import_public_key(pk) - verifier = eddsa.new(key, 'rfc8032', context=ctx) - if hashmod is None: - # PureEdDSA - verifier.verify(msg, exp_signature) - else: - # HashEdDSA - hashobj = hashmod.new(msg) - verifier.verify(hashobj, exp_signature) - - def test_double_sign_verify_ed25519(self): - msg_hash = SHA512.new(b'abc') - key = ECC.generate(curve='ed25519') - signer = eddsa.new(key, 'rfc8032') - verifier = eddsa.new(key, 'rfc8032') - - signature = signer.sign(msg_hash) - signature2 = signer.sign(msg_hash) - self.assertEqual(signature, signature2) - - verifier.verify(msg_hash, signature) - verifier.verify(msg_hash, signature) - - def test_double_sign_verify_ed448(self): - msg_hash = SHAKE256.new(b'abc') - key = ECC.generate(curve='ed448') - signer = eddsa.new(key, 'rfc8032') - verifier = eddsa.new(key, 'rfc8032') - - signature = signer.sign(msg_hash) - signature2 = signer.sign(msg_hash) - self.assertEqual(signature, signature2) - - verifier.verify(msg_hash, signature) - verifier.verify(msg_hash, signature) - - def test_negative(self): - key = ECC.generate(curve="ed25519") - self.assertRaises(ValueError, eddsa.new, key, 'rfc9999') - - nist_key = ECC.generate(curve="p256") - self.assertRaises(ValueError, eddsa.new, nist_key, 'rfc8032') + def test_sign(self): + for sk, _, msg, hashmod, ctx, exp_signature in rfc8032_tv_bytes: + key = eddsa.import_private_key(sk) + signer = eddsa.new(key, "rfc8032", context=ctx) + if hashmod is None: + # PureEdDSA + signature = signer.sign(msg) + else: + # HashEdDSA + hashobj = hashmod.new(msg) + signature = signer.sign(hashobj) + self.assertEqual(exp_signature, signature) + + def test_verify(self): + for _, pk, msg, hashmod, ctx, exp_signature in rfc8032_tv_bytes: + key = eddsa.import_public_key(pk) + verifier = eddsa.new(key, "rfc8032", context=ctx) + if hashmod is None: + # PureEdDSA + verifier.verify(msg, exp_signature) + else: + # HashEdDSA + hashobj = hashmod.new(msg) + verifier.verify(hashobj, exp_signature) + + def test_double_sign_verify_ed25519(self): + msg_hash = SHA512.new(b"abc") + key = ECC.generate(curve="ed25519") + signer = eddsa.new(key, "rfc8032") + verifier = eddsa.new(key, "rfc8032") + + signature = signer.sign(msg_hash) + signature2 = signer.sign(msg_hash) + self.assertEqual(signature, signature2) + + verifier.verify(msg_hash, signature) + verifier.verify(msg_hash, signature) + + def test_double_sign_verify_ed448(self): + msg_hash = SHAKE256.new(b"abc") + key = ECC.generate(curve="ed448") + signer = eddsa.new(key, "rfc8032") + verifier = eddsa.new(key, "rfc8032") + + signature = signer.sign(msg_hash) + signature2 = signer.sign(msg_hash) + self.assertEqual(signature, signature2) + + verifier.verify(msg_hash, signature) + verifier.verify(msg_hash, signature) + + def test_negative(self): + key = ECC.generate(curve="ed25519") + self.assertRaises(ValueError, eddsa.new, key, "rfc9999") + + nist_key = ECC.generate(curve="p256") + self.assertRaises(ValueError, eddsa.new, nist_key, "rfc8032") class TestExport_Ed25519(unittest.TestCase): + def test_raw(self): + key = ECC.generate(curve="Ed25519") + x, y = key.pointQ.xy + raw = bytearray(key._export_eddsa_public()) + sign_x = raw[31] >> 7 + raw[31] &= 0x7F + yt = bytes_to_long(raw[::-1]) + self.assertEqual(y, yt) + self.assertEqual(x & 1, sign_x) - def test_raw(self): - key = ECC.generate(curve="Ed25519") - x, y = key.pointQ.xy - raw = bytearray(key._export_eddsa_public()) - sign_x = raw[31] >> 7 - raw[31] &= 0x7F - yt = bytes_to_long(raw[::-1]) - self.assertEqual(y, yt) - self.assertEqual(x & 1, sign_x) - - key = ECC.construct(point_x=0, point_y=1, curve="Ed25519") - out = key._export_eddsa_public() - self.assertEqual(b'\x01' + b'\x00' * 31, out) + key = ECC.construct(point_x=0, point_y=1, curve="Ed25519") + out = key._export_eddsa_public() + self.assertEqual(b"\x01" + b"\x00" * 31, out) class TestExport_Ed448(unittest.TestCase): + def test_raw(self): + key = ECC.generate(curve="Ed448") + x, y = key.pointQ.xy + raw = bytearray(key._export_eddsa_public()) + sign_x = raw[56] >> 7 + raw[56] &= 0x7F + yt = bytes_to_long(raw[::-1]) + self.assertEqual(y, yt) + self.assertEqual(x & 1, sign_x) - def test_raw(self): - key = ECC.generate(curve="Ed448") - x, y = key.pointQ.xy - raw = bytearray(key._export_eddsa_public()) - sign_x = raw[56] >> 7 - raw[56] &= 0x7F - yt = bytes_to_long(raw[::-1]) - self.assertEqual(y, yt) - self.assertEqual(x & 1, sign_x) - - key = ECC.construct(point_x=0, point_y=1, curve="Ed448") - out = key._export_eddsa_public() - self.assertEqual(b'\x01' + b'\x00' * 56, out) + key = ECC.construct(point_x=0, point_y=1, curve="Ed448") + out = key._export_eddsa_public() + self.assertEqual(b"\x01" + b"\x00" * 56, out) class TestImport_Ed25519(unittest.TestCase): + def test_raw(self): + Px = 24407857220263921307776619664228778204996144802740950419837658238229122415920 + Py = 56480760040633817885061096979765646085062883740629155052073094891081309750690 + encoded = b"\xa2\x05\xd6\x00\xe1 \xe1\xc0\xff\x96\xee?V\x8e\xba/\xd3\x89\x06\xd7\xc4c\xe8$\xc2d\xd7a1\xfa\xde|" + key = eddsa.import_public_key(encoded) + self.assertEqual(Py, key.pointQ.y) + self.assertEqual(Px, key.pointQ.x) - def test_raw(self): - Px = 24407857220263921307776619664228778204996144802740950419837658238229122415920 - Py = 56480760040633817885061096979765646085062883740629155052073094891081309750690 - encoded = b'\xa2\x05\xd6\x00\xe1 \xe1\xc0\xff\x96\xee?V\x8e\xba/\xd3\x89\x06\xd7\xc4c\xe8$\xc2d\xd7a1\xfa\xde|' - key = eddsa.import_public_key(encoded) - self.assertEqual(Py, key.pointQ.y) - self.assertEqual(Px, key.pointQ.x) - - encoded = b'\x01' + b'\x00' * 31 - key = eddsa.import_public_key(encoded) - self.assertEqual(1, key.pointQ.y) - self.assertEqual(0, key.pointQ.x) + encoded = b"\x01" + b"\x00" * 31 + key = eddsa.import_public_key(encoded) + self.assertEqual(1, key.pointQ.y) + self.assertEqual(0, key.pointQ.x) class TestImport_Ed448(unittest.TestCase): - - def test_raw(self): - Px = 0x153f42025aba3b0daecaa5cd79458b3146c7c9378c16c17b4a59bc3561113d90c169045bc12966c3f93e140c2ca0a3acc33d9205b9daf9b1 - Py = 0x38f5c0015d3dedd576c232810dd90373b5b1d631a12894c043b7be529cbae03ede177d8fa490b56131dbcb2465d2aba777ef839fc1719b25 - encoded = unhexlify("259b71c19f83ef77a7abd26524cbdb31" - "61b590a48f7d17de3ee0ba9c52beb743" - "c09428a131d6b1b57303d90d8132c276" - "d5ed3d5d01c0f53880") - key = eddsa.import_public_key(encoded) - self.assertEqual(Py, key.pointQ.y) - self.assertEqual(Px, key.pointQ.x) - - encoded = b'\x01' + b'\x00' * 56 - key = eddsa.import_public_key(encoded) - self.assertEqual(1, key.pointQ.y) - self.assertEqual(0, key.pointQ.x) + def test_raw(self): + Px = 0x153F42025ABA3B0DAECAA5CD79458B3146C7C9378C16C17B4A59BC3561113D90C169045BC12966C3F93E140C2CA0A3ACC33D9205B9DAF9B1 + Py = 0x38F5C0015D3DEDD576C232810DD90373B5B1D631A12894C043B7BE529CBAE03EDE177D8FA490B56131DBCB2465D2ABA777EF839FC1719B25 + encoded = unhexlify( + "259b71c19f83ef77a7abd26524cbdb31" + "61b590a48f7d17de3ee0ba9c52beb743" + "c09428a131d6b1b57303d90d8132c276" + "d5ed3d5d01c0f53880", + ) + key = eddsa.import_public_key(encoded) + self.assertEqual(Py, key.pointQ.y) + self.assertEqual(Px, key.pointQ.x) + + encoded = b"\x01" + b"\x00" * 56 + key = eddsa.import_public_key(encoded) + self.assertEqual(1, key.pointQ.y) + self.assertEqual(0, key.pointQ.x) class TestVectorsEdDSAWycheproof(unittest.TestCase): - - def add_tests(self, filename): - - def pk(group): - elem = group['key']['pk'] - return unhexlify(elem) - - def sk(group): - elem = group['key']['sk'] - return unhexlify(elem) - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof ECDSA signature (%s)" - % filename, - group_tag={'pk': pk, 'sk': sk}) - self.tv += result - - def setUp(self): - self.tv = [] - self.add_tests("eddsa_test.json") - self.add_tests("ed448_test.json") - - def test_sign(self, tv): - if not tv.valid: - return - - self._id = "Wycheproof EdDSA Sign Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - key = eddsa.import_private_key(tv.sk) - signer = eddsa.new(key, 'rfc8032') - signature = signer.sign(tv.msg) - self.assertEqual(signature, tv.sig) - - def test_verify(self, tv): - self._id = "Wycheproof EdDSA Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - key = eddsa.import_public_key(tv.pk) - verifier = eddsa.new(key, 'rfc8032') - try: - verifier.verify(tv.msg, tv.sig) - except ValueError: - assert not tv.valid - else: - assert tv.valid - - def runTest(self): - for tv in self.tv: - self.test_sign(tv) - self.test_verify(tv) + def add_tests(self, filename): + def pk(group): + elem = group["key"]["pk"] + return unhexlify(elem) + + def sk(group): + elem = group["key"]["sk"] + return unhexlify(elem) + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + filename, + "Wycheproof ECDSA signature (%s)" % filename, + group_tag={"pk": pk, "sk": sk}, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.add_tests("eddsa_test.json") + self.add_tests("ed448_test.json") + + def test_sign(self, tv): + if not tv.valid: + return + + self._id = "Wycheproof EdDSA Sign Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + key = eddsa.import_private_key(tv.sk) + signer = eddsa.new(key, "rfc8032") + signature = signer.sign(tv.msg) + self.assertEqual(signature, tv.sig) + + def test_verify(self, tv): + self._id = "Wycheproof EdDSA Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + key = eddsa.import_public_key(tv.pk) + verifier = eddsa.new(key, "rfc8032") + try: + verifier.verify(tv.msg, tv.sig) + except ValueError: + assert not tv.valid + else: + assert tv.valid + + def runTest(self): + for tv in self.tv: + self.test_sign(tv) + self.test_verify(tv) def get_tests(config={}): + tests = [] + tests += list_test_cases(TestExport_Ed25519) + tests += list_test_cases(TestExport_Ed448) + tests += list_test_cases(TestImport_Ed25519) + tests += list_test_cases(TestImport_Ed448) + tests += list_test_cases(TestEdDSA) + tests += [TestVectorsEdDSAWycheproof()] + return tests + - tests = [] - tests += list_test_cases(TestExport_Ed25519) - tests += list_test_cases(TestExport_Ed448) - tests += list_test_cases(TestImport_Ed25519) - tests += list_test_cases(TestImport_Ed448) - tests += list_test_cases(TestEdDSA) - tests += [TestVectorsEdDSAWycheproof()] - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_pkcs1_15.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_pkcs1_15.py index 3a3e30b5..309f9ce9 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_pkcs1_15.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_pkcs1_15.py @@ -28,7 +28,6 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -import json import unittest from binascii import unhexlify @@ -38,118 +37,139 @@ from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof -from Cryptodome.Hash import (SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_384, - SHA3_224, SHA3_256, SHA3_512) +from Cryptodome.Hash import ( + SHA1, + SHA224, + SHA256, + SHA384, + SHA512, + SHA3_384, + SHA3_224, + SHA3_256, + SHA3_512, +) from Cryptodome.PublicKey import RSA from Cryptodome.Signature import pkcs1_15 from Cryptodome.Signature import PKCS1_v1_5 -from Cryptodome.Util._file_system import pycryptodome_filename -from Cryptodome.Util.strxor import strxor - def load_hash_by_name(hash_name): - return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) + return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) class FIPS_PKCS1_Verify_Tests(unittest.TestCase): + def shortDescription(self): + return "FIPS PKCS1 Tests (Verify)" - def shortDescription(self): - return "FIPS PKCS1 Tests (Verify)" - - def test_can_sign(self): - test_public_key = RSA.generate(1024).public_key() - verifier = pkcs1_15.new(test_public_key) - self.assertEqual(verifier.can_sign(), False) + def test_can_sign(self): + test_public_key = RSA.generate(1024).public_key() + verifier = pkcs1_15.new(test_public_key) + self.assertEqual(verifier.can_sign(), False) class FIPS_PKCS1_Verify_Tests_KAT(unittest.TestCase): - pass + pass -test_vectors_verify = load_test_vectors(("Signature", "PKCS1-v1.5"), - "SigVer15_186-3.rsp", - "Signature Verification 186-3", - {'shaalg': lambda x: x, - 'd': lambda x: int(x), - 'result': lambda x: x}) or [] +test_vectors_verify = ( + load_test_vectors( + ("Signature", "PKCS1-v1.5"), + "SigVer15_186-3.rsp", + "Signature Verification 186-3", + { + "shaalg": lambda x: x, + "d": lambda x: int(x), + "result": lambda x: x, + }, + ) + or [] +) for count, tv in enumerate(test_vectors_verify): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue + if isinstance(tv, str): + continue + if hasattr(tv, "n"): + modulus = tv.n + continue - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore - verifier = pkcs1_15.new(public_key) + hash_module = load_hash_by_name(tv.shaalg.upper()) + hash_obj = hash_module.new(tv.msg) + public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore + verifier = pkcs1_15.new(public_key) - def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - verifier.verify(hash_obj, signature) + def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): + verifier.verify(hash_obj, signature) - def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) + def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): + self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - if tv.result == 'f': - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) - else: - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) + if tv.result == "f": + setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) + else: + setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) class FIPS_PKCS1_Sign_Tests(unittest.TestCase): + def shortDescription(self): + return "FIPS PKCS1 Tests (Sign)" - def shortDescription(self): - return "FIPS PKCS1 Tests (Sign)" - - def test_can_sign(self): - test_private_key = RSA.generate(1024) - signer = pkcs1_15.new(test_private_key) - self.assertEqual(signer.can_sign(), True) + def test_can_sign(self): + test_private_key = RSA.generate(1024) + signer = pkcs1_15.new(test_private_key) + self.assertEqual(signer.can_sign(), True) class FIPS_PKCS1_Sign_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_sign = load_test_vectors(("Signature", "PKCS1-v1.5"), - "SigGen15_186-2.txt", - "Signature Generation 186-2", - {'shaalg': lambda x: x}) or [] - -test_vectors_sign += load_test_vectors(("Signature", "PKCS1-v1.5"), - "SigGen15_186-3.txt", - "Signature Generation 186-3", - {'shaalg': lambda x: x}) or [] + pass + + +test_vectors_sign = ( + load_test_vectors( + ("Signature", "PKCS1-v1.5"), + "SigGen15_186-2.txt", + "Signature Generation 186-2", + {"shaalg": lambda x: x}, + ) + or [] +) + +test_vectors_sign += ( + load_test_vectors( + ("Signature", "PKCS1-v1.5"), + "SigGen15_186-3.txt", + "Signature Generation 186-3", + {"shaalg": lambda x: x}, + ) + or [] +) for count, tv in enumerate(test_vectors_sign): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - if hasattr(tv, "e"): - private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore - signer = pkcs1_15.new(private_key) - continue + if isinstance(tv, str): + continue + if hasattr(tv, "n"): + modulus = tv.n + continue + if hasattr(tv, "e"): + private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore + signer = pkcs1_15.new(private_key) + continue - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) + hash_module = load_hash_by_name(tv.shaalg.upper()) + hash_obj = hash_module.new(tv.msg) - def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): - signature = signer.sign(hash_obj) - self.assertEqual(signature, result) + def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): + signature = signer.sign(hash_obj) + self.assertEqual(signature, result) - setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) + setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) class PKCS1_15_NoParams(unittest.TestCase): - """Verify that PKCS#1 v1.5 signatures pass even without NULL parameters in - the algorithm identifier (PyCrypto/LP bug #1119552).""" + """Verify that PKCS#1 v1.5 signatures pass even without NULL parameters in + the algorithm identifier (PyCrypto/LP bug #1119552).""" - rsakey = """-----BEGIN RSA PRIVATE KEY----- + rsakey = """-----BEGIN RSA PRIVATE KEY----- MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8 Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI @@ -159,190 +179,207 @@ class PKCS1_15_NoParams(unittest.TestCase): n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ== -----END RSA PRIVATE KEY-----""" - msg = b"This is a test\x0a" + msg = b"This is a test\x0a" - # PKCS1 v1.5 signature of the message computed using SHA-1. - # The digestAlgorithm SEQUENCE does NOT contain the NULL parameter. - sig_str = "a287a13517f716e72fb14eea8e33a8db4a4643314607e7ca3e3e28"\ - "1893db74013dda8b855fd99f6fecedcb25fcb7a434f35cd0a101f8"\ - "b19348e0bd7b6f152dfc" - signature = unhexlify(sig_str) + # PKCS1 v1.5 signature of the message computed using SHA-1. + # The digestAlgorithm SEQUENCE does NOT contain the NULL parameter. + sig_str = ( + "a287a13517f716e72fb14eea8e33a8db4a4643314607e7ca3e3e28" + "1893db74013dda8b855fd99f6fecedcb25fcb7a434f35cd0a101f8" + "b19348e0bd7b6f152dfc" + ) + signature = unhexlify(sig_str) - def runTest(self): - verifier = pkcs1_15.new(RSA.importKey(self.rsakey)) - hashed = SHA1.new(self.msg) - verifier.verify(hashed, self.signature) + def runTest(self): + verifier = pkcs1_15.new(RSA.importKey(self.rsakey)) + hashed = SHA1.new(self.msg) + verifier.verify(hashed, self.signature) class PKCS1_Legacy_Module_Tests(unittest.TestCase): - """Verify that the legacy module Cryptodome.Signature.PKCS1_v1_5 - behaves as expected. The only difference is that the verify() - method returns True/False and does not raise exceptions.""" + """Verify that the legacy module Cryptodome.Signature.PKCS1_v1_5 + behaves as expected. The only difference is that the verify() + method returns True/False and does not raise exceptions.""" - def shortDescription(self): - return "Test legacy Cryptodome.Signature.PKCS1_v1_5" + def shortDescription(self): + return "Test legacy Cryptodome.Signature.PKCS1_v1_5" - def runTest(self): - key = RSA.importKey(PKCS1_15_NoParams.rsakey) - hashed = SHA1.new(b"Test") - good_signature = PKCS1_v1_5.new(key).sign(hashed) - verifier = PKCS1_v1_5.new(key.public_key()) + def runTest(self): + key = RSA.importKey(PKCS1_15_NoParams.rsakey) + hashed = SHA1.new(b"Test") + good_signature = PKCS1_v1_5.new(key).sign(hashed) + verifier = PKCS1_v1_5.new(key.public_key()) - self.assertEqual(verifier.verify(hashed, good_signature), True) + self.assertEqual(verifier.verify(hashed, good_signature), True) - # Flip a few bits in the signature - bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) - self.assertEqual(verifier.verify(hashed, bad_signature), False) + # Flip a few bits in the signature + bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) + self.assertEqual(verifier.verify(hashed, bad_signature), False) class PKCS1_All_Hashes_Tests(unittest.TestCase): - - def shortDescription(self): - return "Test PKCS#1v1.5 signature in combination with all hashes" - - def runTest(self): - - key = RSA.generate(1024) - signer = pkcs1_15.new(key) - hash_names = ("MD2", "MD4", "MD5", "RIPEMD160", "SHA1", - "SHA224", "SHA256", "SHA384", "SHA512", - "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512") - - for name in hash_names: - hashed = load_hash_by_name(name).new(b"Test") - signer.sign(hashed) - - from Cryptodome.Hash import BLAKE2b, BLAKE2s - for hash_size in (20, 32, 48, 64): - hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b"Test") - signer.sign(hashed_b) - for hash_size in (16, 20, 28, 32): - hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b"Test") - signer.sign(hashed_s) + def shortDescription(self): + return "Test PKCS#1v1.5 signature in combination with all hashes" + + def runTest(self): + key = RSA.generate(1024) + signer = pkcs1_15.new(key) + hash_names = ( + "MD2", + "MD4", + "MD5", + "RIPEMD160", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA3_224", + "SHA3_256", + "SHA3_384", + "SHA3_512", + ) + + for name in hash_names: + hashed = load_hash_by_name(name).new(b"Test") + signer.sign(hashed) + + from Cryptodome.Hash import BLAKE2b, BLAKE2s + + for hash_size in (20, 32, 48, 64): + hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b"Test") + signer.sign(hashed_b) + for hash_size in (16, 20, 28, 32): + hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b"Test") + signer.sign(hashed_s) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def setUp(self): - self.tv = [] - self.add_tests("rsa_sig_gen_misc_test.json") - self.add_tests("rsa_signature_2048_sha224_test.json") - self.add_tests("rsa_signature_2048_sha256_test.json") - self.add_tests("rsa_signature_2048_sha384_test.json") - self.add_tests("rsa_signature_2048_sha3_224_test.json") - self.add_tests("rsa_signature_2048_sha3_256_test.json") - self.add_tests("rsa_signature_2048_sha3_384_test.json") - self.add_tests("rsa_signature_2048_sha3_512_test.json") - self.add_tests("rsa_signature_2048_sha512_test.json") - self.add_tests("rsa_signature_2048_sha512_224_test.json") - self.add_tests("rsa_signature_2048_sha512_256_test.json") - self.add_tests("rsa_signature_3072_sha256_test.json") - self.add_tests("rsa_signature_3072_sha384_test.json") - self.add_tests("rsa_signature_3072_sha3_256_test.json") - self.add_tests("rsa_signature_3072_sha3_384_test.json") - self.add_tests("rsa_signature_3072_sha3_512_test.json") - self.add_tests("rsa_signature_3072_sha512_test.json") - self.add_tests("rsa_signature_3072_sha512_256_test.json") - self.add_tests("rsa_signature_4096_sha384_test.json") - self.add_tests("rsa_signature_4096_sha512_test.json") - self.add_tests("rsa_signature_4096_sha512_256_test.json") - self.add_tests("rsa_signature_test.json") - - def add_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['keyPem']) - - def filter_sha(group): - hash_name = group['sha'] - if hash_name == "SHA-512": - return SHA512 - elif hash_name == "SHA-512/224": - return SHA512.new(truncate="224") - elif hash_name == "SHA-512/256": - return SHA512.new(truncate="256") - elif hash_name == "SHA3-512": - return SHA3_512 - elif hash_name == "SHA-384": - return SHA384 - elif hash_name == "SHA3-384": - return SHA3_384 - elif hash_name == "SHA-256": - return SHA256 - elif hash_name == "SHA3-256": - return SHA3_256 - elif hash_name == "SHA-224": - return SHA224 - elif hash_name == "SHA3-224": - return SHA3_224 - elif hash_name == "SHA-1": - return SHA1 - else: - raise ValueError("Unknown hash algorithm: " + hash_name) - - def filter_type(group): - type_name = group['type'] - if type_name not in ("RsassaPkcs1Verify", "RsassaPkcs1Generate"): - raise ValueError("Unknown type name " + type_name) - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof PKCS#1v1.5 signature (%s)" % filename, - group_tag={'rsa_key': filter_rsa, - 'hash_mod': filter_sha, - 'type': filter_type}) - return result - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof RSA PKCS$#1 Test #" + str(tv.id) - - hashed_msg = tv.hash_module.new(tv.msg) - signer = pkcs1_15.new(tv.key) - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def setUp(self): + self.tv = [] + self.add_tests("rsa_sig_gen_misc_test.json") + self.add_tests("rsa_signature_2048_sha224_test.json") + self.add_tests("rsa_signature_2048_sha256_test.json") + self.add_tests("rsa_signature_2048_sha384_test.json") + self.add_tests("rsa_signature_2048_sha3_224_test.json") + self.add_tests("rsa_signature_2048_sha3_256_test.json") + self.add_tests("rsa_signature_2048_sha3_384_test.json") + self.add_tests("rsa_signature_2048_sha3_512_test.json") + self.add_tests("rsa_signature_2048_sha512_test.json") + self.add_tests("rsa_signature_2048_sha512_224_test.json") + self.add_tests("rsa_signature_2048_sha512_256_test.json") + self.add_tests("rsa_signature_3072_sha256_test.json") + self.add_tests("rsa_signature_3072_sha384_test.json") + self.add_tests("rsa_signature_3072_sha3_256_test.json") + self.add_tests("rsa_signature_3072_sha3_384_test.json") + self.add_tests("rsa_signature_3072_sha3_512_test.json") + self.add_tests("rsa_signature_3072_sha512_test.json") + self.add_tests("rsa_signature_3072_sha512_256_test.json") + self.add_tests("rsa_signature_4096_sha384_test.json") + self.add_tests("rsa_signature_4096_sha512_test.json") + self.add_tests("rsa_signature_4096_sha512_256_test.json") + self.add_tests("rsa_signature_test.json") + + def add_tests(self, filename): + def filter_rsa(group): + return RSA.import_key(group["keyPem"]) + + def filter_sha(group): + hash_name = group["sha"] + if hash_name == "SHA-512": + return SHA512 + elif hash_name == "SHA-512/224": + return SHA512.new(truncate="224") + elif hash_name == "SHA-512/256": + return SHA512.new(truncate="256") + elif hash_name == "SHA3-512": + return SHA3_512 + elif hash_name == "SHA-384": + return SHA384 + elif hash_name == "SHA3-384": + return SHA3_384 + elif hash_name == "SHA-256": + return SHA256 + elif hash_name == "SHA3-256": + return SHA3_256 + elif hash_name == "SHA-224": + return SHA224 + elif hash_name == "SHA3-224": + return SHA3_224 + elif hash_name == "SHA-1": + return SHA1 + else: + raise ValueError("Unknown hash algorithm: " + hash_name) + + def filter_type(group): + type_name = group["type"] + if type_name not in ("RsassaPkcs1Verify", "RsassaPkcs1Generate"): + raise ValueError("Unknown type name " + type_name) + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + filename, + "Wycheproof PKCS#1v1.5 signature (%s)" % filename, + group_tag={ + "rsa_key": filter_rsa, + "hash_mod": filter_sha, + "type": filter_type, + }, + ) + return result + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof RSA PKCS$#1 Test #" + str(tv.id) + + hashed_msg = tv.hash_module.new(tv.msg) + signer = pkcs1_15.new(tv.key) + try: + signature = signer.verify(hashed_msg, tv.sig) + except ValueError: + if tv.warning: + return + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(FIPS_PKCS1_Verify_Tests) + tests += list_test_cases(FIPS_PKCS1_Sign_Tests) + tests += list_test_cases(PKCS1_15_NoParams) + tests += list_test_cases(PKCS1_Legacy_Module_Tests) + tests += list_test_cases(PKCS1_All_Hashes_Tests) + tests += [TestVectorsWycheproof(wycheproof_warnings)] - tests = [] - tests += list_test_cases(FIPS_PKCS1_Verify_Tests) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests) - tests += list_test_cases(PKCS1_15_NoParams) - tests += list_test_cases(PKCS1_Legacy_Module_Tests) - tests += list_test_cases(PKCS1_All_Hashes_Tests) - tests += [ TestVectorsWycheproof(wycheproof_warnings) ] + if config.get("slow_tests"): + tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) + tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) - if config.get('slow_tests'): - tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) + return tests - return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_pss.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_pss.py index c3b1ce56..fbf441d5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_pss.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Signature/test_pss.py @@ -45,333 +45,362 @@ def load_hash_by_name(hash_name): - return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) + return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) class PRNG(object): + def __init__(self, stream): + self.stream = stream + self.idx = 0 - def __init__(self, stream): - self.stream = stream - self.idx = 0 - - def __call__(self, rnd_size): - result = self.stream[self.idx:self.idx + rnd_size] - self.idx += rnd_size - return result + def __call__(self, rnd_size): + result = self.stream[self.idx : self.idx + rnd_size] + self.idx += rnd_size + return result class PSS_Tests(unittest.TestCase): - - rsa_key = b'-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAsvI34FgiTK8+txBvmooNGpNwk23YTU51dwNZi5yha3W4lA/Q\nvcZrDalkmD7ekWQwnduxVKa6pRSI13KBgeUOIqJoGXSWhntEtY3FEwvWOHW5AE7Q\njUzTzCiYT6TVaCcpa/7YLai+p6ai2g5f5Zfh4jSawa9uYeuggFygQq4IVW796MgV\nyqxYMM/arEj+/sKz3Viua9Rp9fFosertCYCX4DUTgW0mX9bwEnEOgjSI3pLOPXz1\n8vx+DRZS5wMCmwCUa0sKonLn3cAUPq+sGix7+eo7T0Z12MU8ud7IYVX/75r3cXiF\nPaYE2q8Le0kgOApIXbb+x74x0rNgyIh1yGygkwIDAQABAoIBABz4t1A0pLT6qHI2\nEIOaNz3mwhK0dZEqkz0GB1Dhtoax5ATgvKCFB98J3lYB08IBURe1snOsnMpOVUtg\naBRSM+QqnCUG6bnzKjAkuFP5liDE+oNQv1YpKp9CsUovuzdmI8Au3ewihl+ZTIN2\nUVNYMEOR1b5m+z2SSwWNOYsiJwpBrT7zkpdlDyjat7FiiPhMMIMXjhQFVxURMIcB\njUBtPzGvV/PG90cVDWi1wRGeeP1dDqti/jsnvykQ15KW1MqGrpeNKRmDdTy/Ucl1\nWIoYklKw3U456lgZ/rDTDB818+Tlnk35z4yF7d5ANPM8CKfqOPcnO1BCKVFzf4eq\n54wvUtkCgYEA1Zv2lp06l7rXMsvNtyYQjbFChezRDRnPwZmN4NCdRtTgGG1G0Ryd\nYz6WWoPGqZp0b4LAaaHd3W2GTcpXF8WXMKfMX1W+tMAxMozfsXRKMcHoypwuS5wT\nfJRXJCG4pvd57AB0iVUEJW2we+uGKU5Zxcx//id2nXGCpoRyViIplQsCgYEA1nVC\neHupHChht0Fh4N09cGqZHZzuwXjOUMzR3Vsfz+4WzVS3NvIgN4g5YgmQFOeKwo5y\niRq5yvubcNdFvf85eHWClg0zPAyxJCVUWigCrrOanGEhJo6re4idJvNVzu4Ucg0v\n6B3SJ1HsCda+ZSNz24bSyqRep8A+RoAaoVSFx5kCgYEAn3RvXPs9s+obnqWYiPF3\nRe5etE6Vt2vfNKwFxx6zaR6bsmBQjuUHcABWiHb6I71S0bMPI0tbrWGG8ibrYKl1\nNTLtUvVVCOS3VP7oNTWT9RTFTAnOXU7DFSo+6o/poWn3r36ff6zhDXeWWMr2OXtt\ndEQ1/2lCGEGVv+v61eVmmQUCgYABFHITPTwqwiFL1O5zPWnzyPWgaovhOYSAb6eW\n38CXQXGn8wdBJZL39J2lWrr4//l45VK6UgIhfYbY2JynSkO10ZGow8RARygVMILu\nOUlaK9lZdDvAf/NpGdUAvzTtZ9F+iYZ2OsA2JnlzyzsGM1l//3vMPWukmJk3ral0\nqoJJ8QKBgGRG3eVHnIegBbFVuMDp2NTcfuSuDVUQ1fGAwtPiFa8u81IodJnMk2pq\niXu2+0ytNA/M+SVrAnE2AgIzcaJbtr0p2srkuVM7KMWnG1vWFNjtXN8fAhf/joOv\nD+NmPL/N4uE57e40tbiU/H7KdyZaDt+5QiTmdhuyAe6CBjKsF2jy\n-----END RSA PRIVATE KEY-----' - msg = b'AAA' - tag = b'\x00[c5\xd8\xb0\x8b!D\x81\x83\x07\xc0\xdd\xb9\xb4\xb2`\x92\xe7\x02\xf1\xe1P\xea\xc3\xf0\xe3>\xddX5\xdd\x8e\xc5\x89\xef\xf3\xc2\xdc\xfeP\x02\x7f\x12+\xc9\xaf\xbb\xec\xfe\xb0\xa5\xb9\x08\x11P\x8fL\xee5\x9b\xb0k{=_\xd2\x14\xfb\x01R\xb7\xfe\x14}b\x03\x8d5Y\x89~}\xfc\xf2l\xd01-\xbd\xeb\x11\xcdV\x11\xe9l\x19k/o5\xa2\x0f\x15\xe7Q$\t=\xec\x1dAB\x19\xa5P\x9a\xaf\xa3G\x86"\xd6~\xf0j\xfcqkbs\x13\x84b\xe4\xbdm(\xed`\xa4F\xfb\x8f.\xe1\x8c)/_\x9eS\x98\xa4v\xb8\xdc\xfe\xf7/D\x18\x19\xb3T\x97:\xe2\x96s\xe8<\xa2\xb4\xb9\xf8/' - - def test_positive_1(self): - key = RSA.import_key(self.rsa_key) - h = SHA256.new(self.msg) - verifier = pss.new(key) - verifier.verify(h, self.tag) - - def test_negative_1(self): - key = RSA.import_key(self.rsa_key) - h = SHA256.new(self.msg + b'A') - verifier = pss.new(key) - tag = bytearray(self.tag) - self.assertRaises(ValueError, verifier.verify, h, tag) - - def test_negative_2(self): - key = RSA.import_key(self.rsa_key) - h = SHA256.new(self.msg) - verifier = pss.new(key, salt_bytes=1000) - tag = bytearray(self.tag) - self.assertRaises(ValueError, verifier.verify, h, tag) + rsa_key = b"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAsvI34FgiTK8+txBvmooNGpNwk23YTU51dwNZi5yha3W4lA/Q\nvcZrDalkmD7ekWQwnduxVKa6pRSI13KBgeUOIqJoGXSWhntEtY3FEwvWOHW5AE7Q\njUzTzCiYT6TVaCcpa/7YLai+p6ai2g5f5Zfh4jSawa9uYeuggFygQq4IVW796MgV\nyqxYMM/arEj+/sKz3Viua9Rp9fFosertCYCX4DUTgW0mX9bwEnEOgjSI3pLOPXz1\n8vx+DRZS5wMCmwCUa0sKonLn3cAUPq+sGix7+eo7T0Z12MU8ud7IYVX/75r3cXiF\nPaYE2q8Le0kgOApIXbb+x74x0rNgyIh1yGygkwIDAQABAoIBABz4t1A0pLT6qHI2\nEIOaNz3mwhK0dZEqkz0GB1Dhtoax5ATgvKCFB98J3lYB08IBURe1snOsnMpOVUtg\naBRSM+QqnCUG6bnzKjAkuFP5liDE+oNQv1YpKp9CsUovuzdmI8Au3ewihl+ZTIN2\nUVNYMEOR1b5m+z2SSwWNOYsiJwpBrT7zkpdlDyjat7FiiPhMMIMXjhQFVxURMIcB\njUBtPzGvV/PG90cVDWi1wRGeeP1dDqti/jsnvykQ15KW1MqGrpeNKRmDdTy/Ucl1\nWIoYklKw3U456lgZ/rDTDB818+Tlnk35z4yF7d5ANPM8CKfqOPcnO1BCKVFzf4eq\n54wvUtkCgYEA1Zv2lp06l7rXMsvNtyYQjbFChezRDRnPwZmN4NCdRtTgGG1G0Ryd\nYz6WWoPGqZp0b4LAaaHd3W2GTcpXF8WXMKfMX1W+tMAxMozfsXRKMcHoypwuS5wT\nfJRXJCG4pvd57AB0iVUEJW2we+uGKU5Zxcx//id2nXGCpoRyViIplQsCgYEA1nVC\neHupHChht0Fh4N09cGqZHZzuwXjOUMzR3Vsfz+4WzVS3NvIgN4g5YgmQFOeKwo5y\niRq5yvubcNdFvf85eHWClg0zPAyxJCVUWigCrrOanGEhJo6re4idJvNVzu4Ucg0v\n6B3SJ1HsCda+ZSNz24bSyqRep8A+RoAaoVSFx5kCgYEAn3RvXPs9s+obnqWYiPF3\nRe5etE6Vt2vfNKwFxx6zaR6bsmBQjuUHcABWiHb6I71S0bMPI0tbrWGG8ibrYKl1\nNTLtUvVVCOS3VP7oNTWT9RTFTAnOXU7DFSo+6o/poWn3r36ff6zhDXeWWMr2OXtt\ndEQ1/2lCGEGVv+v61eVmmQUCgYABFHITPTwqwiFL1O5zPWnzyPWgaovhOYSAb6eW\n38CXQXGn8wdBJZL39J2lWrr4//l45VK6UgIhfYbY2JynSkO10ZGow8RARygVMILu\nOUlaK9lZdDvAf/NpGdUAvzTtZ9F+iYZ2OsA2JnlzyzsGM1l//3vMPWukmJk3ral0\nqoJJ8QKBgGRG3eVHnIegBbFVuMDp2NTcfuSuDVUQ1fGAwtPiFa8u81IodJnMk2pq\niXu2+0ytNA/M+SVrAnE2AgIzcaJbtr0p2srkuVM7KMWnG1vWFNjtXN8fAhf/joOv\nD+NmPL/N4uE57e40tbiU/H7KdyZaDt+5QiTmdhuyAe6CBjKsF2jy\n-----END RSA PRIVATE KEY-----" + msg = b"AAA" + tag = b'\x00[c5\xd8\xb0\x8b!D\x81\x83\x07\xc0\xdd\xb9\xb4\xb2`\x92\xe7\x02\xf1\xe1P\xea\xc3\xf0\xe3>\xddX5\xdd\x8e\xc5\x89\xef\xf3\xc2\xdc\xfeP\x02\x7f\x12+\xc9\xaf\xbb\xec\xfe\xb0\xa5\xb9\x08\x11P\x8fL\xee5\x9b\xb0k{=_\xd2\x14\xfb\x01R\xb7\xfe\x14}b\x03\x8d5Y\x89~}\xfc\xf2l\xd01-\xbd\xeb\x11\xcdV\x11\xe9l\x19k/o5\xa2\x0f\x15\xe7Q$\t=\xec\x1dAB\x19\xa5P\x9a\xaf\xa3G\x86"\xd6~\xf0j\xfcqkbs\x13\x84b\xe4\xbdm(\xed`\xa4F\xfb\x8f.\xe1\x8c)/_\x9eS\x98\xa4v\xb8\xdc\xfe\xf7/D\x18\x19\xb3T\x97:\xe2\x96s\xe8<\xa2\xb4\xb9\xf8/' + + def test_positive_1(self): + key = RSA.import_key(self.rsa_key) + h = SHA256.new(self.msg) + verifier = pss.new(key) + verifier.verify(h, self.tag) + + def test_negative_1(self): + key = RSA.import_key(self.rsa_key) + h = SHA256.new(self.msg + b"A") + verifier = pss.new(key) + tag = bytearray(self.tag) + self.assertRaises(ValueError, verifier.verify, h, tag) + + def test_negative_2(self): + key = RSA.import_key(self.rsa_key) + h = SHA256.new(self.msg) + verifier = pss.new(key, salt_bytes=1000) + tag = bytearray(self.tag) + self.assertRaises(ValueError, verifier.verify, h, tag) class FIPS_PKCS1_Verify_Tests(unittest.TestCase): + def shortDescription(self): + return "FIPS PKCS1 Tests (Verify)" - def shortDescription(self): - return "FIPS PKCS1 Tests (Verify)" + def verify_positive(self, hashmod, message, public_key, salt, signature): + prng = PRNG(salt) + hashed = hashmod.new(message) + verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) + verifier.verify(hashed, signature) - def verify_positive(self, hashmod, message, public_key, salt, signature): - prng = PRNG(salt) - hashed = hashmod.new(message) - verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) - verifier.verify(hashed, signature) + def verify_negative(self, hashmod, message, public_key, salt, signature): + prng = PRNG(salt) + hashed = hashmod.new(message) + verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) + self.assertRaises(ValueError, verifier.verify, hashed, signature) - def verify_negative(self, hashmod, message, public_key, salt, signature): - prng = PRNG(salt) - hashed = hashmod.new(message) - verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) - self.assertRaises(ValueError, verifier.verify, hashed, signature) - - def test_can_sign(self): - test_public_key = RSA.generate(1024).public_key() - verifier = pss.new(test_public_key) - self.assertEqual(verifier.can_sign(), False) + def test_can_sign(self): + test_public_key = RSA.generate(1024).public_key() + verifier = pss.new(test_public_key) + self.assertEqual(verifier.can_sign(), False) class FIPS_PKCS1_Verify_Tests_KAT(unittest.TestCase): - pass + pass -test_vectors_verify = load_test_vectors(("Signature", "PKCS1-PSS"), - "SigVerPSS_186-3.rsp", - "Signature Verification 186-3", - {'shaalg': lambda x: x, - 'result': lambda x: x}) or [] +test_vectors_verify = ( + load_test_vectors( + ("Signature", "PKCS1-PSS"), + "SigVerPSS_186-3.rsp", + "Signature Verification 186-3", + { + "shaalg": lambda x: x, + "result": lambda x: x, + }, + ) + or [] +) for count, tv in enumerate(test_vectors_verify): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - if hasattr(tv, "p"): - continue - - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore - if tv.saltval != b("\x00"): - prng = PRNG(tv.saltval) - verifier = pss.new(public_key, salt_bytes=len(tv.saltval), rand_func=prng) - else: - verifier = pss.new(public_key, salt_bytes=0) - - def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result == 'p': - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) - else: - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) + if isinstance(tv, str): + continue + if hasattr(tv, "n"): + modulus = tv.n + continue + if hasattr(tv, "p"): + continue + + hash_module = load_hash_by_name(tv.shaalg.upper()) + hash_obj = hash_module.new(tv.msg) + public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore + if tv.saltval != b("\x00"): + prng = PRNG(tv.saltval) + verifier = pss.new(public_key, salt_bytes=len(tv.saltval), rand_func=prng) + else: + verifier = pss.new(public_key, salt_bytes=0) + + def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): + verifier.verify(hash_obj, signature) + + def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): + self.assertRaises(ValueError, verifier.verify, hash_obj, signature) + + if tv.result == "p": + setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) + else: + setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) class FIPS_PKCS1_Sign_Tests(unittest.TestCase): + def shortDescription(self): + return "FIPS PKCS1 Tests (Sign)" - def shortDescription(self): - return "FIPS PKCS1 Tests (Sign)" - - def test_can_sign(self): - test_private_key = RSA.generate(1024) - signer = pss.new(test_private_key) - self.assertEqual(signer.can_sign(), True) + def test_can_sign(self): + test_private_key = RSA.generate(1024) + signer = pss.new(test_private_key) + self.assertEqual(signer.can_sign(), True) class FIPS_PKCS1_Sign_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_sign = load_test_vectors(("Signature", "PKCS1-PSS"), - "SigGenPSS_186-2.txt", - "Signature Generation 186-2", - {'shaalg': lambda x: x}) or [] - -test_vectors_sign += load_test_vectors(("Signature", "PKCS1-PSS"), - "SigGenPSS_186-3.txt", - "Signature Generation 186-3", - {'shaalg': lambda x: x}) or [] + pass + + +test_vectors_sign = ( + load_test_vectors( + ("Signature", "PKCS1-PSS"), + "SigGenPSS_186-2.txt", + "Signature Generation 186-2", + {"shaalg": lambda x: x}, + ) + or [] +) + +test_vectors_sign += ( + load_test_vectors( + ("Signature", "PKCS1-PSS"), + "SigGenPSS_186-3.txt", + "Signature Generation 186-3", + {"shaalg": lambda x: x}, + ) + or [] +) for count, tv in enumerate(test_vectors_sign): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - if hasattr(tv, "e"): - private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore - continue - - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - if tv.saltval != b("\x00"): - prng = PRNG(tv.saltval) - signer = pss.new(private_key, salt_bytes=len(tv.saltval), rand_func=prng) - else: - signer = pss.new(private_key, salt_bytes=0) - - def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): - signature = signer.sign(hash_obj) - self.assertEqual(signature, result) - - setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) + if isinstance(tv, str): + continue + if hasattr(tv, "n"): + modulus = tv.n + continue + if hasattr(tv, "e"): + private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore + continue + + hash_module = load_hash_by_name(tv.shaalg.upper()) + hash_obj = hash_module.new(tv.msg) + if tv.saltval != b("\x00"): + prng = PRNG(tv.saltval) + signer = pss.new(private_key, salt_bytes=len(tv.saltval), rand_func=prng) + else: + signer = pss.new(private_key, salt_bytes=0) + + def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): + signature = signer.sign(hash_obj) + self.assertEqual(signature, result) + + setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) class PKCS1_Legacy_Module_Tests(unittest.TestCase): - """Verify that the legacy module Cryptodome.Signature.PKCS1_PSS - behaves as expected. The only difference is that the verify() - method returns True/False and does not raise exceptions.""" + """Verify that the legacy module Cryptodome.Signature.PKCS1_PSS + behaves as expected. The only difference is that the verify() + method returns True/False and does not raise exceptions.""" - def shortDescription(self): - return "Test legacy Cryptodome.Signature.PKCS1_PSS" + def shortDescription(self): + return "Test legacy Cryptodome.Signature.PKCS1_PSS" - def runTest(self): - key = RSA.generate(1024) - hashed = SHA1.new(b("Test")) - good_signature = PKCS1_PSS.new(key).sign(hashed) - verifier = PKCS1_PSS.new(key.public_key()) + def runTest(self): + key = RSA.generate(1024) + hashed = SHA1.new(b("Test")) + good_signature = PKCS1_PSS.new(key).sign(hashed) + verifier = PKCS1_PSS.new(key.public_key()) - self.assertEqual(verifier.verify(hashed, good_signature), True) + self.assertEqual(verifier.verify(hashed, good_signature), True) - # Flip a few bits in the signature - bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) - self.assertEqual(verifier.verify(hashed, bad_signature), False) + # Flip a few bits in the signature + bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) + self.assertEqual(verifier.verify(hashed, bad_signature), False) class PKCS1_All_Hashes_Tests(unittest.TestCase): - - def shortDescription(self): - return "Test PKCS#1 PSS signature in combination with all hashes" - - def runTest(self): - - key = RSA.generate(1280) - signer = pss.new(key) - hash_names = ("MD2", "MD4", "MD5", "RIPEMD160", "SHA1", - "SHA224", "SHA256", "SHA384", "SHA512", - "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512") - - for name in hash_names: - hashed = load_hash_by_name(name).new(b("Test")) - signer.sign(hashed) - - from Cryptodome.Hash import BLAKE2b, BLAKE2s - for hash_size in (20, 32, 48, 64): - hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b("Test")) - signer.sign(hashed_b) - for hash_size in (16, 20, 28, 32): - hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b("Test")) - signer.sign(hashed_s) + def shortDescription(self): + return "Test PKCS#1 PSS signature in combination with all hashes" + + def runTest(self): + key = RSA.generate(1280) + signer = pss.new(key) + hash_names = ( + "MD2", + "MD4", + "MD5", + "RIPEMD160", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA3_224", + "SHA3_256", + "SHA3_384", + "SHA3_512", + ) + + for name in hash_names: + hashed = load_hash_by_name(name).new(b("Test")) + signer.sign(hashed) + + from Cryptodome.Hash import BLAKE2b, BLAKE2s + + for hash_size in (20, 32, 48, 64): + hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b("Test")) + signer.sign(hashed_b) + for hash_size in (16, 20, 28, 32): + hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b("Test")) + signer.sign(hashed_s) def get_hash_module(hash_name): - if hash_name == "SHA-512": - hash_module = SHA512 - elif hash_name == "SHA-512/224": - hash_module = SHA512.new(truncate="224") - elif hash_name == "SHA-512/256": - hash_module = SHA512.new(truncate="256") - elif hash_name == "SHA-384": - hash_module = SHA384 - elif hash_name == "SHA-256": - hash_module = SHA256 - elif hash_name == "SHA-224": - hash_module = SHA224 - elif hash_name == "SHA-1": - hash_module = SHA1 - else: - raise ValueError("Unknown hash algorithm: " + hash_name) - return hash_module + if hash_name == "SHA-512": + hash_module = SHA512 + elif hash_name == "SHA-512/224": + hash_module = SHA512.new(truncate="224") + elif hash_name == "SHA-512/256": + hash_module = SHA512.new(truncate="256") + elif hash_name == "SHA-384": + hash_module = SHA384 + elif hash_name == "SHA-256": + hash_module = SHA256 + elif hash_name == "SHA-224": + hash_module = SHA224 + elif hash_name == "SHA-1": + hash_module = SHA1 + else: + raise ValueError("Unknown hash algorithm: " + hash_name) + return hash_module class TestVectorsPSSWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def add_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['keyPem']) - - def filter_sha(group): - return get_hash_module(group['sha']) - - def filter_type(group): - type_name = group['type'] - if type_name not in ("RsassaPssVerify", ): - raise ValueError("Unknown type name " + type_name) - - def filter_slen(group): - return group['sLen'] - - def filter_mgf(group): - mgf = group['mgf'] - if mgf not in ("MGF1", ): - raise ValueError("Unknown MGF " + mgf) - mgf1_hash = get_hash_module(group['mgfSha']) - - def mgf(x, y, mh=mgf1_hash): - return MGF1(x, y, mh) - - return mgf - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof PSS signature (%s)" % filename, - group_tag={'key': filter_rsa, - 'hash_module': filter_sha, - 'sLen': filter_slen, - 'mgf': filter_mgf, - 'type': filter_type}) - return result - - def setUp(self): - self.tv = [] - self.add_tests("rsa_pss_2048_sha1_mgf1_20_test.json") - self.add_tests("rsa_pss_2048_sha256_mgf1_0_test.json") - self.add_tests("rsa_pss_2048_sha256_mgf1_32_test.json") - self.add_tests("rsa_pss_2048_sha512_256_mgf1_28_test.json") - self.add_tests("rsa_pss_2048_sha512_256_mgf1_32_test.json") - self.add_tests("rsa_pss_3072_sha256_mgf1_32_test.json") - self.add_tests("rsa_pss_4096_sha256_mgf1_32_test.json") - self.add_tests("rsa_pss_4096_sha512_mgf1_32_test.json") - self.add_tests("rsa_pss_misc_test.json") - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof RSA PSS Test #%d (%s)" % (tv.id, tv.comment) - - hashed_msg = tv.hash_module.new(tv.msg) - signer = pss.new(tv.key, mask_func=tv.mgf, salt_bytes=tv.sLen) - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def add_tests(self, filename): + def filter_rsa(group): + return RSA.import_key(group["keyPem"]) + + def filter_sha(group): + return get_hash_module(group["sha"]) + + def filter_type(group): + type_name = group["type"] + if type_name not in ("RsassaPssVerify",): + raise ValueError("Unknown type name " + type_name) + + def filter_slen(group): + return group["sLen"] + + def filter_mgf(group): + mgf = group["mgf"] + if mgf not in ("MGF1",): + raise ValueError("Unknown MGF " + mgf) + mgf1_hash = get_hash_module(group["mgfSha"]) + + def mgf(x, y, mh=mgf1_hash): + return MGF1(x, y, mh) + + return mgf + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + filename, + "Wycheproof PSS signature (%s)" % filename, + group_tag={ + "key": filter_rsa, + "hash_module": filter_sha, + "sLen": filter_slen, + "mgf": filter_mgf, + "type": filter_type, + }, + ) + return result + + def setUp(self): + self.tv = [] + self.add_tests("rsa_pss_2048_sha1_mgf1_20_test.json") + self.add_tests("rsa_pss_2048_sha256_mgf1_0_test.json") + self.add_tests("rsa_pss_2048_sha256_mgf1_32_test.json") + self.add_tests("rsa_pss_2048_sha512_256_mgf1_28_test.json") + self.add_tests("rsa_pss_2048_sha512_256_mgf1_32_test.json") + self.add_tests("rsa_pss_3072_sha256_mgf1_32_test.json") + self.add_tests("rsa_pss_4096_sha256_mgf1_32_test.json") + self.add_tests("rsa_pss_4096_sha512_mgf1_32_test.json") + self.add_tests("rsa_pss_misc_test.json") + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof RSA PSS Test #%d (%s)" % (tv.id, tv.comment) + + hashed_msg = tv.hash_module.new(tv.msg) + signer = pss.new(tv.key, mask_func=tv.mgf, salt_bytes=tv.sLen) + try: + signature = signer.verify(hashed_msg, tv.sig) + except ValueError: + if tv.warning: + return + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(PSS_Tests) + tests += list_test_cases(FIPS_PKCS1_Verify_Tests) + tests += list_test_cases(FIPS_PKCS1_Sign_Tests) + tests += list_test_cases(PKCS1_Legacy_Module_Tests) + tests += list_test_cases(PKCS1_All_Hashes_Tests) + + if config.get("slow_tests"): + tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) + tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) - tests = [] - tests += list_test_cases(PSS_Tests) - tests += list_test_cases(FIPS_PKCS1_Verify_Tests) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests) - tests += list_test_cases(PKCS1_Legacy_Module_Tests) - tests += list_test_cases(PKCS1_All_Hashes_Tests) + tests += [TestVectorsPSSWycheproof(wycheproof_warnings)] - if config.get('slow_tests'): - tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) + return tests - tests += [TestVectorsPSSWycheproof(wycheproof_warnings)] - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/__init__.py index e52c4901..56f5bc9d 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/__init__.py @@ -28,19 +28,34 @@ import os + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Util import test_number; tests += test_number.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_Counter; tests += test_Counter.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_Padding; tests += test_Padding.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_strxor; tests += test_strxor.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_asn1; tests += test_asn1.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_rfc1751; tests += test_rfc1751.get_tests(config=config) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + from Cryptodome.SelfTest.Util import test_number + + tests += test_number.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_Counter + + tests += test_Counter.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_Padding + + tests += test_Padding.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_strxor + + tests += test_strxor.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_asn1 + + tests += test_asn1.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_rfc1751 + + tests += test_rfc1751.get_tests(config=config) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_Counter.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_Counter.py index 0d1e0897..b0b8560b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_Counter.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_Counter.py @@ -28,40 +28,44 @@ import unittest + class CounterTests(unittest.TestCase): - def setUp(self): - global Counter - from Cryptodome.Util import Counter + def setUp(self): + global Counter + from Cryptodome.Util import Counter + + def test_BE(self): + """Big endian""" + c = Counter.new(128) + c = Counter.new(128, little_endian=False) - def test_BE(self): - """Big endian""" - c = Counter.new(128) - c = Counter.new(128, little_endian=False) + def test_LE(self): + """Little endian""" + c = Counter.new(128, little_endian=True) - def test_LE(self): - """Little endian""" - c = Counter.new(128, little_endian=True) + def test_nbits(self): + c = Counter.new(nbits=128) + self.assertRaises(ValueError, Counter.new, 129) - def test_nbits(self): - c = Counter.new(nbits=128) - self.assertRaises(ValueError, Counter.new, 129) + def test_prefix(self): + c = Counter.new(128, prefix=b("xx")) - def test_prefix(self): - c = Counter.new(128, prefix=b("xx")) + def test_suffix(self): + c = Counter.new(128, suffix=b("xx")) - def test_suffix(self): - c = Counter.new(128, suffix=b("xx")) + def test_iv(self): + c = Counter.new(128, initial_value=2) + self.assertRaises(ValueError, Counter.new, 16, initial_value=0x1FFFF) - def test_iv(self): - c = Counter.new(128, initial_value=2) - self.assertRaises(ValueError, Counter.new, 16, initial_value=0x1FFFF) def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - return list_test_cases(CounterTests) + from Cryptodome.SelfTest.st_common import list_test_cases + + return list_test_cases(CounterTests) + -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_Padding.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_Padding.py index a9c3eb67..1d78a8ec 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_Padding.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_Padding.py @@ -38,116 +38,117 @@ from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Util.Padding import pad, unpad + class PKCS7_Tests(unittest.TestCase): + def test1(self): + padded = pad(b(""), 4) + self.assertTrue(padded == uh(b("04040404"))) + padded = pad(b(""), 4, "pkcs7") + self.assertTrue(padded == uh(b("04040404"))) + back = unpad(padded, 4) + self.assertTrue(back == b("")) + + def test2(self): + padded = pad(uh(b("12345678")), 4) + self.assertTrue(padded == uh(b("1234567804040404"))) + back = unpad(padded, 4) + self.assertTrue(back == uh(b("12345678"))) + + def test3(self): + padded = pad(uh(b("123456")), 4) + self.assertTrue(padded == uh(b("12345601"))) + back = unpad(padded, 4) + self.assertTrue(back == uh(b("123456"))) + + def test4(self): + padded = pad(uh(b("1234567890")), 4) + self.assertTrue(padded == uh(b("1234567890030303"))) + back = unpad(padded, 4) + self.assertTrue(back == uh(b("1234567890"))) + + def testn1(self): + self.assertRaises(ValueError, pad, uh(b("12")), 4, "pkcs8") + + def testn2(self): + self.assertRaises(ValueError, unpad, b("\0\0\0"), 4) + self.assertRaises(ValueError, unpad, b(""), 4) + + def testn3(self): + self.assertRaises(ValueError, unpad, b("123456\x02"), 4) + self.assertRaises(ValueError, unpad, b("123456\x00"), 4) + self.assertRaises(ValueError, unpad, b("123456\x05\x05\x05\x05\x05"), 4) - def test1(self): - padded = pad(b(""), 4) - self.assertTrue(padded == uh(b("04040404"))) - padded = pad(b(""), 4, 'pkcs7') - self.assertTrue(padded == uh(b("04040404"))) - back = unpad(padded, 4) - self.assertTrue(back == b("")) - - def test2(self): - padded = pad(uh(b("12345678")), 4) - self.assertTrue(padded == uh(b("1234567804040404"))) - back = unpad(padded, 4) - self.assertTrue(back == uh(b("12345678"))) - - def test3(self): - padded = pad(uh(b("123456")), 4) - self.assertTrue(padded == uh(b("12345601"))) - back = unpad(padded, 4) - self.assertTrue(back == uh(b("123456"))) - - def test4(self): - padded = pad(uh(b("1234567890")), 4) - self.assertTrue(padded == uh(b("1234567890030303"))) - back = unpad(padded, 4) - self.assertTrue(back == uh(b("1234567890"))) - - def testn1(self): - self.assertRaises(ValueError, pad, uh(b("12")), 4, 'pkcs8') - - def testn2(self): - self.assertRaises(ValueError, unpad, b("\0\0\0"), 4) - self.assertRaises(ValueError, unpad, b(""), 4) - - def testn3(self): - self.assertRaises(ValueError, unpad, b("123456\x02"), 4) - self.assertRaises(ValueError, unpad, b("123456\x00"), 4) - self.assertRaises(ValueError, unpad, b("123456\x05\x05\x05\x05\x05"), 4) class X923_Tests(unittest.TestCase): + def test1(self): + padded = pad(b(""), 4, "x923") + self.assertTrue(padded == uh(b("00000004"))) + back = unpad(padded, 4, "x923") + self.assertTrue(back == b("")) + + def test2(self): + padded = pad(uh(b("12345678")), 4, "x923") + self.assertTrue(padded == uh(b("1234567800000004"))) + back = unpad(padded, 4, "x923") + self.assertTrue(back == uh(b("12345678"))) + + def test3(self): + padded = pad(uh(b("123456")), 4, "x923") + self.assertTrue(padded == uh(b("12345601"))) + back = unpad(padded, 4, "x923") + self.assertTrue(back == uh(b("123456"))) + + def test4(self): + padded = pad(uh(b("1234567890")), 4, "x923") + self.assertTrue(padded == uh(b("1234567890000003"))) + back = unpad(padded, 4, "x923") + self.assertTrue(back == uh(b("1234567890"))) + + def testn1(self): + self.assertRaises(ValueError, unpad, b("123456\x02"), 4, "x923") + self.assertRaises(ValueError, unpad, b("123456\x00"), 4, "x923") + self.assertRaises(ValueError, unpad, b("123456\x00\x00\x00\x00\x05"), 4, "x923") + self.assertRaises(ValueError, unpad, b(""), 4, "x923") - def test1(self): - padded = pad(b(""), 4, 'x923') - self.assertTrue(padded == uh(b("00000004"))) - back = unpad(padded, 4, 'x923') - self.assertTrue(back == b("")) - - def test2(self): - padded = pad(uh(b("12345678")), 4, 'x923') - self.assertTrue(padded == uh(b("1234567800000004"))) - back = unpad(padded, 4, 'x923') - self.assertTrue(back == uh(b("12345678"))) - - def test3(self): - padded = pad(uh(b("123456")), 4, 'x923') - self.assertTrue(padded == uh(b("12345601"))) - back = unpad(padded, 4, 'x923') - self.assertTrue(back == uh(b("123456"))) - - def test4(self): - padded = pad(uh(b("1234567890")), 4, 'x923') - self.assertTrue(padded == uh(b("1234567890000003"))) - back = unpad(padded, 4, 'x923') - self.assertTrue(back == uh(b("1234567890"))) - - def testn1(self): - self.assertRaises(ValueError, unpad, b("123456\x02"), 4, 'x923') - self.assertRaises(ValueError, unpad, b("123456\x00"), 4, 'x923') - self.assertRaises(ValueError, unpad, b("123456\x00\x00\x00\x00\x05"), 4, 'x923') - self.assertRaises(ValueError, unpad, b(""), 4, 'x923') class ISO7816_Tests(unittest.TestCase): + def test1(self): + padded = pad(b(""), 4, "iso7816") + self.assertTrue(padded == uh(b("80000000"))) + back = unpad(padded, 4, "iso7816") + self.assertTrue(back == b("")) + + def test2(self): + padded = pad(uh(b("12345678")), 4, "iso7816") + self.assertTrue(padded == uh(b("1234567880000000"))) + back = unpad(padded, 4, "iso7816") + self.assertTrue(back == uh(b("12345678"))) + + def test3(self): + padded = pad(uh(b("123456")), 4, "iso7816") + self.assertTrue(padded == uh(b("12345680"))) + back = unpad(padded, 4, "iso7816") + self.assertTrue(back == uh(b("123456"))) + + def test4(self): + padded = pad(uh(b("1234567890")), 4, "iso7816") + self.assertTrue(padded == uh(b("1234567890800000"))) + back = unpad(padded, 4, "iso7816") + self.assertTrue(back == uh(b("1234567890"))) + + def testn1(self): + self.assertRaises(ValueError, unpad, b("123456\x81"), 4, "iso7816") + self.assertRaises(ValueError, unpad, b(""), 4, "iso7816") - def test1(self): - padded = pad(b(""), 4, 'iso7816') - self.assertTrue(padded == uh(b("80000000"))) - back = unpad(padded, 4, 'iso7816') - self.assertTrue(back == b("")) - - def test2(self): - padded = pad(uh(b("12345678")), 4, 'iso7816') - self.assertTrue(padded == uh(b("1234567880000000"))) - back = unpad(padded, 4, 'iso7816') - self.assertTrue(back == uh(b("12345678"))) - - def test3(self): - padded = pad(uh(b("123456")), 4, 'iso7816') - self.assertTrue(padded == uh(b("12345680"))) - back = unpad(padded, 4, 'iso7816') - self.assertTrue(back == uh(b("123456"))) - - def test4(self): - padded = pad(uh(b("1234567890")), 4, 'iso7816') - self.assertTrue(padded == uh(b("1234567890800000"))) - back = unpad(padded, 4, 'iso7816') - self.assertTrue(back == uh(b("1234567890"))) - - def testn1(self): - self.assertRaises(ValueError, unpad, b("123456\x81"), 4, 'iso7816') - self.assertRaises(ValueError, unpad, b(""), 4, 'iso7816') def get_tests(config={}): - tests = [] - tests += list_test_cases(PKCS7_Tests) - tests += list_test_cases(X923_Tests) - tests += list_test_cases(ISO7816_Tests) - return tests + tests = [] + tests += list_test_cases(PKCS7_Tests) + tests += list_test_cases(X923_Tests) + tests += list_test_cases(ISO7816_Tests) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_asn1.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_asn1.py index 811ac843..82409619 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_asn1.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_asn1.py @@ -36,816 +36,838 @@ import unittest from Cryptodome.Util.py3compat import * -from Cryptodome.Util.asn1 import (DerObject, DerSetOf, DerInteger, - DerBitString, - DerObjectId, DerNull, DerOctetString, - DerSequence, DerBoolean) +from Cryptodome.Util.asn1 import ( + DerObject, + DerSetOf, + DerInteger, + DerBitString, + DerObjectId, + DerNull, + DerOctetString, + DerSequence, + DerBoolean, +) + class DerObjectTests(unittest.TestCase): + def testObjInit1(self): + # Fail with invalid tag format (must be 1 byte) + self.assertRaises(ValueError, DerObject, b("\x00\x99")) + # Fail with invalid implicit tag (must be <0x1F) + self.assertRaises(ValueError, DerObject, 0x1F) + + # ------ + + def testObjEncode1(self): + # No payload + der = DerObject(b("\x02")) + self.assertEqual(der.encode(), b("\x02\x00")) + # Small payload (primitive) + der.payload = b("\x45") + self.assertEqual(der.encode(), b("\x02\x01\x45")) + # Invariant + self.assertEqual(der.encode(), b("\x02\x01\x45")) + # Initialize with numerical tag + der = DerObject(0x04) + der.payload = b("\x45") + self.assertEqual(der.encode(), b("\x04\x01\x45")) + # Initialize with constructed type + der = DerObject(b("\x10"), constructed=True) + self.assertEqual(der.encode(), b("\x30\x00")) + + def testObjEncode2(self): + # Initialize with payload + der = DerObject(0x03, b("\x12\x12")) + self.assertEqual(der.encode(), b("\x03\x02\x12\x12")) + + def testObjEncode3(self): + # Long payload + der = DerObject(b("\x10")) + der.payload = b("0") * 128 + self.assertEqual(der.encode(), b("\x10\x81\x80" + "0" * 128)) + + def testObjEncode4(self): + # Implicit tags (constructed) + der = DerObject(0x10, implicit=1, constructed=True) + der.payload = b("ppll") + self.assertEqual(der.encode(), b("\xa1\x04ppll")) + # Implicit tags (primitive) + der = DerObject(0x02, implicit=0x1E, constructed=False) + der.payload = b("ppll") + self.assertEqual(der.encode(), b("\x9e\x04ppll")) + + def testObjEncode5(self): + # Encode type with explicit tag + der = DerObject(0x10, explicit=5) + der.payload = b("xxll") + self.assertEqual(der.encode(), b("\xa5\x06\x10\x04xxll")) + + # ----- + + def testObjDecode1(self): + # Decode short payload + der = DerObject(0x02) + der.decode(b("\x02\x02\x01\x02")) + self.assertEqual(der.payload, b("\x01\x02")) + self.assertEqual(der._tag_octet, 0x02) + + def testObjDecode2(self): + # Decode long payload + der = DerObject(0x02) + der.decode(b("\x02\x81\x80" + "1" * 128)) + self.assertEqual(der.payload, b("1") * 128) + self.assertEqual(der._tag_octet, 0x02) + + def testObjDecode3(self): + # Decode payload with too much data gives error + der = DerObject(0x02) + self.assertRaises(ValueError, der.decode, b("\x02\x02\x01\x02\xff")) + # Decode payload with too little data gives error + der = DerObject(0x02) + self.assertRaises(ValueError, der.decode, b("\x02\x02\x01")) + + def testObjDecode4(self): + # Decode implicit tag (primitive) + der = DerObject(0x02, constructed=False, implicit=0xF) + self.assertRaises(ValueError, der.decode, b("\x02\x02\x01\x02")) + der.decode(b("\x8f\x01\x00")) + self.assertEqual(der.payload, b("\x00")) + # Decode implicit tag (constructed) + der = DerObject(0x02, constructed=True, implicit=0xF) + self.assertRaises(ValueError, der.decode, b("\x02\x02\x01\x02")) + der.decode(b("\xaf\x01\x00")) + self.assertEqual(der.payload, b("\x00")) + + def testObjDecode5(self): + # Decode payload with unexpected tag gives error + der = DerObject(0x02) + self.assertRaises(ValueError, der.decode, b("\x03\x02\x01\x02")) + + def testObjDecode6(self): + # Arbitrary DER object + der = DerObject() + der.decode(b("\x65\x01\x88")) + self.assertEqual(der._tag_octet, 0x65) + self.assertEqual(der.payload, b("\x88")) + + def testObjDecode7(self): + # Decode explicit tag + der = DerObject(0x10, explicit=5) + der.decode(b("\xa5\x06\x10\x04xxll")) + self.assertEqual(der._inner_tag_octet, 0x10) + self.assertEqual(der.payload, b("xxll")) + + # Explicit tag may be 0 + der = DerObject(0x10, explicit=0) + der.decode(b("\xa0\x06\x10\x04xxll")) + self.assertEqual(der._inner_tag_octet, 0x10) + self.assertEqual(der.payload, b("xxll")) + + def testObjDecode8(self): + # Verify that decode returns the object + der = DerObject(0x02) + self.assertEqual(der, der.decode(b("\x02\x02\x01\x02"))) - def testObjInit1(self): - # Fail with invalid tag format (must be 1 byte) - self.assertRaises(ValueError, DerObject, b('\x00\x99')) - # Fail with invalid implicit tag (must be <0x1F) - self.assertRaises(ValueError, DerObject, 0x1F) - - # ------ - - def testObjEncode1(self): - # No payload - der = DerObject(b('\x02')) - self.assertEqual(der.encode(), b('\x02\x00')) - # Small payload (primitive) - der.payload = b('\x45') - self.assertEqual(der.encode(), b('\x02\x01\x45')) - # Invariant - self.assertEqual(der.encode(), b('\x02\x01\x45')) - # Initialize with numerical tag - der = DerObject(0x04) - der.payload = b('\x45') - self.assertEqual(der.encode(), b('\x04\x01\x45')) - # Initialize with constructed type - der = DerObject(b('\x10'), constructed=True) - self.assertEqual(der.encode(), b('\x30\x00')) - - def testObjEncode2(self): - # Initialize with payload - der = DerObject(0x03, b('\x12\x12')) - self.assertEqual(der.encode(), b('\x03\x02\x12\x12')) - - def testObjEncode3(self): - # Long payload - der = DerObject(b('\x10')) - der.payload = b("0")*128 - self.assertEqual(der.encode(), b('\x10\x81\x80' + "0"*128)) - - def testObjEncode4(self): - # Implicit tags (constructed) - der = DerObject(0x10, implicit=1, constructed=True) - der.payload = b('ppll') - self.assertEqual(der.encode(), b('\xa1\x04ppll')) - # Implicit tags (primitive) - der = DerObject(0x02, implicit=0x1E, constructed=False) - der.payload = b('ppll') - self.assertEqual(der.encode(), b('\x9E\x04ppll')) - - def testObjEncode5(self): - # Encode type with explicit tag - der = DerObject(0x10, explicit=5) - der.payload = b("xxll") - self.assertEqual(der.encode(), b("\xa5\x06\x10\x04xxll")) - - # ----- - - def testObjDecode1(self): - # Decode short payload - der = DerObject(0x02) - der.decode(b('\x02\x02\x01\x02')) - self.assertEqual(der.payload, b("\x01\x02")) - self.assertEqual(der._tag_octet, 0x02) - - def testObjDecode2(self): - # Decode long payload - der = DerObject(0x02) - der.decode(b('\x02\x81\x80' + "1"*128)) - self.assertEqual(der.payload, b("1")*128) - self.assertEqual(der._tag_octet, 0x02) - - def testObjDecode3(self): - # Decode payload with too much data gives error - der = DerObject(0x02) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02\xFF')) - # Decode payload with too little data gives error - der = DerObject(0x02) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01')) - - def testObjDecode4(self): - # Decode implicit tag (primitive) - der = DerObject(0x02, constructed=False, implicit=0xF) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02')) - der.decode(b('\x8F\x01\x00')) - self.assertEqual(der.payload, b('\x00')) - # Decode implicit tag (constructed) - der = DerObject(0x02, constructed=True, implicit=0xF) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02')) - der.decode(b('\xAF\x01\x00')) - self.assertEqual(der.payload, b('\x00')) - - def testObjDecode5(self): - # Decode payload with unexpected tag gives error - der = DerObject(0x02) - self.assertRaises(ValueError, der.decode, b('\x03\x02\x01\x02')) - - def testObjDecode6(self): - # Arbitrary DER object - der = DerObject() - der.decode(b('\x65\x01\x88')) - self.assertEqual(der._tag_octet, 0x65) - self.assertEqual(der.payload, b('\x88')) - - def testObjDecode7(self): - # Decode explicit tag - der = DerObject(0x10, explicit=5) - der.decode(b("\xa5\x06\x10\x04xxll")) - self.assertEqual(der._inner_tag_octet, 0x10) - self.assertEqual(der.payload, b('xxll')) - - # Explicit tag may be 0 - der = DerObject(0x10, explicit=0) - der.decode(b("\xa0\x06\x10\x04xxll")) - self.assertEqual(der._inner_tag_octet, 0x10) - self.assertEqual(der.payload, b('xxll')) - - def testObjDecode8(self): - # Verify that decode returns the object - der = DerObject(0x02) - self.assertEqual(der, der.decode(b('\x02\x02\x01\x02'))) class DerIntegerTests(unittest.TestCase): - - def testInit1(self): - der = DerInteger(1) - self.assertEqual(der.encode(), b('\x02\x01\x01')) - - def testEncode1(self): - # Single-byte integers - # Value 0 - der = DerInteger(0) - self.assertEqual(der.encode(), b('\x02\x01\x00')) - # Value 1 - der = DerInteger(1) - self.assertEqual(der.encode(), b('\x02\x01\x01')) - # Value 127 - der = DerInteger(127) - self.assertEqual(der.encode(), b('\x02\x01\x7F')) - - def testEncode2(self): - # Multi-byte integers - # Value 128 - der = DerInteger(128) - self.assertEqual(der.encode(), b('\x02\x02\x00\x80')) - # Value 0x180 - der = DerInteger(0x180) - self.assertEqual(der.encode(), b('\x02\x02\x01\x80')) - # One very long integer - der = DerInteger(2**2048) - self.assertEqual(der.encode(), - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - - def testEncode3(self): - # Negative integers - # Value -1 - der = DerInteger(-1) - self.assertEqual(der.encode(), b('\x02\x01\xFF')) - # Value -128 - der = DerInteger(-128) - self.assertEqual(der.encode(), b('\x02\x01\x80')) - # Value - der = DerInteger(-87873) - self.assertEqual(der.encode(), b('\x02\x03\xFE\xA8\xBF')) - - def testEncode4(self): - # Explicit encoding - number = DerInteger(0x34, explicit=3) - self.assertEqual(number.encode(), b('\xa3\x03\x02\x01\x34')) - - # ----- - - def testDecode1(self): - # Single-byte integer - der = DerInteger() - # Value 0 - der.decode(b('\x02\x01\x00')) - self.assertEqual(der.value, 0) - # Value 1 - der.decode(b('\x02\x01\x01')) - self.assertEqual(der.value, 1) - # Value 127 - der.decode(b('\x02\x01\x7F')) - self.assertEqual(der.value, 127) - - def testDecode2(self): - # Multi-byte integer - der = DerInteger() - # Value 0x180L - der.decode(b('\x02\x02\x01\x80')) - self.assertEqual(der.value,0x180) - # One very long integer - der.decode( - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - self.assertEqual(der.value,2**2048) - - def testDecode3(self): - # Negative integer - der = DerInteger() - # Value -1 - der.decode(b('\x02\x01\xFF')) - self.assertEqual(der.value, -1) - # Value -32768 - der.decode(b('\x02\x02\x80\x00')) - self.assertEqual(der.value, -32768) - - def testDecode5(self): - # We still accept BER integer format - der = DerInteger() - # Redundant leading zeroes - der.decode(b('\x02\x02\x00\x01')) - self.assertEqual(der.value, 1) - # Redundant leading 0xFF - der.decode(b('\x02\x02\xFF\xFF')) - self.assertEqual(der.value, -1) - # Empty payload - der.decode(b('\x02\x00')) - self.assertEqual(der.value, 0) - - def testDecode6(self): - # Explicit encoding - number = DerInteger(explicit=3) - number.decode(b('\xa3\x03\x02\x01\x34')) - self.assertEqual(number.value, 0x34) - - def testDecode7(self): - # Verify decode returns the DerInteger - der = DerInteger() - self.assertEqual(der, der.decode(b('\x02\x01\x7F'))) - - ### - - def testStrict1(self): - number = DerInteger() - - number.decode(b'\x02\x02\x00\x01') - number.decode(b'\x02\x02\x00\x7F') - self.assertRaises(ValueError, number.decode, b'\x02\x02\x00\x01', strict=True) - self.assertRaises(ValueError, number.decode, b'\x02\x02\x00\x7F', strict=True) - - ### - - def testErrDecode1(self): - # Wide length field - der = DerInteger() - self.assertRaises(ValueError, der.decode, b('\x02\x81\x01\x01')) + def testInit1(self): + der = DerInteger(1) + self.assertEqual(der.encode(), b("\x02\x01\x01")) + + def testEncode1(self): + # Single-byte integers + # Value 0 + der = DerInteger(0) + self.assertEqual(der.encode(), b("\x02\x01\x00")) + # Value 1 + der = DerInteger(1) + self.assertEqual(der.encode(), b("\x02\x01\x01")) + # Value 127 + der = DerInteger(127) + self.assertEqual(der.encode(), b("\x02\x01\x7f")) + + def testEncode2(self): + # Multi-byte integers + # Value 128 + der = DerInteger(128) + self.assertEqual(der.encode(), b("\x02\x02\x00\x80")) + # Value 0x180 + der = DerInteger(0x180) + self.assertEqual(der.encode(), b("\x02\x02\x01\x80")) + # One very long integer + der = DerInteger(2**2048) + self.assertEqual( + der.encode(), + b("\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + ) + + def testEncode3(self): + # Negative integers + # Value -1 + der = DerInteger(-1) + self.assertEqual(der.encode(), b("\x02\x01\xff")) + # Value -128 + der = DerInteger(-128) + self.assertEqual(der.encode(), b("\x02\x01\x80")) + # Value + der = DerInteger(-87873) + self.assertEqual(der.encode(), b("\x02\x03\xfe\xa8\xbf")) + + def testEncode4(self): + # Explicit encoding + number = DerInteger(0x34, explicit=3) + self.assertEqual(number.encode(), b("\xa3\x03\x02\x01\x34")) + + # ----- + + def testDecode1(self): + # Single-byte integer + der = DerInteger() + # Value 0 + der.decode(b("\x02\x01\x00")) + self.assertEqual(der.value, 0) + # Value 1 + der.decode(b("\x02\x01\x01")) + self.assertEqual(der.value, 1) + # Value 127 + der.decode(b("\x02\x01\x7f")) + self.assertEqual(der.value, 127) + + def testDecode2(self): + # Multi-byte integer + der = DerInteger() + # Value 0x180L + der.decode(b("\x02\x02\x01\x80")) + self.assertEqual(der.value, 0x180) + # One very long integer + der.decode( + b("\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + ) + self.assertEqual(der.value, 2**2048) + + def testDecode3(self): + # Negative integer + der = DerInteger() + # Value -1 + der.decode(b("\x02\x01\xff")) + self.assertEqual(der.value, -1) + # Value -32768 + der.decode(b("\x02\x02\x80\x00")) + self.assertEqual(der.value, -32768) + + def testDecode5(self): + # We still accept BER integer format + der = DerInteger() + # Redundant leading zeroes + der.decode(b("\x02\x02\x00\x01")) + self.assertEqual(der.value, 1) + # Redundant leading 0xFF + der.decode(b("\x02\x02\xff\xff")) + self.assertEqual(der.value, -1) + # Empty payload + der.decode(b("\x02\x00")) + self.assertEqual(der.value, 0) + + def testDecode6(self): + # Explicit encoding + number = DerInteger(explicit=3) + number.decode(b("\xa3\x03\x02\x01\x34")) + self.assertEqual(number.value, 0x34) + + def testDecode7(self): + # Verify decode returns the DerInteger + der = DerInteger() + self.assertEqual(der, der.decode(b("\x02\x01\x7f"))) + + ### + + def testStrict1(self): + number = DerInteger() + + number.decode(b"\x02\x02\x00\x01") + number.decode(b"\x02\x02\x00\x7f") + self.assertRaises(ValueError, number.decode, b"\x02\x02\x00\x01", strict=True) + self.assertRaises(ValueError, number.decode, b"\x02\x02\x00\x7f", strict=True) + + ### + + def testErrDecode1(self): + # Wide length field + der = DerInteger() + self.assertRaises(ValueError, der.decode, b("\x02\x81\x01\x01")) class DerSequenceTests(unittest.TestCase): - - def testInit1(self): - der = DerSequence([1, DerInteger(2), b('0\x00')]) - self.assertEqual(der.encode(), b('0\x08\x02\x01\x01\x02\x01\x020\x00')) - - def testEncode1(self): - # Empty sequence - der = DerSequence() - self.assertEqual(der.encode(), b('0\x00')) - self.assertFalse(der.hasOnlyInts()) - # One single-byte integer (zero) - der.append(0) - self.assertEqual(der.encode(), b('0\x03\x02\x01\x00')) - self.assertEqual(der.hasInts(),1) - self.assertEqual(der.hasInts(False),1) - self.assertTrue(der.hasOnlyInts()) - self.assertTrue(der.hasOnlyInts(False)) - # Invariant - self.assertEqual(der.encode(), b('0\x03\x02\x01\x00')) - - def testEncode2(self): - # Indexing - der = DerSequence() - der.append(0) - der[0] = 1 - self.assertEqual(len(der),1) - self.assertEqual(der[0],1) - self.assertEqual(der[-1],1) - self.assertEqual(der.encode(), b('0\x03\x02\x01\x01')) - # - der[:] = [1] - self.assertEqual(len(der),1) - self.assertEqual(der[0],1) - self.assertEqual(der.encode(), b('0\x03\x02\x01\x01')) - - def testEncode3(self): - # One multi-byte integer (non-zero) - der = DerSequence() - der.append(0x180) - self.assertEqual(der.encode(), b('0\x04\x02\x02\x01\x80')) - - def testEncode4(self): - # One very long integer - der = DerSequence() - der.append(2**2048) - self.assertEqual(der.encode(), b('0\x82\x01\x05')+ - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - - def testEncode5(self): - der = DerSequence() - der += 1 - der += b('\x30\x00') - self.assertEqual(der.encode(), b('\x30\x05\x02\x01\x01\x30\x00')) - - def testEncode6(self): - # Two positive integers - der = DerSequence() - der.append(0x180) - der.append(0xFF) - self.assertEqual(der.encode(), b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')) - self.assertTrue(der.hasOnlyInts()) - self.assertTrue(der.hasOnlyInts(False)) - # Two mixed integers - der = DerSequence() - der.append(2) - der.append(-2) - self.assertEqual(der.encode(), b('0\x06\x02\x01\x02\x02\x01\xFE')) - self.assertEqual(der.hasInts(), 1) - self.assertEqual(der.hasInts(False), 2) - self.assertFalse(der.hasOnlyInts()) - self.assertTrue(der.hasOnlyInts(False)) - # - der.append(0x01) - der[1:] = [9,8] - self.assertEqual(len(der),3) - self.assertEqual(der[1:],[9,8]) - self.assertEqual(der[1:-1],[9]) - self.assertEqual(der.encode(), b('0\x09\x02\x01\x02\x02\x01\x09\x02\x01\x08')) - - def testEncode7(self): - # One integer and another type (already encoded) - der = DerSequence() - der.append(0x180) - der.append(b('0\x03\x02\x01\x05')) - self.assertEqual(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05')) - self.assertFalse(der.hasOnlyInts()) - - def testEncode8(self): - # One integer and another type (yet to encode) - der = DerSequence() - der.append(0x180) - der.append(DerSequence([5])) - self.assertEqual(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05')) - self.assertFalse(der.hasOnlyInts()) - - #### - - def testDecode1(self): - # Empty sequence - der = DerSequence() - der.decode(b('0\x00')) - self.assertEqual(len(der),0) - # One single-byte integer (zero) - der.decode(b('0\x03\x02\x01\x00')) - self.assertEqual(len(der),1) - self.assertEqual(der[0],0) - # Invariant - der.decode(b('0\x03\x02\x01\x00')) - self.assertEqual(len(der),1) - self.assertEqual(der[0],0) - - def testDecode2(self): - # One single-byte integer (non-zero) - der = DerSequence() - der.decode(b('0\x03\x02\x01\x7f')) - self.assertEqual(len(der),1) - self.assertEqual(der[0],127) - - def testDecode4(self): - # One very long integer - der = DerSequence() - der.decode(b('0\x82\x01\x05')+ - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - self.assertEqual(len(der),1) - self.assertEqual(der[0],2**2048) - - def testDecode6(self): - # Two integers - der = DerSequence() - der.decode(b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')) - self.assertEqual(len(der),2) - self.assertEqual(der[0],0x180) - self.assertEqual(der[1],0xFF) - - def testDecode7(self): - # One integer and 2 other types - der = DerSequence() - der.decode(b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')) - self.assertEqual(len(der),3) - self.assertEqual(der[0],0x180) - self.assertEqual(der[1],b('\x24\x02\xb6\x63')) - self.assertEqual(der[2],b('\x12\x00')) - - def testDecode8(self): - # Only 2 other types - der = DerSequence() - der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00')) - self.assertEqual(len(der),2) - self.assertEqual(der[0],b('\x24\x02\xb6\x63')) - self.assertEqual(der[1],b('\x12\x00')) - self.assertEqual(der.hasInts(), 0) - self.assertEqual(der.hasInts(False), 0) - self.assertFalse(der.hasOnlyInts()) - self.assertFalse(der.hasOnlyInts(False)) - - def testDecode9(self): - # Verify that decode returns itself - der = DerSequence() - self.assertEqual(der, der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00'))) - - ### - - def testErrDecode1(self): - # Not a sequence - der = DerSequence() - self.assertRaises(ValueError, der.decode, b('')) - self.assertRaises(ValueError, der.decode, b('\x00')) - self.assertRaises(ValueError, der.decode, b('\x30')) - - def testErrDecode2(self): - der = DerSequence() - # Too much data - self.assertRaises(ValueError, der.decode, b('\x30\x00\x00')) - - def testErrDecode3(self): - # Wrong length format - der = DerSequence() - # Missing length in sub-item - self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x01\x01\x00')) - # Valid BER, but invalid DER length - self.assertRaises(ValueError, der.decode, b('\x30\x81\x03\x02\x01\x01')) - self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x81\x01\x01')) - - def test_expected_nr_elements(self): - der_bin = DerSequence([1, 2, 3]).encode() - - DerSequence().decode(der_bin, nr_elements=3) - DerSequence().decode(der_bin, nr_elements=(2,3)) - self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=1) - self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=(4,5)) - - def test_expected_only_integers(self): - - der_bin1 = DerSequence([1, 2, 3]).encode() - der_bin2 = DerSequence([1, 2, DerSequence([3, 4])]).encode() - - DerSequence().decode(der_bin1, only_ints_expected=True) - DerSequence().decode(der_bin1, only_ints_expected=False) - DerSequence().decode(der_bin2, only_ints_expected=False) - self.assertRaises(ValueError, DerSequence().decode, der_bin2, only_ints_expected=True) + def testInit1(self): + der = DerSequence([1, DerInteger(2), b("0\x00")]) + self.assertEqual(der.encode(), b("0\x08\x02\x01\x01\x02\x01\x020\x00")) + + def testEncode1(self): + # Empty sequence + der = DerSequence() + self.assertEqual(der.encode(), b("0\x00")) + self.assertFalse(der.hasOnlyInts()) + # One single-byte integer (zero) + der.append(0) + self.assertEqual(der.encode(), b("0\x03\x02\x01\x00")) + self.assertEqual(der.hasInts(), 1) + self.assertEqual(der.hasInts(False), 1) + self.assertTrue(der.hasOnlyInts()) + self.assertTrue(der.hasOnlyInts(False)) + # Invariant + self.assertEqual(der.encode(), b("0\x03\x02\x01\x00")) + + def testEncode2(self): + # Indexing + der = DerSequence() + der.append(0) + der[0] = 1 + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 1) + self.assertEqual(der[-1], 1) + self.assertEqual(der.encode(), b("0\x03\x02\x01\x01")) + # + der[:] = [1] + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 1) + self.assertEqual(der.encode(), b("0\x03\x02\x01\x01")) + + def testEncode3(self): + # One multi-byte integer (non-zero) + der = DerSequence() + der.append(0x180) + self.assertEqual(der.encode(), b("0\x04\x02\x02\x01\x80")) + + def testEncode4(self): + # One very long integer + der = DerSequence() + der.append(2**2048) + self.assertEqual( + der.encode(), + b("0\x82\x01\x05") + + b("\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + ) + + def testEncode5(self): + der = DerSequence() + der += 1 + der += b("\x30\x00") + self.assertEqual(der.encode(), b("\x30\x05\x02\x01\x01\x30\x00")) + + def testEncode6(self): + # Two positive integers + der = DerSequence() + der.append(0x180) + der.append(0xFF) + self.assertEqual(der.encode(), b("0\x08\x02\x02\x01\x80\x02\x02\x00\xff")) + self.assertTrue(der.hasOnlyInts()) + self.assertTrue(der.hasOnlyInts(False)) + # Two mixed integers + der = DerSequence() + der.append(2) + der.append(-2) + self.assertEqual(der.encode(), b("0\x06\x02\x01\x02\x02\x01\xfe")) + self.assertEqual(der.hasInts(), 1) + self.assertEqual(der.hasInts(False), 2) + self.assertFalse(der.hasOnlyInts()) + self.assertTrue(der.hasOnlyInts(False)) + # + der.append(0x01) + der[1:] = [9, 8] + self.assertEqual(len(der), 3) + self.assertEqual(der[1:], [9, 8]) + self.assertEqual(der[1:-1], [9]) + self.assertEqual(der.encode(), b("0\x09\x02\x01\x02\x02\x01\x09\x02\x01\x08")) + + def testEncode7(self): + # One integer and another type (already encoded) + der = DerSequence() + der.append(0x180) + der.append(b("0\x03\x02\x01\x05")) + self.assertEqual(der.encode(), b("0\x09\x02\x02\x01\x800\x03\x02\x01\x05")) + self.assertFalse(der.hasOnlyInts()) + + def testEncode8(self): + # One integer and another type (yet to encode) + der = DerSequence() + der.append(0x180) + der.append(DerSequence([5])) + self.assertEqual(der.encode(), b("0\x09\x02\x02\x01\x800\x03\x02\x01\x05")) + self.assertFalse(der.hasOnlyInts()) + + #### + + def testDecode1(self): + # Empty sequence + der = DerSequence() + der.decode(b("0\x00")) + self.assertEqual(len(der), 0) + # One single-byte integer (zero) + der.decode(b("0\x03\x02\x01\x00")) + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 0) + # Invariant + der.decode(b("0\x03\x02\x01\x00")) + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 0) + + def testDecode2(self): + # One single-byte integer (non-zero) + der = DerSequence() + der.decode(b("0\x03\x02\x01\x7f")) + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 127) + + def testDecode4(self): + # One very long integer + der = DerSequence() + der.decode( + b("0\x82\x01\x05") + + b("\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + ) + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 2**2048) + + def testDecode6(self): + # Two integers + der = DerSequence() + der.decode(b("0\x08\x02\x02\x01\x80\x02\x02\x00\xff")) + self.assertEqual(len(der), 2) + self.assertEqual(der[0], 0x180) + self.assertEqual(der[1], 0xFF) + + def testDecode7(self): + # One integer and 2 other types + der = DerSequence() + der.decode(b("0\x0a\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00")) + self.assertEqual(len(der), 3) + self.assertEqual(der[0], 0x180) + self.assertEqual(der[1], b("\x24\x02\xb6\x63")) + self.assertEqual(der[2], b("\x12\x00")) + + def testDecode8(self): + # Only 2 other types + der = DerSequence() + der.decode(b("0\x06\x24\x02\xb6\x63\x12\x00")) + self.assertEqual(len(der), 2) + self.assertEqual(der[0], b("\x24\x02\xb6\x63")) + self.assertEqual(der[1], b("\x12\x00")) + self.assertEqual(der.hasInts(), 0) + self.assertEqual(der.hasInts(False), 0) + self.assertFalse(der.hasOnlyInts()) + self.assertFalse(der.hasOnlyInts(False)) + + def testDecode9(self): + # Verify that decode returns itself + der = DerSequence() + self.assertEqual(der, der.decode(b("0\x06\x24\x02\xb6\x63\x12\x00"))) + + ### + + def testErrDecode1(self): + # Not a sequence + der = DerSequence() + self.assertRaises(ValueError, der.decode, b("")) + self.assertRaises(ValueError, der.decode, b("\x00")) + self.assertRaises(ValueError, der.decode, b("\x30")) + + def testErrDecode2(self): + der = DerSequence() + # Too much data + self.assertRaises(ValueError, der.decode, b("\x30\x00\x00")) + + def testErrDecode3(self): + # Wrong length format + der = DerSequence() + # Missing length in sub-item + self.assertRaises(ValueError, der.decode, b("\x30\x04\x02\x01\x01\x00")) + # Valid BER, but invalid DER length + self.assertRaises(ValueError, der.decode, b("\x30\x81\x03\x02\x01\x01")) + self.assertRaises(ValueError, der.decode, b("\x30\x04\x02\x81\x01\x01")) + + def test_expected_nr_elements(self): + der_bin = DerSequence([1, 2, 3]).encode() + + DerSequence().decode(der_bin, nr_elements=3) + DerSequence().decode(der_bin, nr_elements=(2, 3)) + self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=1) + self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=(4, 5)) + + def test_expected_only_integers(self): + der_bin1 = DerSequence([1, 2, 3]).encode() + der_bin2 = DerSequence([1, 2, DerSequence([3, 4])]).encode() + + DerSequence().decode(der_bin1, only_ints_expected=True) + DerSequence().decode(der_bin1, only_ints_expected=False) + DerSequence().decode(der_bin2, only_ints_expected=False) + self.assertRaises(ValueError, DerSequence().decode, der_bin2, only_ints_expected=True) class DerOctetStringTests(unittest.TestCase): + def testInit1(self): + der = DerOctetString(b("\xff")) + self.assertEqual(der.encode(), b("\x04\x01\xff")) + + def testEncode1(self): + # Empty sequence + der = DerOctetString() + self.assertEqual(der.encode(), b("\x04\x00")) + # Small payload + der.payload = b("\x01\x02") + self.assertEqual(der.encode(), b("\x04\x02\x01\x02")) + + #### + + def testDecode1(self): + # Empty sequence + der = DerOctetString() + der.decode(b("\x04\x00")) + self.assertEqual(der.payload, b("")) + # Small payload + der.decode(b("\x04\x02\x01\x02")) + self.assertEqual(der.payload, b("\x01\x02")) + + def testDecode2(self): + # Verify that decode returns the object + der = DerOctetString() + self.assertEqual(der, der.decode(b("\x04\x00"))) + + def testErrDecode1(self): + # No leftovers allowed + der = DerOctetString() + self.assertRaises(ValueError, der.decode, b("\x04\x01\x01\xff")) - def testInit1(self): - der = DerOctetString(b('\xFF')) - self.assertEqual(der.encode(), b('\x04\x01\xFF')) - - def testEncode1(self): - # Empty sequence - der = DerOctetString() - self.assertEqual(der.encode(), b('\x04\x00')) - # Small payload - der.payload = b('\x01\x02') - self.assertEqual(der.encode(), b('\x04\x02\x01\x02')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerOctetString() - der.decode(b('\x04\x00')) - self.assertEqual(der.payload, b('')) - # Small payload - der.decode(b('\x04\x02\x01\x02')) - self.assertEqual(der.payload, b('\x01\x02')) - - def testDecode2(self): - # Verify that decode returns the object - der = DerOctetString() - self.assertEqual(der, der.decode(b('\x04\x00'))) - - def testErrDecode1(self): - # No leftovers allowed - der = DerOctetString() - self.assertRaises(ValueError, der.decode, b('\x04\x01\x01\xff')) class DerNullTests(unittest.TestCase): + def testEncode1(self): + der = DerNull() + self.assertEqual(der.encode(), b("\x05\x00")) - def testEncode1(self): - der = DerNull() - self.assertEqual(der.encode(), b('\x05\x00')) + #### - #### + def testDecode1(self): + # Empty sequence + der = DerNull() + self.assertEqual(der, der.decode(b("\x05\x00"))) - def testDecode1(self): - # Empty sequence - der = DerNull() - self.assertEqual(der, der.decode(b('\x05\x00'))) class DerObjectIdTests(unittest.TestCase): + def testInit1(self): + der = DerObjectId("1.1") + self.assertEqual(der.encode(), b"\x06\x01)") - def testInit1(self): - der = DerObjectId("1.1") - self.assertEqual(der.encode(), b'\x06\x01)') + def testEncode1(self): + der = DerObjectId("1.2.840.113549.1.1.1") + self.assertEqual(der.encode(), b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01") - def testEncode1(self): - der = DerObjectId('1.2.840.113549.1.1.1') - self.assertEqual(der.encode(), b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01') + der = DerObjectId() + der.value = "1.2.840.113549.1.1.1" + self.assertEqual(der.encode(), b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01") - der = DerObjectId() - der.value = '1.2.840.113549.1.1.1' - self.assertEqual(der.encode(), b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01') + der = DerObjectId("2.999.1234") + self.assertEqual(der.encode(), b"\x06\x04\x88\x37\x89\x52") - der = DerObjectId('2.999.1234') - self.assertEqual(der.encode(), b'\x06\x04\x88\x37\x89\x52') + def testEncode2(self): + der = DerObjectId("3.4") + self.assertRaises(ValueError, der.encode) - def testEncode2(self): - der = DerObjectId('3.4') - self.assertRaises(ValueError, der.encode) + der = DerObjectId("1.40") + self.assertRaises(ValueError, der.encode) - der = DerObjectId('1.40') - self.assertRaises(ValueError, der.encode) + #### - #### + def testDecode1(self): + # Empty sequence + der = DerObjectId() + der.decode(b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01") + self.assertEqual(der.value, "1.2.840.113549.1.1.1") - def testDecode1(self): - # Empty sequence - der = DerObjectId() - der.decode(b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01') - self.assertEqual(der.value, '1.2.840.113549.1.1.1') + def testDecode2(self): + # Verify that decode returns the object + der = DerObjectId() + self.assertEqual( + der, + der.decode(b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01"), + ) - def testDecode2(self): - # Verify that decode returns the object - der = DerObjectId() - self.assertEqual(der, - der.decode(b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01')) + def testDecode3(self): + der = DerObjectId() + der.decode(b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x00\x01") + self.assertEqual(der.value, "1.2.840.113549.1.0.1") - def testDecode3(self): - der = DerObjectId() - der.decode(b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x00\x01') - self.assertEqual(der.value, '1.2.840.113549.1.0.1') - - def testDecode4(self): - der = DerObjectId() - der.decode(b'\x06\x04\x88\x37\x89\x52') - self.assertEqual(der.value, '2.999.1234') + def testDecode4(self): + der = DerObjectId() + der.decode(b"\x06\x04\x88\x37\x89\x52") + self.assertEqual(der.value, "2.999.1234") class DerBitStringTests(unittest.TestCase): - - def testInit1(self): - der = DerBitString(b("\xFF")) - self.assertEqual(der.encode(), b('\x03\x02\x00\xFF')) - - def testInit2(self): - der = DerBitString(DerInteger(1)) - self.assertEqual(der.encode(), b('\x03\x04\x00\x02\x01\x01')) - - def testEncode1(self): - # Empty sequence - der = DerBitString() - self.assertEqual(der.encode(), b('\x03\x01\x00')) - # Small payload - der = DerBitString(b('\x01\x02')) - self.assertEqual(der.encode(), b('\x03\x03\x00\x01\x02')) - # Small payload - der = DerBitString() - der.value = b('\x01\x02') - self.assertEqual(der.encode(), b('\x03\x03\x00\x01\x02')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerBitString() - der.decode(b('\x03\x00')) - self.assertEqual(der.value, b('')) - # Small payload - der.decode(b('\x03\x03\x00\x01\x02')) - self.assertEqual(der.value, b('\x01\x02')) - - def testDecode2(self): - # Verify that decode returns the object - der = DerBitString() - self.assertEqual(der, der.decode(b('\x03\x00'))) + def testInit1(self): + der = DerBitString(b("\xff")) + self.assertEqual(der.encode(), b("\x03\x02\x00\xff")) + + def testInit2(self): + der = DerBitString(DerInteger(1)) + self.assertEqual(der.encode(), b("\x03\x04\x00\x02\x01\x01")) + + def testEncode1(self): + # Empty sequence + der = DerBitString() + self.assertEqual(der.encode(), b("\x03\x01\x00")) + # Small payload + der = DerBitString(b("\x01\x02")) + self.assertEqual(der.encode(), b("\x03\x03\x00\x01\x02")) + # Small payload + der = DerBitString() + der.value = b("\x01\x02") + self.assertEqual(der.encode(), b("\x03\x03\x00\x01\x02")) + + #### + + def testDecode1(self): + # Empty sequence + der = DerBitString() + der.decode(b("\x03\x00")) + self.assertEqual(der.value, b("")) + # Small payload + der.decode(b("\x03\x03\x00\x01\x02")) + self.assertEqual(der.value, b("\x01\x02")) + + def testDecode2(self): + # Verify that decode returns the object + der = DerBitString() + self.assertEqual(der, der.decode(b("\x03\x00"))) class DerSetOfTests(unittest.TestCase): - - def testInit1(self): - der = DerSetOf([DerInteger(1), DerInteger(2)]) - self.assertEqual(der.encode(), b('1\x06\x02\x01\x01\x02\x01\x02')) - - def testEncode1(self): - # Empty set - der = DerSetOf() - self.assertEqual(der.encode(), b('1\x00')) - # One single-byte integer (zero) - der.add(0) - self.assertEqual(der.encode(), b('1\x03\x02\x01\x00')) - # Invariant - self.assertEqual(der.encode(), b('1\x03\x02\x01\x00')) - - def testEncode2(self): - # Two integers - der = DerSetOf() - der.add(0x180) - der.add(0xFF) - self.assertEqual(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80')) - # Initialize with integers - der = DerSetOf([0x180, 0xFF]) - self.assertEqual(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80')) - - def testEncode3(self): - # One integer and another type (no matter what it is) - der = DerSetOf() - der.add(0x180) - self.assertRaises(ValueError, der.add, b('\x00\x02\x00\x00')) - - def testEncode4(self): - # Only non integers - der = DerSetOf() - der.add(b('\x01\x00')) - der.add(b('\x01\x01\x01')) - self.assertEqual(der.encode(), b('1\x05\x01\x00\x01\x01\x01')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerSetOf() - der.decode(b('1\x00')) - self.assertEqual(len(der),0) - # One single-byte integer (zero) - der.decode(b('1\x03\x02\x01\x00')) - self.assertEqual(len(der),1) - self.assertEqual(list(der),[0]) - - def testDecode2(self): - # Two integers - der = DerSetOf() - der.decode(b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff')) - self.assertEqual(len(der),2) - l = list(der) - self.assertTrue(0x180 in l) - self.assertTrue(0xFF in l) - - def testDecode3(self): - # One integer and 2 other types - der = DerSetOf() - #import pdb; pdb.set_trace() - self.assertRaises(ValueError, der.decode, - b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')) - - def testDecode4(self): - # Verify that decode returns the object - der = DerSetOf() - self.assertEqual(der, - der.decode(b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff'))) - - ### - - def testErrDecode1(self): - # No leftovers allowed - der = DerSetOf() - self.assertRaises(ValueError, der.decode, - b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff\xAA')) + def testInit1(self): + der = DerSetOf([DerInteger(1), DerInteger(2)]) + self.assertEqual(der.encode(), b("1\x06\x02\x01\x01\x02\x01\x02")) + + def testEncode1(self): + # Empty set + der = DerSetOf() + self.assertEqual(der.encode(), b("1\x00")) + # One single-byte integer (zero) + der.add(0) + self.assertEqual(der.encode(), b("1\x03\x02\x01\x00")) + # Invariant + self.assertEqual(der.encode(), b("1\x03\x02\x01\x00")) + + def testEncode2(self): + # Two integers + der = DerSetOf() + der.add(0x180) + der.add(0xFF) + self.assertEqual(der.encode(), b("1\x08\x02\x02\x00\xff\x02\x02\x01\x80")) + # Initialize with integers + der = DerSetOf([0x180, 0xFF]) + self.assertEqual(der.encode(), b("1\x08\x02\x02\x00\xff\x02\x02\x01\x80")) + + def testEncode3(self): + # One integer and another type (no matter what it is) + der = DerSetOf() + der.add(0x180) + self.assertRaises(ValueError, der.add, b("\x00\x02\x00\x00")) + + def testEncode4(self): + # Only non integers + der = DerSetOf() + der.add(b("\x01\x00")) + der.add(b("\x01\x01\x01")) + self.assertEqual(der.encode(), b("1\x05\x01\x00\x01\x01\x01")) + + #### + + def testDecode1(self): + # Empty sequence + der = DerSetOf() + der.decode(b("1\x00")) + self.assertEqual(len(der), 0) + # One single-byte integer (zero) + der.decode(b("1\x03\x02\x01\x00")) + self.assertEqual(len(der), 1) + self.assertEqual(list(der), [0]) + + def testDecode2(self): + # Two integers + der = DerSetOf() + der.decode(b("1\x08\x02\x02\x01\x80\x02\x02\x00\xff")) + self.assertEqual(len(der), 2) + l = list(der) + self.assertTrue(0x180 in l) + self.assertTrue(0xFF in l) + + def testDecode3(self): + # One integer and 2 other types + der = DerSetOf() + # import pdb; pdb.set_trace() + self.assertRaises( + ValueError, + der.decode, + b("0\x0a\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00"), + ) + + def testDecode4(self): + # Verify that decode returns the object + der = DerSetOf() + self.assertEqual( + der, + der.decode(b("1\x08\x02\x02\x01\x80\x02\x02\x00\xff")), + ) + + ### + + def testErrDecode1(self): + # No leftovers allowed + der = DerSetOf() + self.assertRaises( + ValueError, + der.decode, + b("1\x08\x02\x02\x01\x80\x02\x02\x00\xff\xaa"), + ) class DerBooleanTests(unittest.TestCase): + def testEncode1(self): + der = DerBoolean(False) + self.assertEqual(der.encode(), b"\x01\x01\x00") - def testEncode1(self): - der = DerBoolean(False) - self.assertEqual(der.encode(), b'\x01\x01\x00') + def testEncode2(self): + der = DerBoolean(True) + self.assertEqual(der.encode(), b"\x01\x01\xff") - def testEncode2(self): - der = DerBoolean(True) - self.assertEqual(der.encode(), b'\x01\x01\xFF') + def testEncode3(self): + der = DerBoolean(False, implicit=0x12) + self.assertEqual(der.encode(), b"\x92\x01\x00") - def testEncode3(self): - der = DerBoolean(False, implicit=0x12) - self.assertEqual(der.encode(), b'\x92\x01\x00') + def testEncode4(self): + der = DerBoolean(False, explicit=0x05) + self.assertEqual(der.encode(), b"\xa5\x03\x01\x01\x00") - def testEncode4(self): - der = DerBoolean(False, explicit=0x05) - self.assertEqual(der.encode(), b'\xA5\x03\x01\x01\x00') - #### + #### - def testDecode1(self): - der = DerBoolean() - der.decode(b'\x01\x01\x00') - self.assertEqual(der.value, False) + def testDecode1(self): + der = DerBoolean() + der.decode(b"\x01\x01\x00") + self.assertEqual(der.value, False) - def testDecode2(self): - der = DerBoolean() - der.decode(b'\x01\x01\xFF') - self.assertEqual(der.value, True) + def testDecode2(self): + der = DerBoolean() + der.decode(b"\x01\x01\xff") + self.assertEqual(der.value, True) - def testDecode3(self): - der = DerBoolean(implicit=0x12) - der.decode(b'\x92\x01\x00') - self.assertEqual(der.value, False) + def testDecode3(self): + der = DerBoolean(implicit=0x12) + der.decode(b"\x92\x01\x00") + self.assertEqual(der.value, False) - def testDecode4(self): - der = DerBoolean(explicit=0x05) - der.decode(b'\xA5\x03\x01\x01\x00') - self.assertEqual(der.value, False) + def testDecode4(self): + der = DerBoolean(explicit=0x05) + der.decode(b"\xa5\x03\x01\x01\x00") + self.assertEqual(der.value, False) - def testErrorDecode1(self): - der = DerBoolean() - # Wrong tag - self.assertRaises(ValueError, der.decode, b'\x02\x01\x00') + def testErrorDecode1(self): + der = DerBoolean() + # Wrong tag + self.assertRaises(ValueError, der.decode, b"\x02\x01\x00") - def testErrorDecode2(self): - der = DerBoolean() - # Payload too long - self.assertRaises(ValueError, der.decode, b'\x01\x01\x00\xFF') + def testErrorDecode2(self): + der = DerBoolean() + # Payload too long + self.assertRaises(ValueError, der.decode, b"\x01\x01\x00\xff") def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - listTests = [] - listTests += list_test_cases(DerObjectTests) - listTests += list_test_cases(DerIntegerTests) - listTests += list_test_cases(DerSequenceTests) - listTests += list_test_cases(DerOctetStringTests) - listTests += list_test_cases(DerNullTests) - listTests += list_test_cases(DerObjectIdTests) - listTests += list_test_cases(DerBitStringTests) - listTests += list_test_cases(DerSetOfTests) - listTests += list_test_cases(DerBooleanTests) - return listTests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from Cryptodome.SelfTest.st_common import list_test_cases + + listTests = [] + listTests += list_test_cases(DerObjectTests) + listTests += list_test_cases(DerIntegerTests) + listTests += list_test_cases(DerSequenceTests) + listTests += list_test_cases(DerOctetStringTests) + listTests += list_test_cases(DerNullTests) + listTests += list_test_cases(DerObjectIdTests) + listTests += list_test_cases(DerBitStringTests) + listTests += list_test_cases(DerSetOfTests) + listTests += list_test_cases(DerBooleanTests) + return listTests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_number.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_number.py index 8221443d..48ea9455 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_number.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_number.py @@ -24,7 +24,6 @@ """Self-tests for (some of) Cryptodome.Util.number""" -import math import unittest from Cryptodome.Util.py3compat import * @@ -35,158 +34,177 @@ class MyError(Exception): - """Dummy exception used for tests""" + """Dummy exception used for tests""" + # NB: In some places, we compare tuples instead of just output values so that # if any inputs cause a test failure, we'll be able to tell which ones. -class MiscTests(unittest.TestCase): - def test_ceil_div(self): - """Util.number.ceil_div""" - self.assertRaises(TypeError, number.ceil_div, "1", 1) - self.assertRaises(ZeroDivisionError, number.ceil_div, 1, 0) - self.assertRaises(ZeroDivisionError, number.ceil_div, -1, 0) - - # b = 1 - self.assertEqual(0, number.ceil_div(0, 1)) - self.assertEqual(1, number.ceil_div(1, 1)) - self.assertEqual(2, number.ceil_div(2, 1)) - self.assertEqual(3, number.ceil_div(3, 1)) - - # b = 2 - self.assertEqual(0, number.ceil_div(0, 2)) - self.assertEqual(1, number.ceil_div(1, 2)) - self.assertEqual(1, number.ceil_div(2, 2)) - self.assertEqual(2, number.ceil_div(3, 2)) - self.assertEqual(2, number.ceil_div(4, 2)) - self.assertEqual(3, number.ceil_div(5, 2)) - - # b = 3 - self.assertEqual(0, number.ceil_div(0, 3)) - self.assertEqual(1, number.ceil_div(1, 3)) - self.assertEqual(1, number.ceil_div(2, 3)) - self.assertEqual(1, number.ceil_div(3, 3)) - self.assertEqual(2, number.ceil_div(4, 3)) - self.assertEqual(2, number.ceil_div(5, 3)) - self.assertEqual(2, number.ceil_div(6, 3)) - self.assertEqual(3, number.ceil_div(7, 3)) - - # b = 4 - self.assertEqual(0, number.ceil_div(0, 4)) - self.assertEqual(1, number.ceil_div(1, 4)) - self.assertEqual(1, number.ceil_div(2, 4)) - self.assertEqual(1, number.ceil_div(3, 4)) - self.assertEqual(1, number.ceil_div(4, 4)) - self.assertEqual(2, number.ceil_div(5, 4)) - self.assertEqual(2, number.ceil_div(6, 4)) - self.assertEqual(2, number.ceil_div(7, 4)) - self.assertEqual(2, number.ceil_div(8, 4)) - self.assertEqual(3, number.ceil_div(9, 4)) - - def test_getPrime(self): - """Util.number.getPrime""" - self.assertRaises(ValueError, number.getPrime, -100) - self.assertRaises(ValueError, number.getPrime, 0) - self.assertRaises(ValueError, number.getPrime, 1) - - bits = 4 - for i in range(100): - x = number.getPrime(bits) - self.assertEqual(x >= (1 << bits - 1), 1) - self.assertEqual(x < (1 << bits), 1) - - bits = 512 - x = number.getPrime(bits) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x >= (1 << bits - 1), 1) - self.assertEqual(x < (1 << bits), 1) - - def test_getStrongPrime(self): - """Util.number.getStrongPrime""" - self.assertRaises(ValueError, number.getStrongPrime, 256) - self.assertRaises(ValueError, number.getStrongPrime, 513) - bits = 512 - x = number.getStrongPrime(bits) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x > (1 << bits-1)-1, 1) - self.assertEqual(x < (1 << bits), 1) - e = 2**16+1 - x = number.getStrongPrime(bits, e) - self.assertEqual(number.GCD(x-1, e), 1) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x > (1 << bits-1)-1, 1) - self.assertEqual(x < (1 << bits), 1) - e = 2**16+2 - x = number.getStrongPrime(bits, e) - self.assertEqual(number.GCD((x-1)>>1, e), 1) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x > (1 << bits-1)-1, 1) - self.assertEqual(x < (1 << bits), 1) - - def test_isPrime(self): - """Util.number.isPrime""" - self.assertEqual(number.isPrime(-3), False) # Regression test: negative numbers should not be prime - self.assertEqual(number.isPrime(-2), False) # Regression test: negative numbers should not be prime - self.assertEqual(number.isPrime(1), False) # Regression test: isPrime(1) caused some versions of PyCryptodome to crash. - self.assertEqual(number.isPrime(2), True) - self.assertEqual(number.isPrime(3), True) - self.assertEqual(number.isPrime(4), False) - self.assertEqual(number.isPrime(2**1279-1), True) - self.assertEqual(number.isPrime(-(2**1279-1)), False) # Regression test: negative numbers should not be prime - # test some known gmp pseudo-primes taken from - # http://www.trnicely.net/misc/mpzspsp.html - for composite in (43 * 127 * 211, 61 * 151 * 211, 15259 * 30517, - 346141 * 692281, 1007119 * 2014237, 3589477 * 7178953, - 4859419 * 9718837, 2730439 * 5460877, - 245127919 * 490255837, 963939391 * 1927878781, - 4186358431 * 8372716861, 1576820467 * 3153640933): - self.assertEqual(number.isPrime(int(composite)), False) - - def test_size(self): - self.assertEqual(number.size(2),2) - self.assertEqual(number.size(3),2) - self.assertEqual(number.size(0xa2),8) - self.assertEqual(number.size(0xa2ba40),8*3) - self.assertEqual(number.size(0xa2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5), 1024) - self.assertRaises(ValueError, number.size, -1) +class MiscTests(unittest.TestCase): + def test_ceil_div(self): + """Util.number.ceil_div""" + self.assertRaises(TypeError, number.ceil_div, "1", 1) + self.assertRaises(ZeroDivisionError, number.ceil_div, 1, 0) + self.assertRaises(ZeroDivisionError, number.ceil_div, -1, 0) + + # b = 1 + self.assertEqual(0, number.ceil_div(0, 1)) + self.assertEqual(1, number.ceil_div(1, 1)) + self.assertEqual(2, number.ceil_div(2, 1)) + self.assertEqual(3, number.ceil_div(3, 1)) + + # b = 2 + self.assertEqual(0, number.ceil_div(0, 2)) + self.assertEqual(1, number.ceil_div(1, 2)) + self.assertEqual(1, number.ceil_div(2, 2)) + self.assertEqual(2, number.ceil_div(3, 2)) + self.assertEqual(2, number.ceil_div(4, 2)) + self.assertEqual(3, number.ceil_div(5, 2)) + + # b = 3 + self.assertEqual(0, number.ceil_div(0, 3)) + self.assertEqual(1, number.ceil_div(1, 3)) + self.assertEqual(1, number.ceil_div(2, 3)) + self.assertEqual(1, number.ceil_div(3, 3)) + self.assertEqual(2, number.ceil_div(4, 3)) + self.assertEqual(2, number.ceil_div(5, 3)) + self.assertEqual(2, number.ceil_div(6, 3)) + self.assertEqual(3, number.ceil_div(7, 3)) + + # b = 4 + self.assertEqual(0, number.ceil_div(0, 4)) + self.assertEqual(1, number.ceil_div(1, 4)) + self.assertEqual(1, number.ceil_div(2, 4)) + self.assertEqual(1, number.ceil_div(3, 4)) + self.assertEqual(1, number.ceil_div(4, 4)) + self.assertEqual(2, number.ceil_div(5, 4)) + self.assertEqual(2, number.ceil_div(6, 4)) + self.assertEqual(2, number.ceil_div(7, 4)) + self.assertEqual(2, number.ceil_div(8, 4)) + self.assertEqual(3, number.ceil_div(9, 4)) + + def test_getPrime(self): + """Util.number.getPrime""" + self.assertRaises(ValueError, number.getPrime, -100) + self.assertRaises(ValueError, number.getPrime, 0) + self.assertRaises(ValueError, number.getPrime, 1) + + bits = 4 + for i in range(100): + x = number.getPrime(bits) + self.assertEqual(x >= (1 << bits - 1), 1) + self.assertEqual(x < (1 << bits), 1) + + bits = 512 + x = number.getPrime(bits) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x >= (1 << bits - 1), 1) + self.assertEqual(x < (1 << bits), 1) + + def test_getStrongPrime(self): + """Util.number.getStrongPrime""" + self.assertRaises(ValueError, number.getStrongPrime, 256) + self.assertRaises(ValueError, number.getStrongPrime, 513) + bits = 512 + x = number.getStrongPrime(bits) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x > (1 << bits - 1) - 1, 1) + self.assertEqual(x < (1 << bits), 1) + e = 2**16 + 1 + x = number.getStrongPrime(bits, e) + self.assertEqual(number.GCD(x - 1, e), 1) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x > (1 << bits - 1) - 1, 1) + self.assertEqual(x < (1 << bits), 1) + e = 2**16 + 2 + x = number.getStrongPrime(bits, e) + self.assertEqual(number.GCD((x - 1) >> 1, e), 1) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x > (1 << bits - 1) - 1, 1) + self.assertEqual(x < (1 << bits), 1) + + def test_isPrime(self): + """Util.number.isPrime""" + self.assertEqual(number.isPrime(-3), False) # Regression test: negative numbers should not be prime + self.assertEqual(number.isPrime(-2), False) # Regression test: negative numbers should not be prime + self.assertEqual( + number.isPrime(1), False + ) # Regression test: isPrime(1) caused some versions of PyCryptodome to crash. + self.assertEqual(number.isPrime(2), True) + self.assertEqual(number.isPrime(3), True) + self.assertEqual(number.isPrime(4), False) + self.assertEqual(number.isPrime(2**1279 - 1), True) + self.assertEqual( + number.isPrime(-(2**1279 - 1)), False + ) # Regression test: negative numbers should not be prime + # test some known gmp pseudo-primes taken from + # http://www.trnicely.net/misc/mpzspsp.html + for composite in ( + 43 * 127 * 211, + 61 * 151 * 211, + 15259 * 30517, + 346141 * 692281, + 1007119 * 2014237, + 3589477 * 7178953, + 4859419 * 9718837, + 2730439 * 5460877, + 245127919 * 490255837, + 963939391 * 1927878781, + 4186358431 * 8372716861, + 1576820467 * 3153640933, + ): + self.assertEqual(number.isPrime(int(composite)), False) + + def test_size(self): + self.assertEqual(number.size(2), 2) + self.assertEqual(number.size(3), 2) + self.assertEqual(number.size(0xA2), 8) + self.assertEqual(number.size(0xA2BA40), 8 * 3) + self.assertEqual( + number.size( + 0xA2BA40EE07E3B2BD2F02CE227F36A195024486E49C19CB41BBBDFBBA98B22B0E577C2EEAFFA20D883A76E65E394C69D4B3C05A1E8FADDA27EDB2A42BC000FE888B9B32C22D15ADD0CD76B3E7936E19955B220DD17D4EA904B1EC102B2E4DE7751222AA99151024C7CB41CC5EA21D00EEB41F7C800834D2C6E06BCE3BCE7EA9A5 + ), + 1024, + ) + self.assertRaises(ValueError, number.size, -1) class LongTests(unittest.TestCase): - - def test1(self): - self.assertEqual(long_to_bytes(0), b'\x00') - self.assertEqual(long_to_bytes(1), b'\x01') - self.assertEqual(long_to_bytes(0x100), b'\x01\x00') - self.assertEqual(long_to_bytes(0xFF00000000), b'\xFF\x00\x00\x00\x00') - self.assertEqual(long_to_bytes(0xFF00000000), b'\xFF\x00\x00\x00\x00') - self.assertEqual(long_to_bytes(0x1122334455667788), b'\x11\x22\x33\x44\x55\x66\x77\x88') - self.assertEqual(long_to_bytes(0x112233445566778899), b'\x11\x22\x33\x44\x55\x66\x77\x88\x99') - - def test2(self): - self.assertEqual(long_to_bytes(0, 1), b'\x00') - self.assertEqual(long_to_bytes(0, 2), b'\x00\x00') - self.assertEqual(long_to_bytes(1, 3), b'\x00\x00\x01') - self.assertEqual(long_to_bytes(65535, 2), b'\xFF\xFF') - self.assertEqual(long_to_bytes(65536, 2), b'\x00\x01\x00\x00') - self.assertEqual(long_to_bytes(0x100, 1), b'\x01\x00') - self.assertEqual(long_to_bytes(0xFF00000001, 6), b'\x00\xFF\x00\x00\x00\x01') - self.assertEqual(long_to_bytes(0xFF00000001, 8), b'\x00\x00\x00\xFF\x00\x00\x00\x01') - self.assertEqual(long_to_bytes(0xFF00000001, 10), b'\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x01') - self.assertEqual(long_to_bytes(0xFF00000001, 11), b'\x00\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x01') - - def test_err1(self): - self.assertRaises(ValueError, long_to_bytes, -1) + def test1(self): + self.assertEqual(long_to_bytes(0), b"\x00") + self.assertEqual(long_to_bytes(1), b"\x01") + self.assertEqual(long_to_bytes(0x100), b"\x01\x00") + self.assertEqual(long_to_bytes(0xFF00000000), b"\xff\x00\x00\x00\x00") + self.assertEqual(long_to_bytes(0xFF00000000), b"\xff\x00\x00\x00\x00") + self.assertEqual(long_to_bytes(0x1122334455667788), b"\x11\x22\x33\x44\x55\x66\x77\x88") + self.assertEqual(long_to_bytes(0x112233445566778899), b"\x11\x22\x33\x44\x55\x66\x77\x88\x99") + + def test2(self): + self.assertEqual(long_to_bytes(0, 1), b"\x00") + self.assertEqual(long_to_bytes(0, 2), b"\x00\x00") + self.assertEqual(long_to_bytes(1, 3), b"\x00\x00\x01") + self.assertEqual(long_to_bytes(65535, 2), b"\xff\xff") + self.assertEqual(long_to_bytes(65536, 2), b"\x00\x01\x00\x00") + self.assertEqual(long_to_bytes(0x100, 1), b"\x01\x00") + self.assertEqual(long_to_bytes(0xFF00000001, 6), b"\x00\xff\x00\x00\x00\x01") + self.assertEqual(long_to_bytes(0xFF00000001, 8), b"\x00\x00\x00\xff\x00\x00\x00\x01") + self.assertEqual(long_to_bytes(0xFF00000001, 10), b"\x00\x00\x00\x00\x00\xff\x00\x00\x00\x01") + self.assertEqual(long_to_bytes(0xFF00000001, 11), b"\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x01") + + def test_err1(self): + self.assertRaises(ValueError, long_to_bytes, -1) def get_tests(config={}): - tests = [] - tests += list_test_cases(MiscTests) - tests += list_test_cases(LongTests) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(MiscTests) + tests += list_test_cases(LongTests) + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_rfc1751.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_rfc1751.py index 43b137dc..6aac612a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_rfc1751.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_rfc1751.py @@ -5,34 +5,33 @@ class RFC1751_Tests(unittest.TestCase): + def test1(self): + data = [ + ("EB33F77EE73D4053", "TIDE ITCH SLOW REIN RULE MOT"), + ("CCAC2AED591056BE4F90FD441C534766", "RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE"), + ("EFF81F9BFBC65350920CDD7416DE8009", "TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL"), + ] - def test1(self): - data = [ - ('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), - ('CCAC2AED591056BE4F90FD441C534766', 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), - ('EFF81F9BFBC65350920CDD7416DE8009', 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') - ] + for key_hex, words in data: + key_bin = binascii.a2b_hex(key_hex) - for key_hex, words in data: - key_bin = binascii.a2b_hex(key_hex) + w2 = key_to_english(key_bin) + self.assertEqual(w2, words) - w2 = key_to_english(key_bin) - self.assertEqual(w2, words) + k2 = english_to_key(words) + self.assertEqual(k2, key_bin) - k2 = english_to_key(words) - self.assertEqual(k2, key_bin) - - def test_error_key_to_english(self): - - self.assertRaises(ValueError, key_to_english, b'0' * 7) + def test_error_key_to_english(self): + self.assertRaises(ValueError, key_to_english, b"0" * 7) def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - tests = list_test_cases(RFC1751_Tests) - return tests + from Cryptodome.SelfTest.st_common import list_test_cases + + tests = list_test_cases(RFC1751_Tests) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_strxor.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_strxor.py index 6a96129a..25191d25 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_strxor.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/Util/test_strxor.py @@ -32,249 +32,247 @@ # =================================================================== import unittest -from binascii import unhexlify, hexlify +from binascii import unhexlify from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Util.strxor import strxor, strxor_c class StrxorTests(unittest.TestCase): + def test1(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + result = unhexlify(b"c70ed123c59a7fcb6f12") + self.assertEqual(strxor(term1, term2), result) + self.assertEqual(strxor(term2, term1), result) - def test1(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - result = unhexlify(b"c70ed123c59a7fcb6f12") - self.assertEqual(strxor(term1, term2), result) - self.assertEqual(strxor(term2, term1), result) - - def test2(self): - es = b"" - self.assertEqual(strxor(es, es), es) - - def test3(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - all_zeros = b"\x00" * len(term1) - self.assertEqual(strxor(term1, term1), all_zeros) - - def test_wrong_length(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"ff339a83e5cd4cdf564990") - self.assertRaises(ValueError, strxor, term1, term2) - - def test_bytearray(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_ba = bytearray(term1) - term2 = unhexlify(b"383d4ba020573314395b") - result = unhexlify(b"c70ed123c59a7fcb6f12") - - self.assertEqual(strxor(term1_ba, term2), result) - - def test_memoryview(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_mv = memoryview(term1) - term2 = unhexlify(b"383d4ba020573314395b") - result = unhexlify(b"c70ed123c59a7fcb6f12") - - self.assertEqual(strxor(term1_mv, term2), result) - - def test_output_bytearray(self): - """Verify result can be stored in pre-allocated memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - original_term1 = term1[:] - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - output = bytearray(len(term1)) - - result = strxor(term1, term2, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_xor) - self.assertEqual(term1, original_term1) - self.assertEqual(term2, original_term2) - - def test_output_memoryview(self): - """Verify result can be stored in pre-allocated memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - original_term1 = term1[:] - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - output = memoryview(bytearray(len(term1))) - - result = strxor(term1, term2, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_xor) - self.assertEqual(term1, original_term1) - self.assertEqual(term2, original_term2) - - def test_output_overlapping_bytearray(self): - """Verify result can be stored in overlapping memory""" - - term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) - term2 = unhexlify(b"383d4ba020573314395b") - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - - result = strxor(term1, term2, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - self.assertEqual(term2, original_term2) - - def test_output_overlapping_memoryview(self): - """Verify result can be stored in overlapping memory""" - - term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) - term2 = unhexlify(b"383d4ba020573314395b") - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - - result = strxor(term1, term2, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - self.assertEqual(term2, original_term2) - - def test_output_ro_bytes(self): - """Verify result cannot be stored in read-only memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - - self.assertRaises(TypeError, strxor, term1, term2, output=term1) - - def test_output_ro_memoryview(self): - """Verify result cannot be stored in read-only memory""" - - term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) - term2 = unhexlify(b"383d4ba020573314395b") - - self.assertRaises(TypeError, strxor, term1, term2, output=term1) - - def test_output_incorrect_length(self): - """Verify result cannot be stored in memory of incorrect length""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - output = bytearray(len(term1) - 1) - - self.assertRaises(ValueError, strxor, term1, term2, output=output) + def test2(self): + es = b"" + self.assertEqual(strxor(es, es), es) + + def test3(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + all_zeros = b"\x00" * len(term1) + self.assertEqual(strxor(term1, term1), all_zeros) + + def test_wrong_length(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"ff339a83e5cd4cdf564990") + self.assertRaises(ValueError, strxor, term1, term2) + + def test_bytearray(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term1_ba = bytearray(term1) + term2 = unhexlify(b"383d4ba020573314395b") + result = unhexlify(b"c70ed123c59a7fcb6f12") + + self.assertEqual(strxor(term1_ba, term2), result) + + def test_memoryview(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term1_mv = memoryview(term1) + term2 = unhexlify(b"383d4ba020573314395b") + result = unhexlify(b"c70ed123c59a7fcb6f12") + + self.assertEqual(strxor(term1_mv, term2), result) + + def test_output_bytearray(self): + """Verify result can be stored in pre-allocated memory""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + original_term1 = term1[:] + original_term2 = term2[:] + expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") + output = bytearray(len(term1)) + + result = strxor(term1, term2, output=output) + + self.assertEqual(result, None) + self.assertEqual(output, expected_xor) + self.assertEqual(term1, original_term1) + self.assertEqual(term2, original_term2) + + def test_output_memoryview(self): + """Verify result can be stored in pre-allocated memory""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + original_term1 = term1[:] + original_term2 = term2[:] + expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") + output = memoryview(bytearray(len(term1))) + + result = strxor(term1, term2, output=output) + + self.assertEqual(result, None) + self.assertEqual(output, expected_xor) + self.assertEqual(term1, original_term1) + self.assertEqual(term2, original_term2) + + def test_output_overlapping_bytearray(self): + """Verify result can be stored in overlapping memory""" + + term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) + term2 = unhexlify(b"383d4ba020573314395b") + original_term2 = term2[:] + expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") + + result = strxor(term1, term2, output=term1) + + self.assertEqual(result, None) + self.assertEqual(term1, expected_xor) + self.assertEqual(term2, original_term2) + + def test_output_overlapping_memoryview(self): + """Verify result can be stored in overlapping memory""" + + term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) + term2 = unhexlify(b"383d4ba020573314395b") + original_term2 = term2[:] + expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") + + result = strxor(term1, term2, output=term1) + + self.assertEqual(result, None) + self.assertEqual(term1, expected_xor) + self.assertEqual(term2, original_term2) + + def test_output_ro_bytes(self): + """Verify result cannot be stored in read-only memory""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + + self.assertRaises(TypeError, strxor, term1, term2, output=term1) + + def test_output_ro_memoryview(self): + """Verify result cannot be stored in read-only memory""" + + term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) + term2 = unhexlify(b"383d4ba020573314395b") + + self.assertRaises(TypeError, strxor, term1, term2, output=term1) + + def test_output_incorrect_length(self): + """Verify result cannot be stored in memory of incorrect length""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + output = bytearray(len(term1) - 1) + + self.assertRaises(ValueError, strxor, term1, term2, output=output) class Strxor_cTests(unittest.TestCase): + def test1(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + result = unhexlify(b"be72dbc2a48c0d9e1708") + self.assertEqual(strxor_c(term1, 65), result) + + def test2(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + self.assertEqual(strxor_c(term1, 0), term1) + + def test3(self): + self.assertEqual(strxor_c(b"", 90), b"") + + def test_wrong_range(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + self.assertRaises(ValueError, strxor_c, term1, -1) + self.assertRaises(ValueError, strxor_c, term1, 256) + + def test_bytearray(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term1_ba = bytearray(term1) + result = unhexlify(b"be72dbc2a48c0d9e1708") + + self.assertEqual(strxor_c(term1_ba, 65), result) + + def test_memoryview(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term1_mv = memoryview(term1) + result = unhexlify(b"be72dbc2a48c0d9e1708") + + self.assertEqual(strxor_c(term1_mv, 65), result) + + def test_output_bytearray(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + original_term1 = term1[:] + expected_result = unhexlify(b"be72dbc2a48c0d9e1708") + output = bytearray(len(term1)) + + result = strxor_c(term1, 65, output=output) + + self.assertEqual(result, None) + self.assertEqual(output, expected_result) + self.assertEqual(term1, original_term1) + + def test_output_memoryview(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + original_term1 = term1[:] + expected_result = unhexlify(b"be72dbc2a48c0d9e1708") + output = memoryview(bytearray(len(term1))) + + result = strxor_c(term1, 65, output=output) + + self.assertEqual(result, None) + self.assertEqual(output, expected_result) + self.assertEqual(term1, original_term1) + + def test_output_overlapping_bytearray(self): + """Verify result can be stored in overlapping memory""" + + term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) + expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") + + result = strxor_c(term1, 65, output=term1) + + self.assertEqual(result, None) + self.assertEqual(term1, expected_xor) + + def test_output_overlapping_memoryview(self): + """Verify result can be stored in overlapping memory""" + + term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) + expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") + + result = strxor_c(term1, 65, output=term1) + + self.assertEqual(result, None) + self.assertEqual(term1, expected_xor) + + def test_output_ro_bytes(self): + """Verify result cannot be stored in read-only memory""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + + self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) + + def test_output_ro_memoryview(self): + """Verify result cannot be stored in read-only memory""" + + term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) + term2 = unhexlify(b"383d4ba020573314395b") + + self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) + + def test_output_incorrect_length(self): + """Verify result cannot be stored in memory of incorrect length""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + output = bytearray(len(term1) - 1) - def test1(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - result = unhexlify(b"be72dbc2a48c0d9e1708") - self.assertEqual(strxor_c(term1, 65), result) - - def test2(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - self.assertEqual(strxor_c(term1, 0), term1) - - def test3(self): - self.assertEqual(strxor_c(b"", 90), b"") - - def test_wrong_range(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - self.assertRaises(ValueError, strxor_c, term1, -1) - self.assertRaises(ValueError, strxor_c, term1, 256) - - def test_bytearray(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_ba = bytearray(term1) - result = unhexlify(b"be72dbc2a48c0d9e1708") - - self.assertEqual(strxor_c(term1_ba, 65), result) - - def test_memoryview(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_mv = memoryview(term1) - result = unhexlify(b"be72dbc2a48c0d9e1708") - - self.assertEqual(strxor_c(term1_mv, 65), result) - - def test_output_bytearray(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - original_term1 = term1[:] - expected_result = unhexlify(b"be72dbc2a48c0d9e1708") - output = bytearray(len(term1)) - - result = strxor_c(term1, 65, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_result) - self.assertEqual(term1, original_term1) - - def test_output_memoryview(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - original_term1 = term1[:] - expected_result = unhexlify(b"be72dbc2a48c0d9e1708") - output = memoryview(bytearray(len(term1))) - - result = strxor_c(term1, 65, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_result) - self.assertEqual(term1, original_term1) - - def test_output_overlapping_bytearray(self): - """Verify result can be stored in overlapping memory""" - - term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) - expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") - - result = strxor_c(term1, 65, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - - def test_output_overlapping_memoryview(self): - """Verify result can be stored in overlapping memory""" - - term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) - expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") - - result = strxor_c(term1, 65, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - - def test_output_ro_bytes(self): - """Verify result cannot be stored in read-only memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - - self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) - - def test_output_ro_memoryview(self): - """Verify result cannot be stored in read-only memory""" - - term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) - term2 = unhexlify(b"383d4ba020573314395b") - - self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) - - def test_output_incorrect_length(self): - """Verify result cannot be stored in memory of incorrect length""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - output = bytearray(len(term1) - 1) - - self.assertRaises(ValueError, strxor_c, term1, 65, output=output) + self.assertRaises(ValueError, strxor_c, term1, 65, output=output) def get_tests(config={}): - tests = [] - tests += list_test_cases(StrxorTests) - tests += list_test_cases(Strxor_cTests) - return tests + tests = [] + tests += list_test_cases(StrxorTests) + tests += list_test_cases(Strxor_cTests) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/__init__.py index 09bb48c6..89c0cec8 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/__init__.py @@ -35,68 +35,77 @@ class SelfTestError(Exception): - def __init__(self, message, result): - Exception.__init__(self, message, result) - self.message = message - self.result = result + def __init__(self, message, result): + Exception.__init__(self, message, result) + self.message = message + self.result = result def run(module=None, verbosity=0, stream=None, tests=None, config=None, **kwargs): - """Execute self-tests. - - This raises SelfTestError if any test is unsuccessful. - - You may optionally pass in a sub-module of SelfTest if you only want to - perform some of the tests. For example, the following would test only the - hash modules: - - Cryptodome.SelfTest.run(Cryptodome.SelfTest.Hash) - - """ - - if config is None: - config = {} - suite = unittest.TestSuite() - if module is None: - if tests is None: - tests = get_tests(config=config) - suite.addTests(tests) - else: - if tests is None: - suite.addTests(module.get_tests(config=config)) - else: - raise ValueError("'module' and 'tests' arguments are mutually exclusive") - if stream is None: - kwargs['stream'] = StringIO() - else: - kwargs['stream'] = stream - runner = unittest.TextTestRunner(verbosity=verbosity, **kwargs) - result = runner.run(suite) - if not result.wasSuccessful(): - if stream is None: - sys.stderr.write(kwargs['stream'].getvalue()) - raise SelfTestError("Self-test failed", result) - return result + """Execute self-tests. + + This raises SelfTestError if any test is unsuccessful. + + You may optionally pass in a sub-module of SelfTest if you only want to + perform some of the tests. For example, the following would test only the + hash modules: + + Cryptodome.SelfTest.run(Cryptodome.SelfTest.Hash) + + """ + + if config is None: + config = {} + suite = unittest.TestSuite() + if module is None: + if tests is None: + tests = get_tests(config=config) + suite.addTests(tests) + else: + if tests is None: + suite.addTests(module.get_tests(config=config)) + else: + raise ValueError("'module' and 'tests' arguments are mutually exclusive") + if stream is None: + kwargs["stream"] = StringIO() + else: + kwargs["stream"] = stream + runner = unittest.TextTestRunner(verbosity=verbosity, **kwargs) + result = runner.run(suite) + if not result.wasSuccessful(): + if stream is None: + sys.stderr.write(kwargs["stream"].getvalue()) + raise SelfTestError("Self-test failed", result) + return result def get_tests(config={}): - tests = [] + tests = [] - module_names = [ - "Cipher", "Hash", "Protocol", "PublicKey", "Random", - "Util", "Signature", "IO", "Math", - ] + module_names = [ + "Cipher", + "Hash", + "Protocol", + "PublicKey", + "Random", + "Util", + "Signature", + "IO", + "Math", + ] - for name in module_names: - module = import_module("Cryptodome.SelfTest." + name) - tests += module.get_tests(config=config) + for name in module_names: + module = import_module("Cryptodome.SelfTest." + name) + tests += module.get_tests(config=config) - return tests + return tests -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/__main__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/__main__.py index 242d7818..654c9bde 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/__main__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/__main__.py @@ -26,18 +26,18 @@ from Cryptodome import SelfTest -slow_tests = not ("--skip-slow-tests" in sys.argv) +slow_tests = "--skip-slow-tests" not in sys.argv if not slow_tests: - print("Skipping slow tests") + print("Skipping slow tests") wycheproof_warnings = "--wycheproof-warnings" in sys.argv if wycheproof_warnings: - print("Printing Wycheproof warnings") + print("Printing Wycheproof warnings") if "-v" in sys.argv: - verbosity=2 + verbosity = 2 else: - verbosity=1 + verbosity = 1 -config = {'slow_tests': slow_tests, 'wycheproof_warnings': wycheproof_warnings} +config = {"slow_tests": slow_tests, "wycheproof_warnings": wycheproof_warnings} SelfTest.run(stream=sys.stdout, verbosity=verbosity, config=config) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/loader.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/loader.py index 8699c3d9..0bbcca1a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/loader.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/loader.py @@ -39,212 +39,239 @@ try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False def _load_tests(dir_comps, file_in, description, conversions): - """Load and parse a test vector file - - Return a list of objects, one per group of adjacent - KV lines or for a single line in the form "[.*]". - - For a group of lines, the object has one attribute per line. - """ - - line_number = 0 - results = [] - - class TestVector(object): - def __init__(self, description, count): - self.desc = description - self.count = count - self.others = [] - - test_vector = None - count = 0 - new_group = True - - while True: - line_number += 1 - line = file_in.readline() - if not line: - if test_vector is not None: - results.append(test_vector) - break - line = line.strip() - - # Skip comments and empty lines - if line.startswith('#') or not line: - new_group = True - continue - - if line.startswith("["): - if test_vector is not None: - results.append(test_vector) - test_vector = None - results.append(line) - continue - - if new_group: - count += 1 - new_group = False - if test_vector is not None: - results.append(test_vector) - test_vector = TestVector("%s (#%d)" % (description, count), count) - - res = re.match("([A-Za-z0-9]+) = ?(.*)", line) - if not res: - test_vector.others += [line] - else: - token = res.group(1).lower() - data = res.group(2).lower() - - conversion = conversions.get(token, None) - if conversion is None: - if len(data) % 2 != 0: - data = "0" + data - setattr(test_vector, token, binascii.unhexlify(data)) - else: - setattr(test_vector, token, conversion(data)) - - # This line is ignored - return results + """Load and parse a test vector file + + Return a list of objects, one per group of adjacent + KV lines or for a single line in the form "[.*]". + + For a group of lines, the object has one attribute per line. + """ + + line_number = 0 + results = [] + + class TestVector(object): + def __init__(self, description, count): + self.desc = description + self.count = count + self.others = [] + + test_vector = None + count = 0 + new_group = True + + while True: + line_number += 1 + line = file_in.readline() + if not line: + if test_vector is not None: + results.append(test_vector) + break + line = line.strip() + + # Skip comments and empty lines + if line.startswith("#") or not line: + new_group = True + continue + + if line.startswith("["): + if test_vector is not None: + results.append(test_vector) + test_vector = None + results.append(line) + continue + + if new_group: + count += 1 + new_group = False + if test_vector is not None: + results.append(test_vector) + test_vector = TestVector("%s (#%d)" % (description, count), count) + + res = re.match("([A-Za-z0-9]+) = ?(.*)", line) + if not res: + test_vector.others += [line] + else: + token = res.group(1).lower() + data = res.group(2).lower() + + conversion = conversions.get(token, None) + if conversion is None: + if len(data) % 2 != 0: + data = "0" + data + setattr(test_vector, token, binascii.unhexlify(data)) + else: + setattr(test_vector, token, conversion(data)) + + # This line is ignored + return results def load_test_vectors(dir_comps, file_name, description, conversions): - """Load and parse a test vector file, formatted using the NIST style. - - Args: - dir_comps (list of strings): - The path components under the ``pycryptodome_test_vectors`` package. - For instance ``("Cipher", "AES")``. - file_name (string): - The name of the file with the test vectors. - description (string): - A description applicable to the test vectors in the file. - conversions (dictionary): - The dictionary contains functions. - Values in the file that have an entry in this dictionary - will be converted usign the matching function. - Otherwise, values will be considered as hexadecimal and - converted to binary. - - Returns: - A list of test vector objects. - - The file is formatted in the following way: - - - Lines starting with "#" are comments and will be ignored. - - Each test vector is a sequence of 1 or more adjacent lines, where - each lines is an assignement. - - Test vectors are separated by an empty line, a comment, or - a line starting with "[". - - A test vector object has the following attributes: - - - desc (string): description - - counter (int): the order of the test vector in the file (from 1) - - others (list): zero or more lines of the test vector that were not assignments - - left-hand side of each assignment (lowercase): the value of the - assignement, either converted or bytes. - """ - - results = None - - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) - - description = "%s test (%s)" % (description, file_name) - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name) as file_in: - results = _load_tests(dir_comps, file_in, description, conversions) - - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for " + description, - UserWarning, - stacklevel=2) - - return results - - -def load_test_vectors_wycheproof(dir_comps, file_name, description, - root_tag={}, group_tag={}, unit_tag={}): - - result = [] - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name) as file_in: - tv_tree = json.load(file_in) - - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for " + description, - UserWarning, - stacklevel=2) - return result - - class TestVector(object): - pass - - # Unique attributes that will be converted from - # hexadecimal to binary, unless the attribute is - # listed in the unit_tag dict - unit_attr_hex = {'key', 'iv', 'aad', 'msg', 'ct', 'tag', 'label', - 'ikm', 'salt', 'info', 'okm', 'sig', 'public', - 'shared'} - unit_attr_hex -= set(unit_tag.keys()) - - common_root = {} - for k, v in root_tag.items(): - common_root[k] = v(tv_tree) - - for group in tv_tree['testGroups']: - - common_group = {} - for k, v in group_tag.items(): - common_group[k] = v(group) - - for test in group['tests']: - tv = TestVector() - - for k, v in common_root.items(): - setattr(tv, k, v) - for k, v in common_group.items(): - setattr(tv, k, v) - - tv.id = test['tcId'] - tv.comment = test['comment'] - for attr in unit_attr_hex: - if attr in test: - try: - setattr(tv, attr, unhexlify(test[attr])) - except binascii.Error: - raise ValueError("Error decoding attribute '%s' (tcId=%s, file %s)" % (attr, tv.id, file_name)) - tv.filename = file_name - - for k, v in unit_tag.items(): - setattr(tv, k, v(test)) - - tv.valid = test['result'] != "invalid" - tv.warning = test['result'] == "acceptable" - tv.flags = test.get('flags') - - tv.filename = file_name - - result.append(tv) - - return result - + """Load and parse a test vector file, formatted using the NIST style. + + Args: + dir_comps (list of strings): + The path components under the ``pycryptodome_test_vectors`` package. + For instance ``("Cipher", "AES")``. + file_name (string): + The name of the file with the test vectors. + description (string): + A description applicable to the test vectors in the file. + conversions (dictionary): + The dictionary contains functions. + Values in the file that have an entry in this dictionary + will be converted usign the matching function. + Otherwise, values will be considered as hexadecimal and + converted to binary. + + Returns: + A list of test vector objects. + + The file is formatted in the following way: + + - Lines starting with "#" are comments and will be ignored. + - Each test vector is a sequence of 1 or more adjacent lines, where + each lines is an assignement. + - Test vectors are separated by an empty line, a comment, or + a line starting with "[". + + A test vector object has the following attributes: + + - desc (string): description + - counter (int): the order of the test vector in the file (from 1) + - others (list): zero or more lines of the test vector that were not assignments + - left-hand side of each assignment (lowercase): the value of the + assignement, either converted or bytes. + """ + + results = None + + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) + + description = "%s test (%s)" % (description, file_name) + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name) as file_in: + results = _load_tests(dir_comps, file_in, description, conversions) + + except FileNotFoundError: + warnings.warn( + "Warning: skipping extended tests for " + description, + UserWarning, + stacklevel=2, + ) + + return results + + +def load_test_vectors_wycheproof( + dir_comps, + file_name, + description, + root_tag={}, + group_tag={}, + unit_tag={}, +): + result = [] + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name) as file_in: + tv_tree = json.load(file_in) + + except FileNotFoundError: + warnings.warn( + "Warning: skipping extended tests for " + description, + UserWarning, + stacklevel=2, + ) + return result + + class TestVector(object): + pass + + # Unique attributes that will be converted from + # hexadecimal to binary, unless the attribute is + # listed in the unit_tag dict + unit_attr_hex = { + "key", + "iv", + "aad", + "msg", + "ct", + "tag", + "label", + "ikm", + "salt", + "info", + "okm", + "sig", + "public", + "shared", + } + unit_attr_hex -= set(unit_tag.keys()) + + common_root = {} + for k, v in root_tag.items(): + common_root[k] = v(tv_tree) + + for group in tv_tree["testGroups"]: + common_group = {} + for k, v in group_tag.items(): + common_group[k] = v(group) + + for test in group["tests"]: + tv = TestVector() + + for k, v in common_root.items(): + setattr(tv, k, v) + for k, v in common_group.items(): + setattr(tv, k, v) + + tv.id = test["tcId"] + tv.comment = test["comment"] + for attr in unit_attr_hex: + if attr in test: + try: + setattr(tv, attr, unhexlify(test[attr])) + except binascii.Error: + raise ValueError( + "Error decoding attribute '%s' (tcId=%s, file %s)" % (attr, tv.id, file_name) + ) + tv.filename = file_name + + for k, v in unit_tag.items(): + setattr(tv, k, v(test)) + + tv.valid = test["result"] != "invalid" + tv.warning = test["result"] == "acceptable" + tv.flags = test.get("flags") + + tv.filename = file_name + + result.append(tv) + + return result diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/st_common.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/st_common.py index 35652519..780352b9 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/st_common.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/SelfTest/st_common.py @@ -30,26 +30,30 @@ def list_test_cases(class_): - """Return a list of TestCase instances given a TestCase class + """Return a list of TestCase instances given a TestCase class + + This is useful when you have defined test* methods on your TestCase class. + """ + return unittest.TestLoader().loadTestsFromTestCase(class_) - This is useful when you have defined test* methods on your TestCase class. - """ - return unittest.TestLoader().loadTestsFromTestCase(class_) def strip_whitespace(s): - """Remove whitespace from a text or byte string""" - if isinstance(s,str): - return b("".join(s.split())) - else: - return b("").join(s.split()) + """Remove whitespace from a text or byte string""" + if isinstance(s, str): + return b("".join(s.split())) + else: + return b("").join(s.split()) + def a2b_hex(s): - """Convert hexadecimal to binary, ignoring whitespace""" - return binascii.a2b_hex(strip_whitespace(s)) + """Convert hexadecimal to binary, ignoring whitespace""" + return binascii.a2b_hex(strip_whitespace(s)) + def b2a_hex(s): - """Convert binary to hexadecimal""" - # For completeness - return binascii.b2a_hex(s) + """Convert binary to hexadecimal""" + # For completeness + return binascii.b2a_hex(s) + # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/DSS.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/DSS.py index 97d9c850..3b9ecbba 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/DSS.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/DSS.py @@ -39,365 +39,372 @@ from Cryptodome.PublicKey.ECC import EccKey from Cryptodome.PublicKey.DSA import DsaKey -__all__ = ['DssSigScheme', 'new'] +__all__ = ["DssSigScheme", "new"] class DssSigScheme(object): - """A (EC)DSA signature object. - Do not instantiate directly. - Use :func:`Cryptodome.Signature.DSS.new`. - """ - - def __init__(self, key, encoding, order): - """Create a new Digital Signature Standard (DSS) object. - - Do not instantiate this object directly, - use `Cryptodome.Signature.DSS.new` instead. - """ - - self._key = key - self._encoding = encoding - self._order = order - - self._order_bits = self._order.size_in_bits() - self._order_bytes = (self._order_bits - 1) // 8 + 1 - - def can_sign(self): - """Return ``True`` if this signature object can be used - for signing messages.""" - - return self._key.has_private() - - def _compute_nonce(self, msg_hash): - raise NotImplementedError("To be provided by subclasses") - - def _valid_hash(self, msg_hash): - raise NotImplementedError("To be provided by subclasses") - - def sign(self, msg_hash): - """Compute the DSA/ECDSA signature of a message. - - Args: - msg_hash (hash object): - The hash that was carried out over the message. - The object belongs to the :mod:`Cryptodome.Hash` package. - Under mode ``'fips-186-3'``, the hash must be a FIPS - approved secure hash (SHA-2 or SHA-3). - - :return: The signature as ``bytes`` - :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key - :raise TypeError: if the (EC)DSA key has no private half - """ - - if not self._key.has_private(): - raise TypeError("Private key is needed to sign") - - if not self._valid_hash(msg_hash): - raise ValueError("Hash is not sufficiently strong") - - # Generate the nonce k (critical!) - nonce = self._compute_nonce(msg_hash) - - # Perform signature using the raw API - z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) - sig_pair = self._key._sign(z, nonce) - - # Encode the signature into a single byte string - if self._encoding == 'binary': - output = b"".join([long_to_bytes(x, self._order_bytes) - for x in sig_pair]) - else: - # Dss-sig ::= SEQUENCE { - # r INTEGER, - # s INTEGER - # } - # Ecdsa-Sig-Value ::= SEQUENCE { - # r INTEGER, - # s INTEGER - # } - output = DerSequence(sig_pair).encode() - - return output - - def verify(self, msg_hash, signature): - """Check if a certain (EC)DSA signature is authentic. - - Args: - msg_hash (hash object): - The hash that was carried out over the message. - This is an object belonging to the :mod:`Cryptodome.Hash` module. - Under mode ``'fips-186-3'``, the hash must be a FIPS - approved secure hash (SHA-2 or SHA-3). - - signature (``bytes``): - The signature that needs to be validated. - - :raise ValueError: if the signature is not authentic - """ - - if not self._valid_hash(msg_hash): - raise ValueError("Hash is not sufficiently strong") - - if self._encoding == 'binary': - if len(signature) != (2 * self._order_bytes): - raise ValueError("The signature is not authentic (length)") - r_prime, s_prime = [Integer.from_bytes(x) - for x in (signature[:self._order_bytes], - signature[self._order_bytes:])] - else: - try: - der_seq = DerSequence().decode(signature, strict=True) - except (ValueError, IndexError): - raise ValueError("The signature is not authentic (DER)") - if len(der_seq) != 2 or not der_seq.hasOnlyInts(): - raise ValueError("The signature is not authentic (DER content)") - r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1]) - - if not (0 < r_prime < self._order) or not (0 < s_prime < self._order): - raise ValueError("The signature is not authentic (d)") - - z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) - result = self._key._verify(z, (r_prime, s_prime)) - if not result: - raise ValueError("The signature is not authentic") - # Make PyCryptodome code to fail - return False + """A (EC)DSA signature object. + Do not instantiate directly. + Use :func:`Cryptodome.Signature.DSS.new`. + """ + + def __init__(self, key, encoding, order): + """Create a new Digital Signature Standard (DSS) object. + + Do not instantiate this object directly, + use `Cryptodome.Signature.DSS.new` instead. + """ + + self._key = key + self._encoding = encoding + self._order = order + + self._order_bits = self._order.size_in_bits() + self._order_bytes = (self._order_bits - 1) // 8 + 1 + + def can_sign(self): + """Return ``True`` if this signature object can be used + for signing messages.""" + + return self._key.has_private() + + def _compute_nonce(self, msg_hash): + raise NotImplementedError("To be provided by subclasses") + + def _valid_hash(self, msg_hash): + raise NotImplementedError("To be provided by subclasses") + + def sign(self, msg_hash): + """Compute the DSA/ECDSA signature of a message. + + Args: + msg_hash (hash object): + The hash that was carried out over the message. + The object belongs to the :mod:`Cryptodome.Hash` package. + Under mode ``'fips-186-3'``, the hash must be a FIPS + approved secure hash (SHA-2 or SHA-3). + + :return: The signature as ``bytes`` + :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key + :raise TypeError: if the (EC)DSA key has no private half + """ + + if not self._key.has_private(): + raise TypeError("Private key is needed to sign") + + if not self._valid_hash(msg_hash): + raise ValueError("Hash is not sufficiently strong") + + # Generate the nonce k (critical!) + nonce = self._compute_nonce(msg_hash) + + # Perform signature using the raw API + z = Integer.from_bytes(msg_hash.digest()[: self._order_bytes]) + sig_pair = self._key._sign(z, nonce) + + # Encode the signature into a single byte string + if self._encoding == "binary": + output = b"".join([long_to_bytes(x, self._order_bytes) for x in sig_pair]) + else: + # Dss-sig ::= SEQUENCE { + # r INTEGER, + # s INTEGER + # } + # Ecdsa-Sig-Value ::= SEQUENCE { + # r INTEGER, + # s INTEGER + # } + output = DerSequence(sig_pair).encode() + + return output + + def verify(self, msg_hash, signature): + """Check if a certain (EC)DSA signature is authentic. + + Args: + msg_hash (hash object): + The hash that was carried out over the message. + This is an object belonging to the :mod:`Cryptodome.Hash` module. + Under mode ``'fips-186-3'``, the hash must be a FIPS + approved secure hash (SHA-2 or SHA-3). + + signature (``bytes``): + The signature that needs to be validated. + + :raise ValueError: if the signature is not authentic + """ + + if not self._valid_hash(msg_hash): + raise ValueError("Hash is not sufficiently strong") + + if self._encoding == "binary": + if len(signature) != (2 * self._order_bytes): + raise ValueError("The signature is not authentic (length)") + r_prime, s_prime = [ + Integer.from_bytes(x) + for x in ( + signature[: self._order_bytes], + signature[self._order_bytes :], + ) + ] + else: + try: + der_seq = DerSequence().decode(signature, strict=True) + except (ValueError, IndexError): + raise ValueError("The signature is not authentic (DER)") + if len(der_seq) != 2 or not der_seq.hasOnlyInts(): + raise ValueError("The signature is not authentic (DER content)") + r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1]) + + if not (0 < r_prime < self._order) or not (0 < s_prime < self._order): + raise ValueError("The signature is not authentic (d)") + + z = Integer.from_bytes(msg_hash.digest()[: self._order_bytes]) + result = self._key._verify(z, (r_prime, s_prime)) + if not result: + raise ValueError("The signature is not authentic") + # Make PyCryptodome code to fail + return False class DeterministicDsaSigScheme(DssSigScheme): - # Also applicable to ECDSA - - def __init__(self, key, encoding, order, private_key): - super(DeterministicDsaSigScheme, self).__init__(key, encoding, order) - self._private_key = private_key - - def _bits2int(self, bstr): - """See 2.3.2 in RFC6979""" - - result = Integer.from_bytes(bstr) - q_len = self._order.size_in_bits() - b_len = len(bstr) * 8 - if b_len > q_len: - # Only keep leftmost q_len bits - result >>= (b_len - q_len) - return result - - def _int2octets(self, int_mod_q): - """See 2.3.3 in RFC6979""" - - assert 0 < int_mod_q < self._order - return long_to_bytes(int_mod_q, self._order_bytes) - - def _bits2octets(self, bstr): - """See 2.3.4 in RFC6979""" - - z1 = self._bits2int(bstr) - if z1 < self._order: - z2 = z1 - else: - z2 = z1 - self._order - return self._int2octets(z2) - - def _compute_nonce(self, mhash): - """Generate k in a deterministic way""" - - # See section 3.2 in RFC6979.txt - # Step a - h1 = mhash.digest() - # Step b - mask_v = b'\x01' * mhash.digest_size - # Step c - nonce_k = b'\x00' * mhash.digest_size - - for int_oct in (b'\x00', b'\x01'): - # Step d/f - nonce_k = HMAC.new(nonce_k, - mask_v + int_oct + - self._int2octets(self._private_key) + - self._bits2octets(h1), mhash).digest() - # Step e/g - mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() - - nonce = -1 - while not (0 < nonce < self._order): - # Step h.C (second part) - if nonce != -1: - nonce_k = HMAC.new(nonce_k, mask_v + b'\x00', - mhash).digest() - mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() - - # Step h.A - mask_t = b"" - - # Step h.B - while len(mask_t) < self._order_bytes: - mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() - mask_t += mask_v - - # Step h.C (first part) - nonce = self._bits2int(mask_t) - return nonce - - def _valid_hash(self, msg_hash): - return True + # Also applicable to ECDSA + + def __init__(self, key, encoding, order, private_key): + super(DeterministicDsaSigScheme, self).__init__(key, encoding, order) + self._private_key = private_key + + def _bits2int(self, bstr): + """See 2.3.2 in RFC6979""" + + result = Integer.from_bytes(bstr) + q_len = self._order.size_in_bits() + b_len = len(bstr) * 8 + if b_len > q_len: + # Only keep leftmost q_len bits + result >>= b_len - q_len + return result + + def _int2octets(self, int_mod_q): + """See 2.3.3 in RFC6979""" + + assert 0 < int_mod_q < self._order + return long_to_bytes(int_mod_q, self._order_bytes) + + def _bits2octets(self, bstr): + """See 2.3.4 in RFC6979""" + + z1 = self._bits2int(bstr) + if z1 < self._order: + z2 = z1 + else: + z2 = z1 - self._order + return self._int2octets(z2) + + def _compute_nonce(self, mhash): + """Generate k in a deterministic way""" + + # See section 3.2 in RFC6979.txt + # Step a + h1 = mhash.digest() + # Step b + mask_v = b"\x01" * mhash.digest_size + # Step c + nonce_k = b"\x00" * mhash.digest_size + + for int_oct in (b"\x00", b"\x01"): + # Step d/f + nonce_k = HMAC.new( + nonce_k, + mask_v + int_oct + self._int2octets(self._private_key) + self._bits2octets(h1), + mhash, + ).digest() + # Step e/g + mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() + + nonce = -1 + while not (0 < nonce < self._order): + # Step h.C (second part) + if nonce != -1: + nonce_k = HMAC.new( + nonce_k, + mask_v + b"\x00", + mhash, + ).digest() + mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() + + # Step h.A + mask_t = b"" + + # Step h.B + while len(mask_t) < self._order_bytes: + mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() + mask_t += mask_v + + # Step h.C (first part) + nonce = self._bits2int(mask_t) + return nonce + + def _valid_hash(self, msg_hash): + return True class FipsDsaSigScheme(DssSigScheme): - - #: List of L (bit length of p) and N (bit length of q) combinations - #: that are allowed by FIPS 186-3. The security level is provided in - #: Table 2 of FIPS 800-57 (rev3). - _fips_186_3_L_N = ( - (1024, 160), # 80 bits (SHA-1 or stronger) - (2048, 224), # 112 bits (SHA-224 or stronger) - (2048, 256), # 128 bits (SHA-256 or stronger) - (3072, 256) # 256 bits (SHA-512) - ) - - def __init__(self, key, encoding, order, randfunc): - super(FipsDsaSigScheme, self).__init__(key, encoding, order) - self._randfunc = randfunc - - L = Integer(key.p).size_in_bits() - if (L, self._order_bits) not in self._fips_186_3_L_N: - error = ("L/N (%d, %d) is not compliant to FIPS 186-3" - % (L, self._order_bits)) - raise ValueError(error) - - def _compute_nonce(self, msg_hash): - # hash is not used - return Integer.random_range(min_inclusive=1, - max_exclusive=self._order, - randfunc=self._randfunc) - - def _valid_hash(self, msg_hash): - """Verify that SHA-1, SHA-2 or SHA-3 are used""" - return (msg_hash.oid == "1.3.14.3.2.26" or - msg_hash.oid.startswith("2.16.840.1.101.3.4.2.")) + #: List of L (bit length of p) and N (bit length of q) combinations + #: that are allowed by FIPS 186-3. The security level is provided in + #: Table 2 of FIPS 800-57 (rev3). + _fips_186_3_L_N = ( + (1024, 160), # 80 bits (SHA-1 or stronger) + (2048, 224), # 112 bits (SHA-224 or stronger) + (2048, 256), # 128 bits (SHA-256 or stronger) + (3072, 256), # 256 bits (SHA-512) + ) + + def __init__(self, key, encoding, order, randfunc): + super(FipsDsaSigScheme, self).__init__(key, encoding, order) + self._randfunc = randfunc + + L = Integer(key.p).size_in_bits() + if (L, self._order_bits) not in self._fips_186_3_L_N: + error = "L/N (%d, %d) is not compliant to FIPS 186-3" % (L, self._order_bits) + raise ValueError(error) + + def _compute_nonce(self, msg_hash): + # hash is not used + return Integer.random_range( + min_inclusive=1, + max_exclusive=self._order, + randfunc=self._randfunc, + ) + + def _valid_hash(self, msg_hash): + """Verify that SHA-1, SHA-2 or SHA-3 are used""" + return msg_hash.oid == "1.3.14.3.2.26" or msg_hash.oid.startswith("2.16.840.1.101.3.4.2.") class FipsEcDsaSigScheme(DssSigScheme): - - def __init__(self, key, encoding, order, randfunc): - super(FipsEcDsaSigScheme, self).__init__(key, encoding, order) - self._randfunc = randfunc - - def _compute_nonce(self, msg_hash): - return Integer.random_range(min_inclusive=1, - max_exclusive=self._key._curve.order, - randfunc=self._randfunc) - - def _valid_hash(self, msg_hash): - """Verify that the strength of the hash matches or exceeds - the strength of the EC. We fail if the hash is too weak.""" - - modulus_bits = self._key.pointQ.size_in_bits() - - # SHS: SHA-2, SHA-3, truncated SHA-512 - sha224 = ("2.16.840.1.101.3.4.2.4", "2.16.840.1.101.3.4.2.7", "2.16.840.1.101.3.4.2.5") - sha256 = ("2.16.840.1.101.3.4.2.1", "2.16.840.1.101.3.4.2.8", "2.16.840.1.101.3.4.2.6") - sha384 = ("2.16.840.1.101.3.4.2.2", "2.16.840.1.101.3.4.2.9") - sha512 = ("2.16.840.1.101.3.4.2.3", "2.16.840.1.101.3.4.2.10") - shs = sha224 + sha256 + sha384 + sha512 - - try: - result = msg_hash.oid in shs - except AttributeError: - result = False - return result - - -def new(key, mode, encoding='binary', randfunc=None): - """Create a signature object :class:`DssSigScheme` that - can perform (EC)DSA signature or verification. - - .. note:: - Refer to `NIST SP 800 Part 1 Rev 4`_ (or newer release) for an - overview of the recommended key lengths. - - Args: - key (:class:`Cryptodome.PublicKey.DSA` or :class:`Cryptodome.PublicKey.ECC`): - The key to use for computing the signature (*private* keys only) - or for verifying one. - For DSA keys, let ``L`` and ``N`` be the bit lengths of the modulus ``p`` - and of ``q``: the pair ``(L,N)`` must appear in the following list, - in compliance to section 4.2 of `FIPS 186-4`_: - - - (1024, 160) *legacy only; do not create new signatures with this* - - (2048, 224) *deprecated; do not create new signatures with this* - - (2048, 256) - - (3072, 256) - - For ECC, only keys over P-224, P-256, P-384, and P-521 are accepted. - - mode (string): - The parameter can take these values: - - - ``'fips-186-3'``. The signature generation is randomized and carried out - according to `FIPS 186-3`_: the nonce ``k`` is taken from the RNG. - - ``'deterministic-rfc6979'``. The signature generation is not - randomized. See RFC6979_. - - encoding (string): - How the signature is encoded. This value determines the output of - :meth:`sign` and the input to :meth:`verify`. - - The following values are accepted: - - - ``'binary'`` (default), the signature is the raw concatenation - of ``r`` and ``s``. It is defined in the IEEE P.1363 standard. - For DSA, the size in bytes of the signature is ``N/4`` bytes - (e.g. 64 for ``N=256``). - For ECDSA, the signature is always twice the length of a point - coordinate (e.g. 64 bytes for P-256). - - - ``'der'``, the signature is a ASN.1 DER SEQUENCE - with two INTEGERs (``r`` and ``s``). It is defined in RFC3279_. - The size of the signature is variable. - - randfunc (callable): - A function that returns random ``bytes``, of a given length. - If omitted, the internal RNG is used. - Only applicable for the *'fips-186-3'* mode. - - .. _FIPS 186-3: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf - .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - .. _NIST SP 800 Part 1 Rev 4: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf - .. _RFC6979: http://tools.ietf.org/html/rfc6979 - .. _RFC3279: https://tools.ietf.org/html/rfc3279#section-2.2.2 - """ - - # The goal of the 'mode' parameter is to avoid to - # have the current version of the standard as default. - # - # Over time, such version will be superseded by (for instance) - # FIPS 186-4 and it will be odd to have -3 as default. - - if encoding not in ('binary', 'der'): - raise ValueError("Unknown encoding '%s'" % encoding) - - if isinstance(key, EccKey): - order = key._curve.order - private_key_attr = 'd' - if not key.curve.startswith("NIST"): - raise ValueError("ECC key is not on a NIST P curve") - elif isinstance(key, DsaKey): - order = Integer(key.q) - private_key_attr = 'x' - else: - raise ValueError("Unsupported key type " + str(type(key))) - - if key.has_private(): - private_key = getattr(key, private_key_attr) - else: - private_key = None - - if mode == 'deterministic-rfc6979': - return DeterministicDsaSigScheme(key, encoding, order, private_key) - elif mode == 'fips-186-3': - if isinstance(key, EccKey): - return FipsEcDsaSigScheme(key, encoding, order, randfunc) - else: - return FipsDsaSigScheme(key, encoding, order, randfunc) - else: - raise ValueError("Unknown DSS mode '%s'" % mode) + def __init__(self, key, encoding, order, randfunc): + super(FipsEcDsaSigScheme, self).__init__(key, encoding, order) + self._randfunc = randfunc + + def _compute_nonce(self, msg_hash): + return Integer.random_range( + min_inclusive=1, + max_exclusive=self._key._curve.order, + randfunc=self._randfunc, + ) + + def _valid_hash(self, msg_hash): + """Verify that the strength of the hash matches or exceeds + the strength of the EC. We fail if the hash is too weak.""" + + modulus_bits = self._key.pointQ.size_in_bits() + + # SHS: SHA-2, SHA-3, truncated SHA-512 + sha224 = ("2.16.840.1.101.3.4.2.4", "2.16.840.1.101.3.4.2.7", "2.16.840.1.101.3.4.2.5") + sha256 = ("2.16.840.1.101.3.4.2.1", "2.16.840.1.101.3.4.2.8", "2.16.840.1.101.3.4.2.6") + sha384 = ("2.16.840.1.101.3.4.2.2", "2.16.840.1.101.3.4.2.9") + sha512 = ("2.16.840.1.101.3.4.2.3", "2.16.840.1.101.3.4.2.10") + shs = sha224 + sha256 + sha384 + sha512 + + try: + result = msg_hash.oid in shs + except AttributeError: + result = False + return result + + +def new(key, mode, encoding="binary", randfunc=None): + """Create a signature object :class:`DssSigScheme` that + can perform (EC)DSA signature or verification. + + .. note:: + Refer to `NIST SP 800 Part 1 Rev 4`_ (or newer release) for an + overview of the recommended key lengths. + + Args: + key (:class:`Cryptodome.PublicKey.DSA` or :class:`Cryptodome.PublicKey.ECC`): + The key to use for computing the signature (*private* keys only) + or for verifying one. + For DSA keys, let ``L`` and ``N`` be the bit lengths of the modulus ``p`` + and of ``q``: the pair ``(L,N)`` must appear in the following list, + in compliance to section 4.2 of `FIPS 186-4`_: + + - (1024, 160) *legacy only; do not create new signatures with this* + - (2048, 224) *deprecated; do not create new signatures with this* + - (2048, 256) + - (3072, 256) + + For ECC, only keys over P-224, P-256, P-384, and P-521 are accepted. + + mode (string): + The parameter can take these values: + + - ``'fips-186-3'``. The signature generation is randomized and carried out + according to `FIPS 186-3`_: the nonce ``k`` is taken from the RNG. + - ``'deterministic-rfc6979'``. The signature generation is not + randomized. See RFC6979_. + + encoding (string): + How the signature is encoded. This value determines the output of + :meth:`sign` and the input to :meth:`verify`. + + The following values are accepted: + + - ``'binary'`` (default), the signature is the raw concatenation + of ``r`` and ``s``. It is defined in the IEEE P.1363 standard. + For DSA, the size in bytes of the signature is ``N/4`` bytes + (e.g. 64 for ``N=256``). + For ECDSA, the signature is always twice the length of a point + coordinate (e.g. 64 bytes for P-256). + + - ``'der'``, the signature is a ASN.1 DER SEQUENCE + with two INTEGERs (``r`` and ``s``). It is defined in RFC3279_. + The size of the signature is variable. + + randfunc (callable): + A function that returns random ``bytes``, of a given length. + If omitted, the internal RNG is used. + Only applicable for the *'fips-186-3'* mode. + + .. _FIPS 186-3: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + .. _NIST SP 800 Part 1 Rev 4: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf + .. _RFC6979: http://tools.ietf.org/html/rfc6979 + .. _RFC3279: https://tools.ietf.org/html/rfc3279#section-2.2.2 + """ + + # The goal of the 'mode' parameter is to avoid to + # have the current version of the standard as default. + # + # Over time, such version will be superseded by (for instance) + # FIPS 186-4 and it will be odd to have -3 as default. + + if encoding not in ("binary", "der"): + raise ValueError("Unknown encoding '%s'" % encoding) + + if isinstance(key, EccKey): + order = key._curve.order + private_key_attr = "d" + if not key.curve.startswith("NIST"): + raise ValueError("ECC key is not on a NIST P curve") + elif isinstance(key, DsaKey): + order = Integer(key.q) + private_key_attr = "x" + else: + raise ValueError("Unsupported key type " + str(type(key))) + + if key.has_private(): + private_key = getattr(key, private_key_attr) + else: + private_key = None + + if mode == "deterministic-rfc6979": + return DeterministicDsaSigScheme(key, encoding, order, private_key) + elif mode == "fips-186-3": + if isinstance(key, EccKey): + return FipsEcDsaSigScheme(key, encoding, order, randfunc) + else: + return FipsDsaSigScheme(key, encoding, order, randfunc) + else: + raise ValueError("Unknown DSS mode '%s'" % mode) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/DSS.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/DSS.pyi index 52ecc8fb..7f69e321 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/DSS.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/DSS.pyi @@ -5,23 +5,28 @@ from Cryptodome.PublicKey.DSA import DsaKey from Cryptodome.PublicKey.ECC import EccKey class Hash(Protocol): - def digest(self) -> bytes: ... + def digest(self) -> bytes: ... -__all__ = ['new'] +__all__ = ["new"] class DssSigScheme: - def __init__(self, key: Union[DsaKey, EccKey], encoding: str, order: int) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... + def __init__(self, key: Union[DsaKey, EccKey], encoding: str, order: int) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... class DeterministicDsaSigScheme(DssSigScheme): - def __init__(self, key, encoding, order, private_key) -> None: ... + def __init__(self, key, encoding, order, private_key) -> None: ... class FipsDsaSigScheme(DssSigScheme): - def __init__(self, key: DsaKey, encoding: str, order: int, randfunc: Callable) -> None: ... + def __init__(self, key: DsaKey, encoding: str, order: int, randfunc: Callable) -> None: ... class FipsEcDsaSigScheme(DssSigScheme): - def __init__(self, key: EccKey, encoding: str, order: int, randfunc: Callable) -> None: ... - -def new(key: Union[DsaKey, EccKey], mode: str, encoding: Optional[str]='binary', randfunc: Optional[Callable]=None) -> Union[DeterministicDsaSigScheme, FipsDsaSigScheme, FipsEcDsaSigScheme]: ... + def __init__(self, key: EccKey, encoding: str, order: int, randfunc: Callable) -> None: ... + +def new( + key: Union[DsaKey, EccKey], + mode: str, + encoding: Optional[str] = "binary", + randfunc: Optional[Callable] = None, +) -> Union[DeterministicDsaSigScheme, FipsDsaSigScheme, FipsEcDsaSigScheme]: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_PSS.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_PSS.py index 1e7e5b56..17d7d7f7 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_PSS.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_PSS.py @@ -40,16 +40,20 @@ def _pycrypto_verify(self, hash_object, signature): - try: - self._verify(hash_object, signature) - except (ValueError, TypeError): - return False - return True + try: + self._verify(hash_object, signature) + except (ValueError, TypeError): + return False + return True def new(rsa_key, mgfunc=None, saltLen=None, randfunc=None): - pkcs1 = pss.new(rsa_key, mask_func=mgfunc, - salt_bytes=saltLen, rand_func=randfunc) - pkcs1._verify = pkcs1.verify - pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) - return pkcs1 + pkcs1 = pss.new( + rsa_key, + mask_func=mgfunc, + salt_bytes=saltLen, + rand_func=randfunc, + ) + pkcs1._verify = pkcs1.verify + pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) + return pkcs1 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_PSS.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_PSS.pyi index e7424f58..16da2db2 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_PSS.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_PSS.pyi @@ -3,26 +3,26 @@ from typing_extensions import Protocol from Cryptodome.PublicKey.RSA import RsaKey - class Hash(Protocol): - def digest(self) -> bytes: ... - def update(self, bytes) -> None: ... - + def digest(self) -> bytes: ... + def update(self, bytes) -> None: ... class HashModule(Protocol): - @staticmethod - def new(data: Optional[bytes]) -> Hash: ... - + @staticmethod + def new(data: Optional[bytes]) -> Hash: ... MaskFunction = Callable[[bytes, int, Union[Hash, HashModule]], bytes] RndFunction = Callable[[int], bytes] class PSS_SigScheme: - def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... - - - -def new(rsa_key: RsaKey, mgfunc: Optional[MaskFunction]=None, saltLen: Optional[int]=None, randfunc: Optional[RndFunction]=None) -> PSS_SigScheme: ... + def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... + +def new( + rsa_key: RsaKey, + mgfunc: Optional[MaskFunction] = None, + saltLen: Optional[int] = None, + randfunc: Optional[RndFunction] = None, +) -> PSS_SigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_v1_5.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_v1_5.py index d560663c..51262d13 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_v1_5.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_v1_5.py @@ -38,16 +38,17 @@ from Cryptodome.Signature import pkcs1_15 + def _pycrypto_verify(self, hash_object, signature): - try: - self._verify(hash_object, signature) - except (ValueError, TypeError): - return False - return True + try: + self._verify(hash_object, signature) + except (ValueError, TypeError): + return False + return True -def new(rsa_key): - pkcs1 = pkcs1_15.new(rsa_key) - pkcs1._verify = pkcs1.verify - pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) - return pkcs1 +def new(rsa_key): + pkcs1 = pkcs1_15.new(rsa_key) + pkcs1._verify = pkcs1.verify + pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) + return pkcs1 diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_v1_5.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_v1_5.pyi index d02555cd..6fd91ffb 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_v1_5.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/PKCS1_v1_5.pyi @@ -1,16 +1,14 @@ -from typing import Optional from typing_extensions import Protocol from Cryptodome.PublicKey.RSA import RsaKey class Hash(Protocol): - def digest(self) -> bytes: ... + def digest(self) -> bytes: ... class PKCS115_SigScheme: - def __init__(self, rsa_key: RsaKey) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... - + def __init__(self, rsa_key: RsaKey) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/__init__.py index 11ca64c3..c5d37273 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/__init__.py @@ -33,4 +33,4 @@ A collection of standardized protocols to carry out digital signatures. """ -__all__ = ['PKCS1_v1_5', 'PKCS1_PSS', 'DSS', 'pkcs1_15', 'pss', 'eddsa'] +__all__ = ["PKCS1_v1_5", "PKCS1_PSS", "DSS", "pkcs1_15", "pss", "eddsa"] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/eddsa.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/eddsa.py index 02e1e3e4..c607ed5c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/eddsa.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/eddsa.py @@ -32,312 +32,306 @@ from Cryptodome.Hash import SHA512, SHAKE256 from Cryptodome.Util.py3compat import bchr, is_bytes -from Cryptodome.PublicKey.ECC import (EccKey, - construct, - _import_ed25519_public_key, - _import_ed448_public_key) +from Cryptodome.PublicKey.ECC import ( + EccKey, + construct, + _import_ed25519_public_key, + _import_ed448_public_key, +) def import_public_key(encoded): - """Create a new Ed25519 or Ed448 public key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC8032. + """Create a new Ed25519 or Ed448 public key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC8032. - Args: - encoded (bytes): - The EdDSA public key to import. - It must be 32 bytes for Ed25519, and 57 bytes for Ed448. + Args: + encoded (bytes): + The EdDSA public key to import. + It must be 32 bytes for Ed25519, and 57 bytes for Ed448. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - if len(encoded) == 32: - x, y = _import_ed25519_public_key(encoded) - curve_name = "Ed25519" - elif len(encoded) == 57: - x, y = _import_ed448_public_key(encoded) - curve_name = "Ed448" - else: - raise ValueError("Not an EdDSA key (%d bytes)" % len(encoded)) - return construct(curve=curve_name, point_x=x, point_y=y) + if len(encoded) == 32: + x, y = _import_ed25519_public_key(encoded) + curve_name = "Ed25519" + elif len(encoded) == 57: + x, y = _import_ed448_public_key(encoded) + curve_name = "Ed448" + else: + raise ValueError("Not an EdDSA key (%d bytes)" % len(encoded)) + return construct(curve=curve_name, point_x=x, point_y=y) def import_private_key(encoded): - """Create a new Ed25519 or Ed448 private key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC8032. + """Create a new Ed25519 or Ed448 private key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC8032. - Args: - encoded (bytes): - The EdDSA private key to import. - It must be 32 bytes for Ed25519, and 57 bytes for Ed448. + Args: + encoded (bytes): + The EdDSA private key to import. + It must be 32 bytes for Ed25519, and 57 bytes for Ed448. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - if len(encoded) == 32: - curve_name = "ed25519" - elif len(encoded) == 57: - curve_name = "ed448" - else: - raise ValueError("Incorrect length. Only EdDSA private keys are supported.") + if len(encoded) == 32: + curve_name = "ed25519" + elif len(encoded) == 57: + curve_name = "ed448" + else: + raise ValueError("Incorrect length. Only EdDSA private keys are supported.") - # Note that the private key is truly a sequence of random bytes, - # so we cannot check its correctness in any way. + # Note that the private key is truly a sequence of random bytes, + # so we cannot check its correctness in any way. - return construct(seed=encoded, curve=curve_name) + return construct(seed=encoded, curve=curve_name) class EdDSASigScheme(object): - """An EdDSA signature object. - Do not instantiate directly. - Use :func:`Cryptodome.Signature.eddsa.new`. - """ - - def __init__(self, key, context): - """Create a new EdDSA object. - - Do not instantiate this object directly, - use `Cryptodome.Signature.DSS.new` instead. - """ + """An EdDSA signature object. + Do not instantiate directly. + Use :func:`Cryptodome.Signature.eddsa.new`. + """ + + def __init__(self, key, context): + """Create a new EdDSA object. + + Do not instantiate this object directly, + use `Cryptodome.Signature.DSS.new` instead. + """ + + self._key = key + self._context = context + self._A = key._export_eddsa_public() + self._order = key._curve.order + + def can_sign(self): + """Return ``True`` if this signature object can be used + for signing messages.""" + + return self._key.has_private() - self._key = key - self._context = context - self._A = key._export_eddsa_public() - self._order = key._curve.order - - def can_sign(self): - """Return ``True`` if this signature object can be used - for signing messages.""" - - return self._key.has_private() - - def sign(self, msg_or_hash): - """Compute the EdDSA signature of a message. - - Args: - msg_or_hash (bytes or a hash object): - The message to sign (``bytes``, in case of *PureEdDSA*) or - the hash that was carried out over the message (hash object, for *HashEdDSA*). - - The hash object must be :class:`Cryptodome.Hash.SHA512` for Ed25519, - and :class:`Cryptodome.Hash.SHAKE256` object for Ed448. - - :return: The signature as ``bytes``. It is always 64 bytes for Ed25519, and 114 bytes for Ed448. - :raise TypeError: if the EdDSA key has no private half - """ - - if not self._key.has_private(): - raise TypeError("Private key is needed to sign") - - if self._key.curve == "Ed25519": - ph = isinstance(msg_or_hash, SHA512.SHA512Hash) - if not (ph or is_bytes(msg_or_hash)): - raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash") - eddsa_sign_method = self._sign_ed25519 - - elif self._key.curve == "Ed448": - ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF) - if not (ph or is_bytes(msg_or_hash)): - raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash") - eddsa_sign_method = self._sign_ed448 - - else: - raise ValueError("Incorrect curve for EdDSA") - - return eddsa_sign_method(msg_or_hash, ph) - - def _sign_ed25519(self, msg_or_hash, ph): - - if self._context or ph: - flag = int(ph) - # dom2(flag, self._context) - dom2 = b'SigEd25519 no Ed25519 collisions' + bchr(flag) + \ - bchr(len(self._context)) + self._context - else: - dom2 = b'' - - PHM = msg_or_hash.digest() if ph else msg_or_hash - - # See RFC 8032, section 5.1.6 - - # Step 2 - r_hash = SHA512.new(dom2 + self._key._prefix + PHM).digest() - r = Integer.from_bytes(r_hash, 'little') % self._order - # Step 3 - R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public() - # Step 4 - k_hash = SHA512.new(dom2 + R_pk + self._A + PHM).digest() - k = Integer.from_bytes(k_hash, 'little') % self._order - # Step 5 - s = (r + k * self._key.d) % self._order - - return R_pk + s.to_bytes(32, 'little') - - def _sign_ed448(self, msg_or_hash, ph): - - flag = int(ph) - # dom4(flag, self._context) - dom4 = b'SigEd448' + bchr(flag) + \ - bchr(len(self._context)) + self._context - - PHM = msg_or_hash.copy().read(64) if ph else msg_or_hash - - # See RFC 8032, section 5.2.6 - - # Step 2 - r_hash = SHAKE256.new(dom4 + self._key._prefix + PHM).read(114) - r = Integer.from_bytes(r_hash, 'little') % self._order - # Step 3 - R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public() - # Step 4 - k_hash = SHAKE256.new(dom4 + R_pk + self._A + PHM).read(114) - k = Integer.from_bytes(k_hash, 'little') % self._order - # Step 5 - s = (r + k * self._key.d) % self._order - - return R_pk + s.to_bytes(57, 'little') - - def verify(self, msg_or_hash, signature): - """Check if an EdDSA signature is authentic. - - Args: - msg_or_hash (bytes or a hash object): - The message to verify (``bytes``, in case of *PureEdDSA*) or - the hash that was carried out over the message (hash object, for *HashEdDSA*). - - The hash object must be :class:`Cryptodome.Hash.SHA512` object for Ed25519, - and :class:`Cryptodome.Hash.SHAKE256` for Ed448. - - signature (``bytes``): - The signature that needs to be validated. - It must be 64 bytes for Ed25519, and 114 bytes for Ed448. - - :raise ValueError: if the signature is not authentic - """ - - if self._key.curve == "Ed25519": - ph = isinstance(msg_or_hash, SHA512.SHA512Hash) - if not (ph or is_bytes(msg_or_hash)): - raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash") - eddsa_verify_method = self._verify_ed25519 - - elif self._key.curve == "Ed448": - ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF) - if not (ph or is_bytes(msg_or_hash)): - raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash") - eddsa_verify_method = self._verify_ed448 - - else: - raise ValueError("Incorrect curve for EdDSA") - - return eddsa_verify_method(msg_or_hash, signature, ph) - - def _verify_ed25519(self, msg_or_hash, signature, ph): - - if len(signature) != 64: - raise ValueError("The signature is not authentic (length)") - - if self._context or ph: - flag = int(ph) - dom2 = b'SigEd25519 no Ed25519 collisions' + bchr(flag) + \ - bchr(len(self._context)) + self._context - else: - dom2 = b'' - - PHM = msg_or_hash.digest() if ph else msg_or_hash - - # Section 5.1.7 - - # Step 1 - try: - R = import_public_key(signature[:32]).pointQ - except ValueError: - raise ValueError("The signature is not authentic (R)") - s = Integer.from_bytes(signature[32:], 'little') - if s > self._order: - raise ValueError("The signature is not authentic (S)") - # Step 2 - k_hash = SHA512.new(dom2 + signature[:32] + self._A + PHM).digest() - k = Integer.from_bytes(k_hash, 'little') % self._order - # Step 3 - point1 = s * 8 * self._key._curve.G - # OPTIMIZE: with double-scalar multiplication, with no SCA - # countermeasures because it is public values - point2 = 8 * R + k * 8 * self._key.pointQ - if point1 != point2: - raise ValueError("The signature is not authentic") - - def _verify_ed448(self, msg_or_hash, signature, ph): - - if len(signature) != 114: - raise ValueError("The signature is not authentic (length)") - - flag = int(ph) - # dom4(flag, self._context) - dom4 = b'SigEd448' + bchr(flag) + \ - bchr(len(self._context)) + self._context - - PHM = msg_or_hash.copy().read(64) if ph else msg_or_hash - - # Section 5.2.7 - - # Step 1 - try: - R = import_public_key(signature[:57]).pointQ - except ValueError: - raise ValueError("The signature is not authentic (R)") - s = Integer.from_bytes(signature[57:], 'little') - if s > self._order: - raise ValueError("The signature is not authentic (S)") - # Step 2 - k_hash = SHAKE256.new(dom4 + signature[:57] + self._A + PHM).read(114) - k = Integer.from_bytes(k_hash, 'little') % self._order - # Step 3 - point1 = s * 8 * self._key._curve.G - # OPTIMIZE: with double-scalar multiplication, with no SCA - # countermeasures because it is public values - point2 = 8 * R + k * 8 * self._key.pointQ - if point1 != point2: - raise ValueError("The signature is not authentic") + def sign(self, msg_or_hash): + """Compute the EdDSA signature of a message. + + Args: + msg_or_hash (bytes or a hash object): + The message to sign (``bytes``, in case of *PureEdDSA*) or + the hash that was carried out over the message (hash object, for *HashEdDSA*). + + The hash object must be :class:`Cryptodome.Hash.SHA512` for Ed25519, + and :class:`Cryptodome.Hash.SHAKE256` object for Ed448. + + :return: The signature as ``bytes``. It is always 64 bytes for Ed25519, and 114 bytes for Ed448. + :raise TypeError: if the EdDSA key has no private half + """ + + if not self._key.has_private(): + raise TypeError("Private key is needed to sign") + + if self._key.curve == "Ed25519": + ph = isinstance(msg_or_hash, SHA512.SHA512Hash) + if not (ph or is_bytes(msg_or_hash)): + raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash") + eddsa_sign_method = self._sign_ed25519 + + elif self._key.curve == "Ed448": + ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF) + if not (ph or is_bytes(msg_or_hash)): + raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash") + eddsa_sign_method = self._sign_ed448 + + else: + raise ValueError("Incorrect curve for EdDSA") + + return eddsa_sign_method(msg_or_hash, ph) + + def _sign_ed25519(self, msg_or_hash, ph): + if self._context or ph: + flag = int(ph) + # dom2(flag, self._context) + dom2 = b"SigEd25519 no Ed25519 collisions" + bchr(flag) + bchr(len(self._context)) + self._context + else: + dom2 = b"" + + PHM = msg_or_hash.digest() if ph else msg_or_hash + + # See RFC 8032, section 5.1.6 + + # Step 2 + r_hash = SHA512.new(dom2 + self._key._prefix + PHM).digest() + r = Integer.from_bytes(r_hash, "little") % self._order + # Step 3 + R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public() + # Step 4 + k_hash = SHA512.new(dom2 + R_pk + self._A + PHM).digest() + k = Integer.from_bytes(k_hash, "little") % self._order + # Step 5 + s = (r + k * self._key.d) % self._order + + return R_pk + s.to_bytes(32, "little") + + def _sign_ed448(self, msg_or_hash, ph): + flag = int(ph) + # dom4(flag, self._context) + dom4 = b"SigEd448" + bchr(flag) + bchr(len(self._context)) + self._context + + PHM = msg_or_hash.copy().read(64) if ph else msg_or_hash + + # See RFC 8032, section 5.2.6 + + # Step 2 + r_hash = SHAKE256.new(dom4 + self._key._prefix + PHM).read(114) + r = Integer.from_bytes(r_hash, "little") % self._order + # Step 3 + R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public() + # Step 4 + k_hash = SHAKE256.new(dom4 + R_pk + self._A + PHM).read(114) + k = Integer.from_bytes(k_hash, "little") % self._order + # Step 5 + s = (r + k * self._key.d) % self._order + + return R_pk + s.to_bytes(57, "little") + + def verify(self, msg_or_hash, signature): + """Check if an EdDSA signature is authentic. + + Args: + msg_or_hash (bytes or a hash object): + The message to verify (``bytes``, in case of *PureEdDSA*) or + the hash that was carried out over the message (hash object, for *HashEdDSA*). + + The hash object must be :class:`Cryptodome.Hash.SHA512` object for Ed25519, + and :class:`Cryptodome.Hash.SHAKE256` for Ed448. + + signature (``bytes``): + The signature that needs to be validated. + It must be 64 bytes for Ed25519, and 114 bytes for Ed448. + + :raise ValueError: if the signature is not authentic + """ + + if self._key.curve == "Ed25519": + ph = isinstance(msg_or_hash, SHA512.SHA512Hash) + if not (ph or is_bytes(msg_or_hash)): + raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash") + eddsa_verify_method = self._verify_ed25519 + + elif self._key.curve == "Ed448": + ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF) + if not (ph or is_bytes(msg_or_hash)): + raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash") + eddsa_verify_method = self._verify_ed448 + + else: + raise ValueError("Incorrect curve for EdDSA") + + return eddsa_verify_method(msg_or_hash, signature, ph) + + def _verify_ed25519(self, msg_or_hash, signature, ph): + if len(signature) != 64: + raise ValueError("The signature is not authentic (length)") + + if self._context or ph: + flag = int(ph) + dom2 = b"SigEd25519 no Ed25519 collisions" + bchr(flag) + bchr(len(self._context)) + self._context + else: + dom2 = b"" + + PHM = msg_or_hash.digest() if ph else msg_or_hash + + # Section 5.1.7 + + # Step 1 + try: + R = import_public_key(signature[:32]).pointQ + except ValueError: + raise ValueError("The signature is not authentic (R)") + s = Integer.from_bytes(signature[32:], "little") + if s > self._order: + raise ValueError("The signature is not authentic (S)") + # Step 2 + k_hash = SHA512.new(dom2 + signature[:32] + self._A + PHM).digest() + k = Integer.from_bytes(k_hash, "little") % self._order + # Step 3 + point1 = s * 8 * self._key._curve.G + # OPTIMIZE: with double-scalar multiplication, with no SCA + # countermeasures because it is public values + point2 = 8 * R + k * 8 * self._key.pointQ + if point1 != point2: + raise ValueError("The signature is not authentic") + + def _verify_ed448(self, msg_or_hash, signature, ph): + if len(signature) != 114: + raise ValueError("The signature is not authentic (length)") + + flag = int(ph) + # dom4(flag, self._context) + dom4 = b"SigEd448" + bchr(flag) + bchr(len(self._context)) + self._context + + PHM = msg_or_hash.copy().read(64) if ph else msg_or_hash + + # Section 5.2.7 + + # Step 1 + try: + R = import_public_key(signature[:57]).pointQ + except ValueError: + raise ValueError("The signature is not authentic (R)") + s = Integer.from_bytes(signature[57:], "little") + if s > self._order: + raise ValueError("The signature is not authentic (S)") + # Step 2 + k_hash = SHAKE256.new(dom4 + signature[:57] + self._A + PHM).read(114) + k = Integer.from_bytes(k_hash, "little") % self._order + # Step 3 + point1 = s * 8 * self._key._curve.G + # OPTIMIZE: with double-scalar multiplication, with no SCA + # countermeasures because it is public values + point2 = 8 * R + k * 8 * self._key.pointQ + if point1 != point2: + raise ValueError("The signature is not authentic") def new(key, mode, context=None): - """Create a signature object :class:`EdDSASigScheme` that - can perform or verify an EdDSA signature. + """Create a signature object :class:`EdDSASigScheme` that + can perform or verify an EdDSA signature. - Args: - key (:class:`Cryptodome.PublicKey.ECC` object): - The key to use for computing the signature (*private* keys only) - or for verifying one. - The key must be on the curve ``Ed25519`` or ``Ed448``. + Args: + key (:class:`Cryptodome.PublicKey.ECC` object): + The key to use for computing the signature (*private* keys only) + or for verifying one. + The key must be on the curve ``Ed25519`` or ``Ed448``. - mode (string): - This parameter must be ``'rfc8032'``. + mode (string): + This parameter must be ``'rfc8032'``. - context (bytes): - Up to 255 bytes of `context `_, - which is a constant byte string to segregate different protocols or - different applications of the same key. - """ + context (bytes): + Up to 255 bytes of `context `_, + which is a constant byte string to segregate different protocols or + different applications of the same key. + """ - if not isinstance(key, EccKey) or key.curve not in ("Ed25519", "Ed448"): - raise ValueError("EdDSA can only be used with EdDSA keys") + if not isinstance(key, EccKey) or key.curve not in ("Ed25519", "Ed448"): + raise ValueError("EdDSA can only be used with EdDSA keys") - if mode != 'rfc8032': - raise ValueError("Mode must be 'rfc8032'") + if mode != "rfc8032": + raise ValueError("Mode must be 'rfc8032'") - if context is None: - context = b'' - elif len(context) > 255: - raise ValueError("Context for EdDSA must not be longer than 255 bytes") + if context is None: + context = b"" + elif len(context) > 255: + raise ValueError("Context for EdDSA must not be longer than 255 bytes") - return EdDSASigScheme(key, context) + return EdDSASigScheme(key, context) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/eddsa.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/eddsa.pyi index 809a7ad0..ffc5cafc 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/eddsa.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/eddsa.pyi @@ -3,19 +3,18 @@ from typing_extensions import Protocol from Cryptodome.PublicKey.ECC import EccKey class Hash(Protocol): - def digest(self) -> bytes: ... + def digest(self) -> bytes: ... class XOF(Protocol): - def read(self, len: int) -> bytes: ... + def read(self, len: int) -> bytes: ... def import_public_key(encoded: bytes) -> EccKey: ... def import_private_key(encoded: bytes) -> EccKey: ... class EdDSASigScheme(object): + def __init__(self, key: EccKey, context: bytes) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_or_hash: Union[bytes, Hash, XOF]) -> bytes: ... + def verify(self, msg_or_hash: Union[bytes, Hash, XOF], signature: bytes) -> None: ... - def __init__(self, key: EccKey, context: bytes) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_or_hash: Union[bytes, Hash, XOF]) -> bytes: ... - def verify(self, msg_or_hash: Union[bytes, Hash, XOF], signature: bytes) -> None: ... - -def new(key: EccKey, mode: str, context: Optional[bytes]=None) -> EdDSASigScheme: ... +def new(key: EccKey, mode: str, context: Optional[bytes] = None) -> EdDSASigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pkcs1_15.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pkcs1_15.py index bdde78ab..781436b5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pkcs1_15.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pkcs1_15.py @@ -32,192 +32,195 @@ from Cryptodome.Util.number import ceil_div, bytes_to_long, long_to_bytes from Cryptodome.Util.asn1 import DerSequence, DerNull, DerOctetString, DerObjectId + class PKCS115_SigScheme: - """A signature object for ``RSASSA-PKCS1-v1_5``. - Do not instantiate directly. - Use :func:`Cryptodome.Signature.pkcs1_15.new`. - """ - - def __init__(self, rsa_key): - """Initialize this PKCS#1 v1.5 signature scheme object. - - :Parameters: - rsa_key : an RSA key object - Creation of signatures is only possible if this is a *private* - RSA key. Verification of signatures is always possible. - """ - self._key = rsa_key - - def can_sign(self): - """Return ``True`` if this object can be used to sign messages.""" - return self._key.has_private() - - def sign(self, msg_hash): - """Create the PKCS#1 v1.5 signature of a message. - - This function is also called ``RSASSA-PKCS1-V1_5-SIGN`` and - it is specified in - `section 8.2.1 of RFC8017 `_. - - :parameter msg_hash: - This is an object from the :mod:`Cryptodome.Hash` package. - It has been used to digest the message to sign. - :type msg_hash: hash object - - :return: the signature encoded as a *byte string*. - :raise ValueError: if the RSA key is not long enough for the given hash algorithm. - :raise TypeError: if the RSA key has no private half. - """ - - # See 8.2.1 in RFC3447 - modBits = Cryptodome.Util.number.size(self._key.n) - k = ceil_div(modBits,8) # Convert from bits to bytes - - # Step 1 - em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k) - # Step 2a (OS2IP) - em_int = bytes_to_long(em) - # Step 2b (RSASP1) and Step 2c (I2OSP) - signature = self._key._decrypt_to_bytes(em_int) - # Verify no faults occurred - if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): - raise ValueError("Fault detected in RSA private key operation") - return signature - - def verify(self, msg_hash, signature): - """Check if the PKCS#1 v1.5 signature over a message is valid. - - This function is also called ``RSASSA-PKCS1-V1_5-VERIFY`` and - it is specified in - `section 8.2.2 of RFC8037 `_. - - :parameter msg_hash: - The hash that was carried out over the message. This is an object - belonging to the :mod:`Cryptodome.Hash` module. - :type parameter: hash object - - :parameter signature: - The signature that needs to be validated. - :type signature: byte string - - :raise ValueError: if the signature is not valid. - """ - - # See 8.2.2 in RFC3447 - modBits = Cryptodome.Util.number.size(self._key.n) - k = ceil_div(modBits, 8) # Convert from bits to bytes - - # Step 1 - if len(signature) != k: - raise ValueError("Invalid signature") - # Step 2a (O2SIP) - signature_int = bytes_to_long(signature) - # Step 2b (RSAVP1) - em_int = self._key._encrypt(signature_int) - # Step 2c (I2OSP) - em1 = long_to_bytes(em_int, k) - # Step 3 - try: - possible_em1 = [ _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True) ] - # MD2/4/5 hashes always require NULL params in AlgorithmIdentifier. - # For all others, it is optional. - try: - algorithm_is_md = msg_hash.oid.startswith('1.2.840.113549.2.') - except AttributeError: - algorithm_is_md = False - if not algorithm_is_md: # MD2/MD4/MD5 - possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False)) - except ValueError: - raise ValueError("Invalid signature") - # Step 4 - # By comparing the full encodings (as opposed to checking each - # of its components one at a time) we avoid attacks to the padding - # scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptography@metzdowd.com/msg06537). - # - if em1 not in possible_em1: - raise ValueError("Invalid signature") - pass + """A signature object for ``RSASSA-PKCS1-v1_5``. + Do not instantiate directly. + Use :func:`Cryptodome.Signature.pkcs1_15.new`. + """ + + def __init__(self, rsa_key): + """Initialize this PKCS#1 v1.5 signature scheme object. + + :Parameters: + rsa_key : an RSA key object + Creation of signatures is only possible if this is a *private* + RSA key. Verification of signatures is always possible. + """ + self._key = rsa_key + + def can_sign(self): + """Return ``True`` if this object can be used to sign messages.""" + return self._key.has_private() + + def sign(self, msg_hash): + """Create the PKCS#1 v1.5 signature of a message. + + This function is also called ``RSASSA-PKCS1-V1_5-SIGN`` and + it is specified in + `section 8.2.1 of RFC8017 `_. + + :parameter msg_hash: + This is an object from the :mod:`Cryptodome.Hash` package. + It has been used to digest the message to sign. + :type msg_hash: hash object + + :return: the signature encoded as a *byte string*. + :raise ValueError: if the RSA key is not long enough for the given hash algorithm. + :raise TypeError: if the RSA key has no private half. + """ + + # See 8.2.1 in RFC3447 + modBits = Cryptodome.Util.number.size(self._key.n) + k = ceil_div(modBits, 8) # Convert from bits to bytes + + # Step 1 + em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k) + # Step 2a (OS2IP) + em_int = bytes_to_long(em) + # Step 2b (RSASP1) and Step 2c (I2OSP) + signature = self._key._decrypt_to_bytes(em_int) + # Verify no faults occurred + if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): + raise ValueError("Fault detected in RSA private key operation") + return signature + + def verify(self, msg_hash, signature): + """Check if the PKCS#1 v1.5 signature over a message is valid. + + This function is also called ``RSASSA-PKCS1-V1_5-VERIFY`` and + it is specified in + `section 8.2.2 of RFC8037 `_. + + :parameter msg_hash: + The hash that was carried out over the message. This is an object + belonging to the :mod:`Cryptodome.Hash` module. + :type parameter: hash object + + :parameter signature: + The signature that needs to be validated. + :type signature: byte string + + :raise ValueError: if the signature is not valid. + """ + + # See 8.2.2 in RFC3447 + modBits = Cryptodome.Util.number.size(self._key.n) + k = ceil_div(modBits, 8) # Convert from bits to bytes + + # Step 1 + if len(signature) != k: + raise ValueError("Invalid signature") + # Step 2a (O2SIP) + signature_int = bytes_to_long(signature) + # Step 2b (RSAVP1) + em_int = self._key._encrypt(signature_int) + # Step 2c (I2OSP) + em1 = long_to_bytes(em_int, k) + # Step 3 + try: + possible_em1 = [_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True)] + # MD2/4/5 hashes always require NULL params in AlgorithmIdentifier. + # For all others, it is optional. + try: + algorithm_is_md = msg_hash.oid.startswith("1.2.840.113549.2.") + except AttributeError: + algorithm_is_md = False + if not algorithm_is_md: # MD2/MD4/MD5 + possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False)) + except ValueError: + raise ValueError("Invalid signature") + # Step 4 + # By comparing the full encodings (as opposed to checking each + # of its components one at a time) we avoid attacks to the padding + # scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptography@metzdowd.com/msg06537). + # + if em1 not in possible_em1: + raise ValueError("Invalid signature") + pass def _EMSA_PKCS1_V1_5_ENCODE(msg_hash, emLen, with_hash_parameters=True): - """ - Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined - in PKCS#1 v2.1 (RFC3447, 9.2). - - ``_EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input, - and hash it internally. Here, we expect that the message has already - been hashed instead. - - :Parameters: - msg_hash : hash object - The hash object that holds the digest of the message being signed. - emLen : int - The length the final encoding must have, in bytes. - with_hash_parameters : bool - If True (default), include NULL parameters for the hash - algorithm in the ``digestAlgorithm`` SEQUENCE. - - :attention: the early standard (RFC2313) stated that ``DigestInfo`` - had to be BER-encoded. This means that old signatures - might have length tags in indefinite form, which - is not supported in DER. Such encoding cannot be - reproduced by this function. - - :Return: An ``emLen`` byte long string that encodes the hash. - """ - - # First, build the ASN.1 DER object DigestInfo: - # - # DigestInfo ::= SEQUENCE { - # digestAlgorithm AlgorithmIdentifier, - # digest OCTET STRING - # } - # - # where digestAlgorithm identifies the hash function and shall be an - # algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms. - # - # PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= { - # { OID id-md2 PARAMETERS NULL }| - # { OID id-md5 PARAMETERS NULL }| - # { OID id-sha1 PARAMETERS NULL }| - # { OID id-sha256 PARAMETERS NULL }| - # { OID id-sha384 PARAMETERS NULL }| - # { OID id-sha512 PARAMETERS NULL } - # } - # - # Appendix B.1 also says that for SHA-1/-2 algorithms, the parameters - # should be omitted. They may be present, but when they are, they shall - # have NULL value. - - digestAlgo = DerSequence([ DerObjectId(msg_hash.oid).encode() ]) - - if with_hash_parameters: - digestAlgo.append(DerNull().encode()) - - digest = DerOctetString(msg_hash.digest()) - digestInfo = DerSequence([ - digestAlgo.encode(), - digest.encode() - ]).encode() - - # We need at least 11 bytes for the remaining data: 3 fixed bytes and - # at least 8 bytes of padding). - if emLen bytes: ... + def digest(self) -> bytes: ... class PKCS115_SigScheme: - def __init__(self, rsa_key: RsaKey) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> None: ... - -def _EMSA_PKCS1_V1_5_ENCODE(msg_hash: Hash, emLen: int, with_hash_parameters: Optional[bool]=True) -> bytes: ... + def __init__(self, rsa_key: RsaKey) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> None: ... +def _EMSA_PKCS1_V1_5_ENCODE( + msg_hash: Hash, emLen: int, with_hash_parameters: Optional[bool] = True +) -> bytes: ... def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pss.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pss.py index b929e26a..0059c98a 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pss.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pss.py @@ -30,358 +30,360 @@ from Cryptodome.Util.py3compat import bchr, bord, iter_range import Cryptodome.Util.number -from Cryptodome.Util.number import (ceil_div, - long_to_bytes, - bytes_to_long - ) +from Cryptodome.Util.number import ( + ceil_div, + long_to_bytes, + bytes_to_long, +) from Cryptodome.Util.strxor import strxor from Cryptodome import Random class PSS_SigScheme: - """A signature object for ``RSASSA-PSS``. - Do not instantiate directly. - Use :func:`Cryptodome.Signature.pss.new`. - """ - - def __init__(self, key, mgfunc, saltLen, randfunc): - """Initialize this PKCS#1 PSS signature scheme object. - - :Parameters: - key : an RSA key object - If a private half is given, both signature and - verification are possible. - If a public half is given, only verification is possible. - mgfunc : callable - A mask generation function that accepts two parameters: - a string to use as seed, and the lenth of the mask to - generate, in bytes. - saltLen : integer - Length of the salt, in bytes. - randfunc : callable - A function that returns random bytes. - """ - - self._key = key - self._saltLen = saltLen - self._mgfunc = mgfunc - self._randfunc = randfunc - - def can_sign(self): - """Return ``True`` if this object can be used to sign messages.""" - return self._key.has_private() - - def sign(self, msg_hash): - """Create the PKCS#1 PSS signature of a message. - - This function is also called ``RSASSA-PSS-SIGN`` and - it is specified in - `section 8.1.1 of RFC8017 `_. - - :parameter msg_hash: - This is an object from the :mod:`Cryptodome.Hash` package. - It has been used to digest the message to sign. - :type msg_hash: hash object - - :return: the signature encoded as a *byte string*. - :raise ValueError: if the RSA key is not long enough for the given hash algorithm. - :raise TypeError: if the RSA key has no private half. - """ - - # Set defaults for salt length and mask generation function - if self._saltLen is None: - sLen = msg_hash.digest_size - else: - sLen = self._saltLen - - if self._mgfunc is None: - mgf = lambda x, y: MGF1(x, y, msg_hash) - else: - mgf = self._mgfunc - - modBits = Cryptodome.Util.number.size(self._key.n) - - # See 8.1.1 in RFC3447 - k = ceil_div(modBits, 8) # k is length in bytes of the modulus - # Step 1 - em = _EMSA_PSS_ENCODE(msg_hash, modBits-1, self._randfunc, mgf, sLen) - # Step 2a (OS2IP) - em_int = bytes_to_long(em) - # Step 2b (RSASP1) and Step 2c (I2OSP) - signature = self._key._decrypt_to_bytes(em_int) - # Verify no faults occurred - if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): - raise ValueError("Fault detected in RSA private key operation") - return signature - - def verify(self, msg_hash, signature): - """Check if the PKCS#1 PSS signature over a message is valid. - - This function is also called ``RSASSA-PSS-VERIFY`` and - it is specified in - `section 8.1.2 of RFC8037 `_. - - :parameter msg_hash: - The hash that was carried out over the message. This is an object - belonging to the :mod:`Cryptodome.Hash` module. - :type parameter: hash object - - :parameter signature: - The signature that needs to be validated. - :type signature: bytes - - :raise ValueError: if the signature is not valid. - """ - - # Set defaults for salt length and mask generation function - if self._saltLen is None: - sLen = msg_hash.digest_size - else: - sLen = self._saltLen - if self._mgfunc: - mgf = self._mgfunc - else: - mgf = lambda x, y: MGF1(x, y, msg_hash) - - modBits = Cryptodome.Util.number.size(self._key.n) - - # See 8.1.2 in RFC3447 - k = ceil_div(modBits, 8) # Convert from bits to bytes - # Step 1 - if len(signature) != k: - raise ValueError("Incorrect signature") - # Step 2a (O2SIP) - signature_int = bytes_to_long(signature) - # Step 2b (RSAVP1) - em_int = self._key._encrypt(signature_int) - # Step 2c (I2OSP) - emLen = ceil_div(modBits - 1, 8) - em = long_to_bytes(em_int, emLen) - # Step 3/4 - _EMSA_PSS_VERIFY(msg_hash, em, modBits-1, mgf, sLen) + """A signature object for ``RSASSA-PSS``. + Do not instantiate directly. + Use :func:`Cryptodome.Signature.pss.new`. + """ + + def __init__(self, key, mgfunc, saltLen, randfunc): + """Initialize this PKCS#1 PSS signature scheme object. + + :Parameters: + key : an RSA key object + If a private half is given, both signature and + verification are possible. + If a public half is given, only verification is possible. + mgfunc : callable + A mask generation function that accepts two parameters: + a string to use as seed, and the lenth of the mask to + generate, in bytes. + saltLen : integer + Length of the salt, in bytes. + randfunc : callable + A function that returns random bytes. + """ + + self._key = key + self._saltLen = saltLen + self._mgfunc = mgfunc + self._randfunc = randfunc + + def can_sign(self): + """Return ``True`` if this object can be used to sign messages.""" + return self._key.has_private() + + def sign(self, msg_hash): + """Create the PKCS#1 PSS signature of a message. + + This function is also called ``RSASSA-PSS-SIGN`` and + it is specified in + `section 8.1.1 of RFC8017 `_. + + :parameter msg_hash: + This is an object from the :mod:`Cryptodome.Hash` package. + It has been used to digest the message to sign. + :type msg_hash: hash object + + :return: the signature encoded as a *byte string*. + :raise ValueError: if the RSA key is not long enough for the given hash algorithm. + :raise TypeError: if the RSA key has no private half. + """ + + # Set defaults for salt length and mask generation function + if self._saltLen is None: + sLen = msg_hash.digest_size + else: + sLen = self._saltLen + + if self._mgfunc is None: + mgf = lambda x, y: MGF1(x, y, msg_hash) + else: + mgf = self._mgfunc + + modBits = Cryptodome.Util.number.size(self._key.n) + + # See 8.1.1 in RFC3447 + k = ceil_div(modBits, 8) # k is length in bytes of the modulus + # Step 1 + em = _EMSA_PSS_ENCODE(msg_hash, modBits - 1, self._randfunc, mgf, sLen) + # Step 2a (OS2IP) + em_int = bytes_to_long(em) + # Step 2b (RSASP1) and Step 2c (I2OSP) + signature = self._key._decrypt_to_bytes(em_int) + # Verify no faults occurred + if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): + raise ValueError("Fault detected in RSA private key operation") + return signature + + def verify(self, msg_hash, signature): + """Check if the PKCS#1 PSS signature over a message is valid. + + This function is also called ``RSASSA-PSS-VERIFY`` and + it is specified in + `section 8.1.2 of RFC8037 `_. + + :parameter msg_hash: + The hash that was carried out over the message. This is an object + belonging to the :mod:`Cryptodome.Hash` module. + :type parameter: hash object + + :parameter signature: + The signature that needs to be validated. + :type signature: bytes + + :raise ValueError: if the signature is not valid. + """ + + # Set defaults for salt length and mask generation function + if self._saltLen is None: + sLen = msg_hash.digest_size + else: + sLen = self._saltLen + if self._mgfunc: + mgf = self._mgfunc + else: + mgf = lambda x, y: MGF1(x, y, msg_hash) + + modBits = Cryptodome.Util.number.size(self._key.n) + + # See 8.1.2 in RFC3447 + k = ceil_div(modBits, 8) # Convert from bits to bytes + # Step 1 + if len(signature) != k: + raise ValueError("Incorrect signature") + # Step 2a (O2SIP) + signature_int = bytes_to_long(signature) + # Step 2b (RSAVP1) + em_int = self._key._encrypt(signature_int) + # Step 2c (I2OSP) + emLen = ceil_div(modBits - 1, 8) + em = long_to_bytes(em_int, emLen) + # Step 3/4 + _EMSA_PSS_VERIFY(msg_hash, em, modBits - 1, mgf, sLen) def MGF1(mgfSeed, maskLen, hash_gen): - """Mask Generation Function, described in `B.2.1 of RFC8017 - `_. + """Mask Generation Function, described in `B.2.1 of RFC8017 + `_. - :param mfgSeed: - seed from which the mask is generated - :type mfgSeed: byte string + :param mfgSeed: + seed from which the mask is generated + :type mfgSeed: byte string - :param maskLen: - intended length in bytes of the mask - :type maskLen: integer + :param maskLen: + intended length in bytes of the mask + :type maskLen: integer - :param hash_gen: - A module or a hash object from :mod:`Cryptodome.Hash` - :type hash_object: + :param hash_gen: + A module or a hash object from :mod:`Cryptodome.Hash` + :type hash_object: - :return: the mask, as a *byte string* - """ + :return: the mask, as a *byte string* + """ - T = b"" - for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)): - c = long_to_bytes(counter, 4) - hobj = hash_gen.new() - hobj.update(mgfSeed + c) - T = T + hobj.digest() - assert(len(T) >= maskLen) - return T[:maskLen] + T = b"" + for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)): + c = long_to_bytes(counter, 4) + hobj = hash_gen.new() + hobj.update(mgfSeed + c) + T = T + hobj.digest() + assert len(T) >= maskLen + return T[:maskLen] def _EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen): - r""" - Implement the ``EMSA-PSS-ENCODE`` function, as defined - in PKCS#1 v2.1 (RFC3447, 9.1.1). - - The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` - as input, and hash it internally. Here, we expect that the message - has already been hashed instead. - - :Parameters: - mhash : hash object - The hash object that holds the digest of the message being signed. - emBits : int - Maximum length of the final encoding, in bits. - randFunc : callable - An RNG function that accepts as only parameter an int, and returns - a string of random bytes, to be used as salt. - mgf : callable - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - sLen : int - Length of the salt, in bytes. - - :Return: An ``emLen`` byte long string that encodes the hash - (with ``emLen = \ceil(emBits/8)``). - - :Raise ValueError: - When digest or salt length are too big. - """ - - emLen = ceil_div(emBits, 8) - - # Bitmask of digits that fill up - lmask = 0 - for i in iter_range(8*emLen-emBits): - lmask = lmask >> 1 | 0x80 - - # Step 1 and 2 have been already done - # Step 3 - if emLen < mhash.digest_size+sLen+2: - raise ValueError("Digest or salt length are too long" - " for given key size.") - # Step 4 - salt = randFunc(sLen) - # Step 5 - m_prime = bchr(0)*8 + mhash.digest() + salt - # Step 6 - h = mhash.new() - h.update(m_prime) - # Step 7 - ps = bchr(0)*(emLen-sLen-mhash.digest_size-2) - # Step 8 - db = ps + bchr(1) + salt - # Step 9 - dbMask = mgf(h.digest(), emLen-mhash.digest_size-1) - # Step 10 - maskedDB = strxor(db, dbMask) - # Step 11 - maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:] - # Step 12 - em = maskedDB + h.digest() + bchr(0xBC) - return em + r""" + Implement the ``EMSA-PSS-ENCODE`` function, as defined + in PKCS#1 v2.1 (RFC3447, 9.1.1). + + The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` + as input, and hash it internally. Here, we expect that the message + has already been hashed instead. + + :Parameters: + mhash : hash object + The hash object that holds the digest of the message being signed. + emBits : int + Maximum length of the final encoding, in bits. + randFunc : callable + An RNG function that accepts as only parameter an int, and returns + a string of random bytes, to be used as salt. + mgf : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + sLen : int + Length of the salt, in bytes. + + :Return: An ``emLen`` byte long string that encodes the hash + (with ``emLen = \ceil(emBits/8)``). + + :Raise ValueError: + When digest or salt length are too big. + """ + + emLen = ceil_div(emBits, 8) + + # Bitmask of digits that fill up + lmask = 0 + for i in iter_range(8 * emLen - emBits): + lmask = lmask >> 1 | 0x80 + + # Step 1 and 2 have been already done + # Step 3 + if emLen < mhash.digest_size + sLen + 2: + raise ValueError( + "Digest or salt length are too long for given key size.", + ) + # Step 4 + salt = randFunc(sLen) + # Step 5 + m_prime = bchr(0) * 8 + mhash.digest() + salt + # Step 6 + h = mhash.new() + h.update(m_prime) + # Step 7 + ps = bchr(0) * (emLen - sLen - mhash.digest_size - 2) + # Step 8 + db = ps + bchr(1) + salt + # Step 9 + dbMask = mgf(h.digest(), emLen - mhash.digest_size - 1) + # Step 10 + maskedDB = strxor(db, dbMask) + # Step 11 + maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:] + # Step 12 + em = maskedDB + h.digest() + bchr(0xBC) + return em def _EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen): - """ - Implement the ``EMSA-PSS-VERIFY`` function, as defined - in PKCS#1 v2.1 (RFC3447, 9.1.2). - - ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input, - and hash it internally. Here, we expect that the message has already - been hashed instead. - - :Parameters: - mhash : hash object - The hash object that holds the digest of the message to be verified. - em : string - The signature to verify, therefore proving that the sender really - signed the message that was received. - emBits : int - Length of the final encoding (em), in bits. - mgf : callable - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - sLen : int - Length of the salt, in bytes. - - :Raise ValueError: - When the encoding is inconsistent, or the digest or salt lengths - are too big. - """ - - emLen = ceil_div(emBits, 8) - - # Bitmask of digits that fill up - lmask = 0 - for i in iter_range(8*emLen-emBits): - lmask = lmask >> 1 | 0x80 - - # Step 1 and 2 have been already done - # Step 3 - if emLen < mhash.digest_size+sLen+2: - raise ValueError("Incorrect signature") - # Step 4 - if ord(em[-1:]) != 0xBC: - raise ValueError("Incorrect signature") - # Step 5 - maskedDB = em[:emLen-mhash.digest_size-1] - h = em[emLen-mhash.digest_size-1:-1] - # Step 6 - if lmask & bord(em[0]): - raise ValueError("Incorrect signature") - # Step 7 - dbMask = mgf(h, emLen-mhash.digest_size-1) - # Step 8 - db = strxor(maskedDB, dbMask) - # Step 9 - db = bchr(bord(db[0]) & ~lmask) + db[1:] - # Step 10 - if not db.startswith(bchr(0)*(emLen-mhash.digest_size-sLen-2) + bchr(1)): - raise ValueError("Incorrect signature") - # Step 11 - if sLen > 0: - salt = db[-sLen:] - else: - salt = b"" - # Step 12 - m_prime = bchr(0)*8 + mhash.digest() + salt - # Step 13 - hobj = mhash.new() - hobj.update(m_prime) - hp = hobj.digest() - # Step 14 - if h != hp: - raise ValueError("Incorrect signature") + """ + Implement the ``EMSA-PSS-VERIFY`` function, as defined + in PKCS#1 v2.1 (RFC3447, 9.1.2). + + ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input, + and hash it internally. Here, we expect that the message has already + been hashed instead. + + :Parameters: + mhash : hash object + The hash object that holds the digest of the message to be verified. + em : string + The signature to verify, therefore proving that the sender really + signed the message that was received. + emBits : int + Length of the final encoding (em), in bits. + mgf : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + sLen : int + Length of the salt, in bytes. + + :Raise ValueError: + When the encoding is inconsistent, or the digest or salt lengths + are too big. + """ + + emLen = ceil_div(emBits, 8) + + # Bitmask of digits that fill up + lmask = 0 + for i in iter_range(8 * emLen - emBits): + lmask = lmask >> 1 | 0x80 + + # Step 1 and 2 have been already done + # Step 3 + if emLen < mhash.digest_size + sLen + 2: + raise ValueError("Incorrect signature") + # Step 4 + if ord(em[-1:]) != 0xBC: + raise ValueError("Incorrect signature") + # Step 5 + maskedDB = em[: emLen - mhash.digest_size - 1] + h = em[emLen - mhash.digest_size - 1 : -1] + # Step 6 + if lmask & bord(em[0]): + raise ValueError("Incorrect signature") + # Step 7 + dbMask = mgf(h, emLen - mhash.digest_size - 1) + # Step 8 + db = strxor(maskedDB, dbMask) + # Step 9 + db = bchr(bord(db[0]) & ~lmask) + db[1:] + # Step 10 + if not db.startswith(bchr(0) * (emLen - mhash.digest_size - sLen - 2) + bchr(1)): + raise ValueError("Incorrect signature") + # Step 11 + if sLen > 0: + salt = db[-sLen:] + else: + salt = b"" + # Step 12 + m_prime = bchr(0) * 8 + mhash.digest() + salt + # Step 13 + hobj = mhash.new() + hobj.update(m_prime) + hp = hobj.digest() + # Step 14 + if h != hp: + raise ValueError("Incorrect signature") def new(rsa_key, **kwargs): - """Create an object for making or verifying PKCS#1 PSS signatures. - - :parameter rsa_key: - The RSA key to use for signing or verifying the message. - This is a :class:`Cryptodome.PublicKey.RSA` object. - Signing is only possible when ``rsa_key`` is a **private** RSA key. - :type rsa_key: RSA object - - :Keyword Arguments: - - * *mask_func* (``callable``) -- - A function that returns the mask (as `bytes`). - It must accept two parameters: a seed (as `bytes`) - and the length of the data to return. - - If not specified, it will be the function :func:`MGF1` defined in - `RFC8017 `_ and - combined with the same hash algorithm applied to the - message to sign or verify. - - If you want to use a different function, for instance still :func:`MGF1` - but together with another hash, you can do:: - - from Cryptodome.Hash import SHA256 - from Cryptodome.Signature.pss import MGF1 - mgf = lambda x, y: MGF1(x, y, SHA256) - - * *salt_bytes* (``integer``) -- - Length of the salt, in bytes. - It is a value between 0 and ``emLen - hLen - 2``, where ``emLen`` - is the size of the RSA modulus and ``hLen`` is the size of the digest - applied to the message to sign or verify. - - The salt is generated internally, you don't need to provide it. - - If not specified, the salt length will be ``hLen``. - If it is zero, the signature scheme becomes deterministic. - - Note that in some implementations such as OpenSSL the default - salt length is ``emLen - hLen - 2`` (even though it is not more - secure than ``hLen``). - - * *rand_func* (``callable``) -- - A function that returns random ``bytes``, of the desired length. - The default is :func:`Cryptodome.Random.get_random_bytes`. - - :return: a :class:`PSS_SigScheme` signature object - """ - - mask_func = kwargs.pop("mask_func", None) - salt_len = kwargs.pop("salt_bytes", None) - rand_func = kwargs.pop("rand_func", None) - if rand_func is None: - rand_func = Random.get_random_bytes - if kwargs: - raise ValueError("Unknown keywords: " + str(kwargs.keys())) - return PSS_SigScheme(rsa_key, mask_func, salt_len, rand_func) + """Create an object for making or verifying PKCS#1 PSS signatures. + + :parameter rsa_key: + The RSA key to use for signing or verifying the message. + This is a :class:`Cryptodome.PublicKey.RSA` object. + Signing is only possible when ``rsa_key`` is a **private** RSA key. + :type rsa_key: RSA object + + :Keyword Arguments: + + * *mask_func* (``callable``) -- + A function that returns the mask (as `bytes`). + It must accept two parameters: a seed (as `bytes`) + and the length of the data to return. + + If not specified, it will be the function :func:`MGF1` defined in + `RFC8017 `_ and + combined with the same hash algorithm applied to the + message to sign or verify. + + If you want to use a different function, for instance still :func:`MGF1` + but together with another hash, you can do:: + + from Cryptodome.Hash import SHA256 + from Cryptodome.Signature.pss import MGF1 + mgf = lambda x, y: MGF1(x, y, SHA256) + + * *salt_bytes* (``integer``) -- + Length of the salt, in bytes. + It is a value between 0 and ``emLen - hLen - 2``, where ``emLen`` + is the size of the RSA modulus and ``hLen`` is the size of the digest + applied to the message to sign or verify. + + The salt is generated internally, you don't need to provide it. + + If not specified, the salt length will be ``hLen``. + If it is zero, the signature scheme becomes deterministic. + + Note that in some implementations such as OpenSSL the default + salt length is ``emLen - hLen - 2`` (even though it is not more + secure than ``hLen``). + + * *rand_func* (``callable``) -- + A function that returns random ``bytes``, of the desired length. + The default is :func:`Cryptodome.Random.get_random_bytes`. + + :return: a :class:`PSS_SigScheme` signature object + """ + + mask_func = kwargs.pop("mask_func", None) + salt_len = kwargs.pop("salt_bytes", None) + rand_func = kwargs.pop("rand_func", None) + if rand_func is None: + rand_func = Random.get_random_bytes + if kwargs: + raise ValueError("Unknown keywords: " + str(kwargs.keys())) + return PSS_SigScheme(rsa_key, mask_func, salt_len, rand_func) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pss.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pss.pyi index 84a960e2..09a94500 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pss.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Signature/pss.pyi @@ -3,28 +3,27 @@ from typing_extensions import Protocol from Cryptodome.PublicKey.RSA import RsaKey - class Hash(Protocol): - def digest(self) -> bytes: ... - def update(self, bytes) -> None: ... - + def digest(self) -> bytes: ... + def update(self, bytes) -> None: ... class HashModule(Protocol): - @staticmethod - def new(data: Optional[bytes]) -> Hash: ... - + @staticmethod + def new(data: Optional[bytes]) -> Hash: ... MaskFunction = Callable[[bytes, int, Union[Hash, HashModule]], bytes] RndFunction = Callable[[int], bytes] class PSS_SigScheme: - def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> None: ... + def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> None: ... +MGF1: MaskFunction -MGF1 : MaskFunction -def _EMSA_PSS_ENCODE(mhash: Hash, emBits: int, randFunc: RndFunction, mgf:MaskFunction, sLen: int) -> str: ... +def _EMSA_PSS_ENCODE( + mhash: Hash, emBits: int, randFunc: RndFunction, mgf: MaskFunction, sLen: int +) -> str: ... def _EMSA_PSS_VERIFY(mhash: Hash, em: str, emBits: int, mgf: MaskFunction, sLen: int) -> None: ... def new(rsa_key: RsaKey, **kwargs: Union[MaskFunction, RndFunction, int]) -> PSS_SigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Counter.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Counter.py index e3bdcbec..0f301db8 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Counter.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Counter.py @@ -22,58 +22,60 @@ # SOFTWARE. # =================================================================== + def new(nbits, prefix=b"", suffix=b"", initial_value=1, little_endian=False, allow_wraparound=False): - """Create a stateful counter block function suitable for CTR encryption modes. + """Create a stateful counter block function suitable for CTR encryption modes. - Each call to the function returns the next counter block. - Each counter block is made up by three parts: + Each call to the function returns the next counter block. + Each counter block is made up by three parts: - +------+--------------+-------+ - |prefix| counter value|postfix| - +------+--------------+-------+ + +------+--------------+-------+ + |prefix| counter value|postfix| + +------+--------------+-------+ - The counter value is incremented by 1 at each call. + The counter value is incremented by 1 at each call. - Args: - nbits (integer): - Length of the desired counter value, in bits. It must be a multiple of 8. - prefix (byte string): - The constant prefix of the counter block. By default, no prefix is - used. - suffix (byte string): - The constant postfix of the counter block. By default, no suffix is - used. - initial_value (integer): - The initial value of the counter. Default value is 1. - Its length in bits must not exceed the argument ``nbits``. - little_endian (boolean): - If ``True``, the counter number will be encoded in little endian format. - If ``False`` (default), in big endian format. - allow_wraparound (boolean): - This parameter is ignored. - An ``OverflowError`` exception is always raised when the counter wraps - around to zero. - Returns: - An object that can be passed with the :data:`counter` parameter to a CTR mode - cipher. + Args: + nbits (integer): + Length of the desired counter value, in bits. It must be a multiple of 8. + prefix (byte string): + The constant prefix of the counter block. By default, no prefix is + used. + suffix (byte string): + The constant postfix of the counter block. By default, no suffix is + used. + initial_value (integer): + The initial value of the counter. Default value is 1. + Its length in bits must not exceed the argument ``nbits``. + little_endian (boolean): + If ``True``, the counter number will be encoded in little endian format. + If ``False`` (default), in big endian format. + allow_wraparound (boolean): + This parameter is ignored. + An ``OverflowError`` exception is always raised when the counter wraps + around to zero. + Returns: + An object that can be passed with the :data:`counter` parameter to a CTR mode + cipher. - It must hold that *len(prefix) + nbits//8 + len(suffix)* matches the - block size of the underlying block cipher. - """ + It must hold that *len(prefix) + nbits//8 + len(suffix)* matches the + block size of the underlying block cipher. + """ - if (nbits % 8) != 0: - raise ValueError("'nbits' must be a multiple of 8") + if (nbits % 8) != 0: + raise ValueError("'nbits' must be a multiple of 8") - iv_bl = initial_value.bit_length() - if iv_bl > nbits: - raise ValueError("Initial value takes %d bits but it is longer than " - "the counter (%d bits)" % - (iv_bl, nbits)) + iv_bl = initial_value.bit_length() + if iv_bl > nbits: + raise ValueError( + "Initial value takes %d bits but it is longer than the counter (%d bits)" % (iv_bl, nbits), + ) - # Ignore wraparound - return {"counter_len": nbits // 8, - "prefix": prefix, - "suffix": suffix, - "initial_value": initial_value, - "little_endian": little_endian - } + # Ignore wraparound + return { + "counter_len": nbits // 8, + "prefix": prefix, + "suffix": suffix, + "initial_value": initial_value, + "little_endian": little_endian, + } diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Counter.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Counter.pyi index fa2ffdd8..2372a87f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Counter.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Counter.pyi @@ -1,5 +1,10 @@ from typing import Optional, Union, Dict -def new(nbits: int, prefix: Optional[bytes]=..., suffix: Optional[bytes]=..., initial_value: Optional[int]=1, - little_endian: Optional[bool]=False, allow_wraparound: Optional[bool]=False) -> \ - Dict[str, Union[int, bytes, bool]]: ... +def new( + nbits: int, + prefix: Optional[bytes] = ..., + suffix: Optional[bytes] = ..., + initial_value: Optional[int] = 1, + little_endian: Optional[bool] = False, + allow_wraparound: Optional[bool] = False, +) -> Dict[str, Union[int, bytes, bool]]: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Padding.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Padding.py index 10165680..a337c819 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Padding.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Padding.py @@ -31,89 +31,88 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = [ 'pad', 'unpad' ] +__all__ = ["pad", "unpad"] from Cryptodome.Util.py3compat import * -def pad(data_to_pad, block_size, style='pkcs7'): - """Apply standard padding. +def pad(data_to_pad, block_size, style="pkcs7"): + """Apply standard padding. - Args: - data_to_pad (byte string): - The data that needs to be padded. - block_size (integer): - The block boundary to use for padding. The output length is guaranteed - to be a multiple of :data:`block_size`. - style (string): - Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. + Args: + data_to_pad (byte string): + The data that needs to be padded. + block_size (integer): + The block boundary to use for padding. The output length is guaranteed + to be a multiple of :data:`block_size`. + style (string): + Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. - Return: - byte string : the original data with the appropriate padding added at the end. - """ + Return: + byte string : the original data with the appropriate padding added at the end. + """ - padding_len = block_size - len(data_to_pad) % block_size + padding_len = block_size - len(data_to_pad) % block_size - if style == 'pkcs7': - padding = bchr(padding_len) * padding_len - elif style == 'x923': - padding = bchr(0)*(padding_len-1) + bchr(padding_len) - elif style == 'iso7816': - padding = bchr(128) + bchr(0) * (padding_len-1) - else: - raise ValueError("Unknown padding style") + if style == "pkcs7": + padding = bchr(padding_len) * padding_len + elif style == "x923": + padding = bchr(0) * (padding_len - 1) + bchr(padding_len) + elif style == "iso7816": + padding = bchr(128) + bchr(0) * (padding_len - 1) + else: + raise ValueError("Unknown padding style") - return data_to_pad + padding + return data_to_pad + padding -def unpad(padded_data, block_size, style='pkcs7'): - """Remove standard padding. +def unpad(padded_data, block_size, style="pkcs7"): + """Remove standard padding. - Args: - padded_data (byte string): - A piece of data with padding that needs to be stripped. - block_size (integer): - The block boundary to use for padding. The input length - must be a multiple of :data:`block_size`. - style (string): - Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. - Return: - byte string : data without padding. - Raises: - ValueError: if the padding is incorrect. - """ + Args: + padded_data (byte string): + A piece of data with padding that needs to be stripped. + block_size (integer): + The block boundary to use for padding. The input length + must be a multiple of :data:`block_size`. + style (string): + Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. + Return: + byte string : data without padding. + Raises: + ValueError: if the padding is incorrect. + """ - pdata_len = len(padded_data) + pdata_len = len(padded_data) - if pdata_len == 0: - raise ValueError("Zero-length input cannot be unpadded") + if pdata_len == 0: + raise ValueError("Zero-length input cannot be unpadded") - if pdata_len % block_size: - raise ValueError("Input data is not padded") + if pdata_len % block_size: + raise ValueError("Input data is not padded") - if style in ('pkcs7', 'x923'): - padding_len = bord(padded_data[-1]) + if style in ("pkcs7", "x923"): + padding_len = bord(padded_data[-1]) - if padding_len < 1 or padding_len > min(block_size, pdata_len): - raise ValueError("Padding is incorrect.") + if padding_len < 1 or padding_len > min(block_size, pdata_len): + raise ValueError("Padding is incorrect.") - if style == 'pkcs7': - if padded_data[-padding_len:] != bchr(padding_len)*padding_len: - raise ValueError("PKCS#7 padding is incorrect.") - else: - if padded_data[-padding_len:-1] != bchr(0)*(padding_len-1): - raise ValueError("ANSI X.923 padding is incorrect.") + if style == "pkcs7": + if padded_data[-padding_len:] != bchr(padding_len) * padding_len: + raise ValueError("PKCS#7 padding is incorrect.") + else: + if padded_data[-padding_len:-1] != bchr(0) * (padding_len - 1): + raise ValueError("ANSI X.923 padding is incorrect.") - elif style == 'iso7816': - padding_len = pdata_len - padded_data.rfind(bchr(128)) + elif style == "iso7816": + padding_len = pdata_len - padded_data.rfind(bchr(128)) - if padding_len < 1 or padding_len > min(block_size, pdata_len): - raise ValueError("Padding is incorrect.") + if padding_len < 1 or padding_len > min(block_size, pdata_len): + raise ValueError("Padding is incorrect.") - if padding_len > 1 and padded_data[1-padding_len:] != bchr(0)*(padding_len-1): - raise ValueError("ISO 7816-4 padding is incorrect.") - else: - raise ValueError("Unknown padding style") - - return padded_data[:-padding_len] + if padding_len > 1 and padded_data[1 - padding_len :] != bchr(0) * (padding_len - 1): + raise ValueError("ISO 7816-4 padding is incorrect.") + else: + raise ValueError("Unknown padding style") + return padded_data[:-padding_len] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Padding.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Padding.pyi index 4d8d30df..d381eac5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Padding.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/Padding.pyi @@ -1,6 +1,6 @@ from typing import Optional -__all__ = [ 'pad', 'unpad' ] +__all__ = ["pad", "unpad"] -def pad(data_to_pad: bytes, block_size: int, style: Optional[str]='pkcs7') -> bytes: ... -def unpad(padded_data: bytes, block_size: int, style: Optional[str]='pkcs7') -> bytes: ... \ No newline at end of file +def pad(data_to_pad: bytes, block_size: int, style: Optional[str] = "pkcs7") -> bytes: ... +def unpad(padded_data: bytes, block_size: int, style: Optional[str] = "pkcs7") -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/RFC1751.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/RFC1751.py index 10859c3f..a8211936 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/RFC1751.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/RFC1751.py @@ -26,361 +26,2181 @@ from __future__ import print_function -import binascii from Cryptodome.Util.py3compat import bord, bchr -binary = {0: '0000', 1: '0001', 2: '0010', 3: '0011', 4: '0100', 5: '0101', - 6: '0110', 7: '0111', 8: '1000', 9: '1001', 10: '1010', 11: '1011', - 12: '1100', 13: '1101', 14: '1110', 15: '1111'} +binary = { + 0: "0000", + 1: "0001", + 2: "0010", + 3: "0011", + 4: "0100", + 5: "0101", + 6: "0110", + 7: "0111", + 8: "1000", + 9: "1001", + 10: "1010", + 11: "1011", + 12: "1100", + 13: "1101", + 14: "1110", + 15: "1111", +} def _key2bin(s): - "Convert a key into a string of binary digits" - kl = map(lambda x: bord(x), s) - kl = map(lambda x: binary[x >> 4] + binary[x & 15], kl) - return ''.join(kl) + "Convert a key into a string of binary digits" + kl = map(lambda x: bord(x), s) + kl = map(lambda x: binary[x >> 4] + binary[x & 15], kl) + return "".join(kl) def _extract(key, start, length): - """Extract a bitstring(2.x)/bytestring(2.x) from a string of binary digits, and return its - numeric value.""" + """Extract a bitstring(2.x)/bytestring(2.x) from a string of binary digits, and return its + numeric value.""" - result = 0 - for y in key[start:start+length]: - result = result * 2 + ord(y) - 48 - return result + result = 0 + for y in key[start : start + length]: + result = result * 2 + ord(y) - 48 + return result def key_to_english(key): - """Transform an arbitrary key into a string containing English words. + """Transform an arbitrary key into a string containing English words. - Example:: + Example:: - >>> from Cryptodome.Util.RFC1751 import key_to_english - >>> key_to_english(b'66666666') - 'RAM LOIS GOAD CREW CARE HIT' + >>> from Cryptodome.Util.RFC1751 import key_to_english + >>> key_to_english(b'66666666') + 'RAM LOIS GOAD CREW CARE HIT' - Args: - key (byte string): - The key to convert. Its length must be a multiple of 8. - Return: - A string of English words. - """ + Args: + key (byte string): + The key to convert. Its length must be a multiple of 8. + Return: + A string of English words. + """ - if len(key) % 8 != 0: - raise ValueError('The length of the key must be a multiple of 8.') + if len(key) % 8 != 0: + raise ValueError("The length of the key must be a multiple of 8.") - english = '' - for index in range(0, len(key), 8): # Loop over 8-byte subkeys - subkey = key[index:index + 8] - # Compute the parity of the key - skbin = _key2bin(subkey) - p = 0 - for i in range(0, 64, 2): - p = p + _extract(skbin, i, 2) - # Append parity bits to the subkey - skbin = _key2bin(subkey + bchr((p << 6) & 255)) - for i in range(0, 64, 11): - english = english + wordlist[_extract(skbin, i, 11)] + ' ' + english = "" + for index in range(0, len(key), 8): # Loop over 8-byte subkeys + subkey = key[index : index + 8] + # Compute the parity of the key + skbin = _key2bin(subkey) + p = 0 + for i in range(0, 64, 2): + p = p + _extract(skbin, i, 2) + # Append parity bits to the subkey + skbin = _key2bin(subkey + bchr((p << 6) & 255)) + for i in range(0, 64, 11): + english = english + wordlist[_extract(skbin, i, 11)] + " " - return english.strip() + return english.strip() def english_to_key(s): - """Transform a string into a corresponding key. + """Transform a string into a corresponding key. - Example:: + Example:: - >>> from Cryptodome.Util.RFC1751 import english_to_key - >>> english_to_key('RAM LOIS GOAD CREW CARE HIT') - b'66666666' + >>> from Cryptodome.Util.RFC1751 import english_to_key + >>> english_to_key('RAM LOIS GOAD CREW CARE HIT') + b'66666666' - Args: - s (string): the string with the words separated by whitespace; - the number of words must be a multiple of 6. - Return: - A byte string. - """ + Args: + s (string): the string with the words separated by whitespace; + the number of words must be a multiple of 6. + Return: + A byte string. + """ - L = s.upper().split() - key = b'' - for index in range(0, len(L), 6): - sublist = L[index:index + 6] - char = 9 * [0] - bits = 0 - for i in sublist: - index = wordlist.index(i) - shift = (8 - (bits + 11) % 8) % 8 - y = index << shift - cl, cc, cr = (y >> 16), (y >> 8) & 0xff, y & 0xff - if (shift > 5): - char[bits >> 3] = char[bits >> 3] | cl - char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cc - char[(bits >> 3) + 2] = char[(bits >> 3) + 2] | cr - elif shift > -3: - char[bits >> 3] = char[bits >> 3] | cc - char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cr - else: - char[bits >> 3] = char[bits >> 3] | cr - bits = bits + 11 + L = s.upper().split() + key = b"" + for index in range(0, len(L), 6): + sublist = L[index : index + 6] + char = 9 * [0] + bits = 0 + for i in sublist: + index = wordlist.index(i) + shift = (8 - (bits + 11) % 8) % 8 + y = index << shift + cl, cc, cr = (y >> 16), (y >> 8) & 0xFF, y & 0xFF + if shift > 5: + char[bits >> 3] = char[bits >> 3] | cl + char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cc + char[(bits >> 3) + 2] = char[(bits >> 3) + 2] | cr + elif shift > -3: + char[bits >> 3] = char[bits >> 3] | cc + char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cr + else: + char[bits >> 3] = char[bits >> 3] | cr + bits = bits + 11 - subkey = b'' - for y in char: - subkey = subkey + bchr(y) + subkey = b"" + for y in char: + subkey = subkey + bchr(y) - # Check the parity of the resulting key - skbin = _key2bin(subkey) - p = 0 - for i in range(0, 64, 2): - p = p + _extract(skbin, i, 2) - if (p & 3) != _extract(skbin, 64, 2): - raise ValueError("Parity error in resulting key") - key = key + subkey[0:8] - return key + # Check the parity of the resulting key + skbin = _key2bin(subkey) + p = 0 + for i in range(0, 64, 2): + p = p + _extract(skbin, i, 2) + if (p & 3) != _extract(skbin, 64, 2): + raise ValueError("Parity error in resulting key") + key = key + subkey[0:8] + return key wordlist = [ - "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", - "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA", - "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK", - "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE", - "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM", - "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", - "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO", - "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT", - "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", - "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY", - "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN", - "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG", - "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB", - "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO", - "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE", - "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW", - "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", - "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP", - "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO", - "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD", - "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", - "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT", - "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE", - "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL", - "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", - "ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", - "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", - "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", - "LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", - "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", - "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", - "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", - "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", - "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", - "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", - "NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", - "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", - "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", - "OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", - "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", - "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", - "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", - "PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", - "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", - "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", - "RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", - "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", - "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", - "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", - "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", - "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", - "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", - "TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", - "TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", - "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", - "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", - "WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", - "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", - "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", - "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", - "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA", - "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN", - "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW", - "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA", - "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM", - "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW", - "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", - "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", - "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK", - "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", - "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT", - "BEAU", "BECK", "BEEF", "BEEN", "BEER", - "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", - "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", - "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE", - "BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", - "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", - "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT", - "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK", - "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS", - "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN", - "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", - "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", - "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", - "BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", - "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL", - "CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL", - "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF", - "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG", - "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY", - "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", - "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", - "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK", - "COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST", - "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB", - "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY", - "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE", - "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN", - "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS", - "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", - "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", - "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT", - "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", - "DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA", - "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG", - "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK", - "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK", - "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", - "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", - "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", - "EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", - "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", - "FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT", - "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST", - "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE", - "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE", - "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", - "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", - "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", - "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", - "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", - "FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY", - "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA", - "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH", - "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE", - "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", - "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", - "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", - "GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", - "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", - "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN", - "GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH", - "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR", - "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK", - "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE", - "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", - "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", - "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", - "HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT", - "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", - "HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK", - "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL", - "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK", - "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE", - "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", - "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", - "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", - "JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL", - "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", - "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY", - "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST", - "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL", - "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL", - "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", - "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", - "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", - "LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", - "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS", - "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER", - "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST", - "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU", - "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB", - "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", - "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", - "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", - "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", - "LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE", - "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE", - "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI", - "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK", - "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE", - "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", - "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", - "MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", - "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", - "MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD", - "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON", - "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH", - "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK", - "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", - "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", - "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", - "NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", - "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", - "NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB", - "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY", - "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE", - "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS", - "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", - "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", - "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", - "RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", - "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA", - "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT", - "RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD", - "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME", - "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS", - "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", - "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", - "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", - "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE", - "SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", - "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK", - "SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS", - "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN", - "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE", - "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE", - "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", - "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", - "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", - "SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", - "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA", - "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE", - "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR", - "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH", - "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF", - "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", - "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", - "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", - "TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS", - "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN", - "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER", - "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY", - "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG", - "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR", - "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", - "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", - "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", - "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", - "USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST", - "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", - "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE", - "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK", - "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM", - "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", - "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", - "WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", - "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", - "WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE", - "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD", - "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", - "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR", - "YELL", "YOGA", "YOKE" ] + "A", + "ABE", + "ACE", + "ACT", + "AD", + "ADA", + "ADD", + "AGO", + "AID", + "AIM", + "AIR", + "ALL", + "ALP", + "AM", + "AMY", + "AN", + "ANA", + "AND", + "ANN", + "ANT", + "ANY", + "APE", + "APS", + "APT", + "ARC", + "ARE", + "ARK", + "ARM", + "ART", + "AS", + "ASH", + "ASK", + "AT", + "ATE", + "AUG", + "AUK", + "AVE", + "AWE", + "AWK", + "AWL", + "AWN", + "AX", + "AYE", + "BAD", + "BAG", + "BAH", + "BAM", + "BAN", + "BAR", + "BAT", + "BAY", + "BE", + "BED", + "BEE", + "BEG", + "BEN", + "BET", + "BEY", + "BIB", + "BID", + "BIG", + "BIN", + "BIT", + "BOB", + "BOG", + "BON", + "BOO", + "BOP", + "BOW", + "BOY", + "BUB", + "BUD", + "BUG", + "BUM", + "BUN", + "BUS", + "BUT", + "BUY", + "BY", + "BYE", + "CAB", + "CAL", + "CAM", + "CAN", + "CAP", + "CAR", + "CAT", + "CAW", + "COD", + "COG", + "COL", + "CON", + "COO", + "COP", + "COT", + "COW", + "COY", + "CRY", + "CUB", + "CUE", + "CUP", + "CUR", + "CUT", + "DAB", + "DAD", + "DAM", + "DAN", + "DAR", + "DAY", + "DEE", + "DEL", + "DEN", + "DES", + "DEW", + "DID", + "DIE", + "DIG", + "DIN", + "DIP", + "DO", + "DOE", + "DOG", + "DON", + "DOT", + "DOW", + "DRY", + "DUB", + "DUD", + "DUE", + "DUG", + "DUN", + "EAR", + "EAT", + "ED", + "EEL", + "EGG", + "EGO", + "ELI", + "ELK", + "ELM", + "ELY", + "EM", + "END", + "EST", + "ETC", + "EVA", + "EVE", + "EWE", + "EYE", + "FAD", + "FAN", + "FAR", + "FAT", + "FAY", + "FED", + "FEE", + "FEW", + "FIB", + "FIG", + "FIN", + "FIR", + "FIT", + "FLO", + "FLY", + "FOE", + "FOG", + "FOR", + "FRY", + "FUM", + "FUN", + "FUR", + "GAB", + "GAD", + "GAG", + "GAL", + "GAM", + "GAP", + "GAS", + "GAY", + "GEE", + "GEL", + "GEM", + "GET", + "GIG", + "GIL", + "GIN", + "GO", + "GOT", + "GUM", + "GUN", + "GUS", + "GUT", + "GUY", + "GYM", + "GYP", + "HA", + "HAD", + "HAL", + "HAM", + "HAN", + "HAP", + "HAS", + "HAT", + "HAW", + "HAY", + "HE", + "HEM", + "HEN", + "HER", + "HEW", + "HEY", + "HI", + "HID", + "HIM", + "HIP", + "HIS", + "HIT", + "HO", + "HOB", + "HOC", + "HOE", + "HOG", + "HOP", + "HOT", + "HOW", + "HUB", + "HUE", + "HUG", + "HUH", + "HUM", + "HUT", + "I", + "ICY", + "IDA", + "IF", + "IKE", + "ILL", + "INK", + "INN", + "IO", + "ION", + "IQ", + "IRA", + "IRE", + "IRK", + "IS", + "IT", + "ITS", + "IVY", + "JAB", + "JAG", + "JAM", + "JAN", + "JAR", + "JAW", + "JAY", + "JET", + "JIG", + "JIM", + "JO", + "JOB", + "JOE", + "JOG", + "JOT", + "JOY", + "JUG", + "JUT", + "KAY", + "KEG", + "KEN", + "KEY", + "KID", + "KIM", + "KIN", + "KIT", + "LA", + "LAB", + "LAC", + "LAD", + "LAG", + "LAM", + "LAP", + "LAW", + "LAY", + "LEA", + "LED", + "LEE", + "LEG", + "LEN", + "LEO", + "LET", + "LEW", + "LID", + "LIE", + "LIN", + "LIP", + "LIT", + "LO", + "LOB", + "LOG", + "LOP", + "LOS", + "LOT", + "LOU", + "LOW", + "LOY", + "LUG", + "LYE", + "MA", + "MAC", + "MAD", + "MAE", + "MAN", + "MAO", + "MAP", + "MAT", + "MAW", + "MAY", + "ME", + "MEG", + "MEL", + "MEN", + "MET", + "MEW", + "MID", + "MIN", + "MIT", + "MOB", + "MOD", + "MOE", + "MOO", + "MOP", + "MOS", + "MOT", + "MOW", + "MUD", + "MUG", + "MUM", + "MY", + "NAB", + "NAG", + "NAN", + "NAP", + "NAT", + "NAY", + "NE", + "NED", + "NEE", + "NET", + "NEW", + "NIB", + "NIL", + "NIP", + "NIT", + "NO", + "NOB", + "NOD", + "NON", + "NOR", + "NOT", + "NOV", + "NOW", + "NU", + "NUN", + "NUT", + "O", + "OAF", + "OAK", + "OAR", + "OAT", + "ODD", + "ODE", + "OF", + "OFF", + "OFT", + "OH", + "OIL", + "OK", + "OLD", + "ON", + "ONE", + "OR", + "ORB", + "ORE", + "ORR", + "OS", + "OTT", + "OUR", + "OUT", + "OVA", + "OW", + "OWE", + "OWL", + "OWN", + "OX", + "PA", + "PAD", + "PAL", + "PAM", + "PAN", + "PAP", + "PAR", + "PAT", + "PAW", + "PAY", + "PEA", + "PEG", + "PEN", + "PEP", + "PER", + "PET", + "PEW", + "PHI", + "PI", + "PIE", + "PIN", + "PIT", + "PLY", + "PO", + "POD", + "POE", + "POP", + "POT", + "POW", + "PRO", + "PRY", + "PUB", + "PUG", + "PUN", + "PUP", + "PUT", + "QUO", + "RAG", + "RAM", + "RAN", + "RAP", + "RAT", + "RAW", + "RAY", + "REB", + "RED", + "REP", + "RET", + "RIB", + "RID", + "RIG", + "RIM", + "RIO", + "RIP", + "ROB", + "ROD", + "ROE", + "RON", + "ROT", + "ROW", + "ROY", + "RUB", + "RUE", + "RUG", + "RUM", + "RUN", + "RYE", + "SAC", + "SAD", + "SAG", + "SAL", + "SAM", + "SAN", + "SAP", + "SAT", + "SAW", + "SAY", + "SEA", + "SEC", + "SEE", + "SEN", + "SET", + "SEW", + "SHE", + "SHY", + "SIN", + "SIP", + "SIR", + "SIS", + "SIT", + "SKI", + "SKY", + "SLY", + "SO", + "SOB", + "SOD", + "SON", + "SOP", + "SOW", + "SOY", + "SPA", + "SPY", + "SUB", + "SUD", + "SUE", + "SUM", + "SUN", + "SUP", + "TAB", + "TAD", + "TAG", + "TAN", + "TAP", + "TAR", + "TEA", + "TED", + "TEE", + "TEN", + "THE", + "THY", + "TIC", + "TIE", + "TIM", + "TIN", + "TIP", + "TO", + "TOE", + "TOG", + "TOM", + "TON", + "TOO", + "TOP", + "TOW", + "TOY", + "TRY", + "TUB", + "TUG", + "TUM", + "TUN", + "TWO", + "UN", + "UP", + "US", + "USE", + "VAN", + "VAT", + "VET", + "VIE", + "WAD", + "WAG", + "WAR", + "WAS", + "WAY", + "WE", + "WEB", + "WED", + "WEE", + "WET", + "WHO", + "WHY", + "WIN", + "WIT", + "WOK", + "WON", + "WOO", + "WOW", + "WRY", + "WU", + "YAM", + "YAP", + "YAW", + "YE", + "YEA", + "YES", + "YET", + "YOU", + "ABED", + "ABEL", + "ABET", + "ABLE", + "ABUT", + "ACHE", + "ACID", + "ACME", + "ACRE", + "ACTA", + "ACTS", + "ADAM", + "ADDS", + "ADEN", + "AFAR", + "AFRO", + "AGEE", + "AHEM", + "AHOY", + "AIDA", + "AIDE", + "AIDS", + "AIRY", + "AJAR", + "AKIN", + "ALAN", + "ALEC", + "ALGA", + "ALIA", + "ALLY", + "ALMA", + "ALOE", + "ALSO", + "ALTO", + "ALUM", + "ALVA", + "AMEN", + "AMES", + "AMID", + "AMMO", + "AMOK", + "AMOS", + "AMRA", + "ANDY", + "ANEW", + "ANNA", + "ANNE", + "ANTE", + "ANTI", + "AQUA", + "ARAB", + "ARCH", + "AREA", + "ARGO", + "ARID", + "ARMY", + "ARTS", + "ARTY", + "ASIA", + "ASKS", + "ATOM", + "AUNT", + "AURA", + "AUTO", + "AVER", + "AVID", + "AVIS", + "AVON", + "AVOW", + "AWAY", + "AWRY", + "BABE", + "BABY", + "BACH", + "BACK", + "BADE", + "BAIL", + "BAIT", + "BAKE", + "BALD", + "BALE", + "BALI", + "BALK", + "BALL", + "BALM", + "BAND", + "BANE", + "BANG", + "BANK", + "BARB", + "BARD", + "BARE", + "BARK", + "BARN", + "BARR", + "BASE", + "BASH", + "BASK", + "BASS", + "BATE", + "BATH", + "BAWD", + "BAWL", + "BEAD", + "BEAK", + "BEAM", + "BEAN", + "BEAR", + "BEAT", + "BEAU", + "BECK", + "BEEF", + "BEEN", + "BEER", + "BEET", + "BELA", + "BELL", + "BELT", + "BEND", + "BENT", + "BERG", + "BERN", + "BERT", + "BESS", + "BEST", + "BETA", + "BETH", + "BHOY", + "BIAS", + "BIDE", + "BIEN", + "BILE", + "BILK", + "BILL", + "BIND", + "BING", + "BIRD", + "BITE", + "BITS", + "BLAB", + "BLAT", + "BLED", + "BLEW", + "BLOB", + "BLOC", + "BLOT", + "BLOW", + "BLUE", + "BLUM", + "BLUR", + "BOAR", + "BOAT", + "BOCA", + "BOCK", + "BODE", + "BODY", + "BOGY", + "BOHR", + "BOIL", + "BOLD", + "BOLO", + "BOLT", + "BOMB", + "BONA", + "BOND", + "BONE", + "BONG", + "BONN", + "BONY", + "BOOK", + "BOOM", + "BOON", + "BOOT", + "BORE", + "BORG", + "BORN", + "BOSE", + "BOSS", + "BOTH", + "BOUT", + "BOWL", + "BOYD", + "BRAD", + "BRAE", + "BRAG", + "BRAN", + "BRAY", + "BRED", + "BREW", + "BRIG", + "BRIM", + "BROW", + "BUCK", + "BUDD", + "BUFF", + "BULB", + "BULK", + "BULL", + "BUNK", + "BUNT", + "BUOY", + "BURG", + "BURL", + "BURN", + "BURR", + "BURT", + "BURY", + "BUSH", + "BUSS", + "BUST", + "BUSY", + "BYTE", + "CADY", + "CAFE", + "CAGE", + "CAIN", + "CAKE", + "CALF", + "CALL", + "CALM", + "CAME", + "CANE", + "CANT", + "CARD", + "CARE", + "CARL", + "CARR", + "CART", + "CASE", + "CASH", + "CASK", + "CAST", + "CAVE", + "CEIL", + "CELL", + "CENT", + "CERN", + "CHAD", + "CHAR", + "CHAT", + "CHAW", + "CHEF", + "CHEN", + "CHEW", + "CHIC", + "CHIN", + "CHOU", + "CHOW", + "CHUB", + "CHUG", + "CHUM", + "CITE", + "CITY", + "CLAD", + "CLAM", + "CLAN", + "CLAW", + "CLAY", + "CLOD", + "CLOG", + "CLOT", + "CLUB", + "CLUE", + "COAL", + "COAT", + "COCA", + "COCK", + "COCO", + "CODA", + "CODE", + "CODY", + "COED", + "COIL", + "COIN", + "COKE", + "COLA", + "COLD", + "COLT", + "COMA", + "COMB", + "COME", + "COOK", + "COOL", + "COON", + "COOT", + "CORD", + "CORE", + "CORK", + "CORN", + "COST", + "COVE", + "COWL", + "CRAB", + "CRAG", + "CRAM", + "CRAY", + "CREW", + "CRIB", + "CROW", + "CRUD", + "CUBA", + "CUBE", + "CUFF", + "CULL", + "CULT", + "CUNY", + "CURB", + "CURD", + "CURE", + "CURL", + "CURT", + "CUTS", + "DADE", + "DALE", + "DAME", + "DANA", + "DANE", + "DANG", + "DANK", + "DARE", + "DARK", + "DARN", + "DART", + "DASH", + "DATA", + "DATE", + "DAVE", + "DAVY", + "DAWN", + "DAYS", + "DEAD", + "DEAF", + "DEAL", + "DEAN", + "DEAR", + "DEBT", + "DECK", + "DEED", + "DEEM", + "DEER", + "DEFT", + "DEFY", + "DELL", + "DENT", + "DENY", + "DESK", + "DIAL", + "DICE", + "DIED", + "DIET", + "DIME", + "DINE", + "DING", + "DINT", + "DIRE", + "DIRT", + "DISC", + "DISH", + "DISK", + "DIVE", + "DOCK", + "DOES", + "DOLE", + "DOLL", + "DOLT", + "DOME", + "DONE", + "DOOM", + "DOOR", + "DORA", + "DOSE", + "DOTE", + "DOUG", + "DOUR", + "DOVE", + "DOWN", + "DRAB", + "DRAG", + "DRAM", + "DRAW", + "DREW", + "DRUB", + "DRUG", + "DRUM", + "DUAL", + "DUCK", + "DUCT", + "DUEL", + "DUET", + "DUKE", + "DULL", + "DUMB", + "DUNE", + "DUNK", + "DUSK", + "DUST", + "DUTY", + "EACH", + "EARL", + "EARN", + "EASE", + "EAST", + "EASY", + "EBEN", + "ECHO", + "EDDY", + "EDEN", + "EDGE", + "EDGY", + "EDIT", + "EDNA", + "EGAN", + "ELAN", + "ELBA", + "ELLA", + "ELSE", + "EMIL", + "EMIT", + "EMMA", + "ENDS", + "ERIC", + "EROS", + "EVEN", + "EVER", + "EVIL", + "EYED", + "FACE", + "FACT", + "FADE", + "FAIL", + "FAIN", + "FAIR", + "FAKE", + "FALL", + "FAME", + "FANG", + "FARM", + "FAST", + "FATE", + "FAWN", + "FEAR", + "FEAT", + "FEED", + "FEEL", + "FEET", + "FELL", + "FELT", + "FEND", + "FERN", + "FEST", + "FEUD", + "FIEF", + "FIGS", + "FILE", + "FILL", + "FILM", + "FIND", + "FINE", + "FINK", + "FIRE", + "FIRM", + "FISH", + "FISK", + "FIST", + "FITS", + "FIVE", + "FLAG", + "FLAK", + "FLAM", + "FLAT", + "FLAW", + "FLEA", + "FLED", + "FLEW", + "FLIT", + "FLOC", + "FLOG", + "FLOW", + "FLUB", + "FLUE", + "FOAL", + "FOAM", + "FOGY", + "FOIL", + "FOLD", + "FOLK", + "FOND", + "FONT", + "FOOD", + "FOOL", + "FOOT", + "FORD", + "FORE", + "FORK", + "FORM", + "FORT", + "FOSS", + "FOUL", + "FOUR", + "FOWL", + "FRAU", + "FRAY", + "FRED", + "FREE", + "FRET", + "FREY", + "FROG", + "FROM", + "FUEL", + "FULL", + "FUME", + "FUND", + "FUNK", + "FURY", + "FUSE", + "FUSS", + "GAFF", + "GAGE", + "GAIL", + "GAIN", + "GAIT", + "GALA", + "GALE", + "GALL", + "GALT", + "GAME", + "GANG", + "GARB", + "GARY", + "GASH", + "GATE", + "GAUL", + "GAUR", + "GAVE", + "GAWK", + "GEAR", + "GELD", + "GENE", + "GENT", + "GERM", + "GETS", + "GIBE", + "GIFT", + "GILD", + "GILL", + "GILT", + "GINA", + "GIRD", + "GIRL", + "GIST", + "GIVE", + "GLAD", + "GLEE", + "GLEN", + "GLIB", + "GLOB", + "GLOM", + "GLOW", + "GLUE", + "GLUM", + "GLUT", + "GOAD", + "GOAL", + "GOAT", + "GOER", + "GOES", + "GOLD", + "GOLF", + "GONE", + "GONG", + "GOOD", + "GOOF", + "GORE", + "GORY", + "GOSH", + "GOUT", + "GOWN", + "GRAB", + "GRAD", + "GRAY", + "GREG", + "GREW", + "GREY", + "GRID", + "GRIM", + "GRIN", + "GRIT", + "GROW", + "GRUB", + "GULF", + "GULL", + "GUNK", + "GURU", + "GUSH", + "GUST", + "GWEN", + "GWYN", + "HAAG", + "HAAS", + "HACK", + "HAIL", + "HAIR", + "HALE", + "HALF", + "HALL", + "HALO", + "HALT", + "HAND", + "HANG", + "HANK", + "HANS", + "HARD", + "HARK", + "HARM", + "HART", + "HASH", + "HAST", + "HATE", + "HATH", + "HAUL", + "HAVE", + "HAWK", + "HAYS", + "HEAD", + "HEAL", + "HEAR", + "HEAT", + "HEBE", + "HECK", + "HEED", + "HEEL", + "HEFT", + "HELD", + "HELL", + "HELM", + "HERB", + "HERD", + "HERE", + "HERO", + "HERS", + "HESS", + "HEWN", + "HICK", + "HIDE", + "HIGH", + "HIKE", + "HILL", + "HILT", + "HIND", + "HINT", + "HIRE", + "HISS", + "HIVE", + "HOBO", + "HOCK", + "HOFF", + "HOLD", + "HOLE", + "HOLM", + "HOLT", + "HOME", + "HONE", + "HONK", + "HOOD", + "HOOF", + "HOOK", + "HOOT", + "HORN", + "HOSE", + "HOST", + "HOUR", + "HOVE", + "HOWE", + "HOWL", + "HOYT", + "HUCK", + "HUED", + "HUFF", + "HUGE", + "HUGH", + "HUGO", + "HULK", + "HULL", + "HUNK", + "HUNT", + "HURD", + "HURL", + "HURT", + "HUSH", + "HYDE", + "HYMN", + "IBIS", + "ICON", + "IDEA", + "IDLE", + "IFFY", + "INCA", + "INCH", + "INTO", + "IONS", + "IOTA", + "IOWA", + "IRIS", + "IRMA", + "IRON", + "ISLE", + "ITCH", + "ITEM", + "IVAN", + "JACK", + "JADE", + "JAIL", + "JAKE", + "JANE", + "JAVA", + "JEAN", + "JEFF", + "JERK", + "JESS", + "JEST", + "JIBE", + "JILL", + "JILT", + "JIVE", + "JOAN", + "JOBS", + "JOCK", + "JOEL", + "JOEY", + "JOHN", + "JOIN", + "JOKE", + "JOLT", + "JOVE", + "JUDD", + "JUDE", + "JUDO", + "JUDY", + "JUJU", + "JUKE", + "JULY", + "JUNE", + "JUNK", + "JUNO", + "JURY", + "JUST", + "JUTE", + "KAHN", + "KALE", + "KANE", + "KANT", + "KARL", + "KATE", + "KEEL", + "KEEN", + "KENO", + "KENT", + "KERN", + "KERR", + "KEYS", + "KICK", + "KILL", + "KIND", + "KING", + "KIRK", + "KISS", + "KITE", + "KLAN", + "KNEE", + "KNEW", + "KNIT", + "KNOB", + "KNOT", + "KNOW", + "KOCH", + "KONG", + "KUDO", + "KURD", + "KURT", + "KYLE", + "LACE", + "LACK", + "LACY", + "LADY", + "LAID", + "LAIN", + "LAIR", + "LAKE", + "LAMB", + "LAME", + "LAND", + "LANE", + "LANG", + "LARD", + "LARK", + "LASS", + "LAST", + "LATE", + "LAUD", + "LAVA", + "LAWN", + "LAWS", + "LAYS", + "LEAD", + "LEAF", + "LEAK", + "LEAN", + "LEAR", + "LEEK", + "LEER", + "LEFT", + "LEND", + "LENS", + "LENT", + "LEON", + "LESK", + "LESS", + "LEST", + "LETS", + "LIAR", + "LICE", + "LICK", + "LIED", + "LIEN", + "LIES", + "LIEU", + "LIFE", + "LIFT", + "LIKE", + "LILA", + "LILT", + "LILY", + "LIMA", + "LIMB", + "LIME", + "LIND", + "LINE", + "LINK", + "LINT", + "LION", + "LISA", + "LIST", + "LIVE", + "LOAD", + "LOAF", + "LOAM", + "LOAN", + "LOCK", + "LOFT", + "LOGE", + "LOIS", + "LOLA", + "LONE", + "LONG", + "LOOK", + "LOON", + "LOOT", + "LORD", + "LORE", + "LOSE", + "LOSS", + "LOST", + "LOUD", + "LOVE", + "LOWE", + "LUCK", + "LUCY", + "LUGE", + "LUKE", + "LULU", + "LUND", + "LUNG", + "LURA", + "LURE", + "LURK", + "LUSH", + "LUST", + "LYLE", + "LYNN", + "LYON", + "LYRA", + "MACE", + "MADE", + "MAGI", + "MAID", + "MAIL", + "MAIN", + "MAKE", + "MALE", + "MALI", + "MALL", + "MALT", + "MANA", + "MANN", + "MANY", + "MARC", + "MARE", + "MARK", + "MARS", + "MART", + "MARY", + "MASH", + "MASK", + "MASS", + "MAST", + "MATE", + "MATH", + "MAUL", + "MAYO", + "MEAD", + "MEAL", + "MEAN", + "MEAT", + "MEEK", + "MEET", + "MELD", + "MELT", + "MEMO", + "MEND", + "MENU", + "MERT", + "MESH", + "MESS", + "MICE", + "MIKE", + "MILD", + "MILE", + "MILK", + "MILL", + "MILT", + "MIMI", + "MIND", + "MINE", + "MINI", + "MINK", + "MINT", + "MIRE", + "MISS", + "MIST", + "MITE", + "MITT", + "MOAN", + "MOAT", + "MOCK", + "MODE", + "MOLD", + "MOLE", + "MOLL", + "MOLT", + "MONA", + "MONK", + "MONT", + "MOOD", + "MOON", + "MOOR", + "MOOT", + "MORE", + "MORN", + "MORT", + "MOSS", + "MOST", + "MOTH", + "MOVE", + "MUCH", + "MUCK", + "MUDD", + "MUFF", + "MULE", + "MULL", + "MURK", + "MUSH", + "MUST", + "MUTE", + "MUTT", + "MYRA", + "MYTH", + "NAGY", + "NAIL", + "NAIR", + "NAME", + "NARY", + "NASH", + "NAVE", + "NAVY", + "NEAL", + "NEAR", + "NEAT", + "NECK", + "NEED", + "NEIL", + "NELL", + "NEON", + "NERO", + "NESS", + "NEST", + "NEWS", + "NEWT", + "NIBS", + "NICE", + "NICK", + "NILE", + "NINA", + "NINE", + "NOAH", + "NODE", + "NOEL", + "NOLL", + "NONE", + "NOOK", + "NOON", + "NORM", + "NOSE", + "NOTE", + "NOUN", + "NOVA", + "NUDE", + "NULL", + "NUMB", + "OATH", + "OBEY", + "OBOE", + "ODIN", + "OHIO", + "OILY", + "OINT", + "OKAY", + "OLAF", + "OLDY", + "OLGA", + "OLIN", + "OMAN", + "OMEN", + "OMIT", + "ONCE", + "ONES", + "ONLY", + "ONTO", + "ONUS", + "ORAL", + "ORGY", + "OSLO", + "OTIS", + "OTTO", + "OUCH", + "OUST", + "OUTS", + "OVAL", + "OVEN", + "OVER", + "OWLY", + "OWNS", + "QUAD", + "QUIT", + "QUOD", + "RACE", + "RACK", + "RACY", + "RAFT", + "RAGE", + "RAID", + "RAIL", + "RAIN", + "RAKE", + "RANK", + "RANT", + "RARE", + "RASH", + "RATE", + "RAVE", + "RAYS", + "READ", + "REAL", + "REAM", + "REAR", + "RECK", + "REED", + "REEF", + "REEK", + "REEL", + "REID", + "REIN", + "RENA", + "REND", + "RENT", + "REST", + "RICE", + "RICH", + "RICK", + "RIDE", + "RIFT", + "RILL", + "RIME", + "RING", + "RINK", + "RISE", + "RISK", + "RITE", + "ROAD", + "ROAM", + "ROAR", + "ROBE", + "ROCK", + "RODE", + "ROIL", + "ROLL", + "ROME", + "ROOD", + "ROOF", + "ROOK", + "ROOM", + "ROOT", + "ROSA", + "ROSE", + "ROSS", + "ROSY", + "ROTH", + "ROUT", + "ROVE", + "ROWE", + "ROWS", + "RUBE", + "RUBY", + "RUDE", + "RUDY", + "RUIN", + "RULE", + "RUNG", + "RUNS", + "RUNT", + "RUSE", + "RUSH", + "RUSK", + "RUSS", + "RUST", + "RUTH", + "SACK", + "SAFE", + "SAGE", + "SAID", + "SAIL", + "SALE", + "SALK", + "SALT", + "SAME", + "SAND", + "SANE", + "SANG", + "SANK", + "SARA", + "SAUL", + "SAVE", + "SAYS", + "SCAN", + "SCAR", + "SCAT", + "SCOT", + "SEAL", + "SEAM", + "SEAR", + "SEAT", + "SEED", + "SEEK", + "SEEM", + "SEEN", + "SEES", + "SELF", + "SELL", + "SEND", + "SENT", + "SETS", + "SEWN", + "SHAG", + "SHAM", + "SHAW", + "SHAY", + "SHED", + "SHIM", + "SHIN", + "SHOD", + "SHOE", + "SHOT", + "SHOW", + "SHUN", + "SHUT", + "SICK", + "SIDE", + "SIFT", + "SIGH", + "SIGN", + "SILK", + "SILL", + "SILO", + "SILT", + "SINE", + "SING", + "SINK", + "SIRE", + "SITE", + "SITS", + "SITU", + "SKAT", + "SKEW", + "SKID", + "SKIM", + "SKIN", + "SKIT", + "SLAB", + "SLAM", + "SLAT", + "SLAY", + "SLED", + "SLEW", + "SLID", + "SLIM", + "SLIT", + "SLOB", + "SLOG", + "SLOT", + "SLOW", + "SLUG", + "SLUM", + "SLUR", + "SMOG", + "SMUG", + "SNAG", + "SNOB", + "SNOW", + "SNUB", + "SNUG", + "SOAK", + "SOAR", + "SOCK", + "SODA", + "SOFA", + "SOFT", + "SOIL", + "SOLD", + "SOME", + "SONG", + "SOON", + "SOOT", + "SORE", + "SORT", + "SOUL", + "SOUR", + "SOWN", + "STAB", + "STAG", + "STAN", + "STAR", + "STAY", + "STEM", + "STEW", + "STIR", + "STOW", + "STUB", + "STUN", + "SUCH", + "SUDS", + "SUIT", + "SULK", + "SUMS", + "SUNG", + "SUNK", + "SURE", + "SURF", + "SWAB", + "SWAG", + "SWAM", + "SWAN", + "SWAT", + "SWAY", + "SWIM", + "SWUM", + "TACK", + "TACT", + "TAIL", + "TAKE", + "TALE", + "TALK", + "TALL", + "TANK", + "TASK", + "TATE", + "TAUT", + "TEAL", + "TEAM", + "TEAR", + "TECH", + "TEEM", + "TEEN", + "TEET", + "TELL", + "TEND", + "TENT", + "TERM", + "TERN", + "TESS", + "TEST", + "THAN", + "THAT", + "THEE", + "THEM", + "THEN", + "THEY", + "THIN", + "THIS", + "THUD", + "THUG", + "TICK", + "TIDE", + "TIDY", + "TIED", + "TIER", + "TILE", + "TILL", + "TILT", + "TIME", + "TINA", + "TINE", + "TINT", + "TINY", + "TIRE", + "TOAD", + "TOGO", + "TOIL", + "TOLD", + "TOLL", + "TONE", + "TONG", + "TONY", + "TOOK", + "TOOL", + "TOOT", + "TORE", + "TORN", + "TOTE", + "TOUR", + "TOUT", + "TOWN", + "TRAG", + "TRAM", + "TRAY", + "TREE", + "TREK", + "TRIG", + "TRIM", + "TRIO", + "TROD", + "TROT", + "TROY", + "TRUE", + "TUBA", + "TUBE", + "TUCK", + "TUFT", + "TUNA", + "TUNE", + "TUNG", + "TURF", + "TURN", + "TUSK", + "TWIG", + "TWIN", + "TWIT", + "ULAN", + "UNIT", + "URGE", + "USED", + "USER", + "USES", + "UTAH", + "VAIL", + "VAIN", + "VALE", + "VARY", + "VASE", + "VAST", + "VEAL", + "VEDA", + "VEIL", + "VEIN", + "VEND", + "VENT", + "VERB", + "VERY", + "VETO", + "VICE", + "VIEW", + "VINE", + "VISE", + "VOID", + "VOLT", + "VOTE", + "WACK", + "WADE", + "WAGE", + "WAIL", + "WAIT", + "WAKE", + "WALE", + "WALK", + "WALL", + "WALT", + "WAND", + "WANE", + "WANG", + "WANT", + "WARD", + "WARM", + "WARN", + "WART", + "WASH", + "WAST", + "WATS", + "WATT", + "WAVE", + "WAVY", + "WAYS", + "WEAK", + "WEAL", + "WEAN", + "WEAR", + "WEED", + "WEEK", + "WEIR", + "WELD", + "WELL", + "WELT", + "WENT", + "WERE", + "WERT", + "WEST", + "WHAM", + "WHAT", + "WHEE", + "WHEN", + "WHET", + "WHOA", + "WHOM", + "WICK", + "WIFE", + "WILD", + "WILL", + "WIND", + "WINE", + "WING", + "WINK", + "WINO", + "WIRE", + "WISE", + "WISH", + "WITH", + "WOLF", + "WONT", + "WOOD", + "WOOL", + "WORD", + "WORE", + "WORK", + "WORM", + "WORN", + "WOVE", + "WRIT", + "WYNN", + "YALE", + "YANG", + "YANK", + "YARD", + "YARN", + "YAWL", + "YAWN", + "YEAH", + "YEAR", + "YELL", + "YOGA", + "YOKE", +] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/__init__.py index 1862b828..fc63f03c 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/__init__.py @@ -37,5 +37,4 @@ :undocumented: _galois, _number_new, cpuid, py3compat, _raw_api """ -__all__ = ['RFC1751', 'number', 'strxor', 'asn1', 'Counter', 'Padding'] - +__all__ = ["RFC1751", "number", "strxor", "asn1", "Counter", "Padding"] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_cpu_features.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_cpu_features.py index 4794a027..99dc7235 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_cpu_features.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_cpu_features.py @@ -31,16 +31,18 @@ from Cryptodome.Util._raw_api import load_pycryptodome_raw_lib -_raw_cpuid_lib = load_pycryptodome_raw_lib("Cryptodome.Util._cpuid_c", - """ +_raw_cpuid_lib = load_pycryptodome_raw_lib( + "Cryptodome.Util._cpuid_c", + """ int have_aes_ni(void); int have_clmul(void); - """) + """, +) def have_aes_ni(): - return _raw_cpuid_lib.have_aes_ni() + return _raw_cpuid_lib.have_aes_ni() def have_clmul(): - return _raw_cpuid_lib.have_clmul() + return _raw_cpuid_lib.have_clmul() diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_file_system.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_file_system.py index 282f0dc3..26ace45f 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_file_system.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_file_system.py @@ -32,23 +32,22 @@ def pycryptodome_filename(dir_comps, filename): - """Return the complete file name for the module + """Return the complete file name for the module - dir_comps : list of string - The list of directory names in the PyCryptodome package. - The first element must be "Cryptodome". + dir_comps : list of string + The list of directory names in the PyCryptodome package. + The first element must be "Cryptodome". - filename : string - The filename (inclusing extension) in the target directory. - """ + filename : string + The filename (inclusing extension) in the target directory. + """ - if dir_comps[0] != "Cryptodome": - raise ValueError("Only available for modules under 'Cryptodome'") + if dir_comps[0] != "Cryptodome": + raise ValueError("Only available for modules under 'Cryptodome'") - dir_comps = list(dir_comps[1:]) + [filename] + dir_comps = list(dir_comps[1:]) + [filename] - util_lib, _ = os.path.split(os.path.abspath(__file__)) - root_lib = os.path.join(util_lib, "..") - - return os.path.join(root_lib, *dir_comps) + util_lib, _ = os.path.split(os.path.abspath(__file__)) + root_lib = os.path.join(util_lib, "..") + return os.path.join(root_lib, *dir_comps) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_file_system.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_file_system.pyi index d54a1268..85b403c8 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_file_system.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_file_system.pyi @@ -1,4 +1,3 @@ from typing import List - -def pycryptodome_filename(dir_comps: List[str], filename: str) -> str: ... \ No newline at end of file +def pycryptodome_filename(dir_comps: List[str], filename: str) -> str: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_raw_api.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_raw_api.py index cd64ac82..22a3a8a5 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_raw_api.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_raw_api.py @@ -38,288 +38,292 @@ # List of file suffixes for Python extensions # if sys.version_info[0] < 3: + import imp - import imp - extension_suffixes = [] - for ext, mod, typ in imp.get_suffixes(): - if typ == imp.C_EXTENSION: - extension_suffixes.append(ext) + extension_suffixes = [] + for ext, mod, typ in imp.get_suffixes(): + if typ == imp.C_EXTENSION: + extension_suffixes.append(ext) else: + from importlib import machinery - from importlib import machinery - extension_suffixes = machinery.EXTENSION_SUFFIXES + extension_suffixes = machinery.EXTENSION_SUFFIXES # Which types with buffer interface we support (apart from byte strings) _buffer_type = (bytearray, memoryview) class _VoidPointer(object): - @abc.abstractmethod - def get(self): - """Return the memory location we point to""" - return + @abc.abstractmethod + def get(self): + """Return the memory location we point to""" + return - @abc.abstractmethod - def address_of(self): - """Return a raw pointer to this pointer""" - return + @abc.abstractmethod + def address_of(self): + """Return a raw pointer to this pointer""" + return try: - # Starting from v2.18, pycparser (used by cffi for in-line ABI mode) - # stops working correctly when PYOPTIMIZE==2 or the parameter -OO is - # passed. In that case, we fall back to ctypes. - # Note that PyPy ships with an old version of pycparser so we can keep - # using cffi there. - # See https://github.com/Legrandin/pycryptodome/issues/228 - if '__pypy__' not in sys.builtin_module_names and sys.flags.optimize == 2: - raise ImportError("CFFI with optimize=2 fails due to pycparser bug.") - - # cffi still uses PyUnicode_GetSize, which was removed in Python 3.12 - # thus leading to a crash on cffi.dlopen() - # See https://groups.google.com/u/1/g/python-cffi/c/oZkOIZ_zi5k - if sys.version_info >= (3, 12) and os.name == "nt": - raise ImportError("CFFI is not compatible with Python 3.12 on Windows") - - from cffi import FFI - - ffi = FFI() - null_pointer = ffi.NULL - uint8_t_type = ffi.typeof(ffi.new("const uint8_t*")) - - _Array = ffi.new("uint8_t[1]").__class__.__bases__ - - def load_lib(name, cdecl): - """Load a shared library and return a handle to it. - - @name, either an absolute path or the name of a library - in the system search path. - - @cdecl, the C function declarations. - """ - - if hasattr(ffi, "RTLD_DEEPBIND") and not os.getenv('PYCRYPTODOME_DISABLE_DEEPBIND'): - lib = ffi.dlopen(name, ffi.RTLD_DEEPBIND) - else: - lib = ffi.dlopen(name) - ffi.cdef(cdecl) - return lib - - def c_ulong(x): - """Convert a Python integer to unsigned long""" - return x - - c_ulonglong = c_ulong - c_uint = c_ulong - c_ubyte = c_ulong - - def c_size_t(x): - """Convert a Python integer to size_t""" - return x - - def create_string_buffer(init_or_size, size=None): - """Allocate the given amount of bytes (initially set to 0)""" - - if isinstance(init_or_size, bytes): - size = max(len(init_or_size) + 1, size) - result = ffi.new("uint8_t[]", size) - result[:] = init_or_size - else: - if size: - raise ValueError("Size must be specified once only") - result = ffi.new("uint8_t[]", init_or_size) - return result - - def get_c_string(c_string): - """Convert a C string into a Python byte sequence""" - return ffi.string(c_string) - - def get_raw_buffer(buf): - """Convert a C buffer into a Python byte sequence""" - return ffi.buffer(buf)[:] - - def c_uint8_ptr(data): - if isinstance(data, _buffer_type): - # This only works for cffi >= 1.7 - return ffi.cast(uint8_t_type, ffi.from_buffer(data)) - elif byte_string(data) or isinstance(data, _Array): - return data - else: - raise TypeError("Object type %s cannot be passed to C code" % type(data)) - - class VoidPointer_cffi(_VoidPointer): - """Model a newly allocated pointer to void""" - - def __init__(self): - self._pp = ffi.new("void *[1]") - - def get(self): - return self._pp[0] - - def address_of(self): - return self._pp - - def VoidPointer(): - return VoidPointer_cffi() - - backend = "cffi" + # Starting from v2.18, pycparser (used by cffi for in-line ABI mode) + # stops working correctly when PYOPTIMIZE==2 or the parameter -OO is + # passed. In that case, we fall back to ctypes. + # Note that PyPy ships with an old version of pycparser so we can keep + # using cffi there. + # See https://github.com/Legrandin/pycryptodome/issues/228 + if "__pypy__" not in sys.builtin_module_names and sys.flags.optimize == 2: + raise ImportError("CFFI with optimize=2 fails due to pycparser bug.") + + # cffi still uses PyUnicode_GetSize, which was removed in Python 3.12 + # thus leading to a crash on cffi.dlopen() + # See https://groups.google.com/u/1/g/python-cffi/c/oZkOIZ_zi5k + if sys.version_info >= (3, 12) and os.name == "nt": + raise ImportError("CFFI is not compatible with Python 3.12 on Windows") + + from cffi import FFI + + ffi = FFI() + null_pointer = ffi.NULL + uint8_t_type = ffi.typeof(ffi.new("const uint8_t*")) + + _Array = ffi.new("uint8_t[1]").__class__.__bases__ + + def load_lib(name, cdecl): + """Load a shared library and return a handle to it. + + @name, either an absolute path or the name of a library + in the system search path. + + @cdecl, the C function declarations. + """ + + if hasattr(ffi, "RTLD_DEEPBIND") and not os.getenv("PYCRYPTODOME_DISABLE_DEEPBIND"): + lib = ffi.dlopen(name, ffi.RTLD_DEEPBIND) + else: + lib = ffi.dlopen(name) + ffi.cdef(cdecl) + return lib + + def c_ulong(x): + """Convert a Python integer to unsigned long""" + return x + + c_ulonglong = c_ulong + c_uint = c_ulong + c_ubyte = c_ulong + + def c_size_t(x): + """Convert a Python integer to size_t""" + return x + + def create_string_buffer(init_or_size, size=None): + """Allocate the given amount of bytes (initially set to 0)""" + + if isinstance(init_or_size, bytes): + size = max(len(init_or_size) + 1, size) + result = ffi.new("uint8_t[]", size) + result[:] = init_or_size + else: + if size: + raise ValueError("Size must be specified once only") + result = ffi.new("uint8_t[]", init_or_size) + return result + + def get_c_string(c_string): + """Convert a C string into a Python byte sequence""" + return ffi.string(c_string) + + def get_raw_buffer(buf): + """Convert a C buffer into a Python byte sequence""" + return ffi.buffer(buf)[:] + + def c_uint8_ptr(data): + if isinstance(data, _buffer_type): + # This only works for cffi >= 1.7 + return ffi.cast(uint8_t_type, ffi.from_buffer(data)) + elif byte_string(data) or isinstance(data, _Array): + return data + else: + raise TypeError("Object type %s cannot be passed to C code" % type(data)) + + class VoidPointer_cffi(_VoidPointer): + """Model a newly allocated pointer to void""" + + def __init__(self): + self._pp = ffi.new("void *[1]") + + def get(self): + return self._pp[0] + + def address_of(self): + return self._pp + + def VoidPointer(): + return VoidPointer_cffi() + + backend = "cffi" except ImportError: - - import ctypes - from ctypes import (CDLL, c_void_p, byref, c_ulong, c_ulonglong, c_size_t, - create_string_buffer, c_ubyte, c_uint) - from ctypes.util import find_library - from ctypes import Array as _Array - - null_pointer = None - cached_architecture = [] - - def c_ubyte(c): - if not (0 <= c < 256): - raise OverflowError() - return ctypes.c_ubyte(c) - - def load_lib(name, cdecl): - if not cached_architecture: - # platform.architecture() creates a subprocess, so caching the - # result makes successive imports faster. - import platform - cached_architecture[:] = platform.architecture() - bits, linkage = cached_architecture - if "." not in name and not linkage.startswith("Win"): - full_name = find_library(name) - if full_name is None: - raise OSError("Cannot load library '%s'" % name) - name = full_name - return CDLL(name) - - def get_c_string(c_string): - return c_string.value - - def get_raw_buffer(buf): - return buf.raw - - # ---- Get raw pointer --- - - _c_ssize_t = ctypes.c_ssize_t - - _PyBUF_SIMPLE = 0 - _PyObject_GetBuffer = ctypes.pythonapi.PyObject_GetBuffer - _PyBuffer_Release = ctypes.pythonapi.PyBuffer_Release - _py_object = ctypes.py_object - _c_ssize_p = ctypes.POINTER(_c_ssize_t) - - # See Include/object.h for CPython - # and https://github.com/pallets/click/blob/master/src/click/_winconsole.py - class _Py_buffer(ctypes.Structure): - _fields_ = [ - ('buf', c_void_p), - ('obj', ctypes.py_object), - ('len', _c_ssize_t), - ('itemsize', _c_ssize_t), - ('readonly', ctypes.c_int), - ('ndim', ctypes.c_int), - ('format', ctypes.c_char_p), - ('shape', _c_ssize_p), - ('strides', _c_ssize_p), - ('suboffsets', _c_ssize_p), - ('internal', c_void_p) - ] - - # Extra field for CPython 2.6/2.7 - if sys.version_info[0] == 2: - _fields_.insert(-1, ('smalltable', _c_ssize_t * 2)) - - def c_uint8_ptr(data): - if byte_string(data) or isinstance(data, _Array): - return data - elif isinstance(data, _buffer_type): - obj = _py_object(data) - buf = _Py_buffer() - _PyObject_GetBuffer(obj, byref(buf), _PyBUF_SIMPLE) - try: - buffer_type = ctypes.c_ubyte * buf.len - return buffer_type.from_address(buf.buf) - finally: - _PyBuffer_Release(byref(buf)) - else: - raise TypeError("Object type %s cannot be passed to C code" % type(data)) - - # --- - - class VoidPointer_ctypes(_VoidPointer): - """Model a newly allocated pointer to void""" - - def __init__(self): - self._p = c_void_p() - - def get(self): - return self._p - - def address_of(self): - return byref(self._p) - - def VoidPointer(): - return VoidPointer_ctypes() - - backend = "ctypes" + import ctypes + from ctypes import ( + CDLL, + c_void_p, + byref, + c_ulong, + c_ubyte, + ) + from ctypes.util import find_library + from ctypes import Array as _Array + + null_pointer = None + cached_architecture = [] + + def c_ubyte(c): + if not (0 <= c < 256): + raise OverflowError() + return ctypes.c_ubyte(c) + + def load_lib(name, cdecl): + if not cached_architecture: + # platform.architecture() creates a subprocess, so caching the + # result makes successive imports faster. + import platform + + cached_architecture[:] = platform.architecture() + bits, linkage = cached_architecture + if "." not in name and not linkage.startswith("Win"): + full_name = find_library(name) + if full_name is None: + raise OSError("Cannot load library '%s'" % name) + name = full_name + return CDLL(name) + + def get_c_string(c_string): + return c_string.value + + def get_raw_buffer(buf): + return buf.raw + + # ---- Get raw pointer --- + + _c_ssize_t = ctypes.c_ssize_t + + _PyBUF_SIMPLE = 0 + _PyObject_GetBuffer = ctypes.pythonapi.PyObject_GetBuffer + _PyBuffer_Release = ctypes.pythonapi.PyBuffer_Release + _py_object = ctypes.py_object + _c_ssize_p = ctypes.POINTER(_c_ssize_t) + + # See Include/object.h for CPython + # and https://github.com/pallets/click/blob/master/src/click/_winconsole.py + class _Py_buffer(ctypes.Structure): + _fields_ = [ + ("buf", c_void_p), + ("obj", ctypes.py_object), + ("len", _c_ssize_t), + ("itemsize", _c_ssize_t), + ("readonly", ctypes.c_int), + ("ndim", ctypes.c_int), + ("format", ctypes.c_char_p), + ("shape", _c_ssize_p), + ("strides", _c_ssize_p), + ("suboffsets", _c_ssize_p), + ("internal", c_void_p), + ] + + # Extra field for CPython 2.6/2.7 + if sys.version_info[0] == 2: + _fields_.insert(-1, ("smalltable", _c_ssize_t * 2)) + + def c_uint8_ptr(data): + if byte_string(data) or isinstance(data, _Array): + return data + elif isinstance(data, _buffer_type): + obj = _py_object(data) + buf = _Py_buffer() + _PyObject_GetBuffer(obj, byref(buf), _PyBUF_SIMPLE) + try: + buffer_type = ctypes.c_ubyte * buf.len + return buffer_type.from_address(buf.buf) + finally: + _PyBuffer_Release(byref(buf)) + else: + raise TypeError("Object type %s cannot be passed to C code" % type(data)) + + # --- + + class VoidPointer_ctypes(_VoidPointer): + """Model a newly allocated pointer to void""" + + def __init__(self): + self._p = c_void_p() + + def get(self): + return self._p + + def address_of(self): + return byref(self._p) + + def VoidPointer(): + return VoidPointer_ctypes() + + backend = "ctypes" class SmartPointer(object): - """Class to hold a non-managed piece of memory""" + """Class to hold a non-managed piece of memory""" - def __init__(self, raw_pointer, destructor): - self._raw_pointer = raw_pointer - self._destructor = destructor + def __init__(self, raw_pointer, destructor): + self._raw_pointer = raw_pointer + self._destructor = destructor - def get(self): - return self._raw_pointer + def get(self): + return self._raw_pointer - def release(self): - rp, self._raw_pointer = self._raw_pointer, None - return rp + def release(self): + rp, self._raw_pointer = self._raw_pointer, None + return rp - def __del__(self): - try: - if self._raw_pointer is not None: - self._destructor(self._raw_pointer) - self._raw_pointer = None - except AttributeError: - pass + def __del__(self): + try: + if self._raw_pointer is not None: + self._destructor(self._raw_pointer) + self._raw_pointer = None + except AttributeError: + pass def load_pycryptodome_raw_lib(name, cdecl): - """Load a shared library and return a handle to it. - - @name, the name of the library expressed as a PyCryptodome module, - for instance Cryptodome.Cipher._raw_cbc. - - @cdecl, the C function declarations. - """ - - split = name.split(".") - dir_comps, basename = split[:-1], split[-1] - attempts = [] - for ext in extension_suffixes: - try: - filename = basename + ext - full_name = pycryptodome_filename(dir_comps, filename) - if not os.path.isfile(full_name): - attempts.append("Not found '%s'" % filename) - continue - return load_lib(full_name, cdecl) - except OSError as exp: - attempts.append("Cannot load '%s': %s" % (filename, str(exp))) - raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts))) + """Load a shared library and return a handle to it. + + @name, the name of the library expressed as a PyCryptodome module, + for instance Cryptodome.Cipher._raw_cbc. + + @cdecl, the C function declarations. + """ + + split = name.split(".") + dir_comps, basename = split[:-1], split[-1] + attempts = [] + for ext in extension_suffixes: + try: + filename = basename + ext + full_name = pycryptodome_filename(dir_comps, filename) + if not os.path.isfile(full_name): + attempts.append("Not found '%s'" % filename) + continue + return load_lib(full_name, cdecl) + except OSError as exp: + attempts.append("Cannot load '%s': %s" % (filename, str(exp))) + raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts))) def is_buffer(x): - """Return True if object x supports the buffer interface""" - return isinstance(x, (bytes, bytearray, memoryview)) + """Return True if object x supports the buffer interface""" + return isinstance(x, (bytes, bytearray, memoryview)) def is_writeable_buffer(x): - return (isinstance(x, bytearray) or - (isinstance(x, memoryview) and not x.readonly)) + return isinstance(x, bytearray) or (isinstance(x, memoryview) and not x.readonly) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_raw_api.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_raw_api.pyi index 2bc53016..a5c78dac 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_raw_api.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/_raw_api.pyi @@ -1,27 +1,27 @@ from typing import Any, Optional, Union -def load_lib(name: str, cdecl: str) -> Any : ... -def c_ulong(x: int ) -> Any : ... -def c_ulonglong(x: int ) -> Any : ... -def c_size_t(x: int) -> Any : ... -def create_string_buffer(init_or_size: Union[bytes,int], size: Optional[int]) -> Any : ... -def get_c_string(c_string: Any) -> bytes : ... -def get_raw_buffer(buf: Any) -> bytes : ... -def c_uint8_ptr(data: Union[bytes, memoryview, bytearray]) -> Any : ... +def load_lib(name: str, cdecl: str) -> Any: ... +def c_ulong(x: int) -> Any: ... +def c_ulonglong(x: int) -> Any: ... +def c_size_t(x: int) -> Any: ... +def create_string_buffer(init_or_size: Union[bytes, int], size: Optional[int]) -> Any: ... +def get_c_string(c_string: Any) -> bytes: ... +def get_raw_buffer(buf: Any) -> bytes: ... +def c_uint8_ptr(data: Union[bytes, memoryview, bytearray]) -> Any: ... class VoidPointer(object): - def get(self) -> Any : ... - def address_of(self) -> Any : ... + def get(self) -> Any: ... + def address_of(self) -> Any: ... class SmartPointer(object): - def __init__(self, raw_pointer: Any, destructor: Any) -> None : ... - def get(self) -> Any : ... - def release(self) -> Any : ... + def __init__(self, raw_pointer: Any, destructor: Any) -> None: ... + def get(self) -> Any: ... + def release(self) -> Any: ... -backend : str -null_pointer : Any +backend: str +null_pointer: Any ffi: Any -def load_pycryptodome_raw_lib(name: str, cdecl: str) -> Any : ... -def is_buffer(x: Any) -> bool : ... -def is_writeable_buffer(x: Any) -> bool : ... +def load_pycryptodome_raw_lib(name: str, cdecl: str) -> Any: ... +def is_buffer(x: Any) -> bool: ... +def is_writeable_buffer(x: Any) -> bool: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/asn1.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/asn1.py index 9987fdac..937c81c6 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/asn1.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/asn1.py @@ -26,8 +26,17 @@ from Cryptodome.Util.number import long_to_bytes, bytes_to_long -__all__ = ['DerObject', 'DerInteger', 'DerBoolean', 'DerOctetString', - 'DerNull', 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf'] +__all__ = [ + "DerObject", + "DerInteger", + "DerBoolean", + "DerOctetString", + "DerNull", + "DerSequence", + "DerObjectId", + "DerBitString", + "DerSetOf", +] # Useful references: # - https://luca.ntop.org/Teaching/Appunti/asn1.html @@ -37,1028 +46,1045 @@ # - https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf # - https://misc.daniel-marschall.de/asn.1/oid-converter/online.php + def _is_number(x, only_non_negative=False): - test = 0 - try: - test = x + test - except TypeError: - return False - return not only_non_negative or x >= 0 + test = 0 + try: + test = x + test + except TypeError: + return False + return not only_non_negative or x >= 0 class BytesIO_EOF(object): - """This class differs from BytesIO in that a ValueError exception is - raised whenever EOF is reached.""" + """This class differs from BytesIO in that a ValueError exception is + raised whenever EOF is reached.""" - def __init__(self, initial_bytes): - self._buffer = initial_bytes - self._index = 0 - self._bookmark = None + def __init__(self, initial_bytes): + self._buffer = initial_bytes + self._index = 0 + self._bookmark = None - def set_bookmark(self): - self._bookmark = self._index + def set_bookmark(self): + self._bookmark = self._index - def data_since_bookmark(self): - assert self._bookmark is not None - return self._buffer[self._bookmark:self._index] + def data_since_bookmark(self): + assert self._bookmark is not None + return self._buffer[self._bookmark : self._index] - def remaining_data(self): - return len(self._buffer) - self._index + def remaining_data(self): + return len(self._buffer) - self._index - def read(self, length): - new_index = self._index + length - if new_index > len(self._buffer): - raise ValueError("Not enough data for DER decoding: expected %d bytes and found %d" % (new_index, len(self._buffer))) + def read(self, length): + new_index = self._index + length + if new_index > len(self._buffer): + raise ValueError( + "Not enough data for DER decoding: expected %d bytes and found %d" + % (new_index, len(self._buffer)) + ) - result = self._buffer[self._index:new_index] - self._index = new_index - return result + result = self._buffer[self._index : new_index] + self._index = new_index + return result - def read_byte(self): - return bord(self.read(1)[0]) + def read_byte(self): + return bord(self.read(1)[0]) class DerObject(object): - """Base class for defining a single DER object. - - This class should never be directly instantiated. - """ - - def __init__(self, asn1Id=None, payload=b'', implicit=None, - constructed=False, explicit=None): - """Initialize the DER object according to a specific ASN.1 type. - - :Parameters: - asn1Id : integer or byte - The universal DER tag number for this object - (e.g. 0x10 for a SEQUENCE). - If None, the tag is not known yet. - - payload : byte string - The initial payload of the object (that it, - the content octets). - If not specified, the payload is empty. - - implicit : integer or byte - The IMPLICIT tag number (< 0x1F) to use for the encoded object. - It overrides the universal tag *asn1Id*. - It cannot be combined with the ``explicit`` parameter. - By default, there is no IMPLICIT tag. - - constructed : bool - True when the ASN.1 type is *constructed*. - False when it is *primitive* (default). - - explicit : integer or byte - The EXPLICIT tag number (< 0x1F) to use for the encoded object. - It cannot be combined with the ``implicit`` parameter. - By default, there is no EXPLICIT tag. - """ - - if asn1Id is None: - # The tag octet will be read in with ``decode`` - self._tag_octet = None - return - asn1Id = self._convertTag(asn1Id) - - self.payload = payload - - # In a BER/DER identifier octet: - # * bits 4-0 contain the tag value - # * bit 5 is set if the type is 'constructed' - # and unset if 'primitive' - # * bits 7-6 depend on the encoding class - # - # Class | Bit 7, Bit 6 - # ---------------------------------- - # universal | 0 0 - # application | 0 1 - # context-spec | 1 0 (default for IMPLICIT/EXPLICIT) - # private | 1 1 - # - - constructed_bit = 0x20 if constructed else 0x00 - - if None not in (explicit, implicit): - raise ValueError("Explicit and implicit tags are" - " mutually exclusive") - - if implicit is not None: - # IMPLICIT tag overrides asn1Id - self._tag_octet = 0x80 | constructed_bit | self._convertTag(implicit) - elif explicit is not None: - # 'constructed bit' is always asserted for an EXPLICIT tag - self._tag_octet = 0x80 | 0x20 | self._convertTag(explicit) - self._inner_tag_octet = constructed_bit | asn1Id - else: - # Neither IMPLICIT nor EXPLICIT - self._tag_octet = constructed_bit | asn1Id - - def _convertTag(self, tag): - """Check if *tag* is a real DER tag (5 bits). - Convert it from a character to number if necessary. - """ - if not _is_number(tag): - if len(tag) == 1: - tag = bord(tag[0]) - # Ensure that tag is a low tag - if not (_is_number(tag) and 0 <= tag < 0x1F): - raise ValueError("Wrong DER tag") - return tag - - @staticmethod - def _definite_form(length): - """Build length octets according to BER/DER - definite form. - """ - if length > 127: - encoding = long_to_bytes(length) - return bchr(len(encoding) + 128) + encoding - return bchr(length) - - def encode(self): - """Return this DER element, fully encoded as a binary byte string.""" - - # Concatenate identifier octets, length octets, - # and contents octets - - output_payload = self.payload - - # In case of an EXTERNAL tag, first encode the inner - # element. - if hasattr(self, "_inner_tag_octet"): - output_payload = (bchr(self._inner_tag_octet) + - self._definite_form(len(self.payload)) + - self.payload) - - return (bchr(self._tag_octet) + - self._definite_form(len(output_payload)) + - output_payload) - - def _decodeLen(self, s): - """Decode DER length octets from a file.""" - - length = s.read_byte() - - if length > 127: - encoded_length = s.read(length & 0x7F) - if bord(encoded_length[0]) == 0: - raise ValueError("Invalid DER: length has leading zero") - length = bytes_to_long(encoded_length) - if length <= 127: - raise ValueError("Invalid DER: length in long form but smaller than 128") - - return length - - def decode(self, der_encoded, strict=False): - """Decode a complete DER element, and re-initializes this - object with it. - - Args: - der_encoded (byte string): A complete DER element. - - Raises: - ValueError: in case of parsing errors. - """ - - if not byte_string(der_encoded): - raise ValueError("Input is not a byte string") - - s = BytesIO_EOF(der_encoded) - self._decodeFromStream(s, strict) - - # There shouldn't be other bytes left - if s.remaining_data() > 0: - raise ValueError("Unexpected extra data after the DER structure") - - return self - - def _decodeFromStream(self, s, strict): - """Decode a complete DER element from a file.""" - - idOctet = s.read_byte() - if self._tag_octet is not None: - if idOctet != self._tag_octet: - raise ValueError("Unexpected DER tag") - else: - self._tag_octet = idOctet - length = self._decodeLen(s) - self.payload = s.read(length) - - # In case of an EXTERNAL tag, further decode the inner - # element. - if hasattr(self, "_inner_tag_octet"): - p = BytesIO_EOF(self.payload) - inner_octet = p.read_byte() - if inner_octet != self._inner_tag_octet: - raise ValueError("Unexpected internal DER tag") - length = self._decodeLen(p) - self.payload = p.read(length) - - # There shouldn't be other bytes left - if p.remaining_data() > 0: - raise ValueError("Unexpected extra data after the DER structure") + """Base class for defining a single DER object. + + This class should never be directly instantiated. + """ + + def __init__( + self, + asn1Id=None, + payload=b"", + implicit=None, + constructed=False, + explicit=None, + ): + """Initialize the DER object according to a specific ASN.1 type. + + :Parameters: + asn1Id : integer or byte + The universal DER tag number for this object + (e.g. 0x10 for a SEQUENCE). + If None, the tag is not known yet. + + payload : byte string + The initial payload of the object (that it, + the content octets). + If not specified, the payload is empty. + + implicit : integer or byte + The IMPLICIT tag number (< 0x1F) to use for the encoded object. + It overrides the universal tag *asn1Id*. + It cannot be combined with the ``explicit`` parameter. + By default, there is no IMPLICIT tag. + + constructed : bool + True when the ASN.1 type is *constructed*. + False when it is *primitive* (default). + + explicit : integer or byte + The EXPLICIT tag number (< 0x1F) to use for the encoded object. + It cannot be combined with the ``implicit`` parameter. + By default, there is no EXPLICIT tag. + """ + + if asn1Id is None: + # The tag octet will be read in with ``decode`` + self._tag_octet = None + return + asn1Id = self._convertTag(asn1Id) + + self.payload = payload + + # In a BER/DER identifier octet: + # * bits 4-0 contain the tag value + # * bit 5 is set if the type is 'constructed' + # and unset if 'primitive' + # * bits 7-6 depend on the encoding class + # + # Class | Bit 7, Bit 6 + # ---------------------------------- + # universal | 0 0 + # application | 0 1 + # context-spec | 1 0 (default for IMPLICIT/EXPLICIT) + # private | 1 1 + # + + constructed_bit = 0x20 if constructed else 0x00 + + if None not in (explicit, implicit): + raise ValueError( + "Explicit and implicit tags are mutually exclusive", + ) + + if implicit is not None: + # IMPLICIT tag overrides asn1Id + self._tag_octet = 0x80 | constructed_bit | self._convertTag(implicit) + elif explicit is not None: + # 'constructed bit' is always asserted for an EXPLICIT tag + self._tag_octet = 0x80 | 0x20 | self._convertTag(explicit) + self._inner_tag_octet = constructed_bit | asn1Id + else: + # Neither IMPLICIT nor EXPLICIT + self._tag_octet = constructed_bit | asn1Id + + def _convertTag(self, tag): + """Check if *tag* is a real DER tag (5 bits). + Convert it from a character to number if necessary. + """ + if not _is_number(tag): + if len(tag) == 1: + tag = bord(tag[0]) + # Ensure that tag is a low tag + if not (_is_number(tag) and 0 <= tag < 0x1F): + raise ValueError("Wrong DER tag") + return tag + + @staticmethod + def _definite_form(length): + """Build length octets according to BER/DER + definite form. + """ + if length > 127: + encoding = long_to_bytes(length) + return bchr(len(encoding) + 128) + encoding + return bchr(length) + + def encode(self): + """Return this DER element, fully encoded as a binary byte string.""" + + # Concatenate identifier octets, length octets, + # and contents octets + + output_payload = self.payload + + # In case of an EXTERNAL tag, first encode the inner + # element. + if hasattr(self, "_inner_tag_octet"): + output_payload = ( + bchr(self._inner_tag_octet) + self._definite_form(len(self.payload)) + self.payload + ) + + return bchr(self._tag_octet) + self._definite_form(len(output_payload)) + output_payload + + def _decodeLen(self, s): + """Decode DER length octets from a file.""" + + length = s.read_byte() + + if length > 127: + encoded_length = s.read(length & 0x7F) + if bord(encoded_length[0]) == 0: + raise ValueError("Invalid DER: length has leading zero") + length = bytes_to_long(encoded_length) + if length <= 127: + raise ValueError("Invalid DER: length in long form but smaller than 128") + + return length + + def decode(self, der_encoded, strict=False): + """Decode a complete DER element, and re-initializes this + object with it. + + Args: + der_encoded (byte string): A complete DER element. + + Raises: + ValueError: in case of parsing errors. + """ + + if not byte_string(der_encoded): + raise ValueError("Input is not a byte string") + + s = BytesIO_EOF(der_encoded) + self._decodeFromStream(s, strict) + + # There shouldn't be other bytes left + if s.remaining_data() > 0: + raise ValueError("Unexpected extra data after the DER structure") + + return self + + def _decodeFromStream(self, s, strict): + """Decode a complete DER element from a file.""" + + idOctet = s.read_byte() + if self._tag_octet is not None: + if idOctet != self._tag_octet: + raise ValueError("Unexpected DER tag") + else: + self._tag_octet = idOctet + length = self._decodeLen(s) + self.payload = s.read(length) + + # In case of an EXTERNAL tag, further decode the inner + # element. + if hasattr(self, "_inner_tag_octet"): + p = BytesIO_EOF(self.payload) + inner_octet = p.read_byte() + if inner_octet != self._inner_tag_octet: + raise ValueError("Unexpected internal DER tag") + length = self._decodeLen(p) + self.payload = p.read(length) + + # There shouldn't be other bytes left + if p.remaining_data() > 0: + raise ValueError("Unexpected extra data after the DER structure") class DerInteger(DerObject): - """Class to model a DER INTEGER. - - An example of encoding is:: - - >>> from Cryptodome.Util.asn1 import DerInteger - >>> from binascii import hexlify, unhexlify - >>> int_der = DerInteger(9) - >>> print hexlify(int_der.encode()) - - which will show ``020109``, the DER encoding of 9. - - And for decoding:: - - >>> s = unhexlify(b'020109') - >>> try: - >>> int_der = DerInteger() - >>> int_der.decode(s) - >>> print int_der.value - >>> except ValueError: - >>> print "Not a valid DER INTEGER" - - the output will be ``9``. - - :ivar value: The integer value - :vartype value: integer - """ - - def __init__(self, value=0, implicit=None, explicit=None): - """Initialize the DER object as an INTEGER. - - :Parameters: - value : integer - The value of the integer. - - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for INTEGER (2). - """ - - DerObject.__init__(self, 0x02, b'', implicit, - False, explicit) - self.value = value # The integer value - - def encode(self): - """Return the DER INTEGER, fully encoded as a - binary string.""" - - number = self.value - self.payload = b'' - while True: - self.payload = bchr(int(number & 255)) + self.payload - if 128 <= number <= 255: - self.payload = bchr(0x00) + self.payload - if -128 <= number <= 255: - break - number >>= 8 - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False): - """Decode a DER-encoded INTEGER, and re-initializes this - object with it. - - Args: - der_encoded (byte string): A complete INTEGER DER element. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict=strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER INTEGER from a file.""" - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - if strict: - if len(self.payload) == 0: - raise ValueError("Invalid encoding for DER INTEGER: empty payload") - if len(self.payload) >= 2 and struct.unpack('>H', self.payload[:2])[0] < 0x80: - raise ValueError("Invalid encoding for DER INTEGER: leading zero") - - # Derive self.value from self.payload - self.value = 0 - bits = 1 - for i in self.payload: - self.value *= 256 - self.value += bord(i) - bits <<= 8 - if self.payload and bord(self.payload[0]) & 0x80: - self.value -= bits + """Class to model a DER INTEGER. + + An example of encoding is:: + + >>> from Cryptodome.Util.asn1 import DerInteger + >>> from binascii import hexlify, unhexlify + >>> int_der = DerInteger(9) + >>> print hexlify(int_der.encode()) + + which will show ``020109``, the DER encoding of 9. + + And for decoding:: + + >>> s = unhexlify(b'020109') + >>> try: + >>> int_der = DerInteger() + >>> int_der.decode(s) + >>> print int_der.value + >>> except ValueError: + >>> print "Not a valid DER INTEGER" + + the output will be ``9``. + + :ivar value: The integer value + :vartype value: integer + """ + + def __init__(self, value=0, implicit=None, explicit=None): + """Initialize the DER object as an INTEGER. + + :Parameters: + value : integer + The value of the integer. + + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for INTEGER (2). + """ + + DerObject.__init__( + self, + 0x02, + b"", + implicit, + False, + explicit, + ) + self.value = value # The integer value + + def encode(self): + """Return the DER INTEGER, fully encoded as a + binary string.""" + + number = self.value + self.payload = b"" + while True: + self.payload = bchr(int(number & 255)) + self.payload + if 128 <= number <= 255: + self.payload = bchr(0x00) + self.payload + if -128 <= number <= 255: + break + number >>= 8 + return DerObject.encode(self) + + def decode(self, der_encoded, strict=False): + """Decode a DER-encoded INTEGER, and re-initializes this + object with it. + + Args: + der_encoded (byte string): A complete INTEGER DER element. + + Raises: + ValueError: in case of parsing errors. + """ + + return DerObject.decode(self, der_encoded, strict=strict) + + def _decodeFromStream(self, s, strict): + """Decode a complete DER INTEGER from a file.""" + + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) + + if strict: + if len(self.payload) == 0: + raise ValueError("Invalid encoding for DER INTEGER: empty payload") + if len(self.payload) >= 2 and struct.unpack(">H", self.payload[:2])[0] < 0x80: + raise ValueError("Invalid encoding for DER INTEGER: leading zero") + + # Derive self.value from self.payload + self.value = 0 + bits = 1 + for i in self.payload: + self.value *= 256 + self.value += bord(i) + bits <<= 8 + if self.payload and bord(self.payload[0]) & 0x80: + self.value -= bits class DerBoolean(DerObject): - """Class to model a DER-encoded BOOLEAN. + """Class to model a DER-encoded BOOLEAN. - An example of encoding is:: + An example of encoding is:: - >>> from Cryptodome.Util.asn1 import DerBoolean - >>> bool_der = DerBoolean(True) - >>> print(bool_der.encode().hex()) + >>> from Cryptodome.Util.asn1 import DerBoolean + >>> bool_der = DerBoolean(True) + >>> print(bool_der.encode().hex()) - which will show ``0101ff``, the DER encoding of True. + which will show ``0101ff``, the DER encoding of True. - And for decoding:: + And for decoding:: - >>> s = bytes.fromhex('0101ff') - >>> try: - >>> bool_der = DerBoolean() - >>> bool_der.decode(s) - >>> print(bool_der.value) - >>> except ValueError: - >>> print "Not a valid DER BOOLEAN" + >>> s = bytes.fromhex('0101ff') + >>> try: + >>> bool_der = DerBoolean() + >>> bool_der.decode(s) + >>> print(bool_der.value) + >>> except ValueError: + >>> print "Not a valid DER BOOLEAN" - the output will be ``True``. + the output will be ``True``. - :ivar value: The boolean value - :vartype value: boolean - """ - def __init__(self, value=False, implicit=None, explicit=None): - """Initialize the DER object as a BOOLEAN. + :ivar value: The boolean value + :vartype value: boolean + """ - Args: - value (boolean): - The value of the boolean. Default is False. + def __init__(self, value=False, implicit=None, explicit=None): + """Initialize the DER object as a BOOLEAN. - implicit (integer or byte): - The IMPLICIT tag number (< 0x1F) to use for the encoded object. - It overrides the universal tag for BOOLEAN (1). - It cannot be combined with the ``explicit`` parameter. - By default, there is no IMPLICIT tag. + Args: + value (boolean): + The value of the boolean. Default is False. - explicit (integer or byte): - The EXPLICIT tag number (< 0x1F) to use for the encoded object. - It cannot be combined with the ``implicit`` parameter. - By default, there is no EXPLICIT tag. - """ + implicit (integer or byte): + The IMPLICIT tag number (< 0x1F) to use for the encoded object. + It overrides the universal tag for BOOLEAN (1). + It cannot be combined with the ``explicit`` parameter. + By default, there is no IMPLICIT tag. - DerObject.__init__(self, 0x01, b'', implicit, False, explicit) - self.value = value # The boolean value + explicit (integer or byte): + The EXPLICIT tag number (< 0x1F) to use for the encoded object. + It cannot be combined with the ``implicit`` parameter. + By default, there is no EXPLICIT tag. + """ - def encode(self): - """Return the DER BOOLEAN, fully encoded as a binary string.""" + DerObject.__init__(self, 0x01, b"", implicit, False, explicit) + self.value = value # The boolean value - self.payload = b'\xFF' if self.value else b'\x00' - return DerObject.encode(self) + def encode(self): + """Return the DER BOOLEAN, fully encoded as a binary string.""" - def decode(self, der_encoded, strict=False): - """Decode a DER-encoded BOOLEAN, and re-initializes this object with it. + self.payload = b"\xff" if self.value else b"\x00" + return DerObject.encode(self) - Args: - der_encoded (byte string): A DER-encoded BOOLEAN. + def decode(self, der_encoded, strict=False): + """Decode a DER-encoded BOOLEAN, and re-initializes this object with it. - Raises: - ValueError: in case of parsing errors. - """ + Args: + der_encoded (byte string): A DER-encoded BOOLEAN. - return DerObject.decode(self, der_encoded, strict) + Raises: + ValueError: in case of parsing errors. + """ - def _decodeFromStream(self, s, strict): - """Decode a DER-encoded BOOLEAN from a file.""" + return DerObject.decode(self, der_encoded, strict) - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) + def _decodeFromStream(self, s, strict): + """Decode a DER-encoded BOOLEAN from a file.""" - if len(self.payload) != 1: - raise ValueError("Invalid encoding for DER BOOLEAN: payload is not 1 byte") + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) - if bord(self.payload[0]) == 0: - self.value = False - elif bord(self.payload[0]) == 0xFF: - self.value = True - else: - raise ValueError("Invalid payload for DER BOOLEAN") + if len(self.payload) != 1: + raise ValueError("Invalid encoding for DER BOOLEAN: payload is not 1 byte") + if bord(self.payload[0]) == 0: + self.value = False + elif bord(self.payload[0]) == 0xFF: + self.value = True + else: + raise ValueError("Invalid payload for DER BOOLEAN") -class DerSequence(DerObject): - """Class to model a DER SEQUENCE. - This object behaves like a dynamic Python sequence. +class DerSequence(DerObject): + """Class to model a DER SEQUENCE. - Sub-elements that are INTEGERs behave like Python integers. + This object behaves like a dynamic Python sequence. - Any other sub-element is a binary string encoded as a complete DER - sub-element (TLV). + Sub-elements that are INTEGERs behave like Python integers. - An example of encoding is: + Any other sub-element is a binary string encoded as a complete DER + sub-element (TLV). - >>> from Cryptodome.Util.asn1 import DerSequence, DerInteger - >>> from binascii import hexlify, unhexlify - >>> obj_der = unhexlify('070102') - >>> seq_der = DerSequence([4]) - >>> seq_der.append(9) - >>> seq_der.append(obj_der.encode()) - >>> print hexlify(seq_der.encode()) + An example of encoding is: - which will show ``3009020104020109070102``, the DER encoding of the - sequence containing ``4``, ``9``, and the object with payload ``02``. + >>> from Cryptodome.Util.asn1 import DerSequence, DerInteger + >>> from binascii import hexlify, unhexlify + >>> obj_der = unhexlify('070102') + >>> seq_der = DerSequence([4]) + >>> seq_der.append(9) + >>> seq_der.append(obj_der.encode()) + >>> print hexlify(seq_der.encode()) - For decoding: + which will show ``3009020104020109070102``, the DER encoding of the + sequence containing ``4``, ``9``, and the object with payload ``02``. - >>> s = unhexlify(b'3009020104020109070102') - >>> try: - >>> seq_der = DerSequence() - >>> seq_der.decode(s) - >>> print len(seq_der) - >>> print seq_der[0] - >>> print seq_der[:] - >>> except ValueError: - >>> print "Not a valid DER SEQUENCE" + For decoding: - the output will be:: + >>> s = unhexlify(b'3009020104020109070102') + >>> try: + >>> seq_der = DerSequence() + >>> seq_der.decode(s) + >>> print len(seq_der) + >>> print seq_der[0] + >>> print seq_der[:] + >>> except ValueError: + >>> print "Not a valid DER SEQUENCE" - 3 - 4 - [4, 9, b'\x07\x01\x02'] + the output will be:: - """ + 3 + 4 + [4, 9, b'\x07\x01\x02'] - def __init__(self, startSeq=None, implicit=None, explicit=None): - """Initialize the DER object as a SEQUENCE. - - :Parameters: - startSeq : Python sequence - A sequence whose element are either integers or - other DER objects. + """ - implicit : integer or byte - The IMPLICIT tag number (< 0x1F) to use for the encoded object. - It overrides the universal tag for SEQUENCE (16). - It cannot be combined with the ``explicit`` parameter. - By default, there is no IMPLICIT tag. - - explicit : integer or byte - The EXPLICIT tag number (< 0x1F) to use for the encoded object. - It cannot be combined with the ``implicit`` parameter. - By default, there is no EXPLICIT tag. - """ - - DerObject.__init__(self, 0x10, b'', implicit, True, explicit) - if startSeq is None: - self._seq = [] - else: - self._seq = startSeq - - # A few methods to make it behave like a python sequence - - def __delitem__(self, n): - del self._seq[n] - - def __getitem__(self, n): - return self._seq[n] - - def __setitem__(self, key, value): - self._seq[key] = value + def __init__(self, startSeq=None, implicit=None, explicit=None): + """Initialize the DER object as a SEQUENCE. + + :Parameters: + startSeq : Python sequence + A sequence whose element are either integers or + other DER objects. - def __setslice__(self, i, j, sequence): - self._seq[i:j] = sequence + implicit : integer or byte + The IMPLICIT tag number (< 0x1F) to use for the encoded object. + It overrides the universal tag for SEQUENCE (16). + It cannot be combined with the ``explicit`` parameter. + By default, there is no IMPLICIT tag. + + explicit : integer or byte + The EXPLICIT tag number (< 0x1F) to use for the encoded object. + It cannot be combined with the ``implicit`` parameter. + By default, there is no EXPLICIT tag. + """ + + DerObject.__init__(self, 0x10, b"", implicit, True, explicit) + if startSeq is None: + self._seq = [] + else: + self._seq = startSeq + + # A few methods to make it behave like a python sequence + + def __delitem__(self, n): + del self._seq[n] + + def __getitem__(self, n): + return self._seq[n] + + def __setitem__(self, key, value): + self._seq[key] = value - def __delslice__(self, i, j): - del self._seq[i:j] + def __setslice__(self, i, j, sequence): + self._seq[i:j] = sequence - def __getslice__(self, i, j): - return self._seq[max(0, i):max(0, j)] + def __delslice__(self, i, j): + del self._seq[i:j] - def __len__(self): - return len(self._seq) + def __getslice__(self, i, j): + return self._seq[max(0, i) : max(0, j)] - def __iadd__(self, item): - self._seq.append(item) - return self + def __len__(self): + return len(self._seq) - def append(self, item): - self._seq.append(item) - return self - - def insert(self, index, item): - self._seq.insert(index, item) - return self - - def hasInts(self, only_non_negative=True): - """Return the number of items in this sequence that are - integers. - - Args: - only_non_negative (boolean): - If ``True``, negative integers are not counted in. - """ - - items = [x for x in self._seq if _is_number(x, only_non_negative)] - return len(items) - - def hasOnlyInts(self, only_non_negative=True): - """Return ``True`` if all items in this sequence are integers - or non-negative integers. - - This function returns False is the sequence is empty, - or at least one member is not an integer. - - Args: - only_non_negative (boolean): - If ``True``, the presence of negative integers - causes the method to return ``False``.""" - return self._seq and self.hasInts(only_non_negative) == len(self._seq) - - def encode(self): - """Return this DER SEQUENCE, fully encoded as a - binary string. - - Raises: - ValueError: if some elements in the sequence are neither integers - nor byte strings. - """ - self.payload = b'' - for item in self._seq: - if byte_string(item): - self.payload += item - elif _is_number(item): - self.payload += DerInteger(item).encode() - else: - self.payload += item.encode() - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False, nr_elements=None, only_ints_expected=False): - """Decode a complete DER SEQUENCE, and re-initializes this - object with it. - - Args: - der_encoded (byte string): - A complete SEQUENCE DER element. - nr_elements (None or integer or list of integers): - The number of members the SEQUENCE can have - only_ints_expected (boolean): - Whether the SEQUENCE is expected to contain only integers. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - - DER INTEGERs are decoded into Python integers. Any other DER - element is not decoded. Its validity is not checked. - """ + def __iadd__(self, item): + self._seq.append(item) + return self - self._nr_elements = nr_elements - result = DerObject.decode(self, der_encoded, strict=strict) + def append(self, item): + self._seq.append(item) + return self + + def insert(self, index, item): + self._seq.insert(index, item) + return self + + def hasInts(self, only_non_negative=True): + """Return the number of items in this sequence that are + integers. + + Args: + only_non_negative (boolean): + If ``True``, negative integers are not counted in. + """ + + items = [x for x in self._seq if _is_number(x, only_non_negative)] + return len(items) + + def hasOnlyInts(self, only_non_negative=True): + """Return ``True`` if all items in this sequence are integers + or non-negative integers. + + This function returns False is the sequence is empty, + or at least one member is not an integer. + + Args: + only_non_negative (boolean): + If ``True``, the presence of negative integers + causes the method to return ``False``.""" + return self._seq and self.hasInts(only_non_negative) == len(self._seq) + + def encode(self): + """Return this DER SEQUENCE, fully encoded as a + binary string. + + Raises: + ValueError: if some elements in the sequence are neither integers + nor byte strings. + """ + self.payload = b"" + for item in self._seq: + if byte_string(item): + self.payload += item + elif _is_number(item): + self.payload += DerInteger(item).encode() + else: + self.payload += item.encode() + return DerObject.encode(self) + + def decode(self, der_encoded, strict=False, nr_elements=None, only_ints_expected=False): + """Decode a complete DER SEQUENCE, and re-initializes this + object with it. + + Args: + der_encoded (byte string): + A complete SEQUENCE DER element. + nr_elements (None or integer or list of integers): + The number of members the SEQUENCE can have + only_ints_expected (boolean): + Whether the SEQUENCE is expected to contain only integers. + strict (boolean): + Whether decoding must check for strict DER compliancy. + + Raises: + ValueError: in case of parsing errors. + + DER INTEGERs are decoded into Python integers. Any other DER + element is not decoded. Its validity is not checked. + """ - if only_ints_expected and not self.hasOnlyInts(): - raise ValueError("Some members are not INTEGERs") - - return result - - def _decodeFromStream(self, s, strict): - """Decode a complete DER SEQUENCE from a file.""" - - self._seq = [] - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - # Add one item at a time to self.seq, by scanning self.payload - p = BytesIO_EOF(self.payload) - while p.remaining_data() > 0: - p.set_bookmark() - - der = DerObject() - der._decodeFromStream(p, strict) - - # Parse INTEGERs differently - if der._tag_octet != 0x02: - self._seq.append(p.data_since_bookmark()) - else: - derInt = DerInteger() - data = p.data_since_bookmark() - derInt.decode(data, strict=strict) - self._seq.append(derInt.value) - - ok = True - if self._nr_elements is not None: - try: - ok = len(self._seq) in self._nr_elements - except TypeError: - ok = len(self._seq) == self._nr_elements - - if not ok: - raise ValueError("Unexpected number of members (%d)" - " in the sequence" % len(self._seq)) + self._nr_elements = nr_elements + result = DerObject.decode(self, der_encoded, strict=strict) + + if only_ints_expected and not self.hasOnlyInts(): + raise ValueError("Some members are not INTEGERs") + + return result + + def _decodeFromStream(self, s, strict): + """Decode a complete DER SEQUENCE from a file.""" + + self._seq = [] + + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) + + # Add one item at a time to self.seq, by scanning self.payload + p = BytesIO_EOF(self.payload) + while p.remaining_data() > 0: + p.set_bookmark() + + der = DerObject() + der._decodeFromStream(p, strict) + + # Parse INTEGERs differently + if der._tag_octet != 0x02: + self._seq.append(p.data_since_bookmark()) + else: + derInt = DerInteger() + data = p.data_since_bookmark() + derInt.decode(data, strict=strict) + self._seq.append(derInt.value) + + ok = True + if self._nr_elements is not None: + try: + ok = len(self._seq) in self._nr_elements + except TypeError: + ok = len(self._seq) == self._nr_elements + + if not ok: + raise ValueError( + "Unexpected number of members (%d) in the sequence" % len(self._seq), + ) class DerOctetString(DerObject): - """Class to model a DER OCTET STRING. + """Class to model a DER OCTET STRING. - An example of encoding is: + An example of encoding is: - >>> from Cryptodome.Util.asn1 import DerOctetString - >>> from binascii import hexlify, unhexlify - >>> os_der = DerOctetString(b'\\xaa') - >>> os_der.payload += b'\\xbb' - >>> print hexlify(os_der.encode()) + >>> from Cryptodome.Util.asn1 import DerOctetString + >>> from binascii import hexlify, unhexlify + >>> os_der = DerOctetString(b'\\xaa') + >>> os_der.payload += b'\\xbb' + >>> print hexlify(os_der.encode()) - which will show ``0402aabb``, the DER encoding for the byte string - ``b'\\xAA\\xBB'``. + which will show ``0402aabb``, the DER encoding for the byte string + ``b'\\xAA\\xBB'``. - For decoding: + For decoding: - >>> s = unhexlify(b'0402aabb') - >>> try: - >>> os_der = DerOctetString() - >>> os_der.decode(s) - >>> print hexlify(os_der.payload) - >>> except ValueError: - >>> print "Not a valid DER OCTET STRING" + >>> s = unhexlify(b'0402aabb') + >>> try: + >>> os_der = DerOctetString() + >>> os_der.decode(s) + >>> print hexlify(os_der.payload) + >>> except ValueError: + >>> print "Not a valid DER OCTET STRING" - the output will be ``aabb``. + the output will be ``aabb``. - :ivar payload: The content of the string - :vartype payload: byte string - """ + :ivar payload: The content of the string + :vartype payload: byte string + """ - def __init__(self, value=b'', implicit=None): - """Initialize the DER object as an OCTET STRING. + def __init__(self, value=b"", implicit=None): + """Initialize the DER object as an OCTET STRING. - :Parameters: - value : byte string - The initial payload of the object. - If not specified, the payload is empty. + :Parameters: + value : byte string + The initial payload of the object. + If not specified, the payload is empty. - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for OCTET STRING (4). - """ - DerObject.__init__(self, 0x04, value, implicit, False) + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for OCTET STRING (4). + """ + DerObject.__init__(self, 0x04, value, implicit, False) class DerNull(DerObject): - """Class to model a DER NULL element.""" + """Class to model a DER NULL element.""" - def __init__(self): - """Initialize the DER object as a NULL.""" + def __init__(self): + """Initialize the DER object as a NULL.""" - DerObject.__init__(self, 0x05, b'', None, False) + DerObject.__init__(self, 0x05, b"", None, False) class DerObjectId(DerObject): - """Class to model a DER OBJECT ID. - - An example of encoding is: - - >>> from Cryptodome.Util.asn1 import DerObjectId - >>> from binascii import hexlify, unhexlify - >>> oid_der = DerObjectId("1.2") - >>> oid_der.value += ".840.113549.1.1.1" - >>> print hexlify(oid_der.encode()) - - which will show ``06092a864886f70d010101``, the DER encoding for the - RSA Object Identifier ``1.2.840.113549.1.1.1``. - - For decoding: - - >>> s = unhexlify(b'06092a864886f70d010101') - >>> try: - >>> oid_der = DerObjectId() - >>> oid_der.decode(s) - >>> print oid_der.value - >>> except ValueError: - >>> print "Not a valid DER OBJECT ID" - - the output will be ``1.2.840.113549.1.1.1``. - - :ivar value: The Object ID (OID), a dot separated list of integers - :vartype value: string - """ - - def __init__(self, value='', implicit=None, explicit=None): - """Initialize the DER object as an OBJECT ID. - - :Parameters: - value : string - The initial Object Identifier (e.g. "1.2.0.0.6.2"). - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for OBJECT ID (6). - explicit : integer - The EXPLICIT tag to use for the encoded object. - """ - DerObject.__init__(self, 0x06, b'', implicit, False, explicit) - self.value = value - - def encode(self): - """Return the DER OBJECT ID, fully encoded as a - binary string.""" - - comps = [int(x) for x in self.value.split(".")] - - if len(comps) < 2: - raise ValueError("Not a valid Object Identifier string") - if comps[0] > 2: - raise ValueError("First component must be 0, 1 or 2") - if comps[0] < 2 and comps[1] > 39: - raise ValueError("Second component must be 39 at most") - - subcomps = [40 * comps[0] + comps[1]] + comps[2:] - - encoding = [] - for v in reversed(subcomps): - encoding.append(v & 0x7F) - v >>= 7 - while v: - encoding.append((v & 0x7F) | 0x80) - v >>= 7 - - self.payload = b''.join([bchr(x) for x in reversed(encoding)]) - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False): - """Decode a complete DER OBJECT ID, and re-initializes this - object with it. - - Args: - der_encoded (byte string): - A complete DER OBJECT ID. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER OBJECT ID from a file.""" - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - # Derive self.value from self.payload - p = BytesIO_EOF(self.payload) - - subcomps = [] - v = 0 - while p.remaining_data(): - c = p.read_byte() - v = (v << 7) + (c & 0x7F) - if not (c & 0x80): - subcomps.append(v) - v = 0 - - if len(subcomps) == 0: - raise ValueError("Empty payload") - - if subcomps[0] < 40: - subcomps[:1] = [0, subcomps[0]] - elif subcomps[0] < 80: - subcomps[:1] = [1, subcomps[0] - 40] - else: - subcomps[:1] = [2, subcomps[0] - 80] - - self.value = ".".join([str(x) for x in subcomps]) + """Class to model a DER OBJECT ID. + + An example of encoding is: + + >>> from Cryptodome.Util.asn1 import DerObjectId + >>> from binascii import hexlify, unhexlify + >>> oid_der = DerObjectId("1.2") + >>> oid_der.value += ".840.113549.1.1.1" + >>> print hexlify(oid_der.encode()) + + which will show ``06092a864886f70d010101``, the DER encoding for the + RSA Object Identifier ``1.2.840.113549.1.1.1``. + + For decoding: + + >>> s = unhexlify(b'06092a864886f70d010101') + >>> try: + >>> oid_der = DerObjectId() + >>> oid_der.decode(s) + >>> print oid_der.value + >>> except ValueError: + >>> print "Not a valid DER OBJECT ID" + + the output will be ``1.2.840.113549.1.1.1``. + + :ivar value: The Object ID (OID), a dot separated list of integers + :vartype value: string + """ + + def __init__(self, value="", implicit=None, explicit=None): + """Initialize the DER object as an OBJECT ID. + + :Parameters: + value : string + The initial Object Identifier (e.g. "1.2.0.0.6.2"). + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for OBJECT ID (6). + explicit : integer + The EXPLICIT tag to use for the encoded object. + """ + DerObject.__init__(self, 0x06, b"", implicit, False, explicit) + self.value = value + + def encode(self): + """Return the DER OBJECT ID, fully encoded as a + binary string.""" + + comps = [int(x) for x in self.value.split(".")] + + if len(comps) < 2: + raise ValueError("Not a valid Object Identifier string") + if comps[0] > 2: + raise ValueError("First component must be 0, 1 or 2") + if comps[0] < 2 and comps[1] > 39: + raise ValueError("Second component must be 39 at most") + + subcomps = [40 * comps[0] + comps[1]] + comps[2:] + + encoding = [] + for v in reversed(subcomps): + encoding.append(v & 0x7F) + v >>= 7 + while v: + encoding.append((v & 0x7F) | 0x80) + v >>= 7 + + self.payload = b"".join([bchr(x) for x in reversed(encoding)]) + return DerObject.encode(self) + + def decode(self, der_encoded, strict=False): + """Decode a complete DER OBJECT ID, and re-initializes this + object with it. + + Args: + der_encoded (byte string): + A complete DER OBJECT ID. + strict (boolean): + Whether decoding must check for strict DER compliancy. + + Raises: + ValueError: in case of parsing errors. + """ + + return DerObject.decode(self, der_encoded, strict) + + def _decodeFromStream(self, s, strict): + """Decode a complete DER OBJECT ID from a file.""" + + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) + + # Derive self.value from self.payload + p = BytesIO_EOF(self.payload) + + subcomps = [] + v = 0 + while p.remaining_data(): + c = p.read_byte() + v = (v << 7) + (c & 0x7F) + if not (c & 0x80): + subcomps.append(v) + v = 0 + + if len(subcomps) == 0: + raise ValueError("Empty payload") + + if subcomps[0] < 40: + subcomps[:1] = [0, subcomps[0]] + elif subcomps[0] < 80: + subcomps[:1] = [1, subcomps[0] - 40] + else: + subcomps[:1] = [2, subcomps[0] - 80] + + self.value = ".".join([str(x) for x in subcomps]) class DerBitString(DerObject): - """Class to model a DER BIT STRING. + """Class to model a DER BIT STRING. - An example of encoding is: + An example of encoding is: - >>> from Cryptodome.Util.asn1 import DerBitString - >>> bs_der = DerBitString(b'\\xAA') - >>> bs_der.value += b'\\xBB' - >>> print(bs_der.encode().hex()) + >>> from Cryptodome.Util.asn1 import DerBitString + >>> bs_der = DerBitString(b'\\xAA') + >>> bs_der.value += b'\\xBB' + >>> print(bs_der.encode().hex()) - which will show ``030300aabb``, the DER encoding for the bit string - ``b'\\xAA\\xBB'``. + which will show ``030300aabb``, the DER encoding for the bit string + ``b'\\xAA\\xBB'``. - For decoding: + For decoding: - >>> s = bytes.fromhex('030300aabb') - >>> try: - >>> bs_der = DerBitString() - >>> bs_der.decode(s) - >>> print(bs_der.value.hex()) - >>> except ValueError: - >>> print "Not a valid DER BIT STRING" + >>> s = bytes.fromhex('030300aabb') + >>> try: + >>> bs_der = DerBitString() + >>> bs_der.decode(s) + >>> print(bs_der.value.hex()) + >>> except ValueError: + >>> print "Not a valid DER BIT STRING" - the output will be ``aabb``. + the output will be ``aabb``. - :ivar value: The content of the string - :vartype value: byte string - """ + :ivar value: The content of the string + :vartype value: byte string + """ - def __init__(self, value=b'', implicit=None, explicit=None): - """Initialize the DER object as a BIT STRING. + def __init__(self, value=b"", implicit=None, explicit=None): + """Initialize the DER object as a BIT STRING. - :Parameters: - value : byte string or DER object - The initial, packed bit string. - If not specified, the bit string is empty. - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for BIT STRING (3). - explicit : integer - The EXPLICIT tag to use for the encoded object. - """ - DerObject.__init__(self, 0x03, b'', implicit, False, explicit) + :Parameters: + value : byte string or DER object + The initial, packed bit string. + If not specified, the bit string is empty. + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for BIT STRING (3). + explicit : integer + The EXPLICIT tag to use for the encoded object. + """ + DerObject.__init__(self, 0x03, b"", implicit, False, explicit) - # The bitstring value (packed) - if isinstance(value, DerObject): - self.value = value.encode() - else: - self.value = value + # The bitstring value (packed) + if isinstance(value, DerObject): + self.value = value.encode() + else: + self.value = value - def encode(self): - """Return the DER BIT STRING, fully encoded as a - byte string.""" + def encode(self): + """Return the DER BIT STRING, fully encoded as a + byte string.""" - # Add padding count byte - self.payload = b'\x00' + self.value - return DerObject.encode(self) + # Add padding count byte + self.payload = b"\x00" + self.value + return DerObject.encode(self) - def decode(self, der_encoded, strict=False): - """Decode a complete DER BIT STRING, and re-initializes this - object with it. + def decode(self, der_encoded, strict=False): + """Decode a complete DER BIT STRING, and re-initializes this + object with it. - Args: - der_encoded (byte string): a complete DER BIT STRING. - strict (boolean): - Whether decoding must check for strict DER compliancy. + Args: + der_encoded (byte string): a complete DER BIT STRING. + strict (boolean): + Whether decoding must check for strict DER compliancy. - Raises: - ValueError: in case of parsing errors. - """ + Raises: + ValueError: in case of parsing errors. + """ - return DerObject.decode(self, der_encoded, strict) + return DerObject.decode(self, der_encoded, strict) - def _decodeFromStream(self, s, strict): - """Decode a complete DER BIT STRING DER from a file.""" + def _decodeFromStream(self, s, strict): + """Decode a complete DER BIT STRING DER from a file.""" - # Fill-up self.payload - DerObject._decodeFromStream(self, s, strict) + # Fill-up self.payload + DerObject._decodeFromStream(self, s, strict) - if self.payload and bord(self.payload[0]) != 0: - raise ValueError("Not a valid BIT STRING") + if self.payload and bord(self.payload[0]) != 0: + raise ValueError("Not a valid BIT STRING") - # Fill-up self.value - self.value = b'' - # Remove padding count byte - if self.payload: - self.value = self.payload[1:] + # Fill-up self.value + self.value = b"" + # Remove padding count byte + if self.payload: + self.value = self.payload[1:] class DerSetOf(DerObject): - """Class to model a DER SET OF. + """Class to model a DER SET OF. - An example of encoding is: + An example of encoding is: - >>> from Cryptodome.Util.asn1 import DerBitString - >>> from binascii import hexlify, unhexlify - >>> so_der = DerSetOf([4,5]) - >>> so_der.add(6) - >>> print hexlify(so_der.encode()) + >>> from Cryptodome.Util.asn1 import DerBitString + >>> from binascii import hexlify, unhexlify + >>> so_der = DerSetOf([4,5]) + >>> so_der.add(6) + >>> print hexlify(so_der.encode()) - which will show ``3109020104020105020106``, the DER encoding - of a SET OF with items 4,5, and 6. + which will show ``3109020104020105020106``, the DER encoding + of a SET OF with items 4,5, and 6. - For decoding: + For decoding: - >>> s = unhexlify(b'3109020104020105020106') - >>> try: - >>> so_der = DerSetOf() - >>> so_der.decode(s) - >>> print [x for x in so_der] - >>> except ValueError: - >>> print "Not a valid DER SET OF" + >>> s = unhexlify(b'3109020104020105020106') + >>> try: + >>> so_der = DerSetOf() + >>> so_der.decode(s) + >>> print [x for x in so_der] + >>> except ValueError: + >>> print "Not a valid DER SET OF" - the output will be ``[4, 5, 6]``. - """ - - def __init__(self, startSet=None, implicit=None): - """Initialize the DER object as a SET OF. - - :Parameters: - startSet : container - The initial set of integers or DER encoded objects. - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for SET OF (17). - """ - DerObject.__init__(self, 0x11, b'', implicit, True) - self._seq = [] - - # All elements must be of the same type (and therefore have the - # same leading octet) - self._elemOctet = None - - if startSet: - for e in startSet: - self.add(e) - - def __getitem__(self, n): - return self._seq[n] - - def __iter__(self): - return iter(self._seq) - - def __len__(self): - return len(self._seq) - - def add(self, elem): - """Add an element to the set. - - Args: - elem (byte string or integer): - An element of the same type of objects already in the set. - It can be an integer or a DER encoded object. - """ - - if _is_number(elem): - eo = 0x02 - elif isinstance(elem, DerObject): - eo = self._tag_octet - else: - eo = bord(elem[0]) - - if self._elemOctet != eo: - if self._elemOctet is not None: - raise ValueError("New element does not belong to the set") - self._elemOctet = eo - - if elem not in self._seq: - self._seq.append(elem) - - def decode(self, der_encoded, strict=False): - """Decode a complete SET OF DER element, and re-initializes this - object with it. - - DER INTEGERs are decoded into Python integers. Any other DER - element is left undecoded; its validity is not checked. - - Args: - der_encoded (byte string): a complete DER BIT SET OF. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER SET OF from a file.""" - - self._seq = [] - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - # Add one item at a time to self.seq, by scanning self.payload - p = BytesIO_EOF(self.payload) - setIdOctet = -1 - while p.remaining_data() > 0: - p.set_bookmark() - - der = DerObject() - der._decodeFromStream(p, strict) - - # Verify that all members are of the same type - if setIdOctet < 0: - setIdOctet = der._tag_octet - else: - if setIdOctet != der._tag_octet: - raise ValueError("Not all elements are of the same DER type") - - # Parse INTEGERs differently - if setIdOctet != 0x02: - self._seq.append(p.data_since_bookmark()) - else: - derInt = DerInteger() - derInt.decode(p.data_since_bookmark(), strict) - self._seq.append(derInt.value) - # end - - def encode(self): - """Return this SET OF DER element, fully encoded as a - binary string. - """ - - # Elements in the set must be ordered in lexicographic order - ordered = [] - for item in self._seq: - if _is_number(item): - bys = DerInteger(item).encode() - elif isinstance(item, DerObject): - bys = item.encode() - else: - bys = item - ordered.append(bys) - ordered.sort() - self.payload = b''.join(ordered) - return DerObject.encode(self) + the output will be ``[4, 5, 6]``. + """ + + def __init__(self, startSet=None, implicit=None): + """Initialize the DER object as a SET OF. + + :Parameters: + startSet : container + The initial set of integers or DER encoded objects. + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for SET OF (17). + """ + DerObject.__init__(self, 0x11, b"", implicit, True) + self._seq = [] + + # All elements must be of the same type (and therefore have the + # same leading octet) + self._elemOctet = None + + if startSet: + for e in startSet: + self.add(e) + + def __getitem__(self, n): + return self._seq[n] + + def __iter__(self): + return iter(self._seq) + + def __len__(self): + return len(self._seq) + + def add(self, elem): + """Add an element to the set. + + Args: + elem (byte string or integer): + An element of the same type of objects already in the set. + It can be an integer or a DER encoded object. + """ + + if _is_number(elem): + eo = 0x02 + elif isinstance(elem, DerObject): + eo = self._tag_octet + else: + eo = bord(elem[0]) + + if self._elemOctet != eo: + if self._elemOctet is not None: + raise ValueError("New element does not belong to the set") + self._elemOctet = eo + + if elem not in self._seq: + self._seq.append(elem) + + def decode(self, der_encoded, strict=False): + """Decode a complete SET OF DER element, and re-initializes this + object with it. + + DER INTEGERs are decoded into Python integers. Any other DER + element is left undecoded; its validity is not checked. + + Args: + der_encoded (byte string): a complete DER BIT SET OF. + strict (boolean): + Whether decoding must check for strict DER compliancy. + + Raises: + ValueError: in case of parsing errors. + """ + + return DerObject.decode(self, der_encoded, strict) + + def _decodeFromStream(self, s, strict): + """Decode a complete DER SET OF from a file.""" + + self._seq = [] + + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) + + # Add one item at a time to self.seq, by scanning self.payload + p = BytesIO_EOF(self.payload) + setIdOctet = -1 + while p.remaining_data() > 0: + p.set_bookmark() + + der = DerObject() + der._decodeFromStream(p, strict) + + # Verify that all members are of the same type + if setIdOctet < 0: + setIdOctet = der._tag_octet + else: + if setIdOctet != der._tag_octet: + raise ValueError("Not all elements are of the same DER type") + + # Parse INTEGERs differently + if setIdOctet != 0x02: + self._seq.append(p.data_since_bookmark()) + else: + derInt = DerInteger() + derInt.decode(p.data_since_bookmark(), strict) + self._seq.append(derInt.value) + # end + + def encode(self): + """Return this SET OF DER element, fully encoded as a + binary string. + """ + + # Elements in the set must be ordered in lexicographic order + ordered = [] + for item in self._seq: + if _is_number(item): + bys = DerInteger(item).encode() + elif isinstance(item, DerObject): + bys = item.encode() + else: + bys = item + ordered.append(bys) + ordered.sort() + self.payload = b"".join(ordered) + return DerObject.encode(self) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/asn1.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/asn1.pyi index ee4891c5..b4fe4e7e 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/asn1.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/asn1.pyi @@ -1,80 +1,117 @@ from typing import Optional, Sequence, Union, Set, Iterable -__all__ = ['DerObject', 'DerInteger', 'DerOctetString', 'DerNull', - 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf'] +__all__ = [ + "DerObject", + "DerInteger", + "DerOctetString", + "DerNull", + "DerSequence", + "DerObjectId", + "DerBitString", + "DerSetOf", +] # TODO: Make the encoded DerObjects their own type, so that DerSequence and # DerSetOf can check their contents better class BytesIO_EOF: - def __init__(self, initial_bytes: bytes) -> None: ... - def set_bookmark(self) -> None: ... - def data_since_bookmark(self) -> bytes: ... - def remaining_data(self) -> int: ... - def read(self, length: int) -> bytes: ... - def read_byte(self) -> bytes: ... + def __init__(self, initial_bytes: bytes) -> None: ... + def set_bookmark(self) -> None: ... + def data_since_bookmark(self) -> bytes: ... + def remaining_data(self) -> int: ... + def read(self, length: int) -> bytes: ... + def read_byte(self) -> bytes: ... class DerObject: - payload: bytes - def __init__(self, asn1Id: Optional[int]=None, payload: Optional[bytes]=..., implicit: Optional[int]=None, - constructed: Optional[bool]=False, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerObject: ... + payload: bytes + def __init__( + self, + asn1Id: Optional[int] = None, + payload: Optional[bytes] = ..., + implicit: Optional[int] = None, + constructed: Optional[bool] = False, + explicit: Optional[int] = None, + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerObject: ... class DerInteger(DerObject): - value: int - def __init__(self, value: Optional[int]= 0, implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerInteger: ... + value: int + def __init__( + self, value: Optional[int] = 0, implicit: Optional[int] = None, explicit: Optional[int] = None + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerInteger: ... class DerBoolean(DerObject): - value: bool - def __init__(self, value: bool=..., implicit: Optional[Union[int, bytes]]=..., explicit: Optional[Union[int, bytes]]=...) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerBoolean: ... + value: bool + def __init__( + self, + value: bool = ..., + implicit: Optional[Union[int, bytes]] = ..., + explicit: Optional[Union[int, bytes]] = ..., + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerBoolean: ... class DerSequence(DerObject): - def __init__(self, startSeq: Optional[Sequence[Union[int, DerInteger, DerObject]]]=None, implicit: Optional[int]=None) -> None: ... - def __delitem__(self, n: int) -> None: ... - def __getitem__(self, n: int) -> None: ... - def __setitem__(self, key: int, value: DerObject) -> None: ... - def __setslice__(self, i: int, j: int, sequence: Sequence) -> None: ... - def __delslice__(self, i: int, j: int) -> None: ... - def __getslice__(self, i: int, j: int) -> DerSequence: ... - def __len__(self) -> int: ... - def __iadd__(self, item: DerObject) -> DerSequence: ... - def append(self, item: DerObject) -> DerSequence: ... - def hasInts(self, only_non_negative: Optional[bool]=True) -> int: ... - def hasOnlyInts(self, only_non_negative: Optional[bool]=True) -> bool: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=..., nr_elements: Optional[int]=None, only_ints_expected: Optional[bool]=False) -> DerSequence: ... + def __init__( + self, + startSeq: Optional[Sequence[Union[int, DerInteger, DerObject]]] = None, + implicit: Optional[int] = None, + ) -> None: ... + def __delitem__(self, n: int) -> None: ... + def __getitem__(self, n: int) -> None: ... + def __setitem__(self, key: int, value: DerObject) -> None: ... + def __setslice__(self, i: int, j: int, sequence: Sequence) -> None: ... + def __delslice__(self, i: int, j: int) -> None: ... + def __getslice__(self, i: int, j: int) -> DerSequence: ... + def __len__(self) -> int: ... + def __iadd__(self, item: DerObject) -> DerSequence: ... + def append(self, item: DerObject) -> DerSequence: ... + def hasInts(self, only_non_negative: Optional[bool] = True) -> int: ... + def hasOnlyInts(self, only_non_negative: Optional[bool] = True) -> bool: ... + def encode(self) -> bytes: ... + def decode( + self, + der_encoded: bytes, + strict: bool = ..., + nr_elements: Optional[int] = None, + only_ints_expected: Optional[bool] = False, + ) -> DerSequence: ... class DerOctetString(DerObject): - payload: bytes - def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None) -> None: ... + payload: bytes + def __init__(self, value: Optional[bytes] = ..., implicit: Optional[int] = None) -> None: ... class DerNull(DerObject): - def __init__(self) -> None: ... + def __init__(self) -> None: ... class DerObjectId(DerObject): - value: str - def __init__(self, value: Optional[str]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerObjectId: ... + value: str + def __init__( + self, value: Optional[str] = ..., implicit: Optional[int] = None, explicit: Optional[int] = None + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerObjectId: ... class DerBitString(DerObject): - value: bytes - def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerBitString: ... + value: bytes + def __init__( + self, value: Optional[bytes] = ..., implicit: Optional[int] = None, explicit: Optional[int] = None + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerBitString: ... DerSetElement = Union[bytes, int] class DerSetOf(DerObject): - def __init__(self, startSet: Optional[Set[DerSetElement]]=None, implicit: Optional[int]=None) -> None: ... - def __getitem__(self, n: int) -> DerSetElement: ... - def __iter__(self) -> Iterable: ... - def __len__(self) -> int: ... - def add(self, elem: DerSetElement) -> None: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerObject: ... - def encode(self) -> bytes: ... + def __init__( + self, startSet: Optional[Set[DerSetElement]] = None, implicit: Optional[int] = None + ) -> None: ... + def __getitem__(self, n: int) -> DerSetElement: ... + def __iter__(self) -> Iterable: ... + def __len__(self) -> int: ... + def add(self, elem: DerSetElement) -> None: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerObject: ... + def encode(self) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/number.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/number.py index 701c21c3..5e8aaa3b 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/number.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/number.py @@ -35,1491 +35,10504 @@ def ceil_div(n, d): - """Return ceil(n/d), that is, the smallest integer r such that r*d >= n""" + """Return ceil(n/d), that is, the smallest integer r such that r*d >= n""" - if d == 0: - raise ZeroDivisionError() - if (n < 0) or (d < 0): - raise ValueError("Non positive values") - r, q = divmod(n, d) - if (n != 0) and (q != 0): - r += 1 - return r + if d == 0: + raise ZeroDivisionError() + if (n < 0) or (d < 0): + raise ValueError("Non positive values") + r, q = divmod(n, d) + if (n != 0) and (q != 0): + r += 1 + return r -def size (N): - """Returns the size of the number N in bits.""" +def size(N): + """Returns the size of the number N in bits.""" - if N < 0: - raise ValueError("Size in bits only available for non-negative numbers") - return N.bit_length() + if N < 0: + raise ValueError("Size in bits only available for non-negative numbers") + return N.bit_length() def getRandomInteger(N, randfunc=None): - """Return a random number at most N bits long. + """Return a random number at most N bits long. - If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. + If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. Use :func:`Cryptodome.Random.random.getrandbits` instead. - """ + .. deprecated:: 3.0 + This function is for internal use only and may be renamed or removed in + the future. Use :func:`Cryptodome.Random.random.getrandbits` instead. + """ - if randfunc is None: - randfunc = Random.get_random_bytes + if randfunc is None: + randfunc = Random.get_random_bytes + + S = randfunc(N >> 3) + odd_bits = N % 8 + if odd_bits != 0: + rand_bits = ord(randfunc(1)) >> (8 - odd_bits) + S = struct.pack("B", rand_bits) + S + value = bytes_to_long(S) + return value - S = randfunc(N>>3) - odd_bits = N % 8 - if odd_bits != 0: - rand_bits = ord(randfunc(1)) >> (8-odd_bits) - S = struct.pack('B', rand_bits) + S - value = bytes_to_long(S) - return value def getRandomRange(a, b, randfunc=None): - """Return a random number *n* so that *a <= n < b*. + """Return a random number *n* so that *a <= n < b*. + + If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. - If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. + .. deprecated:: 3.0 + This function is for internal use only and may be renamed or removed in + the future. Use :func:`Cryptodome.Random.random.randrange` instead. + """ - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. Use :func:`Cryptodome.Random.random.randrange` instead. - """ + range_ = b - a - 1 + bits = size(range_) + value = getRandomInteger(bits, randfunc) + while value > range_: + value = getRandomInteger(bits, randfunc) + return a + value - range_ = b - a - 1 - bits = size(range_) - value = getRandomInteger(bits, randfunc) - while value > range_: - value = getRandomInteger(bits, randfunc) - return a + value def getRandomNBitInteger(N, randfunc=None): - """Return a random number with exactly N-bits, - i.e. a random number between 2**(N-1) and (2**N)-1. + """Return a random number with exactly N-bits, + i.e. a random number between 2**(N-1) and (2**N)-1. - If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. + If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. - """ + .. deprecated:: 3.0 + This function is for internal use only and may be renamed or removed in + the future. + """ - value = getRandomInteger (N-1, randfunc) - value |= 2 ** (N-1) # Ensure high bit is set - assert size(value) >= N - return value + value = getRandomInteger(N - 1, randfunc) + value |= 2 ** (N - 1) # Ensure high bit is set + assert size(value) >= N + return value if sys.version_info[:2] >= (3, 5): - - GCD = math.gcd + GCD = math.gcd else: - def GCD(x,y): - """Greatest Common Denominator of :data:`x` and :data:`y`. - """ + def GCD(x, y): + """Greatest Common Denominator of :data:`x` and :data:`y`.""" - x = abs(x) ; y = abs(y) - while x > 0: - x, y = y % x, x - return y + x = abs(x) + y = abs(y) + while x > 0: + x, y = y % x, x + return y if sys.version_info[:2] >= (3, 8): - def inverse(u, v): - """The inverse of :data:`u` *mod* :data:`v`.""" + def inverse(u, v): + """The inverse of :data:`u` *mod* :data:`v`.""" - if v == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if v < 0: - raise ValueError("Modulus cannot be negative") + if v == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if v < 0: + raise ValueError("Modulus cannot be negative") - return pow(u, -1, v) + return pow(u, -1, v) else: - def inverse(u, v): - """The inverse of :data:`u` *mod* :data:`v`.""" - - if v == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if v < 0: - raise ValueError("Modulus cannot be negative") - - u3, v3 = u, v - u1, v1 = 1, 0 - while v3 > 0: - q = u3 // v3 - u1, v1 = v1, u1 - v1*q - u3, v3 = v3, u3 - v3*q - if u3 != 1: - raise ValueError("No inverse value can be computed") - while u1<0: - u1 = u1 + v - return u1 + def inverse(u, v): + """The inverse of :data:`u` *mod* :data:`v`.""" + + if v == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if v < 0: + raise ValueError("Modulus cannot be negative") + + u3, v3 = u, v + u1, v1 = 1, 0 + while v3 > 0: + q = u3 // v3 + u1, v1 = v1, u1 - v1 * q + u3, v3 = v3, u3 - v3 * q + if u3 != 1: + raise ValueError("No inverse value can be computed") + while u1 < 0: + u1 = u1 + v + return u1 # Given a number of bits to generate and a random generation function, # find a prime number of the appropriate size. + def getPrime(N, randfunc=None): - """Return a random N-bit prime number. + """Return a random N-bit prime number. - N must be an integer larger than 1. - If randfunc is omitted, then :meth:`Random.get_random_bytes` is used. - """ - if randfunc is None: - randfunc = Random.get_random_bytes + N must be an integer larger than 1. + If randfunc is omitted, then :meth:`Random.get_random_bytes` is used. + """ + if randfunc is None: + randfunc = Random.get_random_bytes - if N < 2: - raise ValueError("N must be larger than 1") + if N < 2: + raise ValueError("N must be larger than 1") - while True: - number = getRandomNBitInteger(N, randfunc) | 1 - if isPrime(number, randfunc=randfunc): - break - return number + while True: + number = getRandomNBitInteger(N, randfunc) | 1 + if isPrime(number, randfunc=randfunc): + break + return number def _rabinMillerTest(n, rounds, randfunc=None): - """_rabinMillerTest(n:long, rounds:int, randfunc:callable):int - Tests if n is prime. - Returns 0 when n is definitely composite. - Returns 1 when n is probably prime. - Returns 2 when n is definitely prime. - - If randfunc is omitted, then Random.new().read is used. - - This function is for internal use only and may be renamed or removed in - the future. - """ - # check special cases (n==2, n even, n < 2) - if n < 3 or (n & 1) == 0: - return n == 2 - # n might be very large so it might be beneficial to precalculate n-1 - n_1 = n - 1 - # determine m and b so that 2**b * m = n - 1 and b maximal - b = 0 - m = n_1 - while (m & 1) == 0: - b += 1 - m >>= 1 - - tested = [] - # we need to do at most n-2 rounds. - for i in iter_range (min (rounds, n-2)): - # randomly choose a < n and make sure it hasn't been tested yet - a = getRandomRange (2, n, randfunc) - while a in tested: - a = getRandomRange (2, n, randfunc) - tested.append (a) - # do the rabin-miller test - z = pow (a, m, n) # (a**m) % n - if z == 1 or z == n_1: - continue - composite = 1 - for r in iter_range(b): - z = (z * z) % n - if z == 1: - return 0 - elif z == n_1: - composite = 0 - break - if composite: - return 0 - return 1 + """_rabinMillerTest(n:long, rounds:int, randfunc:callable):int + Tests if n is prime. + Returns 0 when n is definitely composite. + Returns 1 when n is probably prime. + Returns 2 when n is definitely prime. + + If randfunc is omitted, then Random.new().read is used. + + This function is for internal use only and may be renamed or removed in + the future. + """ + # check special cases (n==2, n even, n < 2) + if n < 3 or (n & 1) == 0: + return n == 2 + # n might be very large so it might be beneficial to precalculate n-1 + n_1 = n - 1 + # determine m and b so that 2**b * m = n - 1 and b maximal + b = 0 + m = n_1 + while (m & 1) == 0: + b += 1 + m >>= 1 + + tested = [] + # we need to do at most n-2 rounds. + for i in iter_range(min(rounds, n - 2)): + # randomly choose a < n and make sure it hasn't been tested yet + a = getRandomRange(2, n, randfunc) + while a in tested: + a = getRandomRange(2, n, randfunc) + tested.append(a) + # do the rabin-miller test + z = pow(a, m, n) # (a**m) % n + if z == 1 or z == n_1: + continue + composite = 1 + for r in iter_range(b): + z = (z * z) % n + if z == 1: + return 0 + elif z == n_1: + composite = 0 + break + if composite: + return 0 + return 1 + def getStrongPrime(N, e=0, false_positive_prob=1e-6, randfunc=None): - r""" - Return a random strong *N*-bit prime number. - In this context, *p* is a strong prime if *p-1* and *p+1* have at - least one large prime factor. - - Args: - N (integer): the exact length of the strong prime. - It must be a multiple of 128 and > 512. - e (integer): if provided, the returned prime (minus 1) - will be coprime to *e* and thus suitable for RSA where - *e* is the public exponent. - false_positive_prob (float): - The statistical probability for the result not to be actually a - prime. It defaults to 10\ :sup:`-6`. - Note that the real probability of a false-positive is far less. This is - just the mathematically provable limit. - randfunc (callable): - A function that takes a parameter *N* and that returns - a random byte string of such length. - If omitted, :func:`Cryptodome.Random.get_random_bytes` is used. - Return: - The new strong prime. - - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. - """ - - # This function was implemented following the - # instructions found in the paper: - # "FAST GENERATION OF RANDOM, STRONG RSA PRIMES" - # by Robert D. Silverman - # RSA Laboratories - # May 17, 1997 - # which by the time of writing could be freely downloaded here: - # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf - - if randfunc is None: - randfunc = Random.get_random_bytes - - # Use the accelerator if available - if _fastmath is not None: - return _fastmath.getStrongPrime(long(N), long(e), false_positive_prob, - randfunc) - - if (N < 512) or ((N % 128) != 0): - raise ValueError ("bits must be multiple of 128 and > 512") - - rabin_miller_rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4))) - - # calculate range for X - # lower_bound = sqrt(2) * 2^{511 + 128*x} - # upper_bound = 2^{512 + 128*x} - 1 - x = (N - 512) >> 7 - # We need to approximate the sqrt(2) in the lower_bound by an integer - # expression because floating point math overflows with these numbers - lower_bound = (14142135623730950489 * (2 ** (511 + 128*x))) // 10000000000000000000 - upper_bound = (1 << (512 + 128*x)) - 1 - # Randomly choose X in calculated range - X = getRandomRange (lower_bound, upper_bound, randfunc) - - # generate p1 and p2 - p = [0, 0] - for i in (0, 1): - # randomly choose 101-bit y - y = getRandomNBitInteger (101, randfunc) - # initialize the field for sieving - field = [0] * 5 * len (sieve_base) - # sieve the field - for prime in sieve_base: - offset = y % prime - for j in iter_range((prime - offset) % prime, len (field), prime): - field[j] = 1 - - # look for suitable p[i] starting at y - result = 0 - for j in range(len(field)): - composite = field[j] - # look for next canidate - if composite: - continue - tmp = y + j - result = _rabinMillerTest (tmp, rabin_miller_rounds) - if result > 0: - p[i] = tmp - break - if result == 0: - raise RuntimeError ("Couln't find prime in field. " - "Developer: Increase field_size") - - # Calculate R - # R = (p2^{-1} mod p1) * p2 - (p1^{-1} mod p2) * p1 - tmp1 = inverse (p[1], p[0]) * p[1] # (p2^-1 mod p1)*p2 - tmp2 = inverse (p[0], p[1]) * p[0] # (p1^-1 mod p2)*p1 - R = tmp1 - tmp2 # (p2^-1 mod p1)*p2 - (p1^-1 mod p2)*p1 - - # search for final prime number starting by Y0 - # Y0 = X + (R - X mod p1p2) - increment = p[0] * p[1] - X = X + (R - (X % increment)) - while 1: - is_possible_prime = 1 - # first check candidate against sieve_base - for prime in sieve_base: - if (X % prime) == 0: - is_possible_prime = 0 - break - # if e is given make sure that e and X-1 are coprime - # this is not necessarily a strong prime criterion but useful when - # creating them for RSA where the p-1 and q-1 should be coprime to - # the public exponent e - if e and is_possible_prime: - if e & 1: - if GCD(e, X-1) != 1: - is_possible_prime = 0 - else: - if GCD(e, (X-1) // 2) != 1: - is_possible_prime = 0 - - # do some Rabin-Miller-Tests - if is_possible_prime: - result = _rabinMillerTest (X, rabin_miller_rounds) - if result > 0: - break - X += increment + r""" + Return a random strong *N*-bit prime number. + In this context, *p* is a strong prime if *p-1* and *p+1* have at + least one large prime factor. + + Args: + N (integer): the exact length of the strong prime. + It must be a multiple of 128 and > 512. + e (integer): if provided, the returned prime (minus 1) + will be coprime to *e* and thus suitable for RSA where + *e* is the public exponent. + false_positive_prob (float): + The statistical probability for the result not to be actually a + prime. It defaults to 10\ :sup:`-6`. + Note that the real probability of a false-positive is far less. This is + just the mathematically provable limit. + randfunc (callable): + A function that takes a parameter *N* and that returns + a random byte string of such length. + If omitted, :func:`Cryptodome.Random.get_random_bytes` is used. + Return: + The new strong prime. + + .. deprecated:: 3.0 + This function is for internal use only and may be renamed or removed in + the future. + """ + + # This function was implemented following the + # instructions found in the paper: + # "FAST GENERATION OF RANDOM, STRONG RSA PRIMES" + # by Robert D. Silverman + # RSA Laboratories + # May 17, 1997 + # which by the time of writing could be freely downloaded here: + # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf + + if randfunc is None: + randfunc = Random.get_random_bytes + + # Use the accelerator if available + if _fastmath is not None: + return _fastmath.getStrongPrime( + long(N), + long(e), + false_positive_prob, + randfunc, + ) + + if (N < 512) or ((N % 128) != 0): + raise ValueError("bits must be multiple of 128 and > 512") + + rabin_miller_rounds = int(math.ceil(-math.log(false_positive_prob) / math.log(4))) + + # calculate range for X + # lower_bound = sqrt(2) * 2^{511 + 128*x} + # upper_bound = 2^{512 + 128*x} - 1 + x = (N - 512) >> 7 + # We need to approximate the sqrt(2) in the lower_bound by an integer + # expression because floating point math overflows with these numbers + lower_bound = (14142135623730950489 * (2 ** (511 + 128 * x))) // 10000000000000000000 + upper_bound = (1 << (512 + 128 * x)) - 1 + # Randomly choose X in calculated range + X = getRandomRange(lower_bound, upper_bound, randfunc) + + # generate p1 and p2 + p = [0, 0] + for i in (0, 1): + # randomly choose 101-bit y + y = getRandomNBitInteger(101, randfunc) + # initialize the field for sieving + field = [0] * 5 * len(sieve_base) + # sieve the field + for prime in sieve_base: + offset = y % prime + for j in iter_range((prime - offset) % prime, len(field), prime): + field[j] = 1 + + # look for suitable p[i] starting at y + result = 0 + for j in range(len(field)): + composite = field[j] + # look for next canidate + if composite: + continue + tmp = y + j + result = _rabinMillerTest(tmp, rabin_miller_rounds) + if result > 0: + p[i] = tmp + break + if result == 0: + raise RuntimeError( + "Couln't find prime in field. Developer: Increase field_size", + ) + + # Calculate R + # R = (p2^{-1} mod p1) * p2 - (p1^{-1} mod p2) * p1 + tmp1 = inverse(p[1], p[0]) * p[1] # (p2^-1 mod p1)*p2 + tmp2 = inverse(p[0], p[1]) * p[0] # (p1^-1 mod p2)*p1 + R = tmp1 - tmp2 # (p2^-1 mod p1)*p2 - (p1^-1 mod p2)*p1 + + # search for final prime number starting by Y0 + # Y0 = X + (R - X mod p1p2) + increment = p[0] * p[1] + X = X + (R - (X % increment)) + while 1: + is_possible_prime = 1 + # first check candidate against sieve_base + for prime in sieve_base: + if (X % prime) == 0: + is_possible_prime = 0 + break + # if e is given make sure that e and X-1 are coprime + # this is not necessarily a strong prime criterion but useful when + # creating them for RSA where the p-1 and q-1 should be coprime to + # the public exponent e + if e and is_possible_prime: + if e & 1: + if GCD(e, X - 1) != 1: + is_possible_prime = 0 + else: + if GCD(e, (X - 1) // 2) != 1: + is_possible_prime = 0 + + # do some Rabin-Miller-Tests + if is_possible_prime: + result = _rabinMillerTest(X, rabin_miller_rounds) + if result > 0: + break + X += increment # abort when X has more bits than requested # TODO: maybe we shouldn't abort but rather start over. - if X >= 1 << N: - raise RuntimeError ("Couln't find prime in field. " - "Developer: Increase field_size") - return X + if X >= 1 << N: + raise RuntimeError( + "Couln't find prime in field. Developer: Increase field_size", + ) + return X + def isPrime(N, false_positive_prob=1e-6, randfunc=None): - r"""Test if a number *N* is a prime. + r"""Test if a number *N* is a prime. - Args: - false_positive_prob (float): - The statistical probability for the result not to be actually a - prime. It defaults to 10\ :sup:`-6`. - Note that the real probability of a false-positive is far less. - This is just the mathematically provable limit. - randfunc (callable): - A function that takes a parameter *N* and that returns - a random byte string of such length. - If omitted, :func:`Cryptodome.Random.get_random_bytes` is used. + Args: + false_positive_prob (float): + The statistical probability for the result not to be actually a + prime. It defaults to 10\ :sup:`-6`. + Note that the real probability of a false-positive is far less. + This is just the mathematically provable limit. + randfunc (callable): + A function that takes a parameter *N* and that returns + a random byte string of such length. + If omitted, :func:`Cryptodome.Random.get_random_bytes` is used. - Return: - `True` if the input is indeed prime. - """ + Return: + `True` if the input is indeed prime. + """ - if randfunc is None: - randfunc = Random.get_random_bytes + if randfunc is None: + randfunc = Random.get_random_bytes - if _fastmath is not None: - return _fastmath.isPrime(long(N), false_positive_prob, randfunc) + if _fastmath is not None: + return _fastmath.isPrime(long(N), false_positive_prob, randfunc) - if N < 3 or N & 1 == 0: - return N == 2 - for p in sieve_base: - if N == p: - return True - if N % p == 0: - return False + if N < 3 or N & 1 == 0: + return N == 2 + for p in sieve_base: + if N == p: + return True + if N % p == 0: + return False - rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4))) - return bool(_rabinMillerTest(N, rounds, randfunc)) + rounds = int(math.ceil(-math.log(false_positive_prob) / math.log(4))) + return bool(_rabinMillerTest(N, rounds, randfunc)) # Improved conversion functions contributed by Barry Warsaw, after # careful benchmarking -import struct def long_to_bytes(n, blocksize=0): - """Convert a positive integer to a byte string using big endian encoding. + """Convert a positive integer to a byte string using big endian encoding. - If :data:`blocksize` is absent or zero, the byte string will - be of minimal length. + If :data:`blocksize` is absent or zero, the byte string will + be of minimal length. - Otherwise, the length of the byte string is guaranteed to be a multiple - of :data:`blocksize`. If necessary, zeroes (``\\x00``) are added at the left. + Otherwise, the length of the byte string is guaranteed to be a multiple + of :data:`blocksize`. If necessary, zeroes (``\\x00``) are added at the left. - .. note:: - In Python 3, if you are sure that :data:`n` can fit into - :data:`blocksize` bytes, you can simply use the native method instead:: + .. note:: + In Python 3, if you are sure that :data:`n` can fit into + :data:`blocksize` bytes, you can simply use the native method instead:: - >>> n.to_bytes(blocksize, 'big') + >>> n.to_bytes(blocksize, 'big') - For instance:: + For instance:: - >>> n = 80 - >>> n.to_bytes(2, 'big') - b'\\x00P' + >>> n = 80 + >>> n.to_bytes(2, 'big') + b'\\x00P' - However, and unlike this ``long_to_bytes()`` function, - an ``OverflowError`` exception is raised if :data:`n` does not fit. - """ + However, and unlike this ``long_to_bytes()`` function, + an ``OverflowError`` exception is raised if :data:`n` does not fit. + """ - if n < 0 or blocksize < 0: - raise ValueError("Values must be non-negative") + if n < 0 or blocksize < 0: + raise ValueError("Values must be non-negative") - result = [] - pack = struct.pack + result = [] + pack = struct.pack - # Fill the first block independently from the value of n - bsr = blocksize - while bsr >= 8: - result.insert(0, pack('>Q', n & 0xFFFFFFFFFFFFFFFF)) - n = n >> 64 - bsr -= 8 + # Fill the first block independently from the value of n + bsr = blocksize + while bsr >= 8: + result.insert(0, pack(">Q", n & 0xFFFFFFFFFFFFFFFF)) + n = n >> 64 + bsr -= 8 - while bsr >= 4: - result.insert(0, pack('>I', n & 0xFFFFFFFF)) - n = n >> 32 - bsr -= 4 + while bsr >= 4: + result.insert(0, pack(">I", n & 0xFFFFFFFF)) + n = n >> 32 + bsr -= 4 - while bsr > 0: - result.insert(0, pack('>B', n & 0xFF)) - n = n >> 8 - bsr -= 1 + while bsr > 0: + result.insert(0, pack(">B", n & 0xFF)) + n = n >> 8 + bsr -= 1 - if n == 0: - if len(result) == 0: - bresult = b'\x00' - else: - bresult = b''.join(result) - else: - # The encoded number exceeds the block size - while n > 0: - result.insert(0, pack('>Q', n & 0xFFFFFFFFFFFFFFFF)) - n = n >> 64 - result[0] = result[0].lstrip(b'\x00') - bresult = b''.join(result) - # bresult has minimum length here - if blocksize > 0: - target_len = ((len(bresult) - 1) // blocksize + 1) * blocksize - bresult = b'\x00' * (target_len - len(bresult)) + bresult + if n == 0: + if len(result) == 0: + bresult = b"\x00" + else: + bresult = b"".join(result) + else: + # The encoded number exceeds the block size + while n > 0: + result.insert(0, pack(">Q", n & 0xFFFFFFFFFFFFFFFF)) + n = n >> 64 + result[0] = result[0].lstrip(b"\x00") + bresult = b"".join(result) + # bresult has minimum length here + if blocksize > 0: + target_len = ((len(bresult) - 1) // blocksize + 1) * blocksize + bresult = b"\x00" * (target_len - len(bresult)) + bresult - return bresult + return bresult def bytes_to_long(s): - """Convert a byte string to a long integer (big endian). + """Convert a byte string to a long integer (big endian). - In Python 3.2+, use the native method instead:: + In Python 3.2+, use the native method instead:: - >>> int.from_bytes(s, 'big') + >>> int.from_bytes(s, 'big') - For instance:: + For instance:: - >>> int.from_bytes(b'\x00P', 'big') - 80 + >>> int.from_bytes(b'\x00P', 'big') + 80 - This is (essentially) the inverse of :func:`long_to_bytes`. - """ - acc = 0 + This is (essentially) the inverse of :func:`long_to_bytes`. + """ + acc = 0 - unpack = struct.unpack + unpack = struct.unpack - # Up to Python 2.7.4, struct.unpack can't work with bytearrays nor - # memoryviews - if sys.version_info[0:3] < (2, 7, 4): - if isinstance(s, bytearray): - s = bytes(s) - elif isinstance(s, memoryview): - s = s.tobytes() + # Up to Python 2.7.4, struct.unpack can't work with bytearrays nor + # memoryviews + if sys.version_info[0:3] < (2, 7, 4): + if isinstance(s, bytearray): + s = bytes(s) + elif isinstance(s, memoryview): + s = s.tobytes() - length = len(s) - if length % 4: - extra = (4 - length % 4) - s = b'\x00' * extra + s - length = length + extra - for i in range(0, length, 4): - acc = (acc << 32) + unpack('>I', s[i:i+4])[0] - return acc + length = len(s) + if length % 4: + extra = 4 - length % 4 + s = b"\x00" * extra + s + length = length + extra + for i in range(0, length, 4): + acc = (acc << 32) + unpack(">I", s[i : i + 4])[0] + return acc # For backwards compatibility... import warnings + + def long2str(n, blocksize=0): - warnings.warn("long2str() has been replaced by long_to_bytes()") - return long_to_bytes(n, blocksize) + warnings.warn("long2str() has been replaced by long_to_bytes()") + return long_to_bytes(n, blocksize) + + def str2long(s): - warnings.warn("str2long() has been replaced by bytes_to_long()") - return bytes_to_long(s) + warnings.warn("str2long() has been replaced by bytes_to_long()") + return bytes_to_long(s) # The first 10000 primes used for checking primality. # This should be enough to eliminate most of the odd # numbers before needing to do a Rabin-Miller test at all. sieve_base = ( - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, - 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, - 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, - 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, - 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, - 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, - 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, - 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, - 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, - 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, - 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, - 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, - 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, - 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, - 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, - 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, - 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, - 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, - 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, - 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, - 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, - 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, - 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, - 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, - 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, - 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, - 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, - 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, - 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, - 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, - 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, - 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, - 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, - 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, - 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, - 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, - 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, - 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, - 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, - 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, - 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, - 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, - 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, - 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, - 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, - 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, - 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, - 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, - 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, - 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, - 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, - 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, - 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, - 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, - 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, - 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, - 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, - 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, - 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, - 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, - 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, - 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, - 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, - 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, - 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, - 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, - 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, - 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, - 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, - 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, - 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, - 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, - 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, - 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, - 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, - 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, - 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, - 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, - 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, - 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, - 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, - 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, - 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, - 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, - 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, - 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, - 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, - 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, - 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, - 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, - 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, - 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, - 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, - 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, - 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, - 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, - 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, - 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, - 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, - 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, - 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, - 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, - 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, - 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, - 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, - 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, - 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, - 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, - 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, - 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, - 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, - 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, - 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, - 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, - 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, - 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, - 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, - 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, - 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, - 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, - 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, - 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, - 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, - 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, - 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, - 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, - 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, - 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, - 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, - 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, - 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, - 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, - 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, - 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, - 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, - 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, - 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, - 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, - 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, - 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, - 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, - 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, - 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, - 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, - 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, - 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, - 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, - 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, - 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, - 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, - 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, - 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, - 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, - 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, - 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, - 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, - 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, - 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, - 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, - 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, - 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, - 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, - 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, - 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, - 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, - 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, - 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, - 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, - 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, - 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, - 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, - 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, - 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, - 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, - 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, - 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, - 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, - 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, - 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, - 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, - 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, - 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, - 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, - 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, - 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, - 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, - 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, - 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, - 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, - 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, - 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, - 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, - 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, - 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, - 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, - 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, - 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, - 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, - 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, - 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, - 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, - 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, - 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, - 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, - 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, - 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, - 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, - 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, - 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, - 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, - 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, - 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, - 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, - 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, - 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, - 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, - 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, - 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, - 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, - 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, - 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, - 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, - 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, - 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, - 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, - 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, - 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, - 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, - 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, - 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, - 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, - 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, - 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, - 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, - 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, - 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, - 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, - 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, - 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, - 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, - 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, - 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, - 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, - 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, - 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, - 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, - 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, - 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, - 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, - 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, - 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, - 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, - 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, - 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, - 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, - 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, - 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, - 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, - 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, - 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, - 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, - 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, - 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, - 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, - 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, - 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, - 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, - 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, - 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, - 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, - 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, - 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, - 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, - 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, - 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, - 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, - 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, - 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, - 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, - 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, - 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, - 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, - 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, - 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, - 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, - 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, - 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, - 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, - 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, - 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, - 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, - 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, - 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, - 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, - 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, - 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, - 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, - 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, - 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, - 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, - 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, - 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, - 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, - 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, - 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, - 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, - 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, - 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, - 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, - 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, - 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, - 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, - 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, - 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, - 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, - 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, - 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, - 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, - 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, - 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, - 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, - 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, - 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, - 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, - 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, - 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, - 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, - 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, - 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, - 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, - 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, - 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, - 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, - 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, - 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, - 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, - 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, - 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, - 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, - 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, - 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, - 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, - 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, - 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, - 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, - 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, - 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, - 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, - 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, - 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, - 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, - 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, - 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, - 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, - 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, - 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, - 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, - 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, - 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, - 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, - 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, - 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, - 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, - 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, - 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, - 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, - 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, - 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, - 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, - 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, - 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, - 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, - 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, - 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, - 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, - 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, - 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, - 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, - 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, - 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, - 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, - 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, - 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, - 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, - 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, - 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, - 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, - 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, - 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, - 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, - 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, - 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, - 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, - 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, - 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, - 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, - 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, - 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, - 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, - 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, - 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, - 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, - 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, - 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, - 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, - 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, - 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, - 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, - 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, - 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, - 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, - 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, - 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, - 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, - 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, - 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, - 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, - 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, - 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, - 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, - 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, - 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, - 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, - 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, - 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, - 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, - 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, - 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, - 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, - 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, - 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, - 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, - 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, - 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, - 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, - 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, - 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, - 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, - 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, - 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, - 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, - 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, - 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, - 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, - 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, - 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, - 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, - 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, - 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, - 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, - 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, - 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, - 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, - 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, - 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, - 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, - 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, - 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, - 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, - 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, - 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, - 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, - 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, - 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, - 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, - 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, - 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, - 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, - 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, - 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, - 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, - 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, - 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, - 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, - 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, - 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, - 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, - 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, - 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, - 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, - 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, - 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, - 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, - 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, - 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, - 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, - 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, - 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, - 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, - 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, - 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, - 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, - 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, - 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, - 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, - 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, - 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, - 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, - 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, - 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, - 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, - 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, - 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, - 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, - 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, - 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, - 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, - 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, - 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, - 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, - 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, - 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, - 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, - 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, - 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, - 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, - 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, - 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, - 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, - 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, - 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, - 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, - 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, - 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, - 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, - 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, - 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, - 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, - 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, - 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, - 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, - 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, - 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, - 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, - 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, - 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, - 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, - 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, - 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, - 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, - 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, - 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, - 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, - 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, - 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, - 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, - 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, - 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, - 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, - 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, - 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, - 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, - 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, - 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, - 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, - 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, - 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, - 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, - 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, - 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, - 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, - 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, - 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, - 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, - 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, - 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, - 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, - 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, - 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, - 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, - 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, - 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, - 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, - 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, - 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, - 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, - 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, - 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, - 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, - 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, - 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, - 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, - 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, - 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, - 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, - 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, - 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, - 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, - 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, - 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, - 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, - 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, - 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, - 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, - 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, - 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, - 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, - 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, - 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, - 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, - 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, - 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, - 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, - 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, - 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, - 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, - 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, - 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, - 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, - 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, - 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, - 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, - 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, - 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, - 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, - 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, - 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, - 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, - 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, - 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, - 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, - 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, - 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, - 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, - 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, - 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, - 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, - 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, - 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, - 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, - 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, - 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, - 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, - 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, - 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, - 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, - 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, - 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, - 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, - 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, - 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, - 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581, - 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, - 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761, - 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867, - 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983, - 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103, - 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239, - 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377, - 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499, - 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593, - 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, - 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841, - 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943, - 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049, - 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153, - 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231, - 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369, - 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453, - 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547, - 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, - 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763, - 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867, - 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961, - 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087, - 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213, - 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371, - 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489, - 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597, - 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, - 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819, - 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917, - 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061, - 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191, - 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263, - 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403, - 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493, - 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691, - 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, - 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929, - 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039, - 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139, - 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223, - 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321, - 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451, - 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549, - 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657, - 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, - 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901, - 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981, - 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089, - 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209, - 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327, - 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389, - 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473, - 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593, - 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, - 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843, - 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933, - 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031, - 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109, - 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229, - 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341, - 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481, - 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617, - 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, - 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823, - 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923, - 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013, - 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127, - 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303, - 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417, - 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529, - 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613, - 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, - 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859, - 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973, - 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099, - 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197, - 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297, - 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411, - 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521, - 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611, - 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, - 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843, - 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929, - 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079, - 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209, - 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307, - 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401, - 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533, - 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619, - 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, - 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821, - 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979, - 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081, - 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207, - 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303, - 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441, - 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541, - 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667, - 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, - 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907, - 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023, - 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153, - 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261, - 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351, - 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477, - 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551, - 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641, - 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, - 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839, - 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977, - 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101, - 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193, - 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311, - 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479, - 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571, - 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697, - 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, - 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901, - 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063, - 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181, - 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283, - 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393, - 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531, - 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621, - 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699, - 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, - 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939, - 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051, - 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173, - 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263, - 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369, - 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513, - 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629, - 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713, - 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, - 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923, - 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023, - 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101, - 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223, - 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349, - 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463, - 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569, - 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689, - 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, - 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929, - 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009, - 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139, - 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219, - 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339, - 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469, - 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559, - 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651, - 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, - 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891, - 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047, - 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177, - 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267, - 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399, - 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471, - 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609, - 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719, - 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, - 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987, - 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127, - 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221, - 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319, - 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437, - 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521, - 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659, - 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761, - 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, - 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027, - 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121, - 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237, - 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363, - 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469, - 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601, - 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691, - 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829, - 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, - 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111, - 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197, - 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291, - 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371, - 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477, - 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587, - 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743, - 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861, - 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, - 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119, - 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223, - 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323, - 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473, - 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553, - 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641, - 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721, - 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853, - 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, - 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079, - 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259, - 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411, - 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547, - 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667, - 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801, - 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873, - 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003, - 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, - 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209, - 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317, - 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431, - 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527, - 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627, - 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759, - 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849, - 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963, - 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, - 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149, - 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239, - 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373, - 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481, - 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617, - 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709, - 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847, - 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977, - 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, - 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193, - 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303, - 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411, - 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529, - 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673, - 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807, - 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939, - 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033, - 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, - 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243, - 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363, - 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431, - 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567, - 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669, - 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753, - 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849, - 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951, - 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, - 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179, - 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281, - 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383, - 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497, - 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607, - 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787, - 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911, - 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997, - 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, - 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253, - 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349, - 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447, - 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559, - 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687, - 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793, - 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903, - 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021, - 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, - 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231, - 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317, - 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441, - 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539, - 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633, - 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773, - 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873, - 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971, - 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, - 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223, - 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331, - 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461, - 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581, - 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731, - 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799, - 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931, - 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021, - 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, - 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303, - 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429, - 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549, - 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649, - 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813, - 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883, - 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011, - 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179, - 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, - 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411, - 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507, - 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639, - 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737, - 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873, - 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947, - 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053, - 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139, - 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, - 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397, - 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529, - 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643, - 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733, - 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839, - 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, - 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109, -100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237, -100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361, -100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469, -100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549, -100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699, -100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823, -100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957, -100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089, -101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173, -101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281, -101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383, -101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501, -101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599, -101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719, -101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833, -101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929, -101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023, -102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107, -102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217, -102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317, -102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451, -102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551, -102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667, -102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811, -102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931, -102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079, -103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217, -103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387, -103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483, -103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591, -103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703, -103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867, -103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981, -103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059, -104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173, -104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297, -104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399, -104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543, -104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659, -104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, + 2, + 3, + 5, + 7, + 11, + 13, + 17, + 19, + 23, + 29, + 31, + 37, + 41, + 43, + 47, + 53, + 59, + 61, + 67, + 71, + 73, + 79, + 83, + 89, + 97, + 101, + 103, + 107, + 109, + 113, + 127, + 131, + 137, + 139, + 149, + 151, + 157, + 163, + 167, + 173, + 179, + 181, + 191, + 193, + 197, + 199, + 211, + 223, + 227, + 229, + 233, + 239, + 241, + 251, + 257, + 263, + 269, + 271, + 277, + 281, + 283, + 293, + 307, + 311, + 313, + 317, + 331, + 337, + 347, + 349, + 353, + 359, + 367, + 373, + 379, + 383, + 389, + 397, + 401, + 409, + 419, + 421, + 431, + 433, + 439, + 443, + 449, + 457, + 461, + 463, + 467, + 479, + 487, + 491, + 499, + 503, + 509, + 521, + 523, + 541, + 547, + 557, + 563, + 569, + 571, + 577, + 587, + 593, + 599, + 601, + 607, + 613, + 617, + 619, + 631, + 641, + 643, + 647, + 653, + 659, + 661, + 673, + 677, + 683, + 691, + 701, + 709, + 719, + 727, + 733, + 739, + 743, + 751, + 757, + 761, + 769, + 773, + 787, + 797, + 809, + 811, + 821, + 823, + 827, + 829, + 839, + 853, + 857, + 859, + 863, + 877, + 881, + 883, + 887, + 907, + 911, + 919, + 929, + 937, + 941, + 947, + 953, + 967, + 971, + 977, + 983, + 991, + 997, + 1009, + 1013, + 1019, + 1021, + 1031, + 1033, + 1039, + 1049, + 1051, + 1061, + 1063, + 1069, + 1087, + 1091, + 1093, + 1097, + 1103, + 1109, + 1117, + 1123, + 1129, + 1151, + 1153, + 1163, + 1171, + 1181, + 1187, + 1193, + 1201, + 1213, + 1217, + 1223, + 1229, + 1231, + 1237, + 1249, + 1259, + 1277, + 1279, + 1283, + 1289, + 1291, + 1297, + 1301, + 1303, + 1307, + 1319, + 1321, + 1327, + 1361, + 1367, + 1373, + 1381, + 1399, + 1409, + 1423, + 1427, + 1429, + 1433, + 1439, + 1447, + 1451, + 1453, + 1459, + 1471, + 1481, + 1483, + 1487, + 1489, + 1493, + 1499, + 1511, + 1523, + 1531, + 1543, + 1549, + 1553, + 1559, + 1567, + 1571, + 1579, + 1583, + 1597, + 1601, + 1607, + 1609, + 1613, + 1619, + 1621, + 1627, + 1637, + 1657, + 1663, + 1667, + 1669, + 1693, + 1697, + 1699, + 1709, + 1721, + 1723, + 1733, + 1741, + 1747, + 1753, + 1759, + 1777, + 1783, + 1787, + 1789, + 1801, + 1811, + 1823, + 1831, + 1847, + 1861, + 1867, + 1871, + 1873, + 1877, + 1879, + 1889, + 1901, + 1907, + 1913, + 1931, + 1933, + 1949, + 1951, + 1973, + 1979, + 1987, + 1993, + 1997, + 1999, + 2003, + 2011, + 2017, + 2027, + 2029, + 2039, + 2053, + 2063, + 2069, + 2081, + 2083, + 2087, + 2089, + 2099, + 2111, + 2113, + 2129, + 2131, + 2137, + 2141, + 2143, + 2153, + 2161, + 2179, + 2203, + 2207, + 2213, + 2221, + 2237, + 2239, + 2243, + 2251, + 2267, + 2269, + 2273, + 2281, + 2287, + 2293, + 2297, + 2309, + 2311, + 2333, + 2339, + 2341, + 2347, + 2351, + 2357, + 2371, + 2377, + 2381, + 2383, + 2389, + 2393, + 2399, + 2411, + 2417, + 2423, + 2437, + 2441, + 2447, + 2459, + 2467, + 2473, + 2477, + 2503, + 2521, + 2531, + 2539, + 2543, + 2549, + 2551, + 2557, + 2579, + 2591, + 2593, + 2609, + 2617, + 2621, + 2633, + 2647, + 2657, + 2659, + 2663, + 2671, + 2677, + 2683, + 2687, + 2689, + 2693, + 2699, + 2707, + 2711, + 2713, + 2719, + 2729, + 2731, + 2741, + 2749, + 2753, + 2767, + 2777, + 2789, + 2791, + 2797, + 2801, + 2803, + 2819, + 2833, + 2837, + 2843, + 2851, + 2857, + 2861, + 2879, + 2887, + 2897, + 2903, + 2909, + 2917, + 2927, + 2939, + 2953, + 2957, + 2963, + 2969, + 2971, + 2999, + 3001, + 3011, + 3019, + 3023, + 3037, + 3041, + 3049, + 3061, + 3067, + 3079, + 3083, + 3089, + 3109, + 3119, + 3121, + 3137, + 3163, + 3167, + 3169, + 3181, + 3187, + 3191, + 3203, + 3209, + 3217, + 3221, + 3229, + 3251, + 3253, + 3257, + 3259, + 3271, + 3299, + 3301, + 3307, + 3313, + 3319, + 3323, + 3329, + 3331, + 3343, + 3347, + 3359, + 3361, + 3371, + 3373, + 3389, + 3391, + 3407, + 3413, + 3433, + 3449, + 3457, + 3461, + 3463, + 3467, + 3469, + 3491, + 3499, + 3511, + 3517, + 3527, + 3529, + 3533, + 3539, + 3541, + 3547, + 3557, + 3559, + 3571, + 3581, + 3583, + 3593, + 3607, + 3613, + 3617, + 3623, + 3631, + 3637, + 3643, + 3659, + 3671, + 3673, + 3677, + 3691, + 3697, + 3701, + 3709, + 3719, + 3727, + 3733, + 3739, + 3761, + 3767, + 3769, + 3779, + 3793, + 3797, + 3803, + 3821, + 3823, + 3833, + 3847, + 3851, + 3853, + 3863, + 3877, + 3881, + 3889, + 3907, + 3911, + 3917, + 3919, + 3923, + 3929, + 3931, + 3943, + 3947, + 3967, + 3989, + 4001, + 4003, + 4007, + 4013, + 4019, + 4021, + 4027, + 4049, + 4051, + 4057, + 4073, + 4079, + 4091, + 4093, + 4099, + 4111, + 4127, + 4129, + 4133, + 4139, + 4153, + 4157, + 4159, + 4177, + 4201, + 4211, + 4217, + 4219, + 4229, + 4231, + 4241, + 4243, + 4253, + 4259, + 4261, + 4271, + 4273, + 4283, + 4289, + 4297, + 4327, + 4337, + 4339, + 4349, + 4357, + 4363, + 4373, + 4391, + 4397, + 4409, + 4421, + 4423, + 4441, + 4447, + 4451, + 4457, + 4463, + 4481, + 4483, + 4493, + 4507, + 4513, + 4517, + 4519, + 4523, + 4547, + 4549, + 4561, + 4567, + 4583, + 4591, + 4597, + 4603, + 4621, + 4637, + 4639, + 4643, + 4649, + 4651, + 4657, + 4663, + 4673, + 4679, + 4691, + 4703, + 4721, + 4723, + 4729, + 4733, + 4751, + 4759, + 4783, + 4787, + 4789, + 4793, + 4799, + 4801, + 4813, + 4817, + 4831, + 4861, + 4871, + 4877, + 4889, + 4903, + 4909, + 4919, + 4931, + 4933, + 4937, + 4943, + 4951, + 4957, + 4967, + 4969, + 4973, + 4987, + 4993, + 4999, + 5003, + 5009, + 5011, + 5021, + 5023, + 5039, + 5051, + 5059, + 5077, + 5081, + 5087, + 5099, + 5101, + 5107, + 5113, + 5119, + 5147, + 5153, + 5167, + 5171, + 5179, + 5189, + 5197, + 5209, + 5227, + 5231, + 5233, + 5237, + 5261, + 5273, + 5279, + 5281, + 5297, + 5303, + 5309, + 5323, + 5333, + 5347, + 5351, + 5381, + 5387, + 5393, + 5399, + 5407, + 5413, + 5417, + 5419, + 5431, + 5437, + 5441, + 5443, + 5449, + 5471, + 5477, + 5479, + 5483, + 5501, + 5503, + 5507, + 5519, + 5521, + 5527, + 5531, + 5557, + 5563, + 5569, + 5573, + 5581, + 5591, + 5623, + 5639, + 5641, + 5647, + 5651, + 5653, + 5657, + 5659, + 5669, + 5683, + 5689, + 5693, + 5701, + 5711, + 5717, + 5737, + 5741, + 5743, + 5749, + 5779, + 5783, + 5791, + 5801, + 5807, + 5813, + 5821, + 5827, + 5839, + 5843, + 5849, + 5851, + 5857, + 5861, + 5867, + 5869, + 5879, + 5881, + 5897, + 5903, + 5923, + 5927, + 5939, + 5953, + 5981, + 5987, + 6007, + 6011, + 6029, + 6037, + 6043, + 6047, + 6053, + 6067, + 6073, + 6079, + 6089, + 6091, + 6101, + 6113, + 6121, + 6131, + 6133, + 6143, + 6151, + 6163, + 6173, + 6197, + 6199, + 6203, + 6211, + 6217, + 6221, + 6229, + 6247, + 6257, + 6263, + 6269, + 6271, + 6277, + 6287, + 6299, + 6301, + 6311, + 6317, + 6323, + 6329, + 6337, + 6343, + 6353, + 6359, + 6361, + 6367, + 6373, + 6379, + 6389, + 6397, + 6421, + 6427, + 6449, + 6451, + 6469, + 6473, + 6481, + 6491, + 6521, + 6529, + 6547, + 6551, + 6553, + 6563, + 6569, + 6571, + 6577, + 6581, + 6599, + 6607, + 6619, + 6637, + 6653, + 6659, + 6661, + 6673, + 6679, + 6689, + 6691, + 6701, + 6703, + 6709, + 6719, + 6733, + 6737, + 6761, + 6763, + 6779, + 6781, + 6791, + 6793, + 6803, + 6823, + 6827, + 6829, + 6833, + 6841, + 6857, + 6863, + 6869, + 6871, + 6883, + 6899, + 6907, + 6911, + 6917, + 6947, + 6949, + 6959, + 6961, + 6967, + 6971, + 6977, + 6983, + 6991, + 6997, + 7001, + 7013, + 7019, + 7027, + 7039, + 7043, + 7057, + 7069, + 7079, + 7103, + 7109, + 7121, + 7127, + 7129, + 7151, + 7159, + 7177, + 7187, + 7193, + 7207, + 7211, + 7213, + 7219, + 7229, + 7237, + 7243, + 7247, + 7253, + 7283, + 7297, + 7307, + 7309, + 7321, + 7331, + 7333, + 7349, + 7351, + 7369, + 7393, + 7411, + 7417, + 7433, + 7451, + 7457, + 7459, + 7477, + 7481, + 7487, + 7489, + 7499, + 7507, + 7517, + 7523, + 7529, + 7537, + 7541, + 7547, + 7549, + 7559, + 7561, + 7573, + 7577, + 7583, + 7589, + 7591, + 7603, + 7607, + 7621, + 7639, + 7643, + 7649, + 7669, + 7673, + 7681, + 7687, + 7691, + 7699, + 7703, + 7717, + 7723, + 7727, + 7741, + 7753, + 7757, + 7759, + 7789, + 7793, + 7817, + 7823, + 7829, + 7841, + 7853, + 7867, + 7873, + 7877, + 7879, + 7883, + 7901, + 7907, + 7919, + 7927, + 7933, + 7937, + 7949, + 7951, + 7963, + 7993, + 8009, + 8011, + 8017, + 8039, + 8053, + 8059, + 8069, + 8081, + 8087, + 8089, + 8093, + 8101, + 8111, + 8117, + 8123, + 8147, + 8161, + 8167, + 8171, + 8179, + 8191, + 8209, + 8219, + 8221, + 8231, + 8233, + 8237, + 8243, + 8263, + 8269, + 8273, + 8287, + 8291, + 8293, + 8297, + 8311, + 8317, + 8329, + 8353, + 8363, + 8369, + 8377, + 8387, + 8389, + 8419, + 8423, + 8429, + 8431, + 8443, + 8447, + 8461, + 8467, + 8501, + 8513, + 8521, + 8527, + 8537, + 8539, + 8543, + 8563, + 8573, + 8581, + 8597, + 8599, + 8609, + 8623, + 8627, + 8629, + 8641, + 8647, + 8663, + 8669, + 8677, + 8681, + 8689, + 8693, + 8699, + 8707, + 8713, + 8719, + 8731, + 8737, + 8741, + 8747, + 8753, + 8761, + 8779, + 8783, + 8803, + 8807, + 8819, + 8821, + 8831, + 8837, + 8839, + 8849, + 8861, + 8863, + 8867, + 8887, + 8893, + 8923, + 8929, + 8933, + 8941, + 8951, + 8963, + 8969, + 8971, + 8999, + 9001, + 9007, + 9011, + 9013, + 9029, + 9041, + 9043, + 9049, + 9059, + 9067, + 9091, + 9103, + 9109, + 9127, + 9133, + 9137, + 9151, + 9157, + 9161, + 9173, + 9181, + 9187, + 9199, + 9203, + 9209, + 9221, + 9227, + 9239, + 9241, + 9257, + 9277, + 9281, + 9283, + 9293, + 9311, + 9319, + 9323, + 9337, + 9341, + 9343, + 9349, + 9371, + 9377, + 9391, + 9397, + 9403, + 9413, + 9419, + 9421, + 9431, + 9433, + 9437, + 9439, + 9461, + 9463, + 9467, + 9473, + 9479, + 9491, + 9497, + 9511, + 9521, + 9533, + 9539, + 9547, + 9551, + 9587, + 9601, + 9613, + 9619, + 9623, + 9629, + 9631, + 9643, + 9649, + 9661, + 9677, + 9679, + 9689, + 9697, + 9719, + 9721, + 9733, + 9739, + 9743, + 9749, + 9767, + 9769, + 9781, + 9787, + 9791, + 9803, + 9811, + 9817, + 9829, + 9833, + 9839, + 9851, + 9857, + 9859, + 9871, + 9883, + 9887, + 9901, + 9907, + 9923, + 9929, + 9931, + 9941, + 9949, + 9967, + 9973, + 10007, + 10009, + 10037, + 10039, + 10061, + 10067, + 10069, + 10079, + 10091, + 10093, + 10099, + 10103, + 10111, + 10133, + 10139, + 10141, + 10151, + 10159, + 10163, + 10169, + 10177, + 10181, + 10193, + 10211, + 10223, + 10243, + 10247, + 10253, + 10259, + 10267, + 10271, + 10273, + 10289, + 10301, + 10303, + 10313, + 10321, + 10331, + 10333, + 10337, + 10343, + 10357, + 10369, + 10391, + 10399, + 10427, + 10429, + 10433, + 10453, + 10457, + 10459, + 10463, + 10477, + 10487, + 10499, + 10501, + 10513, + 10529, + 10531, + 10559, + 10567, + 10589, + 10597, + 10601, + 10607, + 10613, + 10627, + 10631, + 10639, + 10651, + 10657, + 10663, + 10667, + 10687, + 10691, + 10709, + 10711, + 10723, + 10729, + 10733, + 10739, + 10753, + 10771, + 10781, + 10789, + 10799, + 10831, + 10837, + 10847, + 10853, + 10859, + 10861, + 10867, + 10883, + 10889, + 10891, + 10903, + 10909, + 10937, + 10939, + 10949, + 10957, + 10973, + 10979, + 10987, + 10993, + 11003, + 11027, + 11047, + 11057, + 11059, + 11069, + 11071, + 11083, + 11087, + 11093, + 11113, + 11117, + 11119, + 11131, + 11149, + 11159, + 11161, + 11171, + 11173, + 11177, + 11197, + 11213, + 11239, + 11243, + 11251, + 11257, + 11261, + 11273, + 11279, + 11287, + 11299, + 11311, + 11317, + 11321, + 11329, + 11351, + 11353, + 11369, + 11383, + 11393, + 11399, + 11411, + 11423, + 11437, + 11443, + 11447, + 11467, + 11471, + 11483, + 11489, + 11491, + 11497, + 11503, + 11519, + 11527, + 11549, + 11551, + 11579, + 11587, + 11593, + 11597, + 11617, + 11621, + 11633, + 11657, + 11677, + 11681, + 11689, + 11699, + 11701, + 11717, + 11719, + 11731, + 11743, + 11777, + 11779, + 11783, + 11789, + 11801, + 11807, + 11813, + 11821, + 11827, + 11831, + 11833, + 11839, + 11863, + 11867, + 11887, + 11897, + 11903, + 11909, + 11923, + 11927, + 11933, + 11939, + 11941, + 11953, + 11959, + 11969, + 11971, + 11981, + 11987, + 12007, + 12011, + 12037, + 12041, + 12043, + 12049, + 12071, + 12073, + 12097, + 12101, + 12107, + 12109, + 12113, + 12119, + 12143, + 12149, + 12157, + 12161, + 12163, + 12197, + 12203, + 12211, + 12227, + 12239, + 12241, + 12251, + 12253, + 12263, + 12269, + 12277, + 12281, + 12289, + 12301, + 12323, + 12329, + 12343, + 12347, + 12373, + 12377, + 12379, + 12391, + 12401, + 12409, + 12413, + 12421, + 12433, + 12437, + 12451, + 12457, + 12473, + 12479, + 12487, + 12491, + 12497, + 12503, + 12511, + 12517, + 12527, + 12539, + 12541, + 12547, + 12553, + 12569, + 12577, + 12583, + 12589, + 12601, + 12611, + 12613, + 12619, + 12637, + 12641, + 12647, + 12653, + 12659, + 12671, + 12689, + 12697, + 12703, + 12713, + 12721, + 12739, + 12743, + 12757, + 12763, + 12781, + 12791, + 12799, + 12809, + 12821, + 12823, + 12829, + 12841, + 12853, + 12889, + 12893, + 12899, + 12907, + 12911, + 12917, + 12919, + 12923, + 12941, + 12953, + 12959, + 12967, + 12973, + 12979, + 12983, + 13001, + 13003, + 13007, + 13009, + 13033, + 13037, + 13043, + 13049, + 13063, + 13093, + 13099, + 13103, + 13109, + 13121, + 13127, + 13147, + 13151, + 13159, + 13163, + 13171, + 13177, + 13183, + 13187, + 13217, + 13219, + 13229, + 13241, + 13249, + 13259, + 13267, + 13291, + 13297, + 13309, + 13313, + 13327, + 13331, + 13337, + 13339, + 13367, + 13381, + 13397, + 13399, + 13411, + 13417, + 13421, + 13441, + 13451, + 13457, + 13463, + 13469, + 13477, + 13487, + 13499, + 13513, + 13523, + 13537, + 13553, + 13567, + 13577, + 13591, + 13597, + 13613, + 13619, + 13627, + 13633, + 13649, + 13669, + 13679, + 13681, + 13687, + 13691, + 13693, + 13697, + 13709, + 13711, + 13721, + 13723, + 13729, + 13751, + 13757, + 13759, + 13763, + 13781, + 13789, + 13799, + 13807, + 13829, + 13831, + 13841, + 13859, + 13873, + 13877, + 13879, + 13883, + 13901, + 13903, + 13907, + 13913, + 13921, + 13931, + 13933, + 13963, + 13967, + 13997, + 13999, + 14009, + 14011, + 14029, + 14033, + 14051, + 14057, + 14071, + 14081, + 14083, + 14087, + 14107, + 14143, + 14149, + 14153, + 14159, + 14173, + 14177, + 14197, + 14207, + 14221, + 14243, + 14249, + 14251, + 14281, + 14293, + 14303, + 14321, + 14323, + 14327, + 14341, + 14347, + 14369, + 14387, + 14389, + 14401, + 14407, + 14411, + 14419, + 14423, + 14431, + 14437, + 14447, + 14449, + 14461, + 14479, + 14489, + 14503, + 14519, + 14533, + 14537, + 14543, + 14549, + 14551, + 14557, + 14561, + 14563, + 14591, + 14593, + 14621, + 14627, + 14629, + 14633, + 14639, + 14653, + 14657, + 14669, + 14683, + 14699, + 14713, + 14717, + 14723, + 14731, + 14737, + 14741, + 14747, + 14753, + 14759, + 14767, + 14771, + 14779, + 14783, + 14797, + 14813, + 14821, + 14827, + 14831, + 14843, + 14851, + 14867, + 14869, + 14879, + 14887, + 14891, + 14897, + 14923, + 14929, + 14939, + 14947, + 14951, + 14957, + 14969, + 14983, + 15013, + 15017, + 15031, + 15053, + 15061, + 15073, + 15077, + 15083, + 15091, + 15101, + 15107, + 15121, + 15131, + 15137, + 15139, + 15149, + 15161, + 15173, + 15187, + 15193, + 15199, + 15217, + 15227, + 15233, + 15241, + 15259, + 15263, + 15269, + 15271, + 15277, + 15287, + 15289, + 15299, + 15307, + 15313, + 15319, + 15329, + 15331, + 15349, + 15359, + 15361, + 15373, + 15377, + 15383, + 15391, + 15401, + 15413, + 15427, + 15439, + 15443, + 15451, + 15461, + 15467, + 15473, + 15493, + 15497, + 15511, + 15527, + 15541, + 15551, + 15559, + 15569, + 15581, + 15583, + 15601, + 15607, + 15619, + 15629, + 15641, + 15643, + 15647, + 15649, + 15661, + 15667, + 15671, + 15679, + 15683, + 15727, + 15731, + 15733, + 15737, + 15739, + 15749, + 15761, + 15767, + 15773, + 15787, + 15791, + 15797, + 15803, + 15809, + 15817, + 15823, + 15859, + 15877, + 15881, + 15887, + 15889, + 15901, + 15907, + 15913, + 15919, + 15923, + 15937, + 15959, + 15971, + 15973, + 15991, + 16001, + 16007, + 16033, + 16057, + 16061, + 16063, + 16067, + 16069, + 16073, + 16087, + 16091, + 16097, + 16103, + 16111, + 16127, + 16139, + 16141, + 16183, + 16187, + 16189, + 16193, + 16217, + 16223, + 16229, + 16231, + 16249, + 16253, + 16267, + 16273, + 16301, + 16319, + 16333, + 16339, + 16349, + 16361, + 16363, + 16369, + 16381, + 16411, + 16417, + 16421, + 16427, + 16433, + 16447, + 16451, + 16453, + 16477, + 16481, + 16487, + 16493, + 16519, + 16529, + 16547, + 16553, + 16561, + 16567, + 16573, + 16603, + 16607, + 16619, + 16631, + 16633, + 16649, + 16651, + 16657, + 16661, + 16673, + 16691, + 16693, + 16699, + 16703, + 16729, + 16741, + 16747, + 16759, + 16763, + 16787, + 16811, + 16823, + 16829, + 16831, + 16843, + 16871, + 16879, + 16883, + 16889, + 16901, + 16903, + 16921, + 16927, + 16931, + 16937, + 16943, + 16963, + 16979, + 16981, + 16987, + 16993, + 17011, + 17021, + 17027, + 17029, + 17033, + 17041, + 17047, + 17053, + 17077, + 17093, + 17099, + 17107, + 17117, + 17123, + 17137, + 17159, + 17167, + 17183, + 17189, + 17191, + 17203, + 17207, + 17209, + 17231, + 17239, + 17257, + 17291, + 17293, + 17299, + 17317, + 17321, + 17327, + 17333, + 17341, + 17351, + 17359, + 17377, + 17383, + 17387, + 17389, + 17393, + 17401, + 17417, + 17419, + 17431, + 17443, + 17449, + 17467, + 17471, + 17477, + 17483, + 17489, + 17491, + 17497, + 17509, + 17519, + 17539, + 17551, + 17569, + 17573, + 17579, + 17581, + 17597, + 17599, + 17609, + 17623, + 17627, + 17657, + 17659, + 17669, + 17681, + 17683, + 17707, + 17713, + 17729, + 17737, + 17747, + 17749, + 17761, + 17783, + 17789, + 17791, + 17807, + 17827, + 17837, + 17839, + 17851, + 17863, + 17881, + 17891, + 17903, + 17909, + 17911, + 17921, + 17923, + 17929, + 17939, + 17957, + 17959, + 17971, + 17977, + 17981, + 17987, + 17989, + 18013, + 18041, + 18043, + 18047, + 18049, + 18059, + 18061, + 18077, + 18089, + 18097, + 18119, + 18121, + 18127, + 18131, + 18133, + 18143, + 18149, + 18169, + 18181, + 18191, + 18199, + 18211, + 18217, + 18223, + 18229, + 18233, + 18251, + 18253, + 18257, + 18269, + 18287, + 18289, + 18301, + 18307, + 18311, + 18313, + 18329, + 18341, + 18353, + 18367, + 18371, + 18379, + 18397, + 18401, + 18413, + 18427, + 18433, + 18439, + 18443, + 18451, + 18457, + 18461, + 18481, + 18493, + 18503, + 18517, + 18521, + 18523, + 18539, + 18541, + 18553, + 18583, + 18587, + 18593, + 18617, + 18637, + 18661, + 18671, + 18679, + 18691, + 18701, + 18713, + 18719, + 18731, + 18743, + 18749, + 18757, + 18773, + 18787, + 18793, + 18797, + 18803, + 18839, + 18859, + 18869, + 18899, + 18911, + 18913, + 18917, + 18919, + 18947, + 18959, + 18973, + 18979, + 19001, + 19009, + 19013, + 19031, + 19037, + 19051, + 19069, + 19073, + 19079, + 19081, + 19087, + 19121, + 19139, + 19141, + 19157, + 19163, + 19181, + 19183, + 19207, + 19211, + 19213, + 19219, + 19231, + 19237, + 19249, + 19259, + 19267, + 19273, + 19289, + 19301, + 19309, + 19319, + 19333, + 19373, + 19379, + 19381, + 19387, + 19391, + 19403, + 19417, + 19421, + 19423, + 19427, + 19429, + 19433, + 19441, + 19447, + 19457, + 19463, + 19469, + 19471, + 19477, + 19483, + 19489, + 19501, + 19507, + 19531, + 19541, + 19543, + 19553, + 19559, + 19571, + 19577, + 19583, + 19597, + 19603, + 19609, + 19661, + 19681, + 19687, + 19697, + 19699, + 19709, + 19717, + 19727, + 19739, + 19751, + 19753, + 19759, + 19763, + 19777, + 19793, + 19801, + 19813, + 19819, + 19841, + 19843, + 19853, + 19861, + 19867, + 19889, + 19891, + 19913, + 19919, + 19927, + 19937, + 19949, + 19961, + 19963, + 19973, + 19979, + 19991, + 19993, + 19997, + 20011, + 20021, + 20023, + 20029, + 20047, + 20051, + 20063, + 20071, + 20089, + 20101, + 20107, + 20113, + 20117, + 20123, + 20129, + 20143, + 20147, + 20149, + 20161, + 20173, + 20177, + 20183, + 20201, + 20219, + 20231, + 20233, + 20249, + 20261, + 20269, + 20287, + 20297, + 20323, + 20327, + 20333, + 20341, + 20347, + 20353, + 20357, + 20359, + 20369, + 20389, + 20393, + 20399, + 20407, + 20411, + 20431, + 20441, + 20443, + 20477, + 20479, + 20483, + 20507, + 20509, + 20521, + 20533, + 20543, + 20549, + 20551, + 20563, + 20593, + 20599, + 20611, + 20627, + 20639, + 20641, + 20663, + 20681, + 20693, + 20707, + 20717, + 20719, + 20731, + 20743, + 20747, + 20749, + 20753, + 20759, + 20771, + 20773, + 20789, + 20807, + 20809, + 20849, + 20857, + 20873, + 20879, + 20887, + 20897, + 20899, + 20903, + 20921, + 20929, + 20939, + 20947, + 20959, + 20963, + 20981, + 20983, + 21001, + 21011, + 21013, + 21017, + 21019, + 21023, + 21031, + 21059, + 21061, + 21067, + 21089, + 21101, + 21107, + 21121, + 21139, + 21143, + 21149, + 21157, + 21163, + 21169, + 21179, + 21187, + 21191, + 21193, + 21211, + 21221, + 21227, + 21247, + 21269, + 21277, + 21283, + 21313, + 21317, + 21319, + 21323, + 21341, + 21347, + 21377, + 21379, + 21383, + 21391, + 21397, + 21401, + 21407, + 21419, + 21433, + 21467, + 21481, + 21487, + 21491, + 21493, + 21499, + 21503, + 21517, + 21521, + 21523, + 21529, + 21557, + 21559, + 21563, + 21569, + 21577, + 21587, + 21589, + 21599, + 21601, + 21611, + 21613, + 21617, + 21647, + 21649, + 21661, + 21673, + 21683, + 21701, + 21713, + 21727, + 21737, + 21739, + 21751, + 21757, + 21767, + 21773, + 21787, + 21799, + 21803, + 21817, + 21821, + 21839, + 21841, + 21851, + 21859, + 21863, + 21871, + 21881, + 21893, + 21911, + 21929, + 21937, + 21943, + 21961, + 21977, + 21991, + 21997, + 22003, + 22013, + 22027, + 22031, + 22037, + 22039, + 22051, + 22063, + 22067, + 22073, + 22079, + 22091, + 22093, + 22109, + 22111, + 22123, + 22129, + 22133, + 22147, + 22153, + 22157, + 22159, + 22171, + 22189, + 22193, + 22229, + 22247, + 22259, + 22271, + 22273, + 22277, + 22279, + 22283, + 22291, + 22303, + 22307, + 22343, + 22349, + 22367, + 22369, + 22381, + 22391, + 22397, + 22409, + 22433, + 22441, + 22447, + 22453, + 22469, + 22481, + 22483, + 22501, + 22511, + 22531, + 22541, + 22543, + 22549, + 22567, + 22571, + 22573, + 22613, + 22619, + 22621, + 22637, + 22639, + 22643, + 22651, + 22669, + 22679, + 22691, + 22697, + 22699, + 22709, + 22717, + 22721, + 22727, + 22739, + 22741, + 22751, + 22769, + 22777, + 22783, + 22787, + 22807, + 22811, + 22817, + 22853, + 22859, + 22861, + 22871, + 22877, + 22901, + 22907, + 22921, + 22937, + 22943, + 22961, + 22963, + 22973, + 22993, + 23003, + 23011, + 23017, + 23021, + 23027, + 23029, + 23039, + 23041, + 23053, + 23057, + 23059, + 23063, + 23071, + 23081, + 23087, + 23099, + 23117, + 23131, + 23143, + 23159, + 23167, + 23173, + 23189, + 23197, + 23201, + 23203, + 23209, + 23227, + 23251, + 23269, + 23279, + 23291, + 23293, + 23297, + 23311, + 23321, + 23327, + 23333, + 23339, + 23357, + 23369, + 23371, + 23399, + 23417, + 23431, + 23447, + 23459, + 23473, + 23497, + 23509, + 23531, + 23537, + 23539, + 23549, + 23557, + 23561, + 23563, + 23567, + 23581, + 23593, + 23599, + 23603, + 23609, + 23623, + 23627, + 23629, + 23633, + 23663, + 23669, + 23671, + 23677, + 23687, + 23689, + 23719, + 23741, + 23743, + 23747, + 23753, + 23761, + 23767, + 23773, + 23789, + 23801, + 23813, + 23819, + 23827, + 23831, + 23833, + 23857, + 23869, + 23873, + 23879, + 23887, + 23893, + 23899, + 23909, + 23911, + 23917, + 23929, + 23957, + 23971, + 23977, + 23981, + 23993, + 24001, + 24007, + 24019, + 24023, + 24029, + 24043, + 24049, + 24061, + 24071, + 24077, + 24083, + 24091, + 24097, + 24103, + 24107, + 24109, + 24113, + 24121, + 24133, + 24137, + 24151, + 24169, + 24179, + 24181, + 24197, + 24203, + 24223, + 24229, + 24239, + 24247, + 24251, + 24281, + 24317, + 24329, + 24337, + 24359, + 24371, + 24373, + 24379, + 24391, + 24407, + 24413, + 24419, + 24421, + 24439, + 24443, + 24469, + 24473, + 24481, + 24499, + 24509, + 24517, + 24527, + 24533, + 24547, + 24551, + 24571, + 24593, + 24611, + 24623, + 24631, + 24659, + 24671, + 24677, + 24683, + 24691, + 24697, + 24709, + 24733, + 24749, + 24763, + 24767, + 24781, + 24793, + 24799, + 24809, + 24821, + 24841, + 24847, + 24851, + 24859, + 24877, + 24889, + 24907, + 24917, + 24919, + 24923, + 24943, + 24953, + 24967, + 24971, + 24977, + 24979, + 24989, + 25013, + 25031, + 25033, + 25037, + 25057, + 25073, + 25087, + 25097, + 25111, + 25117, + 25121, + 25127, + 25147, + 25153, + 25163, + 25169, + 25171, + 25183, + 25189, + 25219, + 25229, + 25237, + 25243, + 25247, + 25253, + 25261, + 25301, + 25303, + 25307, + 25309, + 25321, + 25339, + 25343, + 25349, + 25357, + 25367, + 25373, + 25391, + 25409, + 25411, + 25423, + 25439, + 25447, + 25453, + 25457, + 25463, + 25469, + 25471, + 25523, + 25537, + 25541, + 25561, + 25577, + 25579, + 25583, + 25589, + 25601, + 25603, + 25609, + 25621, + 25633, + 25639, + 25643, + 25657, + 25667, + 25673, + 25679, + 25693, + 25703, + 25717, + 25733, + 25741, + 25747, + 25759, + 25763, + 25771, + 25793, + 25799, + 25801, + 25819, + 25841, + 25847, + 25849, + 25867, + 25873, + 25889, + 25903, + 25913, + 25919, + 25931, + 25933, + 25939, + 25943, + 25951, + 25969, + 25981, + 25997, + 25999, + 26003, + 26017, + 26021, + 26029, + 26041, + 26053, + 26083, + 26099, + 26107, + 26111, + 26113, + 26119, + 26141, + 26153, + 26161, + 26171, + 26177, + 26183, + 26189, + 26203, + 26209, + 26227, + 26237, + 26249, + 26251, + 26261, + 26263, + 26267, + 26293, + 26297, + 26309, + 26317, + 26321, + 26339, + 26347, + 26357, + 26371, + 26387, + 26393, + 26399, + 26407, + 26417, + 26423, + 26431, + 26437, + 26449, + 26459, + 26479, + 26489, + 26497, + 26501, + 26513, + 26539, + 26557, + 26561, + 26573, + 26591, + 26597, + 26627, + 26633, + 26641, + 26647, + 26669, + 26681, + 26683, + 26687, + 26693, + 26699, + 26701, + 26711, + 26713, + 26717, + 26723, + 26729, + 26731, + 26737, + 26759, + 26777, + 26783, + 26801, + 26813, + 26821, + 26833, + 26839, + 26849, + 26861, + 26863, + 26879, + 26881, + 26891, + 26893, + 26903, + 26921, + 26927, + 26947, + 26951, + 26953, + 26959, + 26981, + 26987, + 26993, + 27011, + 27017, + 27031, + 27043, + 27059, + 27061, + 27067, + 27073, + 27077, + 27091, + 27103, + 27107, + 27109, + 27127, + 27143, + 27179, + 27191, + 27197, + 27211, + 27239, + 27241, + 27253, + 27259, + 27271, + 27277, + 27281, + 27283, + 27299, + 27329, + 27337, + 27361, + 27367, + 27397, + 27407, + 27409, + 27427, + 27431, + 27437, + 27449, + 27457, + 27479, + 27481, + 27487, + 27509, + 27527, + 27529, + 27539, + 27541, + 27551, + 27581, + 27583, + 27611, + 27617, + 27631, + 27647, + 27653, + 27673, + 27689, + 27691, + 27697, + 27701, + 27733, + 27737, + 27739, + 27743, + 27749, + 27751, + 27763, + 27767, + 27773, + 27779, + 27791, + 27793, + 27799, + 27803, + 27809, + 27817, + 27823, + 27827, + 27847, + 27851, + 27883, + 27893, + 27901, + 27917, + 27919, + 27941, + 27943, + 27947, + 27953, + 27961, + 27967, + 27983, + 27997, + 28001, + 28019, + 28027, + 28031, + 28051, + 28057, + 28069, + 28081, + 28087, + 28097, + 28099, + 28109, + 28111, + 28123, + 28151, + 28163, + 28181, + 28183, + 28201, + 28211, + 28219, + 28229, + 28277, + 28279, + 28283, + 28289, + 28297, + 28307, + 28309, + 28319, + 28349, + 28351, + 28387, + 28393, + 28403, + 28409, + 28411, + 28429, + 28433, + 28439, + 28447, + 28463, + 28477, + 28493, + 28499, + 28513, + 28517, + 28537, + 28541, + 28547, + 28549, + 28559, + 28571, + 28573, + 28579, + 28591, + 28597, + 28603, + 28607, + 28619, + 28621, + 28627, + 28631, + 28643, + 28649, + 28657, + 28661, + 28663, + 28669, + 28687, + 28697, + 28703, + 28711, + 28723, + 28729, + 28751, + 28753, + 28759, + 28771, + 28789, + 28793, + 28807, + 28813, + 28817, + 28837, + 28843, + 28859, + 28867, + 28871, + 28879, + 28901, + 28909, + 28921, + 28927, + 28933, + 28949, + 28961, + 28979, + 29009, + 29017, + 29021, + 29023, + 29027, + 29033, + 29059, + 29063, + 29077, + 29101, + 29123, + 29129, + 29131, + 29137, + 29147, + 29153, + 29167, + 29173, + 29179, + 29191, + 29201, + 29207, + 29209, + 29221, + 29231, + 29243, + 29251, + 29269, + 29287, + 29297, + 29303, + 29311, + 29327, + 29333, + 29339, + 29347, + 29363, + 29383, + 29387, + 29389, + 29399, + 29401, + 29411, + 29423, + 29429, + 29437, + 29443, + 29453, + 29473, + 29483, + 29501, + 29527, + 29531, + 29537, + 29567, + 29569, + 29573, + 29581, + 29587, + 29599, + 29611, + 29629, + 29633, + 29641, + 29663, + 29669, + 29671, + 29683, + 29717, + 29723, + 29741, + 29753, + 29759, + 29761, + 29789, + 29803, + 29819, + 29833, + 29837, + 29851, + 29863, + 29867, + 29873, + 29879, + 29881, + 29917, + 29921, + 29927, + 29947, + 29959, + 29983, + 29989, + 30011, + 30013, + 30029, + 30047, + 30059, + 30071, + 30089, + 30091, + 30097, + 30103, + 30109, + 30113, + 30119, + 30133, + 30137, + 30139, + 30161, + 30169, + 30181, + 30187, + 30197, + 30203, + 30211, + 30223, + 30241, + 30253, + 30259, + 30269, + 30271, + 30293, + 30307, + 30313, + 30319, + 30323, + 30341, + 30347, + 30367, + 30389, + 30391, + 30403, + 30427, + 30431, + 30449, + 30467, + 30469, + 30491, + 30493, + 30497, + 30509, + 30517, + 30529, + 30539, + 30553, + 30557, + 30559, + 30577, + 30593, + 30631, + 30637, + 30643, + 30649, + 30661, + 30671, + 30677, + 30689, + 30697, + 30703, + 30707, + 30713, + 30727, + 30757, + 30763, + 30773, + 30781, + 30803, + 30809, + 30817, + 30829, + 30839, + 30841, + 30851, + 30853, + 30859, + 30869, + 30871, + 30881, + 30893, + 30911, + 30931, + 30937, + 30941, + 30949, + 30971, + 30977, + 30983, + 31013, + 31019, + 31033, + 31039, + 31051, + 31063, + 31069, + 31079, + 31081, + 31091, + 31121, + 31123, + 31139, + 31147, + 31151, + 31153, + 31159, + 31177, + 31181, + 31183, + 31189, + 31193, + 31219, + 31223, + 31231, + 31237, + 31247, + 31249, + 31253, + 31259, + 31267, + 31271, + 31277, + 31307, + 31319, + 31321, + 31327, + 31333, + 31337, + 31357, + 31379, + 31387, + 31391, + 31393, + 31397, + 31469, + 31477, + 31481, + 31489, + 31511, + 31513, + 31517, + 31531, + 31541, + 31543, + 31547, + 31567, + 31573, + 31583, + 31601, + 31607, + 31627, + 31643, + 31649, + 31657, + 31663, + 31667, + 31687, + 31699, + 31721, + 31723, + 31727, + 31729, + 31741, + 31751, + 31769, + 31771, + 31793, + 31799, + 31817, + 31847, + 31849, + 31859, + 31873, + 31883, + 31891, + 31907, + 31957, + 31963, + 31973, + 31981, + 31991, + 32003, + 32009, + 32027, + 32029, + 32051, + 32057, + 32059, + 32063, + 32069, + 32077, + 32083, + 32089, + 32099, + 32117, + 32119, + 32141, + 32143, + 32159, + 32173, + 32183, + 32189, + 32191, + 32203, + 32213, + 32233, + 32237, + 32251, + 32257, + 32261, + 32297, + 32299, + 32303, + 32309, + 32321, + 32323, + 32327, + 32341, + 32353, + 32359, + 32363, + 32369, + 32371, + 32377, + 32381, + 32401, + 32411, + 32413, + 32423, + 32429, + 32441, + 32443, + 32467, + 32479, + 32491, + 32497, + 32503, + 32507, + 32531, + 32533, + 32537, + 32561, + 32563, + 32569, + 32573, + 32579, + 32587, + 32603, + 32609, + 32611, + 32621, + 32633, + 32647, + 32653, + 32687, + 32693, + 32707, + 32713, + 32717, + 32719, + 32749, + 32771, + 32779, + 32783, + 32789, + 32797, + 32801, + 32803, + 32831, + 32833, + 32839, + 32843, + 32869, + 32887, + 32909, + 32911, + 32917, + 32933, + 32939, + 32941, + 32957, + 32969, + 32971, + 32983, + 32987, + 32993, + 32999, + 33013, + 33023, + 33029, + 33037, + 33049, + 33053, + 33071, + 33073, + 33083, + 33091, + 33107, + 33113, + 33119, + 33149, + 33151, + 33161, + 33179, + 33181, + 33191, + 33199, + 33203, + 33211, + 33223, + 33247, + 33287, + 33289, + 33301, + 33311, + 33317, + 33329, + 33331, + 33343, + 33347, + 33349, + 33353, + 33359, + 33377, + 33391, + 33403, + 33409, + 33413, + 33427, + 33457, + 33461, + 33469, + 33479, + 33487, + 33493, + 33503, + 33521, + 33529, + 33533, + 33547, + 33563, + 33569, + 33577, + 33581, + 33587, + 33589, + 33599, + 33601, + 33613, + 33617, + 33619, + 33623, + 33629, + 33637, + 33641, + 33647, + 33679, + 33703, + 33713, + 33721, + 33739, + 33749, + 33751, + 33757, + 33767, + 33769, + 33773, + 33791, + 33797, + 33809, + 33811, + 33827, + 33829, + 33851, + 33857, + 33863, + 33871, + 33889, + 33893, + 33911, + 33923, + 33931, + 33937, + 33941, + 33961, + 33967, + 33997, + 34019, + 34031, + 34033, + 34039, + 34057, + 34061, + 34123, + 34127, + 34129, + 34141, + 34147, + 34157, + 34159, + 34171, + 34183, + 34211, + 34213, + 34217, + 34231, + 34253, + 34259, + 34261, + 34267, + 34273, + 34283, + 34297, + 34301, + 34303, + 34313, + 34319, + 34327, + 34337, + 34351, + 34361, + 34367, + 34369, + 34381, + 34403, + 34421, + 34429, + 34439, + 34457, + 34469, + 34471, + 34483, + 34487, + 34499, + 34501, + 34511, + 34513, + 34519, + 34537, + 34543, + 34549, + 34583, + 34589, + 34591, + 34603, + 34607, + 34613, + 34631, + 34649, + 34651, + 34667, + 34673, + 34679, + 34687, + 34693, + 34703, + 34721, + 34729, + 34739, + 34747, + 34757, + 34759, + 34763, + 34781, + 34807, + 34819, + 34841, + 34843, + 34847, + 34849, + 34871, + 34877, + 34883, + 34897, + 34913, + 34919, + 34939, + 34949, + 34961, + 34963, + 34981, + 35023, + 35027, + 35051, + 35053, + 35059, + 35069, + 35081, + 35083, + 35089, + 35099, + 35107, + 35111, + 35117, + 35129, + 35141, + 35149, + 35153, + 35159, + 35171, + 35201, + 35221, + 35227, + 35251, + 35257, + 35267, + 35279, + 35281, + 35291, + 35311, + 35317, + 35323, + 35327, + 35339, + 35353, + 35363, + 35381, + 35393, + 35401, + 35407, + 35419, + 35423, + 35437, + 35447, + 35449, + 35461, + 35491, + 35507, + 35509, + 35521, + 35527, + 35531, + 35533, + 35537, + 35543, + 35569, + 35573, + 35591, + 35593, + 35597, + 35603, + 35617, + 35671, + 35677, + 35729, + 35731, + 35747, + 35753, + 35759, + 35771, + 35797, + 35801, + 35803, + 35809, + 35831, + 35837, + 35839, + 35851, + 35863, + 35869, + 35879, + 35897, + 35899, + 35911, + 35923, + 35933, + 35951, + 35963, + 35969, + 35977, + 35983, + 35993, + 35999, + 36007, + 36011, + 36013, + 36017, + 36037, + 36061, + 36067, + 36073, + 36083, + 36097, + 36107, + 36109, + 36131, + 36137, + 36151, + 36161, + 36187, + 36191, + 36209, + 36217, + 36229, + 36241, + 36251, + 36263, + 36269, + 36277, + 36293, + 36299, + 36307, + 36313, + 36319, + 36341, + 36343, + 36353, + 36373, + 36383, + 36389, + 36433, + 36451, + 36457, + 36467, + 36469, + 36473, + 36479, + 36493, + 36497, + 36523, + 36527, + 36529, + 36541, + 36551, + 36559, + 36563, + 36571, + 36583, + 36587, + 36599, + 36607, + 36629, + 36637, + 36643, + 36653, + 36671, + 36677, + 36683, + 36691, + 36697, + 36709, + 36713, + 36721, + 36739, + 36749, + 36761, + 36767, + 36779, + 36781, + 36787, + 36791, + 36793, + 36809, + 36821, + 36833, + 36847, + 36857, + 36871, + 36877, + 36887, + 36899, + 36901, + 36913, + 36919, + 36923, + 36929, + 36931, + 36943, + 36947, + 36973, + 36979, + 36997, + 37003, + 37013, + 37019, + 37021, + 37039, + 37049, + 37057, + 37061, + 37087, + 37097, + 37117, + 37123, + 37139, + 37159, + 37171, + 37181, + 37189, + 37199, + 37201, + 37217, + 37223, + 37243, + 37253, + 37273, + 37277, + 37307, + 37309, + 37313, + 37321, + 37337, + 37339, + 37357, + 37361, + 37363, + 37369, + 37379, + 37397, + 37409, + 37423, + 37441, + 37447, + 37463, + 37483, + 37489, + 37493, + 37501, + 37507, + 37511, + 37517, + 37529, + 37537, + 37547, + 37549, + 37561, + 37567, + 37571, + 37573, + 37579, + 37589, + 37591, + 37607, + 37619, + 37633, + 37643, + 37649, + 37657, + 37663, + 37691, + 37693, + 37699, + 37717, + 37747, + 37781, + 37783, + 37799, + 37811, + 37813, + 37831, + 37847, + 37853, + 37861, + 37871, + 37879, + 37889, + 37897, + 37907, + 37951, + 37957, + 37963, + 37967, + 37987, + 37991, + 37993, + 37997, + 38011, + 38039, + 38047, + 38053, + 38069, + 38083, + 38113, + 38119, + 38149, + 38153, + 38167, + 38177, + 38183, + 38189, + 38197, + 38201, + 38219, + 38231, + 38237, + 38239, + 38261, + 38273, + 38281, + 38287, + 38299, + 38303, + 38317, + 38321, + 38327, + 38329, + 38333, + 38351, + 38371, + 38377, + 38393, + 38431, + 38447, + 38449, + 38453, + 38459, + 38461, + 38501, + 38543, + 38557, + 38561, + 38567, + 38569, + 38593, + 38603, + 38609, + 38611, + 38629, + 38639, + 38651, + 38653, + 38669, + 38671, + 38677, + 38693, + 38699, + 38707, + 38711, + 38713, + 38723, + 38729, + 38737, + 38747, + 38749, + 38767, + 38783, + 38791, + 38803, + 38821, + 38833, + 38839, + 38851, + 38861, + 38867, + 38873, + 38891, + 38903, + 38917, + 38921, + 38923, + 38933, + 38953, + 38959, + 38971, + 38977, + 38993, + 39019, + 39023, + 39041, + 39043, + 39047, + 39079, + 39089, + 39097, + 39103, + 39107, + 39113, + 39119, + 39133, + 39139, + 39157, + 39161, + 39163, + 39181, + 39191, + 39199, + 39209, + 39217, + 39227, + 39229, + 39233, + 39239, + 39241, + 39251, + 39293, + 39301, + 39313, + 39317, + 39323, + 39341, + 39343, + 39359, + 39367, + 39371, + 39373, + 39383, + 39397, + 39409, + 39419, + 39439, + 39443, + 39451, + 39461, + 39499, + 39503, + 39509, + 39511, + 39521, + 39541, + 39551, + 39563, + 39569, + 39581, + 39607, + 39619, + 39623, + 39631, + 39659, + 39667, + 39671, + 39679, + 39703, + 39709, + 39719, + 39727, + 39733, + 39749, + 39761, + 39769, + 39779, + 39791, + 39799, + 39821, + 39827, + 39829, + 39839, + 39841, + 39847, + 39857, + 39863, + 39869, + 39877, + 39883, + 39887, + 39901, + 39929, + 39937, + 39953, + 39971, + 39979, + 39983, + 39989, + 40009, + 40013, + 40031, + 40037, + 40039, + 40063, + 40087, + 40093, + 40099, + 40111, + 40123, + 40127, + 40129, + 40151, + 40153, + 40163, + 40169, + 40177, + 40189, + 40193, + 40213, + 40231, + 40237, + 40241, + 40253, + 40277, + 40283, + 40289, + 40343, + 40351, + 40357, + 40361, + 40387, + 40423, + 40427, + 40429, + 40433, + 40459, + 40471, + 40483, + 40487, + 40493, + 40499, + 40507, + 40519, + 40529, + 40531, + 40543, + 40559, + 40577, + 40583, + 40591, + 40597, + 40609, + 40627, + 40637, + 40639, + 40693, + 40697, + 40699, + 40709, + 40739, + 40751, + 40759, + 40763, + 40771, + 40787, + 40801, + 40813, + 40819, + 40823, + 40829, + 40841, + 40847, + 40849, + 40853, + 40867, + 40879, + 40883, + 40897, + 40903, + 40927, + 40933, + 40939, + 40949, + 40961, + 40973, + 40993, + 41011, + 41017, + 41023, + 41039, + 41047, + 41051, + 41057, + 41077, + 41081, + 41113, + 41117, + 41131, + 41141, + 41143, + 41149, + 41161, + 41177, + 41179, + 41183, + 41189, + 41201, + 41203, + 41213, + 41221, + 41227, + 41231, + 41233, + 41243, + 41257, + 41263, + 41269, + 41281, + 41299, + 41333, + 41341, + 41351, + 41357, + 41381, + 41387, + 41389, + 41399, + 41411, + 41413, + 41443, + 41453, + 41467, + 41479, + 41491, + 41507, + 41513, + 41519, + 41521, + 41539, + 41543, + 41549, + 41579, + 41593, + 41597, + 41603, + 41609, + 41611, + 41617, + 41621, + 41627, + 41641, + 41647, + 41651, + 41659, + 41669, + 41681, + 41687, + 41719, + 41729, + 41737, + 41759, + 41761, + 41771, + 41777, + 41801, + 41809, + 41813, + 41843, + 41849, + 41851, + 41863, + 41879, + 41887, + 41893, + 41897, + 41903, + 41911, + 41927, + 41941, + 41947, + 41953, + 41957, + 41959, + 41969, + 41981, + 41983, + 41999, + 42013, + 42017, + 42019, + 42023, + 42043, + 42061, + 42071, + 42073, + 42083, + 42089, + 42101, + 42131, + 42139, + 42157, + 42169, + 42179, + 42181, + 42187, + 42193, + 42197, + 42209, + 42221, + 42223, + 42227, + 42239, + 42257, + 42281, + 42283, + 42293, + 42299, + 42307, + 42323, + 42331, + 42337, + 42349, + 42359, + 42373, + 42379, + 42391, + 42397, + 42403, + 42407, + 42409, + 42433, + 42437, + 42443, + 42451, + 42457, + 42461, + 42463, + 42467, + 42473, + 42487, + 42491, + 42499, + 42509, + 42533, + 42557, + 42569, + 42571, + 42577, + 42589, + 42611, + 42641, + 42643, + 42649, + 42667, + 42677, + 42683, + 42689, + 42697, + 42701, + 42703, + 42709, + 42719, + 42727, + 42737, + 42743, + 42751, + 42767, + 42773, + 42787, + 42793, + 42797, + 42821, + 42829, + 42839, + 42841, + 42853, + 42859, + 42863, + 42899, + 42901, + 42923, + 42929, + 42937, + 42943, + 42953, + 42961, + 42967, + 42979, + 42989, + 43003, + 43013, + 43019, + 43037, + 43049, + 43051, + 43063, + 43067, + 43093, + 43103, + 43117, + 43133, + 43151, + 43159, + 43177, + 43189, + 43201, + 43207, + 43223, + 43237, + 43261, + 43271, + 43283, + 43291, + 43313, + 43319, + 43321, + 43331, + 43391, + 43397, + 43399, + 43403, + 43411, + 43427, + 43441, + 43451, + 43457, + 43481, + 43487, + 43499, + 43517, + 43541, + 43543, + 43573, + 43577, + 43579, + 43591, + 43597, + 43607, + 43609, + 43613, + 43627, + 43633, + 43649, + 43651, + 43661, + 43669, + 43691, + 43711, + 43717, + 43721, + 43753, + 43759, + 43777, + 43781, + 43783, + 43787, + 43789, + 43793, + 43801, + 43853, + 43867, + 43889, + 43891, + 43913, + 43933, + 43943, + 43951, + 43961, + 43963, + 43969, + 43973, + 43987, + 43991, + 43997, + 44017, + 44021, + 44027, + 44029, + 44041, + 44053, + 44059, + 44071, + 44087, + 44089, + 44101, + 44111, + 44119, + 44123, + 44129, + 44131, + 44159, + 44171, + 44179, + 44189, + 44201, + 44203, + 44207, + 44221, + 44249, + 44257, + 44263, + 44267, + 44269, + 44273, + 44279, + 44281, + 44293, + 44351, + 44357, + 44371, + 44381, + 44383, + 44389, + 44417, + 44449, + 44453, + 44483, + 44491, + 44497, + 44501, + 44507, + 44519, + 44531, + 44533, + 44537, + 44543, + 44549, + 44563, + 44579, + 44587, + 44617, + 44621, + 44623, + 44633, + 44641, + 44647, + 44651, + 44657, + 44683, + 44687, + 44699, + 44701, + 44711, + 44729, + 44741, + 44753, + 44771, + 44773, + 44777, + 44789, + 44797, + 44809, + 44819, + 44839, + 44843, + 44851, + 44867, + 44879, + 44887, + 44893, + 44909, + 44917, + 44927, + 44939, + 44953, + 44959, + 44963, + 44971, + 44983, + 44987, + 45007, + 45013, + 45053, + 45061, + 45077, + 45083, + 45119, + 45121, + 45127, + 45131, + 45137, + 45139, + 45161, + 45179, + 45181, + 45191, + 45197, + 45233, + 45247, + 45259, + 45263, + 45281, + 45289, + 45293, + 45307, + 45317, + 45319, + 45329, + 45337, + 45341, + 45343, + 45361, + 45377, + 45389, + 45403, + 45413, + 45427, + 45433, + 45439, + 45481, + 45491, + 45497, + 45503, + 45523, + 45533, + 45541, + 45553, + 45557, + 45569, + 45587, + 45589, + 45599, + 45613, + 45631, + 45641, + 45659, + 45667, + 45673, + 45677, + 45691, + 45697, + 45707, + 45737, + 45751, + 45757, + 45763, + 45767, + 45779, + 45817, + 45821, + 45823, + 45827, + 45833, + 45841, + 45853, + 45863, + 45869, + 45887, + 45893, + 45943, + 45949, + 45953, + 45959, + 45971, + 45979, + 45989, + 46021, + 46027, + 46049, + 46051, + 46061, + 46073, + 46091, + 46093, + 46099, + 46103, + 46133, + 46141, + 46147, + 46153, + 46171, + 46181, + 46183, + 46187, + 46199, + 46219, + 46229, + 46237, + 46261, + 46271, + 46273, + 46279, + 46301, + 46307, + 46309, + 46327, + 46337, + 46349, + 46351, + 46381, + 46399, + 46411, + 46439, + 46441, + 46447, + 46451, + 46457, + 46471, + 46477, + 46489, + 46499, + 46507, + 46511, + 46523, + 46549, + 46559, + 46567, + 46573, + 46589, + 46591, + 46601, + 46619, + 46633, + 46639, + 46643, + 46649, + 46663, + 46679, + 46681, + 46687, + 46691, + 46703, + 46723, + 46727, + 46747, + 46751, + 46757, + 46769, + 46771, + 46807, + 46811, + 46817, + 46819, + 46829, + 46831, + 46853, + 46861, + 46867, + 46877, + 46889, + 46901, + 46919, + 46933, + 46957, + 46993, + 46997, + 47017, + 47041, + 47051, + 47057, + 47059, + 47087, + 47093, + 47111, + 47119, + 47123, + 47129, + 47137, + 47143, + 47147, + 47149, + 47161, + 47189, + 47207, + 47221, + 47237, + 47251, + 47269, + 47279, + 47287, + 47293, + 47297, + 47303, + 47309, + 47317, + 47339, + 47351, + 47353, + 47363, + 47381, + 47387, + 47389, + 47407, + 47417, + 47419, + 47431, + 47441, + 47459, + 47491, + 47497, + 47501, + 47507, + 47513, + 47521, + 47527, + 47533, + 47543, + 47563, + 47569, + 47581, + 47591, + 47599, + 47609, + 47623, + 47629, + 47639, + 47653, + 47657, + 47659, + 47681, + 47699, + 47701, + 47711, + 47713, + 47717, + 47737, + 47741, + 47743, + 47777, + 47779, + 47791, + 47797, + 47807, + 47809, + 47819, + 47837, + 47843, + 47857, + 47869, + 47881, + 47903, + 47911, + 47917, + 47933, + 47939, + 47947, + 47951, + 47963, + 47969, + 47977, + 47981, + 48017, + 48023, + 48029, + 48049, + 48073, + 48079, + 48091, + 48109, + 48119, + 48121, + 48131, + 48157, + 48163, + 48179, + 48187, + 48193, + 48197, + 48221, + 48239, + 48247, + 48259, + 48271, + 48281, + 48299, + 48311, + 48313, + 48337, + 48341, + 48353, + 48371, + 48383, + 48397, + 48407, + 48409, + 48413, + 48437, + 48449, + 48463, + 48473, + 48479, + 48481, + 48487, + 48491, + 48497, + 48523, + 48527, + 48533, + 48539, + 48541, + 48563, + 48571, + 48589, + 48593, + 48611, + 48619, + 48623, + 48647, + 48649, + 48661, + 48673, + 48677, + 48679, + 48731, + 48733, + 48751, + 48757, + 48761, + 48767, + 48779, + 48781, + 48787, + 48799, + 48809, + 48817, + 48821, + 48823, + 48847, + 48857, + 48859, + 48869, + 48871, + 48883, + 48889, + 48907, + 48947, + 48953, + 48973, + 48989, + 48991, + 49003, + 49009, + 49019, + 49031, + 49033, + 49037, + 49043, + 49057, + 49069, + 49081, + 49103, + 49109, + 49117, + 49121, + 49123, + 49139, + 49157, + 49169, + 49171, + 49177, + 49193, + 49199, + 49201, + 49207, + 49211, + 49223, + 49253, + 49261, + 49277, + 49279, + 49297, + 49307, + 49331, + 49333, + 49339, + 49363, + 49367, + 49369, + 49391, + 49393, + 49409, + 49411, + 49417, + 49429, + 49433, + 49451, + 49459, + 49463, + 49477, + 49481, + 49499, + 49523, + 49529, + 49531, + 49537, + 49547, + 49549, + 49559, + 49597, + 49603, + 49613, + 49627, + 49633, + 49639, + 49663, + 49667, + 49669, + 49681, + 49697, + 49711, + 49727, + 49739, + 49741, + 49747, + 49757, + 49783, + 49787, + 49789, + 49801, + 49807, + 49811, + 49823, + 49831, + 49843, + 49853, + 49871, + 49877, + 49891, + 49919, + 49921, + 49927, + 49937, + 49939, + 49943, + 49957, + 49991, + 49993, + 49999, + 50021, + 50023, + 50033, + 50047, + 50051, + 50053, + 50069, + 50077, + 50087, + 50093, + 50101, + 50111, + 50119, + 50123, + 50129, + 50131, + 50147, + 50153, + 50159, + 50177, + 50207, + 50221, + 50227, + 50231, + 50261, + 50263, + 50273, + 50287, + 50291, + 50311, + 50321, + 50329, + 50333, + 50341, + 50359, + 50363, + 50377, + 50383, + 50387, + 50411, + 50417, + 50423, + 50441, + 50459, + 50461, + 50497, + 50503, + 50513, + 50527, + 50539, + 50543, + 50549, + 50551, + 50581, + 50587, + 50591, + 50593, + 50599, + 50627, + 50647, + 50651, + 50671, + 50683, + 50707, + 50723, + 50741, + 50753, + 50767, + 50773, + 50777, + 50789, + 50821, + 50833, + 50839, + 50849, + 50857, + 50867, + 50873, + 50891, + 50893, + 50909, + 50923, + 50929, + 50951, + 50957, + 50969, + 50971, + 50989, + 50993, + 51001, + 51031, + 51043, + 51047, + 51059, + 51061, + 51071, + 51109, + 51131, + 51133, + 51137, + 51151, + 51157, + 51169, + 51193, + 51197, + 51199, + 51203, + 51217, + 51229, + 51239, + 51241, + 51257, + 51263, + 51283, + 51287, + 51307, + 51329, + 51341, + 51343, + 51347, + 51349, + 51361, + 51383, + 51407, + 51413, + 51419, + 51421, + 51427, + 51431, + 51437, + 51439, + 51449, + 51461, + 51473, + 51479, + 51481, + 51487, + 51503, + 51511, + 51517, + 51521, + 51539, + 51551, + 51563, + 51577, + 51581, + 51593, + 51599, + 51607, + 51613, + 51631, + 51637, + 51647, + 51659, + 51673, + 51679, + 51683, + 51691, + 51713, + 51719, + 51721, + 51749, + 51767, + 51769, + 51787, + 51797, + 51803, + 51817, + 51827, + 51829, + 51839, + 51853, + 51859, + 51869, + 51871, + 51893, + 51899, + 51907, + 51913, + 51929, + 51941, + 51949, + 51971, + 51973, + 51977, + 51991, + 52009, + 52021, + 52027, + 52051, + 52057, + 52067, + 52069, + 52081, + 52103, + 52121, + 52127, + 52147, + 52153, + 52163, + 52177, + 52181, + 52183, + 52189, + 52201, + 52223, + 52237, + 52249, + 52253, + 52259, + 52267, + 52289, + 52291, + 52301, + 52313, + 52321, + 52361, + 52363, + 52369, + 52379, + 52387, + 52391, + 52433, + 52453, + 52457, + 52489, + 52501, + 52511, + 52517, + 52529, + 52541, + 52543, + 52553, + 52561, + 52567, + 52571, + 52579, + 52583, + 52609, + 52627, + 52631, + 52639, + 52667, + 52673, + 52691, + 52697, + 52709, + 52711, + 52721, + 52727, + 52733, + 52747, + 52757, + 52769, + 52783, + 52807, + 52813, + 52817, + 52837, + 52859, + 52861, + 52879, + 52883, + 52889, + 52901, + 52903, + 52919, + 52937, + 52951, + 52957, + 52963, + 52967, + 52973, + 52981, + 52999, + 53003, + 53017, + 53047, + 53051, + 53069, + 53077, + 53087, + 53089, + 53093, + 53101, + 53113, + 53117, + 53129, + 53147, + 53149, + 53161, + 53171, + 53173, + 53189, + 53197, + 53201, + 53231, + 53233, + 53239, + 53267, + 53269, + 53279, + 53281, + 53299, + 53309, + 53323, + 53327, + 53353, + 53359, + 53377, + 53381, + 53401, + 53407, + 53411, + 53419, + 53437, + 53441, + 53453, + 53479, + 53503, + 53507, + 53527, + 53549, + 53551, + 53569, + 53591, + 53593, + 53597, + 53609, + 53611, + 53617, + 53623, + 53629, + 53633, + 53639, + 53653, + 53657, + 53681, + 53693, + 53699, + 53717, + 53719, + 53731, + 53759, + 53773, + 53777, + 53783, + 53791, + 53813, + 53819, + 53831, + 53849, + 53857, + 53861, + 53881, + 53887, + 53891, + 53897, + 53899, + 53917, + 53923, + 53927, + 53939, + 53951, + 53959, + 53987, + 53993, + 54001, + 54011, + 54013, + 54037, + 54049, + 54059, + 54083, + 54091, + 54101, + 54121, + 54133, + 54139, + 54151, + 54163, + 54167, + 54181, + 54193, + 54217, + 54251, + 54269, + 54277, + 54287, + 54293, + 54311, + 54319, + 54323, + 54331, + 54347, + 54361, + 54367, + 54371, + 54377, + 54401, + 54403, + 54409, + 54413, + 54419, + 54421, + 54437, + 54443, + 54449, + 54469, + 54493, + 54497, + 54499, + 54503, + 54517, + 54521, + 54539, + 54541, + 54547, + 54559, + 54563, + 54577, + 54581, + 54583, + 54601, + 54617, + 54623, + 54629, + 54631, + 54647, + 54667, + 54673, + 54679, + 54709, + 54713, + 54721, + 54727, + 54751, + 54767, + 54773, + 54779, + 54787, + 54799, + 54829, + 54833, + 54851, + 54869, + 54877, + 54881, + 54907, + 54917, + 54919, + 54941, + 54949, + 54959, + 54973, + 54979, + 54983, + 55001, + 55009, + 55021, + 55049, + 55051, + 55057, + 55061, + 55073, + 55079, + 55103, + 55109, + 55117, + 55127, + 55147, + 55163, + 55171, + 55201, + 55207, + 55213, + 55217, + 55219, + 55229, + 55243, + 55249, + 55259, + 55291, + 55313, + 55331, + 55333, + 55337, + 55339, + 55343, + 55351, + 55373, + 55381, + 55399, + 55411, + 55439, + 55441, + 55457, + 55469, + 55487, + 55501, + 55511, + 55529, + 55541, + 55547, + 55579, + 55589, + 55603, + 55609, + 55619, + 55621, + 55631, + 55633, + 55639, + 55661, + 55663, + 55667, + 55673, + 55681, + 55691, + 55697, + 55711, + 55717, + 55721, + 55733, + 55763, + 55787, + 55793, + 55799, + 55807, + 55813, + 55817, + 55819, + 55823, + 55829, + 55837, + 55843, + 55849, + 55871, + 55889, + 55897, + 55901, + 55903, + 55921, + 55927, + 55931, + 55933, + 55949, + 55967, + 55987, + 55997, + 56003, + 56009, + 56039, + 56041, + 56053, + 56081, + 56087, + 56093, + 56099, + 56101, + 56113, + 56123, + 56131, + 56149, + 56167, + 56171, + 56179, + 56197, + 56207, + 56209, + 56237, + 56239, + 56249, + 56263, + 56267, + 56269, + 56299, + 56311, + 56333, + 56359, + 56369, + 56377, + 56383, + 56393, + 56401, + 56417, + 56431, + 56437, + 56443, + 56453, + 56467, + 56473, + 56477, + 56479, + 56489, + 56501, + 56503, + 56509, + 56519, + 56527, + 56531, + 56533, + 56543, + 56569, + 56591, + 56597, + 56599, + 56611, + 56629, + 56633, + 56659, + 56663, + 56671, + 56681, + 56687, + 56701, + 56711, + 56713, + 56731, + 56737, + 56747, + 56767, + 56773, + 56779, + 56783, + 56807, + 56809, + 56813, + 56821, + 56827, + 56843, + 56857, + 56873, + 56891, + 56893, + 56897, + 56909, + 56911, + 56921, + 56923, + 56929, + 56941, + 56951, + 56957, + 56963, + 56983, + 56989, + 56993, + 56999, + 57037, + 57041, + 57047, + 57059, + 57073, + 57077, + 57089, + 57097, + 57107, + 57119, + 57131, + 57139, + 57143, + 57149, + 57163, + 57173, + 57179, + 57191, + 57193, + 57203, + 57221, + 57223, + 57241, + 57251, + 57259, + 57269, + 57271, + 57283, + 57287, + 57301, + 57329, + 57331, + 57347, + 57349, + 57367, + 57373, + 57383, + 57389, + 57397, + 57413, + 57427, + 57457, + 57467, + 57487, + 57493, + 57503, + 57527, + 57529, + 57557, + 57559, + 57571, + 57587, + 57593, + 57601, + 57637, + 57641, + 57649, + 57653, + 57667, + 57679, + 57689, + 57697, + 57709, + 57713, + 57719, + 57727, + 57731, + 57737, + 57751, + 57773, + 57781, + 57787, + 57791, + 57793, + 57803, + 57809, + 57829, + 57839, + 57847, + 57853, + 57859, + 57881, + 57899, + 57901, + 57917, + 57923, + 57943, + 57947, + 57973, + 57977, + 57991, + 58013, + 58027, + 58031, + 58043, + 58049, + 58057, + 58061, + 58067, + 58073, + 58099, + 58109, + 58111, + 58129, + 58147, + 58151, + 58153, + 58169, + 58171, + 58189, + 58193, + 58199, + 58207, + 58211, + 58217, + 58229, + 58231, + 58237, + 58243, + 58271, + 58309, + 58313, + 58321, + 58337, + 58363, + 58367, + 58369, + 58379, + 58391, + 58393, + 58403, + 58411, + 58417, + 58427, + 58439, + 58441, + 58451, + 58453, + 58477, + 58481, + 58511, + 58537, + 58543, + 58549, + 58567, + 58573, + 58579, + 58601, + 58603, + 58613, + 58631, + 58657, + 58661, + 58679, + 58687, + 58693, + 58699, + 58711, + 58727, + 58733, + 58741, + 58757, + 58763, + 58771, + 58787, + 58789, + 58831, + 58889, + 58897, + 58901, + 58907, + 58909, + 58913, + 58921, + 58937, + 58943, + 58963, + 58967, + 58979, + 58991, + 58997, + 59009, + 59011, + 59021, + 59023, + 59029, + 59051, + 59053, + 59063, + 59069, + 59077, + 59083, + 59093, + 59107, + 59113, + 59119, + 59123, + 59141, + 59149, + 59159, + 59167, + 59183, + 59197, + 59207, + 59209, + 59219, + 59221, + 59233, + 59239, + 59243, + 59263, + 59273, + 59281, + 59333, + 59341, + 59351, + 59357, + 59359, + 59369, + 59377, + 59387, + 59393, + 59399, + 59407, + 59417, + 59419, + 59441, + 59443, + 59447, + 59453, + 59467, + 59471, + 59473, + 59497, + 59509, + 59513, + 59539, + 59557, + 59561, + 59567, + 59581, + 59611, + 59617, + 59621, + 59627, + 59629, + 59651, + 59659, + 59663, + 59669, + 59671, + 59693, + 59699, + 59707, + 59723, + 59729, + 59743, + 59747, + 59753, + 59771, + 59779, + 59791, + 59797, + 59809, + 59833, + 59863, + 59879, + 59887, + 59921, + 59929, + 59951, + 59957, + 59971, + 59981, + 59999, + 60013, + 60017, + 60029, + 60037, + 60041, + 60077, + 60083, + 60089, + 60091, + 60101, + 60103, + 60107, + 60127, + 60133, + 60139, + 60149, + 60161, + 60167, + 60169, + 60209, + 60217, + 60223, + 60251, + 60257, + 60259, + 60271, + 60289, + 60293, + 60317, + 60331, + 60337, + 60343, + 60353, + 60373, + 60383, + 60397, + 60413, + 60427, + 60443, + 60449, + 60457, + 60493, + 60497, + 60509, + 60521, + 60527, + 60539, + 60589, + 60601, + 60607, + 60611, + 60617, + 60623, + 60631, + 60637, + 60647, + 60649, + 60659, + 60661, + 60679, + 60689, + 60703, + 60719, + 60727, + 60733, + 60737, + 60757, + 60761, + 60763, + 60773, + 60779, + 60793, + 60811, + 60821, + 60859, + 60869, + 60887, + 60889, + 60899, + 60901, + 60913, + 60917, + 60919, + 60923, + 60937, + 60943, + 60953, + 60961, + 61001, + 61007, + 61027, + 61031, + 61043, + 61051, + 61057, + 61091, + 61099, + 61121, + 61129, + 61141, + 61151, + 61153, + 61169, + 61211, + 61223, + 61231, + 61253, + 61261, + 61283, + 61291, + 61297, + 61331, + 61333, + 61339, + 61343, + 61357, + 61363, + 61379, + 61381, + 61403, + 61409, + 61417, + 61441, + 61463, + 61469, + 61471, + 61483, + 61487, + 61493, + 61507, + 61511, + 61519, + 61543, + 61547, + 61553, + 61559, + 61561, + 61583, + 61603, + 61609, + 61613, + 61627, + 61631, + 61637, + 61643, + 61651, + 61657, + 61667, + 61673, + 61681, + 61687, + 61703, + 61717, + 61723, + 61729, + 61751, + 61757, + 61781, + 61813, + 61819, + 61837, + 61843, + 61861, + 61871, + 61879, + 61909, + 61927, + 61933, + 61949, + 61961, + 61967, + 61979, + 61981, + 61987, + 61991, + 62003, + 62011, + 62017, + 62039, + 62047, + 62053, + 62057, + 62071, + 62081, + 62099, + 62119, + 62129, + 62131, + 62137, + 62141, + 62143, + 62171, + 62189, + 62191, + 62201, + 62207, + 62213, + 62219, + 62233, + 62273, + 62297, + 62299, + 62303, + 62311, + 62323, + 62327, + 62347, + 62351, + 62383, + 62401, + 62417, + 62423, + 62459, + 62467, + 62473, + 62477, + 62483, + 62497, + 62501, + 62507, + 62533, + 62539, + 62549, + 62563, + 62581, + 62591, + 62597, + 62603, + 62617, + 62627, + 62633, + 62639, + 62653, + 62659, + 62683, + 62687, + 62701, + 62723, + 62731, + 62743, + 62753, + 62761, + 62773, + 62791, + 62801, + 62819, + 62827, + 62851, + 62861, + 62869, + 62873, + 62897, + 62903, + 62921, + 62927, + 62929, + 62939, + 62969, + 62971, + 62981, + 62983, + 62987, + 62989, + 63029, + 63031, + 63059, + 63067, + 63073, + 63079, + 63097, + 63103, + 63113, + 63127, + 63131, + 63149, + 63179, + 63197, + 63199, + 63211, + 63241, + 63247, + 63277, + 63281, + 63299, + 63311, + 63313, + 63317, + 63331, + 63337, + 63347, + 63353, + 63361, + 63367, + 63377, + 63389, + 63391, + 63397, + 63409, + 63419, + 63421, + 63439, + 63443, + 63463, + 63467, + 63473, + 63487, + 63493, + 63499, + 63521, + 63527, + 63533, + 63541, + 63559, + 63577, + 63587, + 63589, + 63599, + 63601, + 63607, + 63611, + 63617, + 63629, + 63647, + 63649, + 63659, + 63667, + 63671, + 63689, + 63691, + 63697, + 63703, + 63709, + 63719, + 63727, + 63737, + 63743, + 63761, + 63773, + 63781, + 63793, + 63799, + 63803, + 63809, + 63823, + 63839, + 63841, + 63853, + 63857, + 63863, + 63901, + 63907, + 63913, + 63929, + 63949, + 63977, + 63997, + 64007, + 64013, + 64019, + 64033, + 64037, + 64063, + 64067, + 64081, + 64091, + 64109, + 64123, + 64151, + 64153, + 64157, + 64171, + 64187, + 64189, + 64217, + 64223, + 64231, + 64237, + 64271, + 64279, + 64283, + 64301, + 64303, + 64319, + 64327, + 64333, + 64373, + 64381, + 64399, + 64403, + 64433, + 64439, + 64451, + 64453, + 64483, + 64489, + 64499, + 64513, + 64553, + 64567, + 64577, + 64579, + 64591, + 64601, + 64609, + 64613, + 64621, + 64627, + 64633, + 64661, + 64663, + 64667, + 64679, + 64693, + 64709, + 64717, + 64747, + 64763, + 64781, + 64783, + 64793, + 64811, + 64817, + 64849, + 64853, + 64871, + 64877, + 64879, + 64891, + 64901, + 64919, + 64921, + 64927, + 64937, + 64951, + 64969, + 64997, + 65003, + 65011, + 65027, + 65029, + 65033, + 65053, + 65063, + 65071, + 65089, + 65099, + 65101, + 65111, + 65119, + 65123, + 65129, + 65141, + 65147, + 65167, + 65171, + 65173, + 65179, + 65183, + 65203, + 65213, + 65239, + 65257, + 65267, + 65269, + 65287, + 65293, + 65309, + 65323, + 65327, + 65353, + 65357, + 65371, + 65381, + 65393, + 65407, + 65413, + 65419, + 65423, + 65437, + 65447, + 65449, + 65479, + 65497, + 65519, + 65521, + 65537, + 65539, + 65543, + 65551, + 65557, + 65563, + 65579, + 65581, + 65587, + 65599, + 65609, + 65617, + 65629, + 65633, + 65647, + 65651, + 65657, + 65677, + 65687, + 65699, + 65701, + 65707, + 65713, + 65717, + 65719, + 65729, + 65731, + 65761, + 65777, + 65789, + 65809, + 65827, + 65831, + 65837, + 65839, + 65843, + 65851, + 65867, + 65881, + 65899, + 65921, + 65927, + 65929, + 65951, + 65957, + 65963, + 65981, + 65983, + 65993, + 66029, + 66037, + 66041, + 66047, + 66067, + 66071, + 66083, + 66089, + 66103, + 66107, + 66109, + 66137, + 66161, + 66169, + 66173, + 66179, + 66191, + 66221, + 66239, + 66271, + 66293, + 66301, + 66337, + 66343, + 66347, + 66359, + 66361, + 66373, + 66377, + 66383, + 66403, + 66413, + 66431, + 66449, + 66457, + 66463, + 66467, + 66491, + 66499, + 66509, + 66523, + 66529, + 66533, + 66541, + 66553, + 66569, + 66571, + 66587, + 66593, + 66601, + 66617, + 66629, + 66643, + 66653, + 66683, + 66697, + 66701, + 66713, + 66721, + 66733, + 66739, + 66749, + 66751, + 66763, + 66791, + 66797, + 66809, + 66821, + 66841, + 66851, + 66853, + 66863, + 66877, + 66883, + 66889, + 66919, + 66923, + 66931, + 66943, + 66947, + 66949, + 66959, + 66973, + 66977, + 67003, + 67021, + 67033, + 67043, + 67049, + 67057, + 67061, + 67073, + 67079, + 67103, + 67121, + 67129, + 67139, + 67141, + 67153, + 67157, + 67169, + 67181, + 67187, + 67189, + 67211, + 67213, + 67217, + 67219, + 67231, + 67247, + 67261, + 67271, + 67273, + 67289, + 67307, + 67339, + 67343, + 67349, + 67369, + 67391, + 67399, + 67409, + 67411, + 67421, + 67427, + 67429, + 67433, + 67447, + 67453, + 67477, + 67481, + 67489, + 67493, + 67499, + 67511, + 67523, + 67531, + 67537, + 67547, + 67559, + 67567, + 67577, + 67579, + 67589, + 67601, + 67607, + 67619, + 67631, + 67651, + 67679, + 67699, + 67709, + 67723, + 67733, + 67741, + 67751, + 67757, + 67759, + 67763, + 67777, + 67783, + 67789, + 67801, + 67807, + 67819, + 67829, + 67843, + 67853, + 67867, + 67883, + 67891, + 67901, + 67927, + 67931, + 67933, + 67939, + 67943, + 67957, + 67961, + 67967, + 67979, + 67987, + 67993, + 68023, + 68041, + 68053, + 68059, + 68071, + 68087, + 68099, + 68111, + 68113, + 68141, + 68147, + 68161, + 68171, + 68207, + 68209, + 68213, + 68219, + 68227, + 68239, + 68261, + 68279, + 68281, + 68311, + 68329, + 68351, + 68371, + 68389, + 68399, + 68437, + 68443, + 68447, + 68449, + 68473, + 68477, + 68483, + 68489, + 68491, + 68501, + 68507, + 68521, + 68531, + 68539, + 68543, + 68567, + 68581, + 68597, + 68611, + 68633, + 68639, + 68659, + 68669, + 68683, + 68687, + 68699, + 68711, + 68713, + 68729, + 68737, + 68743, + 68749, + 68767, + 68771, + 68777, + 68791, + 68813, + 68819, + 68821, + 68863, + 68879, + 68881, + 68891, + 68897, + 68899, + 68903, + 68909, + 68917, + 68927, + 68947, + 68963, + 68993, + 69001, + 69011, + 69019, + 69029, + 69031, + 69061, + 69067, + 69073, + 69109, + 69119, + 69127, + 69143, + 69149, + 69151, + 69163, + 69191, + 69193, + 69197, + 69203, + 69221, + 69233, + 69239, + 69247, + 69257, + 69259, + 69263, + 69313, + 69317, + 69337, + 69341, + 69371, + 69379, + 69383, + 69389, + 69401, + 69403, + 69427, + 69431, + 69439, + 69457, + 69463, + 69467, + 69473, + 69481, + 69491, + 69493, + 69497, + 69499, + 69539, + 69557, + 69593, + 69623, + 69653, + 69661, + 69677, + 69691, + 69697, + 69709, + 69737, + 69739, + 69761, + 69763, + 69767, + 69779, + 69809, + 69821, + 69827, + 69829, + 69833, + 69847, + 69857, + 69859, + 69877, + 69899, + 69911, + 69929, + 69931, + 69941, + 69959, + 69991, + 69997, + 70001, + 70003, + 70009, + 70019, + 70039, + 70051, + 70061, + 70067, + 70079, + 70099, + 70111, + 70117, + 70121, + 70123, + 70139, + 70141, + 70157, + 70163, + 70177, + 70181, + 70183, + 70199, + 70201, + 70207, + 70223, + 70229, + 70237, + 70241, + 70249, + 70271, + 70289, + 70297, + 70309, + 70313, + 70321, + 70327, + 70351, + 70373, + 70379, + 70381, + 70393, + 70423, + 70429, + 70439, + 70451, + 70457, + 70459, + 70481, + 70487, + 70489, + 70501, + 70507, + 70529, + 70537, + 70549, + 70571, + 70573, + 70583, + 70589, + 70607, + 70619, + 70621, + 70627, + 70639, + 70657, + 70663, + 70667, + 70687, + 70709, + 70717, + 70729, + 70753, + 70769, + 70783, + 70793, + 70823, + 70841, + 70843, + 70849, + 70853, + 70867, + 70877, + 70879, + 70891, + 70901, + 70913, + 70919, + 70921, + 70937, + 70949, + 70951, + 70957, + 70969, + 70979, + 70981, + 70991, + 70997, + 70999, + 71011, + 71023, + 71039, + 71059, + 71069, + 71081, + 71089, + 71119, + 71129, + 71143, + 71147, + 71153, + 71161, + 71167, + 71171, + 71191, + 71209, + 71233, + 71237, + 71249, + 71257, + 71261, + 71263, + 71287, + 71293, + 71317, + 71327, + 71329, + 71333, + 71339, + 71341, + 71347, + 71353, + 71359, + 71363, + 71387, + 71389, + 71399, + 71411, + 71413, + 71419, + 71429, + 71437, + 71443, + 71453, + 71471, + 71473, + 71479, + 71483, + 71503, + 71527, + 71537, + 71549, + 71551, + 71563, + 71569, + 71593, + 71597, + 71633, + 71647, + 71663, + 71671, + 71693, + 71699, + 71707, + 71711, + 71713, + 71719, + 71741, + 71761, + 71777, + 71789, + 71807, + 71809, + 71821, + 71837, + 71843, + 71849, + 71861, + 71867, + 71879, + 71881, + 71887, + 71899, + 71909, + 71917, + 71933, + 71941, + 71947, + 71963, + 71971, + 71983, + 71987, + 71993, + 71999, + 72019, + 72031, + 72043, + 72047, + 72053, + 72073, + 72077, + 72089, + 72091, + 72101, + 72103, + 72109, + 72139, + 72161, + 72167, + 72169, + 72173, + 72211, + 72221, + 72223, + 72227, + 72229, + 72251, + 72253, + 72269, + 72271, + 72277, + 72287, + 72307, + 72313, + 72337, + 72341, + 72353, + 72367, + 72379, + 72383, + 72421, + 72431, + 72461, + 72467, + 72469, + 72481, + 72493, + 72497, + 72503, + 72533, + 72547, + 72551, + 72559, + 72577, + 72613, + 72617, + 72623, + 72643, + 72647, + 72649, + 72661, + 72671, + 72673, + 72679, + 72689, + 72701, + 72707, + 72719, + 72727, + 72733, + 72739, + 72763, + 72767, + 72797, + 72817, + 72823, + 72859, + 72869, + 72871, + 72883, + 72889, + 72893, + 72901, + 72907, + 72911, + 72923, + 72931, + 72937, + 72949, + 72953, + 72959, + 72973, + 72977, + 72997, + 73009, + 73013, + 73019, + 73037, + 73039, + 73043, + 73061, + 73063, + 73079, + 73091, + 73121, + 73127, + 73133, + 73141, + 73181, + 73189, + 73237, + 73243, + 73259, + 73277, + 73291, + 73303, + 73309, + 73327, + 73331, + 73351, + 73361, + 73363, + 73369, + 73379, + 73387, + 73417, + 73421, + 73433, + 73453, + 73459, + 73471, + 73477, + 73483, + 73517, + 73523, + 73529, + 73547, + 73553, + 73561, + 73571, + 73583, + 73589, + 73597, + 73607, + 73609, + 73613, + 73637, + 73643, + 73651, + 73673, + 73679, + 73681, + 73693, + 73699, + 73709, + 73721, + 73727, + 73751, + 73757, + 73771, + 73783, + 73819, + 73823, + 73847, + 73849, + 73859, + 73867, + 73877, + 73883, + 73897, + 73907, + 73939, + 73943, + 73951, + 73961, + 73973, + 73999, + 74017, + 74021, + 74027, + 74047, + 74051, + 74071, + 74077, + 74093, + 74099, + 74101, + 74131, + 74143, + 74149, + 74159, + 74161, + 74167, + 74177, + 74189, + 74197, + 74201, + 74203, + 74209, + 74219, + 74231, + 74257, + 74279, + 74287, + 74293, + 74297, + 74311, + 74317, + 74323, + 74353, + 74357, + 74363, + 74377, + 74381, + 74383, + 74411, + 74413, + 74419, + 74441, + 74449, + 74453, + 74471, + 74489, + 74507, + 74509, + 74521, + 74527, + 74531, + 74551, + 74561, + 74567, + 74573, + 74587, + 74597, + 74609, + 74611, + 74623, + 74653, + 74687, + 74699, + 74707, + 74713, + 74717, + 74719, + 74729, + 74731, + 74747, + 74759, + 74761, + 74771, + 74779, + 74797, + 74821, + 74827, + 74831, + 74843, + 74857, + 74861, + 74869, + 74873, + 74887, + 74891, + 74897, + 74903, + 74923, + 74929, + 74933, + 74941, + 74959, + 75011, + 75013, + 75017, + 75029, + 75037, + 75041, + 75079, + 75083, + 75109, + 75133, + 75149, + 75161, + 75167, + 75169, + 75181, + 75193, + 75209, + 75211, + 75217, + 75223, + 75227, + 75239, + 75253, + 75269, + 75277, + 75289, + 75307, + 75323, + 75329, + 75337, + 75347, + 75353, + 75367, + 75377, + 75389, + 75391, + 75401, + 75403, + 75407, + 75431, + 75437, + 75479, + 75503, + 75511, + 75521, + 75527, + 75533, + 75539, + 75541, + 75553, + 75557, + 75571, + 75577, + 75583, + 75611, + 75617, + 75619, + 75629, + 75641, + 75653, + 75659, + 75679, + 75683, + 75689, + 75703, + 75707, + 75709, + 75721, + 75731, + 75743, + 75767, + 75773, + 75781, + 75787, + 75793, + 75797, + 75821, + 75833, + 75853, + 75869, + 75883, + 75913, + 75931, + 75937, + 75941, + 75967, + 75979, + 75983, + 75989, + 75991, + 75997, + 76001, + 76003, + 76031, + 76039, + 76079, + 76081, + 76091, + 76099, + 76103, + 76123, + 76129, + 76147, + 76157, + 76159, + 76163, + 76207, + 76213, + 76231, + 76243, + 76249, + 76253, + 76259, + 76261, + 76283, + 76289, + 76303, + 76333, + 76343, + 76367, + 76369, + 76379, + 76387, + 76403, + 76421, + 76423, + 76441, + 76463, + 76471, + 76481, + 76487, + 76493, + 76507, + 76511, + 76519, + 76537, + 76541, + 76543, + 76561, + 76579, + 76597, + 76603, + 76607, + 76631, + 76649, + 76651, + 76667, + 76673, + 76679, + 76697, + 76717, + 76733, + 76753, + 76757, + 76771, + 76777, + 76781, + 76801, + 76819, + 76829, + 76831, + 76837, + 76847, + 76871, + 76873, + 76883, + 76907, + 76913, + 76919, + 76943, + 76949, + 76961, + 76963, + 76991, + 77003, + 77017, + 77023, + 77029, + 77041, + 77047, + 77069, + 77081, + 77093, + 77101, + 77137, + 77141, + 77153, + 77167, + 77171, + 77191, + 77201, + 77213, + 77237, + 77239, + 77243, + 77249, + 77261, + 77263, + 77267, + 77269, + 77279, + 77291, + 77317, + 77323, + 77339, + 77347, + 77351, + 77359, + 77369, + 77377, + 77383, + 77417, + 77419, + 77431, + 77447, + 77471, + 77477, + 77479, + 77489, + 77491, + 77509, + 77513, + 77521, + 77527, + 77543, + 77549, + 77551, + 77557, + 77563, + 77569, + 77573, + 77587, + 77591, + 77611, + 77617, + 77621, + 77641, + 77647, + 77659, + 77681, + 77687, + 77689, + 77699, + 77711, + 77713, + 77719, + 77723, + 77731, + 77743, + 77747, + 77761, + 77773, + 77783, + 77797, + 77801, + 77813, + 77839, + 77849, + 77863, + 77867, + 77893, + 77899, + 77929, + 77933, + 77951, + 77969, + 77977, + 77983, + 77999, + 78007, + 78017, + 78031, + 78041, + 78049, + 78059, + 78079, + 78101, + 78121, + 78137, + 78139, + 78157, + 78163, + 78167, + 78173, + 78179, + 78191, + 78193, + 78203, + 78229, + 78233, + 78241, + 78259, + 78277, + 78283, + 78301, + 78307, + 78311, + 78317, + 78341, + 78347, + 78367, + 78401, + 78427, + 78437, + 78439, + 78467, + 78479, + 78487, + 78497, + 78509, + 78511, + 78517, + 78539, + 78541, + 78553, + 78569, + 78571, + 78577, + 78583, + 78593, + 78607, + 78623, + 78643, + 78649, + 78653, + 78691, + 78697, + 78707, + 78713, + 78721, + 78737, + 78779, + 78781, + 78787, + 78791, + 78797, + 78803, + 78809, + 78823, + 78839, + 78853, + 78857, + 78877, + 78887, + 78889, + 78893, + 78901, + 78919, + 78929, + 78941, + 78977, + 78979, + 78989, + 79031, + 79039, + 79043, + 79063, + 79087, + 79103, + 79111, + 79133, + 79139, + 79147, + 79151, + 79153, + 79159, + 79181, + 79187, + 79193, + 79201, + 79229, + 79231, + 79241, + 79259, + 79273, + 79279, + 79283, + 79301, + 79309, + 79319, + 79333, + 79337, + 79349, + 79357, + 79367, + 79379, + 79393, + 79397, + 79399, + 79411, + 79423, + 79427, + 79433, + 79451, + 79481, + 79493, + 79531, + 79537, + 79549, + 79559, + 79561, + 79579, + 79589, + 79601, + 79609, + 79613, + 79621, + 79627, + 79631, + 79633, + 79657, + 79669, + 79687, + 79691, + 79693, + 79697, + 79699, + 79757, + 79769, + 79777, + 79801, + 79811, + 79813, + 79817, + 79823, + 79829, + 79841, + 79843, + 79847, + 79861, + 79867, + 79873, + 79889, + 79901, + 79903, + 79907, + 79939, + 79943, + 79967, + 79973, + 79979, + 79987, + 79997, + 79999, + 80021, + 80039, + 80051, + 80071, + 80077, + 80107, + 80111, + 80141, + 80147, + 80149, + 80153, + 80167, + 80173, + 80177, + 80191, + 80207, + 80209, + 80221, + 80231, + 80233, + 80239, + 80251, + 80263, + 80273, + 80279, + 80287, + 80309, + 80317, + 80329, + 80341, + 80347, + 80363, + 80369, + 80387, + 80407, + 80429, + 80447, + 80449, + 80471, + 80473, + 80489, + 80491, + 80513, + 80527, + 80537, + 80557, + 80567, + 80599, + 80603, + 80611, + 80621, + 80627, + 80629, + 80651, + 80657, + 80669, + 80671, + 80677, + 80681, + 80683, + 80687, + 80701, + 80713, + 80737, + 80747, + 80749, + 80761, + 80777, + 80779, + 80783, + 80789, + 80803, + 80809, + 80819, + 80831, + 80833, + 80849, + 80863, + 80897, + 80909, + 80911, + 80917, + 80923, + 80929, + 80933, + 80953, + 80963, + 80989, + 81001, + 81013, + 81017, + 81019, + 81023, + 81031, + 81041, + 81043, + 81047, + 81049, + 81071, + 81077, + 81083, + 81097, + 81101, + 81119, + 81131, + 81157, + 81163, + 81173, + 81181, + 81197, + 81199, + 81203, + 81223, + 81233, + 81239, + 81281, + 81283, + 81293, + 81299, + 81307, + 81331, + 81343, + 81349, + 81353, + 81359, + 81371, + 81373, + 81401, + 81409, + 81421, + 81439, + 81457, + 81463, + 81509, + 81517, + 81527, + 81533, + 81547, + 81551, + 81553, + 81559, + 81563, + 81569, + 81611, + 81619, + 81629, + 81637, + 81647, + 81649, + 81667, + 81671, + 81677, + 81689, + 81701, + 81703, + 81707, + 81727, + 81737, + 81749, + 81761, + 81769, + 81773, + 81799, + 81817, + 81839, + 81847, + 81853, + 81869, + 81883, + 81899, + 81901, + 81919, + 81929, + 81931, + 81937, + 81943, + 81953, + 81967, + 81971, + 81973, + 82003, + 82007, + 82009, + 82013, + 82021, + 82031, + 82037, + 82039, + 82051, + 82067, + 82073, + 82129, + 82139, + 82141, + 82153, + 82163, + 82171, + 82183, + 82189, + 82193, + 82207, + 82217, + 82219, + 82223, + 82231, + 82237, + 82241, + 82261, + 82267, + 82279, + 82301, + 82307, + 82339, + 82349, + 82351, + 82361, + 82373, + 82387, + 82393, + 82421, + 82457, + 82463, + 82469, + 82471, + 82483, + 82487, + 82493, + 82499, + 82507, + 82529, + 82531, + 82549, + 82559, + 82561, + 82567, + 82571, + 82591, + 82601, + 82609, + 82613, + 82619, + 82633, + 82651, + 82657, + 82699, + 82721, + 82723, + 82727, + 82729, + 82757, + 82759, + 82763, + 82781, + 82787, + 82793, + 82799, + 82811, + 82813, + 82837, + 82847, + 82883, + 82889, + 82891, + 82903, + 82913, + 82939, + 82963, + 82981, + 82997, + 83003, + 83009, + 83023, + 83047, + 83059, + 83063, + 83071, + 83077, + 83089, + 83093, + 83101, + 83117, + 83137, + 83177, + 83203, + 83207, + 83219, + 83221, + 83227, + 83231, + 83233, + 83243, + 83257, + 83267, + 83269, + 83273, + 83299, + 83311, + 83339, + 83341, + 83357, + 83383, + 83389, + 83399, + 83401, + 83407, + 83417, + 83423, + 83431, + 83437, + 83443, + 83449, + 83459, + 83471, + 83477, + 83497, + 83537, + 83557, + 83561, + 83563, + 83579, + 83591, + 83597, + 83609, + 83617, + 83621, + 83639, + 83641, + 83653, + 83663, + 83689, + 83701, + 83717, + 83719, + 83737, + 83761, + 83773, + 83777, + 83791, + 83813, + 83833, + 83843, + 83857, + 83869, + 83873, + 83891, + 83903, + 83911, + 83921, + 83933, + 83939, + 83969, + 83983, + 83987, + 84011, + 84017, + 84047, + 84053, + 84059, + 84061, + 84067, + 84089, + 84121, + 84127, + 84131, + 84137, + 84143, + 84163, + 84179, + 84181, + 84191, + 84199, + 84211, + 84221, + 84223, + 84229, + 84239, + 84247, + 84263, + 84299, + 84307, + 84313, + 84317, + 84319, + 84347, + 84349, + 84377, + 84389, + 84391, + 84401, + 84407, + 84421, + 84431, + 84437, + 84443, + 84449, + 84457, + 84463, + 84467, + 84481, + 84499, + 84503, + 84509, + 84521, + 84523, + 84533, + 84551, + 84559, + 84589, + 84629, + 84631, + 84649, + 84653, + 84659, + 84673, + 84691, + 84697, + 84701, + 84713, + 84719, + 84731, + 84737, + 84751, + 84761, + 84787, + 84793, + 84809, + 84811, + 84827, + 84857, + 84859, + 84869, + 84871, + 84913, + 84919, + 84947, + 84961, + 84967, + 84977, + 84979, + 84991, + 85009, + 85021, + 85027, + 85037, + 85049, + 85061, + 85081, + 85087, + 85091, + 85093, + 85103, + 85109, + 85121, + 85133, + 85147, + 85159, + 85193, + 85199, + 85201, + 85213, + 85223, + 85229, + 85237, + 85243, + 85247, + 85259, + 85297, + 85303, + 85313, + 85331, + 85333, + 85361, + 85363, + 85369, + 85381, + 85411, + 85427, + 85429, + 85439, + 85447, + 85451, + 85453, + 85469, + 85487, + 85513, + 85517, + 85523, + 85531, + 85549, + 85571, + 85577, + 85597, + 85601, + 85607, + 85619, + 85621, + 85627, + 85639, + 85643, + 85661, + 85667, + 85669, + 85691, + 85703, + 85711, + 85717, + 85733, + 85751, + 85781, + 85793, + 85817, + 85819, + 85829, + 85831, + 85837, + 85843, + 85847, + 85853, + 85889, + 85903, + 85909, + 85931, + 85933, + 85991, + 85999, + 86011, + 86017, + 86027, + 86029, + 86069, + 86077, + 86083, + 86111, + 86113, + 86117, + 86131, + 86137, + 86143, + 86161, + 86171, + 86179, + 86183, + 86197, + 86201, + 86209, + 86239, + 86243, + 86249, + 86257, + 86263, + 86269, + 86287, + 86291, + 86293, + 86297, + 86311, + 86323, + 86341, + 86351, + 86353, + 86357, + 86369, + 86371, + 86381, + 86389, + 86399, + 86413, + 86423, + 86441, + 86453, + 86461, + 86467, + 86477, + 86491, + 86501, + 86509, + 86531, + 86533, + 86539, + 86561, + 86573, + 86579, + 86587, + 86599, + 86627, + 86629, + 86677, + 86689, + 86693, + 86711, + 86719, + 86729, + 86743, + 86753, + 86767, + 86771, + 86783, + 86813, + 86837, + 86843, + 86851, + 86857, + 86861, + 86869, + 86923, + 86927, + 86929, + 86939, + 86951, + 86959, + 86969, + 86981, + 86993, + 87011, + 87013, + 87037, + 87041, + 87049, + 87071, + 87083, + 87103, + 87107, + 87119, + 87121, + 87133, + 87149, + 87151, + 87179, + 87181, + 87187, + 87211, + 87221, + 87223, + 87251, + 87253, + 87257, + 87277, + 87281, + 87293, + 87299, + 87313, + 87317, + 87323, + 87337, + 87359, + 87383, + 87403, + 87407, + 87421, + 87427, + 87433, + 87443, + 87473, + 87481, + 87491, + 87509, + 87511, + 87517, + 87523, + 87539, + 87541, + 87547, + 87553, + 87557, + 87559, + 87583, + 87587, + 87589, + 87613, + 87623, + 87629, + 87631, + 87641, + 87643, + 87649, + 87671, + 87679, + 87683, + 87691, + 87697, + 87701, + 87719, + 87721, + 87739, + 87743, + 87751, + 87767, + 87793, + 87797, + 87803, + 87811, + 87833, + 87853, + 87869, + 87877, + 87881, + 87887, + 87911, + 87917, + 87931, + 87943, + 87959, + 87961, + 87973, + 87977, + 87991, + 88001, + 88003, + 88007, + 88019, + 88037, + 88069, + 88079, + 88093, + 88117, + 88129, + 88169, + 88177, + 88211, + 88223, + 88237, + 88241, + 88259, + 88261, + 88289, + 88301, + 88321, + 88327, + 88337, + 88339, + 88379, + 88397, + 88411, + 88423, + 88427, + 88463, + 88469, + 88471, + 88493, + 88499, + 88513, + 88523, + 88547, + 88589, + 88591, + 88607, + 88609, + 88643, + 88651, + 88657, + 88661, + 88663, + 88667, + 88681, + 88721, + 88729, + 88741, + 88747, + 88771, + 88789, + 88793, + 88799, + 88801, + 88807, + 88811, + 88813, + 88817, + 88819, + 88843, + 88853, + 88861, + 88867, + 88873, + 88883, + 88897, + 88903, + 88919, + 88937, + 88951, + 88969, + 88993, + 88997, + 89003, + 89009, + 89017, + 89021, + 89041, + 89051, + 89057, + 89069, + 89071, + 89083, + 89087, + 89101, + 89107, + 89113, + 89119, + 89123, + 89137, + 89153, + 89189, + 89203, + 89209, + 89213, + 89227, + 89231, + 89237, + 89261, + 89269, + 89273, + 89293, + 89303, + 89317, + 89329, + 89363, + 89371, + 89381, + 89387, + 89393, + 89399, + 89413, + 89417, + 89431, + 89443, + 89449, + 89459, + 89477, + 89491, + 89501, + 89513, + 89519, + 89521, + 89527, + 89533, + 89561, + 89563, + 89567, + 89591, + 89597, + 89599, + 89603, + 89611, + 89627, + 89633, + 89653, + 89657, + 89659, + 89669, + 89671, + 89681, + 89689, + 89753, + 89759, + 89767, + 89779, + 89783, + 89797, + 89809, + 89819, + 89821, + 89833, + 89839, + 89849, + 89867, + 89891, + 89897, + 89899, + 89909, + 89917, + 89923, + 89939, + 89959, + 89963, + 89977, + 89983, + 89989, + 90001, + 90007, + 90011, + 90017, + 90019, + 90023, + 90031, + 90053, + 90059, + 90067, + 90071, + 90073, + 90089, + 90107, + 90121, + 90127, + 90149, + 90163, + 90173, + 90187, + 90191, + 90197, + 90199, + 90203, + 90217, + 90227, + 90239, + 90247, + 90263, + 90271, + 90281, + 90289, + 90313, + 90353, + 90359, + 90371, + 90373, + 90379, + 90397, + 90401, + 90403, + 90407, + 90437, + 90439, + 90469, + 90473, + 90481, + 90499, + 90511, + 90523, + 90527, + 90529, + 90533, + 90547, + 90583, + 90599, + 90617, + 90619, + 90631, + 90641, + 90647, + 90659, + 90677, + 90679, + 90697, + 90703, + 90709, + 90731, + 90749, + 90787, + 90793, + 90803, + 90821, + 90823, + 90833, + 90841, + 90847, + 90863, + 90887, + 90901, + 90907, + 90911, + 90917, + 90931, + 90947, + 90971, + 90977, + 90989, + 90997, + 91009, + 91019, + 91033, + 91079, + 91081, + 91097, + 91099, + 91121, + 91127, + 91129, + 91139, + 91141, + 91151, + 91153, + 91159, + 91163, + 91183, + 91193, + 91199, + 91229, + 91237, + 91243, + 91249, + 91253, + 91283, + 91291, + 91297, + 91303, + 91309, + 91331, + 91367, + 91369, + 91373, + 91381, + 91387, + 91393, + 91397, + 91411, + 91423, + 91433, + 91453, + 91457, + 91459, + 91463, + 91493, + 91499, + 91513, + 91529, + 91541, + 91571, + 91573, + 91577, + 91583, + 91591, + 91621, + 91631, + 91639, + 91673, + 91691, + 91703, + 91711, + 91733, + 91753, + 91757, + 91771, + 91781, + 91801, + 91807, + 91811, + 91813, + 91823, + 91837, + 91841, + 91867, + 91873, + 91909, + 91921, + 91939, + 91943, + 91951, + 91957, + 91961, + 91967, + 91969, + 91997, + 92003, + 92009, + 92033, + 92041, + 92051, + 92077, + 92083, + 92107, + 92111, + 92119, + 92143, + 92153, + 92173, + 92177, + 92179, + 92189, + 92203, + 92219, + 92221, + 92227, + 92233, + 92237, + 92243, + 92251, + 92269, + 92297, + 92311, + 92317, + 92333, + 92347, + 92353, + 92357, + 92363, + 92369, + 92377, + 92381, + 92383, + 92387, + 92399, + 92401, + 92413, + 92419, + 92431, + 92459, + 92461, + 92467, + 92479, + 92489, + 92503, + 92507, + 92551, + 92557, + 92567, + 92569, + 92581, + 92593, + 92623, + 92627, + 92639, + 92641, + 92647, + 92657, + 92669, + 92671, + 92681, + 92683, + 92693, + 92699, + 92707, + 92717, + 92723, + 92737, + 92753, + 92761, + 92767, + 92779, + 92789, + 92791, + 92801, + 92809, + 92821, + 92831, + 92849, + 92857, + 92861, + 92863, + 92867, + 92893, + 92899, + 92921, + 92927, + 92941, + 92951, + 92957, + 92959, + 92987, + 92993, + 93001, + 93047, + 93053, + 93059, + 93077, + 93083, + 93089, + 93097, + 93103, + 93113, + 93131, + 93133, + 93139, + 93151, + 93169, + 93179, + 93187, + 93199, + 93229, + 93239, + 93241, + 93251, + 93253, + 93257, + 93263, + 93281, + 93283, + 93287, + 93307, + 93319, + 93323, + 93329, + 93337, + 93371, + 93377, + 93383, + 93407, + 93419, + 93427, + 93463, + 93479, + 93481, + 93487, + 93491, + 93493, + 93497, + 93503, + 93523, + 93529, + 93553, + 93557, + 93559, + 93563, + 93581, + 93601, + 93607, + 93629, + 93637, + 93683, + 93701, + 93703, + 93719, + 93739, + 93761, + 93763, + 93787, + 93809, + 93811, + 93827, + 93851, + 93871, + 93887, + 93889, + 93893, + 93901, + 93911, + 93913, + 93923, + 93937, + 93941, + 93949, + 93967, + 93971, + 93979, + 93983, + 93997, + 94007, + 94009, + 94033, + 94049, + 94057, + 94063, + 94079, + 94099, + 94109, + 94111, + 94117, + 94121, + 94151, + 94153, + 94169, + 94201, + 94207, + 94219, + 94229, + 94253, + 94261, + 94273, + 94291, + 94307, + 94309, + 94321, + 94327, + 94331, + 94343, + 94349, + 94351, + 94379, + 94397, + 94399, + 94421, + 94427, + 94433, + 94439, + 94441, + 94447, + 94463, + 94477, + 94483, + 94513, + 94529, + 94531, + 94541, + 94543, + 94547, + 94559, + 94561, + 94573, + 94583, + 94597, + 94603, + 94613, + 94621, + 94649, + 94651, + 94687, + 94693, + 94709, + 94723, + 94727, + 94747, + 94771, + 94777, + 94781, + 94789, + 94793, + 94811, + 94819, + 94823, + 94837, + 94841, + 94847, + 94849, + 94873, + 94889, + 94903, + 94907, + 94933, + 94949, + 94951, + 94961, + 94993, + 94999, + 95003, + 95009, + 95021, + 95027, + 95063, + 95071, + 95083, + 95087, + 95089, + 95093, + 95101, + 95107, + 95111, + 95131, + 95143, + 95153, + 95177, + 95189, + 95191, + 95203, + 95213, + 95219, + 95231, + 95233, + 95239, + 95257, + 95261, + 95267, + 95273, + 95279, + 95287, + 95311, + 95317, + 95327, + 95339, + 95369, + 95383, + 95393, + 95401, + 95413, + 95419, + 95429, + 95441, + 95443, + 95461, + 95467, + 95471, + 95479, + 95483, + 95507, + 95527, + 95531, + 95539, + 95549, + 95561, + 95569, + 95581, + 95597, + 95603, + 95617, + 95621, + 95629, + 95633, + 95651, + 95701, + 95707, + 95713, + 95717, + 95723, + 95731, + 95737, + 95747, + 95773, + 95783, + 95789, + 95791, + 95801, + 95803, + 95813, + 95819, + 95857, + 95869, + 95873, + 95881, + 95891, + 95911, + 95917, + 95923, + 95929, + 95947, + 95957, + 95959, + 95971, + 95987, + 95989, + 96001, + 96013, + 96017, + 96043, + 96053, + 96059, + 96079, + 96097, + 96137, + 96149, + 96157, + 96167, + 96179, + 96181, + 96199, + 96211, + 96221, + 96223, + 96233, + 96259, + 96263, + 96269, + 96281, + 96289, + 96293, + 96323, + 96329, + 96331, + 96337, + 96353, + 96377, + 96401, + 96419, + 96431, + 96443, + 96451, + 96457, + 96461, + 96469, + 96479, + 96487, + 96493, + 96497, + 96517, + 96527, + 96553, + 96557, + 96581, + 96587, + 96589, + 96601, + 96643, + 96661, + 96667, + 96671, + 96697, + 96703, + 96731, + 96737, + 96739, + 96749, + 96757, + 96763, + 96769, + 96779, + 96787, + 96797, + 96799, + 96821, + 96823, + 96827, + 96847, + 96851, + 96857, + 96893, + 96907, + 96911, + 96931, + 96953, + 96959, + 96973, + 96979, + 96989, + 96997, + 97001, + 97003, + 97007, + 97021, + 97039, + 97073, + 97081, + 97103, + 97117, + 97127, + 97151, + 97157, + 97159, + 97169, + 97171, + 97177, + 97187, + 97213, + 97231, + 97241, + 97259, + 97283, + 97301, + 97303, + 97327, + 97367, + 97369, + 97373, + 97379, + 97381, + 97387, + 97397, + 97423, + 97429, + 97441, + 97453, + 97459, + 97463, + 97499, + 97501, + 97511, + 97523, + 97547, + 97549, + 97553, + 97561, + 97571, + 97577, + 97579, + 97583, + 97607, + 97609, + 97613, + 97649, + 97651, + 97673, + 97687, + 97711, + 97729, + 97771, + 97777, + 97787, + 97789, + 97813, + 97829, + 97841, + 97843, + 97847, + 97849, + 97859, + 97861, + 97871, + 97879, + 97883, + 97919, + 97927, + 97931, + 97943, + 97961, + 97967, + 97973, + 97987, + 98009, + 98011, + 98017, + 98041, + 98047, + 98057, + 98081, + 98101, + 98123, + 98129, + 98143, + 98179, + 98207, + 98213, + 98221, + 98227, + 98251, + 98257, + 98269, + 98297, + 98299, + 98317, + 98321, + 98323, + 98327, + 98347, + 98369, + 98377, + 98387, + 98389, + 98407, + 98411, + 98419, + 98429, + 98443, + 98453, + 98459, + 98467, + 98473, + 98479, + 98491, + 98507, + 98519, + 98533, + 98543, + 98561, + 98563, + 98573, + 98597, + 98621, + 98627, + 98639, + 98641, + 98663, + 98669, + 98689, + 98711, + 98713, + 98717, + 98729, + 98731, + 98737, + 98773, + 98779, + 98801, + 98807, + 98809, + 98837, + 98849, + 98867, + 98869, + 98873, + 98887, + 98893, + 98897, + 98899, + 98909, + 98911, + 98927, + 98929, + 98939, + 98947, + 98953, + 98963, + 98981, + 98993, + 98999, + 99013, + 99017, + 99023, + 99041, + 99053, + 99079, + 99083, + 99089, + 99103, + 99109, + 99119, + 99131, + 99133, + 99137, + 99139, + 99149, + 99173, + 99181, + 99191, + 99223, + 99233, + 99241, + 99251, + 99257, + 99259, + 99277, + 99289, + 99317, + 99347, + 99349, + 99367, + 99371, + 99377, + 99391, + 99397, + 99401, + 99409, + 99431, + 99439, + 99469, + 99487, + 99497, + 99523, + 99527, + 99529, + 99551, + 99559, + 99563, + 99571, + 99577, + 99581, + 99607, + 99611, + 99623, + 99643, + 99661, + 99667, + 99679, + 99689, + 99707, + 99709, + 99713, + 99719, + 99721, + 99733, + 99761, + 99767, + 99787, + 99793, + 99809, + 99817, + 99823, + 99829, + 99833, + 99839, + 99859, + 99871, + 99877, + 99881, + 99901, + 99907, + 99923, + 99929, + 99961, + 99971, + 99989, + 99991, + 100003, + 100019, + 100043, + 100049, + 100057, + 100069, + 100103, + 100109, + 100129, + 100151, + 100153, + 100169, + 100183, + 100189, + 100193, + 100207, + 100213, + 100237, + 100267, + 100271, + 100279, + 100291, + 100297, + 100313, + 100333, + 100343, + 100357, + 100361, + 100363, + 100379, + 100391, + 100393, + 100403, + 100411, + 100417, + 100447, + 100459, + 100469, + 100483, + 100493, + 100501, + 100511, + 100517, + 100519, + 100523, + 100537, + 100547, + 100549, + 100559, + 100591, + 100609, + 100613, + 100621, + 100649, + 100669, + 100673, + 100693, + 100699, + 100703, + 100733, + 100741, + 100747, + 100769, + 100787, + 100799, + 100801, + 100811, + 100823, + 100829, + 100847, + 100853, + 100907, + 100913, + 100927, + 100931, + 100937, + 100943, + 100957, + 100981, + 100987, + 100999, + 101009, + 101021, + 101027, + 101051, + 101063, + 101081, + 101089, + 101107, + 101111, + 101113, + 101117, + 101119, + 101141, + 101149, + 101159, + 101161, + 101173, + 101183, + 101197, + 101203, + 101207, + 101209, + 101221, + 101267, + 101273, + 101279, + 101281, + 101287, + 101293, + 101323, + 101333, + 101341, + 101347, + 101359, + 101363, + 101377, + 101383, + 101399, + 101411, + 101419, + 101429, + 101449, + 101467, + 101477, + 101483, + 101489, + 101501, + 101503, + 101513, + 101527, + 101531, + 101533, + 101537, + 101561, + 101573, + 101581, + 101599, + 101603, + 101611, + 101627, + 101641, + 101653, + 101663, + 101681, + 101693, + 101701, + 101719, + 101723, + 101737, + 101741, + 101747, + 101749, + 101771, + 101789, + 101797, + 101807, + 101833, + 101837, + 101839, + 101863, + 101869, + 101873, + 101879, + 101891, + 101917, + 101921, + 101929, + 101939, + 101957, + 101963, + 101977, + 101987, + 101999, + 102001, + 102013, + 102019, + 102023, + 102031, + 102043, + 102059, + 102061, + 102071, + 102077, + 102079, + 102101, + 102103, + 102107, + 102121, + 102139, + 102149, + 102161, + 102181, + 102191, + 102197, + 102199, + 102203, + 102217, + 102229, + 102233, + 102241, + 102251, + 102253, + 102259, + 102293, + 102299, + 102301, + 102317, + 102329, + 102337, + 102359, + 102367, + 102397, + 102407, + 102409, + 102433, + 102437, + 102451, + 102461, + 102481, + 102497, + 102499, + 102503, + 102523, + 102533, + 102539, + 102547, + 102551, + 102559, + 102563, + 102587, + 102593, + 102607, + 102611, + 102643, + 102647, + 102653, + 102667, + 102673, + 102677, + 102679, + 102701, + 102761, + 102763, + 102769, + 102793, + 102797, + 102811, + 102829, + 102841, + 102859, + 102871, + 102877, + 102881, + 102911, + 102913, + 102929, + 102931, + 102953, + 102967, + 102983, + 103001, + 103007, + 103043, + 103049, + 103067, + 103069, + 103079, + 103087, + 103091, + 103093, + 103099, + 103123, + 103141, + 103171, + 103177, + 103183, + 103217, + 103231, + 103237, + 103289, + 103291, + 103307, + 103319, + 103333, + 103349, + 103357, + 103387, + 103391, + 103393, + 103399, + 103409, + 103421, + 103423, + 103451, + 103457, + 103471, + 103483, + 103511, + 103529, + 103549, + 103553, + 103561, + 103567, + 103573, + 103577, + 103583, + 103591, + 103613, + 103619, + 103643, + 103651, + 103657, + 103669, + 103681, + 103687, + 103699, + 103703, + 103723, + 103769, + 103787, + 103801, + 103811, + 103813, + 103837, + 103841, + 103843, + 103867, + 103889, + 103903, + 103913, + 103919, + 103951, + 103963, + 103967, + 103969, + 103979, + 103981, + 103991, + 103993, + 103997, + 104003, + 104009, + 104021, + 104033, + 104047, + 104053, + 104059, + 104087, + 104089, + 104107, + 104113, + 104119, + 104123, + 104147, + 104149, + 104161, + 104173, + 104179, + 104183, + 104207, + 104231, + 104233, + 104239, + 104243, + 104281, + 104287, + 104297, + 104309, + 104311, + 104323, + 104327, + 104347, + 104369, + 104381, + 104383, + 104393, + 104399, + 104417, + 104459, + 104471, + 104473, + 104479, + 104491, + 104513, + 104527, + 104537, + 104543, + 104549, + 104551, + 104561, + 104579, + 104593, + 104597, + 104623, + 104639, + 104651, + 104659, + 104677, + 104681, + 104683, + 104693, + 104701, + 104707, + 104711, + 104717, + 104723, + 104729, ) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/number.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/number.pyi index f8680bf8..fbb063e1 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/number.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/number.pyi @@ -1,19 +1,25 @@ from typing import List, Optional, Callable - def ceil_div(n: int, d: int) -> int: ... -def size (N: int) -> int: ... -def getRandomInteger(N: int, randfunc: Optional[Callable]=None) -> int: ... -def getRandomRange(a: int, b: int, randfunc: Optional[Callable]=None) -> int: ... -def getRandomNBitInteger(N: int, randfunc: Optional[Callable]=None) -> int: ... -def GCD(x: int,y: int) -> int: ... +def size(N: int) -> int: ... +def getRandomInteger(N: int, randfunc: Optional[Callable] = None) -> int: ... +def getRandomRange(a: int, b: int, randfunc: Optional[Callable] = None) -> int: ... +def getRandomNBitInteger(N: int, randfunc: Optional[Callable] = None) -> int: ... +def GCD(x: int, y: int) -> int: ... def inverse(u: int, v: int) -> int: ... -def getPrime(N: int, randfunc: Optional[Callable]=None) -> int: ... -def getStrongPrime(N: int, e: Optional[int]=0, false_positive_prob: Optional[float]=1e-6, randfunc: Optional[Callable]=None) -> int: ... -def isPrime(N: int, false_positive_prob: Optional[float]=1e-6, randfunc: Optional[Callable]=None) -> bool: ... -def long_to_bytes(n: int, blocksize: Optional[int]=0) -> bytes: ... +def getPrime(N: int, randfunc: Optional[Callable] = None) -> int: ... +def getStrongPrime( + N: int, + e: Optional[int] = 0, + false_positive_prob: Optional[float] = 1e-6, + randfunc: Optional[Callable] = None, +) -> int: ... +def isPrime( + N: int, false_positive_prob: Optional[float] = 1e-6, randfunc: Optional[Callable] = None +) -> bool: ... +def long_to_bytes(n: int, blocksize: Optional[int] = 0) -> bytes: ... def bytes_to_long(s: bytes) -> int: ... -def long2str(n: int, blocksize: Optional[int]=0) -> bytes: ... +def long2str(n: int, blocksize: Optional[int] = 0) -> bytes: ... def str2long(s: bytes) -> int: ... sieve_base: List[int] diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/py3compat.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/py3compat.py index 3294b66b..592861d3 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/py3compat.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/py3compat.py @@ -63,123 +63,129 @@ if sys.version_info[0] == 2: - def b(s): - return s - def bchr(s): - return chr(s) - def bstr(s): - return str(s) - def bord(s): - return ord(s) - def tobytes(s, encoding="latin-1"): - if isinstance(s, unicode): - return s.encode(encoding) - elif isinstance(s, str): - return s - elif isinstance(s, bytearray): - return bytes(s) - elif isinstance(s, memoryview): - return s.tobytes() - else: - return ''.join(s) - def tostr(bs): - return bs - def byte_string(s): - return isinstance(s, str) - - # In Python 2, a memoryview does not support concatenation - def concat_buffers(a, b): - if isinstance(a, memoryview): - a = a.tobytes() - if isinstance(b, memoryview): - b = b.tobytes() - return a + b - - from StringIO import StringIO - BytesIO = StringIO - - from sys import maxint - - iter_range = xrange - - def is_native_int(x): - return isinstance(x, (int, long)) - - def is_string(x): - return isinstance(x, basestring) - - def is_bytes(x): - return isinstance(x, str) or \ - isinstance(x, bytearray) or \ - isinstance(x, memoryview) - - ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()}) - - FileNotFoundError = IOError + + def b(s): + return s + + def bchr(s): + return chr(s) + + def bstr(s): + return str(s) + + def bord(s): + return ord(s) + + def tobytes(s, encoding="latin-1"): + if isinstance(s, unicode): + return s.encode(encoding) + elif isinstance(s, str): + return s + elif isinstance(s, bytearray): + return bytes(s) + elif isinstance(s, memoryview): + return s.tobytes() + else: + return "".join(s) + + def tostr(bs): + return bs + + def byte_string(s): + return isinstance(s, str) + + # In Python 2, a memoryview does not support concatenation + def concat_buffers(a, b): + if isinstance(a, memoryview): + a = a.tobytes() + if isinstance(b, memoryview): + b = b.tobytes() + return a + b + + from StringIO import StringIO + + BytesIO = StringIO + + iter_range = xrange + + def is_native_int(x): + return isinstance(x, (int, long)) + + def is_string(x): + return isinstance(x, basestring) + + def is_bytes(x): + return isinstance(x, str) or isinstance(x, bytearray) or isinstance(x, memoryview) + + ABC = abc.ABCMeta("ABC", (object,), {"__slots__": ()}) + + FileNotFoundError = IOError else: - def b(s): - return s.encode("latin-1") # utf-8 would cause some side-effects we don't want - def bchr(s): - return bytes([s]) - def bstr(s): - if isinstance(s,str): - return bytes(s,"latin-1") - else: - return bytes(s) - def bord(s): - return s - def tobytes(s, encoding="latin-1"): - if isinstance(s, bytes): - return s - elif isinstance(s, bytearray): - return bytes(s) - elif isinstance(s,str): - return s.encode(encoding) - elif isinstance(s, memoryview): - return s.tobytes() - else: - return bytes([s]) - def tostr(bs): - return bs.decode("latin-1") - def byte_string(s): - return isinstance(s, bytes) - - def concat_buffers(a, b): - return a + b - - from io import BytesIO - from io import StringIO - from sys import maxsize as maxint - - iter_range = range - - def is_native_int(x): - return isinstance(x, int) - - def is_string(x): - return isinstance(x, str) - - def is_bytes(x): - return isinstance(x, bytes) or \ - isinstance(x, bytearray) or \ - isinstance(x, memoryview) - - from abc import ABC - - FileNotFoundError = FileNotFoundError + + def b(s): + return s.encode("latin-1") # utf-8 would cause some side-effects we don't want + + def bchr(s): + return bytes([s]) + + def bstr(s): + if isinstance(s, str): + return bytes(s, "latin-1") + else: + return bytes(s) + + def bord(s): + return s + + def tobytes(s, encoding="latin-1"): + if isinstance(s, bytes): + return s + elif isinstance(s, bytearray): + return bytes(s) + elif isinstance(s, str): + return s.encode(encoding) + elif isinstance(s, memoryview): + return s.tobytes() + else: + return bytes([s]) + + def tostr(bs): + return bs.decode("latin-1") + + def byte_string(s): + return isinstance(s, bytes) + + def concat_buffers(a, b): + return a + b + + from io import StringIO + + iter_range = range + + def is_native_int(x): + return isinstance(x, int) + + def is_string(x): + return isinstance(x, str) + + def is_bytes(x): + return isinstance(x, bytes) or isinstance(x, bytearray) or isinstance(x, memoryview) + + FileNotFoundError = FileNotFoundError def _copy_bytes(start, end, seq): - """Return an immutable copy of a sequence (byte string, byte array, memoryview) - in a certain interval [start:seq]""" - - if isinstance(seq, memoryview): - return seq[start:end].tobytes() - elif isinstance(seq, bytearray): - return bytes(seq[start:end]) - else: - return seq[start:end] + """Return an immutable copy of a sequence (byte string, byte array, memoryview) + in a certain interval [start:seq]""" + + if isinstance(seq, memoryview): + return seq[start:end].tobytes() + elif isinstance(seq, bytearray): + return bytes(seq[start:end]) + else: + return seq[start:end] + del sys del abc diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/py3compat.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/py3compat.pyi index 74e04a2b..0a2e1375 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/py3compat.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/py3compat.pyi @@ -10,24 +10,20 @@ def bord(s: bytes) -> int: ... def tobytes(s: Union[bytes, str]) -> bytes: ... def tostr(b: bytes) -> str: ... def bytestring(x: Any) -> bool: ... - def is_native_int(s: Any) -> bool: ... def is_string(x: Any) -> bool: ... def is_bytes(x: Any) -> bool: ... - def BytesIO(b: bytes) -> IO[bytes]: ... def StringIO(s: str) -> IO[str]: ... if sys.version_info[0] == 2: - from sys import maxint - iter_range = xrange + iter_range = xrange else: - from sys import maxsize as maxint - iter_range = range + iter_range = range class FileNotFoundError: - def __init__(self, err: int, msg: str, filename: str) -> None: - pass + def __init__(self, err: int, msg: str, filename: str) -> None: + pass def _copy_bytes(start: Optional[int], end: Optional[int], seq: Buffer) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/strxor.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/strxor.py index 6b161552..a6d03499 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/strxor.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/strxor.py @@ -28,13 +28,18 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t, - create_string_buffer, get_raw_buffer, - c_uint8_ptr, is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + c_size_t, + create_string_buffer, + get_raw_buffer, + c_uint8_ptr, + is_writeable_buffer, +) _raw_strxor = load_pycryptodome_raw_lib( - "Cryptodome.Util._strxor", - """ + "Cryptodome.Util._strxor", + """ void strxor(const uint8_t *in1, const uint8_t *in2, uint8_t *out, size_t len); @@ -42,105 +47,111 @@ uint8_t c, uint8_t *out, size_t len); - """) + """, +) def strxor(term1, term2, output=None): - """From two byte strings of equal length, - create a third one which is the byte-by-byte XOR of the two. - - Args: - term1 (bytes/bytearray/memoryview): - The first byte string to XOR. - term2 (bytes/bytearray/memoryview): - The second byte string to XOR. - output (bytearray/memoryview): - The location where the result will be written to. - It must have the same length as ``term1`` and ``term2``. - If ``None``, the result is returned. - :Return: - If ``output`` is ``None``, a new byte string with the result. - Otherwise ``None``. - - .. note:: - ``term1`` and ``term2`` must have the same length. - """ - - if len(term1) != len(term2): - raise ValueError("Only byte strings of equal length can be xored") - - if output is None: - result = create_string_buffer(len(term1)) - else: - # Note: output may overlap with either input - result = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(term1) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(term1)) - - _raw_strxor.strxor(c_uint8_ptr(term1), - c_uint8_ptr(term2), - c_uint8_ptr(result), - c_size_t(len(term1))) - - if output is None: - return get_raw_buffer(result) - else: - return None + """From two byte strings of equal length, + create a third one which is the byte-by-byte XOR of the two. + + Args: + term1 (bytes/bytearray/memoryview): + The first byte string to XOR. + term2 (bytes/bytearray/memoryview): + The second byte string to XOR. + output (bytearray/memoryview): + The location where the result will be written to. + It must have the same length as ``term1`` and ``term2``. + If ``None``, the result is returned. + :Return: + If ``output`` is ``None``, a new byte string with the result. + Otherwise ``None``. + + .. note:: + ``term1`` and ``term2`` must have the same length. + """ + + if len(term1) != len(term2): + raise ValueError("Only byte strings of equal length can be xored") + + if output is None: + result = create_string_buffer(len(term1)) + else: + # Note: output may overlap with either input + result = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(term1) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(term1), + ) + + _raw_strxor.strxor( + c_uint8_ptr(term1), + c_uint8_ptr(term2), + c_uint8_ptr(result), + c_size_t(len(term1)), + ) + + if output is None: + return get_raw_buffer(result) + else: + return None def strxor_c(term, c, output=None): - """From a byte string, create a second one of equal length - where each byte is XOR-red with the same value. - - Args: - term(bytes/bytearray/memoryview): - The byte string to XOR. - c (int): - Every byte in the string will be XOR-ed with this value. - It must be between 0 and 255 (included). - output (None or bytearray/memoryview): - The location where the result will be written to. - It must have the same length as ``term``. - If ``None``, the result is returned. - - Return: - If ``output`` is ``None``, a new ``bytes`` string with the result. - Otherwise ``None``. - """ - - if not 0 <= c < 256: - raise ValueError("c must be in range(256)") - - if output is None: - result = create_string_buffer(len(term)) - else: - # Note: output may overlap with either input - result = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(term) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(term)) - - _raw_strxor.strxor_c(c_uint8_ptr(term), - c, - c_uint8_ptr(result), - c_size_t(len(term)) - ) - - if output is None: - return get_raw_buffer(result) - else: - return None + """From a byte string, create a second one of equal length + where each byte is XOR-red with the same value. + + Args: + term(bytes/bytearray/memoryview): + The byte string to XOR. + c (int): + Every byte in the string will be XOR-ed with this value. + It must be between 0 and 255 (included). + output (None or bytearray/memoryview): + The location where the result will be written to. + It must have the same length as ``term``. + If ``None``, the result is returned. + + Return: + If ``output`` is ``None``, a new ``bytes`` string with the result. + Otherwise ``None``. + """ + + if not 0 <= c < 256: + raise ValueError("c must be in range(256)") + + if output is None: + result = create_string_buffer(len(term)) + else: + # Note: output may overlap with either input + result = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(term) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(term), + ) + + _raw_strxor.strxor_c( + c_uint8_ptr(term), + c, + c_uint8_ptr(result), + c_size_t(len(term)), + ) + + if output is None: + return get_raw_buffer(result) + else: + return None def _strxor_direct(term1, term2, result): - """Very fast XOR - check conditions!""" - _raw_strxor.strxor(term1, term2, result, c_size_t(len(term1))) + """Very fast XOR - check conditions!""" + _raw_strxor.strxor(term1, term2, result, c_size_t(len(term1))) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/strxor.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/strxor.pyi index ca896f3b..d1cbcd82 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/strxor.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/Util/strxor.pyi @@ -2,5 +2,5 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] -def strxor(term1: bytes, term2: bytes, output: Optional[Buffer]=...) -> bytes: ... -def strxor_c(term: bytes, c: int, output: Optional[Buffer]=...) -> bytes: ... +def strxor(term1: bytes, term2: bytes, output: Optional[Buffer] = ...) -> bytes: ... +def strxor_c(term: bytes, c: int, output: Optional[Buffer] = ...) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/__init__.py b/addon/globalPlugins/remoteClient/lib32/Cryptodome/__init__.py index 1fc2db90..46857578 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/__init__.py +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/__init__.py @@ -1,6 +1,14 @@ -__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util', 'Signature', - 'IO', 'Math'] +__all__ = [ + "Cipher", + "Hash", + "Protocol", + "PublicKey", + "Util", + "Signature", + "IO", + "Math", +] -version_info = (3, 23, '0') +version_info = (3, 23, "0") __version__ = ".".join([str(x) for x in version_info]) diff --git a/addon/globalPlugins/remoteClient/lib32/Cryptodome/__init__.pyi b/addon/globalPlugins/remoteClient/lib32/Cryptodome/__init__.pyi index bc73446d..9fb3d057 100644 --- a/addon/globalPlugins/remoteClient/lib32/Cryptodome/__init__.pyi +++ b/addon/globalPlugins/remoteClient/lib32/Cryptodome/__init__.pyi @@ -1,4 +1,4 @@ from typing import Tuple, Union -version_info : Tuple[int, int, Union[int, str]] -__version__ : str +version_info: Tuple[int, int, Union[int, str]] +__version__: str diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/AES.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/AES.py index 42f4bab1..82040057 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/AES.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/AES.py @@ -23,26 +23,30 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) from Cryptodome.Util import _cpu_features from Cryptodome.Random import get_random_bytes -MODE_ECB = 1 #: Electronic Code Book (:ref:`ecb_mode`) -MODE_CBC = 2 #: Cipher-Block Chaining (:ref:`cbc_mode`) -MODE_CFB = 3 #: Cipher Feedback (:ref:`cfb_mode`) -MODE_OFB = 5 #: Output Feedback (:ref:`ofb_mode`) -MODE_CTR = 6 #: Counter mode (:ref:`ctr_mode`) -MODE_OPENPGP = 7 #: OpenPGP mode (:ref:`openpgp_mode`) -MODE_CCM = 8 #: Counter with CBC-MAC (:ref:`ccm_mode`) -MODE_EAX = 9 #: :ref:`eax_mode` -MODE_SIV = 10 #: Synthetic Initialization Vector (:ref:`siv_mode`) -MODE_GCM = 11 #: Galois Counter Mode (:ref:`gcm_mode`) -MODE_OCB = 12 #: Offset Code Book (:ref:`ocb_mode`) -MODE_KW = 13 #: Key Wrap (:ref:`kw_mode`) -MODE_KWP = 14 #: Key Wrap with Padding (:ref:`kwp_mode`) +MODE_ECB = 1 #: Electronic Code Book (:ref:`ecb_mode`) +MODE_CBC = 2 #: Cipher-Block Chaining (:ref:`cbc_mode`) +MODE_CFB = 3 #: Cipher Feedback (:ref:`cfb_mode`) +MODE_OFB = 5 #: Output Feedback (:ref:`ofb_mode`) +MODE_CTR = 6 #: Counter mode (:ref:`ctr_mode`) +MODE_OPENPGP = 7 #: OpenPGP mode (:ref:`openpgp_mode`) +MODE_CCM = 8 #: Counter with CBC-MAC (:ref:`ccm_mode`) +MODE_EAX = 9 #: :ref:`eax_mode` +MODE_SIV = 10 #: Synthetic Initialization Vector (:ref:`siv_mode`) +MODE_GCM = 11 #: Galois Counter Mode (:ref:`gcm_mode`) +MODE_OCB = 12 #: Offset Code Book (:ref:`ocb_mode`) +MODE_KW = 13 #: Key Wrap (:ref:`kw_mode`) +MODE_KWP = 14 #: Key Wrap with Padding (:ref:`kwp_mode`) _cproto = """ int AES_start_operation(const uint8_t key[], @@ -61,172 +65,181 @@ # Load portable AES -_raw_aes_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_aes", - _cproto) +_raw_aes_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_aes", + _cproto, +) # Try to load AES with AES NI instructions try: - _raw_aesni_lib = None - if _cpu_features.have_aes_ni(): - _raw_aesni_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_aesni", - _cproto.replace("AES", - "AESNI")) + _raw_aesni_lib = None + if _cpu_features.have_aes_ni(): + _raw_aesni_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_aesni", + _cproto.replace( + "AES", + "AESNI", + ), + ) # _raw_aesni may not have been compiled in except OSError: - pass + pass def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" - - use_aesni = dict_parameters.pop("use_aesni", True) - - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - if len(key) not in key_size: - raise ValueError("Incorrect AES key length (%d bytes)" % len(key)) - - if use_aesni and _raw_aesni_lib: - start_operation = _raw_aesni_lib.AESNI_start_operation - stop_operation = _raw_aesni_lib.AESNI_stop_operation - else: - start_operation = _raw_aes_lib.AES_start_operation - stop_operation = _raw_aes_lib.AES_stop_operation - - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the AES cipher" - % result) - return SmartPointer(cipher.get(), stop_operation) + """This method instantiates and returns a handle to a low-level + base cipher. It will absorb named parameters in the process.""" + + use_aesni = dict_parameters.pop("use_aesni", True) + + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") + + if len(key) not in key_size: + raise ValueError("Incorrect AES key length (%d bytes)" % len(key)) + + if use_aesni and _raw_aesni_lib: + start_operation = _raw_aesni_lib.AESNI_start_operation + stop_operation = _raw_aesni_lib.AESNI_stop_operation + else: + start_operation = _raw_aes_lib.AES_start_operation + stop_operation = _raw_aes_lib.AES_stop_operation + + cipher = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the AES cipher" % result, + ) + return SmartPointer(cipher.get(), stop_operation) def _derive_Poly1305_key_pair(key, nonce): - """Derive a tuple (r, s, nonce) for a Poly1305 MAC. + """Derive a tuple (r, s, nonce) for a Poly1305 MAC. - If nonce is ``None``, a new 16-byte nonce is generated. - """ + If nonce is ``None``, a new 16-byte nonce is generated. + """ - if len(key) != 32: - raise ValueError("Poly1305 with AES requires a 32-byte key") + if len(key) != 32: + raise ValueError("Poly1305 with AES requires a 32-byte key") - if nonce is None: - nonce = get_random_bytes(16) - elif len(nonce) != 16: - raise ValueError("Poly1305 with AES requires a 16-byte nonce") + if nonce is None: + nonce = get_random_bytes(16) + elif len(nonce) != 16: + raise ValueError("Poly1305 with AES requires a 16-byte nonce") - s = new(key[:16], MODE_ECB).encrypt(nonce) - return key[16:], s, nonce + s = new(key[:16], MODE_ECB).encrypt(nonce) + return key[16:], s, nonce def new(key, mode, *args, **kwargs): - """Create a new AES cipher. + """Create a new AES cipher. - Args: - key(bytes/bytearray/memoryview): - The secret key to use in the symmetric cipher. + Args: + key(bytes/bytearray/memoryview): + The secret key to use in the symmetric cipher. - It must be 16 (*AES-128)*, 24 (*AES-192*) or 32 (*AES-256*) bytes long. + It must be 16 (*AES-128)*, 24 (*AES-192*) or 32 (*AES-256*) bytes long. - For ``MODE_SIV`` only, it doubles to 32, 48, or 64 bytes. - mode (a ``MODE_*`` constant): - The chaining mode to use for encryption or decryption. - If in doubt, use ``MODE_EAX``. + For ``MODE_SIV`` only, it doubles to 32, 48, or 64 bytes. + mode (a ``MODE_*`` constant): + The chaining mode to use for encryption or decryption. + If in doubt, use ``MODE_EAX``. - Keyword Args: - iv (bytes/bytearray/memoryview): - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + Keyword Args: + iv (bytes/bytearray/memoryview): + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 16 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 16 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 16 bytes long for encryption - and 18 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 16 bytes long for encryption + and 18 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - nonce (bytes/bytearray/memoryview): - (Only applicable for ``MODE_CCM``, ``MODE_EAX``, ``MODE_GCM``, - ``MODE_SIV``, ``MODE_OCB``, and ``MODE_CTR``). + nonce (bytes/bytearray/memoryview): + (Only applicable for ``MODE_CCM``, ``MODE_EAX``, ``MODE_GCM``, + ``MODE_SIV``, ``MODE_OCB``, and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key (except possibly for ``MODE_SIV``, see below). + A value that must never be reused for any other encryption done + with this key (except possibly for ``MODE_SIV``, see below). - For ``MODE_EAX``, ``MODE_GCM`` and ``MODE_SIV`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX``, ``MODE_GCM`` and ``MODE_SIV`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CCM``, its length must be in the range **[7..13]**. - Bear in mind that with CCM there is a trade-off between nonce - length and maximum message size. Recommendation: **11** bytes. + For ``MODE_CCM``, its length must be in the range **[7..13]**. + Bear in mind that with CCM there is a trade-off between nonce + length and maximum message size. Recommendation: **11** bytes. - For ``MODE_OCB``, its length must be in the range **[1..15]** - (recommended: **15**). + For ``MODE_OCB``, its length must be in the range **[1..15]** + (recommended: **15**). - For ``MODE_CTR``, its length must be in the range **[0..15]** - (recommended: **8**). + For ``MODE_CTR``, its length must be in the range **[0..15]** + (recommended: **8**). - For ``MODE_SIV``, the nonce is optional, if it is not specified, - then no nonce is being used, which renders the encryption - deterministic. + For ``MODE_SIV``, the nonce is optional, if it is not specified, + then no nonce is being used, which renders the encryption + deterministic. - If not provided, for modes other than ``MODE_SIV``, a random - byte string of the recommended length is used (you must then - read its value with the :attr:`nonce` attribute). + If not provided, for modes other than ``MODE_SIV``, a random + byte string of the recommended length is used (you must then + read its value with the :attr:`nonce` attribute). - segment_size (integer): - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + segment_size (integer): + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - mac_len (integer): - (Only ``MODE_EAX``, ``MODE_GCM``, ``MODE_OCB``, ``MODE_CCM``) - Length of the authentication tag, in bytes. + mac_len (integer): + (Only ``MODE_EAX``, ``MODE_GCM``, ``MODE_OCB``, ``MODE_CCM``) + Length of the authentication tag, in bytes. - It must be even and in the range **[4..16]**. - The recommended value (and the default, if not specified) is **16**. + It must be even and in the range **[4..16]**. + The recommended value (and the default, if not specified) is **16**. - msg_len (integer): - (Only ``MODE_CCM``). Length of the message to (de)cipher. - If not specified, ``encrypt`` must be called with the entire message. - Similarly, ``decrypt`` can only be called once. + msg_len (integer): + (Only ``MODE_CCM``). Length of the message to (de)cipher. + If not specified, ``encrypt`` must be called with the entire message. + Similarly, ``decrypt`` can only be called once. - assoc_len (integer): - (Only ``MODE_CCM``). Length of the associated data. - If not specified, all associated data is buffered internally, - which may represent a problem for very large messages. + assoc_len (integer): + (Only ``MODE_CCM``). Length of the associated data. + If not specified, all associated data is buffered internally, + which may represent a problem for very large messages. - initial_value (integer or bytes/bytearray/memoryview): - (Only ``MODE_CTR``). - The initial value for the counter. If not present, the cipher will - start counting from 0. The value is incremented by one for each block. - The counter number is encoded in big endian mode. + initial_value (integer or bytes/bytearray/memoryview): + (Only ``MODE_CTR``). + The initial value for the counter. If not present, the cipher will + start counting from 0. The value is incremented by one for each block. + The counter number is encoded in big endian mode. - counter (object): - (Only ``MODE_CTR``). - Instance of ``Cryptodome.Util.Counter``, which allows full customization - of the counter block. This parameter is incompatible to both ``nonce`` - and ``initial_value``. + counter (object): + (Only ``MODE_CTR``). + Instance of ``Cryptodome.Util.Counter``, which allows full customization + of the counter block. This parameter is incompatible to both ``nonce`` + and ``initial_value``. - use_aesni: (boolean): - Use Intel AES-NI hardware extensions (default: use if available). + use_aesni: (boolean): + Use Intel AES-NI hardware extensions (default: use if available). - Returns: - an AES object, of the applicable mode. - """ + Returns: + an AES object, of the applicable mode. + """ - kwargs["add_aes_modes"] = True - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) + kwargs["add_aes_modes"] = True + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) # Size of a data block (in bytes) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/AES.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/AES.pyi index 3f07b655..9cf4ff0e 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/AES.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/AES.pyi @@ -1,7 +1,7 @@ from typing import Dict, Optional, Tuple, Union, overload from typing_extensions import Literal -Buffer=bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -29,128 +29,79 @@ MODE_OCB: Literal[12] # MODE_ECB @overload -def new(key: Buffer, - mode: Literal[1], - use_aesni : bool = ...) -> \ - EcbMode: ... +def new(key: Buffer, mode: Literal[1], use_aesni: bool = ...) -> EcbMode: ... # MODE_CBC @overload -def new(key: Buffer, - mode: Literal[2], - iv : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - CbcMode: ... - +def new(key: Buffer, mode: Literal[2], iv: Optional[Buffer] = ..., use_aesni: bool = ...) -> CbcMode: ... @overload -def new(key: Buffer, - mode: Literal[2], - IV : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - CbcMode: ... +def new(key: Buffer, mode: Literal[2], IV: Optional[Buffer] = ..., use_aesni: bool = ...) -> CbcMode: ... # MODE_CFB @overload -def new(key: Buffer, - mode: Literal[3], - iv : Optional[Buffer] = ..., - segment_size : int = ..., - use_aesni : bool = ...) -> \ - CfbMode: ... - +def new( + key: Buffer, mode: Literal[3], iv: Optional[Buffer] = ..., segment_size: int = ..., use_aesni: bool = ... +) -> CfbMode: ... @overload -def new(key: Buffer, - mode: Literal[3], - IV : Optional[Buffer] = ..., - segment_size : int = ..., - use_aesni : bool = ...) -> \ - CfbMode: ... +def new( + key: Buffer, mode: Literal[3], IV: Optional[Buffer] = ..., segment_size: int = ..., use_aesni: bool = ... +) -> CfbMode: ... # MODE_OFB @overload -def new(key: Buffer, - mode: Literal[5], - iv : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - OfbMode: ... - +def new(key: Buffer, mode: Literal[5], iv: Optional[Buffer] = ..., use_aesni: bool = ...) -> OfbMode: ... @overload -def new(key: Buffer, - mode: Literal[5], - IV : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - OfbMode: ... +def new(key: Buffer, mode: Literal[5], IV: Optional[Buffer] = ..., use_aesni: bool = ...) -> OfbMode: ... # MODE_CTR @overload -def new(key: Buffer, - mode: Literal[6], - nonce : Optional[Buffer] = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ..., - use_aesni : bool = ...) -> \ - CtrMode: ... +def new( + key: Buffer, + mode: Literal[6], + nonce: Optional[Buffer] = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., + use_aesni: bool = ..., +) -> CtrMode: ... # MODE_OPENPGP @overload -def new(key: Buffer, - mode: Literal[7], - iv : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - OpenPgpMode: ... - +def new(key: Buffer, mode: Literal[7], iv: Optional[Buffer] = ..., use_aesni: bool = ...) -> OpenPgpMode: ... @overload -def new(key: Buffer, - mode: Literal[7], - IV : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - OpenPgpMode: ... +def new(key: Buffer, mode: Literal[7], IV: Optional[Buffer] = ..., use_aesni: bool = ...) -> OpenPgpMode: ... # MODE_CCM @overload -def new(key: Buffer, - mode: Literal[8], - nonce : Optional[Buffer] = ..., - mac_len : int = ..., - assoc_len : int = ..., - use_aesni : bool = ...) -> \ - CcmMode: ... +def new( + key: Buffer, + mode: Literal[8], + nonce: Optional[Buffer] = ..., + mac_len: int = ..., + assoc_len: int = ..., + use_aesni: bool = ..., +) -> CcmMode: ... # MODE_EAX @overload -def new(key: Buffer, - mode: Literal[9], - nonce : Optional[Buffer] = ..., - mac_len : int = ..., - use_aesni : bool = ...) -> \ - EaxMode: ... +def new( + key: Buffer, mode: Literal[9], nonce: Optional[Buffer] = ..., mac_len: int = ..., use_aesni: bool = ... +) -> EaxMode: ... # MODE_GCM @overload -def new(key: Buffer, - mode: Literal[10], - nonce : Optional[Buffer] = ..., - use_aesni : bool = ...) -> \ - SivMode: ... +def new(key: Buffer, mode: Literal[10], nonce: Optional[Buffer] = ..., use_aesni: bool = ...) -> SivMode: ... # MODE_SIV @overload -def new(key: Buffer, - mode: Literal[11], - nonce : Optional[Buffer] = ..., - mac_len : int = ..., - use_aesni : bool = ...) -> \ - GcmMode: ... +def new( + key: Buffer, mode: Literal[11], nonce: Optional[Buffer] = ..., mac_len: int = ..., use_aesni: bool = ... +) -> GcmMode: ... # MODE_OCB @overload -def new(key: Buffer, - mode: Literal[12], - nonce : Optional[Buffer] = ..., - mac_len : int = ..., - use_aesni : bool = ...) -> \ - OcbMode: ... - +def new( + key: Buffer, mode: Literal[12], nonce: Optional[Buffer] = ..., mac_len: int = ..., use_aesni: bool = ... +) -> OcbMode: ... block_size: int key_size: Tuple[int, int, int] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC2.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC2.py index 4dc1bb88..766b8c65 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC2.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC2.py @@ -34,14 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util.py3compat import byte_string -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) _raw_arc2_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_arc2", - """ + "Cryptodome.Cipher._raw_arc2", + """ int ARC2_start_operation(const uint8_t key[], size_t key_len, size_t effective_key_len, @@ -55,111 +58,116 @@ uint8_t *out, size_t data_len); int ARC2_stop_operation(void *state); - """ - ) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" + """This method instantiates and returns a handle to a low-level + base cipher. It will absorb named parameters in the process.""" - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") - effective_keylen = dict_parameters.pop("effective_keylen", 1024) + effective_keylen = dict_parameters.pop("effective_keylen", 1024) - if len(key) not in key_size: - raise ValueError("Incorrect ARC2 key length (%d bytes)" % len(key)) + if len(key) not in key_size: + raise ValueError("Incorrect ARC2 key length (%d bytes)" % len(key)) - if not (40 <= effective_keylen <= 1024): - raise ValueError("'effective_key_len' must be at least 40 and no larger than 1024 " - "(not %d)" % effective_keylen) + if not (40 <= effective_keylen <= 1024): + raise ValueError( + "'effective_key_len' must be at least 40 and no larger than 1024 (not %d)" % effective_keylen, + ) - start_operation = _raw_arc2_lib.ARC2_start_operation - stop_operation = _raw_arc2_lib.ARC2_stop_operation + start_operation = _raw_arc2_lib.ARC2_start_operation + stop_operation = _raw_arc2_lib.ARC2_stop_operation - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - c_size_t(effective_keylen), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the ARC2 cipher" - % result) + cipher = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + c_size_t(effective_keylen), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the ARC2 cipher" % result, + ) - return SmartPointer(cipher.get(), stop_operation) + return SmartPointer(cipher.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new RC2 cipher. + """Create a new RC2 cipher. - :param key: - The secret key to use in the symmetric cipher. - Its length can vary from 5 to 128 bytes; the actual search space - (and the cipher strength) can be reduced with the ``effective_keylen`` parameter. - :type key: bytes, bytearray, memoryview + :param key: + The secret key to use in the symmetric cipher. + Its length can vary from 5 to 128 bytes; the actual search space + (and the cipher strength) can be reduced with the ``effective_keylen`` parameter. + :type key: bytes, bytearray, memoryview - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + :Keyword Arguments: + * **iv** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + * **nonce** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key. + A value that must never be reused for any other encryption done + with this key. - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CTR``, its length must be in the range **[0..7]**. + For ``MODE_CTR``, its length must be in the range **[0..7]**. - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - * **effective_keylen** (*integer*) -- - Optional. Maximum strength in bits of the actual key used by the ARC2 algorithm. - If the supplied ``key`` parameter is longer (in bits) of the value specified - here, it will be weakened to match it. - If not specified, no limitation is applied. + * **effective_keylen** (*integer*) -- + Optional. Maximum strength in bits of the actual key used by the ARC2 algorithm. + If the supplied ``key`` parameter is longer (in bits) of the value specified + here, it will be weakened to match it. + If not specified, no limitation is applied. - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - :Return: an ARC2 object, of the applicable mode. - """ + :Return: an ARC2 object, of the applicable mode. + """ + + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC2.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC2.pyi index a122a52d..9f307a80 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC2.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC2.pyi @@ -1,6 +1,6 @@ from typing import Union, Dict, Iterable, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode ARC2Mode = int @@ -20,16 +19,17 @@ MODE_CTR: ARC2Mode MODE_OPENPGP: ARC2Mode MODE_EAX: ARC2Mode -def new(key: Buffer, - mode: ARC2Mode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: ARC2Mode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC4.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC4.py index 543a3232..caf6ced3 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC4.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC4.py @@ -20,117 +20,134 @@ # SOFTWARE. # =================================================================== -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr) - - -_raw_arc4_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._ARC4", """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) + + +_raw_arc4_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._ARC4", + """ int ARC4_stream_encrypt(void *rc4State, const uint8_t in[], uint8_t out[], size_t len); int ARC4_stream_init(uint8_t *key, size_t keylen, void **pRc4State); int ARC4_stream_destroy(void *rc4State); - """) + """, +) class ARC4Cipher: - """ARC4 cipher object. Do not create it directly. Use - :func:`Cryptodome.Cipher.ARC4.new` instead. - """ - - def __init__(self, key, *args, **kwargs): - """Initialize an ARC4 cipher object - - See also `new()` at the module level.""" - - if len(args) > 0: - ndrop = args[0] - args = args[1:] - else: - ndrop = kwargs.pop('drop', 0) - - if len(key) not in key_size: - raise ValueError("Incorrect ARC4 key length (%d bytes)" % - len(key)) - - self._state = VoidPointer() - result = _raw_arc4_lib.ARC4_stream_init(c_uint8_ptr(key), - c_size_t(len(key)), - self._state.address_of()) - if result != 0: - raise ValueError("Error %d while creating the ARC4 cipher" - % result) - self._state = SmartPointer(self._state.get(), - _raw_arc4_lib.ARC4_stream_destroy) - - if ndrop > 0: - # This is OK even if the cipher is used for decryption, - # since encrypt and decrypt are actually the same thing - # with ARC4. - self.encrypt(b'\x00' * ndrop) - - self.block_size = 1 - self.key_size = len(key) - - def encrypt(self, plaintext): - """Encrypt a piece of data. - - :param plaintext: The data to encrypt, of any size. - :type plaintext: bytes, bytearray, memoryview - :returns: the encrypted byte string, of equal length as the - plaintext. - """ - - ciphertext = create_string_buffer(len(plaintext)) - result = _raw_arc4_lib.ARC4_stream_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - ciphertext, - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting with RC4" % result) - return get_raw_buffer(ciphertext) - - def decrypt(self, ciphertext): - """Decrypt a piece of data. - - :param ciphertext: The data to decrypt, of any size. - :type ciphertext: bytes, bytearray, memoryview - :returns: the decrypted byte string, of equal length as the - ciphertext. - """ - - try: - return self.encrypt(ciphertext) - except ValueError as e: - raise ValueError(str(e).replace("enc", "dec")) + """ARC4 cipher object. Do not create it directly. Use + :func:`Cryptodome.Cipher.ARC4.new` instead. + """ + + def __init__(self, key, *args, **kwargs): + """Initialize an ARC4 cipher object + + See also `new()` at the module level.""" + + if len(args) > 0: + ndrop = args[0] + args = args[1:] + else: + ndrop = kwargs.pop("drop", 0) + + if len(key) not in key_size: + raise ValueError( + "Incorrect ARC4 key length (%d bytes)" % len(key), + ) + + self._state = VoidPointer() + result = _raw_arc4_lib.ARC4_stream_init( + c_uint8_ptr(key), + c_size_t(len(key)), + self._state.address_of(), + ) + if result != 0: + raise ValueError( + "Error %d while creating the ARC4 cipher" % result, + ) + self._state = SmartPointer( + self._state.get(), + _raw_arc4_lib.ARC4_stream_destroy, + ) + + if ndrop > 0: + # This is OK even if the cipher is used for decryption, + # since encrypt and decrypt are actually the same thing + # with ARC4. + self.encrypt(b"\x00" * ndrop) + + self.block_size = 1 + self.key_size = len(key) + + def encrypt(self, plaintext): + """Encrypt a piece of data. + + :param plaintext: The data to encrypt, of any size. + :type plaintext: bytes, bytearray, memoryview + :returns: the encrypted byte string, of equal length as the + plaintext. + """ + + ciphertext = create_string_buffer(len(plaintext)) + result = _raw_arc4_lib.ARC4_stream_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + ciphertext, + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting with RC4" % result) + return get_raw_buffer(ciphertext) + + def decrypt(self, ciphertext): + """Decrypt a piece of data. + + :param ciphertext: The data to decrypt, of any size. + :type ciphertext: bytes, bytearray, memoryview + :returns: the decrypted byte string, of equal length as the + ciphertext. + """ + + try: + return self.encrypt(ciphertext) + except ValueError as e: + raise ValueError(str(e).replace("enc", "dec")) def new(key, *args, **kwargs): - """Create a new ARC4 cipher. + """Create a new ARC4 cipher. - :param key: - The secret key to use in the symmetric cipher. - Its length must be in the range ``[1..256]``. - The recommended length is 16 bytes. - :type key: bytes, bytearray, memoryview + :param key: + The secret key to use in the symmetric cipher. + Its length must be in the range ``[1..256]``. + The recommended length is 16 bytes. + :type key: bytes, bytearray, memoryview - :Keyword Arguments: - * *drop* (``integer``) -- - The amount of bytes to discard from the initial part of the keystream. - In fact, such part has been found to be distinguishable from random - data (while it shouldn't) and also correlated to key. + :Keyword Arguments: + * *drop* (``integer``) -- + The amount of bytes to discard from the initial part of the keystream. + In fact, such part has been found to be distinguishable from random + data (while it shouldn't) and also correlated to key. - The recommended value is 3072_ bytes. The default value is 0. + The recommended value is 3072_ bytes. The default value is 0. - :Return: an `ARC4Cipher` object + :Return: an `ARC4Cipher` object - .. _3072: http://eprint.iacr.org/2002/067.pdf - """ - return ARC4Cipher(key, *args, **kwargs) + .. _3072: http://eprint.iacr.org/2002/067.pdf + """ + return ARC4Cipher(key, *args, **kwargs) # Size of a data block (in bytes) block_size = 1 # Size of a key (in bytes) -key_size = range(1, 256+1) +key_size = range(1, 256 + 1) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC4.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC4.pyi index b0815859..c29f1b13 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC4.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ARC4.pyi @@ -1,16 +1,16 @@ -from typing import Any, Union, Iterable +from typing import Any, Iterable -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview class ARC4Cipher: - block_size: int - key_size: int + block_size: int + key_size: int - def __init__(self, key: Buffer, *args: Any, **kwargs: Any) -> None: ... - def encrypt(self, plaintext: Buffer) -> bytes: ... - def decrypt(self, ciphertext: Buffer) -> bytes: ... + def __init__(self, key: Buffer, *args: Any, **kwargs: Any) -> None: ... + def encrypt(self, plaintext: Buffer) -> bytes: ... + def decrypt(self, ciphertext: Buffer) -> bytes: ... -def new(key: Buffer, drop : int = ...) -> ARC4Cipher: ... +def new(key: Buffer, drop: int = ...) -> ARC4Cipher: ... block_size: int key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Blowfish.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Blowfish.py index 536cbc80..c9912618 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Blowfish.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Blowfish.py @@ -34,13 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) _raw_blowfish_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_blowfish", - """ + "Cryptodome.Cipher._raw_blowfish", + """ int Blowfish_start_operation(const uint8_t key[], size_t key_len, void **pResult); @@ -53,97 +57,101 @@ uint8_t *out, size_t data_len); int Blowfish_stop_operation(void *state); - """ - ) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a smart pointer to - a low-level base cipher. It will absorb named parameters in - the process.""" - - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - if len(key) not in key_size: - raise ValueError("Incorrect Blowfish key length (%d bytes)" % len(key)) - - start_operation = _raw_blowfish_lib.Blowfish_start_operation - stop_operation = _raw_blowfish_lib.Blowfish_stop_operation - - void_p = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - void_p.address_of()) - if result: - raise ValueError("Error %X while instantiating the Blowfish cipher" - % result) - return SmartPointer(void_p.get(), stop_operation) + """This method instantiates and returns a smart pointer to + a low-level base cipher. It will absorb named parameters in + the process.""" + + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") + + if len(key) not in key_size: + raise ValueError("Incorrect Blowfish key length (%d bytes)" % len(key)) + + start_operation = _raw_blowfish_lib.Blowfish_start_operation + stop_operation = _raw_blowfish_lib.Blowfish_stop_operation + + void_p = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + void_p.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the Blowfish cipher" % result, + ) + return SmartPointer(void_p.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new Blowfish cipher + """Create a new Blowfish cipher + + :param key: + The secret key to use in the symmetric cipher. + Its length can vary from 5 to 56 bytes. + :type key: bytes, bytearray, memoryview - :param key: - The secret key to use in the symmetric cipher. - Its length can vary from 5 to 56 bytes. - :type key: bytes, bytearray, memoryview + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :Keyword Arguments: + * **iv** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + The initialization vector to use for encryption or decryption. - The initialization vector to use for encryption or decryption. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + * **nonce** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + A value that must never be reused for any other encryption done + with this key. - A value that must never be reused for any other encryption done - with this key. + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_CTR``, its length must be in the range **[0..7]**. - For ``MODE_CTR``, its length must be in the range **[0..7]**. + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + :Return: a Blowfish object, of the applicable mode. + """ - :Return: a Blowfish object, of the applicable mode. - """ + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Blowfish.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Blowfish.pyi index b8b21c69..57ec3796 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Blowfish.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Blowfish.pyi @@ -1,6 +1,6 @@ from typing import Union, Dict, Iterable, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode BlowfishMode = int @@ -20,16 +19,17 @@ MODE_CTR: BlowfishMode MODE_OPENPGP: BlowfishMode MODE_EAX: BlowfishMode -def new(key: Buffer, - mode: BlowfishMode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: BlowfishMode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/CAST.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/CAST.py index 84eb88ed..a6290455 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/CAST.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/CAST.py @@ -34,14 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util.py3compat import byte_string -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) _raw_cast_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_cast", - """ + "Cryptodome.Cipher._raw_cast", + """ int CAST_start_operation(const uint8_t key[], size_t key_len, void **pResult); @@ -54,96 +57,101 @@ uint8_t *out, size_t data_len); int CAST_stop_operation(void *state); - """) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" + """This method instantiates and returns a handle to a low-level + base cipher. It will absorb named parameters in the process.""" - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") - if len(key) not in key_size: - raise ValueError("Incorrect CAST key length (%d bytes)" % len(key)) + if len(key) not in key_size: + raise ValueError("Incorrect CAST key length (%d bytes)" % len(key)) - start_operation = _raw_cast_lib.CAST_start_operation - stop_operation = _raw_cast_lib.CAST_stop_operation + start_operation = _raw_cast_lib.CAST_start_operation + stop_operation = _raw_cast_lib.CAST_stop_operation - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the CAST cipher" - % result) + cipher = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the CAST cipher" % result, + ) - return SmartPointer(cipher.get(), stop_operation) + return SmartPointer(cipher.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new CAST cipher + """Create a new CAST cipher - :param key: - The secret key to use in the symmetric cipher. - Its length can vary from 5 to 16 bytes. - :type key: bytes, bytearray, memoryview + :param key: + The secret key to use in the symmetric cipher. + Its length can vary from 5 to 16 bytes. + :type key: bytes, bytearray, memoryview - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + :Keyword Arguments: + * **iv** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + * **nonce** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key. + A value that must never be reused for any other encryption done + with this key. - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CTR``, its length must be in the range **[0..7]**. + For ``MODE_CTR``, its length must be in the range **[0..7]**. - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - :Return: a CAST object, of the applicable mode. - """ + :Return: a CAST object, of the applicable mode. + """ + + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/CAST.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/CAST.pyi index be01f09b..68b55e33 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/CAST.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/CAST.pyi @@ -1,6 +1,6 @@ from typing import Union, Dict, Iterable, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode CASTMode = int @@ -20,16 +19,17 @@ MODE_CTR: CASTMode MODE_OPENPGP: CASTMode MODE_EAX: CASTMode -def new(key: Buffer, - mode: CASTMode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: CASTMode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int -key_size : Iterable[int] +key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20.py index b2759b97..a4be6e5b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20.py @@ -31,15 +31,21 @@ from Cryptodome.Random import get_random_bytes from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, VoidPointer, - SmartPointer, c_size_t, - c_uint8_ptr, c_ulong, - is_writeable_buffer) - -_raw_chacha20_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._chacha20", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + create_string_buffer, + get_raw_buffer, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + c_ulong, + is_writeable_buffer, +) + +_raw_chacha20_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._chacha20", + """ int chacha20_init(void **pState, const uint8_t *key, size_t keySize, @@ -61,228 +67,240 @@ int hchacha20( const uint8_t key[32], const uint8_t nonce16[16], uint8_t subkey[32]); - """) + """, +) def _HChaCha20(key, nonce): + assert len(key) == 32 + assert len(nonce) == 16 - assert(len(key) == 32) - assert(len(nonce) == 16) + subkey = bytearray(32) + result = _raw_chacha20_lib.hchacha20( + c_uint8_ptr(key), + c_uint8_ptr(nonce), + c_uint8_ptr(subkey), + ) + if result: + raise ValueError("Error %d when deriving subkey with HChaCha20" % result) - subkey = bytearray(32) - result = _raw_chacha20_lib.hchacha20( - c_uint8_ptr(key), - c_uint8_ptr(nonce), - c_uint8_ptr(subkey)) - if result: - raise ValueError("Error %d when deriving subkey with HChaCha20" % result) - - return subkey + return subkey class ChaCha20Cipher(object): - """ChaCha20 (or XChaCha20) cipher object. - Do not create it directly. Use :py:func:`new` instead. - - :var nonce: The nonce with length 8, 12 or 24 bytes - :vartype nonce: bytes - """ - - block_size = 1 - - def __init__(self, key, nonce): - """Initialize a ChaCha20/XChaCha20 cipher object - - See also `new()` at the module level.""" - - self.nonce = _copy_bytes(None, None, nonce) - - # XChaCha20 requires a key derivation with HChaCha20 - # See 2.3 in https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - if len(nonce) == 24: - key = _HChaCha20(key, nonce[:16]) - nonce = b'\x00' * 4 + nonce[16:] - self._name = "XChaCha20" - else: - self._name = "ChaCha20" - nonce = self.nonce - - self._next = ("encrypt", "decrypt") - - self._state = VoidPointer() - result = _raw_chacha20_lib.chacha20_init( - self._state.address_of(), - c_uint8_ptr(key), - c_size_t(len(key)), - nonce, - c_size_t(len(nonce))) - if result: - raise ValueError("Error %d instantiating a %s cipher" % (result, - self._name)) - self._state = SmartPointer(self._state.get(), - _raw_chacha20_lib.chacha20_destroy) - - def encrypt(self, plaintext, output=None): - """Encrypt a piece of data. - - Args: - plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the ciphertext - is written to. If ``None``, the ciphertext is returned. - Returns: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "encrypt" not in self._next: - raise TypeError("Cipher object can only be used for decryption") - self._next = ("encrypt",) - return self._encrypt(plaintext, output) - - def _encrypt(self, plaintext, output): - """Encrypt without FSM checks""" - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = _raw_chacha20_lib.chacha20_encrypt( - self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting with %s" % (result, self._name)) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt a piece of data. - - Args: - ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the plaintext - is written to. If ``None``, the plaintext is returned. - Returns: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("Cipher object can only be used for encryption") - self._next = ("decrypt",) - - try: - return self._encrypt(ciphertext, output) - except ValueError as e: - raise ValueError(str(e).replace("enc", "dec")) - - def seek(self, position): - """Seek to a certain position in the key stream. - - If you want to seek to a certain block, - use ``seek(block_number * 64)``. - - Args: - position (integer): - The absolute position within the key stream, in bytes. - """ - - block_number, offset = divmod(position, 64) - block_low = block_number & 0xFFFFFFFF - block_high = block_number >> 32 - - result = _raw_chacha20_lib.chacha20_seek( - self._state.get(), - c_ulong(block_high), - c_ulong(block_low), - offset - ) - if result: - raise ValueError("Error %d while seeking with %s" % (result, self._name)) + """ChaCha20 (or XChaCha20) cipher object. + Do not create it directly. Use :py:func:`new` instead. + + :var nonce: The nonce with length 8, 12 or 24 bytes + :vartype nonce: bytes + """ + + block_size = 1 + + def __init__(self, key, nonce): + """Initialize a ChaCha20/XChaCha20 cipher object + + See also `new()` at the module level.""" + + self.nonce = _copy_bytes(None, None, nonce) + + # XChaCha20 requires a key derivation with HChaCha20 + # See 2.3 in https://tools.ietf.org/html/draft-arciszewski-xchacha-03 + if len(nonce) == 24: + key = _HChaCha20(key, nonce[:16]) + nonce = b"\x00" * 4 + nonce[16:] + self._name = "XChaCha20" + else: + self._name = "ChaCha20" + nonce = self.nonce + + self._next = ("encrypt", "decrypt") + + self._state = VoidPointer() + result = _raw_chacha20_lib.chacha20_init( + self._state.address_of(), + c_uint8_ptr(key), + c_size_t(len(key)), + nonce, + c_size_t(len(nonce)), + ) + if result: + raise ValueError( + "Error %d instantiating a %s cipher" + % ( + result, + self._name, + ), + ) + self._state = SmartPointer( + self._state.get(), + _raw_chacha20_lib.chacha20_destroy, + ) + + def encrypt(self, plaintext, output=None): + """Encrypt a piece of data. + + Args: + plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the ciphertext + is written to. If ``None``, the ciphertext is returned. + Returns: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "encrypt" not in self._next: + raise TypeError("Cipher object can only be used for decryption") + self._next = ("encrypt",) + return self._encrypt(plaintext, output) + + def _encrypt(self, plaintext, output): + """Encrypt without FSM checks""" + + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = _raw_chacha20_lib.chacha20_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting with %s" % (result, self._name)) + + if output is None: + return get_raw_buffer(ciphertext) + else: + return None + + def decrypt(self, ciphertext, output=None): + """Decrypt a piece of data. + + Args: + ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the plaintext + is written to. If ``None``, the plaintext is returned. + Returns: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError("Cipher object can only be used for encryption") + self._next = ("decrypt",) + + try: + return self._encrypt(ciphertext, output) + except ValueError as e: + raise ValueError(str(e).replace("enc", "dec")) + + def seek(self, position): + """Seek to a certain position in the key stream. + + If you want to seek to a certain block, + use ``seek(block_number * 64)``. + + Args: + position (integer): + The absolute position within the key stream, in bytes. + """ + + block_number, offset = divmod(position, 64) + block_low = block_number & 0xFFFFFFFF + block_high = block_number >> 32 + + result = _raw_chacha20_lib.chacha20_seek( + self._state.get(), + c_ulong(block_high), + c_ulong(block_low), + offset, + ) + if result: + raise ValueError("Error %d while seeking with %s" % (result, self._name)) def _derive_Poly1305_key_pair(key, nonce): - """Derive a tuple (r, s, nonce) for a Poly1305 MAC. - - If nonce is ``None``, a new 12-byte nonce is generated. - """ - - if len(key) != 32: - raise ValueError("Poly1305 with ChaCha20 requires a 32-byte key") - - if nonce is None: - padded_nonce = nonce = get_random_bytes(12) - elif len(nonce) == 8: - # See RFC7538, 2.6: [...] ChaCha20 as specified here requires a 96-bit - # nonce. So if the provided nonce is only 64-bit, then the first 32 - # bits of the nonce will be set to a constant number. - # This will usually be zero, but for protocols with multiple senders it may be - # different for each sender, but should be the same for all - # invocations of the function with the same key by a particular - # sender. - padded_nonce = b'\x00\x00\x00\x00' + nonce - elif len(nonce) == 12: - padded_nonce = nonce - else: - raise ValueError("Poly1305 with ChaCha20 requires an 8- or 12-byte nonce") - - rs = new(key=key, nonce=padded_nonce).encrypt(b'\x00' * 32) - return rs[:16], rs[16:], nonce + """Derive a tuple (r, s, nonce) for a Poly1305 MAC. + + If nonce is ``None``, a new 12-byte nonce is generated. + """ + + if len(key) != 32: + raise ValueError("Poly1305 with ChaCha20 requires a 32-byte key") + + if nonce is None: + padded_nonce = nonce = get_random_bytes(12) + elif len(nonce) == 8: + # See RFC7538, 2.6: [...] ChaCha20 as specified here requires a 96-bit + # nonce. So if the provided nonce is only 64-bit, then the first 32 + # bits of the nonce will be set to a constant number. + # This will usually be zero, but for protocols with multiple senders it may be + # different for each sender, but should be the same for all + # invocations of the function with the same key by a particular + # sender. + padded_nonce = b"\x00\x00\x00\x00" + nonce + elif len(nonce) == 12: + padded_nonce = nonce + else: + raise ValueError("Poly1305 with ChaCha20 requires an 8- or 12-byte nonce") + + rs = new(key=key, nonce=padded_nonce).encrypt(b"\x00" * 32) + return rs[:16], rs[16:], nonce def new(**kwargs): - """Create a new ChaCha20 or XChaCha20 cipher + """Create a new ChaCha20 or XChaCha20 cipher + + Keyword Args: + key (bytes/bytearray/memoryview): The secret key to use. + It must be 32 bytes long. + nonce (bytes/bytearray/memoryview): A mandatory value that + must never be reused for any other encryption + done with this key. - Keyword Args: - key (bytes/bytearray/memoryview): The secret key to use. - It must be 32 bytes long. - nonce (bytes/bytearray/memoryview): A mandatory value that - must never be reused for any other encryption - done with this key. + For ChaCha20, it must be 8 or 12 bytes long. - For ChaCha20, it must be 8 or 12 bytes long. + For XChaCha20, it must be 24 bytes long. - For XChaCha20, it must be 24 bytes long. + If not provided, 8 bytes will be randomly generated + (you can find them back in the ``nonce`` attribute). - If not provided, 8 bytes will be randomly generated - (you can find them back in the ``nonce`` attribute). + :Return: a :class:`Cryptodome.Cipher.ChaCha20.ChaCha20Cipher` object + """ - :Return: a :class:`Cryptodome.Cipher.ChaCha20.ChaCha20Cipher` object - """ + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter %s" % e) - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter %s" % e) + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(8) - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(8) + if len(key) != 32: + raise ValueError("ChaCha20/XChaCha20 key must be 32 bytes long") - if len(key) != 32: - raise ValueError("ChaCha20/XChaCha20 key must be 32 bytes long") + if len(nonce) not in (8, 12, 24): + raise ValueError("Nonce must be 8/12 bytes(ChaCha20) or 24 bytes (XChaCha20)") - if len(nonce) not in (8, 12, 24): - raise ValueError("Nonce must be 8/12 bytes(ChaCha20) or 24 bytes (XChaCha20)") + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) + return ChaCha20Cipher(key, nonce) - return ChaCha20Cipher(key, nonce) # Size of a data block (in bytes) block_size = 1 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20.pyi index f5001cdb..593029a1 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20.pyi @@ -1,23 +1,23 @@ from typing import Union, overload, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview def _HChaCha20(key: Buffer, nonce: Buffer) -> bytearray: ... class ChaCha20Cipher: - block_size: int - nonce: bytes + block_size: int + nonce: bytes - def __init__(self, key: Buffer, nonce: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - def seek(self, position: int) -> None: ... + def __init__(self, key: Buffer, nonce: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def seek(self, position: int) -> None: ... def new(key: Buffer, nonce: Optional[Buffer] = ...) -> ChaCha20Cipher: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20_Poly1305.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20_Poly1305.py index 6a89e2ad..32530a75 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20_Poly1305.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20_Poly1305.py @@ -42,292 +42,305 @@ def _enum(**enums): - return type('Enum', (), enums) + return type("Enum", (), enums) -_CipherStatus = _enum(PROCESSING_AUTH_DATA=1, - PROCESSING_CIPHERTEXT=2, - PROCESSING_DONE=3) +_CipherStatus = _enum( + PROCESSING_AUTH_DATA=1, + PROCESSING_CIPHERTEXT=2, + PROCESSING_DONE=3, +) class ChaCha20Poly1305Cipher(object): - """ChaCha20-Poly1305 and XChaCha20-Poly1305 cipher object. - Do not create it directly. Use :py:func:`new` instead. + """ChaCha20-Poly1305 and XChaCha20-Poly1305 cipher object. + Do not create it directly. Use :py:func:`new` instead. + + :var nonce: The nonce with length 8, 12 or 24 bytes + :vartype nonce: byte string + """ + + def __init__(self, key, nonce): + """Initialize a ChaCha20-Poly1305 AEAD cipher object + + See also `new()` at the module level.""" + + self._next = ( + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ) + + self._authenticator = Poly1305.new(key=key, nonce=nonce, cipher=ChaCha20) - :var nonce: The nonce with length 8, 12 or 24 bytes - :vartype nonce: byte string - """ + self._cipher = ChaCha20.new(key=key, nonce=nonce) + self._cipher.seek(64) # Block counter starts at 1 - def __init__(self, key, nonce): - """Initialize a ChaCha20-Poly1305 AEAD cipher object + self._len_aad = 0 + self._len_ct = 0 + self._mac_tag = None + self._status = _CipherStatus.PROCESSING_AUTH_DATA - See also `new()` at the module level.""" + def update(self, data): + """Protect the associated data. - self._next = ("update", "encrypt", "decrypt", "digest", - "verify") + Associated data (also known as *additional authenticated data* - AAD) + is the piece of the message that must stay in the clear, while + still allowing the receiver to verify its integrity. + An example is packet headers. - self._authenticator = Poly1305.new(key=key, nonce=nonce, cipher=ChaCha20) + The associated data (possibly split into multiple segments) is + fed into :meth:`update` before any call to :meth:`decrypt` or :meth:`encrypt`. + If there is no associated data, :meth:`update` is not called. - self._cipher = ChaCha20.new(key=key, nonce=nonce) - self._cipher.seek(64) # Block counter starts at 1 + :param bytes/bytearray/memoryview assoc_data: + A piece of associated data. There are no restrictions on its size. + """ - self._len_aad = 0 - self._len_ct = 0 - self._mac_tag = None - self._status = _CipherStatus.PROCESSING_AUTH_DATA + if "update" not in self._next: + raise TypeError("update() method cannot be called") - def update(self, data): - """Protect the associated data. + self._len_aad += len(data) + self._authenticator.update(data) - Associated data (also known as *additional authenticated data* - AAD) - is the piece of the message that must stay in the clear, while - still allowing the receiver to verify its integrity. - An example is packet headers. + def _pad_aad(self): + assert self._status == _CipherStatus.PROCESSING_AUTH_DATA + if self._len_aad & 0x0F: + self._authenticator.update(b"\x00" * (16 - (self._len_aad & 0x0F))) + self._status = _CipherStatus.PROCESSING_CIPHERTEXT - The associated data (possibly split into multiple segments) is - fed into :meth:`update` before any call to :meth:`decrypt` or :meth:`encrypt`. - If there is no associated data, :meth:`update` is not called. + def encrypt(self, plaintext, output=None): + """Encrypt a piece of data. - :param bytes/bytearray/memoryview assoc_data: - A piece of associated data. There are no restrictions on its size. - """ + Args: + plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the ciphertext + is written to. If ``None``, the ciphertext is returned. + Returns: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "update" not in self._next: - raise TypeError("update() method cannot be called") + if "encrypt" not in self._next: + raise TypeError("encrypt() method cannot be called") - self._len_aad += len(data) - self._authenticator.update(data) + if self._status == _CipherStatus.PROCESSING_AUTH_DATA: + self._pad_aad() - def _pad_aad(self): + self._next = ("encrypt", "digest") - assert(self._status == _CipherStatus.PROCESSING_AUTH_DATA) - if self._len_aad & 0x0F: - self._authenticator.update(b'\x00' * (16 - (self._len_aad & 0x0F))) - self._status = _CipherStatus.PROCESSING_CIPHERTEXT + result = self._cipher.encrypt(plaintext, output=output) + self._len_ct += len(plaintext) + if output is None: + self._authenticator.update(result) + else: + self._authenticator.update(output) + return result - def encrypt(self, plaintext, output=None): - """Encrypt a piece of data. + def decrypt(self, ciphertext, output=None): + """Decrypt a piece of data. - Args: - plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the ciphertext - is written to. If ``None``, the ciphertext is returned. - Returns: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ + Args: + ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the plaintext + is written to. If ``None``, the plaintext is returned. + Returns: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() method cannot be called") + if "decrypt" not in self._next: + raise TypeError("decrypt() method cannot be called") - if self._status == _CipherStatus.PROCESSING_AUTH_DATA: - self._pad_aad() + if self._status == _CipherStatus.PROCESSING_AUTH_DATA: + self._pad_aad() - self._next = ("encrypt", "digest") + self._next = ("decrypt", "verify") - result = self._cipher.encrypt(plaintext, output=output) - self._len_ct += len(plaintext) - if output is None: - self._authenticator.update(result) - else: - self._authenticator.update(output) - return result + self._len_ct += len(ciphertext) + self._authenticator.update(ciphertext) + return self._cipher.decrypt(ciphertext, output=output) - def decrypt(self, ciphertext, output=None): - """Decrypt a piece of data. + def _compute_mac(self): + """Finalize the cipher (if not done already) and return the MAC.""" - Args: - ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the plaintext - is written to. If ``None``, the plaintext is returned. - Returns: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ + if self._mac_tag: + assert self._status == _CipherStatus.PROCESSING_DONE + return self._mac_tag - if "decrypt" not in self._next: - raise TypeError("decrypt() method cannot be called") + assert self._status != _CipherStatus.PROCESSING_DONE - if self._status == _CipherStatus.PROCESSING_AUTH_DATA: - self._pad_aad() + if self._status == _CipherStatus.PROCESSING_AUTH_DATA: + self._pad_aad() - self._next = ("decrypt", "verify") + if self._len_ct & 0x0F: + self._authenticator.update(b"\x00" * (16 - (self._len_ct & 0x0F))) - self._len_ct += len(ciphertext) - self._authenticator.update(ciphertext) - return self._cipher.decrypt(ciphertext, output=output) + self._status = _CipherStatus.PROCESSING_DONE - def _compute_mac(self): - """Finalize the cipher (if not done already) and return the MAC.""" + self._authenticator.update(long_to_bytes(self._len_aad, 8)[::-1]) + self._authenticator.update(long_to_bytes(self._len_ct, 8)[::-1]) + self._mac_tag = self._authenticator.digest() + return self._mac_tag - if self._mac_tag: - assert(self._status == _CipherStatus.PROCESSING_DONE) - return self._mac_tag + def digest(self): + """Compute the *binary* authentication tag (MAC). - assert(self._status != _CipherStatus.PROCESSING_DONE) + :Return: the MAC tag, as 16 ``bytes``. + """ - if self._status == _CipherStatus.PROCESSING_AUTH_DATA: - self._pad_aad() + if "digest" not in self._next: + raise TypeError("digest() method cannot be called") + self._next = ("digest",) - if self._len_ct & 0x0F: - self._authenticator.update(b'\x00' * (16 - (self._len_ct & 0x0F))) + return self._compute_mac() - self._status = _CipherStatus.PROCESSING_DONE + def hexdigest(self): + """Compute the *printable* authentication tag (MAC). - self._authenticator.update(long_to_bytes(self._len_aad, 8)[::-1]) - self._authenticator.update(long_to_bytes(self._len_ct, 8)[::-1]) - self._mac_tag = self._authenticator.digest() - return self._mac_tag + This method is like :meth:`digest`. - def digest(self): - """Compute the *binary* authentication tag (MAC). + :Return: the MAC tag, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) - :Return: the MAC tag, as 16 ``bytes``. - """ + def verify(self, received_mac_tag): + """Validate the *binary* authentication tag (MAC). - if "digest" not in self._next: - raise TypeError("digest() method cannot be called") - self._next = ("digest",) + The receiver invokes this method at the very end, to + check if the associated data (if any) and the decrypted + messages are valid. - return self._compute_mac() + :param bytes/bytearray/memoryview received_mac_tag: + This is the 16-byte *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - def hexdigest(self): - """Compute the *printable* authentication tag (MAC). + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ("verify",) - This method is like :meth:`digest`. + secret = get_random_bytes(16) - :Return: the MAC tag, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) + self._compute_mac() - def verify(self, received_mac_tag): - """Validate the *binary* authentication tag (MAC). + mac1 = BLAKE2s.new( + digest_bits=160, + key=secret, + data=self._mac_tag, + ) + mac2 = BLAKE2s.new( + digest_bits=160, + key=secret, + data=received_mac_tag, + ) - The receiver invokes this method at the very end, to - check if the associated data (if any) and the decrypted - messages are valid. + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - :param bytes/bytearray/memoryview received_mac_tag: - This is the 16-byte *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + def hexverify(self, hex_mac_tag): + """Validate the *printable* authentication tag (MAC). - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ("verify",) + This method is like :meth:`verify`. - secret = get_random_bytes(16) + :param string hex_mac_tag: + This is the *printable* MAC. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - self._compute_mac() + self.verify(unhexlify(hex_mac_tag)) - mac1 = BLAKE2s.new(digest_bits=160, key=secret, - data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, - data=received_mac_tag) + def encrypt_and_digest(self, plaintext): + """Perform :meth:`encrypt` and :meth:`digest` in one step. - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + :param plaintext: The data to encrypt, of any size. + :type plaintext: bytes/bytearray/memoryview + :return: a tuple with two ``bytes`` objects: - def hexverify(self, hex_mac_tag): - """Validate the *printable* authentication tag (MAC). + - the ciphertext, of equal length as the plaintext + - the 16-byte MAC tag + """ - This method is like :meth:`verify`. + return self.encrypt(plaintext), self.digest() - :param string hex_mac_tag: - This is the *printable* MAC. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + def decrypt_and_verify(self, ciphertext, received_mac_tag): + """Perform :meth:`decrypt` and :meth:`verify` in one step. - self.verify(unhexlify(hex_mac_tag)) + :param ciphertext: The piece of data to decrypt. + :type ciphertext: bytes/bytearray/memoryview + :param bytes received_mac_tag: + This is the 16-byte *binary* MAC, as received from the sender. + :return: the decrypted data (as ``bytes``) + :raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - def encrypt_and_digest(self, plaintext): - """Perform :meth:`encrypt` and :meth:`digest` in one step. - - :param plaintext: The data to encrypt, of any size. - :type plaintext: bytes/bytearray/memoryview - :return: a tuple with two ``bytes`` objects: - - - the ciphertext, of equal length as the plaintext - - the 16-byte MAC tag - """ - - return self.encrypt(plaintext), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag): - """Perform :meth:`decrypt` and :meth:`verify` in one step. - - :param ciphertext: The piece of data to decrypt. - :type ciphertext: bytes/bytearray/memoryview - :param bytes received_mac_tag: - This is the 16-byte *binary* MAC, as received from the sender. - :return: the decrypted data (as ``bytes``) - :raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - plaintext = self.decrypt(ciphertext) - self.verify(received_mac_tag) - return plaintext + plaintext = self.decrypt(ciphertext) + self.verify(received_mac_tag) + return plaintext def new(**kwargs): - """Create a new ChaCha20-Poly1305 or XChaCha20-Poly1305 AEAD cipher. + """Create a new ChaCha20-Poly1305 or XChaCha20-Poly1305 AEAD cipher. - :keyword key: The secret key to use. It must be 32 bytes long. - :type key: byte string + :keyword key: The secret key to use. It must be 32 bytes long. + :type key: byte string - :keyword nonce: - A value that must never be reused for any other encryption - done with this key. + :keyword nonce: + A value that must never be reused for any other encryption + done with this key. - For ChaCha20-Poly1305, it must be 8 or 12 bytes long. + For ChaCha20-Poly1305, it must be 8 or 12 bytes long. - For XChaCha20-Poly1305, it must be 24 bytes long. + For XChaCha20-Poly1305, it must be 24 bytes long. - If not provided, 12 ``bytes`` will be generated randomly - (you can find them back in the ``nonce`` attribute). - :type nonce: bytes, bytearray, memoryview + If not provided, 12 ``bytes`` will be generated randomly + (you can find them back in the ``nonce`` attribute). + :type nonce: bytes, bytearray, memoryview - :Return: a :class:`Cryptodome.Cipher.ChaCha20.ChaCha20Poly1305Cipher` object - """ + :Return: a :class:`Cryptodome.Cipher.ChaCha20.ChaCha20Poly1305Cipher` object + """ - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter %s" % e) + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter %s" % e) - if len(key) != 32: - raise ValueError("Key must be 32 bytes long") + if len(key) != 32: + raise ValueError("Key must be 32 bytes long") - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(12) + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(12) - if len(nonce) in (8, 12): - chacha20_poly1305_nonce = nonce - elif len(nonce) == 24: - key = _HChaCha20(key, nonce[:16]) - chacha20_poly1305_nonce = b'\x00\x00\x00\x00' + nonce[16:] - else: - raise ValueError("Nonce must be 8, 12 or 24 bytes long") + if len(nonce) in (8, 12): + chacha20_poly1305_nonce = nonce + elif len(nonce) == 24: + key = _HChaCha20(key, nonce[:16]) + chacha20_poly1305_nonce = b"\x00\x00\x00\x00" + nonce[16:] + else: + raise ValueError("Nonce must be 8, 12 or 24 bytes long") - if not is_buffer(nonce): - raise TypeError("nonce must be bytes, bytearray or memoryview") + if not is_buffer(nonce): + raise TypeError("nonce must be bytes, bytearray or memoryview") - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) - cipher = ChaCha20Poly1305Cipher(key, chacha20_poly1305_nonce) - cipher.nonce = _copy_bytes(None, None, nonce) - return cipher + cipher = ChaCha20Poly1305Cipher(key, chacha20_poly1305_nonce) + cipher.nonce = _copy_bytes(None, None, nonce) + return cipher # Size of a key (in bytes) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20_Poly1305.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20_Poly1305.pyi index 109e8051..69186118 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20_Poly1305.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/ChaCha20_Poly1305.pyi @@ -1,26 +1,26 @@ from typing import Union, Tuple, overload, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview class ChaCha20Poly1305Cipher: - nonce: bytes + nonce: bytes - def __init__(self, key: Buffer, nonce: Buffer) -> None: ... - def update(self, data: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, received_mac_tag: str) -> None: ... - def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... - def decrypt_and_verify(self, ciphertext: Buffer, received_mac_tag: Buffer) -> bytes: ... + def __init__(self, key: Buffer, nonce: Buffer) -> None: ... + def update(self, data: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, received_mac_tag: str) -> None: ... + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + def decrypt_and_verify(self, ciphertext: Buffer, received_mac_tag: Buffer) -> bytes: ... def new(key: Buffer, nonce: Optional[Buffer] = ...) -> ChaCha20Poly1305Cipher: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES.py index 026b491d..be0fae87 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES.py @@ -34,14 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util.py3compat import byte_string -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) _raw_des_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_des", - """ + "Cryptodome.Cipher._raw_des", + """ int DES_start_operation(const uint8_t key[], size_t key_len, void **pResult); @@ -54,95 +57,100 @@ uint8_t *out, size_t data_len); int DES_stop_operation(void *state); - """) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" + """This method instantiates and returns a handle to a low-level + base cipher. It will absorb named parameters in the process.""" - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") + try: + key = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") - if len(key) != key_size: - raise ValueError("Incorrect DES key length (%d bytes)" % len(key)) + if len(key) != key_size: + raise ValueError("Incorrect DES key length (%d bytes)" % len(key)) - start_operation = _raw_des_lib.DES_start_operation - stop_operation = _raw_des_lib.DES_stop_operation + start_operation = _raw_des_lib.DES_start_operation + stop_operation = _raw_des_lib.DES_stop_operation - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the DES cipher" - % result) - return SmartPointer(cipher.get(), stop_operation) + cipher = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the DES cipher" % result, + ) + return SmartPointer(cipher.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new DES cipher. + """Create a new DES cipher. - :param key: - The secret key to use in the symmetric cipher. - It must be 8 byte long. The parity bits will be ignored. - :type key: bytes/bytearray/memoryview + :param key: + The secret key to use in the symmetric cipher. + It must be 8 byte long. The parity bits will be ignored. + :type key: bytes/bytearray/memoryview - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :Keyword Arguments: - * **iv** (*byte string*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + :Keyword Arguments: + * **iv** (*byte string*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - * **nonce** (*byte string*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + * **nonce** (*byte string*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key. + A value that must never be reused for any other encryption done + with this key. - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CTR``, its length must be in the range **[0..7]**. + For ``MODE_CTR``, its length must be in the range **[0..7]**. - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - :Return: a DES object, of the applicable mode. - """ + :Return: a DES object, of the applicable mode. + """ + + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES.pyi index 25a3b230..57ed526f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES.pyi @@ -1,6 +1,6 @@ -from typing import Union, Dict, Iterable, Optional +from typing import Union, Dict, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode DESMode = int @@ -20,16 +19,17 @@ MODE_CTR: DESMode MODE_OPENPGP: DESMode MODE_EAX: DESMode -def new(key: Buffer, - mode: DESMode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: DESMode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int key_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES3.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES3.py index 3b2828eb..59eeb8c6 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES3.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES3.py @@ -34,14 +34,17 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util.py3compat import byte_string, bchr, bord, bstr -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t) +from Cryptodome.Util.py3compat import bchr, bord, bstr +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, +) _raw_des3_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_des3", - """ + "Cryptodome.Cipher._raw_des3", + """ int DES3_start_operation(const uint8_t key[], size_t key_len, void **pResult); @@ -54,124 +57,129 @@ uint8_t *out, size_t data_len); int DES3_stop_operation(void *state); - """) + """, +) def adjust_key_parity(key_in): - """Set the parity bits in a TDES key. + """Set the parity bits in a TDES key. - :param key_in: the TDES key whose bits need to be adjusted - :type key_in: byte string + :param key_in: the TDES key whose bits need to be adjusted + :type key_in: byte string - :returns: a copy of ``key_in``, with the parity bits correctly set - :rtype: byte string + :returns: a copy of ``key_in``, with the parity bits correctly set + :rtype: byte string - :raises ValueError: if the TDES key is not 16 or 24 bytes long - :raises ValueError: if the TDES key degenerates into Single DES - """ + :raises ValueError: if the TDES key is not 16 or 24 bytes long + :raises ValueError: if the TDES key degenerates into Single DES + """ - def parity_byte(key_byte): - parity = 1 - for i in range(1, 8): - parity ^= (key_byte >> i) & 1 - return (key_byte & 0xFE) | parity + def parity_byte(key_byte): + parity = 1 + for i in range(1, 8): + parity ^= (key_byte >> i) & 1 + return (key_byte & 0xFE) | parity - if len(key_in) not in key_size: - raise ValueError("Not a valid TDES key") + if len(key_in) not in key_size: + raise ValueError("Not a valid TDES key") - key_out = b"".join([ bchr(parity_byte(bord(x))) for x in key_in ]) + key_out = b"".join([bchr(parity_byte(bord(x))) for x in key_in]) - if key_out[:8] == key_out[8:16] or key_out[-16:-8] == key_out[-8:]: - raise ValueError("Triple DES key degenerates to single DES") + if key_out[:8] == key_out[8:16] or key_out[-16:-8] == key_out[-8:]: + raise ValueError("Triple DES key degenerates to single DES") - return key_out + return key_out def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level base cipher. - It will absorb named parameters in the process.""" + """This method instantiates and returns a handle to a low-level base cipher. + It will absorb named parameters in the process.""" - try: - key_in = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") + try: + key_in = dict_parameters.pop("key") + except KeyError: + raise TypeError("Missing 'key' parameter") - key = adjust_key_parity(bstr(key_in)) + key = adjust_key_parity(bstr(key_in)) - start_operation = _raw_des3_lib.DES3_start_operation - stop_operation = _raw_des3_lib.DES3_stop_operation + start_operation = _raw_des3_lib.DES3_start_operation + stop_operation = _raw_des3_lib.DES3_stop_operation - cipher = VoidPointer() - result = start_operation(key, - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the TDES cipher" - % result) - return SmartPointer(cipher.get(), stop_operation) + cipher = VoidPointer() + result = start_operation( + key, + c_size_t(len(key)), + cipher.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the TDES cipher" % result, + ) + return SmartPointer(cipher.get(), stop_operation) def new(key, mode, *args, **kwargs): - """Create a new Triple DES cipher. + """Create a new Triple DES cipher. - :param key: - The secret key to use in the symmetric cipher. - It must be 16 or 24 byte long. The parity bits will be ignored. - :type key: bytes/bytearray/memoryview + :param key: + The secret key to use in the symmetric cipher. + It must be 16 or 24 byte long. The parity bits will be ignored. + :type key: bytes/bytearray/memoryview - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants + :param mode: + The chaining mode to use for encryption or decryption. + :type mode: One of the supported ``MODE_*`` constants - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). + :Keyword Arguments: + * **iv** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, + and ``MODE_OPENPGP`` modes). - The initialization vector to use for encryption or decryption. + The initialization vector to use for encryption or decryption. - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. + For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). + For ``MODE_OPENPGP`` mode only, + it must be 8 bytes long for encryption + and 10 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). + If not provided, a random byte string is generated (you must then + read its value with the :attr:`iv` attribute). - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). + * **nonce** (*bytes*, *bytearray*, *memoryview*) -- + (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - A value that must never be reused for any other encryption done - with this key. + A value that must never be reused for any other encryption done + with this key. - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). + For ``MODE_EAX`` there are no + restrictions on its length (recommended: **16** bytes). - For ``MODE_CTR``, its length must be in the range **[0..7]**. + For ``MODE_CTR``, its length must be in the range **[0..7]**. - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). + If not provided for ``MODE_EAX``, a random byte string is generated (you + can read it back via the ``nonce`` attribute). - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. + * **segment_size** (*integer*) -- + (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext + are segmented in. It must be a multiple of 8. + If not specified, it will be assumed to be 8. - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). + * **mac_len** : (*integer*) -- + (Only ``MODE_EAX``) + Length of the authentication tag, in bytes. + It must be no longer than 8 (default). - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. + * **initial_value** : (*integer*) -- + (Only ``MODE_CTR``). The initial value for the counter within + the counter block. By default it is **0**. - :Return: a Triple DES object, of the applicable mode. - """ + :Return: a Triple DES object, of the applicable mode. + """ + + return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) MODE_ECB = 1 MODE_CBC = 2 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES3.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES3.pyi index 2c150f86..f247a74e 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES3.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/DES3.pyi @@ -1,6 +1,6 @@ from typing import Union, Dict, Tuple, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview from Cryptodome.Cipher._mode_ecb import EcbMode from Cryptodome.Cipher._mode_cbc import CbcMode @@ -8,7 +8,6 @@ from Cryptodome.Cipher._mode_cfb import CfbMode from Cryptodome.Cipher._mode_ofb import OfbMode from Cryptodome.Cipher._mode_ctr import CtrMode from Cryptodome.Cipher._mode_openpgp import OpenPgpMode -from Cryptodome.Cipher._mode_eax import EaxMode def adjust_key_parity(key_in: bytes) -> bytes: ... @@ -22,16 +21,17 @@ MODE_CTR: DES3Mode MODE_OPENPGP: DES3Mode MODE_EAX: DES3Mode -def new(key: Buffer, - mode: DES3Mode, - iv : Optional[Buffer] = ..., - IV : Optional[Buffer] = ..., - nonce : Optional[Buffer] = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... +def new( + key: Buffer, + mode: DES3Mode, + iv: Optional[Buffer] = ..., + IV: Optional[Buffer] = ..., + nonce: Optional[Buffer] = ..., + segment_size: int = ..., + mac_len: int = ..., + initial_value: Union[int, Buffer] = ..., + counter: Dict = ..., +) -> Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... block_size: int key_size: Tuple[int, int] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_OAEP.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_OAEP.py index 08f9efe5..a7a41194 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_OAEP.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_OAEP.py @@ -32,200 +32,200 @@ class PKCS1OAEP_Cipher: - """Cipher object for PKCS#1 v1.5 OAEP. - Do not create directly: use :func:`new` instead.""" - - def __init__(self, key, hashAlgo, mgfunc, label, randfunc): - """Initialize this PKCS#1 OAEP cipher object. - - :Parameters: - key : an RSA key object - If a private half is given, both encryption and decryption are possible. - If a public half is given, only encryption is possible. - hashAlgo : hash object - The hash function to use. This can be a module under `Cryptodome.Hash` - or an existing hash object created from any of such modules. If not specified, - `Cryptodome.Hash.SHA1` is used. - mgfunc : callable - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice). - label : bytes/bytearray/memoryview - A label to apply to this particular encryption. If not specified, - an empty string is used. Specifying a label does not improve - security. - randfunc : callable - A function that returns random bytes. - - :attention: Modify the mask generation function only if you know what you are doing. - Sender and receiver must use the same one. - """ - self._key = key - - if hashAlgo: - self._hashObj = hashAlgo - else: - self._hashObj = Cryptodome.Hash.SHA1 - - if mgfunc: - self._mgf = mgfunc - else: - self._mgf = lambda x, y: MGF1(x, y, self._hashObj) - - self._label = _copy_bytes(None, None, label) - self._randfunc = randfunc - - def can_encrypt(self): - """Legacy function to check if you can call :meth:`encrypt`. - - .. deprecated:: 3.0""" - return self._key.can_encrypt() - - def can_decrypt(self): - """Legacy function to check if you can call :meth:`decrypt`. - - .. deprecated:: 3.0""" - return self._key.can_decrypt() - - def encrypt(self, message): - """Encrypt a message with PKCS#1 OAEP. - - :param message: - The message to encrypt, also known as plaintext. It can be of - variable length, but not longer than the RSA modulus (in bytes) - minus 2, minus twice the hash output size. - For instance, if you use RSA 2048 and SHA-256, the longest message - you can encrypt is 190 byte long. - :type message: bytes/bytearray/memoryview - - :returns: The ciphertext, as large as the RSA modulus. - :rtype: bytes - - :raises ValueError: - if the message is too long. - """ - - # See 7.1.1 in RFC3447 - modBits = Cryptodome.Util.number.size(self._key.n) - k = ceil_div(modBits, 8) # Convert from bits to bytes - hLen = self._hashObj.digest_size - mLen = len(message) - - # Step 1b - ps_len = k - mLen - 2 * hLen - 2 - if ps_len < 0: - raise ValueError("Plaintext is too long.") - # Step 2a - lHash = self._hashObj.new(self._label).digest() - # Step 2b - ps = b'\x00' * ps_len - # Step 2c - db = lHash + ps + b'\x01' + _copy_bytes(None, None, message) - # Step 2d - ros = self._randfunc(hLen) - # Step 2e - dbMask = self._mgf(ros, k-hLen-1) - # Step 2f - maskedDB = strxor(db, dbMask) - # Step 2g - seedMask = self._mgf(maskedDB, hLen) - # Step 2h - maskedSeed = strxor(ros, seedMask) - # Step 2i - em = b'\x00' + maskedSeed + maskedDB - # Step 3a (OS2IP) - em_int = bytes_to_long(em) - # Step 3b (RSAEP) - m_int = self._key._encrypt(em_int) - # Step 3c (I2OSP) - c = long_to_bytes(m_int, k) - return c - - def decrypt(self, ciphertext): - """Decrypt a message with PKCS#1 OAEP. - - :param ciphertext: The encrypted message. - :type ciphertext: bytes/bytearray/memoryview - - :returns: The original message (plaintext). - :rtype: bytes - - :raises ValueError: - if the ciphertext has the wrong length, or if decryption - fails the integrity check (in which case, the decryption - key is probably wrong). - :raises TypeError: - if the RSA key has no private half (i.e. you are trying - to decrypt using a public key). - """ - - # See 7.1.2 in RFC3447 - modBits = Cryptodome.Util.number.size(self._key.n) - k = ceil_div(modBits, 8) # Convert from bits to bytes - hLen = self._hashObj.digest_size - - # Step 1b and 1c - if len(ciphertext) != k or k < hLen+2: - raise ValueError("Ciphertext with incorrect length.") - # Step 2a (O2SIP) - ct_int = bytes_to_long(ciphertext) - # Step 2b (RSADP) and step 2c (I2OSP) - em = self._key._decrypt_to_bytes(ct_int) - # Step 3a - lHash = self._hashObj.new(self._label).digest() - # y must be 0, but we MUST NOT check it here in order not to - # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143) - maskedSeed = em[1:hLen+1] - maskedDB = em[hLen+1:] - # Step 3c - seedMask = self._mgf(maskedDB, hLen) - # Step 3d - seed = strxor(maskedSeed, seedMask) - # Step 3e - dbMask = self._mgf(seed, k-hLen-1) - # Step 3f - db = strxor(maskedDB, dbMask) - # Step 3b + 3g - res = oaep_decode(em, lHash, db) - if res <= 0: - raise ValueError("Incorrect decryption.") - # Step 4 - return db[res:] - - -def new(key, hashAlgo=None, mgfunc=None, label=b'', randfunc=None): - """Return a cipher object :class:`PKCS1OAEP_Cipher` - that can be used to perform PKCS#1 OAEP encryption or decryption. - - :param key: - The key object to use to encrypt or decrypt the message. - Decryption is only possible with a private RSA key. - :type key: RSA key object - - :param hashAlgo: - The hash function to use. This can be a module under `Cryptodome.Hash` - or an existing hash object created from any of such modules. - If not specified, `Cryptodome.Hash.SHA1` is used. - :type hashAlgo: hash object - - :param mgfunc: - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice). - :type mgfunc: callable - - :param label: - A label to apply to this particular encryption. If not specified, - an empty string is used. Specifying a label does not improve - security. - :type label: bytes/bytearray/memoryview - - :param randfunc: - A function that returns random bytes. - The default is `Random.get_random_bytes`. - :type randfunc: callable - """ - - if randfunc is None: - randfunc = Random.get_random_bytes - return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc) + """Cipher object for PKCS#1 v1.5 OAEP. + Do not create directly: use :func:`new` instead.""" + + def __init__(self, key, hashAlgo, mgfunc, label, randfunc): + """Initialize this PKCS#1 OAEP cipher object. + + :Parameters: + key : an RSA key object + If a private half is given, both encryption and decryption are possible. + If a public half is given, only encryption is possible. + hashAlgo : hash object + The hash function to use. This can be a module under `Cryptodome.Hash` + or an existing hash object created from any of such modules. If not specified, + `Cryptodome.Hash.SHA1` is used. + mgfunc : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice). + label : bytes/bytearray/memoryview + A label to apply to this particular encryption. If not specified, + an empty string is used. Specifying a label does not improve + security. + randfunc : callable + A function that returns random bytes. + + :attention: Modify the mask generation function only if you know what you are doing. + Sender and receiver must use the same one. + """ + self._key = key + + if hashAlgo: + self._hashObj = hashAlgo + else: + self._hashObj = Cryptodome.Hash.SHA1 + + if mgfunc: + self._mgf = mgfunc + else: + self._mgf = lambda x, y: MGF1(x, y, self._hashObj) + + self._label = _copy_bytes(None, None, label) + self._randfunc = randfunc + + def can_encrypt(self): + """Legacy function to check if you can call :meth:`encrypt`. + + .. deprecated:: 3.0""" + return self._key.can_encrypt() + + def can_decrypt(self): + """Legacy function to check if you can call :meth:`decrypt`. + + .. deprecated:: 3.0""" + return self._key.can_decrypt() + + def encrypt(self, message): + """Encrypt a message with PKCS#1 OAEP. + + :param message: + The message to encrypt, also known as plaintext. It can be of + variable length, but not longer than the RSA modulus (in bytes) + minus 2, minus twice the hash output size. + For instance, if you use RSA 2048 and SHA-256, the longest message + you can encrypt is 190 byte long. + :type message: bytes/bytearray/memoryview + + :returns: The ciphertext, as large as the RSA modulus. + :rtype: bytes + + :raises ValueError: + if the message is too long. + """ + + # See 7.1.1 in RFC3447 + modBits = Cryptodome.Util.number.size(self._key.n) + k = ceil_div(modBits, 8) # Convert from bits to bytes + hLen = self._hashObj.digest_size + mLen = len(message) + + # Step 1b + ps_len = k - mLen - 2 * hLen - 2 + if ps_len < 0: + raise ValueError("Plaintext is too long.") + # Step 2a + lHash = self._hashObj.new(self._label).digest() + # Step 2b + ps = b"\x00" * ps_len + # Step 2c + db = lHash + ps + b"\x01" + _copy_bytes(None, None, message) + # Step 2d + ros = self._randfunc(hLen) + # Step 2e + dbMask = self._mgf(ros, k - hLen - 1) + # Step 2f + maskedDB = strxor(db, dbMask) + # Step 2g + seedMask = self._mgf(maskedDB, hLen) + # Step 2h + maskedSeed = strxor(ros, seedMask) + # Step 2i + em = b"\x00" + maskedSeed + maskedDB + # Step 3a (OS2IP) + em_int = bytes_to_long(em) + # Step 3b (RSAEP) + m_int = self._key._encrypt(em_int) + # Step 3c (I2OSP) + c = long_to_bytes(m_int, k) + return c + + def decrypt(self, ciphertext): + """Decrypt a message with PKCS#1 OAEP. + + :param ciphertext: The encrypted message. + :type ciphertext: bytes/bytearray/memoryview + + :returns: The original message (plaintext). + :rtype: bytes + + :raises ValueError: + if the ciphertext has the wrong length, or if decryption + fails the integrity check (in which case, the decryption + key is probably wrong). + :raises TypeError: + if the RSA key has no private half (i.e. you are trying + to decrypt using a public key). + """ + + # See 7.1.2 in RFC3447 + modBits = Cryptodome.Util.number.size(self._key.n) + k = ceil_div(modBits, 8) # Convert from bits to bytes + hLen = self._hashObj.digest_size + + # Step 1b and 1c + if len(ciphertext) != k or k < hLen + 2: + raise ValueError("Ciphertext with incorrect length.") + # Step 2a (O2SIP) + ct_int = bytes_to_long(ciphertext) + # Step 2b (RSADP) and step 2c (I2OSP) + em = self._key._decrypt_to_bytes(ct_int) + # Step 3a + lHash = self._hashObj.new(self._label).digest() + # y must be 0, but we MUST NOT check it here in order not to + # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143) + maskedSeed = em[1 : hLen + 1] + maskedDB = em[hLen + 1 :] + # Step 3c + seedMask = self._mgf(maskedDB, hLen) + # Step 3d + seed = strxor(maskedSeed, seedMask) + # Step 3e + dbMask = self._mgf(seed, k - hLen - 1) + # Step 3f + db = strxor(maskedDB, dbMask) + # Step 3b + 3g + res = oaep_decode(em, lHash, db) + if res <= 0: + raise ValueError("Incorrect decryption.") + # Step 4 + return db[res:] + + +def new(key, hashAlgo=None, mgfunc=None, label=b"", randfunc=None): + """Return a cipher object :class:`PKCS1OAEP_Cipher` + that can be used to perform PKCS#1 OAEP encryption or decryption. + + :param key: + The key object to use to encrypt or decrypt the message. + Decryption is only possible with a private RSA key. + :type key: RSA key object + + :param hashAlgo: + The hash function to use. This can be a module under `Cryptodome.Hash` + or an existing hash object created from any of such modules. + If not specified, `Cryptodome.Hash.SHA1` is used. + :type hashAlgo: hash object + + :param mgfunc: + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice). + :type mgfunc: callable + + :param label: + A label to apply to this particular encryption. If not specified, + an empty string is used. Specifying a label does not improve + security. + :type label: bytes/bytearray/memoryview + + :param randfunc: + A function that returns random bytes. + The default is `Random.get_random_bytes`. + :type randfunc: callable + """ + + if randfunc is None: + randfunc = Random.get_random_bytes + return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_OAEP.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_OAEP.pyi index b54cd3f3..733d41da 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_OAEP.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_OAEP.pyi @@ -1,35 +1,39 @@ -from typing import Optional, Union, Callable, Any, overload +from typing import Optional, Union, Callable, Any from typing_extensions import Protocol from Cryptodome.PublicKey.RSA import RsaKey class HashLikeClass(Protocol): - digest_size : int - def new(self, data: Optional[bytes] = ...) -> Any: ... + digest_size: int + def new(self, data: Optional[bytes] = ...) -> Any: ... class HashLikeModule(Protocol): - digest_size : int - @staticmethod - def new(data: Optional[bytes] = ...) -> Any: ... + digest_size: int + @staticmethod + def new(data: Optional[bytes] = ...) -> Any: ... HashLike = Union[HashLikeClass, HashLikeModule] Buffer = Union[bytes, bytearray, memoryview] class PKCS1OAEP_Cipher: - def __init__(self, - key: RsaKey, - hashAlgo: HashLike, - mgfunc: Callable[[bytes, int], bytes], - label: Buffer, - randfunc: Callable[[int], bytes]) -> None: ... - def can_encrypt(self) -> bool: ... - def can_decrypt(self) -> bool: ... - def encrypt(self, message: Buffer) -> bytes: ... - def decrypt(self, ciphertext: Buffer) -> bytes: ... + def __init__( + self, + key: RsaKey, + hashAlgo: HashLike, + mgfunc: Callable[[bytes, int], bytes], + label: Buffer, + randfunc: Callable[[int], bytes], + ) -> None: ... + def can_encrypt(self) -> bool: ... + def can_decrypt(self) -> bool: ... + def encrypt(self, message: Buffer) -> bytes: ... + def decrypt(self, ciphertext: Buffer) -> bytes: ... -def new(key: RsaKey, - hashAlgo: Optional[HashLike] = ..., - mgfunc: Optional[Callable[[bytes, int], bytes]] = ..., - label: Optional[Buffer] = ..., - randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS1OAEP_Cipher: ... +def new( + key: RsaKey, + hashAlgo: Optional[HashLike] = ..., + mgfunc: Optional[Callable[[bytes, int], bytes]] = ..., + label: Optional[Buffer] = ..., + randfunc: Optional[Callable[[int], bytes]] = ..., +) -> PKCS1OAEP_Cipher: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_v1_5.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_v1_5.py index d7a9b793..82f7c59a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_v1_5.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_v1_5.py @@ -20,7 +20,7 @@ # SOFTWARE. # =================================================================== -__all__ = ['new', 'PKCS115_Cipher'] +__all__ = ["new", "PKCS115_Cipher"] from Cryptodome import Random from Cryptodome.Util.number import bytes_to_long, long_to_bytes @@ -29,161 +29,161 @@ class PKCS115_Cipher: - """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption. - Do not instantiate directly. Use :func:`Cryptodome.Cipher.PKCS1_v1_5.new` instead.""" - - def __init__(self, key, randfunc): - """Initialize this PKCS#1 v1.5 cipher object. - - :Parameters: - key : an RSA key object - If a private half is given, both encryption and decryption are possible. - If a public half is given, only encryption is possible. - randfunc : callable - Function that returns random bytes. - """ - - self._key = key - self._randfunc = randfunc - - def can_encrypt(self): - """Return True if this cipher object can be used for encryption.""" - return self._key.can_encrypt() - - def can_decrypt(self): - """Return True if this cipher object can be used for decryption.""" - return self._key.can_decrypt() - - def encrypt(self, message): - """Produce the PKCS#1 v1.5 encryption of a message. - - This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and it is specified in - `section 7.2.1 of RFC8017 - `_. - - :param message: - The message to encrypt, also known as plaintext. It can be of - variable length, but not longer than the RSA modulus (in bytes) minus 11. - :type message: bytes/bytearray/memoryview - - :Returns: A byte string, the ciphertext in which the message is encrypted. - It is as long as the RSA modulus (in bytes). - - :Raises ValueError: - If the RSA key length is not sufficiently long to deal with the given - message. - """ - - # See 7.2.1 in RFC8017 - k = self._key.size_in_bytes() - mLen = len(message) - - # Step 1 - if mLen > k - 11: - raise ValueError("Plaintext is too long.") - # Step 2a - ps = [] - while len(ps) != k - mLen - 3: - new_byte = self._randfunc(1) - if bord(new_byte[0]) == 0x00: - continue - ps.append(new_byte) - ps = b"".join(ps) - # Step 2b - em = b'\x00\x02' + ps + b'\x00' + _copy_bytes(None, None, message) - # Step 3a (OS2IP) - em_int = bytes_to_long(em) - # Step 3b (RSAEP) - m_int = self._key._encrypt(em_int) - # Step 3c (I2OSP) - c = long_to_bytes(m_int, k) - return c - - def decrypt(self, ciphertext, sentinel, expected_pt_len=0): - r"""Decrypt a PKCS#1 v1.5 ciphertext. - - This is the function ``RSAES-PKCS1-V1_5-DECRYPT`` specified in - `section 7.2.2 of RFC8017 - `_. - - Args: - ciphertext (bytes/bytearray/memoryview): - The ciphertext that contains the message to recover. - sentinel (any type): - The object to return whenever an error is detected. - expected_pt_len (integer): - The length the plaintext is known to have, or 0 if unknown. - - Returns (byte string): - It is either the original message or the ``sentinel`` (in case of an error). - - .. warning:: - PKCS#1 v1.5 decryption is intrinsically vulnerable to timing - attacks (see `Bleichenbacher's`__ attack). - **Use PKCS#1 OAEP instead**. - - This implementation attempts to mitigate the risk - with some constant-time constructs. - However, they are not sufficient by themselves: the type of protocol you - implement and the way you handle errors make a big difference. - - Specifically, you should make it very hard for the (malicious) - party that submitted the ciphertext to quickly understand if decryption - succeeded or not. - - To this end, it is recommended that your protocol only encrypts - plaintexts of fixed length (``expected_pt_len``), - that ``sentinel`` is a random byte string of the same length, - and that processing continues for as long - as possible even if ``sentinel`` is returned (i.e. in case of - incorrect decryption). - - .. __: https://dx.doi.org/10.1007/BFb0055716 - """ - - # See 7.2.2 in RFC8017 - k = self._key.size_in_bytes() - - # Step 1 - if len(ciphertext) != k: - raise ValueError("Ciphertext with incorrect length (not %d bytes)" % k) - - # Step 2a (O2SIP) - ct_int = bytes_to_long(ciphertext) - - # Step 2b (RSADP) and Step 2c (I2OSP) - em = self._key._decrypt_to_bytes(ct_int) - - # Step 3 (not constant time when the sentinel is not a byte string) - output = bytes(bytearray(k)) - if not is_bytes(sentinel) or len(sentinel) > k: - size = pkcs1_decode(em, b'', expected_pt_len, output) - if size < 0: - return sentinel - else: - return output[size:] - - # Step 3 (somewhat constant time) - size = pkcs1_decode(em, sentinel, expected_pt_len, output) - return output[size:] + """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption. + Do not instantiate directly. Use :func:`Cryptodome.Cipher.PKCS1_v1_5.new` instead.""" + + def __init__(self, key, randfunc): + """Initialize this PKCS#1 v1.5 cipher object. + + :Parameters: + key : an RSA key object + If a private half is given, both encryption and decryption are possible. + If a public half is given, only encryption is possible. + randfunc : callable + Function that returns random bytes. + """ + + self._key = key + self._randfunc = randfunc + + def can_encrypt(self): + """Return True if this cipher object can be used for encryption.""" + return self._key.can_encrypt() + + def can_decrypt(self): + """Return True if this cipher object can be used for decryption.""" + return self._key.can_decrypt() + + def encrypt(self, message): + """Produce the PKCS#1 v1.5 encryption of a message. + + This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and it is specified in + `section 7.2.1 of RFC8017 + `_. + + :param message: + The message to encrypt, also known as plaintext. It can be of + variable length, but not longer than the RSA modulus (in bytes) minus 11. + :type message: bytes/bytearray/memoryview + + :Returns: A byte string, the ciphertext in which the message is encrypted. + It is as long as the RSA modulus (in bytes). + + :Raises ValueError: + If the RSA key length is not sufficiently long to deal with the given + message. + """ + + # See 7.2.1 in RFC8017 + k = self._key.size_in_bytes() + mLen = len(message) + + # Step 1 + if mLen > k - 11: + raise ValueError("Plaintext is too long.") + # Step 2a + ps = [] + while len(ps) != k - mLen - 3: + new_byte = self._randfunc(1) + if bord(new_byte[0]) == 0x00: + continue + ps.append(new_byte) + ps = b"".join(ps) + # Step 2b + em = b"\x00\x02" + ps + b"\x00" + _copy_bytes(None, None, message) + # Step 3a (OS2IP) + em_int = bytes_to_long(em) + # Step 3b (RSAEP) + m_int = self._key._encrypt(em_int) + # Step 3c (I2OSP) + c = long_to_bytes(m_int, k) + return c + + def decrypt(self, ciphertext, sentinel, expected_pt_len=0): + r"""Decrypt a PKCS#1 v1.5 ciphertext. + + This is the function ``RSAES-PKCS1-V1_5-DECRYPT`` specified in + `section 7.2.2 of RFC8017 + `_. + + Args: + ciphertext (bytes/bytearray/memoryview): + The ciphertext that contains the message to recover. + sentinel (any type): + The object to return whenever an error is detected. + expected_pt_len (integer): + The length the plaintext is known to have, or 0 if unknown. + + Returns (byte string): + It is either the original message or the ``sentinel`` (in case of an error). + + .. warning:: + PKCS#1 v1.5 decryption is intrinsically vulnerable to timing + attacks (see `Bleichenbacher's`__ attack). + **Use PKCS#1 OAEP instead**. + + This implementation attempts to mitigate the risk + with some constant-time constructs. + However, they are not sufficient by themselves: the type of protocol you + implement and the way you handle errors make a big difference. + + Specifically, you should make it very hard for the (malicious) + party that submitted the ciphertext to quickly understand if decryption + succeeded or not. + + To this end, it is recommended that your protocol only encrypts + plaintexts of fixed length (``expected_pt_len``), + that ``sentinel`` is a random byte string of the same length, + and that processing continues for as long + as possible even if ``sentinel`` is returned (i.e. in case of + incorrect decryption). + + .. __: https://dx.doi.org/10.1007/BFb0055716 + """ + + # See 7.2.2 in RFC8017 + k = self._key.size_in_bytes() + + # Step 1 + if len(ciphertext) != k: + raise ValueError("Ciphertext with incorrect length (not %d bytes)" % k) + + # Step 2a (O2SIP) + ct_int = bytes_to_long(ciphertext) + + # Step 2b (RSADP) and Step 2c (I2OSP) + em = self._key._decrypt_to_bytes(ct_int) + + # Step 3 (not constant time when the sentinel is not a byte string) + output = bytes(bytearray(k)) + if not is_bytes(sentinel) or len(sentinel) > k: + size = pkcs1_decode(em, b"", expected_pt_len, output) + if size < 0: + return sentinel + else: + return output[size:] + + # Step 3 (somewhat constant time) + size = pkcs1_decode(em, sentinel, expected_pt_len, output) + return output[size:] def new(key, randfunc=None): - """Create a cipher for performing PKCS#1 v1.5 encryption or decryption. + """Create a cipher for performing PKCS#1 v1.5 encryption or decryption. - :param key: - The key to use to encrypt or decrypt the message. This is a `Cryptodome.PublicKey.RSA` object. - Decryption is only possible if *key* is a private RSA key. - :type key: RSA key object + :param key: + The key to use to encrypt or decrypt the message. This is a `Cryptodome.PublicKey.RSA` object. + Decryption is only possible if *key* is a private RSA key. + :type key: RSA key object - :param randfunc: - Function that return random bytes. - The default is :func:`Cryptodome.Random.get_random_bytes`. - :type randfunc: callable + :param randfunc: + Function that return random bytes. + The default is :func:`Cryptodome.Random.get_random_bytes`. + :type randfunc: callable - :returns: A cipher object `PKCS115_Cipher`. - """ + :returns: A cipher object `PKCS115_Cipher`. + """ - if randfunc is None: - randfunc = Random.get_random_bytes - return PKCS115_Cipher(key, randfunc) + if randfunc is None: + randfunc = Random.get_random_bytes + return PKCS115_Cipher(key, randfunc) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_v1_5.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_v1_5.pyi index b69f5095..e4ed0738 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_v1_5.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/PKCS1_v1_5.pyi @@ -1,20 +1,17 @@ -from typing import Callable, Union, Any, Optional, TypeVar +from typing import Callable, Union, Optional, TypeVar from Cryptodome.PublicKey.RSA import RsaKey Buffer = Union[bytes, bytearray, memoryview] -T = TypeVar('T') +T = TypeVar("T") class PKCS115_Cipher: - def __init__(self, - key: RsaKey, - randfunc: Callable[[int], bytes]) -> None: ... - def can_encrypt(self) -> bool: ... - def can_decrypt(self) -> bool: ... - def encrypt(self, message: Buffer) -> bytes: ... - def decrypt(self, ciphertext: Buffer, - sentinel: T, - expected_pt_len: Optional[int] = ...) -> Union[bytes, T]: ... + def __init__(self, key: RsaKey, randfunc: Callable[[int], bytes]) -> None: ... + def can_encrypt(self) -> bool: ... + def can_decrypt(self) -> bool: ... + def encrypt(self, message: Buffer) -> bytes: ... + def decrypt( + self, ciphertext: Buffer, sentinel: T, expected_pt_len: Optional[int] = ... + ) -> Union[bytes, T]: ... -def new(key: RsaKey, - randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS115_Cipher: ... +def new(key: RsaKey, randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS115_Cipher: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Salsa20.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Salsa20.py index 79e67017..22b4bfe2 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Salsa20.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Salsa20.py @@ -23,16 +23,22 @@ # =================================================================== from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, VoidPointer, - SmartPointer, c_size_t, - c_uint8_ptr, is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + create_string_buffer, + get_raw_buffer, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes -_raw_salsa20_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._Salsa20", - """ +_raw_salsa20_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._Salsa20", + """ int Salsa20_stream_init(uint8_t *key, size_t keylen, uint8_t *nonce, size_t nonce_len, void **pSalsaState); @@ -40,128 +46,135 @@ int Salsa20_stream_encrypt(void *salsaState, const uint8_t in[], uint8_t out[], size_t len); - """) + """, +) class Salsa20Cipher: - """Salsa20 cipher object. Do not create it directly. Use :py:func:`new` - instead. - - :var nonce: The nonce with length 8 - :vartype nonce: byte string - """ - - def __init__(self, key, nonce): - """Initialize a Salsa20 cipher object - - See also `new()` at the module level.""" - - if len(key) not in key_size: - raise ValueError("Incorrect key length for Salsa20 (%d bytes)" % len(key)) - - if len(nonce) != 8: - raise ValueError("Incorrect nonce length for Salsa20 (%d bytes)" % - len(nonce)) - - self.nonce = _copy_bytes(None, None, nonce) - - self._state = VoidPointer() - result = _raw_salsa20_lib.Salsa20_stream_init( - c_uint8_ptr(key), - c_size_t(len(key)), - c_uint8_ptr(nonce), - c_size_t(len(nonce)), - self._state.address_of()) - if result: - raise ValueError("Error %d instantiating a Salsa20 cipher") - self._state = SmartPointer(self._state.get(), - _raw_salsa20_lib.Salsa20_stream_destroy) - - self.block_size = 1 - self.key_size = len(key) - - def encrypt(self, plaintext, output=None): - """Encrypt a piece of data. - - Args: - plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the ciphertext - is written to. If ``None``, the ciphertext is returned. - Returns: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = _raw_salsa20_lib.Salsa20_stream_encrypt( - self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting with Salsa20" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt a piece of data. - - Args: - ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the plaintext - is written to. If ``None``, the plaintext is returned. - Returns: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - try: - return self.encrypt(ciphertext, output=output) - except ValueError as e: - raise ValueError(str(e).replace("enc", "dec")) + """Salsa20 cipher object. Do not create it directly. Use :py:func:`new` + instead. + + :var nonce: The nonce with length 8 + :vartype nonce: byte string + """ + + def __init__(self, key, nonce): + """Initialize a Salsa20 cipher object + + See also `new()` at the module level.""" + + if len(key) not in key_size: + raise ValueError("Incorrect key length for Salsa20 (%d bytes)" % len(key)) + + if len(nonce) != 8: + raise ValueError( + "Incorrect nonce length for Salsa20 (%d bytes)" % len(nonce), + ) + + self.nonce = _copy_bytes(None, None, nonce) + + self._state = VoidPointer() + result = _raw_salsa20_lib.Salsa20_stream_init( + c_uint8_ptr(key), + c_size_t(len(key)), + c_uint8_ptr(nonce), + c_size_t(len(nonce)), + self._state.address_of(), + ) + if result: + raise ValueError("Error %d instantiating a Salsa20 cipher") + self._state = SmartPointer( + self._state.get(), + _raw_salsa20_lib.Salsa20_stream_destroy, + ) + + self.block_size = 1 + self.key_size = len(key) + + def encrypt(self, plaintext, output=None): + """Encrypt a piece of data. + + Args: + plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the ciphertext + is written to. If ``None``, the ciphertext is returned. + Returns: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = _raw_salsa20_lib.Salsa20_stream_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting with Salsa20" % result) + + if output is None: + return get_raw_buffer(ciphertext) + else: + return None + + def decrypt(self, ciphertext, output=None): + """Decrypt a piece of data. + + Args: + ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. + Keyword Args: + output(bytes/bytearray/memoryview): The location where the plaintext + is written to. If ``None``, the plaintext is returned. + Returns: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + try: + return self.encrypt(ciphertext, output=output) + except ValueError as e: + raise ValueError(str(e).replace("enc", "dec")) def new(key, nonce=None): - """Create a new Salsa20 cipher + """Create a new Salsa20 cipher - :keyword key: The secret key to use. It must be 16 or 32 bytes long. - :type key: bytes/bytearray/memoryview + :keyword key: The secret key to use. It must be 16 or 32 bytes long. + :type key: bytes/bytearray/memoryview - :keyword nonce: - A value that must never be reused for any other encryption - done with this key. It must be 8 bytes long. + :keyword nonce: + A value that must never be reused for any other encryption + done with this key. It must be 8 bytes long. - If not provided, a random byte string will be generated (you can read - it back via the ``nonce`` attribute of the returned object). - :type nonce: bytes/bytearray/memoryview + If not provided, a random byte string will be generated (you can read + it back via the ``nonce`` attribute of the returned object). + :type nonce: bytes/bytearray/memoryview - :Return: a :class:`Cryptodome.Cipher.Salsa20.Salsa20Cipher` object - """ + :Return: a :class:`Cryptodome.Cipher.Salsa20.Salsa20Cipher` object + """ - if nonce is None: - nonce = get_random_bytes(8) + if nonce is None: + nonce = get_random_bytes(8) + + return Salsa20Cipher(key, nonce) - return Salsa20Cipher(key, nonce) # Size of a data block (in bytes) block_size = 1 # Size of a key (in bytes) key_size = (16, 32) - diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Salsa20.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Salsa20.pyi index cf8690e2..1e1e60b4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Salsa20.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/Salsa20.pyi @@ -1,26 +1,23 @@ -from typing import Union, Tuple, Optional, overload, Optional +from typing import Union, Tuple, overload, Optional -Buffer = bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview class Salsa20Cipher: - nonce: bytes - block_size: int - key_size: int + nonce: bytes + block_size: int + key_size: int - def __init__(self, - key: Buffer, - nonce: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def __init__(self, key: Buffer, nonce: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... def new(key: Buffer, nonce: Optional[Buffer] = ...) -> Salsa20Cipher: ... block_size: int key_size: Tuple[int, int] - diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_EKSBlowfish.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_EKSBlowfish.py index c1c3249a..a13550cc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_EKSBlowfish.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_EKSBlowfish.py @@ -31,13 +31,18 @@ import sys from Cryptodome.Cipher import _create_cipher -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, c_size_t, - c_uint8_ptr, c_uint) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + c_uint, +) _raw_blowfish_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._raw_eksblowfish", - """ + "Cryptodome.Cipher._raw_eksblowfish", + """ int EKSBlowfish_start_operation(const uint8_t key[], size_t key_len, const uint8_t salt[16], @@ -54,73 +59,76 @@ uint8_t *out, size_t data_len); int EKSBlowfish_stop_operation(void *state); - """ - ) + """, +) def _create_base_cipher(dict_parameters): - """This method instantiates and returns a smart pointer to - a low-level base cipher. It will absorb named parameters in - the process.""" - - try: - key = dict_parameters.pop("key") - salt = dict_parameters.pop("salt") - cost = dict_parameters.pop("cost") - except KeyError as e: - raise TypeError("Missing EKSBlowfish parameter: " + str(e)) - invert = dict_parameters.pop("invert", True) - - if len(key) not in key_size: - raise ValueError("Incorrect EKSBlowfish key length (%d bytes)" % len(key)) - - start_operation = _raw_blowfish_lib.EKSBlowfish_start_operation - stop_operation = _raw_blowfish_lib.EKSBlowfish_stop_operation - - void_p = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - c_uint8_ptr(salt), - c_size_t(len(salt)), - c_uint(cost), - c_uint(int(invert)), - void_p.address_of()) - if result: - raise ValueError("Error %X while instantiating the EKSBlowfish cipher" - % result) - return SmartPointer(void_p.get(), stop_operation) + """This method instantiates and returns a smart pointer to + a low-level base cipher. It will absorb named parameters in + the process.""" + + try: + key = dict_parameters.pop("key") + salt = dict_parameters.pop("salt") + cost = dict_parameters.pop("cost") + except KeyError as e: + raise TypeError("Missing EKSBlowfish parameter: " + str(e)) + invert = dict_parameters.pop("invert", True) + + if len(key) not in key_size: + raise ValueError("Incorrect EKSBlowfish key length (%d bytes)" % len(key)) + + start_operation = _raw_blowfish_lib.EKSBlowfish_start_operation + stop_operation = _raw_blowfish_lib.EKSBlowfish_stop_operation + + void_p = VoidPointer() + result = start_operation( + c_uint8_ptr(key), + c_size_t(len(key)), + c_uint8_ptr(salt), + c_size_t(len(salt)), + c_uint(cost), + c_uint(int(invert)), + void_p.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the EKSBlowfish cipher" % result, + ) + return SmartPointer(void_p.get(), stop_operation) def new(key, mode, salt, cost, invert): - """Create a new EKSBlowfish cipher - - Args: + """Create a new EKSBlowfish cipher - key (bytes, bytearray, memoryview): - The secret key to use in the symmetric cipher. - Its length can vary from 0 to 72 bytes. + Args: - mode (one of the supported ``MODE_*`` constants): - The chaining mode to use for encryption or decryption. + key (bytes, bytearray, memoryview): + The secret key to use in the symmetric cipher. + Its length can vary from 0 to 72 bytes. - salt (bytes, bytearray, memoryview): - The salt that bcrypt uses to thwart rainbow table attacks + mode (one of the supported ``MODE_*`` constants): + The chaining mode to use for encryption or decryption. - cost (integer): - The complexity factor in bcrypt + salt (bytes, bytearray, memoryview): + The salt that bcrypt uses to thwart rainbow table attacks - invert (bool): - If ``False``, in the inner loop use ``ExpandKey`` first over the salt - and then over the key, as defined in - the `original bcrypt specification `_. - If ``True``, reverse the order, as in the first implementation of - `bcrypt` in OpenBSD. + cost (integer): + The complexity factor in bcrypt - :Return: an EKSBlowfish object - """ + invert (bool): + If ``False``, in the inner loop use ``ExpandKey`` first over the salt + and then over the key, as defined in + the `original bcrypt specification `_. + If ``True``, reverse the order, as in the first implementation of + `bcrypt` in OpenBSD. - kwargs = { 'salt':salt, 'cost':cost, 'invert':invert } - return _create_cipher(sys.modules[__name__], key, mode, **kwargs) + :Return: an EKSBlowfish object + """ + + kwargs = {"salt": salt, "cost": cost, "invert": invert} + return _create_cipher(sys.modules[__name__], key, mode, **kwargs) MODE_ECB = 1 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_EKSBlowfish.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_EKSBlowfish.pyi index 49c84489..812577c6 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_EKSBlowfish.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_EKSBlowfish.pyi @@ -6,10 +6,7 @@ MODE_ECB: int Buffer = Union[bytes, bytearray, memoryview] -def new(key: Buffer, - mode: int, - salt: Buffer, - cost: int) -> EcbMode: ... +def new(key: Buffer, mode: int, salt: Buffer, cost: int) -> EcbMode: ... block_size: int key_size: Iterable[int] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/__init__.py index 88237119..09630900 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/__init__.py @@ -22,70 +22,83 @@ # # where mode_state is a a pointer to base_cipher_state plus mode-specific data. + def _create_cipher(factory, key, mode, *args, **kwargs): + kwargs["key"] = key + + if args: + if mode in (8, 9, 10, 11, 12): + if len(args) > 1: + raise TypeError("Too many arguments for this mode") + kwargs["nonce"] = args[0] + elif mode in (2, 3, 5, 7): + if len(args) > 1: + raise TypeError("Too many arguments for this mode") + kwargs["IV"] = args[0] + elif mode == 6: + if len(args) > 0: + raise TypeError("Too many arguments for this mode") + elif mode == 1: + raise TypeError("IV is not meaningful for the ECB mode") + + res = None + extra_modes = kwargs.pop("add_aes_modes", False) + + if mode == 1: + from Cryptodome.Cipher._mode_ecb import _create_ecb_cipher + + res = _create_ecb_cipher(factory, **kwargs) + elif mode == 2: + from Cryptodome.Cipher._mode_cbc import _create_cbc_cipher + + res = _create_cbc_cipher(factory, **kwargs) + elif mode == 3: + from Cryptodome.Cipher._mode_cfb import _create_cfb_cipher + + res = _create_cfb_cipher(factory, **kwargs) + elif mode == 5: + from Cryptodome.Cipher._mode_ofb import _create_ofb_cipher + + res = _create_ofb_cipher(factory, **kwargs) + elif mode == 6: + from Cryptodome.Cipher._mode_ctr import _create_ctr_cipher + + res = _create_ctr_cipher(factory, **kwargs) + elif mode == 7: + from Cryptodome.Cipher._mode_openpgp import _create_openpgp_cipher + + res = _create_openpgp_cipher(factory, **kwargs) + elif mode == 9: + from Cryptodome.Cipher._mode_eax import _create_eax_cipher + + res = _create_eax_cipher(factory, **kwargs) + elif extra_modes: + if mode == 8: + from Cryptodome.Cipher._mode_ccm import _create_ccm_cipher + + res = _create_ccm_cipher(factory, **kwargs) + elif mode == 10: + from Cryptodome.Cipher._mode_siv import _create_siv_cipher + + res = _create_siv_cipher(factory, **kwargs) + elif mode == 11: + from Cryptodome.Cipher._mode_gcm import _create_gcm_cipher + + res = _create_gcm_cipher(factory, **kwargs) + elif mode == 12: + from Cryptodome.Cipher._mode_ocb import _create_ocb_cipher + + res = _create_ocb_cipher(factory, **kwargs) + elif mode == 13: + from Cryptodome.Cipher._mode_kw import _create_kw_cipher + + res = _create_kw_cipher(factory, **kwargs) + elif mode == 14: + from Cryptodome.Cipher._mode_kwp import _create_kwp_cipher + + res = _create_kwp_cipher(factory, **kwargs) + + if res is None: + raise ValueError("Mode not supported") - kwargs["key"] = key - - if args: - if mode in (8, 9, 10, 11, 12): - if len(args) > 1: - raise TypeError("Too many arguments for this mode") - kwargs["nonce"] = args[0] - elif mode in (2, 3, 5, 7): - if len(args) > 1: - raise TypeError("Too many arguments for this mode") - kwargs["IV"] = args[0] - elif mode == 6: - if len(args) > 0: - raise TypeError("Too many arguments for this mode") - elif mode == 1: - raise TypeError("IV is not meaningful for the ECB mode") - - res = None - extra_modes = kwargs.pop("add_aes_modes", False) - - if mode == 1: - from Cryptodome.Cipher._mode_ecb import _create_ecb_cipher - res = _create_ecb_cipher(factory, **kwargs) - elif mode == 2: - from Cryptodome.Cipher._mode_cbc import _create_cbc_cipher - res = _create_cbc_cipher(factory, **kwargs) - elif mode == 3: - from Cryptodome.Cipher._mode_cfb import _create_cfb_cipher - res = _create_cfb_cipher(factory, **kwargs) - elif mode == 5: - from Cryptodome.Cipher._mode_ofb import _create_ofb_cipher - res = _create_ofb_cipher(factory, **kwargs) - elif mode == 6: - from Cryptodome.Cipher._mode_ctr import _create_ctr_cipher - res = _create_ctr_cipher(factory, **kwargs) - elif mode == 7: - from Cryptodome.Cipher._mode_openpgp import _create_openpgp_cipher - res = _create_openpgp_cipher(factory, **kwargs) - elif mode == 9: - from Cryptodome.Cipher._mode_eax import _create_eax_cipher - res = _create_eax_cipher(factory, **kwargs) - elif extra_modes: - if mode == 8: - from Cryptodome.Cipher._mode_ccm import _create_ccm_cipher - res = _create_ccm_cipher(factory, **kwargs) - elif mode == 10: - from Cryptodome.Cipher._mode_siv import _create_siv_cipher - res = _create_siv_cipher(factory, **kwargs) - elif mode == 11: - from Cryptodome.Cipher._mode_gcm import _create_gcm_cipher - res = _create_gcm_cipher(factory, **kwargs) - elif mode == 12: - from Cryptodome.Cipher._mode_ocb import _create_ocb_cipher - res = _create_ocb_cipher(factory, **kwargs) - elif mode == 13: - from Cryptodome.Cipher._mode_kw import _create_kw_cipher - res = _create_kw_cipher(factory, **kwargs) - elif mode == 14: - from Cryptodome.Cipher._mode_kwp import _create_kwp_cipher - res = _create_kwp_cipher(factory, **kwargs) - - if res is None: - raise ValueError("Mode not supported") - - return res + return res diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cbc.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cbc.py index 94d02e70..b07772bc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cbc.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cbc.py @@ -32,17 +32,25 @@ Ciphertext Block Chaining (CBC) mode. """ -__all__ = ['CbcMode'] +__all__ = ["CbcMode"] from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes -raw_cbc_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_cbc", """ +raw_cbc_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_cbc", + """ int CBC_start_operation(void *cipher, const uint8_t iv[], size_t iv_len, @@ -56,238 +64,250 @@ uint8_t *out, size_t data_len); int CBC_stop_operation(void *state); - """ - ) + """, +) class CbcMode(object): - """*Cipher-Block Chaining (CBC)*. + """*Cipher-Block Chaining (CBC)*. - Each of the ciphertext blocks depends on the current - and all previous plaintext blocks. + Each of the ciphertext blocks depends on the current + and all previous plaintext blocks. - An Initialization Vector (*IV*) is required. + An Initialization Vector (*IV*) is required. - See `NIST SP800-38A`_ , Section 6.2 . + See `NIST SP800-38A`_ , Section 6.2 . - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, block_cipher, iv): - """Create a new block cipher, configured in CBC mode. + def __init__(self, block_cipher, iv): + """Create a new block cipher, configured in CBC mode. - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. - iv : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - It is as long as the cipher block. + iv : bytes/bytearray/memoryview + The initialization vector to use for encryption or decryption. + It is as long as the cipher block. - **The IV must be unpredictable**. Ideally it is picked randomly. + **The IV must be unpredictable**. Ideally it is picked randomly. - Reusing the *IV* for encryptions performed with the same key - compromises confidentiality. - """ + Reusing the *IV* for encryptions performed with the same key + compromises confidentiality. + """ - self._state = VoidPointer() - result = raw_cbc_lib.CBC_start_operation(block_cipher.get(), - c_uint8_ptr(iv), - c_size_t(len(iv)), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the CBC mode" - % result) + self._state = VoidPointer() + result = raw_cbc_lib.CBC_start_operation( + block_cipher.get(), + c_uint8_ptr(iv), + c_size_t(len(iv)), + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %d while instantiating the CBC mode" % result, + ) - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_cbc_lib.CBC_stop_operation) + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + raw_cbc_lib.CBC_stop_operation, + ) - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + block_cipher.release() - self.block_size = len(iv) - """The block size of the underlying cipher, in bytes.""" + self.block_size = len(iv) + """The block size of the underlying cipher, in bytes.""" - self.iv = _copy_bytes(None, None, iv) - """The Initialization Vector originally used to create the object. + self.iv = _copy_bytes(None, None, iv) + """The Initialization Vector originally used to create the object. The value does not change.""" - self.IV = self.iv - """Alias for `iv`""" + self.IV = self.iv + """Alias for `iv`""" - self._next = ["encrypt", "decrypt"] + self._next = ["encrypt", "decrypt"] - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.encrypt(a) + c.encrypt(b) + >>> c.encrypt(a) + c.encrypt(b) - is equivalent to: + is equivalent to: - >>> c.encrypt(a+b) + >>> c.encrypt(a+b) - That also means that you cannot reuse an object for encrypting - or decrypting other data with the same key. + That also means that you cannot reuse an object for encrypting + or decrypting other data with the same key. - This function does not add any padding to the plaintext. + This function does not add any padding to the plaintext. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - Its lenght must be multiple of the cipher block size. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + Its lenght must be multiple of the cipher block size. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = ["encrypt"] + if "encrypt" not in self._next: + raise TypeError("encrypt() cannot be called after decrypt()") + self._next = ["encrypt"] - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) - result = raw_cbc_lib.CBC_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - if result == 3: - raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) - raise ValueError("Error %d while encrypting in CBC mode" % result) + result = raw_cbc_lib.CBC_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + if result == 3: + raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) + raise ValueError("Error %d while encrypting in CBC mode" % result) - if output is None: - return get_raw_buffer(ciphertext) - else: - return None + if output is None: + return get_raw_buffer(ciphertext) + else: + return None - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.decrypt(a) + c.decrypt(b) + >>> c.decrypt(a) + c.decrypt(b) - is equivalent to: + is equivalent to: - >>> c.decrypt(a+b) + >>> c.decrypt(a+b) - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - Its length must be multiple of the cipher block size. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = ["decrypt"] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_cbc_lib.CBC_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - if result == 3: - raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) - raise ValueError("Error %d while decrypting in CBC mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + Its length must be multiple of the cipher block size. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError("decrypt() cannot be called after encrypt()") + self._next = ["decrypt"] + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_cbc_lib.CBC_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + if result == 3: + raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) + raise ValueError("Error %d while decrypting in CBC mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_cbc_cipher(factory, **kwargs): - """Instantiate a cipher object that performs CBC encryption/decryption. + """Instantiate a cipher object that performs CBC encryption/decryption. - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. - :Keywords: - iv : bytes/bytearray/memoryview - The IV to use for CBC. + :Keywords: + iv : bytes/bytearray/memoryview + The IV to use for CBC. - IV : bytes/bytearray/memoryview - Alias for ``iv``. + IV : bytes/bytearray/memoryview + Alias for ``iv``. - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ - cipher_state = factory._create_base_cipher(kwargs) - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) + cipher_state = factory._create_base_cipher(kwargs) + iv = kwargs.pop("IV", None) + IV = kwargs.pop("iv", None) - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV + if (None, None) == (iv, IV): + iv = get_random_bytes(factory.block_size) + if iv is not None: + if IV is not None: + raise TypeError("You must either use 'iv' or 'IV', not both") + else: + iv = IV - if len(iv) != factory.block_size: - raise ValueError("Incorrect IV length (it must be %d bytes long)" % - factory.block_size) + if len(iv) != factory.block_size: + raise ValueError( + "Incorrect IV length (it must be %d bytes long)" % factory.block_size, + ) - if kwargs: - raise TypeError("Unknown parameters for CBC: %s" % str(kwargs)) + if kwargs: + raise TypeError("Unknown parameters for CBC: %s" % str(kwargs)) - return CbcMode(cipher_state, iv) + return CbcMode(cipher_state, iv) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cbc.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cbc.pyi index 526632eb..779e8dee 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cbc.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cbc.pyi @@ -4,22 +4,19 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['CbcMode'] +__all__ = ["CbcMode"] class CbcMode(object): - block_size: int - iv: Buffer - IV: Buffer - - def __init__(self, - block_cipher: SmartPointer, - iv: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + block_size: int + iv: Buffer + IV: Buffer + def __init__(self, block_cipher: SmartPointer, iv: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ccm.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ccm.py index ac272217..1ca5cbad 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ccm.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ccm.py @@ -32,13 +32,15 @@ Counter with CBC-MAC (CCM) mode. """ -__all__ = ['CcmMode'] +__all__ = ["CcmMode"] import struct from binascii import unhexlify -from Cryptodome.Util.py3compat import (byte_string, bord, - _copy_bytes) +from Cryptodome.Util.py3compat import ( + bord, + _copy_bytes, +) from Cryptodome.Util._raw_api import is_writeable_buffer from Cryptodome.Util.strxor import strxor @@ -49,623 +51,663 @@ def enum(**enums): - return type('Enum', (), enums) + return type("Enum", (), enums) + MacStatus = enum(NOT_STARTED=0, PROCESSING_AUTH_DATA=1, PROCESSING_PLAINTEXT=2) class CCMMessageTooLongError(ValueError): - pass + pass class CcmMode(object): - """Counter with CBC-MAC (CCM). - - This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. - It provides both confidentiality and authenticity. - - The header of the message may be left in the clear, if needed, and it will - still be subject to authentication. The decryption step tells the receiver - if the message comes from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - including the - header - has been modified or corrupted. - - This mode requires a nonce. The nonce shall never repeat for two - different messages encrypted with the same key, but it does not need - to be random. - Note that there is a trade-off between the size of the nonce and the - maximum size of a single message you can encrypt. - - It is important to use a large nonce if the key is reused across several - messages and the nonce is chosen randomly. - - It is acceptable to us a short nonce if the key is only used a few times or - if the nonce is taken from a counter. - - The following table shows the trade-off when the nonce is chosen at - random. The column on the left shows how many messages it takes - for the keystream to repeat **on average**. In practice, you will want to - stop using the key way before that. - - +--------------------+---------------+-------------------+ - | Avg. # of messages | nonce | Max. message | - | before keystream | size | size | - | repeats | (bytes) | (bytes) | - +====================+===============+===================+ - | 2^52 | 13 | 64K | - +--------------------+---------------+-------------------+ - | 2^48 | 12 | 16M | - +--------------------+---------------+-------------------+ - | 2^44 | 11 | 4G | - +--------------------+---------------+-------------------+ - | 2^40 | 10 | 1T | - +--------------------+---------------+-------------------+ - | 2^36 | 9 | 64P | - +--------------------+---------------+-------------------+ - | 2^32 | 8 | 16E | - +--------------------+---------------+-------------------+ - - This mode is only available for ciphers that operate on 128 bits blocks - (e.g. AES but not TDES). - - See `NIST SP800-38C`_ or RFC3610_. - - .. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf - .. _RFC3610: https://tools.ietf.org/html/rfc3610 - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, mac_len, msg_len, assoc_len, - cipher_params): - - self.block_size = factory.block_size - """The block size of the underlying cipher, in bytes.""" - - self.nonce = _copy_bytes(None, None, nonce) - """The nonce used for this cipher instance""" - - self._factory = factory - self._key = _copy_bytes(None, None, key) - self._mac_len = mac_len - self._msg_len = msg_len - self._assoc_len = assoc_len - self._cipher_params = cipher_params - - self._mac_tag = None # Cache for MAC tag - - if self.block_size != 16: - raise ValueError("CCM mode is only available for ciphers" - " that operate on 128 bits blocks") - - # MAC tag length (Tlen) - if mac_len not in (4, 6, 8, 10, 12, 14, 16): - raise ValueError("Parameter 'mac_len' must be even" - " and in the range 4..16 (not %d)" % mac_len) - - # Nonce value - if not (7 <= len(nonce) <= 13): - raise ValueError("Length of parameter 'nonce' must be" - " in the range 7..13 bytes") - - # Message length (if known already) - q = 15 - len(nonce) # length of Q, the encoded message length - if msg_len and len(long_to_bytes(msg_len)) > q: - raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(nonce)) - - # Create MAC object (the tag will be the last block - # bytes worth of ciphertext) - self._mac = self._factory.new(key, - factory.MODE_CBC, - iv=b'\x00' * 16, - **cipher_params) - self._mac_status = MacStatus.NOT_STARTED - self._t = None - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - # Cumulative lengths - self._cumul_assoc_len = 0 - self._cumul_msg_len = 0 - - # Cache for unaligned associated data/plaintext. - # This is a list with byte strings, but when the MAC starts, - # it will become a binary string no longer than the block size. - self._cache = [] - - # Start CTR cipher, by formatting the counter (A.3) - self._cipher = self._factory.new(key, - self._factory.MODE_CTR, - nonce=struct.pack("B", q - 1) + self.nonce, - **cipher_params) - - # S_0, step 6 in 6.1 for j=0 - self._s_0 = self._cipher.encrypt(b'\x00' * 16) - - # Try to start the MAC - if None not in (assoc_len, msg_len): - self._start_mac() - - def _start_mac(self): - - assert(self._mac_status == MacStatus.NOT_STARTED) - assert(None not in (self._assoc_len, self._msg_len)) - assert(isinstance(self._cache, list)) - - # Formatting control information and nonce (A.2.1) - q = 15 - len(self.nonce) # length of Q, the encoded message length (2..8) - flags = (self._assoc_len > 0) << 6 - flags |= ((self._mac_len - 2) // 2) << 3 - flags |= q - 1 - b_0 = struct.pack("B", flags) + self.nonce + long_to_bytes(self._msg_len, q) - - # Formatting associated data (A.2.2) - # Encoded 'a' is concatenated with the associated data 'A' - assoc_len_encoded = b'' - if self._assoc_len > 0: - if self._assoc_len < (2 ** 16 - 2 ** 8): - enc_size = 2 - elif self._assoc_len < (2 ** 32): - assoc_len_encoded = b'\xFF\xFE' - enc_size = 4 - else: - assoc_len_encoded = b'\xFF\xFF' - enc_size = 8 - assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size) - - # b_0 and assoc_len_encoded must be processed first - self._cache.insert(0, b_0) - self._cache.insert(1, assoc_len_encoded) - - # Process all the data cached so far - first_data_to_mac = b"".join(self._cache) - self._cache = b"" - self._mac_status = MacStatus.PROCESSING_AUTH_DATA - self._update(first_data_to_mac) - - def _pad_cache_and_update(self): - - assert(self._mac_status != MacStatus.NOT_STARTED) - assert(len(self._cache) < self.block_size) - - # Associated data is concatenated with the least number - # of zero bytes (possibly none) to reach alignment to - # the 16 byte boundary (A.2.3) - len_cache = len(self._cache) - if len_cache > 0: - self._update(b'\x00' * (self.block_size - len_cache)) - - def update(self, assoc_data): - """Protect associated data - - If there is any associated data, the caller has to invoke - this function one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver is still able to detect any modification to it. - In CCM, the *associated data* is also called - *additional authenticated data* (AAD). - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. There are no restrictions on its size. - """ - - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - self._cumul_assoc_len += len(assoc_data) - if self._assoc_len is not None and \ - self._cumul_assoc_len > self._assoc_len: - raise ValueError("Associated data is too long") - - self._update(assoc_data) - return self - - def _update(self, assoc_data_pt=b""): - """Update the MAC with associated data or plaintext - (without FSM checks)""" - - # If MAC has not started yet, we just park the data into a list. - # If the data is mutable, we create a copy and store that instead. - if self._mac_status == MacStatus.NOT_STARTED: - if is_writeable_buffer(assoc_data_pt): - assoc_data_pt = _copy_bytes(None, None, assoc_data_pt) - self._cache.append(assoc_data_pt) - return - - assert(len(self._cache) < self.block_size) - - if len(self._cache) > 0: - filler = min(self.block_size - len(self._cache), - len(assoc_data_pt)) - self._cache += _copy_bytes(None, filler, assoc_data_pt) - assoc_data_pt = _copy_bytes(filler, None, assoc_data_pt) - - if len(self._cache) < self.block_size: - return - - # The cache is exactly one block - self._t = self._mac.encrypt(self._cache) - self._cache = b"" - - update_len = len(assoc_data_pt) // self.block_size * self.block_size - self._cache = _copy_bytes(update_len, None, assoc_data_pt) - if update_len > 0: - self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:] - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - This method can be called only **once** if ``msg_len`` was - not passed at initialization. - - If ``msg_len`` was given, the data to encrypt can be broken - up in two or more pieces and `encrypt` can be called - multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext as ``bytes``. - Otherwise, ``None``. - """ - - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - self._next = ["encrypt", "digest"] - - # No more associated data allowed from now - if self._assoc_len is None: - assert(isinstance(self._cache, list)) - self._assoc_len = sum([len(x) for x in self._cache]) - if self._msg_len is not None: - self._start_mac() - else: - if self._cumul_assoc_len < self._assoc_len: - raise ValueError("Associated data is too short") - - # Only once piece of plaintext accepted if message length was - # not declared in advance - if self._msg_len is None: - q = 15 - len(self.nonce) - if len(long_to_bytes(len(plaintext))) > q: - raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(self.nonce)) - - self._msg_len = len(plaintext) - self._start_mac() - self._next = ["digest"] - - self._cumul_msg_len += len(plaintext) - if self._cumul_msg_len > self._msg_len: - msg = "Message longer than declared for (%u bytes vs %u bytes" % \ - (self._cumul_msg_len, self._msg_len) - raise CCMMessageTooLongError(msg) - - if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: - # Associated data is concatenated with the least number - # of zero bytes (possibly none) to reach alignment to - # the 16 byte boundary (A.2.3) - self._pad_cache_and_update() - self._mac_status = MacStatus.PROCESSING_PLAINTEXT - - self._update(plaintext) - return self._cipher.encrypt(plaintext, output=output) - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - This method can be called only **once** if ``msg_len`` was - not passed at initialization. - - If ``msg_len`` was given, the data to decrypt can be - broken up in two or more pieces and `decrypt` can be - called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = ["decrypt", "verify"] - - # No more associated data allowed from now - if self._assoc_len is None: - assert(isinstance(self._cache, list)) - self._assoc_len = sum([len(x) for x in self._cache]) - if self._msg_len is not None: - self._start_mac() - else: - if self._cumul_assoc_len < self._assoc_len: - raise ValueError("Associated data is too short") - - # Only once piece of ciphertext accepted if message length was - # not declared in advance - if self._msg_len is None: - q = 15 - len(self.nonce) - if len(long_to_bytes(len(ciphertext))) > q: - raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(self.nonce)) - - self._msg_len = len(ciphertext) - self._start_mac() - self._next = ["verify"] - - self._cumul_msg_len += len(ciphertext) - if self._cumul_msg_len > self._msg_len: - msg = "Message longer than declared for (%u bytes vs %u bytes" % \ - (self._cumul_msg_len, self._msg_len) - raise CCMMessageTooLongError(msg) - - if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: - # Associated data is concatenated with the least number - # of zero bytes (possibly none) to reach alignment to - # the 16 byte boundary (A.2.3) - self._pad_cache_and_update() - self._mac_status = MacStatus.PROCESSING_PLAINTEXT - - # Encrypt is equivalent to decrypt with the CTR mode - plaintext = self._cipher.encrypt(ciphertext, output=output) - if output is None: - self._update(plaintext) - else: - self._update(output) - return plaintext - - def digest(self): - """Compute the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. - - :Return: the MAC, as a byte string. - """ - - if "digest" not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = ["digest"] - return self._digest() - - def _digest(self): - if self._mac_tag: - return self._mac_tag - - if self._assoc_len is None: - assert(isinstance(self._cache, list)) - self._assoc_len = sum([len(x) for x in self._cache]) - if self._msg_len is not None: - self._start_mac() - else: - if self._cumul_assoc_len < self._assoc_len: - raise ValueError("Associated data is too short") - - if self._msg_len is None: - self._msg_len = 0 - self._start_mac() - - if self._cumul_msg_len != self._msg_len: - raise ValueError("Message is too short") - - # Both associated data and payload are concatenated with the least - # number of zero bytes (possibly none) that align it to the - # 16 byte boundary (A.2.2 and A.2.3) - self._pad_cache_and_update() - - # Step 8 in 6.1 (T xor MSB_Tlen(S_0)) - self._mac_tag = strxor(self._t, self._s_0)[:self._mac_len] - - return self._mac_tag - - def hexdigest(self): - """Compute the *printable* MAC tag. - - This method is like `digest`. - - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. - - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ["verify"] - - self._digest() - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. - - This method is like `verify`. - - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: - - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` - - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ - - return self.encrypt(plaintext, output=output), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): - """Perform decrypt() and verify() in one step. + """Counter with CBC-MAC (CCM). + + This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. + It provides both confidentiality and authenticity. + + The header of the message may be left in the clear, if needed, and it will + still be subject to authentication. The decryption step tells the receiver + if the message comes from a source that really knowns the secret key. + Additionally, decryption detects if any part of the message - including the + header - has been modified or corrupted. + + This mode requires a nonce. The nonce shall never repeat for two + different messages encrypted with the same key, but it does not need + to be random. + Note that there is a trade-off between the size of the nonce and the + maximum size of a single message you can encrypt. + + It is important to use a large nonce if the key is reused across several + messages and the nonce is chosen randomly. + + It is acceptable to us a short nonce if the key is only used a few times or + if the nonce is taken from a counter. + + The following table shows the trade-off when the nonce is chosen at + random. The column on the left shows how many messages it takes + for the keystream to repeat **on average**. In practice, you will want to + stop using the key way before that. + + +--------------------+---------------+-------------------+ + | Avg. # of messages | nonce | Max. message | + | before keystream | size | size | + | repeats | (bytes) | (bytes) | + +====================+===============+===================+ + | 2^52 | 13 | 64K | + +--------------------+---------------+-------------------+ + | 2^48 | 12 | 16M | + +--------------------+---------------+-------------------+ + | 2^44 | 11 | 4G | + +--------------------+---------------+-------------------+ + | 2^40 | 10 | 1T | + +--------------------+---------------+-------------------+ + | 2^36 | 9 | 64P | + +--------------------+---------------+-------------------+ + | 2^32 | 8 | 16E | + +--------------------+---------------+-------------------+ + + This mode is only available for ciphers that operate on 128 bits blocks + (e.g. AES but not TDES). + + See `NIST SP800-38C`_ or RFC3610_. + + .. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf + .. _RFC3610: https://tools.ietf.org/html/rfc3610 + .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html + + :undocumented: __init__ + """ + + def __init__( + self, + factory, + key, + nonce, + mac_len, + msg_len, + assoc_len, + cipher_params, + ): + self.block_size = factory.block_size + """The block size of the underlying cipher, in bytes.""" + + self.nonce = _copy_bytes(None, None, nonce) + """The nonce used for this cipher instance""" + + self._factory = factory + self._key = _copy_bytes(None, None, key) + self._mac_len = mac_len + self._msg_len = msg_len + self._assoc_len = assoc_len + self._cipher_params = cipher_params + + self._mac_tag = None # Cache for MAC tag + + if self.block_size != 16: + raise ValueError( + "CCM mode is only available for ciphers that operate on 128 bits blocks", + ) + + # MAC tag length (Tlen) + if mac_len not in (4, 6, 8, 10, 12, 14, 16): + raise ValueError( + "Parameter 'mac_len' must be even and in the range 4..16 (not %d)" % mac_len, + ) + + # Nonce value + if not (7 <= len(nonce) <= 13): + raise ValueError( + "Length of parameter 'nonce' must be in the range 7..13 bytes", + ) + + # Message length (if known already) + q = 15 - len(nonce) # length of Q, the encoded message length + if msg_len and len(long_to_bytes(msg_len)) > q: + raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(nonce)) + + # Create MAC object (the tag will be the last block + # bytes worth of ciphertext) + self._mac = self._factory.new( + key, + factory.MODE_CBC, + iv=b"\x00" * 16, + **cipher_params, + ) + self._mac_status = MacStatus.NOT_STARTED + self._t = None + + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + # Cumulative lengths + self._cumul_assoc_len = 0 + self._cumul_msg_len = 0 + + # Cache for unaligned associated data/plaintext. + # This is a list with byte strings, but when the MAC starts, + # it will become a binary string no longer than the block size. + self._cache = [] + + # Start CTR cipher, by formatting the counter (A.3) + self._cipher = self._factory.new( + key, + self._factory.MODE_CTR, + nonce=struct.pack("B", q - 1) + self.nonce, + **cipher_params, + ) + + # S_0, step 6 in 6.1 for j=0 + self._s_0 = self._cipher.encrypt(b"\x00" * 16) + + # Try to start the MAC + if None not in (assoc_len, msg_len): + self._start_mac() + + def _start_mac(self): + assert self._mac_status == MacStatus.NOT_STARTED + assert None not in (self._assoc_len, self._msg_len) + assert isinstance(self._cache, list) + + # Formatting control information and nonce (A.2.1) + q = 15 - len(self.nonce) # length of Q, the encoded message length (2..8) + flags = (self._assoc_len > 0) << 6 + flags |= ((self._mac_len - 2) // 2) << 3 + flags |= q - 1 + b_0 = struct.pack("B", flags) + self.nonce + long_to_bytes(self._msg_len, q) + + # Formatting associated data (A.2.2) + # Encoded 'a' is concatenated with the associated data 'A' + assoc_len_encoded = b"" + if self._assoc_len > 0: + if self._assoc_len < (2**16 - 2**8): + enc_size = 2 + elif self._assoc_len < (2**32): + assoc_len_encoded = b"\xff\xfe" + enc_size = 4 + else: + assoc_len_encoded = b"\xff\xff" + enc_size = 8 + assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size) + + # b_0 and assoc_len_encoded must be processed first + self._cache.insert(0, b_0) + self._cache.insert(1, assoc_len_encoded) + + # Process all the data cached so far + first_data_to_mac = b"".join(self._cache) + self._cache = b"" + self._mac_status = MacStatus.PROCESSING_AUTH_DATA + self._update(first_data_to_mac) + + def _pad_cache_and_update(self): + assert self._mac_status != MacStatus.NOT_STARTED + assert len(self._cache) < self.block_size + + # Associated data is concatenated with the least number + # of zero bytes (possibly none) to reach alignment to + # the 16 byte boundary (A.2.3) + len_cache = len(self._cache) + if len_cache > 0: + self._update(b"\x00" * (self.block_size - len_cache)) + + def update(self, assoc_data): + """Protect associated data + + If there is any associated data, the caller has to invoke + this function one or more times, before using + ``decrypt`` or ``encrypt``. + + By *associated data* it is meant any data (e.g. packet headers) that + will not be encrypted and will be transmitted in the clear. + However, the receiver is still able to detect any modification to it. + In CCM, the *associated data* is also called + *additional authenticated data* (AAD). + + If there is no associated data, this method must not be called. + + The caller may split associated data in segments of any size, and + invoke this method multiple times, each time with the next segment. + + :Parameters: + assoc_data : bytes/bytearray/memoryview + A piece of associated data. There are no restrictions on its size. + """ + + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) + + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + self._cumul_assoc_len += len(assoc_data) + if self._assoc_len is not None and self._cumul_assoc_len > self._assoc_len: + raise ValueError("Associated data is too long") + + self._update(assoc_data) + return self + + def _update(self, assoc_data_pt=b""): + """Update the MAC with associated data or plaintext + (without FSM checks)""" + + # If MAC has not started yet, we just park the data into a list. + # If the data is mutable, we create a copy and store that instead. + if self._mac_status == MacStatus.NOT_STARTED: + if is_writeable_buffer(assoc_data_pt): + assoc_data_pt = _copy_bytes(None, None, assoc_data_pt) + self._cache.append(assoc_data_pt) + return + + assert len(self._cache) < self.block_size + + if len(self._cache) > 0: + filler = min( + self.block_size - len(self._cache), + len(assoc_data_pt), + ) + self._cache += _copy_bytes(None, filler, assoc_data_pt) + assoc_data_pt = _copy_bytes(filler, None, assoc_data_pt) + + if len(self._cache) < self.block_size: + return + + # The cache is exactly one block + self._t = self._mac.encrypt(self._cache) + self._cache = b"" + + update_len = len(assoc_data_pt) // self.block_size * self.block_size + self._cache = _copy_bytes(update_len, None, assoc_data_pt) + if update_len > 0: + self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:] + + def encrypt(self, plaintext, output=None): + """Encrypt data with the key set at initialization. + + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. + + This method can be called only **once** if ``msg_len`` was + not passed at initialization. + + If ``msg_len`` was given, the data to encrypt can be broken + up in two or more pieces and `encrypt` can be called + multiple times. + + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is equivalent to: + + >>> c.encrypt(a+b) + + This function does not add any padding to the plaintext. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext as ``bytes``. + Otherwise, ``None``. + """ + + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) + self._next = ["encrypt", "digest"] + + # No more associated data allowed from now + if self._assoc_len is None: + assert isinstance(self._cache, list) + self._assoc_len = sum([len(x) for x in self._cache]) + if self._msg_len is not None: + self._start_mac() + else: + if self._cumul_assoc_len < self._assoc_len: + raise ValueError("Associated data is too short") + + # Only once piece of plaintext accepted if message length was + # not declared in advance + if self._msg_len is None: + q = 15 - len(self.nonce) + if len(long_to_bytes(len(plaintext))) > q: + raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(self.nonce)) + + self._msg_len = len(plaintext) + self._start_mac() + self._next = ["digest"] + + self._cumul_msg_len += len(plaintext) + if self._cumul_msg_len > self._msg_len: + msg = "Message longer than declared for (%u bytes vs %u bytes" % ( + self._cumul_msg_len, + self._msg_len, + ) + raise CCMMessageTooLongError(msg) + + if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: + # Associated data is concatenated with the least number + # of zero bytes (possibly none) to reach alignment to + # the 16 byte boundary (A.2.3) + self._pad_cache_and_update() + self._mac_status = MacStatus.PROCESSING_PLAINTEXT + + self._update(plaintext) + return self._cipher.encrypt(plaintext, output=output) + + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key set at initialization. + + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. + + This method can be called only **once** if ``msg_len`` was + not passed at initialization. + + If ``msg_len`` was given, the data to decrypt can be + broken up in two or more pieces and `decrypt` can be + called multiple times. + + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is equivalent to: + + >>> c.decrypt(a+b) + + This function does not remove any padding from the plaintext. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + self._next = ["decrypt", "verify"] + + # No more associated data allowed from now + if self._assoc_len is None: + assert isinstance(self._cache, list) + self._assoc_len = sum([len(x) for x in self._cache]) + if self._msg_len is not None: + self._start_mac() + else: + if self._cumul_assoc_len < self._assoc_len: + raise ValueError("Associated data is too short") + + # Only once piece of ciphertext accepted if message length was + # not declared in advance + if self._msg_len is None: + q = 15 - len(self.nonce) + if len(long_to_bytes(len(ciphertext))) > q: + raise CCMMessageTooLongError("Message too long for a %u-byte nonce" % len(self.nonce)) + + self._msg_len = len(ciphertext) + self._start_mac() + self._next = ["verify"] + + self._cumul_msg_len += len(ciphertext) + if self._cumul_msg_len > self._msg_len: + msg = "Message longer than declared for (%u bytes vs %u bytes" % ( + self._cumul_msg_len, + self._msg_len, + ) + raise CCMMessageTooLongError(msg) + + if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: + # Associated data is concatenated with the least number + # of zero bytes (possibly none) to reach alignment to + # the 16 byte boundary (A.2.3) + self._pad_cache_and_update() + self._mac_status = MacStatus.PROCESSING_PLAINTEXT + + # Encrypt is equivalent to decrypt with the CTR mode + plaintext = self._cipher.encrypt(ciphertext, output=output) + if output is None: + self._update(plaintext) + else: + self._update(output) + return plaintext + + def digest(self): + """Compute the *binary* MAC tag. + + The caller invokes this function at the very end. + + This method returns the MAC that shall be sent to the receiver, + together with the ciphertext. + + :Return: the MAC, as a byte string. + """ + + if "digest" not in self._next: + raise TypeError( + "digest() cannot be called when decrypting or validating a message", + ) + self._next = ["digest"] + return self._digest() + + def _digest(self): + if self._mac_tag: + return self._mac_tag + + if self._assoc_len is None: + assert isinstance(self._cache, list) + self._assoc_len = sum([len(x) for x in self._cache]) + if self._msg_len is not None: + self._start_mac() + else: + if self._cumul_assoc_len < self._assoc_len: + raise ValueError("Associated data is too short") + + if self._msg_len is None: + self._msg_len = 0 + self._start_mac() + + if self._cumul_msg_len != self._msg_len: + raise ValueError("Message is too short") + + # Both associated data and payload are concatenated with the least + # number of zero bytes (possibly none) that align it to the + # 16 byte boundary (A.2.2 and A.2.3) + self._pad_cache_and_update() + + # Step 8 in 6.1 (T xor MSB_Tlen(S_0)) + self._mac_tag = strxor(self._t, self._s_0)[: self._mac_len] + + return self._mac_tag + + def hexdigest(self): + """Compute the *printable* MAC tag. + + This method is like `digest`. + + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. + + The caller invokes this function at the very end. + + This method checks if the decrypted message is indeed valid + (that is, if the key is correct) and it has not been + tampered with while in transit. + + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ["verify"] + + self._digest() + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. + + This method is like `verify`. + + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + self.verify(unhexlify(hex_mac_tag)) + + def encrypt_and_digest(self, plaintext, output=None): + """Perform encrypt() and digest() in one step. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + a tuple with two items: + + - the ciphertext, as ``bytes`` + - the MAC tag, as ``bytes`` + + The first item becomes ``None`` when the ``output`` parameter + specified a location for the result. + """ + + return self.encrypt(plaintext, output=output), self.digest() + + def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): + """Perform decrypt() and verify() in one step. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` + parameter specified a location for the result. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - plaintext = self.decrypt(ciphertext, output=output) - self.verify(received_mac_tag) - return plaintext + plaintext = self.decrypt(ciphertext, output=output) + self.verify(received_mac_tag) + return plaintext def _create_ccm_cipher(factory, **kwargs): - """Create a new block cipher, configured in CCM mode. - - :Parameters: - factory : module - A symmetric cipher module from `Cryptodome.Cipher` (like - `Cryptodome.Cipher.AES`). - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - - Its length must be in the range ``[7..13]``. - 11 or 12 bytes are reasonable values in general. Bear in - mind that with CCM there is a trade-off between nonce length and - maximum message size. - - If not specified, a 11 byte long random string is used. - - mac_len : integer - Length of the MAC, in bytes. It must be even and in - the range ``[4..16]``. The default is 16. - - msg_len : integer - Length of the message to (de)cipher. - If not specified, ``encrypt`` or ``decrypt`` may only be called once. - - assoc_len : integer - Length of the associated data. - If not specified, all data is internally buffered. - """ - - try: - key = key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter: " + str(e)) - - nonce = kwargs.pop("nonce", None) # N - if nonce is None: - nonce = get_random_bytes(11) - mac_len = kwargs.pop("mac_len", factory.block_size) - msg_len = kwargs.pop("msg_len", None) # p - assoc_len = kwargs.pop("assoc_len", None) # a - cipher_params = dict(kwargs) - - return CcmMode(factory, key, nonce, mac_len, msg_len, - assoc_len, cipher_params) + """Create a new block cipher, configured in CCM mode. + + :Parameters: + factory : module + A symmetric cipher module from `Cryptodome.Cipher` (like + `Cryptodome.Cipher.AES`). + + :Keywords: + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. + + nonce : bytes/bytearray/memoryview + A value that must never be reused for any other encryption. + + Its length must be in the range ``[7..13]``. + 11 or 12 bytes are reasonable values in general. Bear in + mind that with CCM there is a trade-off between nonce length and + maximum message size. + + If not specified, a 11 byte long random string is used. + + mac_len : integer + Length of the MAC, in bytes. It must be even and in + the range ``[4..16]``. The default is 16. + + msg_len : integer + Length of the message to (de)cipher. + If not specified, ``encrypt`` or ``decrypt`` may only be called once. + + assoc_len : integer + Length of the associated data. + If not specified, all data is internally buffered. + """ + + try: + key = key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter: " + str(e)) + + nonce = kwargs.pop("nonce", None) # N + if nonce is None: + nonce = get_random_bytes(11) + mac_len = kwargs.pop("mac_len", factory.block_size) + msg_len = kwargs.pop("msg_len", None) # p + assoc_len = kwargs.pop("assoc_len", None) # a + cipher_params = dict(kwargs) + + return CcmMode( + factory, + key, + nonce, + mac_len, + msg_len, + assoc_len, + cipher_params, + ) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ccm.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ccm.pyi index 98af96a4..147fa6fd 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ccm.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ccm.pyi @@ -3,50 +3,45 @@ from typing import Union, overload, Dict, Tuple, Optional Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['CcmMode'] - +__all__ = ["CcmMode"] class CCMMessageTooLongError(ValueError): - pass - + pass class CcmMode(object): - block_size: int - nonce: bytes - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - mac_len: int, - msg_len: Optional[int], - assoc_len: Optional[int], - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> CcmMode: ... - - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... + block_size: int + nonce: bytes + + def __init__( + self, + factory: ModuleType, + key: Buffer, + nonce: Buffer, + mac_len: int, + msg_len: Optional[int], + assoc_len: Optional[int], + cipher_params: Dict, + ) -> None: ... + def update(self, assoc_data: Buffer) -> CcmMode: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer, output: Buffer) -> Tuple[None, bytes]: ... + def decrypt_and_verify( + self, + ciphertext: Buffer, + received_mac_tag: Buffer, + output: Optional[Union[bytearray, memoryview]] = ..., + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cfb.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cfb.py index 1b1b6c31..f1863cde 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cfb.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cfb.py @@ -24,17 +24,25 @@ Counter Feedback (CFB) mode. """ -__all__ = ['CfbMode'] +__all__ = ["CfbMode"] from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes -raw_cfb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_cfb",""" +raw_cfb_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_cfb", + """ int CFB_start_operation(void *cipher, const uint8_t iv[], size_t iv_len, @@ -48,246 +56,257 @@ const uint8_t *in, uint8_t *out, size_t data_len); - int CFB_stop_operation(void *state);""" - ) + int CFB_stop_operation(void *state);""", +) class CfbMode(object): - """*Cipher FeedBack (CFB)*. + """*Cipher FeedBack (CFB)*. - This mode is similar to CFB, but it transforms - the underlying block cipher into a stream cipher. + This mode is similar to CFB, but it transforms + the underlying block cipher into a stream cipher. - Plaintext and ciphertext are processed in *segments* - of **s** bits. The mode is therefore sometimes - labelled **s**-bit CFB. + Plaintext and ciphertext are processed in *segments* + of **s** bits. The mode is therefore sometimes + labelled **s**-bit CFB. - An Initialization Vector (*IV*) is required. + An Initialization Vector (*IV*) is required. - See `NIST SP800-38A`_ , Section 6.3. + See `NIST SP800-38A`_ , Section 6.3. - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, block_cipher, iv, segment_size): - """Create a new block cipher, configured in CFB mode. + def __init__(self, block_cipher, iv, segment_size): + """Create a new block cipher, configured in CFB mode. - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. - iv : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - It is as long as the cipher block. + iv : bytes/bytearray/memoryview + The initialization vector to use for encryption or decryption. + It is as long as the cipher block. - **The IV must be unpredictable**. Ideally it is picked randomly. + **The IV must be unpredictable**. Ideally it is picked randomly. - Reusing the *IV* for encryptions performed with the same key - compromises confidentiality. + Reusing the *IV* for encryptions performed with the same key + compromises confidentiality. - segment_size : integer - The number of bytes the plaintext and ciphertext are segmented in. - """ + segment_size : integer + The number of bytes the plaintext and ciphertext are segmented in. + """ - self._state = VoidPointer() - result = raw_cfb_lib.CFB_start_operation(block_cipher.get(), - c_uint8_ptr(iv), - c_size_t(len(iv)), - c_size_t(segment_size), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the CFB mode" % result) + self._state = VoidPointer() + result = raw_cfb_lib.CFB_start_operation( + block_cipher.get(), + c_uint8_ptr(iv), + c_size_t(len(iv)), + c_size_t(segment_size), + self._state.address_of(), + ) + if result: + raise ValueError("Error %d while instantiating the CFB mode" % result) - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_cfb_lib.CFB_stop_operation) + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + raw_cfb_lib.CFB_stop_operation, + ) - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + block_cipher.release() - self.block_size = len(iv) - """The block size of the underlying cipher, in bytes.""" + self.block_size = len(iv) + """The block size of the underlying cipher, in bytes.""" - self.iv = _copy_bytes(None, None, iv) - """The Initialization Vector originally used to create the object. + self.iv = _copy_bytes(None, None, iv) + """The Initialization Vector originally used to create the object. The value does not change.""" - self.IV = self.iv - """Alias for `iv`""" + self.IV = self.iv + """Alias for `iv`""" - self._next = ["encrypt", "decrypt"] + self._next = ["encrypt", "decrypt"] - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.encrypt(a) + c.encrypt(b) + >>> c.encrypt(a) + c.encrypt(b) - is equivalent to: + is equivalent to: - >>> c.encrypt(a+b) + >>> c.encrypt(a+b) - This function does not add any padding to the plaintext. + This function does not add any padding to the plaintext. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = ["encrypt"] + if "encrypt" not in self._next: + raise TypeError("encrypt() cannot be called after decrypt()") + self._next = ["encrypt"] - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) - result = raw_cfb_lib.CFB_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting in CFB mode" % result) + result = raw_cfb_lib.CFB_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting in CFB mode" % result) - if output is None: - return get_raw_buffer(ciphertext) - else: - return None + if output is None: + return get_raw_buffer(ciphertext) + else: + return None - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.decrypt(a) + c.decrypt(b) + >>> c.decrypt(a) + c.decrypt(b) - is equivalent to: + is equivalent to: - >>> c.decrypt(a+b) + >>> c.decrypt(a+b) - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "decrypt" not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = ["decrypt"] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_cfb_lib.CFB_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - raise ValueError("Error %d while decrypting in CFB mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + if "decrypt" not in self._next: + raise TypeError("decrypt() cannot be called after encrypt()") + self._next = ["decrypt"] + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_cfb_lib.CFB_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + raise ValueError("Error %d while decrypting in CFB mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_cfb_cipher(factory, **kwargs): - """Instantiate a cipher object that performs CFB encryption/decryption. + """Instantiate a cipher object that performs CFB encryption/decryption. - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. - :Keywords: - iv : bytes/bytearray/memoryview - The IV to use for CFB. + :Keywords: + iv : bytes/bytearray/memoryview + The IV to use for CFB. - IV : bytes/bytearray/memoryview - Alias for ``iv``. + IV : bytes/bytearray/memoryview + Alias for ``iv``. - segment_size : integer - The number of bit the plaintext and ciphertext are segmented in. - If not present, the default is 8. + segment_size : integer + The number of bit the plaintext and ciphertext are segmented in. + If not present, the default is 8. - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ - cipher_state = factory._create_base_cipher(kwargs) + cipher_state = factory._create_base_cipher(kwargs) - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) + iv = kwargs.pop("IV", None) + IV = kwargs.pop("iv", None) - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV + if (None, None) == (iv, IV): + iv = get_random_bytes(factory.block_size) + if iv is not None: + if IV is not None: + raise TypeError("You must either use 'iv' or 'IV', not both") + else: + iv = IV - if len(iv) != factory.block_size: - raise ValueError("Incorrect IV length (it must be %d bytes long)" % - factory.block_size) + if len(iv) != factory.block_size: + raise ValueError( + "Incorrect IV length (it must be %d bytes long)" % factory.block_size, + ) - segment_size_bytes, rem = divmod(kwargs.pop("segment_size", 8), 8) - if segment_size_bytes == 0 or rem != 0: - raise ValueError("'segment_size' must be positive and multiple of 8 bits") + segment_size_bytes, rem = divmod(kwargs.pop("segment_size", 8), 8) + if segment_size_bytes == 0 or rem != 0: + raise ValueError("'segment_size' must be positive and multiple of 8 bits") - if kwargs: - raise TypeError("Unknown parameters for CFB: %s" % str(kwargs)) - return CfbMode(cipher_state, iv, segment_size_bytes) + if kwargs: + raise TypeError("Unknown parameters for CFB: %s" % str(kwargs)) + return CfbMode(cipher_state, iv, segment_size_bytes) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cfb.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cfb.pyi index 228e4645..623ea4c5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cfb.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_cfb.pyi @@ -4,23 +4,19 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['CfbMode'] - +__all__ = ["CfbMode"] class CfbMode(object): - block_size: int - iv: Buffer - IV: Buffer - - def __init__(self, - block_cipher: SmartPointer, - iv: Buffer, - segment_size: int) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + block_size: int + iv: Buffer + IV: Buffer + + def __init__(self, block_cipher: SmartPointer, iv: Buffer, segment_size: int) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ctr.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ctr.py index 9ce357fc..20c64b5c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ctr.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ctr.py @@ -24,20 +24,28 @@ Counter (CTR) mode. """ -__all__ = ['CtrMode'] +__all__ = ["CtrMode"] import struct -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes from Cryptodome.Util.py3compat import _copy_bytes, is_native_int from Cryptodome.Util.number import long_to_bytes -raw_ctr_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ctr", """ +raw_ctr_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_ctr", + """ int CTR_start_operation(void *cipher, uint8_t initialCounterBlock[], size_t initialCounterBlock_len, @@ -53,341 +61,377 @@ const uint8_t *in, uint8_t *out, size_t data_len); - int CTR_stop_operation(void *ctrState);""" - ) + int CTR_stop_operation(void *ctrState);""", +) class CtrMode(object): - """*CounTeR (CTR)* mode. + """*CounTeR (CTR)* mode. + + This mode is very similar to ECB, in that + encryption of one block is done independently of all other blocks. + + Unlike ECB, the block *position* contributes to the encryption + and no information leaks about symbol frequency. + + Each message block is associated to a *counter* which + must be unique across all messages that get encrypted + with the same key (not just within the same message). + The counter is as big as the block size. + + Counters can be generated in several ways. The most + straightword one is to choose an *initial counter block* + (which can be made public, similarly to the *IV* for the + other modes) and increment its lowest **m** bits by one + (modulo *2^m*) for each block. In most cases, **m** is + chosen to be half the block size. + + See `NIST SP800-38A`_, Section 6.5 (for the mode) and + Appendix B (for how to manage the *initial counter block*). - This mode is very similar to ECB, in that - encryption of one block is done independently of all other blocks. - - Unlike ECB, the block *position* contributes to the encryption - and no information leaks about symbol frequency. - - Each message block is associated to a *counter* which - must be unique across all messages that get encrypted - with the same key (not just within the same message). - The counter is as big as the block size. - - Counters can be generated in several ways. The most - straightword one is to choose an *initial counter block* - (which can be made public, similarly to the *IV* for the - other modes) and increment its lowest **m** bits by one - (modulo *2^m*) for each block. In most cases, **m** is - chosen to be half the block size. - - See `NIST SP800-38A`_, Section 6.5 (for the mode) and - Appendix B (for how to manage the *initial counter block*). - - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - :undocumented: __init__ - """ - - def __init__(self, block_cipher, initial_counter_block, - prefix_len, counter_len, little_endian): - """Create a new block cipher, configured in CTR mode. - - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. - - initial_counter_block : bytes/bytearray/memoryview - The initial plaintext to use to generate the key stream. - - It is as large as the cipher block, and it embeds - the initial value of the counter. - - This value must not be reused. - It shall contain a nonce or a random component. - Reusing the *initial counter block* for encryptions - performed with the same key compromises confidentiality. - - prefix_len : integer - The amount of bytes at the beginning of the counter block - that never change. - - counter_len : integer - The length in bytes of the counter embedded in the counter - block. - - little_endian : boolean - True if the counter in the counter block is an integer encoded - in little endian mode. If False, it is big endian. - """ - - if len(initial_counter_block) == prefix_len + counter_len: - self.nonce = _copy_bytes(None, prefix_len, initial_counter_block) - """Nonce; not available if there is a fixed suffix""" - - self._state = VoidPointer() - result = raw_ctr_lib.CTR_start_operation(block_cipher.get(), - c_uint8_ptr(initial_counter_block), - c_size_t(len(initial_counter_block)), - c_size_t(prefix_len), - counter_len, - little_endian, - self._state.address_of()) - if result: - raise ValueError("Error %X while instantiating the CTR mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_ctr_lib.CTR_stop_operation) - - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() - - self.block_size = len(initial_counter_block) - """The block size of the underlying cipher, in bytes.""" - - self._next = ["encrypt", "decrypt"] - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "encrypt" not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = ["encrypt"] - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ctr_lib.CTR_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - if result == 0x60002: - raise OverflowError("The counter has wrapped around in" - " CTR mode") - raise ValueError("Error %X while encrypting in CTR mode" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = ["decrypt"] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ctr_lib.CTR_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - if result == 0x60002: - raise OverflowError("The counter has wrapped around in" - " CTR mode") - raise ValueError("Error %X while decrypting in CTR mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + + :undocumented: __init__ + """ + + def __init__( + self, + block_cipher, + initial_counter_block, + prefix_len, + counter_len, + little_endian, + ): + """Create a new block cipher, configured in CTR mode. + + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. + + initial_counter_block : bytes/bytearray/memoryview + The initial plaintext to use to generate the key stream. + + It is as large as the cipher block, and it embeds + the initial value of the counter. + + This value must not be reused. + It shall contain a nonce or a random component. + Reusing the *initial counter block* for encryptions + performed with the same key compromises confidentiality. + + prefix_len : integer + The amount of bytes at the beginning of the counter block + that never change. + + counter_len : integer + The length in bytes of the counter embedded in the counter + block. + + little_endian : boolean + True if the counter in the counter block is an integer encoded + in little endian mode. If False, it is big endian. + """ + + if len(initial_counter_block) == prefix_len + counter_len: + self.nonce = _copy_bytes(None, prefix_len, initial_counter_block) + """Nonce; not available if there is a fixed suffix""" + + self._state = VoidPointer() + result = raw_ctr_lib.CTR_start_operation( + block_cipher.get(), + c_uint8_ptr(initial_counter_block), + c_size_t(len(initial_counter_block)), + c_size_t(prefix_len), + counter_len, + little_endian, + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %X while instantiating the CTR mode" % result, + ) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + raw_ctr_lib.CTR_stop_operation, + ) + + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + block_cipher.release() + + self.block_size = len(initial_counter_block) + """The block size of the underlying cipher, in bytes.""" + + self._next = ["encrypt", "decrypt"] + + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. + + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. + + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is equivalent to: + + >>> c.encrypt(a+b) + + This function does not add any padding to the plaintext. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "encrypt" not in self._next: + raise TypeError("encrypt() cannot be called after decrypt()") + self._next = ["encrypt"] + + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ctr_lib.CTR_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + if result == 0x60002: + raise OverflowError( + "The counter has wrapped around in CTR mode", + ) + raise ValueError("Error %X while encrypting in CTR mode" % result) + + if output is None: + return get_raw_buffer(ciphertext) + else: + return None + + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. + + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. + + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is equivalent to: + + >>> c.decrypt(a+b) + + This function does not remove any padding from the plaintext. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError("decrypt() cannot be called after encrypt()") + self._next = ["decrypt"] + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ctr_lib.CTR_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + if result == 0x60002: + raise OverflowError( + "The counter has wrapped around in CTR mode", + ) + raise ValueError("Error %X while decrypting in CTR mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_ctr_cipher(factory, **kwargs): - """Instantiate a cipher object that performs CTR encryption/decryption. - - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. - - :Keywords: - nonce : bytes/bytearray/memoryview - The fixed part at the beginning of the counter block - the rest is - the counter number that gets increased when processing the next block. - The nonce must be such that no two messages are encrypted under the - same key and the same nonce. - - The nonce must be shorter than the block size (it can have - zero length; the counter is then as long as the block). - - If this parameter is not present, a random nonce will be created with - length equal to half the block size. No random nonce shorter than - 64 bits will be created though - you must really think through all - security consequences of using such a short block size. - - initial_value : posive integer or bytes/bytearray/memoryview - The initial value for the counter. If not present, the cipher will - start counting from 0. The value is incremented by one for each block. - The counter number is encoded in big endian mode. - - counter : object - Instance of ``Cryptodome.Util.Counter``, which allows full customization - of the counter block. This parameter is incompatible to both ``nonce`` - and ``initial_value``. - - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ - - cipher_state = factory._create_base_cipher(kwargs) - - counter = kwargs.pop("counter", None) - nonce = kwargs.pop("nonce", None) - initial_value = kwargs.pop("initial_value", None) - if kwargs: - raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs)) - - if counter is not None and (nonce, initial_value) != (None, None): - raise TypeError("'counter' and 'nonce'/'initial_value'" - " are mutually exclusive") - - if counter is None: - # Cryptodome.Util.Counter is not used - if nonce is None: - if factory.block_size < 16: - raise TypeError("Impossible to create a safe nonce for short" - " block sizes") - nonce = get_random_bytes(factory.block_size // 2) - else: - if len(nonce) >= factory.block_size: - raise ValueError("Nonce is too long") - - # What is not nonce is counter - counter_len = factory.block_size - len(nonce) - - if initial_value is None: - initial_value = 0 - - if is_native_int(initial_value): - if (1 << (counter_len * 8)) - 1 < initial_value: - raise ValueError("Initial counter value is too large") - initial_counter_block = nonce + long_to_bytes(initial_value, counter_len) - else: - if len(initial_value) != counter_len: - raise ValueError("Incorrect length for counter byte string (%d bytes, expected %d)" % - (len(initial_value), counter_len)) - initial_counter_block = nonce + initial_value - - return CtrMode(cipher_state, - initial_counter_block, - len(nonce), # prefix - counter_len, - False) # little_endian - - # Cryptodome.Util.Counter is used - - # 'counter' used to be a callable object, but now it is - # just a dictionary for backward compatibility. - _counter = dict(counter) - try: - counter_len = _counter.pop("counter_len") - prefix = _counter.pop("prefix") - suffix = _counter.pop("suffix") - initial_value = _counter.pop("initial_value") - little_endian = _counter.pop("little_endian") - except KeyError: - raise TypeError("Incorrect counter object" - " (use Cryptodome.Util.Counter.new)") - - # Compute initial counter block - words = [] - while initial_value > 0: - words.append(struct.pack('B', initial_value & 255)) - initial_value >>= 8 - words += [b'\x00'] * max(0, counter_len - len(words)) - if not little_endian: - words.reverse() - initial_counter_block = prefix + b"".join(words) + suffix - - if len(initial_counter_block) != factory.block_size: - raise ValueError("Size of the counter block (%d bytes) must match" - " block size (%d)" % (len(initial_counter_block), - factory.block_size)) - - return CtrMode(cipher_state, initial_counter_block, - len(prefix), counter_len, little_endian) + """Instantiate a cipher object that performs CTR encryption/decryption. + + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. + + :Keywords: + nonce : bytes/bytearray/memoryview + The fixed part at the beginning of the counter block - the rest is + the counter number that gets increased when processing the next block. + The nonce must be such that no two messages are encrypted under the + same key and the same nonce. + + The nonce must be shorter than the block size (it can have + zero length; the counter is then as long as the block). + + If this parameter is not present, a random nonce will be created with + length equal to half the block size. No random nonce shorter than + 64 bits will be created though - you must really think through all + security consequences of using such a short block size. + + initial_value : posive integer or bytes/bytearray/memoryview + The initial value for the counter. If not present, the cipher will + start counting from 0. The value is incremented by one for each block. + The counter number is encoded in big endian mode. + + counter : object + Instance of ``Cryptodome.Util.Counter``, which allows full customization + of the counter block. This parameter is incompatible to both ``nonce`` + and ``initial_value``. + + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ + + cipher_state = factory._create_base_cipher(kwargs) + + counter = kwargs.pop("counter", None) + nonce = kwargs.pop("nonce", None) + initial_value = kwargs.pop("initial_value", None) + if kwargs: + raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs)) + + if counter is not None and (nonce, initial_value) != (None, None): + raise TypeError( + "'counter' and 'nonce'/'initial_value' are mutually exclusive", + ) + + if counter is None: + # Cryptodome.Util.Counter is not used + if nonce is None: + if factory.block_size < 16: + raise TypeError( + "Impossible to create a safe nonce for short block sizes", + ) + nonce = get_random_bytes(factory.block_size // 2) + else: + if len(nonce) >= factory.block_size: + raise ValueError("Nonce is too long") + + # What is not nonce is counter + counter_len = factory.block_size - len(nonce) + + if initial_value is None: + initial_value = 0 + + if is_native_int(initial_value): + if (1 << (counter_len * 8)) - 1 < initial_value: + raise ValueError("Initial counter value is too large") + initial_counter_block = nonce + long_to_bytes(initial_value, counter_len) + else: + if len(initial_value) != counter_len: + raise ValueError( + "Incorrect length for counter byte string (%d bytes, expected %d)" + % (len(initial_value), counter_len), + ) + initial_counter_block = nonce + initial_value + + return CtrMode( + cipher_state, + initial_counter_block, + len(nonce), # prefix + counter_len, + False, + ) # little_endian + + # Cryptodome.Util.Counter is used + + # 'counter' used to be a callable object, but now it is + # just a dictionary for backward compatibility. + _counter = dict(counter) + try: + counter_len = _counter.pop("counter_len") + prefix = _counter.pop("prefix") + suffix = _counter.pop("suffix") + initial_value = _counter.pop("initial_value") + little_endian = _counter.pop("little_endian") + except KeyError: + raise TypeError( + "Incorrect counter object (use Cryptodome.Util.Counter.new)", + ) + + # Compute initial counter block + words = [] + while initial_value > 0: + words.append(struct.pack("B", initial_value & 255)) + initial_value >>= 8 + words += [b"\x00"] * max(0, counter_len - len(words)) + if not little_endian: + words.reverse() + initial_counter_block = prefix + b"".join(words) + suffix + + if len(initial_counter_block) != factory.block_size: + raise ValueError( + "Size of the counter block (%d bytes) must match" + " block size (%d)" + % ( + len(initial_counter_block), + factory.block_size, + ), + ) + + return CtrMode( + cipher_state, + initial_counter_block, + len(prefix), + counter_len, + little_endian, + ) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ctr.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ctr.pyi index a68a8909..e5270bce 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ctr.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ctr.pyi @@ -4,24 +4,25 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['CtrMode'] +__all__ = ["CtrMode"] class CtrMode(object): - block_size: int - nonce: bytes - - def __init__(self, - block_cipher: SmartPointer, - initial_counter_block: Buffer, - prefix_len: int, - counter_len: int, - little_endian: bool) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + block_size: int + nonce: bytes + def __init__( + self, + block_cipher: SmartPointer, + initial_counter_block: Buffer, + prefix_len: int, + counter_len: int, + little_endian: bool, + ) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_eax.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_eax.py index 44ef21f5..8126cc3f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_eax.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_eax.py @@ -32,377 +32,397 @@ EAX mode. """ -__all__ = ['EaxMode'] +__all__ = ["EaxMode"] import struct from binascii import unhexlify -from Cryptodome.Util.py3compat import byte_string, bord, _copy_bytes +from Cryptodome.Util.py3compat import bord, _copy_bytes from Cryptodome.Util._raw_api import is_buffer from Cryptodome.Util.strxor import strxor -from Cryptodome.Util.number import long_to_bytes, bytes_to_long +from Cryptodome.Util.number import bytes_to_long from Cryptodome.Hash import CMAC, BLAKE2s from Cryptodome.Random import get_random_bytes class EaxMode(object): - """*EAX* mode. + """*EAX* mode. + + This is an Authenticated Encryption with Associated Data + (`AEAD`_) mode. It provides both confidentiality and authenticity. + + The header of the message may be left in the clear, if needed, + and it will still be subject to authentication. + + The decryption step tells the receiver if the message comes + from a source that really knowns the secret key. + Additionally, decryption detects if any part of the message - + including the header - has been modified or corrupted. + + This mode requires a *nonce*. + + This mode is only available for ciphers that operate on 64 or + 128 bits blocks. + + There are no official standards defining EAX. + The implementation is based on `a proposal`__ that + was presented to NIST. + + .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html + .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf + + :undocumented: __init__ + """ + + def __init__(self, factory, key, nonce, mac_len, cipher_params): + """EAX cipher mode""" + + self.block_size = factory.block_size + """The block size of the underlying cipher, in bytes.""" + + self.nonce = _copy_bytes(None, None, nonce) + """The nonce originally used to create the object.""" + + self._mac_len = mac_len + self._mac_tag = None # Cache for MAC tag - This is an Authenticated Encryption with Associated Data - (`AEAD`_) mode. It provides both confidentiality and authenticity. + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + # MAC tag length + if not (2 <= self._mac_len <= self.block_size): + raise ValueError( + "'mac_len' must be at least 2 and not larger than %d" % self.block_size, + ) + + # Nonce cannot be empty and must be a byte string + if len(self.nonce) == 0: + raise ValueError("Nonce cannot be empty in EAX mode") + if not is_buffer(nonce): + raise TypeError("nonce must be bytes, bytearray or memoryview") + + self._omac = [ + CMAC.new( + key, + b"\x00" * (self.block_size - 1) + struct.pack("B", i), + ciphermod=factory, + cipher_params=cipher_params, + ) + for i in range(0, 3) + ] + + # Compute MAC of nonce + self._omac[0].update(self.nonce) + self._signer = self._omac[1] + + # MAC of the nonce is also the initial counter for CTR encryption + counter_int = bytes_to_long(self._omac[0].digest()) + self._cipher = factory.new( + key, + factory.MODE_CTR, + initial_value=counter_int, + nonce=b"", + **cipher_params, + ) + + def update(self, assoc_data): + """Protect associated data + + If there is any associated data, the caller has to invoke + this function one or more times, before using + ``decrypt`` or ``encrypt``. + + By *associated data* it is meant any data (e.g. packet headers) that + will not be encrypted and will be transmitted in the clear. + However, the receiver is still able to detect any modification to it. + + If there is no associated data, this method must not be called. + + The caller may split associated data in segments of any size, and + invoke this method multiple times, each time with the next segment. + + :Parameters: + assoc_data : bytes/bytearray/memoryview + A piece of associated data. There are no restrictions on its size. + """ + + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) + + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + self._signer.update(assoc_data) + return self + + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. + + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. + + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is equivalent to: + + >>> c.encrypt(a+b) + + This function does not add any padding to the plaintext. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext as ``bytes``. + Otherwise, ``None``. + """ + + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) + self._next = ["encrypt", "digest"] + ct = self._cipher.encrypt(plaintext, output=output) + if output is None: + self._omac[2].update(ct) + else: + self._omac[2].update(output) + return ct + + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. + + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. + + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is equivalent to: - The header of the message may be left in the clear, if needed, - and it will still be subject to authentication. + >>> c.decrypt(a+b) - The decryption step tells the receiver if the message comes - from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - - including the header - has been modified or corrupted. + This function does not remove any padding from the plaintext. - This mode requires a *nonce*. + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext as ``bytes``. + Otherwise, ``None``. + """ + + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + self._next = ["decrypt", "verify"] + self._omac[2].update(ciphertext) + return self._cipher.decrypt(ciphertext, output=output) + + def digest(self): + """Compute the *binary* MAC tag. + + The caller invokes this function at the very end. + + This method returns the MAC that shall be sent to the receiver, + together with the ciphertext. - This mode is only available for ciphers that operate on 64 or - 128 bits blocks. + :Return: the MAC, as a byte string. + """ - There are no official standards defining EAX. - The implementation is based on `a proposal`__ that - was presented to NIST. + if "digest" not in self._next: + raise TypeError( + "digest() cannot be called when decrypting or validating a message", + ) + self._next = ["digest"] + + if not self._mac_tag: + tag = b"\x00" * self.block_size + for i in range(3): + tag = strxor(tag, self._omac[i].digest()) + self._mac_tag = tag[: self._mac_len] + + return self._mac_tag + + def hexdigest(self): + """Compute the *printable* MAC tag. + + This method is like `digest`. + + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. + + The caller invokes this function at the very end. + + This method checks if the decrypted message is indeed valid + (that is, if the key is correct) and it has not been + tampered with while in transit. + + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises MacMismatchError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ["verify"] + + if not self._mac_tag: + tag = b"\x00" * self.block_size + for i in range(3): + tag = strxor(tag, self._omac[i].digest()) + self._mac_tag = tag[: self._mac_len] + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. + + This method is like `verify`. + + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises MacMismatchError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + self.verify(unhexlify(hex_mac_tag)) + + def encrypt_and_digest(self, plaintext, output=None): + """Perform encrypt() and digest() in one step. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + a tuple with two items: - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf + - the ciphertext, as ``bytes`` + - the MAC tag, as ``bytes`` - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, mac_len, cipher_params): - """EAX cipher mode""" - - self.block_size = factory.block_size - """The block size of the underlying cipher, in bytes.""" - - self.nonce = _copy_bytes(None, None, nonce) - """The nonce originally used to create the object.""" - - self._mac_len = mac_len - self._mac_tag = None # Cache for MAC tag - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - # MAC tag length - if not (2 <= self._mac_len <= self.block_size): - raise ValueError("'mac_len' must be at least 2 and not larger than %d" - % self.block_size) - - # Nonce cannot be empty and must be a byte string - if len(self.nonce) == 0: - raise ValueError("Nonce cannot be empty in EAX mode") - if not is_buffer(nonce): - raise TypeError("nonce must be bytes, bytearray or memoryview") - - self._omac = [ - CMAC.new(key, - b'\x00' * (self.block_size - 1) + struct.pack('B', i), - ciphermod=factory, - cipher_params=cipher_params) - for i in range(0, 3) - ] - - # Compute MAC of nonce - self._omac[0].update(self.nonce) - self._signer = self._omac[1] - - # MAC of the nonce is also the initial counter for CTR encryption - counter_int = bytes_to_long(self._omac[0].digest()) - self._cipher = factory.new(key, - factory.MODE_CTR, - initial_value=counter_int, - nonce=b"", - **cipher_params) - - def update(self, assoc_data): - """Protect associated data - - If there is any associated data, the caller has to invoke - this function one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver is still able to detect any modification to it. - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. There are no restrictions on its size. - """ - - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - self._signer.update(assoc_data) - return self - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext as ``bytes``. - Otherwise, ``None``. - """ - - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - self._next = ["encrypt", "digest"] - ct = self._cipher.encrypt(plaintext, output=output) - if output is None: - self._omac[2].update(ct) - else: - self._omac[2].update(output) - return ct - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext as ``bytes``. - Otherwise, ``None``. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = ["decrypt", "verify"] - self._omac[2].update(ciphertext) - return self._cipher.decrypt(ciphertext, output=output) - - def digest(self): - """Compute the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. - - :Return: the MAC, as a byte string. - """ - - if "digest" not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = ["digest"] - - if not self._mac_tag: - tag = b'\x00' * self.block_size - for i in range(3): - tag = strxor(tag, self._omac[i].digest()) - self._mac_tag = tag[:self._mac_len] - - return self._mac_tag - - def hexdigest(self): - """Compute the *printable* MAC tag. - - This method is like `digest`. - - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. - - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises MacMismatchError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ["verify"] - - if not self._mac_tag: - tag = b'\x00' * self.block_size - for i in range(3): - tag = strxor(tag, self._omac[i].digest()) - self._mac_tag = tag[:self._mac_len] - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. - - This method is like `verify`. - - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises MacMismatchError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: - - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` - - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ - - return self.encrypt(plaintext, output=output), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): - """Perform decrypt() and verify() in one step. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises MacMismatchError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - pt = self.decrypt(ciphertext, output=output) - self.verify(received_mac_tag) - return pt + The first item becomes ``None`` when the ``output`` parameter + specified a location for the result. + """ + + return self.encrypt(plaintext, output=output), self.digest() + + def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): + """Perform decrypt() and verify() in one step. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` + parameter specified a location for the result. + :Raises MacMismatchError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + pt = self.decrypt(ciphertext, output=output) + self.verify(received_mac_tag) + return pt def _create_eax_cipher(factory, **kwargs): - """Create a new block cipher, configured in EAX mode. - - :Parameters: - factory : module - A symmetric cipher module from `Cryptodome.Cipher` (like - `Cryptodome.Cipher.AES`). - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - There are no restrictions on its length, but it is recommended to use - at least 16 bytes. - - The nonce shall never repeat for two different messages encrypted with - the same key, but it does not need to be random. - - If not specified, a 16 byte long random string is used. - - mac_len : integer - Length of the MAC, in bytes. It must be no larger than the cipher - block bytes (which is the default). - """ - - try: - key = kwargs.pop("key") - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(16) - mac_len = kwargs.pop("mac_len", factory.block_size) - except KeyError as e: - raise TypeError("Missing parameter: " + str(e)) - - return EaxMode(factory, key, nonce, mac_len, kwargs) + """Create a new block cipher, configured in EAX mode. + + :Parameters: + factory : module + A symmetric cipher module from `Cryptodome.Cipher` (like + `Cryptodome.Cipher.AES`). + + :Keywords: + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. + + nonce : bytes/bytearray/memoryview + A value that must never be reused for any other encryption. + There are no restrictions on its length, but it is recommended to use + at least 16 bytes. + + The nonce shall never repeat for two different messages encrypted with + the same key, but it does not need to be random. + + If not specified, a 16 byte long random string is used. + + mac_len : integer + Length of the MAC, in bytes. It must be no larger than the cipher + block bytes (which is the default). + """ + + try: + key = kwargs.pop("key") + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(16) + mac_len = kwargs.pop("mac_len", factory.block_size) + except KeyError as e: + raise TypeError("Missing parameter: " + str(e)) + + return EaxMode(factory, key, nonce, mac_len, kwargs) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_eax.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_eax.pyi index cbfa467e..b5129fa9 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_eax.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_eax.pyi @@ -1,45 +1,37 @@ from types import ModuleType -from typing import Any, Union, Tuple, Dict, overload, Optional +from typing import Union, Tuple, Dict, overload, Optional Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['EaxMode'] +__all__ = ["EaxMode"] class EaxMode(object): - block_size: int - nonce: bytes - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - mac_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> EaxMode: ... + block_size: int + nonce: bytes - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... + def __init__( + self, factory: ModuleType, key: Buffer, nonce: Buffer, mac_len: int, cipher_params: Dict + ) -> None: ... + def update(self, assoc_data: Buffer) -> EaxMode: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer, output: Buffer) -> Tuple[None, bytes]: ... + def decrypt_and_verify( + self, + ciphertext: Buffer, + received_mac_tag: Buffer, + output: Optional[Union[bytearray, memoryview]] = ..., + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ecb.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ecb.py index a01a16fe..bf32c165 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ecb.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ecb.py @@ -24,15 +24,22 @@ Electronic Code Book (ECB) mode. """ -__all__ = [ 'EcbMode' ] - -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, create_string_buffer, - get_raw_buffer, SmartPointer, - c_size_t, c_uint8_ptr, - is_writeable_buffer) - -raw_ecb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ecb", """ +__all__ = ["EcbMode"] + +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) + +raw_ecb_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_ecb", + """ int ECB_start_operation(void *cipher, void **pResult); int ECB_encrypt(void *ecbState, @@ -44,177 +51,188 @@ uint8_t *out, size_t data_len); int ECB_stop_operation(void *state); - """ - ) + """, +) class EcbMode(object): - """*Electronic Code Book (ECB)*. - - This is the simplest encryption mode. Each of the plaintext blocks - is directly encrypted into a ciphertext block, independently of - any other block. - - This mode is dangerous because it exposes frequency of symbols - in your plaintext. Other modes (e.g. *CBC*) should be used instead. - - See `NIST SP800-38A`_ , Section 6.1. + """*Electronic Code Book (ECB)*. + + This is the simplest encryption mode. Each of the plaintext blocks + is directly encrypted into a ciphertext block, independently of + any other block. + + This mode is dangerous because it exposes frequency of symbols + in your plaintext. Other modes (e.g. *CBC*) should be used instead. + + See `NIST SP800-38A`_ , Section 6.1. + + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + + :undocumented: __init__ + """ + + def __init__(self, block_cipher): + """Create a new block cipher, configured in ECB mode. - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. + """ + self.block_size = block_cipher.block_size - :undocumented: __init__ - """ - - def __init__(self, block_cipher): - """Create a new block cipher, configured in ECB mode. - - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. - """ - self.block_size = block_cipher.block_size - - self._state = VoidPointer() - result = raw_ecb_lib.ECB_start_operation(block_cipher.get(), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the ECB mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher - # mode - self._state = SmartPointer(self._state.get(), - raw_ecb_lib.ECB_stop_operation) - - # Memory allocated for the underlying block cipher is now owned - # by the cipher mode - block_cipher.release() - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key set at initialization. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - The length must be multiple of the cipher block length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ecb_lib.ECB_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - if result == 3: - raise ValueError("Data must be aligned to block boundary in ECB mode") - raise ValueError("Error %d while encrypting in ECB mode" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key set at initialization. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - The length must be multiple of the cipher block length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ecb_lib.ECB_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - if result == 3: - raise ValueError("Data must be aligned to block boundary in ECB mode") - raise ValueError("Error %d while decrypting in ECB mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + self._state = VoidPointer() + result = raw_ecb_lib.ECB_start_operation( + block_cipher.get(), + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %d while instantiating the ECB mode" % result, + ) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher + # mode + self._state = SmartPointer( + self._state.get(), + raw_ecb_lib.ECB_stop_operation, + ) + + # Memory allocated for the underlying block cipher is now owned + # by the cipher mode + block_cipher.release() + + def encrypt(self, plaintext, output=None): + """Encrypt data with the key set at initialization. + + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. + + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is equivalent to: + + >>> c.encrypt(a+b) + + This function does not add any padding to the plaintext. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + The length must be multiple of the cipher block length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ecb_lib.ECB_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + if result == 3: + raise ValueError("Data must be aligned to block boundary in ECB mode") + raise ValueError("Error %d while encrypting in ECB mode" % result) + + if output is None: + return get_raw_buffer(ciphertext) + else: + return None + + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key set at initialization. + + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. + + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is equivalent to: + + >>> c.decrypt(a+b) + + This function does not remove any padding from the plaintext. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + The length must be multiple of the cipher block length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ecb_lib.ECB_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + if result == 3: + raise ValueError("Data must be aligned to block boundary in ECB mode") + raise ValueError("Error %d while decrypting in ECB mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_ecb_cipher(factory, **kwargs): - """Instantiate a cipher object that performs ECB encryption/decryption. + """Instantiate a cipher object that performs ECB encryption/decryption. - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. - All keywords are passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present""" + All keywords are passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present""" - cipher_state = factory._create_base_cipher(kwargs) - cipher_state.block_size = factory.block_size - if kwargs: - raise TypeError("Unknown parameters for ECB: %s" % str(kwargs)) - return EcbMode(cipher_state) + cipher_state = factory._create_base_cipher(kwargs) + cipher_state.block_size = factory.block_size + if kwargs: + raise TypeError("Unknown parameters for ECB: %s" % str(kwargs)) + return EcbMode(cipher_state) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ecb.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ecb.pyi index 936195f9..474ccd6f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ecb.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ecb.pyi @@ -4,16 +4,15 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = [ 'EcbMode' ] +__all__ = ["EcbMode"] class EcbMode(object): - def __init__(self, block_cipher: SmartPointer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - + def __init__(self, block_cipher: SmartPointer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_gcm.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_gcm.py index 99144006..42ce3084 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_gcm.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_gcm.py @@ -32,7 +32,7 @@ Galois/Counter Mode (GCM). """ -__all__ = ['GcmMode'] +__all__ = ["GcmMode"] from binascii import unhexlify @@ -44,9 +44,15 @@ from Cryptodome.Hash import BLAKE2s from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, +) from Cryptodome.Util import _cpu_features @@ -63,558 +69,592 @@ int ghash_destroy_%imp%(void *ghash_tables); """ + def _build_impl(lib, postfix): - from collections import namedtuple + from collections import namedtuple - funcs = ( "ghash", "ghash_expand", "ghash_destroy" ) - GHASH_Imp = namedtuple('_GHash_Imp', funcs) - try: - imp_funcs = [ getattr(lib, x + "_" + postfix) for x in funcs ] - except AttributeError: # Make sphinx stop complaining with its mocklib - imp_funcs = [ None ] * 3 - params = dict(zip(funcs, imp_funcs)) - return GHASH_Imp(**params) + funcs = ("ghash", "ghash_expand", "ghash_destroy") + GHASH_Imp = namedtuple("_GHash_Imp", funcs) + try: + imp_funcs = [getattr(lib, x + "_" + postfix) for x in funcs] + except AttributeError: # Make sphinx stop complaining with its mocklib + imp_funcs = [None] * 3 + params = dict(zip(funcs, imp_funcs)) + return GHASH_Imp(**params) def _get_ghash_portable(): - api = _ghash_api_template.replace("%imp%", "portable") - lib = load_pycryptodome_raw_lib("Cryptodome.Hash._ghash_portable", api) - result = _build_impl(lib, "portable") - return result + api = _ghash_api_template.replace("%imp%", "portable") + lib = load_pycryptodome_raw_lib("Cryptodome.Hash._ghash_portable", api) + result = _build_impl(lib, "portable") + return result + + _ghash_portable = _get_ghash_portable() def _get_ghash_clmul(): - """Return None if CLMUL implementation is not available""" - - if not _cpu_features.have_clmul(): - return None - try: - api = _ghash_api_template.replace("%imp%", "clmul") - lib = load_pycryptodome_raw_lib("Cryptodome.Hash._ghash_clmul", api) - result = _build_impl(lib, "clmul") - except OSError: - result = None - return result + """Return None if CLMUL implementation is not available""" + + if not _cpu_features.have_clmul(): + return None + try: + api = _ghash_api_template.replace("%imp%", "clmul") + lib = load_pycryptodome_raw_lib("Cryptodome.Hash._ghash_clmul", api) + result = _build_impl(lib, "clmul") + except OSError: + result = None + return result + + _ghash_clmul = _get_ghash_clmul() class _GHASH(object): - """GHASH function defined in NIST SP 800-38D, Algorithm 2. + """GHASH function defined in NIST SP 800-38D, Algorithm 2. - If X_1, X_2, .. X_m are the blocks of input data, the function - computes: + If X_1, X_2, .. X_m are the blocks of input data, the function + computes: - X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H + X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H - in the Galois field GF(2^256) using the reducing polynomial - (x^128 + x^7 + x^2 + x + 1). - """ + in the Galois field GF(2^256) using the reducing polynomial + (x^128 + x^7 + x^2 + x + 1). + """ - def __init__(self, subkey, ghash_c): - assert len(subkey) == 16 + def __init__(self, subkey, ghash_c): + assert len(subkey) == 16 - self.ghash_c = ghash_c + self.ghash_c = ghash_c - self._exp_key = VoidPointer() - result = ghash_c.ghash_expand(c_uint8_ptr(subkey), - self._exp_key.address_of()) - if result: - raise ValueError("Error %d while expanding the GHASH key" % result) + self._exp_key = VoidPointer() + result = ghash_c.ghash_expand( + c_uint8_ptr(subkey), + self._exp_key.address_of(), + ) + if result: + raise ValueError("Error %d while expanding the GHASH key" % result) - self._exp_key = SmartPointer(self._exp_key.get(), - ghash_c.ghash_destroy) + self._exp_key = SmartPointer( + self._exp_key.get(), + ghash_c.ghash_destroy, + ) - # create_string_buffer always returns a string of zeroes - self._last_y = create_string_buffer(16) + # create_string_buffer always returns a string of zeroes + self._last_y = create_string_buffer(16) - def update(self, block_data): - assert len(block_data) % 16 == 0 + def update(self, block_data): + assert len(block_data) % 16 == 0 - result = self.ghash_c.ghash(self._last_y, - c_uint8_ptr(block_data), - c_size_t(len(block_data)), - self._last_y, - self._exp_key.get()) - if result: - raise ValueError("Error %d while updating GHASH" % result) + result = self.ghash_c.ghash( + self._last_y, + c_uint8_ptr(block_data), + c_size_t(len(block_data)), + self._last_y, + self._exp_key.get(), + ) + if result: + raise ValueError("Error %d while updating GHASH" % result) - return self + return self - def digest(self): - return get_raw_buffer(self._last_y) + def digest(self): + return get_raw_buffer(self._last_y) def enum(**enums): - return type('Enum', (), enums) + return type("Enum", (), enums) MacStatus = enum(PROCESSING_AUTH_DATA=1, PROCESSING_CIPHERTEXT=2) class GcmMode(object): - """Galois Counter Mode (GCM). - - This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. - It provides both confidentiality and authenticity. - - The header of the message may be left in the clear, if needed, and it will - still be subject to authentication. The decryption step tells the receiver - if the message comes from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - including the - header - has been modified or corrupted. - - This mode requires a *nonce*. - - This mode is only available for ciphers that operate on 128 bits blocks - (e.g. AES but not TDES). - - See `NIST SP800-38D`_. - - .. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, mac_len, cipher_params, ghash_c): - - self.block_size = factory.block_size - if self.block_size != 16: - raise ValueError("GCM mode is only available for ciphers" - " that operate on 128 bits blocks") - - if len(nonce) == 0: - raise ValueError("Nonce cannot be empty") - - if not is_buffer(nonce): - raise TypeError("Nonce must be bytes, bytearray or memoryview") - - # See NIST SP 800 38D, 5.2.1.1 - if len(nonce) > 2**64 - 1: - raise ValueError("Nonce exceeds maximum length") - - - self.nonce = _copy_bytes(None, None, nonce) - """Nonce""" - - self._factory = factory - self._key = _copy_bytes(None, None, key) - self._tag = None # Cache for MAC tag - - self._mac_len = mac_len - if not (4 <= mac_len <= 16): - raise ValueError("Parameter 'mac_len' must be in the range 4..16") - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - self._no_more_assoc_data = False - - # Length of associated data - self._auth_len = 0 - - # Length of the ciphertext or plaintext - self._msg_len = 0 - - # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H - # See also Algorithm 5 (decryption) - hash_subkey = factory.new(key, - self._factory.MODE_ECB, - **cipher_params - ).encrypt(b'\x00' * 16) - - # Step 2 - Compute J0 - if len(self.nonce) == 12: - j0 = self.nonce + b"\x00\x00\x00\x01" - else: - fill = (16 - (len(self.nonce) % 16)) % 16 + 8 - ghash_in = (self.nonce + - b'\x00' * fill + - long_to_bytes(8 * len(self.nonce), 8)) - j0 = _GHASH(hash_subkey, ghash_c).update(ghash_in).digest() - - # Step 3 - Prepare GCTR cipher for encryption/decryption - nonce_ctr = j0[:12] - iv_ctr = (bytes_to_long(j0) + 1) & 0xFFFFFFFF - self._cipher = factory.new(key, - self._factory.MODE_CTR, - initial_value=iv_ctr, - nonce=nonce_ctr, - **cipher_params) - - # Step 5 - Bootstrat GHASH - self._signer = _GHASH(hash_subkey, ghash_c) - - # Step 6 - Prepare GCTR cipher for GMAC - self._tag_cipher = factory.new(key, - self._factory.MODE_CTR, - initial_value=j0, - nonce=b"", - **cipher_params) - - # Cache for data to authenticate - self._cache = b"" - - self._status = MacStatus.PROCESSING_AUTH_DATA - - def update(self, assoc_data): - """Protect associated data - - If there is any associated data, the caller has to invoke - this function one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver is still able to detect any modification to it. - In GCM, the *associated data* is also called - *additional authenticated data* (AAD). - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. There are no restrictions on its size. - """ - - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - self._update(assoc_data) - self._auth_len += len(assoc_data) - - # See NIST SP 800 38D, 5.2.1.1 - if self._auth_len > 2**64 - 1: - raise ValueError("Additional Authenticated Data exceeds maximum length") - - return self - - def _update(self, data): - assert(len(self._cache) < 16) - - if len(self._cache) > 0: - filler = min(16 - len(self._cache), len(data)) - self._cache += _copy_bytes(None, filler, data) - data = data[filler:] - - if len(self._cache) < 16: - return - - # The cache is exactly one block - self._signer.update(self._cache) - self._cache = b"" - - update_len = len(data) // 16 * 16 - self._cache = _copy_bytes(update_len, None, data) - if update_len > 0: - self._signer.update(data[:update_len]) - - def _pad_cache_and_update(self): - assert(len(self._cache) < 16) - - # The authenticated data A is concatenated to the minimum - # number of zero bytes (possibly none) such that the - # - ciphertext C is aligned to the 16 byte boundary. - # See step 5 in section 7.1 - # - ciphertext C is aligned to the 16 byte boundary. - # See step 6 in section 7.2 - len_cache = len(self._cache) - if len_cache > 0: - self._update(b'\x00' * (16 - len_cache)) - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) + """Galois Counter Mode (GCM). + + This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. + It provides both confidentiality and authenticity. + + The header of the message may be left in the clear, if needed, and it will + still be subject to authentication. The decryption step tells the receiver + if the message comes from a source that really knowns the secret key. + Additionally, decryption detects if any part of the message - including the + header - has been modified or corrupted. + + This mode requires a *nonce*. + + This mode is only available for ciphers that operate on 128 bits blocks + (e.g. AES but not TDES). + + See `NIST SP800-38D`_. + + .. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html + + :undocumented: __init__ + """ + + def __init__(self, factory, key, nonce, mac_len, cipher_params, ghash_c): + self.block_size = factory.block_size + if self.block_size != 16: + raise ValueError( + "GCM mode is only available for ciphers that operate on 128 bits blocks", + ) + + if len(nonce) == 0: + raise ValueError("Nonce cannot be empty") + + if not is_buffer(nonce): + raise TypeError("Nonce must be bytes, bytearray or memoryview") + + # See NIST SP 800 38D, 5.2.1.1 + if len(nonce) > 2**64 - 1: + raise ValueError("Nonce exceeds maximum length") + + self.nonce = _copy_bytes(None, None, nonce) + """Nonce""" + + self._factory = factory + self._key = _copy_bytes(None, None, key) + self._tag = None # Cache for MAC tag + + self._mac_len = mac_len + if not (4 <= mac_len <= 16): + raise ValueError("Parameter 'mac_len' must be in the range 4..16") + + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + self._no_more_assoc_data = False + + # Length of associated data + self._auth_len = 0 + + # Length of the ciphertext or plaintext + self._msg_len = 0 + + # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H + # See also Algorithm 5 (decryption) + hash_subkey = factory.new( + key, + self._factory.MODE_ECB, + **cipher_params, + ).encrypt(b"\x00" * 16) + + # Step 2 - Compute J0 + if len(self.nonce) == 12: + j0 = self.nonce + b"\x00\x00\x00\x01" + else: + fill = (16 - (len(self.nonce) % 16)) % 16 + 8 + ghash_in = self.nonce + b"\x00" * fill + long_to_bytes(8 * len(self.nonce), 8) + j0 = _GHASH(hash_subkey, ghash_c).update(ghash_in).digest() + + # Step 3 - Prepare GCTR cipher for encryption/decryption + nonce_ctr = j0[:12] + iv_ctr = (bytes_to_long(j0) + 1) & 0xFFFFFFFF + self._cipher = factory.new( + key, + self._factory.MODE_CTR, + initial_value=iv_ctr, + nonce=nonce_ctr, + **cipher_params, + ) + + # Step 5 - Bootstrat GHASH + self._signer = _GHASH(hash_subkey, ghash_c) + + # Step 6 - Prepare GCTR cipher for GMAC + self._tag_cipher = factory.new( + key, + self._factory.MODE_CTR, + initial_value=j0, + nonce=b"", + **cipher_params, + ) + + # Cache for data to authenticate + self._cache = b"" - This function does not add any padding to the plaintext. + self._status = MacStatus.PROCESSING_AUTH_DATA + + def update(self, assoc_data): + """Protect associated data + + If there is any associated data, the caller has to invoke + this function one or more times, before using + ``decrypt`` or ``encrypt``. + + By *associated data* it is meant any data (e.g. packet headers) that + will not be encrypted and will be transmitted in the clear. + However, the receiver is still able to detect any modification to it. + In GCM, the *associated data* is also called + *additional authenticated data* (AAD). + + If there is no associated data, this method must not be called. + + The caller may split associated data in segments of any size, and + invoke this method multiple times, each time with the next segment. + + :Parameters: + assoc_data : bytes/bytearray/memoryview + A piece of associated data. There are no restrictions on its size. + """ + + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) + + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + self._update(assoc_data) + self._auth_len += len(assoc_data) + + # See NIST SP 800 38D, 5.2.1.1 + if self._auth_len > 2**64 - 1: + raise ValueError("Additional Authenticated Data exceeds maximum length") + + return self + + def _update(self, data): + assert len(self._cache) < 16 - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext as ``bytes``. - Otherwise, ``None``. - """ + if len(self._cache) > 0: + filler = min(16 - len(self._cache), len(data)) + self._cache += _copy_bytes(None, filler, data) + data = data[filler:] - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - self._next = ["encrypt", "digest"] + if len(self._cache) < 16: + return + + # The cache is exactly one block + self._signer.update(self._cache) + self._cache = b"" + + update_len = len(data) // 16 * 16 + self._cache = _copy_bytes(update_len, None, data) + if update_len > 0: + self._signer.update(data[:update_len]) + + def _pad_cache_and_update(self): + assert len(self._cache) < 16 + + # The authenticated data A is concatenated to the minimum + # number of zero bytes (possibly none) such that the + # - ciphertext C is aligned to the 16 byte boundary. + # See step 5 in section 7.1 + # - ciphertext C is aligned to the 16 byte boundary. + # See step 6 in section 7.2 + len_cache = len(self._cache) + if len_cache > 0: + self._update(b"\x00" * (16 - len_cache)) - ciphertext = self._cipher.encrypt(plaintext, output=output) + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. - if self._status == MacStatus.PROCESSING_AUTH_DATA: - self._pad_cache_and_update() - self._status = MacStatus.PROCESSING_CIPHERTEXT + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - self._update(ciphertext if output is None else output) - self._msg_len += len(plaintext) + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - # See NIST SP 800 38D, 5.2.1.1 - if self._msg_len > 2**39 - 256: - raise ValueError("Plaintext exceeds maximum length") + That is, the statement: - return ciphertext + >>> c.encrypt(a) + c.encrypt(b) - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. + is equivalent to: - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + >>> c.encrypt(a+b) - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + This function does not add any padding to the plaintext. - That is, the statement: + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext as ``bytes``. + Otherwise, ``None``. + """ - >>> c.decrypt(a) + c.decrypt(b) + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) + self._next = ["encrypt", "digest"] - is equivalent to: + ciphertext = self._cipher.encrypt(plaintext, output=output) - >>> c.decrypt(a+b) + if self._status == MacStatus.PROCESSING_AUTH_DATA: + self._pad_cache_and_update() + self._status = MacStatus.PROCESSING_CIPHERTEXT - This function does not remove any padding from the plaintext. + self._update(ciphertext if output is None else output) + self._msg_len += len(plaintext) - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext as ``bytes``. - Otherwise, ``None``. - """ + # See NIST SP 800 38D, 5.2.1.1 + if self._msg_len > 2**39 - 256: + raise ValueError("Plaintext exceeds maximum length") - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = ["decrypt", "verify"] + return ciphertext - if self._status == MacStatus.PROCESSING_AUTH_DATA: - self._pad_cache_and_update() - self._status = MacStatus.PROCESSING_CIPHERTEXT + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. - self._update(ciphertext) - self._msg_len += len(ciphertext) + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - return self._cipher.decrypt(ciphertext, output=output) + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - def digest(self): - """Compute the *binary* MAC tag in an AEAD mode. + That is, the statement: - The caller invokes this function at the very end. + >>> c.decrypt(a) + c.decrypt(b) - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. + is equivalent to: - :Return: the MAC, as a byte string. - """ + >>> c.decrypt(a+b) - if "digest" not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = ["digest"] + This function does not remove any padding from the plaintext. - return self._compute_mac() + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext as ``bytes``. + Otherwise, ``None``. + """ - def _compute_mac(self): - """Compute MAC without any FSM checks.""" + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + self._next = ["decrypt", "verify"] - if self._tag: - return self._tag + if self._status == MacStatus.PROCESSING_AUTH_DATA: + self._pad_cache_and_update() + self._status = MacStatus.PROCESSING_CIPHERTEXT - # Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S - self._pad_cache_and_update() - self._update(long_to_bytes(8 * self._auth_len, 8)) - self._update(long_to_bytes(8 * self._msg_len, 8)) - s_tag = self._signer.digest() + self._update(ciphertext) + self._msg_len += len(ciphertext) - # Step 6 - Compute T - self._tag = self._tag_cipher.encrypt(s_tag)[:self._mac_len] + return self._cipher.decrypt(ciphertext, output=output) - return self._tag + def digest(self): + """Compute the *binary* MAC tag in an AEAD mode. - def hexdigest(self): - """Compute the *printable* MAC tag. + The caller invokes this function at the very end. - This method is like `digest`. + This method returns the MAC that shall be sent to the receiver, + together with the ciphertext. - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) + :Return: the MAC, as a byte string. + """ - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. + if "digest" not in self._next: + raise TypeError( + "digest() cannot be called when decrypting or validating a message", + ) + self._next = ["digest"] - The caller invokes this function at the very end. + return self._compute_mac() - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. + def _compute_mac(self): + """Compute MAC without any FSM checks.""" - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + if self._tag: + return self._tag - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ["verify"] + # Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S + self._pad_cache_and_update() + self._update(long_to_bytes(8 * self._auth_len, 8)) + self._update(long_to_bytes(8 * self._msg_len, 8)) + s_tag = self._signer.digest() - secret = get_random_bytes(16) + # Step 6 - Compute T + self._tag = self._tag_cipher.encrypt(s_tag)[: self._mac_len] - mac1 = BLAKE2s.new(digest_bits=160, key=secret, - data=self._compute_mac()) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, - data=received_mac_tag) + return self._tag - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + def hexdigest(self): + """Compute the *printable* MAC tag. - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. + This method is like `digest`. - This method is like `verify`. + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. - self.verify(unhexlify(hex_mac_tag)) + The caller invokes this function at the very end. - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. + This method checks if the decrypted message is indeed valid + (that is, if the key is correct) and it has not been + tampered with while in transit. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ["verify"] + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new( + digest_bits=160, + key=secret, + data=self._compute_mac(), + ) + mac2 = BLAKE2s.new( + digest_bits=160, + key=secret, + data=received_mac_tag, + ) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. - return self.encrypt(plaintext, output=output), self.digest() + This method is like `verify`. - def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): - """Perform decrypt() and verify() in one step. + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - received_mac_tag : byte string - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + self.verify(unhexlify(hex_mac_tag)) - plaintext = self.decrypt(ciphertext, output=output) - self.verify(received_mac_tag) - return plaintext + def encrypt_and_digest(self, plaintext, output=None): + """Perform encrypt() and digest() in one step. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + a tuple with two items: + + - the ciphertext, as ``bytes`` + - the MAC tag, as ``bytes`` + + The first item becomes ``None`` when the ``output`` parameter + specified a location for the result. + """ + + return self.encrypt(plaintext, output=output), self.digest() + + def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): + """Perform decrypt() and verify() in one step. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + received_mac_tag : byte string + This is the *binary* MAC, as received from the sender. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` + parameter specified a location for the result. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + plaintext = self.decrypt(ciphertext, output=output) + self.verify(received_mac_tag) + return plaintext def _create_gcm_cipher(factory, **kwargs): - """Create a new block cipher, configured in Galois Counter Mode (GCM). - - :Parameters: - factory : module - A block cipher module, taken from `Cryptodome.Cipher`. - The cipher must have block length of 16 bytes. - GCM has been only defined for `Cryptodome.Cipher.AES`. - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - It must be 16 (e.g. *AES-128*), 24 (e.g. *AES-192*) - or 32 (e.g. *AES-256*) bytes long. - - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - - There are no restrictions on its length, - but it is recommended to use at least 16 bytes. - - The nonce shall never repeat for two - different messages encrypted with the same key, - but it does not need to be random. - - If not provided, a 16 byte nonce will be randomly created. - - mac_len : integer - Length of the MAC, in bytes. - It must be no larger than 16 bytes (which is the default). - """ - - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter:" + str(e)) - - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(16) - mac_len = kwargs.pop("mac_len", 16) - - # Not documented - only used for testing - use_clmul = kwargs.pop("use_clmul", True) - if use_clmul and _ghash_clmul: - ghash_c = _ghash_clmul - else: - ghash_c = _ghash_portable - - return GcmMode(factory, key, nonce, mac_len, kwargs, ghash_c) + """Create a new block cipher, configured in Galois Counter Mode (GCM). + + :Parameters: + factory : module + A block cipher module, taken from `Cryptodome.Cipher`. + The cipher must have block length of 16 bytes. + GCM has been only defined for `Cryptodome.Cipher.AES`. + + :Keywords: + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. + It must be 16 (e.g. *AES-128*), 24 (e.g. *AES-192*) + or 32 (e.g. *AES-256*) bytes long. + + nonce : bytes/bytearray/memoryview + A value that must never be reused for any other encryption. + + There are no restrictions on its length, + but it is recommended to use at least 16 bytes. + + The nonce shall never repeat for two + different messages encrypted with the same key, + but it does not need to be random. + + If not provided, a 16 byte nonce will be randomly created. + + mac_len : integer + Length of the MAC, in bytes. + It must be no larger than 16 bytes (which is the default). + """ + + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter:" + str(e)) + + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(16) + mac_len = kwargs.pop("mac_len", 16) + + # Not documented - only used for testing + use_clmul = kwargs.pop("use_clmul", True) + if use_clmul and _ghash_clmul: + ghash_c = _ghash_clmul + else: + ghash_c = _ghash_portable + + return GcmMode(factory, key, nonce, mac_len, kwargs, ghash_c) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_gcm.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_gcm.pyi index 8912955f..ff0382bd 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_gcm.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_gcm.pyi @@ -1,45 +1,37 @@ from types import ModuleType from typing import Union, Tuple, Dict, overload, Optional -__all__ = ['GcmMode'] +__all__ = ["GcmMode"] Buffer = Union[bytes, bytearray, memoryview] class GcmMode(object): - block_size: int - nonce: Buffer - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - mac_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> GcmMode: ... + block_size: int + nonce: Buffer - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... + def __init__( + self, factory: ModuleType, key: Buffer, nonce: Buffer, mac_len: int, cipher_params: Dict + ) -> None: ... + def update(self, assoc_data: Buffer) -> GcmMode: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer, output: Buffer) -> Tuple[None, bytes]: ... + def decrypt_and_verify( + self, + ciphertext: Buffer, + received_mac_tag: Buffer, + output: Optional[Union[bytearray, memoryview]] = ..., + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_kw.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_kw.py index 41c09ef7..f5de3357 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_kw.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_kw.py @@ -7,152 +7,158 @@ from Cryptodome.Util.strxor import strxor -def W(cipher: ModuleType, - plaintext: Union[bytes, bytearray]) -> bytes: - - S = [plaintext[i:i+8] for i in range(0, len(plaintext), 8)] - n = len(S) - s = 6 * (n - 1) - A = S[0] - R = deque(S[1:]) - - for t in range(1, s + 1): - t_64 = struct.pack('>Q', t) - ct = cipher.encrypt(A + R.popleft()) - A = strxor(ct[:8], t_64) - R.append(ct[8:]) - - return A + b''.join(R) - - -def W_inverse(cipher: ModuleType, - ciphertext: Union[bytes, bytearray]) -> bytes: - - C = [ciphertext[i:i+8] for i in range(0, len(ciphertext), 8)] - n = len(C) - s = 6 * (n - 1) - A = C[0] - R = deque(C[1:]) - - for t in range(s, 0, -1): - t_64 = struct.pack('>Q', t) - pt = cipher.decrypt(strxor(A, t_64) + R.pop()) - A = pt[:8] - R.appendleft(pt[8:]) - - return A + b''.join(R) +def W( + cipher: ModuleType, + plaintext: Union[bytes, bytearray], +) -> bytes: + S = [plaintext[i : i + 8] for i in range(0, len(plaintext), 8)] + n = len(S) + s = 6 * (n - 1) + A = S[0] + R = deque(S[1:]) + + for t in range(1, s + 1): + t_64 = struct.pack(">Q", t) + ct = cipher.encrypt(A + R.popleft()) + A = strxor(ct[:8], t_64) + R.append(ct[8:]) + + return A + b"".join(R) + + +def W_inverse( + cipher: ModuleType, + ciphertext: Union[bytes, bytearray], +) -> bytes: + C = [ciphertext[i : i + 8] for i in range(0, len(ciphertext), 8)] + n = len(C) + s = 6 * (n - 1) + A = C[0] + R = deque(C[1:]) + + for t in range(s, 0, -1): + t_64 = struct.pack(">Q", t) + pt = cipher.decrypt(strxor(A, t_64) + R.pop()) + A = pt[:8] + R.appendleft(pt[8:]) + + return A + b"".join(R) class KWMode(object): - """Key Wrap (KW) mode. - - This is a deterministic Authenticated Encryption (AE) mode - for protecting cryptographic keys. See `NIST SP800-38F`_. + """Key Wrap (KW) mode. - It provides both confidentiality and authenticity, and it designed - so that any bit of the ciphertext depends on all bits of the plaintext. + This is a deterministic Authenticated Encryption (AE) mode + for protecting cryptographic keys. See `NIST SP800-38F`_. - This mode is only available for ciphers that operate on 128 bits blocks - (e.g., AES). + It provides both confidentiality and authenticity, and it designed + so that any bit of the ciphertext depends on all bits of the plaintext. - .. _`NIST SP800-38F`: http://csrc.nist.gov/publications/nistpubs/800-38F/SP-800-38F.pdf + This mode is only available for ciphers that operate on 128 bits blocks + (e.g., AES). - :undocumented: __init__ - """ + .. _`NIST SP800-38F`: http://csrc.nist.gov/publications/nistpubs/800-38F/SP-800-38F.pdf - def __init__(self, - factory: ModuleType, - key: Union[bytes, bytearray]): + :undocumented: __init__ + """ - self.block_size = factory.block_size - if self.block_size != 16: - raise ValueError("Key Wrap mode is only available for ciphers" - " that operate on 128 bits blocks") + def __init__( + self, + factory: ModuleType, + key: Union[bytes, bytearray], + ): + self.block_size = factory.block_size + if self.block_size != 16: + raise ValueError( + "Key Wrap mode is only available for ciphers that operate on 128 bits blocks", + ) - self._factory = factory - self._cipher = factory.new(key, factory.MODE_ECB) - self._done = False + self._factory = factory + self._cipher = factory.new(key, factory.MODE_ECB) + self._done = False - def seal(self, plaintext: Union[bytes, bytearray]) -> bytes: - """Encrypt and authenticate (wrap) a cryptographic key. + def seal(self, plaintext: Union[bytes, bytearray]) -> bytes: + """Encrypt and authenticate (wrap) a cryptographic key. - Args: - plaintext: - The cryptographic key to wrap. - It must be at least 16 bytes long, and its length - must be a multiple of 8. + Args: + plaintext: + The cryptographic key to wrap. + It must be at least 16 bytes long, and its length + must be a multiple of 8. - Returns: - The wrapped key. - """ + Returns: + The wrapped key. + """ - if self._done: - raise ValueError("The cipher cannot be used more than once") + if self._done: + raise ValueError("The cipher cannot be used more than once") - if len(plaintext) % 8: - raise ValueError("The plaintext must have length multiple of 8 bytes") + if len(plaintext) % 8: + raise ValueError("The plaintext must have length multiple of 8 bytes") - if len(plaintext) < 16: - raise ValueError("The plaintext must be at least 16 bytes long") + if len(plaintext) < 16: + raise ValueError("The plaintext must be at least 16 bytes long") - if len(plaintext) >= 2**32: - raise ValueError("The plaintext is too long") + if len(plaintext) >= 2**32: + raise ValueError("The plaintext is too long") - res = W(self._cipher, b'\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6' + plaintext) - self._done = True - return res + res = W(self._cipher, b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" + plaintext) + self._done = True + return res - def unseal(self, ciphertext: Union[bytes, bytearray]) -> bytes: - """Decrypt and authenticate (unwrap) a cryptographic key. + def unseal(self, ciphertext: Union[bytes, bytearray]) -> bytes: + """Decrypt and authenticate (unwrap) a cryptographic key. - Args: - ciphertext: - The cryptographic key to unwrap. - It must be at least 24 bytes long, and its length - must be a multiple of 8. + Args: + ciphertext: + The cryptographic key to unwrap. + It must be at least 24 bytes long, and its length + must be a multiple of 8. - Returns: - The original key. + Returns: + The original key. - Raises: ValueError - If the ciphertext or the key are not valid. - """ + Raises: ValueError + If the ciphertext or the key are not valid. + """ - if self._done: - raise ValueError("The cipher cannot be used more than once") + if self._done: + raise ValueError("The cipher cannot be used more than once") - if len(ciphertext) % 8: - raise ValueError("The ciphertext must have length multiple of 8 bytes") + if len(ciphertext) % 8: + raise ValueError("The ciphertext must have length multiple of 8 bytes") - if len(ciphertext) < 24: - raise ValueError("The ciphertext must be at least 24 bytes long") + if len(ciphertext) < 24: + raise ValueError("The ciphertext must be at least 24 bytes long") - pt = W_inverse(self._cipher, ciphertext) + pt = W_inverse(self._cipher, ciphertext) - if pt[:8] != b'\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6': - raise ValueError("Incorrect integrity check value") - self._done = True + if pt[:8] != b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6": + raise ValueError("Incorrect integrity check value") + self._done = True - return pt[8:] + return pt[8:] -def _create_kw_cipher(factory: ModuleType, - **kwargs: Union[bytes, bytearray]) -> KWMode: - """Create a new block cipher in Key Wrap mode. +def _create_kw_cipher( + factory: ModuleType, + **kwargs: Union[bytes, bytearray], +) -> KWMode: + """Create a new block cipher in Key Wrap mode. - Args: - factory: - A block cipher module, taken from `Cryptodome.Cipher`. - The cipher must have block length of 16 bytes, such as AES. + Args: + factory: + A block cipher module, taken from `Cryptodome.Cipher`. + The cipher must have block length of 16 bytes, such as AES. - Keywords: - key: - The secret key to use to seal or unseal. - """ + Keywords: + key: + The secret key to use to seal or unseal. + """ - try: - key = kwargs["key"] - except KeyError as e: - raise TypeError("Missing parameter:" + str(e)) + try: + key = kwargs["key"] + except KeyError as e: + raise TypeError("Missing parameter:" + str(e)) - return KWMode(factory, key) + return KWMode(factory, key) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_kwp.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_kwp.py index 08684431..56679d4a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_kwp.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_kwp.py @@ -7,129 +7,133 @@ class KWPMode(object): - """Key Wrap with Padding (KWP) mode. + """Key Wrap with Padding (KWP) mode. - This is a deterministic Authenticated Encryption (AE) mode - for protecting cryptographic keys. See `NIST SP800-38F`_. + This is a deterministic Authenticated Encryption (AE) mode + for protecting cryptographic keys. See `NIST SP800-38F`_. - It provides both confidentiality and authenticity, and it designed - so that any bit of the ciphertext depends on all bits of the plaintext. + It provides both confidentiality and authenticity, and it designed + so that any bit of the ciphertext depends on all bits of the plaintext. - This mode is only available for ciphers that operate on 128 bits blocks - (e.g., AES). + This mode is only available for ciphers that operate on 128 bits blocks + (e.g., AES). - .. _`NIST SP800-38F`: http://csrc.nist.gov/publications/nistpubs/800-38F/SP-800-38F.pdf + .. _`NIST SP800-38F`: http://csrc.nist.gov/publications/nistpubs/800-38F/SP-800-38F.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, - factory: ModuleType, - key: Union[bytes, bytearray]): + def __init__( + self, + factory: ModuleType, + key: Union[bytes, bytearray], + ): + self.block_size = factory.block_size + if self.block_size != 16: + raise ValueError( + "Key Wrap with Padding mode is only available for ciphers that operate on 128 bits blocks", + ) - self.block_size = factory.block_size - if self.block_size != 16: - raise ValueError("Key Wrap with Padding mode is only available for ciphers" - " that operate on 128 bits blocks") + self._factory = factory + self._cipher = factory.new(key, factory.MODE_ECB) + self._done = False - self._factory = factory - self._cipher = factory.new(key, factory.MODE_ECB) - self._done = False + def seal(self, plaintext: Union[bytes, bytearray]) -> bytes: + """Encrypt and authenticate (wrap) a cryptographic key. - def seal(self, plaintext: Union[bytes, bytearray]) -> bytes: - """Encrypt and authenticate (wrap) a cryptographic key. + Args: + plaintext: + The cryptographic key to wrap. - Args: - plaintext: - The cryptographic key to wrap. + Returns: + The wrapped key. + """ - Returns: - The wrapped key. - """ + if self._done: + raise ValueError("The cipher cannot be used more than once") - if self._done: - raise ValueError("The cipher cannot be used more than once") + if len(plaintext) == 0: + raise ValueError("The plaintext must be at least 1 byte") - if len(plaintext) == 0: - raise ValueError("The plaintext must be at least 1 byte") + if len(plaintext) >= 2**32: + raise ValueError("The plaintext is too long") - if len(plaintext) >= 2 ** 32: - raise ValueError("The plaintext is too long") + padlen = (8 - len(plaintext)) % 8 + padded = plaintext + b"\x00" * padlen - padlen = (8 - len(plaintext)) % 8 - padded = plaintext + b'\x00' * padlen + AIV = b"\xa6\x59\x59\xa6" + struct.pack(">I", len(plaintext)) - AIV = b'\xA6\x59\x59\xA6' + struct.pack('>I', len(plaintext)) + if len(padded) == 8: + res = self._cipher.encrypt(AIV + padded) + else: + res = W(self._cipher, AIV + padded) - if len(padded) == 8: - res = self._cipher.encrypt(AIV + padded) - else: - res = W(self._cipher, AIV + padded) + return res - return res + def unseal(self, ciphertext: Union[bytes, bytearray]) -> bytes: + """Decrypt and authenticate (unwrap) a cryptographic key. - def unseal(self, ciphertext: Union[bytes, bytearray]) -> bytes: - """Decrypt and authenticate (unwrap) a cryptographic key. + Args: + ciphertext: + The cryptographic key to unwrap. + It must be at least 16 bytes long, and its length + must be a multiple of 8. - Args: - ciphertext: - The cryptographic key to unwrap. - It must be at least 16 bytes long, and its length - must be a multiple of 8. + Returns: + The original key. - Returns: - The original key. + Raises: ValueError + If the ciphertext or the key are not valid. + """ - Raises: ValueError - If the ciphertext or the key are not valid. - """ + if self._done: + raise ValueError("The cipher cannot be used more than once") - if self._done: - raise ValueError("The cipher cannot be used more than once") + if len(ciphertext) % 8: + raise ValueError("The ciphertext must have length multiple of 8 bytes") - if len(ciphertext) % 8: - raise ValueError("The ciphertext must have length multiple of 8 bytes") + if len(ciphertext) < 16: + raise ValueError("The ciphertext must be at least 24 bytes long") - if len(ciphertext) < 16: - raise ValueError("The ciphertext must be at least 24 bytes long") + if len(ciphertext) == 16: + S = self._cipher.decrypt(ciphertext) + else: + S = W_inverse(self._cipher, ciphertext) - if len(ciphertext) == 16: - S = self._cipher.decrypt(ciphertext) - else: - S = W_inverse(self._cipher, ciphertext) + if S[:4] != b"\xa6\x59\x59\xa6": + raise ValueError("Incorrect decryption") - if S[:4] != b'\xA6\x59\x59\xA6': - raise ValueError("Incorrect decryption") + Plen = struct.unpack(">I", S[4:8])[0] - Plen = struct.unpack('>I', S[4:8])[0] + padlen = len(S) - 8 - Plen + if padlen < 0 or padlen > 7: + raise ValueError("Incorrect decryption") - padlen = len(S) - 8 - Plen - if padlen < 0 or padlen > 7: - raise ValueError("Incorrect decryption") + if S[len(S) - padlen :] != b"\x00" * padlen: + raise ValueError("Incorrect decryption") - if S[len(S) - padlen:] != b'\x00' * padlen: - raise ValueError("Incorrect decryption") + return S[8 : len(S) - padlen] - return S[8:len(S) - padlen] +def _create_kwp_cipher( + factory: ModuleType, + **kwargs: Union[bytes, bytearray], +) -> KWPMode: + """Create a new block cipher in Key Wrap with Padding mode. -def _create_kwp_cipher(factory: ModuleType, - **kwargs: Union[bytes, bytearray]) -> KWPMode: - """Create a new block cipher in Key Wrap with Padding mode. + Args: + factory: + A block cipher module, taken from `Cryptodome.Cipher`. + The cipher must have block length of 16 bytes, such as AES. - Args: - factory: - A block cipher module, taken from `Cryptodome.Cipher`. - The cipher must have block length of 16 bytes, such as AES. + Keywords: + key: + The secret key to use to seal or unseal. + """ - Keywords: - key: - The secret key to use to seal or unseal. - """ + try: + key = kwargs["key"] + except KeyError as e: + raise TypeError("Missing parameter:" + str(e)) - try: - key = kwargs["key"] - except KeyError as e: - raise TypeError("Missing parameter:" + str(e)) - - return KWPMode(factory, key) + return KWPMode(factory, key) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ocb.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ocb.py index 1295e61a..e7c648fc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ocb.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ocb.py @@ -78,12 +78,20 @@ from Cryptodome.Hash import BLAKE2s from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_buffer) - -_raw_ocb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ocb", """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_buffer, +) + +_raw_ocb_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_ocb", + """ int OCB_start_operation(void *cipher, const uint8_t *offset_0, size_t offset_0_len, @@ -103,430 +111,471 @@ uint8_t *tag, size_t tag_len); int OCB_stop_operation(void *state); - """) + """, +) class OcbMode(object): - """Offset Codebook (OCB) mode. - - :undocumented: __init__ - """ - - def __init__(self, factory, nonce, mac_len, cipher_params): - - if factory.block_size != 16: - raise ValueError("OCB mode is only available for ciphers" - " that operate on 128 bits blocks") - - self.block_size = 16 - """The block size of the underlying cipher, in bytes.""" - - self.nonce = _copy_bytes(None, None, nonce) - """Nonce used for this session.""" - if len(nonce) not in range(1, 16): - raise ValueError("Nonce must be at most 15 bytes long") - if not is_buffer(nonce): - raise TypeError("Nonce must be bytes, bytearray or memoryview") - - self._mac_len = mac_len - if not 8 <= mac_len <= 16: - raise ValueError("MAC tag must be between 8 and 16 bytes long") - - # Cache for MAC tag - self._mac_tag = None - - # Cache for unaligned associated data - self._cache_A = b"" - - # Cache for unaligned ciphertext/plaintext - self._cache_P = b"" - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - # Compute Offset_0 - params_without_key = dict(cipher_params) - key = params_without_key.pop("key") - - taglen_mod128 = (self._mac_len * 8) % 128 - if len(self.nonce) < 15: - nonce = bchr(taglen_mod128 << 1) +\ - b'\x00' * (14 - len(nonce)) +\ - b'\x01' +\ - self.nonce - else: - nonce = bchr((taglen_mod128 << 1) | 0x01) +\ - self.nonce - - bottom_bits = bord(nonce[15]) & 0x3F # 6 bits, 0..63 - top_bits = bord(nonce[15]) & 0xC0 # 2 bits - - ktop_cipher = factory.new(key, - factory.MODE_ECB, - **params_without_key) - ktop = ktop_cipher.encrypt(struct.pack('15sB', - nonce[:15], - top_bits)) - - stretch = ktop + strxor(ktop[:8], ktop[1:9]) # 192 bits - offset_0 = long_to_bytes(bytes_to_long(stretch) >> - (64 - bottom_bits), 24)[8:] - - # Create low-level cipher instance - raw_cipher = factory._create_base_cipher(cipher_params) - if cipher_params: - raise TypeError("Unknown keywords: " + str(cipher_params)) - - self._state = VoidPointer() - result = _raw_ocb_lib.OCB_start_operation(raw_cipher.get(), - offset_0, - c_size_t(len(offset_0)), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the OCB mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - _raw_ocb_lib.OCB_stop_operation) - - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - raw_cipher.release() - - def _update(self, assoc_data, assoc_data_len): - result = _raw_ocb_lib.OCB_update(self._state.get(), - c_uint8_ptr(assoc_data), - c_size_t(assoc_data_len)) - if result: - raise ValueError("Error %d while computing MAC in OCB mode" % result) - - def update(self, assoc_data): - """Process the associated data. - - If there is any associated data, the caller has to invoke - this method one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver shall still able to detect modifications. - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. - """ - - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = ["encrypt", "decrypt", "digest", - "verify", "update"] - - if len(self._cache_A) > 0: - filler = min(16 - len(self._cache_A), len(assoc_data)) - self._cache_A += _copy_bytes(None, filler, assoc_data) - assoc_data = assoc_data[filler:] - - if len(self._cache_A) < 16: - return self - - # Clear the cache, and proceeding with any other aligned data - self._cache_A, seg = b"", self._cache_A - self.update(seg) - - update_len = len(assoc_data) // 16 * 16 - self._cache_A = _copy_bytes(update_len, None, assoc_data) - self._update(assoc_data, update_len) - return self - - def _transcrypt_aligned(self, in_data, in_data_len, - trans_func, trans_desc): - - out_data = create_string_buffer(in_data_len) - result = trans_func(self._state.get(), - in_data, - out_data, - c_size_t(in_data_len)) - if result: - raise ValueError("Error %d while %sing in OCB mode" - % (result, trans_desc)) - return get_raw_buffer(out_data) - - def _transcrypt(self, in_data, trans_func, trans_desc): - # Last piece to encrypt/decrypt - if in_data is None: - out_data = self._transcrypt_aligned(self._cache_P, - len(self._cache_P), - trans_func, - trans_desc) - self._cache_P = b"" - return out_data - - # Try to fill up the cache, if it already contains something - prefix = b"" - if len(self._cache_P) > 0: - filler = min(16 - len(self._cache_P), len(in_data)) - self._cache_P += _copy_bytes(None, filler, in_data) - in_data = in_data[filler:] - - if len(self._cache_P) < 16: - # We could not manage to fill the cache, so there is certainly - # no output yet. - return b"" - - # Clear the cache, and proceeding with any other aligned data - prefix = self._transcrypt_aligned(self._cache_P, - len(self._cache_P), - trans_func, - trans_desc) - self._cache_P = b"" - - # Process data in multiples of the block size - trans_len = len(in_data) // 16 * 16 - result = self._transcrypt_aligned(c_uint8_ptr(in_data), - trans_len, - trans_func, - trans_desc) - if prefix: - result = prefix + result - - # Left-over - self._cache_P = _copy_bytes(trans_len, None, in_data) - - return result - - def encrypt(self, plaintext=None): - """Encrypt the next piece of plaintext. - - After the entire plaintext has been passed (but before `digest`), - you **must** call this method one last time with no arguments to collect - the final piece of ciphertext. - - If possible, use the method `encrypt_and_digest` instead. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The next piece of data to encrypt or ``None`` to signify - that encryption has finished and that any remaining ciphertext - has to be produced. - :Return: - the ciphertext, as a byte string. - Its length may not match the length of the *plaintext*. - """ - - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - - if plaintext is None: - self._next = ["digest"] - else: - self._next = ["encrypt"] - return self._transcrypt(plaintext, _raw_ocb_lib.OCB_encrypt, "encrypt") - - def decrypt(self, ciphertext=None): - """Decrypt the next piece of ciphertext. - - After the entire ciphertext has been passed (but before `verify`), - you **must** call this method one last time with no arguments to collect - the remaining piece of plaintext. - - If possible, use the method `decrypt_and_verify` instead. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The next piece of data to decrypt or ``None`` to signify - that decryption has finished and that any remaining plaintext - has to be produced. - :Return: - the plaintext, as a byte string. - Its length may not match the length of the *ciphertext*. - """ - - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called after" - " initialization or an update()") - - if ciphertext is None: - self._next = ["verify"] - else: - self._next = ["decrypt"] - return self._transcrypt(ciphertext, - _raw_ocb_lib.OCB_decrypt, - "decrypt") - - def _compute_mac_tag(self): - - if self._mac_tag is not None: - return - - if self._cache_A: - self._update(self._cache_A, len(self._cache_A)) - self._cache_A = b"" - - mac_tag = create_string_buffer(16) - result = _raw_ocb_lib.OCB_digest(self._state.get(), - mac_tag, - c_size_t(len(mac_tag)) - ) - if result: - raise ValueError("Error %d while computing digest in OCB mode" - % result) - self._mac_tag = get_raw_buffer(mac_tag)[:self._mac_len] - - def digest(self): - """Compute the *binary* MAC tag. - - Call this method after the final `encrypt` (the one with no arguments) - to obtain the MAC tag. - - The MAC tag is needed by the receiver to determine authenticity - of the message. - - :Return: the MAC, as a byte string. - """ - - if "digest" not in self._next: - raise TypeError("digest() cannot be called now for this cipher") + """Offset Codebook (OCB) mode. + + :undocumented: __init__ + """ + + def __init__(self, factory, nonce, mac_len, cipher_params): + if factory.block_size != 16: + raise ValueError( + "OCB mode is only available for ciphers that operate on 128 bits blocks", + ) + + self.block_size = 16 + """The block size of the underlying cipher, in bytes.""" + + self.nonce = _copy_bytes(None, None, nonce) + """Nonce used for this session.""" + if len(nonce) not in range(1, 16): + raise ValueError("Nonce must be at most 15 bytes long") + if not is_buffer(nonce): + raise TypeError("Nonce must be bytes, bytearray or memoryview") + + self._mac_len = mac_len + if not 8 <= mac_len <= 16: + raise ValueError("MAC tag must be between 8 and 16 bytes long") + + # Cache for MAC tag + self._mac_tag = None + + # Cache for unaligned associated data + self._cache_A = b"" + + # Cache for unaligned ciphertext/plaintext + self._cache_P = b"" + + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] + + # Compute Offset_0 + params_without_key = dict(cipher_params) + key = params_without_key.pop("key") + + taglen_mod128 = (self._mac_len * 8) % 128 + if len(self.nonce) < 15: + nonce = bchr(taglen_mod128 << 1) + b"\x00" * (14 - len(nonce)) + b"\x01" + self.nonce + else: + nonce = bchr((taglen_mod128 << 1) | 0x01) + self.nonce + + bottom_bits = bord(nonce[15]) & 0x3F # 6 bits, 0..63 + top_bits = bord(nonce[15]) & 0xC0 # 2 bits + + ktop_cipher = factory.new( + key, + factory.MODE_ECB, + **params_without_key, + ) + ktop = ktop_cipher.encrypt( + struct.pack( + "15sB", + nonce[:15], + top_bits, + ), + ) + + stretch = ktop + strxor(ktop[:8], ktop[1:9]) # 192 bits + offset_0 = long_to_bytes( + bytes_to_long(stretch) >> (64 - bottom_bits), + 24, + )[8:] + + # Create low-level cipher instance + raw_cipher = factory._create_base_cipher(cipher_params) + if cipher_params: + raise TypeError("Unknown keywords: " + str(cipher_params)) + + self._state = VoidPointer() + result = _raw_ocb_lib.OCB_start_operation( + raw_cipher.get(), + offset_0, + c_size_t(len(offset_0)), + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %d while instantiating the OCB mode" % result, + ) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + _raw_ocb_lib.OCB_stop_operation, + ) + + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + raw_cipher.release() + + def _update(self, assoc_data, assoc_data_len): + result = _raw_ocb_lib.OCB_update( + self._state.get(), + c_uint8_ptr(assoc_data), + c_size_t(assoc_data_len), + ) + if result: + raise ValueError("Error %d while computing MAC in OCB mode" % result) + + def update(self, assoc_data): + """Process the associated data. + + If there is any associated data, the caller has to invoke + this method one or more times, before using + ``decrypt`` or ``encrypt``. + + By *associated data* it is meant any data (e.g. packet headers) that + will not be encrypted and will be transmitted in the clear. + However, the receiver shall still able to detect modifications. + + If there is no associated data, this method must not be called. + + The caller may split associated data in segments of any size, and + invoke this method multiple times, each time with the next segment. + + :Parameters: + assoc_data : bytes/bytearray/memoryview + A piece of associated data. + """ + + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) + + self._next = [ + "encrypt", + "decrypt", + "digest", + "verify", + "update", + ] + + if len(self._cache_A) > 0: + filler = min(16 - len(self._cache_A), len(assoc_data)) + self._cache_A += _copy_bytes(None, filler, assoc_data) + assoc_data = assoc_data[filler:] + + if len(self._cache_A) < 16: + return self + + # Clear the cache, and proceeding with any other aligned data + self._cache_A, seg = b"", self._cache_A + self.update(seg) + + update_len = len(assoc_data) // 16 * 16 + self._cache_A = _copy_bytes(update_len, None, assoc_data) + self._update(assoc_data, update_len) + return self + + def _transcrypt_aligned( + self, + in_data, + in_data_len, + trans_func, + trans_desc, + ): + out_data = create_string_buffer(in_data_len) + result = trans_func( + self._state.get(), + in_data, + out_data, + c_size_t(in_data_len), + ) + if result: + raise ValueError( + "Error %d while %sing in OCB mode" % (result, trans_desc), + ) + return get_raw_buffer(out_data) + + def _transcrypt(self, in_data, trans_func, trans_desc): + # Last piece to encrypt/decrypt + if in_data is None: + out_data = self._transcrypt_aligned( + self._cache_P, + len(self._cache_P), + trans_func, + trans_desc, + ) + self._cache_P = b"" + return out_data + + # Try to fill up the cache, if it already contains something + prefix = b"" + if len(self._cache_P) > 0: + filler = min(16 - len(self._cache_P), len(in_data)) + self._cache_P += _copy_bytes(None, filler, in_data) + in_data = in_data[filler:] + + if len(self._cache_P) < 16: + # We could not manage to fill the cache, so there is certainly + # no output yet. + return b"" + + # Clear the cache, and proceeding with any other aligned data + prefix = self._transcrypt_aligned( + self._cache_P, + len(self._cache_P), + trans_func, + trans_desc, + ) + self._cache_P = b"" + + # Process data in multiples of the block size + trans_len = len(in_data) // 16 * 16 + result = self._transcrypt_aligned( + c_uint8_ptr(in_data), + trans_len, + trans_func, + trans_desc, + ) + if prefix: + result = prefix + result + + # Left-over + self._cache_P = _copy_bytes(trans_len, None, in_data) + + return result + + def encrypt(self, plaintext=None): + """Encrypt the next piece of plaintext. + + After the entire plaintext has been passed (but before `digest`), + you **must** call this method one last time with no arguments to collect + the final piece of ciphertext. + + If possible, use the method `encrypt_and_digest` instead. + + :Parameters: + plaintext : bytes/bytearray/memoryview + The next piece of data to encrypt or ``None`` to signify + that encryption has finished and that any remaining ciphertext + has to be produced. + :Return: + the ciphertext, as a byte string. + Its length may not match the length of the *plaintext*. + """ + + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) + + if plaintext is None: + self._next = ["digest"] + else: + self._next = ["encrypt"] + return self._transcrypt(plaintext, _raw_ocb_lib.OCB_encrypt, "encrypt") + + def decrypt(self, ciphertext=None): + """Decrypt the next piece of ciphertext. + + After the entire ciphertext has been passed (but before `verify`), + you **must** call this method one last time with no arguments to collect + the remaining piece of plaintext. + + If possible, use the method `decrypt_and_verify` instead. + + :Parameters: + ciphertext : bytes/bytearray/memoryview + The next piece of data to decrypt or ``None`` to signify + that decryption has finished and that any remaining plaintext + has to be produced. + :Return: + the plaintext, as a byte string. + Its length may not match the length of the *ciphertext*. + """ + + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + + if ciphertext is None: + self._next = ["verify"] + else: + self._next = ["decrypt"] + return self._transcrypt( + ciphertext, + _raw_ocb_lib.OCB_decrypt, + "decrypt", + ) + + def _compute_mac_tag(self): + if self._mac_tag is not None: + return + + if self._cache_A: + self._update(self._cache_A, len(self._cache_A)) + self._cache_A = b"" + + mac_tag = create_string_buffer(16) + result = _raw_ocb_lib.OCB_digest( + self._state.get(), + mac_tag, + c_size_t(len(mac_tag)), + ) + if result: + raise ValueError( + "Error %d while computing digest in OCB mode" % result, + ) + self._mac_tag = get_raw_buffer(mac_tag)[: self._mac_len] + + def digest(self): + """Compute the *binary* MAC tag. + + Call this method after the final `encrypt` (the one with no arguments) + to obtain the MAC tag. + + The MAC tag is needed by the receiver to determine authenticity + of the message. - assert(len(self._cache_P) == 0) + :Return: the MAC, as a byte string. + """ + + if "digest" not in self._next: + raise TypeError("digest() cannot be called now for this cipher") - self._next = ["digest"] + assert len(self._cache_P) == 0 - if self._mac_tag is None: - self._compute_mac_tag() + self._next = ["digest"] - return self._mac_tag + if self._mac_tag is None: + self._compute_mac_tag() - def hexdigest(self): - """Compute the *printable* MAC tag. + return self._mac_tag - This method is like `digest`. + def hexdigest(self): + """Compute the *printable* MAC tag. + + This method is like `digest`. - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. - Call this method after the final `decrypt` (the one with no arguments) - to check if the message is authentic and valid. + Call this method after the final `decrypt` (the one with no arguments) + to check if the message is authentic and valid. - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - if "verify" not in self._next: - raise TypeError("verify() cannot be called now for this cipher") + if "verify" not in self._next: + raise TypeError("verify() cannot be called now for this cipher") - assert(len(self._cache_P) == 0) + assert len(self._cache_P) == 0 - self._next = ["verify"] + self._next = ["verify"] - if self._mac_tag is None: - self._compute_mac_tag() + if self._mac_tag is None: + self._compute_mac_tag() - secret = get_random_bytes(16) - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + secret = get_random_bytes(16) + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. - This method is like `verify`. + This method is like `verify`. - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - self.verify(unhexlify(hex_mac_tag)) + self.verify(unhexlify(hex_mac_tag)) - def encrypt_and_digest(self, plaintext): - """Encrypt the message and create the MAC tag in one step. + def encrypt_and_digest(self, plaintext): + """Encrypt the message and create the MAC tag in one step. - :Parameters: - plaintext : bytes/bytearray/memoryview - The entire message to encrypt. - :Return: - a tuple with two byte strings: + :Parameters: + plaintext : bytes/bytearray/memoryview + The entire message to encrypt. + :Return: + a tuple with two byte strings: - - the encrypted data - - the MAC - """ + - the encrypted data + - the MAC + """ - return self.encrypt(plaintext) + self.encrypt(), self.digest() + return self.encrypt(plaintext) + self.encrypt(), self.digest() - def decrypt_and_verify(self, ciphertext, received_mac_tag): - """Decrypted the message and verify its authenticity in one step. + def decrypt_and_verify(self, ciphertext, received_mac_tag): + """Decrypted the message and verify its authenticity in one step. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The entire message to decrypt. - received_mac_tag : byte string - This is the *binary* MAC, as received from the sender. + :Parameters: + ciphertext : bytes/bytearray/memoryview + The entire message to decrypt. + received_mac_tag : byte string + This is the *binary* MAC, as received from the sender. - :Return: the decrypted data (byte string). - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Return: the decrypted data (byte string). + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - plaintext = self.decrypt(ciphertext) + self.decrypt() - self.verify(received_mac_tag) - return plaintext + plaintext = self.decrypt(ciphertext) + self.decrypt() + self.verify(received_mac_tag) + return plaintext def _create_ocb_cipher(factory, **kwargs): - """Create a new block cipher, configured in OCB mode. - - :Parameters: - factory : module - A symmetric cipher module from `Cryptodome.Cipher` - (like `Cryptodome.Cipher.AES`). - - :Keywords: - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - Its length can vary from 1 to 15 bytes. - If not specified, a random 15 bytes long nonce is generated. - - mac_len : integer - Length of the MAC, in bytes. - It must be in the range ``[8..16]``. - The default is 16 (128 bits). - - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ - - try: - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(15) - mac_len = kwargs.pop("mac_len", 16) - except KeyError as e: - raise TypeError("Keyword missing: " + str(e)) - - return OcbMode(factory, nonce, mac_len, kwargs) + """Create a new block cipher, configured in OCB mode. + + :Parameters: + factory : module + A symmetric cipher module from `Cryptodome.Cipher` + (like `Cryptodome.Cipher.AES`). + + :Keywords: + nonce : bytes/bytearray/memoryview + A value that must never be reused for any other encryption. + Its length can vary from 1 to 15 bytes. + If not specified, a random 15 bytes long nonce is generated. + + mac_len : integer + Length of the MAC, in bytes. + It must be in the range ``[8..16]``. + The default is 16 (128 bits). + + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ + + try: + nonce = kwargs.pop("nonce", None) + if nonce is None: + nonce = get_random_bytes(15) + mac_len = kwargs.pop("mac_len", 16) + except KeyError as e: + raise TypeError("Keyword missing: " + str(e)) + + return OcbMode(factory, nonce, mac_len, kwargs) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ocb.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ocb.pyi index a1909fc3..eae2f343 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ocb.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ocb.pyi @@ -1,36 +1,25 @@ from types import ModuleType -from typing import Union, Any, Optional, Tuple, Dict, overload +from typing import Union, Tuple, Dict, overload Buffer = Union[bytes, bytearray, memoryview] class OcbMode(object): - block_size: int - nonce: Buffer + block_size: int + nonce: Buffer - def __init__(self, - factory: ModuleType, - nonce: Buffer, - mac_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> OcbMode: ... - - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer) -> bytes: ... + def __init__(self, factory: ModuleType, nonce: Buffer, mac_len: int, cipher_params: Dict) -> None: ... + def update(self, assoc_data: Buffer) -> OcbMode: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + def decrypt_and_verify(self, ciphertext: Buffer, received_mac_tag: Buffer) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ofb.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ofb.py index 8c0ccf63..97c0ed8e 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ofb.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ofb.py @@ -24,17 +24,25 @@ Output Feedback (CFB) mode. """ -__all__ = ['OfbMode'] +__all__ = ["OfbMode"] from Cryptodome.Util.py3compat import _copy_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + create_string_buffer, + get_raw_buffer, + SmartPointer, + c_size_t, + c_uint8_ptr, + is_writeable_buffer, +) from Cryptodome.Random import get_random_bytes -raw_ofb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ofb", """ +raw_ofb_lib = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._raw_ofb", + """ int OFB_start_operation(void *cipher, const uint8_t iv[], size_t iv_len, @@ -48,235 +56,247 @@ uint8_t *out, size_t data_len); int OFB_stop_operation(void *state); - """ - ) + """, +) class OfbMode(object): - """*Output FeedBack (OFB)*. + """*Output FeedBack (OFB)*. - This mode is very similar to CBC, but it - transforms the underlying block cipher into a stream cipher. + This mode is very similar to CBC, but it + transforms the underlying block cipher into a stream cipher. - The keystream is the iterated block encryption of the - previous ciphertext block. + The keystream is the iterated block encryption of the + previous ciphertext block. - An Initialization Vector (*IV*) is required. + An Initialization Vector (*IV*) is required. - See `NIST SP800-38A`_ , Section 6.4. + See `NIST SP800-38A`_ , Section 6.4. - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, block_cipher, iv): - """Create a new block cipher, configured in OFB mode. + def __init__(self, block_cipher, iv): + """Create a new block cipher, configured in OFB mode. - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. + :Parameters: + block_cipher : C pointer + A smart pointer to the low-level block cipher instance. - iv : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - It is as long as the cipher block. + iv : bytes/bytearray/memoryview + The initialization vector to use for encryption or decryption. + It is as long as the cipher block. - **The IV must be a nonce, to to be reused for any other - message**. It shall be a nonce or a random value. + **The IV must be a nonce, to to be reused for any other + message**. It shall be a nonce or a random value. - Reusing the *IV* for encryptions performed with the same key - compromises confidentiality. - """ + Reusing the *IV* for encryptions performed with the same key + compromises confidentiality. + """ - self._state = VoidPointer() - result = raw_ofb_lib.OFB_start_operation(block_cipher.get(), - c_uint8_ptr(iv), - c_size_t(len(iv)), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the OFB mode" - % result) + self._state = VoidPointer() + result = raw_ofb_lib.OFB_start_operation( + block_cipher.get(), + c_uint8_ptr(iv), + c_size_t(len(iv)), + self._state.address_of(), + ) + if result: + raise ValueError( + "Error %d while instantiating the OFB mode" % result, + ) - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_ofb_lib.OFB_stop_operation) + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the cipher mode + self._state = SmartPointer( + self._state.get(), + raw_ofb_lib.OFB_stop_operation, + ) - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() + # Memory allocated for the underlying block cipher is now owed + # by the cipher mode + block_cipher.release() - self.block_size = len(iv) - """The block size of the underlying cipher, in bytes.""" + self.block_size = len(iv) + """The block size of the underlying cipher, in bytes.""" - self.iv = _copy_bytes(None, None, iv) - """The Initialization Vector originally used to create the object. + self.iv = _copy_bytes(None, None, iv) + """The Initialization Vector originally used to create the object. The value does not change.""" - self.IV = self.iv - """Alias for `iv`""" + self.IV = self.iv + """Alias for `iv`""" - self._next = ["encrypt", "decrypt"] + self._next = ["encrypt", "decrypt"] - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. + def encrypt(self, plaintext, output=None): + """Encrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.encrypt(a) + c.encrypt(b) + >>> c.encrypt(a) + c.encrypt(b) - is equivalent to: + is equivalent to: - >>> c.encrypt(a+b) + >>> c.encrypt(a+b) - This function does not add any padding to the plaintext. + This function does not add any padding to the plaintext. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + If ``output`` is ``None``, the ciphertext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = ["encrypt"] + if "encrypt" not in self._next: + raise TypeError("encrypt() cannot be called after decrypt()") + self._next = ["encrypt"] - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output + if output is None: + ciphertext = create_string_buffer(len(plaintext)) + else: + ciphertext = output - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) + if len(plaintext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) - result = raw_ofb_lib.OFB_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting in OFB mode" % result) + result = raw_ofb_lib.OFB_encrypt( + self._state.get(), + c_uint8_ptr(plaintext), + c_uint8_ptr(ciphertext), + c_size_t(len(plaintext)), + ) + if result: + raise ValueError("Error %d while encrypting in OFB mode" % result) - if output is None: - return get_raw_buffer(ciphertext) - else: - return None + if output is None: + return get_raw_buffer(ciphertext) + else: + return None - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. + def decrypt(self, ciphertext, output=None): + """Decrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.decrypt(a) + c.decrypt(b) + >>> c.decrypt(a) + c.decrypt(b) - is equivalent to: + is equivalent to: - >>> c.decrypt(a+b) + >>> c.decrypt(a+b) - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext is written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + :Keywords: + output : bytearray/memoryview + The location where the plaintext is written to. + If ``None``, the plaintext is returned. + :Return: + If ``output`` is ``None``, the plaintext is returned as ``bytes``. + Otherwise, ``None``. + """ - if "decrypt" not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = ["decrypt"] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ofb_lib.OFB_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - raise ValueError("Error %d while decrypting in OFB mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None + if "decrypt" not in self._next: + raise TypeError("decrypt() cannot be called after encrypt()") + self._next = ["decrypt"] + + if output is None: + plaintext = create_string_buffer(len(ciphertext)) + else: + plaintext = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(ciphertext) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(plaintext), + ) + + result = raw_ofb_lib.OFB_decrypt( + self._state.get(), + c_uint8_ptr(ciphertext), + c_uint8_ptr(plaintext), + c_size_t(len(ciphertext)), + ) + if result: + raise ValueError("Error %d while decrypting in OFB mode" % result) + + if output is None: + return get_raw_buffer(plaintext) + else: + return None def _create_ofb_cipher(factory, **kwargs): - """Instantiate a cipher object that performs OFB encryption/decryption. + """Instantiate a cipher object that performs OFB encryption/decryption. - :Parameters: - factory : module - The underlying block cipher, a module from ``Cryptodome.Cipher``. + :Parameters: + factory : module + The underlying block cipher, a module from ``Cryptodome.Cipher``. - :Keywords: - iv : bytes/bytearray/memoryview - The IV to use for OFB. + :Keywords: + iv : bytes/bytearray/memoryview + The IV to use for OFB. - IV : bytes/bytearray/memoryview - Alias for ``iv``. + IV : bytes/bytearray/memoryview + Alias for ``iv``. - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ + Any other keyword will be passed to the underlying block cipher. + See the relevant documentation for details (at least ``key`` will need + to be present). + """ - cipher_state = factory._create_base_cipher(kwargs) - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) + cipher_state = factory._create_base_cipher(kwargs) + iv = kwargs.pop("IV", None) + IV = kwargs.pop("iv", None) - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV + if (None, None) == (iv, IV): + iv = get_random_bytes(factory.block_size) + if iv is not None: + if IV is not None: + raise TypeError("You must either use 'iv' or 'IV', not both") + else: + iv = IV - if len(iv) != factory.block_size: - raise ValueError("Incorrect IV length (it must be %d bytes long)" % - factory.block_size) + if len(iv) != factory.block_size: + raise ValueError( + "Incorrect IV length (it must be %d bytes long)" % factory.block_size, + ) - if kwargs: - raise TypeError("Unknown parameters for OFB: %s" % str(kwargs)) + if kwargs: + raise TypeError("Unknown parameters for OFB: %s" % str(kwargs)) - return OfbMode(cipher_state, iv) + return OfbMode(cipher_state, iv) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ofb.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ofb.pyi index d28608ec..2988e240 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ofb.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_ofb.pyi @@ -4,22 +4,19 @@ from Cryptodome.Util._raw_api import SmartPointer Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['OfbMode'] +__all__ = ["OfbMode"] class OfbMode(object): - block_size: int - iv: Buffer - IV: Buffer - - def __init__(self, - block_cipher: SmartPointer, - iv: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + block_size: int + iv: Buffer + IV: Buffer + def __init__(self, block_cipher: SmartPointer, iv: Buffer) -> None: ... + @overload + def encrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... + @overload + def decrypt(self, plaintext: Buffer) -> bytes: ... + @overload + def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_openpgp.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_openpgp.py index d86ed19a..f55a3821 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_openpgp.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_openpgp.py @@ -32,175 +32,178 @@ OpenPGP mode. """ -__all__ = ['OpenPgpMode'] +__all__ = ["OpenPgpMode"] from Cryptodome.Util.py3compat import _copy_bytes from Cryptodome.Random import get_random_bytes -class OpenPgpMode(object): - """OpenPGP mode. - This mode is a variant of CFB, and it is only used in PGP and - OpenPGP_ applications. If in doubt, use another mode. +class OpenPgpMode(object): + """OpenPGP mode. - An Initialization Vector (*IV*) is required. + This mode is a variant of CFB, and it is only used in PGP and + OpenPGP_ applications. If in doubt, use another mode. - Unlike CFB, the *encrypted* IV (not the IV itself) is - transmitted to the receiver. + An Initialization Vector (*IV*) is required. - The IV is a random data block. For legacy reasons, two of its bytes are - duplicated to act as a checksum for the correctness of the key, which is now - known to be insecure and is ignored. The encrypted IV is therefore 2 bytes - longer than the clean IV. + Unlike CFB, the *encrypted* IV (not the IV itself) is + transmitted to the receiver. - .. _OpenPGP: http://tools.ietf.org/html/rfc4880 + The IV is a random data block. For legacy reasons, two of its bytes are + duplicated to act as a checksum for the correctness of the key, which is now + known to be insecure and is ignored. The encrypted IV is therefore 2 bytes + longer than the clean IV. - :undocumented: __init__ - """ + .. _OpenPGP: http://tools.ietf.org/html/rfc4880 - def __init__(self, factory, key, iv, cipher_params): + :undocumented: __init__ + """ - #: The block size of the underlying cipher, in bytes. - self.block_size = factory.block_size + def __init__(self, factory, key, iv, cipher_params): + #: The block size of the underlying cipher, in bytes. + self.block_size = factory.block_size - self._done_first_block = False # True after the first encryption + self._done_first_block = False # True after the first encryption - # Instantiate a temporary cipher to process the IV - IV_cipher = factory.new( - key, - factory.MODE_CFB, - IV=b'\x00' * self.block_size, - segment_size=self.block_size * 8, - **cipher_params) + # Instantiate a temporary cipher to process the IV + IV_cipher = factory.new( + key, + factory.MODE_CFB, + IV=b"\x00" * self.block_size, + segment_size=self.block_size * 8, + **cipher_params, + ) - iv = _copy_bytes(None, None, iv) + iv = _copy_bytes(None, None, iv) - # The cipher will be used for... - if len(iv) == self.block_size: - # ... encryption - self._encrypted_IV = IV_cipher.encrypt(iv + iv[-2:]) - elif len(iv) == self.block_size + 2: - # ... decryption - self._encrypted_IV = iv - # Last two bytes are for a deprecated "quick check" feature that - # should not be used. (https://eprint.iacr.org/2005/033) - iv = IV_cipher.decrypt(iv)[:-2] - else: - raise ValueError("Length of IV must be %d or %d bytes" - " for MODE_OPENPGP" - % (self.block_size, self.block_size + 2)) + # The cipher will be used for... + if len(iv) == self.block_size: + # ... encryption + self._encrypted_IV = IV_cipher.encrypt(iv + iv[-2:]) + elif len(iv) == self.block_size + 2: + # ... decryption + self._encrypted_IV = iv + # Last two bytes are for a deprecated "quick check" feature that + # should not be used. (https://eprint.iacr.org/2005/033) + iv = IV_cipher.decrypt(iv)[:-2] + else: + raise ValueError( + "Length of IV must be %d or %d bytes" + " for MODE_OPENPGP" % (self.block_size, self.block_size + 2), + ) - self.iv = self.IV = iv + self.iv = self.IV = iv - # Instantiate the cipher for the real PGP data - self._cipher = factory.new( - key, - factory.MODE_CFB, - IV=self._encrypted_IV[-self.block_size:], - segment_size=self.block_size * 8, - **cipher_params) + # Instantiate the cipher for the real PGP data + self._cipher = factory.new( + key, + factory.MODE_CFB, + IV=self._encrypted_IV[-self.block_size :], + segment_size=self.block_size * 8, + **cipher_params, + ) - def encrypt(self, plaintext): - """Encrypt data with the key and the parameters set at initialization. + def encrypt(self, plaintext): + """Encrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. + The data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.encrypt(a) + c.encrypt(b) + >>> c.encrypt(a) + c.encrypt(b) - is equivalent to: + is equivalent to: - >>> c.encrypt(a+b) + >>> c.encrypt(a+b) - This function does not add any padding to the plaintext. + This function does not add any padding to the plaintext. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. - :Return: - the encrypted data, as a byte string. - It is as long as *plaintext* with one exception: - when encrypting the first message chunk, - the encypted IV is prepended to the returned ciphertext. - """ + :Return: + the encrypted data, as a byte string. + It is as long as *plaintext* with one exception: + when encrypting the first message chunk, + the encypted IV is prepended to the returned ciphertext. + """ - res = self._cipher.encrypt(plaintext) - if not self._done_first_block: - res = self._encrypted_IV + res - self._done_first_block = True - return res + res = self._cipher.encrypt(plaintext) + if not self._done_first_block: + res = self._encrypted_IV + res + self._done_first_block = True + return res - def decrypt(self, ciphertext): - """Decrypt data with the key and the parameters set at initialization. + def decrypt(self, ciphertext): + """Decrypt data with the key and the parameters set at initialization. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. + The data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. - That is, the statement: + That is, the statement: - >>> c.decrypt(a) + c.decrypt(b) + >>> c.decrypt(a) + c.decrypt(b) - is equivalent to: + is equivalent to: - >>> c.decrypt(a+b) + >>> c.decrypt(a+b) - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. - :Return: the decrypted data (byte string). - """ + :Return: the decrypted data (byte string). + """ - return self._cipher.decrypt(ciphertext) + return self._cipher.decrypt(ciphertext) def _create_openpgp_cipher(factory, **kwargs): - """Create a new block cipher, configured in OpenPGP mode. + """Create a new block cipher, configured in OpenPGP mode. - :Parameters: - factory : module - The module. + :Parameters: + factory : module + The module. - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. + :Keywords: + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. - IV : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. + IV : bytes/bytearray/memoryview + The initialization vector to use for encryption or decryption. - For encryption, the IV must be as long as the cipher block size. + For encryption, the IV must be as long as the cipher block size. - For decryption, it must be 2 bytes longer (it is actually the - *encrypted* IV which was prefixed to the ciphertext). - """ + For decryption, it must be 2 bytes longer (it is actually the + *encrypted* IV which was prefixed to the ciphertext). + """ - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) + iv = kwargs.pop("IV", None) + IV = kwargs.pop("iv", None) - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV + if (None, None) == (iv, IV): + iv = get_random_bytes(factory.block_size) + if iv is not None: + if IV is not None: + raise TypeError("You must either use 'iv' or 'IV', not both") + else: + iv = IV - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing component: " + str(e)) + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing component: " + str(e)) - return OpenPgpMode(factory, key, iv, kwargs) + return OpenPgpMode(factory, key, iv, kwargs) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_openpgp.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_openpgp.pyi index 14b81058..79b85e05 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_openpgp.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_openpgp.pyi @@ -3,18 +3,13 @@ from typing import Union, Dict Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['OpenPgpMode'] +__all__ = ["OpenPgpMode"] class OpenPgpMode(object): - block_size: int - iv: Union[bytes, bytearray, memoryview] - IV: Union[bytes, bytearray, memoryview] - - def __init__(self, - factory: ModuleType, - key: Buffer, - iv: Buffer, - cipher_params: Dict) -> None: ... - def encrypt(self, plaintext: Buffer) -> bytes: ... - def decrypt(self, plaintext: Buffer) -> bytes: ... + block_size: int + iv: Union[bytes, bytearray, memoryview] + IV: Union[bytes, bytearray, memoryview] + def __init__(self, factory: ModuleType, key: Buffer, iv: Buffer, cipher_params: Dict) -> None: ... + def encrypt(self, plaintext: Buffer) -> bytes: ... + def decrypt(self, plaintext: Buffer) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_siv.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_siv.py index 4a76ad6d..b5a3aba5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_siv.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_siv.py @@ -32,361 +32,380 @@ Synthetic Initialization Vector (SIV) mode. """ -__all__ = ['SivMode'] +__all__ = ["SivMode"] -from binascii import hexlify, unhexlify +from binascii import unhexlify from Cryptodome.Util.py3compat import bord, _copy_bytes from Cryptodome.Util._raw_api import is_buffer -from Cryptodome.Util.number import long_to_bytes, bytes_to_long +from Cryptodome.Util.number import bytes_to_long from Cryptodome.Protocol.KDF import _S2V from Cryptodome.Hash import BLAKE2s from Cryptodome.Random import get_random_bytes class SivMode(object): - """Synthetic Initialization Vector (SIV). + """Synthetic Initialization Vector (SIV). - This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. - It provides both confidentiality and authenticity. + This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. + It provides both confidentiality and authenticity. - The header of the message may be left in the clear, if needed, and it will - still be subject to authentication. The decryption step tells the receiver - if the message comes from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - including the - header - has been modified or corrupted. + The header of the message may be left in the clear, if needed, and it will + still be subject to authentication. The decryption step tells the receiver + if the message comes from a source that really knowns the secret key. + Additionally, decryption detects if any part of the message - including the + header - has been modified or corrupted. - Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a - nonce is not catastrophic for the confidentiality of the message. The only - effect is that an attacker can tell when the same plaintext (and same - associated data) is protected with the same key. + Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a + nonce is not catastrophic for the confidentiality of the message. The only + effect is that an attacker can tell when the same plaintext (and same + associated data) is protected with the same key. - The length of the MAC is fixed to the block size of the underlying cipher. - The key size is twice the length of the key of the underlying cipher. + The length of the MAC is fixed to the block size of the underlying cipher. + The key size is twice the length of the key of the underlying cipher. - This mode is only available for AES ciphers. + This mode is only available for AES ciphers. - +--------------------+---------------+-------------------+ - | Cipher | SIV MAC size | SIV key length | - | | (bytes) | (bytes) | - +====================+===============+===================+ - | AES-128 | 16 | 32 | - +--------------------+---------------+-------------------+ - | AES-192 | 16 | 48 | - +--------------------+---------------+-------------------+ - | AES-256 | 16 | 64 | - +--------------------+---------------+-------------------+ + +--------------------+---------------+-------------------+ + | Cipher | SIV MAC size | SIV key length | + | | (bytes) | (bytes) | + +====================+===============+===================+ + | AES-128 | 16 | 32 | + +--------------------+---------------+-------------------+ + | AES-192 | 16 | 48 | + +--------------------+---------------+-------------------+ + | AES-256 | 16 | 64 | + +--------------------+---------------+-------------------+ - See `RFC5297`_ and the `original paper`__. + See `RFC5297`_ and the `original paper`__. - .. _RFC5297: https://tools.ietf.org/html/rfc5297 - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf + .. _RFC5297: https://tools.ietf.org/html/rfc5297 + .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html + .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf - :undocumented: __init__ - """ + :undocumented: __init__ + """ - def __init__(self, factory, key, nonce, kwargs): + def __init__(self, factory, key, nonce, kwargs): + self.block_size = factory.block_size + """The block size of the underlying cipher, in bytes.""" - self.block_size = factory.block_size - """The block size of the underlying cipher, in bytes.""" + self._factory = factory - self._factory = factory + self._cipher_params = kwargs - self._cipher_params = kwargs + if len(key) not in (32, 48, 64): + raise ValueError("Incorrect key length (%d bytes)" % len(key)) - if len(key) not in (32, 48, 64): - raise ValueError("Incorrect key length (%d bytes)" % len(key)) + if nonce is not None: + if not is_buffer(nonce): + raise TypeError("When provided, the nonce must be bytes, bytearray or memoryview") - if nonce is not None: - if not is_buffer(nonce): - raise TypeError("When provided, the nonce must be bytes, bytearray or memoryview") + if len(nonce) == 0: + raise ValueError("When provided, the nonce must be non-empty") - if len(nonce) == 0: - raise ValueError("When provided, the nonce must be non-empty") - - self.nonce = _copy_bytes(None, None, nonce) - """Public attribute is only available in case of non-deterministic + self.nonce = _copy_bytes(None, None, nonce) + """Public attribute is only available in case of non-deterministic encryption.""" - subkey_size = len(key) // 2 - - self._mac_tag = None # Cache for MAC tag - self._kdf = _S2V(key[:subkey_size], - ciphermod=factory, - cipher_params=self._cipher_params) - self._subkey_cipher = key[subkey_size:] - - # Purely for the purpose of verifying that cipher_params are OK - factory.new(key[:subkey_size], factory.MODE_ECB, **kwargs) - - # Allowed transitions after initialization - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] - - def _create_ctr_cipher(self, v): - """Create a new CTR cipher from V in SIV mode""" - - v_int = bytes_to_long(v) - q = v_int & 0xFFFFFFFFFFFFFFFF7FFFFFFF7FFFFFFF - return self._factory.new( - self._subkey_cipher, - self._factory.MODE_CTR, - initial_value=q, - nonce=b"", - **self._cipher_params) - - def update(self, component): - """Protect one associated data component + subkey_size = len(key) // 2 - For SIV, the associated data is a sequence (*vector*) of non-empty - byte strings (*components*). + self._mac_tag = None # Cache for MAC tag + self._kdf = _S2V( + key[:subkey_size], + ciphermod=factory, + cipher_params=self._cipher_params, + ) + self._subkey_cipher = key[subkey_size:] - This method consumes the next component. It must be called - once for each of the components that constitue the associated data. + # Purely for the purpose of verifying that cipher_params are OK + factory.new(key[:subkey_size], factory.MODE_ECB, **kwargs) - Note that the components have clear boundaries, so that: + # Allowed transitions after initialization + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] - >>> cipher.update(b"builtin") - >>> cipher.update(b"securely") + def _create_ctr_cipher(self, v): + """Create a new CTR cipher from V in SIV mode""" - is not equivalent to: + v_int = bytes_to_long(v) + q = v_int & 0xFFFFFFFFFFFFFFFF7FFFFFFF7FFFFFFF + return self._factory.new( + self._subkey_cipher, + self._factory.MODE_CTR, + initial_value=q, + nonce=b"", + **self._cipher_params, + ) - >>> cipher.update(b"built") - >>> cipher.update(b"insecurely") + def update(self, component): + """Protect one associated data component - If there is no associated data, this method must not be called. + For SIV, the associated data is a sequence (*vector*) of non-empty + byte strings (*components*). - :Parameters: - component : bytes/bytearray/memoryview - The next associated data component. - """ + This method consumes the next component. It must be called + once for each of the components that constitue the associated data. - if "update" not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") + Note that the components have clear boundaries, so that: - self._next = ["update", "encrypt", "decrypt", - "digest", "verify"] + >>> cipher.update(b"builtin") + >>> cipher.update(b"securely") - return self._kdf.update(component) + is not equivalent to: + + >>> cipher.update(b"built") + >>> cipher.update(b"insecurely") - def encrypt(self, plaintext): - """ - For SIV, encryption and MAC authentication must take place at the same - point. This method shall not be used. + If there is no associated data, this method must not be called. - Use `encrypt_and_digest` instead. - """ + :Parameters: + component : bytes/bytearray/memoryview + The next associated data component. + """ - raise TypeError("encrypt() not allowed for SIV mode." - " Use encrypt_and_digest() instead.") + if "update" not in self._next: + raise TypeError( + "update() can only be called immediately after initialization", + ) - def decrypt(self, ciphertext): - """ - For SIV, decryption and verification must take place at the same - point. This method shall not be used. + self._next = [ + "update", + "encrypt", + "decrypt", + "digest", + "verify", + ] - Use `decrypt_and_verify` instead. - """ + return self._kdf.update(component) - raise TypeError("decrypt() not allowed for SIV mode." - " Use decrypt_and_verify() instead.") + def encrypt(self, plaintext): + """ + For SIV, encryption and MAC authentication must take place at the same + point. This method shall not be used. - def digest(self): - """Compute the *binary* MAC tag. + Use `encrypt_and_digest` instead. + """ - The caller invokes this function at the very end. + raise TypeError( + "encrypt() not allowed for SIV mode. Use encrypt_and_digest() instead.", + ) - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. + def decrypt(self, ciphertext): + """ + For SIV, decryption and verification must take place at the same + point. This method shall not be used. - :Return: the MAC, as a byte string. - """ + Use `decrypt_and_verify` instead. + """ - if "digest" not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = ["digest"] - if self._mac_tag is None: - self._mac_tag = self._kdf.derive() - return self._mac_tag + raise TypeError( + "decrypt() not allowed for SIV mode. Use decrypt_and_verify() instead.", + ) - def hexdigest(self): - """Compute the *printable* MAC tag. + def digest(self): + """Compute the *binary* MAC tag. + + The caller invokes this function at the very end. - This method is like `digest`. + This method returns the MAC that shall be sent to the receiver, + together with the ciphertext. - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) + :Return: the MAC, as a byte string. + """ - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. + if "digest" not in self._next: + raise TypeError( + "digest() cannot be called when decrypting or validating a message", + ) + self._next = ["digest"] + if self._mac_tag is None: + self._mac_tag = self._kdf.derive() + return self._mac_tag - The caller invokes this function at the very end. + def hexdigest(self): + """Compute the *printable* MAC tag. - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. + This method is like `digest`. - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) - if "verify" not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = ["verify"] + def verify(self, received_mac_tag): + """Validate the *binary* MAC tag. - if self._mac_tag is None: - self._mac_tag = self._kdf.derive() + The caller invokes this function at the very end. - secret = get_random_bytes(16) + This method checks if the decrypted message is indeed valid + (that is, if the key is correct) and it has not been + tampered with while in transit. - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + :Parameters: + received_mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + if "verify" not in self._next: + raise TypeError( + "verify() cannot be called when encrypting a message", + ) + self._next = ["verify"] + + if self._mac_tag is None: + self._mac_tag = self._kdf.derive() + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag. - This method is like `verify`. + This method is like `verify`. - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - self.verify(unhexlify(hex_mac_tag)) + self.verify(unhexlify(hex_mac_tag)) - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. + def encrypt_and_digest(self, plaintext, output=None): + """Perform encrypt() and digest() in one step. - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: + :Parameters: + plaintext : bytes/bytearray/memoryview + The piece of data to encrypt. + :Keywords: + output : bytearray/memoryview + The location where the ciphertext must be written to. + If ``None``, the ciphertext is returned. + :Return: + a tuple with two items: - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` + - the ciphertext, as ``bytes`` + - the MAC tag, as ``bytes`` - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ + The first item becomes ``None`` when the ``output`` parameter + specified a location for the result. + """ - if "encrypt" not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") + if "encrypt" not in self._next: + raise TypeError( + "encrypt() can only be called after initialization or an update()", + ) - self._next = ["digest"] + self._next = ["digest"] - # Compute V (MAC) - if hasattr(self, 'nonce'): - self._kdf.update(self.nonce) - self._kdf.update(plaintext) - self._mac_tag = self._kdf.derive() + # Compute V (MAC) + if hasattr(self, "nonce"): + self._kdf.update(self.nonce) + self._kdf.update(plaintext) + self._mac_tag = self._kdf.derive() - cipher = self._create_ctr_cipher(self._mac_tag) + cipher = self._create_ctr_cipher(self._mac_tag) - return cipher.encrypt(plaintext, output=output), self._mac_tag + return cipher.encrypt(plaintext, output=output), self._mac_tag - def decrypt_and_verify(self, ciphertext, mac_tag, output=None): - """Perform decryption and verification in one step. + def decrypt_and_verify(self, ciphertext, mac_tag, output=None): + """Perform decryption and verification in one step. - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. - You cannot reuse an object for encrypting - or decrypting other data with the same key. + You cannot reuse an object for encrypting + or decrypting other data with the same key. - This function does not remove any padding from the plaintext. + This function does not remove any padding from the plaintext. - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ + :Parameters: + ciphertext : bytes/bytearray/memoryview + The piece of data to decrypt. + It can be of any length. + mac_tag : bytes/bytearray/memoryview + This is the *binary* MAC, as received from the sender. + :Keywords: + output : bytearray/memoryview + The location where the plaintext must be written to. + If ``None``, the plaintext is returned. + :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` + parameter specified a location for the result. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ - if "decrypt" not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = ["verify"] + if "decrypt" not in self._next: + raise TypeError( + "decrypt() can only be called after initialization or an update()", + ) + self._next = ["verify"] - # Take the MAC and start the cipher for decryption - self._cipher = self._create_ctr_cipher(mac_tag) + # Take the MAC and start the cipher for decryption + self._cipher = self._create_ctr_cipher(mac_tag) - plaintext = self._cipher.decrypt(ciphertext, output=output) + plaintext = self._cipher.decrypt(ciphertext, output=output) - if hasattr(self, 'nonce'): - self._kdf.update(self.nonce) - self._kdf.update(plaintext if output is None else output) - self.verify(mac_tag) + if hasattr(self, "nonce"): + self._kdf.update(self.nonce) + self._kdf.update(plaintext if output is None else output) + self.verify(mac_tag) - return plaintext + return plaintext def _create_siv_cipher(factory, **kwargs): - """Create a new block cipher, configured in - Synthetic Initializaton Vector (SIV) mode. + """Create a new block cipher, configured in + Synthetic Initializaton Vector (SIV) mode. - :Parameters: + :Parameters: - factory : object - A symmetric cipher module from `Cryptodome.Cipher` - (like `Cryptodome.Cipher.AES`). + factory : object + A symmetric cipher module from `Cryptodome.Cipher` + (like `Cryptodome.Cipher.AES`). - :Keywords: + :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - It must be 32, 48 or 64 bytes long. - If AES is the chosen cipher, the variants *AES-128*, - *AES-192* and or *AES-256* will be used internally. + key : bytes/bytearray/memoryview + The secret key to use in the symmetric cipher. + It must be 32, 48 or 64 bytes long. + If AES is the chosen cipher, the variants *AES-128*, + *AES-192* and or *AES-256* will be used internally. - nonce : bytes/bytearray/memoryview - For deterministic encryption, it is not present. + nonce : bytes/bytearray/memoryview + For deterministic encryption, it is not present. - Otherwise, it is a value that must never be reused - for encrypting message under this key. + Otherwise, it is a value that must never be reused + for encrypting message under this key. - There are no restrictions on its length, - but it is recommended to use at least 16 bytes. - """ + There are no restrictions on its length, + but it is recommended to use at least 16 bytes. + """ - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter: " + str(e)) + try: + key = kwargs.pop("key") + except KeyError as e: + raise TypeError("Missing parameter: " + str(e)) - nonce = kwargs.pop("nonce", None) + nonce = kwargs.pop("nonce", None) - return SivMode(factory, key, nonce, kwargs) + return SivMode(factory, key, nonce, kwargs) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_siv.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_siv.pyi index 2934f23d..afaf9cc4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_siv.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_mode_siv.pyi @@ -3,36 +3,27 @@ from typing import Union, Tuple, Dict, Optional, overload Buffer = Union[bytes, bytearray, memoryview] -__all__ = ['SivMode'] +__all__ = ["SivMode"] class SivMode(object): - block_size: int - nonce: bytes - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - kwargs: Dict) -> None: ... - - def update(self, component: Buffer) -> SivMode: ... + block_size: int + nonce: bytes - def encrypt(self, plaintext: Buffer) -> bytes: ... - def decrypt(self, plaintext: Buffer) -> bytes: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... + def __init__(self, factory: ModuleType, key: Buffer, nonce: Buffer, kwargs: Dict) -> None: ... + def update(self, component: Buffer) -> SivMode: ... + def encrypt(self, plaintext: Buffer) -> bytes: ... + def decrypt(self, plaintext: Buffer) -> bytes: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, received_mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... + @overload + def encrypt_and_digest(self, plaintext: Buffer, output: Buffer) -> Tuple[None, bytes]: ... + def decrypt_and_verify( + self, + ciphertext: Buffer, + received_mac_tag: Buffer, + output: Optional[Union[bytearray, memoryview]] = ..., + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_pkcs1_oaep_decode.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_pkcs1_oaep_decode.py index 82bdaa74..25747893 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_pkcs1_oaep_decode.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Cipher/_pkcs1_oaep_decode.py @@ -1,9 +1,13 @@ -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + c_size_t, + c_uint8_ptr, +) -_raw_pkcs1_decode = load_pycryptodome_raw_lib("Cryptodome.Cipher._pkcs1_decode", - """ +_raw_pkcs1_decode = load_pycryptodome_raw_lib( + "Cryptodome.Cipher._pkcs1_decode", + """ int pkcs1_decode(const uint8_t *em, size_t len_em, const uint8_t *sentinel, size_t len_sentinel, size_t expected_pt_len, @@ -15,27 +19,32 @@ size_t hLen, const uint8_t *db, size_t db_len); - """) + """, +) def pkcs1_decode(em, sentinel, expected_pt_len, output): - if len(em) != len(output): - raise ValueError("Incorrect output length") + if len(em) != len(output): + raise ValueError("Incorrect output length") - ret = _raw_pkcs1_decode.pkcs1_decode(c_uint8_ptr(em), - c_size_t(len(em)), - c_uint8_ptr(sentinel), - c_size_t(len(sentinel)), - c_size_t(expected_pt_len), - c_uint8_ptr(output)) - return ret + ret = _raw_pkcs1_decode.pkcs1_decode( + c_uint8_ptr(em), + c_size_t(len(em)), + c_uint8_ptr(sentinel), + c_size_t(len(sentinel)), + c_size_t(expected_pt_len), + c_uint8_ptr(output), + ) + return ret def oaep_decode(em, lHash, db): - ret = _raw_pkcs1_decode.oaep_decode(c_uint8_ptr(em), - c_size_t(len(em)), - c_uint8_ptr(lHash), - c_size_t(len(lHash)), - c_uint8_ptr(db), - c_size_t(len(db))) - return ret + ret = _raw_pkcs1_decode.oaep_decode( + c_uint8_ptr(em), + c_size_t(len(em)), + c_uint8_ptr(lHash), + c_size_t(len(lHash)), + c_uint8_ptr(db), + c_size_t(len(db)), + ) + return ret diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2b.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2b.py index 85da8877..d0347cb1 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2b.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2b.py @@ -33,14 +33,19 @@ from Cryptodome.Util.py3compat import bord, tobytes from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_blake2b_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._BLAKE2b", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_blake2b_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._BLAKE2b", + """ int blake2b_init(void **state, const uint8_t *key, size_t key_size, @@ -52,196 +57,198 @@ int blake2b_digest(const void *state, uint8_t digest[64]); int blake2b_copy(const void *src, void *dst); - """) + """, +) class BLAKE2b_Hash(object): - """A BLAKE2b hash object. - Do not instantiate directly. Use the :func:`new` function. + """A BLAKE2b hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The internal block size of the hash algorithm in bytes. + block_size = 64 + + def __init__(self, data, key, digest_bytes, update_after_digest): + # The size of the resulting hash in bytes. + self.digest_size = digest_bytes + + self._update_after_digest = update_after_digest + self._digest_done = False + + # See https://tools.ietf.org/html/rfc7693 + if digest_bytes in (20, 32, 48, 64) and not key: + self.oid = "1.3.6.1.4.1.1722.12.2.1." + str(digest_bytes) + + state = VoidPointer() + result = _raw_blake2b_lib.blake2b_init( + state.address_of(), + c_uint8_ptr(key), + c_size_t(len(key)), + c_size_t(digest_bytes), + ) + if result: + raise ValueError("Error %d while instantiating BLAKE2b" % result) + self._state = SmartPointer( + state.get(), + _raw_blake2b_lib.blake2b_destroy, + ) + if data: + self.update(data) - :ivar oid: ASN.1 Object ID - :vartype oid: string + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer + Args: + data (bytes/bytearray/memoryview): The next chunk of the message being hashed. + """ - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - # The internal block size of the hash algorithm in bytes. - block_size = 64 + result = _raw_blake2b_lib.blake2b_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError("Error %d while hashing BLAKE2b data" % result) + return self - def __init__(self, data, key, digest_bytes, update_after_digest): + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. - # The size of the resulting hash in bytes. - self.digest_size = digest_bytes + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ - self._update_after_digest = update_after_digest - self._digest_done = False + bfr = create_string_buffer(64) + result = _raw_blake2b_lib.blake2b_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError("Error %d while creating BLAKE2b digest" % result) - # See https://tools.ietf.org/html/rfc7693 - if digest_bytes in (20, 32, 48, 64) and not key: - self.oid = "1.3.6.1.4.1.1722.12.2.1." + str(digest_bytes) + self._digest_done = True - state = VoidPointer() - result = _raw_blake2b_lib.blake2b_init(state.address_of(), - c_uint8_ptr(key), - c_size_t(len(key)), - c_size_t(digest_bytes) - ) - if result: - raise ValueError("Error %d while instantiating BLAKE2b" % result) - self._state = SmartPointer(state.get(), - _raw_blake2b_lib.blake2b_destroy) - if data: - self.update(data) + return get_raw_buffer(bfr)[: self.digest_size] + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ - Args: - data (bytes/bytearray/memoryview): The next chunk of the message being hashed. - """ + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. - result = _raw_blake2b_lib.blake2b_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing BLAKE2b data" % result) - return self + Args: + mac_tag (bytes/bytearray/memoryview): the expected MAC of the message. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. + secret = get_random_bytes(16) - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ + mac1 = new(digest_bits=160, key=secret, data=mac_tag) + mac2 = new(digest_bits=160, key=secret, data=self.digest()) - bfr = create_string_buffer(64) - result = _raw_blake2b_lib.blake2b_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while creating BLAKE2b digest" % result) + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - self._digest_done = True + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. - return get_raw_buffer(bfr)[:self.digest_size] + Args: + hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. + self.verify(unhexlify(tobytes(hex_mac_tag))) - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ + def new(self, **kwargs): + """Return a new instance of a BLAKE2b hash object. + See :func:`new`. + """ - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: + kwargs["digest_bytes"] = self.digest_size - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (bytes/bytearray/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = new(digest_bits=160, key=secret, data=mac_tag) - mac2 = new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - - def new(self, **kwargs): - """Return a new instance of a BLAKE2b hash object. - See :func:`new`. - """ - - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) + return new(**kwargs) def new(**kwargs): - """Create a new hash object. - - Args: - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`BLAKE2b_Hash.update`. - digest_bytes (integer): - Optional. The size of the digest, in bytes (1 to 64). Default is 64. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (8 to 512, in steps of 8). - Default is 512. - key (bytes/bytearray/memoryview): - Optional. The key to use to compute the MAC (1 to 64 bytes). - If not specified, no key will be used. - update_after_digest (boolean): - Optional. By default, a hash object cannot be updated anymore after - the digest is computed. When this flag is ``True``, such check - is no longer enforced. - - Returns: - A :class:`BLAKE2b_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 64 - if digest_bytes is not None: - if not (1 <= digest_bytes <= 64): - raise ValueError("'digest_bytes' not in range 1..64") - else: - if not (8 <= digest_bits <= 512) or (digest_bits % 8): - raise ValueError("'digest_bits' not in range 8..512, " - "with steps of 8") - digest_bytes = digest_bits // 8 - - key = kwargs.pop("key", b"") - if len(key) > 64: - raise ValueError("BLAKE2b key cannot exceed 64 bytes") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest) + """Create a new hash object. + + Args: + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`BLAKE2b_Hash.update`. + digest_bytes (integer): + Optional. The size of the digest, in bytes (1 to 64). Default is 64. + digest_bits (integer): + Optional and alternative to ``digest_bytes``. + The size of the digest, in bits (8 to 512, in steps of 8). + Default is 512. + key (bytes/bytearray/memoryview): + Optional. The key to use to compute the MAC (1 to 64 bytes). + If not specified, no key will be used. + update_after_digest (boolean): + Optional. By default, a hash object cannot be updated anymore after + the digest is computed. When this flag is ``True``, such check + is no longer enforced. + + Returns: + A :class:`BLAKE2b_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + digest_bytes = 64 + if digest_bytes is not None: + if not (1 <= digest_bytes <= 64): + raise ValueError("'digest_bytes' not in range 1..64") + else: + if not (8 <= digest_bits <= 512) or (digest_bits % 8): + raise ValueError( + "'digest_bits' not in range 8..512, with steps of 8", + ) + digest_bytes = digest_bits // 8 + + key = kwargs.pop("key", b"") + if len(key) > 64: + raise ValueError("BLAKE2b key cannot exceed 64 bytes") + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2b.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2b.pyi index d37c3749..9fde522a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2b.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2b.pyi @@ -1,32 +1,31 @@ -from typing import Any, Union -from types import ModuleType +from typing import Union Buffer = Union[bytes, bytearray, memoryview] class BLAKE2b_Hash(object): - block_size: int - digest_size: int - oid: str + block_size: int + digest_size: int + oid: str - def __init__(self, - data: Buffer, - key: Buffer, - digest_bytes: bytes, - update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> BLAKE2b_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - def new(self, - data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - key: Buffer = ..., - update_after_digest: bool = ...) -> BLAKE2b_Hash: ... + def __init__(self, data: Buffer, key: Buffer, digest_bytes: bytes, update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> BLAKE2b_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + def new( + self, + data: Buffer = ..., + digest_bytes: int = ..., + digest_bits: int = ..., + key: Buffer = ..., + update_after_digest: bool = ..., + ) -> BLAKE2b_Hash: ... -def new(data: Buffer = ..., +def new( + data: Buffer = ..., digest_bytes: int = ..., digest_bits: int = ..., key: Buffer = ..., - update_after_digest: bool = ...) -> BLAKE2b_Hash: ... + update_after_digest: bool = ..., +) -> BLAKE2b_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2s.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2s.py index 43be5c43..575f82a5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2s.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2s.py @@ -33,14 +33,19 @@ from Cryptodome.Util.py3compat import bord, tobytes from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_blake2s_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._BLAKE2s", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_blake2s_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._BLAKE2s", + """ int blake2s_init(void **state, const uint8_t *key, size_t key_size, @@ -52,196 +57,198 @@ int blake2s_digest(const void *state, uint8_t digest[32]); int blake2s_copy(const void *src, void *dst); - """) + """, +) class BLAKE2s_Hash(object): - """A BLAKE2s hash object. - Do not instantiate directly. Use the :func:`new` function. + """A BLAKE2s hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The internal block size of the hash algorithm in bytes. + block_size = 32 + + def __init__(self, data, key, digest_bytes, update_after_digest): + # The size of the resulting hash in bytes. + self.digest_size = digest_bytes + + self._update_after_digest = update_after_digest + self._digest_done = False + + # See https://tools.ietf.org/html/rfc7693 + if digest_bytes in (16, 20, 28, 32) and not key: + self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes) + + state = VoidPointer() + result = _raw_blake2s_lib.blake2s_init( + state.address_of(), + c_uint8_ptr(key), + c_size_t(len(key)), + c_size_t(digest_bytes), + ) + if result: + raise ValueError("Error %d while instantiating BLAKE2s" % result) + self._state = SmartPointer( + state.get(), + _raw_blake2s_lib.blake2s_destroy, + ) + if data: + self.update(data) - :ivar oid: ASN.1 Object ID - :vartype oid: string + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - # The internal block size of the hash algorithm in bytes. - block_size = 32 + result = _raw_blake2s_lib.blake2s_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError("Error %d while hashing BLAKE2s data" % result) + return self - def __init__(self, data, key, digest_bytes, update_after_digest): + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. - # The size of the resulting hash in bytes. - self.digest_size = digest_bytes + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ - self._update_after_digest = update_after_digest - self._digest_done = False + bfr = create_string_buffer(32) + result = _raw_blake2s_lib.blake2s_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError("Error %d while creating BLAKE2s digest" % result) - # See https://tools.ietf.org/html/rfc7693 - if digest_bytes in (16, 20, 28, 32) and not key: - self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes) + self._digest_done = True - state = VoidPointer() - result = _raw_blake2s_lib.blake2s_init(state.address_of(), - c_uint8_ptr(key), - c_size_t(len(key)), - c_size_t(digest_bytes) - ) - if result: - raise ValueError("Error %d while instantiating BLAKE2s" % result) - self._state = SmartPointer(state.get(), - _raw_blake2s_lib.blake2s_destroy) - if data: - self.update(data) + return get_raw_buffer(bfr)[: self.digest_size] + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. - result = _raw_blake2s_lib.blake2s_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing BLAKE2s data" % result) - return self + Args: + mac_tag (byte string/byte array/memoryview): the expected MAC of the message. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. + secret = get_random_bytes(16) - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ + mac1 = new(digest_bits=160, key=secret, data=mac_tag) + mac2 = new(digest_bits=160, key=secret, data=self.digest()) - bfr = create_string_buffer(32) - result = _raw_blake2s_lib.blake2s_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while creating BLAKE2s digest" % result) + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - self._digest_done = True + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. - return get_raw_buffer(bfr)[:self.digest_size] + Args: + hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. + self.verify(unhexlify(tobytes(hex_mac_tag))) - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ + def new(self, **kwargs): + """Return a new instance of a BLAKE2s hash object. + See :func:`new`. + """ - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: + kwargs["digest_bytes"] = self.digest_size - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte array/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = new(digest_bits=160, key=secret, data=mac_tag) - mac2 = new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - - def new(self, **kwargs): - """Return a new instance of a BLAKE2s hash object. - See :func:`new`. - """ - - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) + return new(**kwargs) def new(**kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`BLAKE2s_Hash.update`. - digest_bytes (integer): - Optional. The size of the digest, in bytes (1 to 32). Default is 32. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (8 to 256, in steps of 8). - Default is 256. - key (byte string): - Optional. The key to use to compute the MAC (1 to 64 bytes). - If not specified, no key will be used. - update_after_digest (boolean): - Optional. By default, a hash object cannot be updated anymore after - the digest is computed. When this flag is ``True``, such check - is no longer enforced. - - Returns: - A :class:`BLAKE2s_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 32 - if digest_bytes is not None: - if not (1 <= digest_bytes <= 32): - raise ValueError("'digest_bytes' not in range 1..32") - else: - if not (8 <= digest_bits <= 256) or (digest_bits % 8): - raise ValueError("'digest_bits' not in range 8..256, " - "with steps of 8") - digest_bytes = digest_bits // 8 - - key = kwargs.pop("key", b"") - if len(key) > 32: - raise ValueError("BLAKE2s key cannot exceed 32 bytes") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return BLAKE2s_Hash(data, key, digest_bytes, update_after_digest) + """Create a new hash object. + + Args: + data (byte string/byte array/memoryview): + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`BLAKE2s_Hash.update`. + digest_bytes (integer): + Optional. The size of the digest, in bytes (1 to 32). Default is 32. + digest_bits (integer): + Optional and alternative to ``digest_bytes``. + The size of the digest, in bits (8 to 256, in steps of 8). + Default is 256. + key (byte string): + Optional. The key to use to compute the MAC (1 to 64 bytes). + If not specified, no key will be used. + update_after_digest (boolean): + Optional. By default, a hash object cannot be updated anymore after + the digest is computed. When this flag is ``True``, such check + is no longer enforced. + + Returns: + A :class:`BLAKE2s_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + digest_bytes = 32 + if digest_bytes is not None: + if not (1 <= digest_bytes <= 32): + raise ValueError("'digest_bytes' not in range 1..32") + else: + if not (8 <= digest_bits <= 256) or (digest_bits % 8): + raise ValueError( + "'digest_bits' not in range 8..256, with steps of 8", + ) + digest_bytes = digest_bits // 8 + + key = kwargs.pop("key", b"") + if len(key) > 32: + raise ValueError("BLAKE2s key cannot exceed 32 bytes") + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return BLAKE2s_Hash(data, key, digest_bytes, update_after_digest) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2s.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2s.pyi index 374b3a43..47a970ab 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2s.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/BLAKE2s.pyi @@ -3,24 +3,22 @@ from typing import Any, Union Buffer = Union[bytes, bytearray, memoryview] class BLAKE2s_Hash(object): - block_size: int - digest_size: int - oid: str + block_size: int + digest_size: int + oid: str - def __init__(self, - data: Buffer, - key: Buffer, - digest_bytes: bytes, - update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> BLAKE2s_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - def new(self, **kwargs: Any) -> BLAKE2s_Hash: ... + def __init__(self, data: Buffer, key: Buffer, digest_bytes: bytes, update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> BLAKE2s_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + def new(self, **kwargs: Any) -> BLAKE2s_Hash: ... -def new(data: Buffer = ..., +def new( + data: Buffer = ..., digest_bytes: int = ..., digest_bits: int = ..., key: Buffer = ..., - update_after_digest: bool = ...) -> BLAKE2s_Hash: ... + update_after_digest: bool = ..., +) -> BLAKE2s_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/CMAC.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/CMAC.py index 8feb79fd..935cb1d8 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/CMAC.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/CMAC.py @@ -34,273 +34,299 @@ def _shift_bytes(bs, xor_lsb=0): - num = (bytes_to_long(bs) << 1) ^ xor_lsb - return long_to_bytes(num, len(bs))[-len(bs):] + num = (bytes_to_long(bs) << 1) ^ xor_lsb + return long_to_bytes(num, len(bs))[-len(bs) :] class CMAC(object): - """A CMAC hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting MAC tag - :vartype digest_size: integer - """ - - digest_size = None - - def __init__(self, key, msg, ciphermod, cipher_params, mac_len, - update_after_digest): - - self.digest_size = mac_len - - self._key = _copy_bytes(None, None, key) - self._factory = ciphermod - self._cipher_params = cipher_params - self._block_size = bs = ciphermod.block_size - self._mac_tag = None - self._update_after_digest = update_after_digest - - # Section 5.3 of NIST SP 800 38B and Appendix B - if bs == 8: - const_Rb = 0x1B - self._max_size = 8 * (2 ** 21) - elif bs == 16: - const_Rb = 0x87 - self._max_size = 16 * (2 ** 48) - else: - raise TypeError("CMAC requires a cipher with a block size" - " of 8 or 16 bytes, not %d" % bs) - - # Compute sub-keys - zero_block = b'\x00' * bs - self._ecb = ciphermod.new(key, - ciphermod.MODE_ECB, - **self._cipher_params) - L = self._ecb.encrypt(zero_block) - if bord(L[0]) & 0x80: - self._k1 = _shift_bytes(L, const_Rb) - else: - self._k1 = _shift_bytes(L) - if bord(self._k1[0]) & 0x80: - self._k2 = _shift_bytes(self._k1, const_Rb) - else: - self._k2 = _shift_bytes(self._k1) - - # Initialize CBC cipher with zero IV - self._cbc = ciphermod.new(key, - ciphermod.MODE_CBC, - zero_block, - **self._cipher_params) - - # Cache for outstanding data to authenticate - self._cache = bytearray(bs) - self._cache_n = 0 - - # Last piece of ciphertext produced - self._last_ct = zero_block - - # Last block that was encrypted with AES - self._last_pt = None - - # Counter for total message size - self._data_size = 0 - - if msg: - self.update(msg) - - def update(self, msg): - """Authenticate the next chunk of message. - - Args: - data (byte string/byte array/memoryview): The next chunk of data - """ - - if self._mac_tag is not None and not self._update_after_digest: - raise TypeError("update() cannot be called after digest() or verify()") - - self._data_size += len(msg) - bs = self._block_size - - if self._cache_n > 0: - filler = min(bs - self._cache_n, len(msg)) - self._cache[self._cache_n:self._cache_n+filler] = msg[:filler] - self._cache_n += filler - - if self._cache_n < bs: - return self - - msg = memoryview(msg)[filler:] - self._update(self._cache) - self._cache_n = 0 - - remain = len(msg) % bs - if remain > 0: - self._update(msg[:-remain]) - self._cache[:remain] = msg[-remain:] - else: - self._update(msg) - self._cache_n = remain - return self - - def _update(self, data_block): - """Update a block aligned to the block boundary""" - - bs = self._block_size - assert len(data_block) % bs == 0 - - if len(data_block) == 0: - return - - ct = self._cbc.encrypt(data_block) - if len(data_block) == bs: - second_last = self._last_ct - else: - second_last = ct[-bs*2:-bs] - self._last_ct = ct[-bs:] - self._last_pt = strxor(second_last, data_block[-bs:]) - - def copy(self): - """Return a copy ("clone") of the CMAC object. - - The copy will have the same internal state as the original CMAC - object. - This can be used to efficiently compute the MAC tag of byte - strings that share a common initial substring. - - :return: An :class:`CMAC` - """ - - obj = self.__new__(CMAC) - obj.__dict__ = self.__dict__.copy() - obj._cbc = self._factory.new(self._key, - self._factory.MODE_CBC, - self._last_ct, - **self._cipher_params) - obj._cache = self._cache[:] - obj._last_ct = self._last_ct[:] - return obj - - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message - that has been authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bs = self._block_size - - if self._mac_tag is not None and not self._update_after_digest: - return self._mac_tag - - if self._data_size > self._max_size: - raise ValueError("MAC is unsafe for this message") - - if self._cache_n == 0 and self._data_size > 0: - # Last block was full - pt = strxor(self._last_pt, self._k1) - else: - # Last block is partial (or message length is zero) - partial = self._cache[:] - partial[self._cache_n:] = b'\x80' + b'\x00' * (bs - self._cache_n - 1) - pt = strxor(strxor(self._last_ct, partial), self._k2) - - self._mac_tag = self._ecb.encrypt(pt)[:self.digest_size] - - return self._mac_tag - - def hexdigest(self): - """Return the **printable** MAC tag of the message authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) - for x in tuple(self.digest())]) - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte array/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - -def new(key, msg=None, ciphermod=None, cipher_params=None, mac_len=None, - update_after_digest=False): - """Create a new MAC object. - - Args: - key (byte string/byte array/memoryview): - key for the CMAC object. - The key must be valid for the underlying cipher algorithm. - For instance, it must be 16 bytes long for AES-128. - ciphermod (module): - A cipher module from :mod:`Cryptodome.Cipher`. - The cipher's block size has to be 128 bits, - like :mod:`Cryptodome.Cipher.AES`, to reduce the probability - of collisions. - msg (byte string/byte array/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to `CMAC.update`. Optional. - cipher_params (dict): - Optional. A set of parameters to use when instantiating a cipher - object. - mac_len (integer): - Length of the MAC, in bytes. - It must be at least 4 bytes long. - The default (and recommended) length matches the size of a cipher block. - update_after_digest (boolean): - Optional. By default, a hash object cannot be updated anymore after - the digest is computed. When this flag is ``True``, such check - is no longer enforced. - Returns: - A :class:`CMAC` object - """ - - if ciphermod is None: - raise TypeError("ciphermod must be specified (try AES)") - - cipher_params = {} if cipher_params is None else dict(cipher_params) - - if mac_len is None: - mac_len = ciphermod.block_size - - if mac_len < 4: - raise ValueError("MAC tag length must be at least 4 bytes long") - - if mac_len > ciphermod.block_size: - raise ValueError("MAC tag length cannot be larger than a cipher block (%d) bytes" % ciphermod.block_size) - - return CMAC(key, msg, ciphermod, cipher_params, mac_len, - update_after_digest) + """A CMAC hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar digest_size: the size in bytes of the resulting MAC tag + :vartype digest_size: integer + """ + + digest_size = None + + def __init__( + self, + key, + msg, + ciphermod, + cipher_params, + mac_len, + update_after_digest, + ): + self.digest_size = mac_len + + self._key = _copy_bytes(None, None, key) + self._factory = ciphermod + self._cipher_params = cipher_params + self._block_size = bs = ciphermod.block_size + self._mac_tag = None + self._update_after_digest = update_after_digest + + # Section 5.3 of NIST SP 800 38B and Appendix B + if bs == 8: + const_Rb = 0x1B + self._max_size = 8 * (2**21) + elif bs == 16: + const_Rb = 0x87 + self._max_size = 16 * (2**48) + else: + raise TypeError( + "CMAC requires a cipher with a block size of 8 or 16 bytes, not %d" % bs, + ) + + # Compute sub-keys + zero_block = b"\x00" * bs + self._ecb = ciphermod.new( + key, + ciphermod.MODE_ECB, + **self._cipher_params, + ) + L = self._ecb.encrypt(zero_block) + if bord(L[0]) & 0x80: + self._k1 = _shift_bytes(L, const_Rb) + else: + self._k1 = _shift_bytes(L) + if bord(self._k1[0]) & 0x80: + self._k2 = _shift_bytes(self._k1, const_Rb) + else: + self._k2 = _shift_bytes(self._k1) + + # Initialize CBC cipher with zero IV + self._cbc = ciphermod.new( + key, + ciphermod.MODE_CBC, + zero_block, + **self._cipher_params, + ) + + # Cache for outstanding data to authenticate + self._cache = bytearray(bs) + self._cache_n = 0 + + # Last piece of ciphertext produced + self._last_ct = zero_block + + # Last block that was encrypted with AES + self._last_pt = None + + # Counter for total message size + self._data_size = 0 + + if msg: + self.update(msg) + + def update(self, msg): + """Authenticate the next chunk of message. + + Args: + data (byte string/byte array/memoryview): The next chunk of data + """ + + if self._mac_tag is not None and not self._update_after_digest: + raise TypeError("update() cannot be called after digest() or verify()") + + self._data_size += len(msg) + bs = self._block_size + + if self._cache_n > 0: + filler = min(bs - self._cache_n, len(msg)) + self._cache[self._cache_n : self._cache_n + filler] = msg[:filler] + self._cache_n += filler + + if self._cache_n < bs: + return self + + msg = memoryview(msg)[filler:] + self._update(self._cache) + self._cache_n = 0 + + remain = len(msg) % bs + if remain > 0: + self._update(msg[:-remain]) + self._cache[:remain] = msg[-remain:] + else: + self._update(msg) + self._cache_n = remain + return self + + def _update(self, data_block): + """Update a block aligned to the block boundary""" + + bs = self._block_size + assert len(data_block) % bs == 0 + + if len(data_block) == 0: + return + + ct = self._cbc.encrypt(data_block) + if len(data_block) == bs: + second_last = self._last_ct + else: + second_last = ct[-bs * 2 : -bs] + self._last_ct = ct[-bs:] + self._last_pt = strxor(second_last, data_block[-bs:]) + + def copy(self): + """Return a copy ("clone") of the CMAC object. + + The copy will have the same internal state as the original CMAC + object. + This can be used to efficiently compute the MAC tag of byte + strings that share a common initial substring. + + :return: An :class:`CMAC` + """ + + obj = self.__new__(CMAC) + obj.__dict__ = self.__dict__.copy() + obj._cbc = self._factory.new( + self._key, + self._factory.MODE_CBC, + self._last_ct, + **self._cipher_params, + ) + obj._cache = self._cache[:] + obj._last_ct = self._last_ct[:] + return obj + + def digest(self): + """Return the **binary** (non-printable) MAC tag of the message + that has been authenticated so far. + + :return: The MAC tag, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bs = self._block_size + + if self._mac_tag is not None and not self._update_after_digest: + return self._mac_tag + + if self._data_size > self._max_size: + raise ValueError("MAC is unsafe for this message") + + if self._cache_n == 0 and self._data_size > 0: + # Last block was full + pt = strxor(self._last_pt, self._k1) + else: + # Last block is partial (or message length is zero) + partial = self._cache[:] + partial[self._cache_n :] = b"\x80" + b"\x00" * (bs - self._cache_n - 1) + pt = strxor(strxor(self._last_ct, partial), self._k2) + + self._mac_tag = self._ecb.encrypt(pt)[: self.digest_size] + + return self._mac_tag + + def hexdigest(self): + """Return the **printable** MAC tag of the message authenticated so far. + + :return: The MAC tag, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. + + Args: + mac_tag (byte string/byte array/memoryview): the expected MAC of the message. + + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. + + Args: + hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. + + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + self.verify(unhexlify(tobytes(hex_mac_tag))) + + +def new( + key, + msg=None, + ciphermod=None, + cipher_params=None, + mac_len=None, + update_after_digest=False, +): + """Create a new MAC object. + + Args: + key (byte string/byte array/memoryview): + key for the CMAC object. + The key must be valid for the underlying cipher algorithm. + For instance, it must be 16 bytes long for AES-128. + ciphermod (module): + A cipher module from :mod:`Cryptodome.Cipher`. + The cipher's block size has to be 128 bits, + like :mod:`Cryptodome.Cipher.AES`, to reduce the probability + of collisions. + msg (byte string/byte array/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to `CMAC.update`. Optional. + cipher_params (dict): + Optional. A set of parameters to use when instantiating a cipher + object. + mac_len (integer): + Length of the MAC, in bytes. + It must be at least 4 bytes long. + The default (and recommended) length matches the size of a cipher block. + update_after_digest (boolean): + Optional. By default, a hash object cannot be updated anymore after + the digest is computed. When this flag is ``True``, such check + is no longer enforced. + Returns: + A :class:`CMAC` object + """ + + if ciphermod is None: + raise TypeError("ciphermod must be specified (try AES)") + + cipher_params = {} if cipher_params is None else dict(cipher_params) + + if mac_len is None: + mac_len = ciphermod.block_size + + if mac_len < 4: + raise ValueError("MAC tag length must be at least 4 bytes long") + + if mac_len > ciphermod.block_size: + raise ValueError( + "MAC tag length cannot be larger than a cipher block (%d) bytes" % ciphermod.block_size + ) + + return CMAC( + key, + msg, + ciphermod, + cipher_params, + mac_len, + update_after_digest, + ) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/CMAC.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/CMAC.pyi index acdf0553..10cd2afc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/CMAC.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/CMAC.pyi @@ -6,25 +6,29 @@ Buffer = Union[bytes, bytearray, memoryview] digest_size: int class CMAC(object): - digest_size: int + digest_size: int - def __init__(self, - key: Buffer, - msg: Buffer, - ciphermod: ModuleType, - cipher_params: Dict[str, Any], - mac_len: int, update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> CMAC: ... - def copy(self) -> CMAC: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... + def __init__( + self, + key: Buffer, + msg: Buffer, + ciphermod: ModuleType, + cipher_params: Dict[str, Any], + mac_len: int, + update_after_digest: bool, + ) -> None: ... + def update(self, data: Buffer) -> CMAC: ... + def copy(self) -> CMAC: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... - -def new(key: Buffer, - msg: Buffer = ..., +def new( + key: Buffer, + msg: Buffer = ..., ciphermod: ModuleType = ..., cipher_params: Dict[str, Any] = ..., mac_len: int = ..., - update_after_digest: bool = ...) -> CMAC: ... + update_after_digest: bool = ..., +) -> CMAC: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/HMAC.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/HMAC.py index 615056a8..13aa2089 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/HMAC.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/HMAC.py @@ -39,200 +39,200 @@ from Cryptodome.Util.strxor import strxor from Cryptodome.Random import get_random_bytes -__all__ = ['new', 'HMAC'] +__all__ = ["new", "HMAC"] _hash2hmac_oid = { - '1.3.14.3.2.26': '1.2.840.113549.2.7', # SHA-1 - '2.16.840.1.101.3.4.2.4': '1.2.840.113549.2.8', # SHA-224 - '2.16.840.1.101.3.4.2.1': '1.2.840.113549.2.9', # SHA-256 - '2.16.840.1.101.3.4.2.2': '1.2.840.113549.2.10', # SHA-384 - '2.16.840.1.101.3.4.2.3': '1.2.840.113549.2.11', # SHA-512 - '2.16.840.1.101.3.4.2.5': '1.2.840.113549.2.12', # SHA-512_224 - '2.16.840.1.101.3.4.2.6': '1.2.840.113549.2.13', # SHA-512_256 - '2.16.840.1.101.3.4.2.7': '2.16.840.1.101.3.4.2.13', # SHA-3 224 - '2.16.840.1.101.3.4.2.8': '2.16.840.1.101.3.4.2.14', # SHA-3 256 - '2.16.840.1.101.3.4.2.9': '2.16.840.1.101.3.4.2.15', # SHA-3 384 - '2.16.840.1.101.3.4.2.10': '2.16.840.1.101.3.4.2.16', # SHA-3 512 + "1.3.14.3.2.26": "1.2.840.113549.2.7", # SHA-1 + "2.16.840.1.101.3.4.2.4": "1.2.840.113549.2.8", # SHA-224 + "2.16.840.1.101.3.4.2.1": "1.2.840.113549.2.9", # SHA-256 + "2.16.840.1.101.3.4.2.2": "1.2.840.113549.2.10", # SHA-384 + "2.16.840.1.101.3.4.2.3": "1.2.840.113549.2.11", # SHA-512 + "2.16.840.1.101.3.4.2.5": "1.2.840.113549.2.12", # SHA-512_224 + "2.16.840.1.101.3.4.2.6": "1.2.840.113549.2.13", # SHA-512_256 + "2.16.840.1.101.3.4.2.7": "2.16.840.1.101.3.4.2.13", # SHA-3 224 + "2.16.840.1.101.3.4.2.8": "2.16.840.1.101.3.4.2.14", # SHA-3 256 + "2.16.840.1.101.3.4.2.9": "2.16.840.1.101.3.4.2.15", # SHA-3 384 + "2.16.840.1.101.3.4.2.10": "2.16.840.1.101.3.4.2.16", # SHA-3 512 } _hmac2hash_oid = {v: k for k, v in _hash2hmac_oid.items()} class HMAC(object): - """An HMAC hash object. - Do not instantiate directly. Use the :func:`new` function. + """An HMAC hash object. + Do not instantiate directly. Use the :func:`new` function. - :ivar digest_size: the size in bytes of the resulting MAC tag - :vartype digest_size: integer + :ivar digest_size: the size in bytes of the resulting MAC tag + :vartype digest_size: integer - :ivar oid: the ASN.1 object ID of the HMAC algorithm. - Only present if the algorithm was officially assigned one. - """ + :ivar oid: the ASN.1 object ID of the HMAC algorithm. + Only present if the algorithm was officially assigned one. + """ - def __init__(self, key, msg=b"", digestmod=None): + def __init__(self, key, msg=b"", digestmod=None): + if digestmod is None: + from Cryptodome.Hash import MD5 - if digestmod is None: - from Cryptodome.Hash import MD5 - digestmod = MD5 + digestmod = MD5 - if msg is None: - msg = b"" + if msg is None: + msg = b"" - # Size of the MAC tag - self.digest_size = digestmod.digest_size + # Size of the MAC tag + self.digest_size = digestmod.digest_size - self._digestmod = digestmod + self._digestmod = digestmod - # Hash OID --> HMAC OID - try: - self.oid = _hash2hmac_oid[digestmod.oid] - except (KeyError, AttributeError): - pass + # Hash OID --> HMAC OID + try: + self.oid = _hash2hmac_oid[digestmod.oid] + except (KeyError, AttributeError): + pass - if isinstance(key, memoryview): - key = key.tobytes() + if isinstance(key, memoryview): + key = key.tobytes() - try: - if len(key) <= digestmod.block_size: - # Step 1 or 2 - key_0 = key + b"\x00" * (digestmod.block_size - len(key)) - else: - # Step 3 - hash_k = digestmod.new(key).digest() - key_0 = hash_k + b"\x00" * (digestmod.block_size - len(hash_k)) - except AttributeError: - # Not all hash types have "block_size" - raise ValueError("Hash type incompatible to HMAC") + try: + if len(key) <= digestmod.block_size: + # Step 1 or 2 + key_0 = key + b"\x00" * (digestmod.block_size - len(key)) + else: + # Step 3 + hash_k = digestmod.new(key).digest() + key_0 = hash_k + b"\x00" * (digestmod.block_size - len(hash_k)) + except AttributeError: + # Not all hash types have "block_size" + raise ValueError("Hash type incompatible to HMAC") - # Step 4 - key_0_ipad = strxor(key_0, b"\x36" * len(key_0)) + # Step 4 + key_0_ipad = strxor(key_0, b"\x36" * len(key_0)) - # Start step 5 and 6 - self._inner = digestmod.new(key_0_ipad) - self._inner.update(msg) + # Start step 5 and 6 + self._inner = digestmod.new(key_0_ipad) + self._inner.update(msg) - # Step 7 - key_0_opad = strxor(key_0, b"\x5c" * len(key_0)) + # Step 7 + key_0_opad = strxor(key_0, b"\x5c" * len(key_0)) - # Start step 8 and 9 - self._outer = digestmod.new(key_0_opad) + # Start step 8 and 9 + self._outer = digestmod.new(key_0_opad) - def update(self, msg): - """Authenticate the next chunk of message. + def update(self, msg): + """Authenticate the next chunk of message. - Args: - data (byte string/byte array/memoryview): The next chunk of data - """ + Args: + data (byte string/byte array/memoryview): The next chunk of data + """ - self._inner.update(msg) - return self + self._inner.update(msg) + return self - def _pbkdf2_hmac_assist(self, first_digest, iterations): - """Carry out the expensive inner loop for PBKDF2-HMAC""" + def _pbkdf2_hmac_assist(self, first_digest, iterations): + """Carry out the expensive inner loop for PBKDF2-HMAC""" - result = self._digestmod._pbkdf2_hmac_assist( - self._inner, - self._outer, - first_digest, - iterations) - return result + result = self._digestmod._pbkdf2_hmac_assist( + self._inner, + self._outer, + first_digest, + iterations, + ) + return result - def copy(self): - """Return a copy ("clone") of the HMAC object. + def copy(self): + """Return a copy ("clone") of the HMAC object. - The copy will have the same internal state as the original HMAC - object. - This can be used to efficiently compute the MAC tag of byte - strings that share a common initial substring. + The copy will have the same internal state as the original HMAC + object. + This can be used to efficiently compute the MAC tag of byte + strings that share a common initial substring. - :return: An :class:`HMAC` - """ + :return: An :class:`HMAC` + """ - new_hmac = HMAC(b"fake key", digestmod=self._digestmod) + new_hmac = HMAC(b"fake key", digestmod=self._digestmod) - # Syncronize the state - new_hmac._inner = self._inner.copy() - new_hmac._outer = self._outer.copy() + # Syncronize the state + new_hmac._inner = self._inner.copy() + new_hmac._outer = self._outer.copy() - return new_hmac + return new_hmac - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message - authenticated so far. + def digest(self): + """Return the **binary** (non-printable) MAC tag of the message + authenticated so far. - :return: The MAC tag digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ + :return: The MAC tag digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ - frozen_outer_hash = self._outer.copy() - frozen_outer_hash.update(self._inner.digest()) - return frozen_outer_hash.digest() + frozen_outer_hash = self._outer.copy() + frozen_outer_hash.update(self._inner.digest()) + return frozen_outer_hash.digest() - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. - Args: - mac_tag (byte string/byte string/memoryview): the expected MAC of the message. + Args: + mac_tag (byte string/byte string/memoryview): the expected MAC of the message. - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - secret = get_random_bytes(16) + secret = get_random_bytes(16) - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - def hexdigest(self): - """Return the **printable** MAC tag of the message authenticated so far. + def hexdigest(self): + """Return the **printable** MAC tag of the message authenticated so far. - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ + :return: The MAC tag, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ - return "".join(["%02x" % bord(x) - for x in tuple(self.digest())]) + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. - Args: - hex_mac_tag (string): the expected MAC of the message, - as a hexadecimal string. + Args: + hex_mac_tag (string): the expected MAC of the message, + as a hexadecimal string. - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - self.verify(unhexlify(tobytes(hex_mac_tag))) + self.verify(unhexlify(tobytes(hex_mac_tag))) def new(key, msg=b"", digestmod=None): - """Create a new MAC object. - - Args: - key (bytes/bytearray/memoryview): - key for the MAC object. - It must be long enough to match the expected security level of the - MAC. - msg (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to :meth:`HMAC.update`. - digestmod (module): - The hash to use to implement the HMAC. - Default is :mod:`Cryptodome.Hash.MD5`. - - Returns: - An :class:`HMAC` object - """ - - return HMAC(key, msg, digestmod) + """Create a new MAC object. + + Args: + key (bytes/bytearray/memoryview): + key for the MAC object. + It must be long enough to match the expected security level of the + MAC. + msg (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to :meth:`HMAC.update`. + digestmod (module): + The hash to use to implement the HMAC. + Default is :mod:`Cryptodome.Hash.MD5`. + + Returns: + An :class:`HMAC` object + """ + + return HMAC(key, msg, digestmod) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/HMAC.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/HMAC.pyi index b577230f..8d3b7c52 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/HMAC.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/HMAC.pyi @@ -1,25 +1,19 @@ from types import ModuleType -from typing import Union, Dict +from typing import Union Buffer = Union[bytes, bytearray, memoryview] digest_size: int class HMAC(object): - digest_size: int + digest_size: int - def __init__(self, - key: Buffer, - msg: Buffer, - digestmod: ModuleType) -> None: ... - def update(self, msg: Buffer) -> HMAC: ... - def copy(self) -> HMAC: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... + def __init__(self, key: Buffer, msg: Buffer, digestmod: ModuleType) -> None: ... + def update(self, msg: Buffer) -> HMAC: ... + def copy(self) -> HMAC: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... - -def new(key: Buffer, - msg: Buffer = ..., - digestmod: ModuleType = ...) -> HMAC: ... +def new(key: Buffer, msg: Buffer = ..., digestmod: ModuleType = ...) -> HMAC: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC128.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC128.py index afd91c46..bf284faa 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC128.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC128.py @@ -38,142 +38,149 @@ class KMAC_Hash(object): - """A KMAC hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ + """A KMAC hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ - def __init__(self, data, key, mac_len, custom, - oid_variant, cshake, rate): + def __init__( + self, + data, + key, + mac_len, + custom, + oid_variant, + cshake, + rate, + ): + # See https://tools.ietf.org/html/rfc8702 + self.oid = "2.16.840.1.101.3.4.2." + oid_variant + self.digest_size = mac_len - # See https://tools.ietf.org/html/rfc8702 - self.oid = "2.16.840.1.101.3.4.2." + oid_variant - self.digest_size = mac_len + self._mac = None - self._mac = None + partial_newX = _bytepad(_encode_str(tobytes(key)), rate) + self._cshake = cshake._new(partial_newX, custom, b"KMAC") - partial_newX = _bytepad(_encode_str(tobytes(key)), rate) - self._cshake = cshake._new(partial_newX, custom, b"KMAC") + if data: + self._cshake.update(data) - if data: - self._cshake.update(data) + def update(self, data): + """Authenticate the next chunk of message. - def update(self, data): - """Authenticate the next chunk of message. + Args: + data (bytes/bytearray/memoryview): The next chunk of the message to + authenticate. + """ - Args: - data (bytes/bytearray/memoryview): The next chunk of the message to - authenticate. - """ + if self._mac: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - if self._mac: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + self._cshake.update(data) + return self - self._cshake.update(data) - return self + def digest(self): + """Return the **binary** (non-printable) MAC tag of the message. - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message. + :return: The MAC tag. Binary form. + :rtype: byte string + """ - :return: The MAC tag. Binary form. - :rtype: byte string - """ + if not self._mac: + self._cshake.update(_right_encode(self.digest_size * 8)) + self._mac = self._cshake.read(self.digest_size) - if not self._mac: - self._cshake.update(_right_encode(self.digest_size * 8)) - self._mac = self._cshake.read(self.digest_size) + return self._mac - return self._mac + def hexdigest(self): + """Return the **printable** MAC tag of the message. - def hexdigest(self): - """Return the **printable** MAC tag of the message. + :return: The MAC tag. Hexadecimal encoded. + :rtype: string + """ - :return: The MAC tag. Hexadecimal encoded. - :rtype: string - """ + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. + Args: + mac_tag (bytes/bytearray/memoryview): the expected MAC of the message. - Args: - mac_tag (bytes/bytearray/memoryview): the expected MAC of the message. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ + secret = get_random_bytes(16) - secret = get_random_bytes(16) + mac1 = SHA3_256.new(secret + mac_tag) + mac2 = SHA3_256.new(secret + self.digest()) - mac1 = SHA3_256.new(secret + mac_tag) - mac2 = SHA3_256.new(secret + self.digest()) + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. + Args: + hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ + self.verify(unhexlify(tobytes(hex_mac_tag))) - self.verify(unhexlify(tobytes(hex_mac_tag))) + def new(self, **kwargs): + """Return a new instance of a KMAC hash object. + See :func:`new`. + """ - def new(self, **kwargs): - """Return a new instance of a KMAC hash object. - See :func:`new`. - """ + if "mac_len" not in kwargs: + kwargs["mac_len"] = self.digest_size - if "mac_len" not in kwargs: - kwargs["mac_len"] = self.digest_size - - return new(**kwargs) + return new(**kwargs) def new(**kwargs): - """Create a new KMAC128 object. - - Args: - key (bytes/bytearray/memoryview): - The key to use to compute the MAC. - It must be at least 128 bits long (16 bytes). - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to :meth:`KMAC_Hash.update`. - mac_len (integer): - Optional. The size of the authentication tag, in bytes. - Default is 64. Minimum is 8. - custom (bytes/bytearray/memoryview): - Optional. A customization byte string (``S`` in SP 800-185). - - Returns: - A :class:`KMAC_Hash` hash object - """ - - key = kwargs.pop("key", None) - if not is_bytes(key): - raise TypeError("You must pass a key to KMAC128") - if len(key) < 16: - raise ValueError("The key must be at least 128 bits long (16 bytes)") - - data = kwargs.pop("data", None) - - mac_len = kwargs.pop("mac_len", 64) - if mac_len < 8: - raise ValueError("'mac_len' must be 8 bytes or more") - - custom = kwargs.pop("custom", b"") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return KMAC_Hash(data, key, mac_len, custom, "19", cSHAKE128, 168) + """Create a new KMAC128 object. + + Args: + key (bytes/bytearray/memoryview): + The key to use to compute the MAC. + It must be at least 128 bits long (16 bytes). + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to :meth:`KMAC_Hash.update`. + mac_len (integer): + Optional. The size of the authentication tag, in bytes. + Default is 64. Minimum is 8. + custom (bytes/bytearray/memoryview): + Optional. A customization byte string (``S`` in SP 800-185). + + Returns: + A :class:`KMAC_Hash` hash object + """ + + key = kwargs.pop("key", None) + if not is_bytes(key): + raise TypeError("You must pass a key to KMAC128") + if len(key) < 16: + raise ValueError("The key must be at least 128 bits long (16 bytes)") + + data = kwargs.pop("data", None) + + mac_len = kwargs.pop("mac_len", 64) + if mac_len < 8: + raise ValueError("'mac_len' must be 8 bytes or more") + + custom = kwargs.pop("custom", b"") + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return KMAC_Hash(data, key, mac_len, custom, "19", cSHAKE128, 168) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC128.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC128.pyi index 8947dabc..23223322 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC128.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC128.pyi @@ -4,30 +4,23 @@ from types import ModuleType Buffer = Union[bytes, bytearray, memoryview] class KMAC_Hash(object): + def __init__( + self, + data: Buffer, + key: Buffer, + mac_len: int, + custom: Buffer, + oid_variant: str, + cshake: ModuleType, + rate: int, + ) -> None: ... + def update(self, data: Buffer) -> KMAC_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... + def new( + self, data: Buffer = ..., mac_len: int = ..., key: Buffer = ..., custom: Buffer = ... + ) -> KMAC_Hash: ... - def __init__(self, - data: Buffer, - key: Buffer, - mac_len: int, - custom: Buffer, - oid_variant: str, - cshake: ModuleType, - rate: int) -> None: ... - - def update(self, data: Buffer) -> KMAC_Hash: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - def new(self, - data: Buffer = ..., - mac_len: int = ..., - key: Buffer = ..., - custom: Buffer = ...) -> KMAC_Hash: ... - - -def new(key: Buffer, - data: Buffer = ..., - mac_len: int = ..., - custom: Buffer = ...) -> KMAC_Hash: ... +def new(key: Buffer, data: Buffer = ..., mac_len: int = ..., custom: Buffer = ...) -> KMAC_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC256.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC256.py index 82da0626..2d957b1b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC256.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC256.py @@ -35,40 +35,40 @@ def new(**kwargs): - """Create a new KMAC256 object. + """Create a new KMAC256 object. - Args: - key (bytes/bytearray/memoryview): - The key to use to compute the MAC. - It must be at least 256 bits long (32 bytes). - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to :meth:`KMAC_Hash.update`. - mac_len (integer): - Optional. The size of the authentication tag, in bytes. - Default is 64. Minimum is 8. - custom (bytes/bytearray/memoryview): - Optional. A customization byte string (``S`` in SP 800-185). + Args: + key (bytes/bytearray/memoryview): + The key to use to compute the MAC. + It must be at least 256 bits long (32 bytes). + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to :meth:`KMAC_Hash.update`. + mac_len (integer): + Optional. The size of the authentication tag, in bytes. + Default is 64. Minimum is 8. + custom (bytes/bytearray/memoryview): + Optional. A customization byte string (``S`` in SP 800-185). - Returns: - A :class:`KMAC_Hash` hash object - """ + Returns: + A :class:`KMAC_Hash` hash object + """ - key = kwargs.pop("key", None) - if not is_bytes(key): - raise TypeError("You must pass a key to KMAC256") - if len(key) < 32: - raise ValueError("The key must be at least 256 bits long (32 bytes)") + key = kwargs.pop("key", None) + if not is_bytes(key): + raise TypeError("You must pass a key to KMAC256") + if len(key) < 32: + raise ValueError("The key must be at least 256 bits long (32 bytes)") - data = kwargs.pop("data", None) + data = kwargs.pop("data", None) - mac_len = kwargs.pop("mac_len", 64) - if mac_len < 8: - raise ValueError("'mac_len' must be 8 bytes or more") + mac_len = kwargs.pop("mac_len", 64) + if mac_len < 8: + raise ValueError("'mac_len' must be 8 bytes or more") - custom = kwargs.pop("custom", b"") + custom = kwargs.pop("custom", b"") - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) - return KMAC_Hash(data, key, mac_len, custom, "20", cSHAKE256, 136) + return KMAC_Hash(data, key, mac_len, custom, "20", cSHAKE256, 136) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC256.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC256.pyi index 86cc5000..a2f684b4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC256.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KMAC256.pyi @@ -4,7 +4,4 @@ from .KMAC128 import KMAC_Hash Buffer = Union[bytes, bytearray, memoryview] -def new(key: Buffer, - data: Buffer = ..., - mac_len: int = ..., - custom: Buffer = ...) -> KMAC_Hash: ... +def new(key: Buffer, data: Buffer = ..., mac_len: int = ..., custom: Buffer = ...) -> KMAC_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KangarooTwelve.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KangarooTwelve.py index 60ced572..3155ea5c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KangarooTwelve.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KangarooTwelve.py @@ -33,190 +33,189 @@ from . import TurboSHAKE128 + def _length_encode(x): - if x == 0: - return b'\x00' + if x == 0: + return b"\x00" - S = long_to_bytes(x) - return S + bchr(len(S)) + S = long_to_bytes(x) + return S + bchr(len(S)) # Possible states for a KangarooTwelve instance, which depend on the amount of data processed so far. -SHORT_MSG = 1 # Still within the first 8192 bytes, but it is not certain we will exceed them. -LONG_MSG_S0 = 2 # Still within the first 8192 bytes, and it is certain we will exceed them. -LONG_MSG_SX = 3 # Beyond the first 8192 bytes. -SQUEEZING = 4 # No more data to process. +SHORT_MSG = 1 # Still within the first 8192 bytes, but it is not certain we will exceed them. +LONG_MSG_S0 = 2 # Still within the first 8192 bytes, and it is certain we will exceed them. +LONG_MSG_SX = 3 # Beyond the first 8192 bytes. +SQUEEZING = 4 # No more data to process. class K12_XOF(object): - """A KangarooTwelve hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ - - def __init__(self, data, custom): - - if custom == None: - custom = b'' - - self._custom = custom + _length_encode(len(custom)) - self._state = SHORT_MSG - self._padding = None # Final padding is only decided in read() - - # Internal hash that consumes FinalNode - # The real domain separation byte will be known before squeezing - self._hash1 = TurboSHAKE128.new(domain=1) - self._length1 = 0 - - # Internal hash that produces CV_i (reset each time) - self._hash2 = None - self._length2 = 0 - - # Incremented by one for each 8192-byte block - self._ctr = 0 - - if data: - self.update(data) - - def update(self, data): - """Hash the next piece of data. - - .. note:: - For better performance, submit chunks with a length multiple of 8192 bytes. - - Args: - data (byte string/byte array/memoryview): The next chunk of the - message to hash. - """ - - if self._state == SQUEEZING: - raise TypeError("You cannot call 'update' after the first 'read'") - - if self._state == SHORT_MSG: - next_length = self._length1 + len(data) - - if next_length + len(self._custom) <= 8192: - self._length1 = next_length - self._hash1.update(data) - return self + """A KangarooTwelve hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ + + def __init__(self, data, custom): + if custom == None: + custom = b"" + + self._custom = custom + _length_encode(len(custom)) + self._state = SHORT_MSG + self._padding = None # Final padding is only decided in read() + + # Internal hash that consumes FinalNode + # The real domain separation byte will be known before squeezing + self._hash1 = TurboSHAKE128.new(domain=1) + self._length1 = 0 - # Switch to tree hashing - self._state = LONG_MSG_S0 + # Internal hash that produces CV_i (reset each time) + self._hash2 = None + self._length2 = 0 - if self._state == LONG_MSG_S0: - data_mem = memoryview(data) - assert(self._length1 < 8192) - dtc = min(len(data), 8192 - self._length1) - self._hash1.update(data_mem[:dtc]) - self._length1 += dtc + # Incremented by one for each 8192-byte block + self._ctr = 0 + + if data: + self.update(data) + + def update(self, data): + """Hash the next piece of data. - if self._length1 < 8192: - return self + .. note:: + For better performance, submit chunks with a length multiple of 8192 bytes. + + Args: + data (byte string/byte array/memoryview): The next chunk of the + message to hash. + """ + + if self._state == SQUEEZING: + raise TypeError("You cannot call 'update' after the first 'read'") + + if self._state == SHORT_MSG: + next_length = self._length1 + len(data) + + if next_length + len(self._custom) <= 8192: + self._length1 = next_length + self._hash1.update(data) + return self + + # Switch to tree hashing + self._state = LONG_MSG_S0 - # Finish hashing S_0 and start S_1 - assert(self._length1 == 8192) + if self._state == LONG_MSG_S0: + data_mem = memoryview(data) + assert self._length1 < 8192 + dtc = min(len(data), 8192 - self._length1) + self._hash1.update(data_mem[:dtc]) + self._length1 += dtc - divider = b'\x03' + b'\x00' * 7 - self._hash1.update(divider) - self._length1 += 8 + if self._length1 < 8192: + return self - self._hash2 = TurboSHAKE128.new(domain=0x0B) - self._length2 = 0 - self._ctr = 1 + # Finish hashing S_0 and start S_1 + assert self._length1 == 8192 - self._state = LONG_MSG_SX - return self.update(data_mem[dtc:]) + divider = b"\x03" + b"\x00" * 7 + self._hash1.update(divider) + self._length1 += 8 - # LONG_MSG_SX - assert(self._state == LONG_MSG_SX) - index = 0 - len_data = len(data) + self._hash2 = TurboSHAKE128.new(domain=0x0B) + self._length2 = 0 + self._ctr = 1 - # All iteractions could actually run in parallel - data_mem = memoryview(data) - while index < len_data: + self._state = LONG_MSG_SX + return self.update(data_mem[dtc:]) - new_index = min(index + 8192 - self._length2, len_data) - self._hash2.update(data_mem[index:new_index]) - self._length2 += new_index - index - index = new_index + # LONG_MSG_SX + assert self._state == LONG_MSG_SX + index = 0 + len_data = len(data) - if self._length2 == 8192: - cv_i = self._hash2.read(32) - self._hash1.update(cv_i) - self._length1 += 32 - self._hash2._reset() - self._length2 = 0 - self._ctr += 1 + # All iteractions could actually run in parallel + data_mem = memoryview(data) + while index < len_data: + new_index = min(index + 8192 - self._length2, len_data) + self._hash2.update(data_mem[index:new_index]) + self._length2 += new_index - index + index = new_index - return self + if self._length2 == 8192: + cv_i = self._hash2.read(32) + self._hash1.update(cv_i) + self._length1 += 32 + self._hash2._reset() + self._length2 = 0 + self._ctr += 1 - def read(self, length): - """ - Produce more bytes of the digest. + return self - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. + def read(self, length): + """ + Produce more bytes of the digest. - Args: - length (integer): the amount of bytes this method must return + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ + Args: + length (integer): the amount of bytes this method must return - custom_was_consumed = False + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ - if self._state == SHORT_MSG: - self._hash1.update(self._custom) - self._padding = 0x07 - self._state = SQUEEZING + custom_was_consumed = False - if self._state == LONG_MSG_S0: - self.update(self._custom) - custom_was_consumed = True - assert(self._state == LONG_MSG_SX) + if self._state == SHORT_MSG: + self._hash1.update(self._custom) + self._padding = 0x07 + self._state = SQUEEZING - if self._state == LONG_MSG_SX: - if not custom_was_consumed: - self.update(self._custom) + if self._state == LONG_MSG_S0: + self.update(self._custom) + custom_was_consumed = True + assert self._state == LONG_MSG_SX - # Is there still some leftover data in hash2? - if self._length2 > 0: - cv_i = self._hash2.read(32) - self._hash1.update(cv_i) - self._length1 += 32 - self._hash2._reset() - self._length2 = 0 - self._ctr += 1 + if self._state == LONG_MSG_SX: + if not custom_was_consumed: + self.update(self._custom) - trailer = _length_encode(self._ctr - 1) + b'\xFF\xFF' - self._hash1.update(trailer) + # Is there still some leftover data in hash2? + if self._length2 > 0: + cv_i = self._hash2.read(32) + self._hash1.update(cv_i) + self._length1 += 32 + self._hash2._reset() + self._length2 = 0 + self._ctr += 1 - self._padding = 0x06 - self._state = SQUEEZING + trailer = _length_encode(self._ctr - 1) + b"\xff\xff" + self._hash1.update(trailer) - self._hash1._domain = self._padding - return self._hash1.read(length) + self._padding = 0x06 + self._state = SQUEEZING + + self._hash1._domain = self._padding + return self._hash1.read(length) - def new(self, data=None, custom=b''): - return type(self)(data, custom) + def new(self, data=None, custom=b""): + return type(self)(data, custom) def new(data=None, custom=None): - """Return a fresh instance of a KangarooTwelve object. + """Return a fresh instance of a KangarooTwelve object. - Args: - data (bytes/bytearray/memoryview): - Optional. - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - custom (bytes): - Optional. - A customization byte string. + Args: + data (bytes/bytearray/memoryview): + Optional. + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + custom (bytes): + Optional. + A customization byte string. - :Return: A :class:`K12_XOF` object - """ + :Return: A :class:`K12_XOF` object + """ - return K12_XOF(data, custom) + return K12_XOF(data, custom) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KangarooTwelve.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KangarooTwelve.pyi index 8b3fd74f..acf09644 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KangarooTwelve.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/KangarooTwelve.pyi @@ -3,14 +3,9 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class K12_XOF(object): - def __init__(self, - data: Optional[Buffer] = ..., - custom: Optional[bytes] = ...) -> None: ... - def update(self, data: Buffer) -> K12_XOF: ... - def read(self, length: int) -> bytes: ... - def new(self, - data: Optional[Buffer] = ..., - custom: Optional[bytes] = ...) -> None: ... + def __init__(self, data: Optional[Buffer] = ..., custom: Optional[bytes] = ...) -> None: ... + def update(self, data: Buffer) -> K12_XOF: ... + def read(self, length: int) -> bytes: ... + def new(self, data: Optional[Buffer] = ..., custom: Optional[bytes] = ...) -> None: ... -def new(data: Optional[Buffer] = ..., - custom: Optional[Buffer] = ...) -> K12_XOF: ... +def new(data: Optional[Buffer] = ..., custom: Optional[Buffer] = ...) -> K12_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD2.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD2.py index 47ecc05f..9792e682 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD2.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD2.py @@ -30,15 +30,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) _raw_md2_lib = load_pycryptodome_raw_lib( - "Cryptodome.Hash._MD2", - """ + "Cryptodome.Hash._MD2", + """ int md2_init(void **shaState); int md2_destroy(void *shaState); int md2_update(void *hs, @@ -47,117 +51,130 @@ int md2_digest(const void *shaState, uint8_t digest[20]); int md2_copy(const void *src, void *dst); - """) + """, +) class MD2Hash(object): - """An MD2 hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 16 - # The internal block size of the hash algorithm in bytes. - block_size = 16 - # ASN.1 Object ID - oid = "1.2.840.113549.2.2" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_md2_lib.md2_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating MD2" - % result) - self._state = SmartPointer(state.get(), - _raw_md2_lib.md2_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_md2_lib.md2_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating MD2" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_md2_lib.md2_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating MD2" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = MD2Hash() - result = _raw_md2_lib.md2_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying MD2" % result) - return clone - - def new(self, data=None): - return MD2Hash(data) + """An MD2 hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 16 + # The internal block size of the hash algorithm in bytes. + block_size = 16 + # ASN.1 Object ID + oid = "1.2.840.113549.2.2" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_md2_lib.md2_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating MD2" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_md2_lib.md2_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_md2_lib.md2_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating MD2" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_md2_lib.md2_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating MD2" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = MD2Hash() + result = _raw_md2_lib.md2_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying MD2" % result) + return clone + + def new(self, data=None): + return MD2Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`MD2Hash.update`. - :type data: bytes/bytearray/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`MD2Hash.update`. + :type data: bytes/bytearray/memoryview - :Return: A :class:`MD2Hash` hash object - """ + :Return: A :class:`MD2Hash` hash object + """ + + return MD2Hash().new(data) - return MD2Hash().new(data) # The size of the resulting hash in bytes. digest_size = MD2Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD2.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD2.pyi index 95a97a9e..8b1425f0 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD2.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD2.pyi @@ -3,17 +3,18 @@ from typing import Union Buffer = Union[bytes, bytearray, memoryview] class MD4Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Buffer = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> MD4Hash: ... - def new(self, data: Buffer = ...) -> MD4Hash: ... + def __init__(self, data: Buffer = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> MD4Hash: ... + def new(self, data: Buffer = ...) -> MD4Hash: ... def new(data: Buffer = ...) -> MD4Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD4.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD4.py index 668fa653..ce7224c4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD4.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD4.py @@ -45,15 +45,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) _raw_md4_lib = load_pycryptodome_raw_lib( - "Cryptodome.Hash._MD4", - """ + "Cryptodome.Hash._MD4", + """ int md4_init(void **shaState); int md4_destroy(void *shaState); int md4_update(void *hs, @@ -62,121 +66,133 @@ int md4_digest(const void *shaState, uint8_t digest[20]); int md4_copy(const void *src, void *dst); - """) + """, +) class MD4Hash(object): - """Class that implements an MD4 hash - """ - - #: The size of the resulting hash in bytes. - digest_size = 16 - #: The internal block size of the hash algorithm in bytes. - block_size = 64 - #: ASN.1 Object ID - oid = "1.2.840.113549.2.4" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_md4_lib.md4_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating MD4" - % result) - self._state = SmartPointer(state.get(), - _raw_md4_lib.md4_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Repeated calls are equivalent to a single call with the concatenation - of all the arguments. In other words: - - >>> m.update(a); m.update(b) - - is equivalent to: - - >>> m.update(a+b) - - :Parameters: - data : byte string/byte array/memoryview - The next chunk of the message being hashed. - """ - - result = _raw_md4_lib.md4_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating MD4" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that - has been hashed so far. - - This method does not change the state of the hash object. - You can continue updating the object after calling this function. - - :Return: A byte string of `digest_size` bytes. It may contain non-ASCII - characters, including null bytes. - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_md4_lib.md4_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating MD4" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been - hashed so far. - - This method does not change the state of the hash object. - - :Return: A string of 2* `digest_size` characters. It contains only - hexadecimal ASCII digits. - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :Return: A hash object of the same type - """ - - clone = MD4Hash() - result = _raw_md4_lib.md4_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying MD4" % result) - return clone - - def new(self, data=None): - return MD4Hash(data) + """Class that implements an MD4 hash""" + + #: The size of the resulting hash in bytes. + digest_size = 16 + #: The internal block size of the hash algorithm in bytes. + block_size = 64 + #: ASN.1 Object ID + oid = "1.2.840.113549.2.4" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_md4_lib.md4_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating MD4" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_md4_lib.md4_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Repeated calls are equivalent to a single call with the concatenation + of all the arguments. In other words: + + >>> m.update(a); m.update(b) + + is equivalent to: + + >>> m.update(a+b) + + :Parameters: + data : byte string/byte array/memoryview + The next chunk of the message being hashed. + """ + + result = _raw_md4_lib.md4_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating MD4" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that + has been hashed so far. + + This method does not change the state of the hash object. + You can continue updating the object after calling this function. + + :Return: A byte string of `digest_size` bytes. It may contain non-ASCII + characters, including null bytes. + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_md4_lib.md4_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating MD4" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been + hashed so far. + + This method does not change the state of the hash object. + + :Return: A string of 2* `digest_size` characters. It contains only + hexadecimal ASCII digits. + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :Return: A hash object of the same type + """ + + clone = MD4Hash() + result = _raw_md4_lib.md4_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying MD4" % result) + return clone + + def new(self, data=None): + return MD4Hash(data) def new(data=None): - """Return a fresh instance of the hash object. + """Return a fresh instance of the hash object. + + :Parameters: + data : byte string/byte array/memoryview + The very first chunk of the message to hash. + It is equivalent to an early call to `MD4Hash.update()`. + Optional. - :Parameters: - data : byte string/byte array/memoryview - The very first chunk of the message to hash. - It is equivalent to an early call to `MD4Hash.update()`. - Optional. + :Return: A `MD4Hash` object + """ + return MD4Hash().new(data) - :Return: A `MD4Hash` object - """ - return MD4Hash().new(data) #: The size of the resulting hash in bytes. digest_size = MD4Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD4.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD4.pyi index a9a72953..9f79ebde 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD4.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD4.pyi @@ -3,17 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class MD4Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> MD4Hash: ... - def new(self, data: Optional[Buffer] = ...) -> MD4Hash: ... + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> MD4Hash: ... + def new(self, data: Optional[Buffer] = ...) -> MD4Hash: ... def new(data: Optional[Buffer] = ...) -> MD4Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD5.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD5.py index 8f573a9b..d02a162f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD5.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD5.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import * -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_md5_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._MD5", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_md5_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._MD5", + """ #define MD5_DIGEST_SIZE 16 int MD5_init(void **shaState); @@ -44,118 +49,132 @@ const uint8_t first_digest[MD5_DIGEST_SIZE], uint8_t final_digest[MD5_DIGEST_SIZE], size_t iterations); - """) + """, +) + class MD5Hash(object): - """A MD5 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 16 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "1.2.840.113549.2.5" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_md5_lib.MD5_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating MD5" - % result) - self._state = SmartPointer(state.get(), - _raw_md5_lib.MD5_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_md5_lib.MD5_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating MD5" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_md5_lib.MD5_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating MD5" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = MD5Hash() - result = _raw_md5_lib.MD5_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying MD5" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-1 hash object.""" - - return MD5Hash(data) + """A MD5 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 16 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "1.2.840.113549.2.5" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_md5_lib.MD5_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating MD5" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_md5_lib.MD5_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_md5_lib.MD5_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating MD5" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_md5_lib.MD5_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating MD5" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = MD5Hash() + result = _raw_md5_lib.MD5_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying MD5" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-1 hash object.""" + + return MD5Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. + + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`MD5Hash.update`. + :type data: byte string/byte array/memoryview - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`MD5Hash.update`. - :type data: byte string/byte array/memoryview + :Return: A :class:`MD5Hash` hash object + """ + return MD5Hash().new(data) - :Return: A :class:`MD5Hash` hash object - """ - return MD5Hash().new(data) # The size of the resulting hash in bytes. digest_size = 16 @@ -165,20 +184,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert len(first_digest) == digest_size - assert iterations > 0 + assert len(first_digest) == digest_size + assert iterations > 0 - bfr = create_string_buffer(digest_size); - result = _raw_md5_lib.MD5_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations)) + bfr = create_string_buffer(digest_size) + result = _raw_md5_lib.MD5_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assis for MD5" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assis for MD5" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD5.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD5.pyi index d8195562..a8b7e084 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD5.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/MD5.pyi @@ -3,17 +3,18 @@ from typing import Union Buffer = Union[bytes, bytearray, memoryview] class MD5Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Buffer = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> MD5Hash: ... - def new(self, data: Buffer = ...) -> MD5Hash: ... + def __init__(self, data: Buffer = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> MD5Hash: ... + def new(self, data: Buffer = ...) -> MD5Hash: ... def new(data: Buffer = ...) -> MD5Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/Poly1305.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/Poly1305.py index c03f5229..993bfda1 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/Poly1305.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/Poly1305.py @@ -26,15 +26,20 @@ from Cryptodome.Hash import BLAKE2s from Cryptodome.Random import get_random_bytes -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - - -_raw_poly1305 = load_pycryptodome_raw_lib("Cryptodome.Hash._poly1305", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + + +_raw_poly1305 = load_pycryptodome_raw_lib( + "Cryptodome.Hash._poly1305", + """ int poly1305_init(void **state, const uint8_t *r, size_t r_len, @@ -47,171 +52,176 @@ int poly1305_digest(const void *state, uint8_t *digest, size_t len); - """) + """, +) class Poly1305_MAC(object): - """An Poly1305 MAC object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting MAC tag - :vartype digest_size: integer - """ - - digest_size = 16 - - def __init__(self, r, s, data): - - if len(r) != 16: - raise ValueError("Parameter r is not 16 bytes long") - if len(s) != 16: - raise ValueError("Parameter s is not 16 bytes long") - - self._mac_tag = None - - state = VoidPointer() - result = _raw_poly1305.poly1305_init(state.address_of(), - c_uint8_ptr(r), - c_size_t(len(r)), - c_uint8_ptr(s), - c_size_t(len(s)) - ) - if result: - raise ValueError("Error %d while instantiating Poly1305" % result) - self._state = SmartPointer(state.get(), - _raw_poly1305.poly1305_destroy) - if data: - self.update(data) - - def update(self, data): - """Authenticate the next chunk of message. - - Args: - data (byte string/byte array/memoryview): The next chunk of data - """ - - if self._mac_tag: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_poly1305.poly1305_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing Poly1305 data" % result) - return self - - def copy(self): - raise NotImplementedError() - - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message - authenticated so far. - - :return: The MAC tag digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - if self._mac_tag: - return self._mac_tag - - bfr = create_string_buffer(16) - result = _raw_poly1305.poly1305_digest(self._state.get(), - bfr, - c_size_t(len(bfr))) - if result: - raise ValueError("Error %d while creating Poly1305 digest" % result) - - self._mac_tag = get_raw_buffer(bfr) - return self._mac_tag - - def hexdigest(self): - """Return the **printable** MAC tag of the message authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) - for x in tuple(self.digest())]) - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte string/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, - as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - + """An Poly1305 MAC object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar digest_size: the size in bytes of the resulting MAC tag + :vartype digest_size: integer + """ + + digest_size = 16 + + def __init__(self, r, s, data): + if len(r) != 16: + raise ValueError("Parameter r is not 16 bytes long") + if len(s) != 16: + raise ValueError("Parameter s is not 16 bytes long") + + self._mac_tag = None + + state = VoidPointer() + result = _raw_poly1305.poly1305_init( + state.address_of(), + c_uint8_ptr(r), + c_size_t(len(r)), + c_uint8_ptr(s), + c_size_t(len(s)), + ) + if result: + raise ValueError("Error %d while instantiating Poly1305" % result) + self._state = SmartPointer( + state.get(), + _raw_poly1305.poly1305_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Authenticate the next chunk of message. + + Args: + data (byte string/byte array/memoryview): The next chunk of data + """ + + if self._mac_tag: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_poly1305.poly1305_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError("Error %d while hashing Poly1305 data" % result) + return self + + def copy(self): + raise NotImplementedError() + + def digest(self): + """Return the **binary** (non-printable) MAC tag of the message + authenticated so far. + + :return: The MAC tag digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + if self._mac_tag: + return self._mac_tag + + bfr = create_string_buffer(16) + result = _raw_poly1305.poly1305_digest( + self._state.get(), + bfr, + c_size_t(len(bfr)), + ) + if result: + raise ValueError("Error %d while creating Poly1305 digest" % result) + + self._mac_tag = get_raw_buffer(bfr) + return self._mac_tag + + def hexdigest(self): + """Return the **printable** MAC tag of the message authenticated so far. + + :return: The MAC tag, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) + is valid. + + Args: + mac_tag (byte string/byte string/memoryview): the expected MAC of the message. + + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) + + if mac1.digest() != mac2.digest(): + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) + is valid. + + Args: + hex_mac_tag (string): the expected MAC of the message, + as a hexadecimal string. + + Raises: + ValueError: if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + self.verify(unhexlify(tobytes(hex_mac_tag))) def new(**kwargs): - """Create a new Poly1305 MAC object. - - Args: - key (bytes/bytearray/memoryview): - The 32-byte key for the Poly1305 object. - cipher (module from ``Cryptodome.Cipher``): - The cipher algorithm to use for deriving the Poly1305 - key pair *(r, s)*. - It can only be ``Cryptodome.Cipher.AES`` or ``Cryptodome.Cipher.ChaCha20``. - nonce (bytes/bytearray/memoryview): - Optional. The non-repeatable value to use for the MAC of this message. - It must be 16 bytes long for ``AES`` and 8 or 12 bytes for ``ChaCha20``. - If not passed, a random nonce is created; you will find it in the - ``nonce`` attribute of the new object. - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to ``update()``. - - Returns: - A :class:`Poly1305_MAC` object - """ - - cipher = kwargs.pop("cipher", None) - if not hasattr(cipher, '_derive_Poly1305_key_pair'): - raise ValueError("Parameter 'cipher' must be AES or ChaCha20") - - cipher_key = kwargs.pop("key", None) - if cipher_key is None: - raise TypeError("You must pass a parameter 'key'") - - nonce = kwargs.pop("nonce", None) - data = kwargs.pop("data", None) - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - r, s, nonce = cipher._derive_Poly1305_key_pair(cipher_key, nonce) - - new_mac = Poly1305_MAC(r, s, data) - new_mac.nonce = _copy_bytes(None, None, nonce) # nonce may still be just a memoryview - return new_mac + """Create a new Poly1305 MAC object. + + Args: + key (bytes/bytearray/memoryview): + The 32-byte key for the Poly1305 object. + cipher (module from ``Cryptodome.Cipher``): + The cipher algorithm to use for deriving the Poly1305 + key pair *(r, s)*. + It can only be ``Cryptodome.Cipher.AES`` or ``Cryptodome.Cipher.ChaCha20``. + nonce (bytes/bytearray/memoryview): + Optional. The non-repeatable value to use for the MAC of this message. + It must be 16 bytes long for ``AES`` and 8 or 12 bytes for ``ChaCha20``. + If not passed, a random nonce is created; you will find it in the + ``nonce`` attribute of the new object. + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to authenticate. + It is equivalent to an early call to ``update()``. + + Returns: + A :class:`Poly1305_MAC` object + """ + + cipher = kwargs.pop("cipher", None) + if not hasattr(cipher, "_derive_Poly1305_key_pair"): + raise ValueError("Parameter 'cipher' must be AES or ChaCha20") + + cipher_key = kwargs.pop("key", None) + if cipher_key is None: + raise TypeError("You must pass a parameter 'key'") + + nonce = kwargs.pop("nonce", None) + data = kwargs.pop("data", None) + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + r, s, nonce = cipher._derive_Poly1305_key_pair(cipher_key, nonce) + + new_mac = Poly1305_MAC(r, s, data) + new_mac.nonce = _copy_bytes(None, None, nonce) # nonce may still be just a memoryview + return new_mac diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/Poly1305.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/Poly1305.pyi index f97a14a0..362f500a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/Poly1305.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/Poly1305.pyi @@ -4,21 +4,15 @@ from typing import Union Buffer = Union[bytes, bytearray, memoryview] class Poly1305_MAC(object): - block_size: int - digest_size: int - oid: str + block_size: int + digest_size: int + oid: str - def __init__(self, - r : int, - s : int, - data : Buffer) -> None: ... - def update(self, data: Buffer) -> Poly1305_MAC: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... + def __init__(self, r: int, s: int, data: Buffer) -> None: ... + def update(self, data: Buffer) -> Poly1305_MAC: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def verify(self, mac_tag: Buffer) -> None: ... + def hexverify(self, hex_mac_tag: str) -> None: ... -def new(key: Buffer, - cipher: ModuleType, - nonce: Buffer = ..., - data: Buffer = ...) -> Poly1305_MAC: ... +def new(key: Buffer, cipher: ModuleType, nonce: Buffer = ..., data: Buffer = ...) -> Poly1305_MAC: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD.py index 35ad576c..03717ec6 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD.py @@ -22,5 +22,3 @@ # Cryptodome.Hash.RIPEMD """Deprecated alias for `Cryptodome.Hash.RIPEMD160`""" - -from Cryptodome.Hash.RIPEMD160 import new, block_size, digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD160.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD160.py index f9590275..1487646c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD160.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD160.py @@ -30,15 +30,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) _raw_ripemd160_lib = load_pycryptodome_raw_lib( - "Cryptodome.Hash._RIPEMD160", - """ + "Cryptodome.Hash._RIPEMD160", + """ int ripemd160_init(void **shaState); int ripemd160_destroy(void *shaState); int ripemd160_update(void *hs, @@ -47,120 +51,133 @@ int ripemd160_digest(const void *shaState, uint8_t digest[20]); int ripemd160_copy(const void *src, void *dst); - """) + """, +) class RIPEMD160Hash(object): - """A RIPEMD-160 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 20 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "1.3.36.3.2.1" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_ripemd160_lib.ripemd160_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating RIPEMD160" - % result) - self._state = SmartPointer(state.get(), - _raw_ripemd160_lib.ripemd160_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_ripemd160_lib.ripemd160_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating ripemd160" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_ripemd160_lib.ripemd160_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating ripemd160" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = RIPEMD160Hash() - result = _raw_ripemd160_lib.ripemd160_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying ripemd160" % result) - return clone - - def new(self, data=None): - """Create a fresh RIPEMD-160 hash object.""" - - return RIPEMD160Hash(data) + """A RIPEMD-160 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 20 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "1.3.36.3.2.1" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_ripemd160_lib.ripemd160_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating RIPEMD160" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_ripemd160_lib.ripemd160_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_ripemd160_lib.ripemd160_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating ripemd160" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_ripemd160_lib.ripemd160_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating ripemd160" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = RIPEMD160Hash() + result = _raw_ripemd160_lib.ripemd160_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying ripemd160" % result) + return clone + + def new(self, data=None): + """Create a fresh RIPEMD-160 hash object.""" + + return RIPEMD160Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`RIPEMD160Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`RIPEMD160Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`RIPEMD160Hash` hash object - """ + :Return: A :class:`RIPEMD160Hash` hash object + """ + + return RIPEMD160Hash().new(data) - return RIPEMD160Hash().new(data) # The size of the resulting hash in bytes. digest_size = RIPEMD160Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD160.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD160.pyi index b6194737..9022e49a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD160.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/RIPEMD160.pyi @@ -3,17 +3,18 @@ from typing import Union Buffer = Union[bytes, bytearray, memoryview] class RIPEMD160Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Buffer = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> RIPEMD160Hash: ... - def new(self, data: Buffer = ...) -> RIPEMD160Hash: ... + def __init__(self, data: Buffer = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> RIPEMD160Hash: ... + def new(self, data: Buffer = ...) -> RIPEMD160Hash: ... def new(data: Buffer = ...) -> RIPEMD160Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA.py index 95f8745b..0fd021ea 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA.py @@ -21,4 +21,3 @@ # This file exists for backward compatibility with old code that refers to # Cryptodome.Hash.SHA -from Cryptodome.Hash.SHA1 import __doc__, new, block_size, digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA.pyi index 7d01a5f9..cfb22524 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA.pyi @@ -1,4 +1,3 @@ # This file exists for backward compatibility with old code that refers to # Cryptodome.Hash.SHA -from Cryptodome.Hash.SHA1 import __doc__, new, block_size, digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA1.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA1.py index dea51bce..add3b6e0 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA1.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA1.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import * -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha1_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA1", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha1_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA1", + """ #define SHA1_DIGEST_SIZE 20 int SHA1_init(void **shaState); @@ -44,118 +49,131 @@ const uint8_t first_digest[SHA1_DIGEST_SIZE], uint8_t final_digest[SHA1_DIGEST_SIZE], size_t iterations); - """) + """, +) + class SHA1Hash(object): - """A SHA-1 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 20 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "1.3.14.3.2.26" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha1_lib.SHA1_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA1" - % result) - self._state = SmartPointer(state.get(), - _raw_sha1_lib.SHA1_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha1_lib.SHA1_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating SHA1" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha1_lib.SHA1_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating SHA1" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA1Hash() - result = _raw_sha1_lib.SHA1_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA1" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-1 hash object.""" - - return SHA1Hash(data) + """A SHA-1 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 20 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "1.3.14.3.2.26" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_sha1_lib.SHA1_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating SHA1" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha1_lib.SHA1_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha1_lib.SHA1_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA1" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha1_lib.SHA1_digest( + self._state.get(), + bfr, + ) + if result: + raise ValueError( + "Error %d while instantiating SHA1" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA1Hash() + result = _raw_sha1_lib.SHA1_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA1" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-1 hash object.""" + + return SHA1Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA1Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA1Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`SHA1Hash` hash object - """ - return SHA1Hash().new(data) + :Return: A :class:`SHA1Hash` hash object + """ + return SHA1Hash().new(data) # The size of the resulting hash in bytes. @@ -166,20 +184,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert len(first_digest) == digest_size - assert iterations > 0 + assert len(first_digest) == digest_size + assert iterations > 0 - bfr = create_string_buffer(digest_size); - result = _raw_sha1_lib.SHA1_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations)) + bfr = create_string_buffer(digest_size) + result = _raw_sha1_lib.SHA1_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assis for SHA1" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assis for SHA1" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA1.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA1.pyi index d6c8e25e..6b05ebc4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA1.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA1.pyi @@ -3,17 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA1Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA1Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA1Hash: ... + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA1Hash: ... + def new(self, data: Optional[Buffer] = ...) -> SHA1Hash: ... def new(data: Optional[Buffer] = ...) -> SHA1Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA224.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA224.py index fca7622e..04a1c505 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA224.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA224.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha224_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA224", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha224_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA224", + """ int SHA224_init(void **shaState); int SHA224_destroy(void *shaState); int SHA224_update(void *hs, @@ -44,119 +49,132 @@ uint8_t *final_digest, size_t iterations, size_t digest_size); - """) + """, +) + class SHA224Hash(object): - """A SHA-224 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 28 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = '2.16.840.1.101.3.4.2.4' - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha224_lib.SHA224_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA224" - % result) - self._state = SmartPointer(state.get(), - _raw_sha224_lib.SHA224_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha224_lib.SHA224_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA224" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha224_lib.SHA224_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA224 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA224Hash() - result = _raw_sha224_lib.SHA224_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA224" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-224 hash object.""" - - return SHA224Hash(data) + """A SHA-224 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 28 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.4" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_sha224_lib.SHA224_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating SHA224" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha224_lib.SHA224_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha224_lib.SHA224_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while hashing data with SHA224" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha224_lib.SHA224_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while making SHA224 digest" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA224Hash() + result = _raw_sha224_lib.SHA224_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA224" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-224 hash object.""" + + return SHA224Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA224Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA224Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`SHA224Hash` hash object - """ - return SHA224Hash().new(data) + :Return: A :class:`SHA224Hash` hash object + """ + return SHA224Hash().new(data) # The size of the resulting hash in bytes. @@ -167,20 +185,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert iterations > 0 + assert iterations > 0 - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha224_lib.SHA224_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) + bfr = create_string_buffer(len(first_digest)) + result = _raw_sha224_lib.SHA224_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + c_size_t(len(first_digest)), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA224" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assist for SHA224" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA224.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA224.pyi index 613a7f9a..65d18ed1 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA224.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA224.pyi @@ -3,17 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA224Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA224Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA224Hash: ... + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA224Hash: ... + def new(self, data: Optional[Buffer] = ...) -> SHA224Hash: ... def new(data: Optional[Buffer] = ...) -> SHA224Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA256.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA256.py index c1a81b1d..a538ef34 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA256.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA256.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha256_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA256", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha256_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA256", + """ int SHA256_init(void **shaState); int SHA256_destroy(void *shaState); int SHA256_update(void *hs, @@ -44,118 +49,132 @@ uint8_t *final_digest, size_t iterations, size_t digest_size); - """) + """, +) + class SHA256Hash(object): - """A SHA-256 hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 32 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.1" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha256_lib.SHA256_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA256" - % result) - self._state = SmartPointer(state.get(), - _raw_sha256_lib.SHA256_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha256_lib.SHA256_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA256" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha256_lib.SHA256_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA256 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA256Hash() - result = _raw_sha256_lib.SHA256_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA256" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-256 hash object.""" - - return SHA256Hash(data) + """A SHA-256 hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 32 + # The internal block size of the hash algorithm in bytes. + block_size = 64 + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.1" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_sha256_lib.SHA256_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating SHA256" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha256_lib.SHA256_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha256_lib.SHA256_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while hashing data with SHA256" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha256_lib.SHA256_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while making SHA256 digest" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA256Hash() + result = _raw_sha256_lib.SHA256_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA256" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-256 hash object.""" + + return SHA256Hash(data) + def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA256Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA256Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`SHA256Hash` hash object - """ + :Return: A :class:`SHA256Hash` hash object + """ - return SHA256Hash().new(data) + return SHA256Hash().new(data) # The size of the resulting hash in bytes. @@ -166,20 +185,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert iterations > 0 + assert iterations > 0 - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha256_lib.SHA256_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) + bfr = create_string_buffer(len(first_digest)) + result = _raw_sha256_lib.SHA256_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + c_size_t(len(first_digest)), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA256" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assist for SHA256" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA256.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA256.pyi index cbf21bfb..3521cff9 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA256.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA256.pyi @@ -1,18 +1,17 @@ from typing import Union, Optional - class SHA256Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> None: ... - def update(self, data: Union[bytes, bytearray, memoryview]) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA256Hash: ... - def new(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Union[bytes, bytearray, memoryview]] = None) -> None: ... + def update(self, data: Union[bytes, bytearray, memoryview]) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA256Hash: ... + def new(self, data: Optional[Union[bytes, bytearray, memoryview]] = None) -> SHA256Hash: ... -def new(data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ... +def new(data: Optional[Union[bytes, bytearray, memoryview]] = None) -> SHA256Hash: ... digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA384.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA384.py index 711aa73c..4c15f7ae 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA384.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA384.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha384_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA384", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha384_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA384", + """ int SHA384_init(void **shaState); int SHA384_destroy(void *shaState); int SHA384_update(void *hs, @@ -44,119 +49,132 @@ uint8_t *final_digest, size_t iterations, size_t digest_size); - """) + """, +) + class SHA384Hash(object): - """A SHA-384 hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 48 - # The internal block size of the hash algorithm in bytes. - block_size = 128 - # ASN.1 Object ID - oid = '2.16.840.1.101.3.4.2.2' - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha384_lib.SHA384_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA384" - % result) - self._state = SmartPointer(state.get(), - _raw_sha384_lib.SHA384_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha384_lib.SHA384_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA384" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha384_lib.SHA384_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA384 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA384Hash() - result = _raw_sha384_lib.SHA384_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA384" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-384 hash object.""" - - return SHA384Hash(data) + """A SHA-384 hash object. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 48 + # The internal block size of the hash algorithm in bytes. + block_size = 128 + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.2" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_sha384_lib.SHA384_init(state.address_of()) + if result: + raise ValueError( + "Error %d while instantiating SHA384" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha384_lib.SHA384_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha384_lib.SHA384_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while hashing data with SHA384" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha384_lib.SHA384_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while making SHA384 digest" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA384Hash() + result = _raw_sha384_lib.SHA384_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA384" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-384 hash object.""" + + return SHA384Hash(data) def new(data=None): - """Create a new hash object. + """Create a new hash object. - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA384Hash.update`. - :type data: byte string/byte array/memoryview + :parameter data: + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA384Hash.update`. + :type data: byte string/byte array/memoryview - :Return: A :class:`SHA384Hash` hash object - """ + :Return: A :class:`SHA384Hash` hash object + """ - return SHA384Hash().new(data) + return SHA384Hash().new(data) # The size of the resulting hash in bytes. @@ -167,20 +185,21 @@ def new(data=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert iterations > 0 + assert iterations > 0 - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha384_lib.SHA384_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) + bfr = create_string_buffer(len(first_digest)) + result = _raw_sha384_lib.SHA384_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + c_size_t(len(first_digest)), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA384" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assist for SHA384" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA384.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA384.pyi index c2aab9e0..249a6855 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA384.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA384.pyi @@ -3,17 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA384Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA384Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA384Hash: ... + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA384Hash: ... + def new(self, data: Optional[Buffer] = ...) -> SHA384Hash: ... def new(data: Optional[Buffer] = ...) -> SHA384Hash: ... + digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_224.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_224.py index 34888c56..bcac372c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_224.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_224.py @@ -20,152 +20,170 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib -class SHA3_224_Hash(object): - """A SHA3-224 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 28 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.7" - - # Input block size for HMAC - block_size = 144 - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x06 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHA-3/224" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data)) - ) - if result: - raise ValueError("Error %d while updating SHA-3/224" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while instantiating SHA-3/224" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA3-224" % result) - return clone - def new(self, data=None): - """Create a fresh SHA3-224 hash object.""" - - return type(self)(data, self._update_after_digest) +class SHA3_224_Hash(object): + """A SHA3-224 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 28 + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.7" + + # Input block size for HMAC + block_size = 144 + + def __init__(self, data, update_after_digest): + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x06 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/224" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHA-3/224" % result, + ) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/224" % result, + ) + + self._digest_value = get_raw_buffer(bfr) + return self._digest_value + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA3-224" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA3-224 hash object.""" + + return type(self)(data, self._update_after_digest) def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_224_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_224_Hash(data, update_after_digest) + """Create a new hash object. + + Args: + data (byte string/byte array/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + update_after_digest (boolean): + Whether :meth:`digest` can be followed by another :meth:`update` + (default: ``False``). + + :Return: A :class:`SHA3_224_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + if len(args) == 1: + if data: + raise ValueError("Initial data for hash specified twice") + data = args[0] + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return SHA3_224_Hash(data, update_after_digest) + # The size of the resulting hash in bytes. digest_size = SHA3_224_Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_224.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_224.pyi index 21808219..3f3896ea 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_224.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_224.pyi @@ -3,15 +3,15 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA3_224_Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_224_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA3_224_Hash: ... - def new(self, data: Optional[Buffer]) -> SHA3_224_Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> SHA3_224_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA3_224_Hash: ... + def new(self, data: Optional[Buffer]) -> SHA3_224_Hash: ... def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_224_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_256.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_256.py index 024962fa..a0b99c01 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_256.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_256.py @@ -20,152 +20,170 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib -class SHA3_256_Hash(object): - """A SHA3-256 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 32 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.8" - - # Input block size for HMAC - block_size = 136 - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x06 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHA-3/256" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data)) - ) - if result: - raise ValueError("Error %d while updating SHA-3/256" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while instantiating SHA-3/256" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA3-256" % result) - return clone - def new(self, data=None): - """Create a fresh SHA3-256 hash object.""" - - return type(self)(data, self._update_after_digest) +class SHA3_256_Hash(object): + """A SHA3-256 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 32 + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.8" + + # Input block size for HMAC + block_size = 136 + + def __init__(self, data, update_after_digest): + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x06 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/256" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHA-3/256" % result, + ) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/256" % result, + ) + + self._digest_value = get_raw_buffer(bfr) + return self._digest_value + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA3-256" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA3-256 hash object.""" + + return type(self)(data, self._update_after_digest) def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_256_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_256_Hash(data, update_after_digest) + """Create a new hash object. + + Args: + data (byte string/byte array/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + update_after_digest (boolean): + Whether :meth:`digest` can be followed by another :meth:`update` + (default: ``False``). + + :Return: A :class:`SHA3_256_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + if len(args) == 1: + if data: + raise ValueError("Initial data for hash specified twice") + data = args[0] + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return SHA3_256_Hash(data, update_after_digest) + # The size of the resulting hash in bytes. digest_size = SHA3_256_Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_256.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_256.pyi index 88436bd8..731c6229 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_256.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_256.pyi @@ -3,15 +3,15 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA3_256_Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_256_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA3_256_Hash: ... - def new(self, data: Optional[Buffer]) -> SHA3_256_Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> SHA3_256_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA3_256_Hash: ... + def new(self, data: Optional[Buffer]) -> SHA3_256_Hash: ... def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_256_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_384.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_384.py index 26eeb791..227fd234 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_384.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_384.py @@ -20,157 +20,175 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib -class SHA3_384_Hash(object): - """A SHA3-384 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 48 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.9" - - # Input block size for HMAC - block_size = 104 - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x06 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHA-3/384" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHA-3/384" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while instantiating SHA-3/384" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ +class SHA3_384_Hash(object): + """A SHA3-384 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 48 + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.9" + + # Input block size for HMAC + block_size = 104 + + def __init__(self, data, update_after_digest): + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x06 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/384" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHA-3/384" % result, + ) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/384" % result, + ) + + self._digest_value = get_raw_buffer(bfr) + return self._digest_value + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA3-384" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA3-256 hash object.""" + + return type(self)(data, self._update_after_digest) + + def new(self, data=None): + """Create a fresh SHA3-384 hash object.""" + + return type(self)(data, self._update_after_digest) - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA3-384" % result) - return clone - def new(self, data=None): - """Create a fresh SHA3-256 hash object.""" +def new(*args, **kwargs): + """Create a new hash object. - return type(self)(data, self._update_after_digest) + Args: + data (byte string/byte array/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + update_after_digest (boolean): + Whether :meth:`digest` can be followed by another :meth:`update` + (default: ``False``). + :Return: A :class:`SHA3_384_Hash` hash object + """ - def new(self, data=None): - """Create a fresh SHA3-384 hash object.""" + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + if len(args) == 1: + if data: + raise ValueError("Initial data for hash specified twice") + data = args[0] - return type(self)(data, self._update_after_digest) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + return SHA3_384_Hash(data, update_after_digest) -def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_384_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_384_Hash(data, update_after_digest) # The size of the resulting hash in bytes. digest_size = SHA3_384_Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_384.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_384.pyi index 98d00c6c..2f35bde4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_384.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_384.pyi @@ -3,15 +3,15 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA3_384_Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_384_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA3_384_Hash: ... - def new(self, data: Optional[Buffer]) -> SHA3_384_Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> SHA3_384_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA3_384_Hash: ... + def new(self, data: Optional[Buffer]) -> SHA3_384_Hash: ... def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_384_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_512.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_512.py index 99b1c37a..23e0c45c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_512.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_512.py @@ -20,152 +20,170 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib -class SHA3_512_Hash(object): - """A SHA3-512 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 64 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.10" - - # Input block size for HMAC - block_size = 72 - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x06 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHA-3/512" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHA-3/512" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while instantiating SHA-3/512" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) +class SHA3_512_Hash(object): + """A SHA3-512 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The size of the resulting hash in bytes. + digest_size = 64 + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.10" + + # Input block size for HMAC + block_size = 72 + + def __init__(self, data, update_after_digest): + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x06 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/512" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHA-3/512" % result, + ) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-3/512" % result, + ) + + self._digest_value = get_raw_buffer(bfr) + return self._digest_value + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA3-512" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA3-521 hash object.""" + + return type(self)(data, self._update_after_digest) - def copy(self): - """Return a copy ("clone") of the hash object. - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. +def new(*args, **kwargs): + """Create a new hash object. - :return: A hash object of the same type - """ + Args: + data (byte string/byte array/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + update_after_digest (boolean): + Whether :meth:`digest` can be followed by another :meth:`update` + (default: ``False``). - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA3-512" % result) - return clone + :Return: A :class:`SHA3_512_Hash` hash object + """ - def new(self, data=None): - """Create a fresh SHA3-521 hash object.""" + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + if len(args) == 1: + if data: + raise ValueError("Initial data for hash specified twice") + data = args[0] - return type(self)(data, self._update_after_digest) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + return SHA3_512_Hash(data, update_after_digest) -def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_512_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_512_Hash(data, update_after_digest) # The size of the resulting hash in bytes. digest_size = SHA3_512_Hash.digest_size diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_512.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_512.pyi index cdeec165..79ff19fc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_512.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA3_512.pyi @@ -3,15 +3,15 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA3_512_Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_512_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA3_512_Hash: ... - def new(self, data: Optional[Buffer]) -> SHA3_512_Hash: ... + digest_size: int + block_size: int + oid: str + def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> SHA3_512_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA3_512_Hash: ... + def new(self, data: Optional[Buffer]) -> SHA3_512_Hash: ... def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_512_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA512.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA512.py index 5066197a..e9bb53a9 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA512.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA512.py @@ -20,14 +20,19 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha512_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA512", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, +) + +_raw_sha512_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._SHA512", + """ int SHA512_init(void **shaState, size_t digest_size); int SHA512_destroy(void *shaState); @@ -45,136 +50,151 @@ uint8_t *final_digest, size_t iterations, size_t digest_size); - """) + """, +) + class SHA512Hash(object): - """A SHA-512 hash object (possibly in its truncated version SHA-512/224 or - SHA-512/256. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The internal block size of the hash algorithm in bytes. - block_size = 128 - - def __init__(self, data, truncate): - self._truncate = truncate - - if truncate is None: - self.oid = "2.16.840.1.101.3.4.2.3" - self.digest_size = 64 - elif truncate == "224": - self.oid = "2.16.840.1.101.3.4.2.5" - self.digest_size = 28 - elif truncate == "256": - self.oid = "2.16.840.1.101.3.4.2.6" - self.digest_size = 32 - else: - raise ValueError("Incorrect truncation length. It must be '224' or '256'.") - - state = VoidPointer() - result = _raw_sha512_lib.SHA512_init(state.address_of(), - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while instantiating SHA-512" - % result) - self._state = SmartPointer(state.get(), - _raw_sha512_lib.SHA512_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha512_lib.SHA512_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA512" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha512_lib.SHA512_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA512 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA512Hash(None, self._truncate) - result = _raw_sha512_lib.SHA512_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA512" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-512 hash object.""" - - return SHA512Hash(data, self._truncate) + """A SHA-512 hash object (possibly in its truncated version SHA-512/224 or + SHA-512/256. + Do not instantiate directly. Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + + :ivar block_size: the size in bytes of the internal message block, + input to the compression function + :vartype block_size: integer + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + # The internal block size of the hash algorithm in bytes. + block_size = 128 + + def __init__(self, data, truncate): + self._truncate = truncate + + if truncate is None: + self.oid = "2.16.840.1.101.3.4.2.3" + self.digest_size = 64 + elif truncate == "224": + self.oid = "2.16.840.1.101.3.4.2.5" + self.digest_size = 28 + elif truncate == "256": + self.oid = "2.16.840.1.101.3.4.2.6" + self.digest_size = 32 + else: + raise ValueError("Incorrect truncation length. It must be '224' or '256'.") + + state = VoidPointer() + result = _raw_sha512_lib.SHA512_init( + state.address_of(), + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while instantiating SHA-512" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_sha512_lib.SHA512_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + result = _raw_sha512_lib.SHA512_update( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while hashing data with SHA512" % result, + ) + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + bfr = create_string_buffer(self.digest_size) + result = _raw_sha512_lib.SHA512_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + ) + if result: + raise ValueError( + "Error %d while making SHA512 digest" % result, + ) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + This can be used to efficiently compute the digests of strings that + share a common initial substring. + + :return: A hash object of the same type + """ + + clone = SHA512Hash(None, self._truncate) + result = _raw_sha512_lib.SHA512_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHA512" % result) + return clone + + def new(self, data=None): + """Create a fresh SHA-512 hash object.""" + + return SHA512Hash(data, self._truncate) def new(data=None, truncate=None): - """Create a new hash object. + """Create a new hash object. - Args: - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA512Hash.update`. - truncate (string): - Optional. The desired length of the digest. It can be either "224" or - "256". If not present, the digest is 512 bits long. - Passing this parameter is **not** equivalent to simply truncating - the output digest. + Args: + data (bytes/bytearray/memoryview): + Optional. The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`SHA512Hash.update`. + truncate (string): + Optional. The desired length of the digest. It can be either "224" or + "256". If not present, the digest is 512 bits long. + Passing this parameter is **not** equivalent to simply truncating + the output digest. - :Return: A :class:`SHA512Hash` hash object - """ + :Return: A :class:`SHA512Hash` hash object + """ - return SHA512Hash(data, truncate) + return SHA512Hash(data, truncate) # The size of the full SHA-512 hash in bytes. @@ -185,20 +205,21 @@ def new(data=None, truncate=None): def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" + """Compute the expensive inner loop in PBKDF-HMAC.""" - assert iterations > 0 + assert iterations > 0 - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha512_lib.SHA512_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) + bfr = create_string_buffer(len(first_digest)) + result = _raw_sha512_lib.SHA512_pbkdf2_hmac_assist( + inner._state.get(), + outer._state.get(), + first_digest, + bfr, + c_size_t(iterations), + c_size_t(len(first_digest)), + ) - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA512" % result) + if result: + raise ValueError("Error %d with PBKDF2-HMAC assist for SHA512" % result) - return get_raw_buffer(bfr) + return get_raw_buffer(bfr) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA512.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA512.pyi index f219ee94..7b7f7c29 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA512.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHA512.pyi @@ -3,20 +3,18 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHA512Hash(object): - digest_size: int - block_size: int - oid: str + digest_size: int + block_size: int + oid: str - def __init__(self, - data: Optional[Buffer], - truncate: Optional[str]) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA512Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA512Hash: ... + def __init__(self, data: Optional[Buffer], truncate: Optional[str]) -> None: ... + def update(self, data: Buffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> SHA512Hash: ... + def new(self, data: Optional[Buffer] = ...) -> SHA512Hash: ... + +def new(data: Optional[Buffer] = ..., truncate: Optional[str] = ...) -> SHA512Hash: ... -def new(data: Optional[Buffer] = ..., - truncate: Optional[str] = ...) -> SHA512Hash: ... digest_size: int block_size: int diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE128.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE128.py index 847b5141..6e9dbb06 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE128.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE128.py @@ -28,118 +28,135 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib + class SHAKE128_XOF(object): - """A SHAKE128 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - """ - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.11" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(32), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHAKE128" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - self._is_squeezing = False - self._padding = 0x1F - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHAKE128 state" - % result) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while extracting from SHAKE128" - % result) - - return get_raw_buffer(bfr) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - - :return: A hash object of the same type - """ - - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHAKE128" % result) - return clone - - def new(self, data=None): - return type(self)(data=data) + """A SHAKE128 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + """ + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.11" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(32), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHAKE128" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + self._is_squeezing = False + self._padding = 0x1F + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._is_squeezing: + raise TypeError("You cannot call 'update' after the first 'read'") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHAKE128 state" % result, + ) + return self + + def read(self, length): + """ + Compute the next piece of XOF output. + + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. + + Args: + length (integer): the amount of bytes this method must return + + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ + + self._is_squeezing = True + bfr = create_string_buffer(length) + result = _raw_keccak_lib.keccak_squeeze( + self._state.get(), + bfr, + c_size_t(length), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while extracting from SHAKE128" % result, + ) + + return get_raw_buffer(bfr) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHAKE128" % result) + return clone + + def new(self, data=None): + return type(self)(data=data) def new(data=None): - """Return a fresh instance of a SHAKE128 object. + """Return a fresh instance of a SHAKE128 object. - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - Optional. + Args: + data (bytes/bytearray/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + Optional. - :Return: A :class:`SHAKE128_XOF` object - """ + :Return: A :class:`SHAKE128_XOF` object + """ - return SHAKE128_XOF(data=data) + return SHAKE128_XOF(data=data) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE128.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE128.pyi index de51d8ea..c585628f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE128.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE128.pyi @@ -3,12 +3,11 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHAKE128_XOF(object): - oid: str - def __init__(self, - data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> SHAKE128_XOF: ... - def read(self, length: int) -> bytes: ... - def copy(self) -> SHAKE128_XOF: ... - def new(self, data: Optional[Buffer] = ...) -> SHAKE128_XOF: ... + oid: str + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> SHAKE128_XOF: ... + def read(self, length: int) -> bytes: ... + def copy(self) -> SHAKE128_XOF: ... + def new(self, data: Optional[Buffer] = ...) -> SHAKE128_XOF: ... def new(data: Optional[Buffer] = ...) -> SHAKE128_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE256.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE256.py index 637044eb..2623852f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE256.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE256.py @@ -28,119 +28,136 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Hash.keccak import _raw_keccak_lib + class SHAKE256_XOF(object): - """A SHAKE256 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - """ - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.12" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(64), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating SHAKE256" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - self._is_squeezing = False - self._padding = 0x1F - - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHAKE256 state" - % result) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while extracting from SHAKE256" - % result) - - return get_raw_buffer(bfr) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - - :return: A hash object of the same type - """ - - clone = self.new() - result = _raw_keccak_lib.keccak_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHAKE256" % result) - return clone - - def new(self, data=None): - return type(self)(data=data) + """A SHAKE256 hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar oid: ASN.1 Object ID + :vartype oid: string + """ + + # ASN.1 Object ID + oid = "2.16.840.1.101.3.4.2.12" + + def __init__(self, data=None): + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(64), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating SHAKE256" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + self._is_squeezing = False + self._padding = 0x1F + + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._is_squeezing: + raise TypeError("You cannot call 'update' after the first 'read'") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating SHAKE256 state" % result, + ) + return self + + def read(self, length): + """ + Compute the next piece of XOF output. + + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. + + Args: + length (integer): the amount of bytes this method must return + + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ + + self._is_squeezing = True + bfr = create_string_buffer(length) + result = _raw_keccak_lib.keccak_squeeze( + self._state.get(), + bfr, + c_size_t(length), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while extracting from SHAKE256" % result, + ) + + return get_raw_buffer(bfr) + + def copy(self): + """Return a copy ("clone") of the hash object. + + The copy will have the same internal state as the original hash + object. + + :return: A hash object of the same type + """ + + clone = self.new() + result = _raw_keccak_lib.keccak_copy( + self._state.get(), + clone._state.get(), + ) + if result: + raise ValueError("Error %d while copying SHAKE256" % result) + return clone + + def new(self, data=None): + return type(self)(data=data) def new(data=None): - """Return a fresh instance of a SHAKE256 object. + """Return a fresh instance of a SHAKE256 object. - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - Optional. + Args: + data (bytes/bytearray/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + Optional. - :Return: A :class:`SHAKE256_XOF` object - """ + :Return: A :class:`SHAKE256_XOF` object + """ - return SHAKE256_XOF(data=data) + return SHAKE256_XOF(data=data) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE256.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE256.pyi index 72eb8985..3660833d 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE256.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/SHAKE256.pyi @@ -3,12 +3,11 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class SHAKE256_XOF(object): - oid: str - def __init__(self, - data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> SHAKE256_XOF: ... - def read(self, length: int) -> bytes: ... - def copy(self) -> SHAKE256_XOF: ... - def new(self, data: Optional[Buffer] = ...) -> SHAKE256_XOF: ... + oid: str + def __init__(self, data: Optional[Buffer] = ...) -> None: ... + def update(self, data: Buffer) -> SHAKE256_XOF: ... + def read(self, length: int) -> bytes: ... + def copy(self) -> SHAKE256_XOF: ... + def new(self, data: Optional[Buffer] = ...) -> SHAKE256_XOF: ... def new(data: Optional[Buffer] = ...) -> SHAKE256_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash128.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash128.py index 49aeccc5..a5677c14 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash128.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash128.py @@ -28,109 +28,109 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util.py3compat import bord, is_bytes, tobytes +from Cryptodome.Util.py3compat import bord, is_bytes from . import cSHAKE128 from .cSHAKE128 import _encode_str, _right_encode class TupleHash(object): - """A Tuple hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ + """A Tuple hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ - def __init__(self, custom, cshake, digest_size): + def __init__(self, custom, cshake, digest_size): + self.digest_size = digest_size - self.digest_size = digest_size + self._cshake = cshake._new(b"", custom, b"TupleHash") + self._digest = None - self._cshake = cshake._new(b'', custom, b'TupleHash') - self._digest = None + def update(self, *data): + """Authenticate the next tuple of byte strings. + TupleHash guarantees the logical separation between each byte string. - def update(self, *data): - """Authenticate the next tuple of byte strings. - TupleHash guarantees the logical separation between each byte string. + Args: + data (bytes/bytearray/memoryview): One or more items to hash. + """ - Args: - data (bytes/bytearray/memoryview): One or more items to hash. - """ + if self._digest is not None: + raise TypeError("You cannot call 'update' after 'digest' or 'hexdigest'") - if self._digest is not None: - raise TypeError("You cannot call 'update' after 'digest' or 'hexdigest'") + for item in data: + if not is_bytes(item): + raise TypeError("You can only call 'update' on bytes") + self._cshake.update(_encode_str(item)) - for item in data: - if not is_bytes(item): - raise TypeError("You can only call 'update' on bytes" ) - self._cshake.update(_encode_str(item)) + return self - return self + def digest(self): + """Return the **binary** (non-printable) digest of the tuple of byte strings. - def digest(self): - """Return the **binary** (non-printable) digest of the tuple of byte strings. + :return: The hash digest. Binary form. + :rtype: byte string + """ - :return: The hash digest. Binary form. - :rtype: byte string - """ + if self._digest is None: + self._cshake.update(_right_encode(self.digest_size * 8)) + self._digest = self._cshake.read(self.digest_size) - if self._digest is None: - self._cshake.update(_right_encode(self.digest_size * 8)) - self._digest = self._cshake.read(self.digest_size) + return self._digest - return self._digest + def hexdigest(self): + """Return the **printable** digest of the tuple of byte strings. - def hexdigest(self): - """Return the **printable** digest of the tuple of byte strings. + :return: The hash digest. Hexadecimal encoded. + :rtype: string + """ - :return: The hash digest. Hexadecimal encoded. - :rtype: string - """ + return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) + def new(self, **kwargs): + """Return a new instance of a TupleHash object. + See :func:`new`. + """ - def new(self, **kwargs): - """Return a new instance of a TupleHash object. - See :func:`new`. - """ + if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: + kwargs["digest_bytes"] = self.digest_size - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) + return new(**kwargs) def new(**kwargs): - """Create a new TupleHash128 object. - - Args: - digest_bytes (integer): - Optional. The size of the digest, in bytes. - Default is 64. Minimum is 8. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (and in steps of 8). - Default is 512. Minimum is 64. - custom (bytes): - Optional. - A customization bytestring (``S`` in SP 800-185). - - :Return: A :class:`TupleHash` object - """ - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 64 - if digest_bytes is not None: - if digest_bytes < 8: - raise ValueError("'digest_bytes' must be at least 8") - else: - if digest_bits < 64 or digest_bits % 8: - raise ValueError("'digest_bytes' must be at least 64 " - "in steps of 8") - digest_bytes = digest_bits // 8 - - custom = kwargs.pop("custom", b'') - - return TupleHash(custom, cSHAKE128, digest_bytes) + """Create a new TupleHash128 object. + + Args: + digest_bytes (integer): + Optional. The size of the digest, in bytes. + Default is 64. Minimum is 8. + digest_bits (integer): + Optional and alternative to ``digest_bytes``. + The size of the digest, in bits (and in steps of 8). + Default is 512. Minimum is 64. + custom (bytes): + Optional. + A customization bytestring (``S`` in SP 800-185). + + :Return: A :class:`TupleHash` object + """ + + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + digest_bytes = 64 + if digest_bytes is not None: + if digest_bytes < 8: + raise ValueError("'digest_bytes' must be at least 8") + else: + if digest_bits < 64 or digest_bits % 8: + raise ValueError( + "'digest_bytes' must be at least 64 in steps of 8", + ) + digest_bytes = digest_bits // 8 + + custom = kwargs.pop("custom", b"") + + return TupleHash(custom, cSHAKE128, digest_bytes) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash128.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash128.pyi index 2e0ea833..3ef55a2d 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash128.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash128.pyi @@ -1,22 +1,14 @@ -from typing import Any, Union, List, Tuple +from typing import Union from types import ModuleType Buffer = Union[bytes, bytearray, memoryview] class TupleHash(object): - digest_size: int - def __init__(self, - custom: bytes, - cshake: ModuleType, - digest_size: int) -> None: ... - def update(self, *data: Buffer) -> TupleHash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def new(self, - digest_bytes: int = ..., - digest_bits: int = ..., - custom: int = ...) -> TupleHash: ... + digest_size: int + def __init__(self, custom: bytes, cshake: ModuleType, digest_size: int) -> None: ... + def update(self, *data: Buffer) -> TupleHash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def new(self, digest_bytes: int = ..., digest_bits: int = ..., custom: int = ...) -> TupleHash: ... -def new(digest_bytes: int = ..., - digest_bits: int = ..., - custom: int = ...) -> TupleHash: ... +def new(digest_bytes: int = ..., digest_bits: int = ..., custom: int = ...) -> TupleHash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash256.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash256.py index 40a824a9..d6a925b8 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash256.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash256.py @@ -33,38 +33,39 @@ def new(**kwargs): - """Create a new TupleHash256 object. + """Create a new TupleHash256 object. - Args: - digest_bytes (integer): - Optional. The size of the digest, in bytes. - Default is 64. Minimum is 8. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (and in steps of 8). - Default is 512. Minimum is 64. - custom (bytes): - Optional. - A customization bytestring (``S`` in SP 800-185). + Args: + digest_bytes (integer): + Optional. The size of the digest, in bytes. + Default is 64. Minimum is 8. + digest_bits (integer): + Optional and alternative to ``digest_bytes``. + The size of the digest, in bits (and in steps of 8). + Default is 512. Minimum is 64. + custom (bytes): + Optional. + A customization bytestring (``S`` in SP 800-185). - :Return: A :class:`TupleHash` object - """ + :Return: A :class:`TupleHash` object + """ - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 64 - if digest_bytes is not None: - if digest_bytes < 8: - raise ValueError("'digest_bytes' must be at least 8") - else: - if digest_bits < 64 or digest_bits % 8: - raise ValueError("'digest_bytes' must be at least 64 " - "in steps of 8") - digest_bytes = digest_bits // 8 + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + digest_bytes = 64 + if digest_bytes is not None: + if digest_bytes < 8: + raise ValueError("'digest_bytes' must be at least 8") + else: + if digest_bits < 64 or digest_bits % 8: + raise ValueError( + "'digest_bytes' must be at least 64 in steps of 8", + ) + digest_bytes = digest_bits // 8 - custom = kwargs.pop("custom", b'') + custom = kwargs.pop("custom", b"") - return TupleHash(custom, cSHAKE256, digest_bytes) + return TupleHash(custom, cSHAKE256, digest_bytes) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash256.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash256.pyi index 82d943f0..e6dfc87a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash256.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TupleHash256.pyi @@ -1,5 +1,3 @@ from .TupleHash128 import TupleHash -def new(digest_bytes: int = ..., - digest_bits: int = ..., - custom: int = ...) -> TupleHash: ... +def new(digest_bytes: int = ..., digest_bits: int = ..., custom: int = ...) -> TupleHash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE128.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE128.py index 92ac59e4..8cda579d 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE128.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE128.py @@ -1,112 +1,124 @@ -from Cryptodome.Util._raw_api import (VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) -from Cryptodome.Util.number import long_to_bytes -from Cryptodome.Util.py3compat import bchr from .keccak import _raw_keccak_lib class TurboSHAKE(object): - """A TurboSHAKE hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ - - def __init__(self, capacity, domain_separation, data): - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(capacity), - c_ubyte(12)) # Reduced number of rounds - if result: - raise ValueError("Error %d while instantiating TurboSHAKE" - % result) - self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy) - - self._is_squeezing = False - self._capacity = capacity - self._domain = domain_separation - - if data: - self.update(data) - - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating TurboSHAKE state" - % result) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length), - c_ubyte(self._domain)) - if result: - raise ValueError("Error %d while extracting from TurboSHAKE" - % result) - - return get_raw_buffer(bfr) - - def new(self, data=None): - return type(self)(self._capacity, self._domain, data) - - def _reset(self): - result = _raw_keccak_lib.keccak_reset(self._state.get()) - if result: - raise ValueError("Error %d while resetting TurboSHAKE state" - % result) - self._is_squeezing = False + """A TurboSHAKE hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ + + def __init__(self, capacity, domain_separation, data): + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(capacity), + c_ubyte(12), + ) # Reduced number of rounds + if result: + raise ValueError( + "Error %d while instantiating TurboSHAKE" % result, + ) + self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy) + + self._is_squeezing = False + self._capacity = capacity + self._domain = domain_separation + + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._is_squeezing: + raise TypeError("You cannot call 'update' after the first 'read'") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating TurboSHAKE state" % result, + ) + return self + + def read(self, length): + """ + Compute the next piece of XOF output. + + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. + + Args: + length (integer): the amount of bytes this method must return + + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ + + self._is_squeezing = True + bfr = create_string_buffer(length) + result = _raw_keccak_lib.keccak_squeeze( + self._state.get(), + bfr, + c_size_t(length), + c_ubyte(self._domain), + ) + if result: + raise ValueError( + "Error %d while extracting from TurboSHAKE" % result, + ) + + return get_raw_buffer(bfr) + + def new(self, data=None): + return type(self)(self._capacity, self._domain, data) + + def _reset(self): + result = _raw_keccak_lib.keccak_reset(self._state.get()) + if result: + raise ValueError( + "Error %d while resetting TurboSHAKE state" % result, + ) + self._is_squeezing = False def new(**kwargs): - """Create a new TurboSHAKE128 object. - - Args: - domain (integer): - Optional - A domain separation byte, between 0x01 and 0x7F. - The default value is 0x1F. - data (bytes/bytearray/memoryview): - Optional - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - - :Return: A :class:`TurboSHAKE` object - """ - - domain_separation = kwargs.get('domain', 0x1F) - if not (0x01 <= domain_separation <= 0x7F): - raise ValueError("Incorrect domain separation value (%d)" % - domain_separation) - data = kwargs.get('data') - return TurboSHAKE(32, domain_separation, data=data) + """Create a new TurboSHAKE128 object. + + Args: + domain (integer): + Optional - A domain separation byte, between 0x01 and 0x7F. + The default value is 0x1F. + data (bytes/bytearray/memoryview): + Optional - The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + + :Return: A :class:`TurboSHAKE` object + """ + + domain_separation = kwargs.get("domain", 0x1F) + if not (0x01 <= domain_separation <= 0x7F): + raise ValueError( + "Incorrect domain separation value (%d)" % domain_separation, + ) + data = kwargs.get("data") + return TurboSHAKE(32, domain_separation, data=data) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE128.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE128.pyi index d74c9c08..83b573a9 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE128.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE128.pyi @@ -4,14 +4,13 @@ from typing_extensions import TypedDict, Unpack, NotRequired Buffer = Union[bytes, bytearray, memoryview] class TurboSHAKE(object): - - def __init__(self, capacity: int, domain_separation: int, data: Union[Buffer, None]) -> None: ... - def update(self, data: Buffer) -> TurboSHAKE : ... - def read(self, length: int) -> bytes: ... - def new(self, data: Optional[Buffer]=None) -> TurboSHAKE: ... + def __init__(self, capacity: int, domain_separation: int, data: Union[Buffer, None]) -> None: ... + def update(self, data: Buffer) -> TurboSHAKE: ... + def read(self, length: int) -> bytes: ... + def new(self, data: Optional[Buffer] = None) -> TurboSHAKE: ... class Args(TypedDict): - domain: NotRequired[int] - data: NotRequired[Buffer] + domain: NotRequired[int] + data: NotRequired[Buffer] def new(**kwargs: Unpack[Args]) -> TurboSHAKE: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE256.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE256.py index ce27a485..d8acf75c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE256.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE256.py @@ -1,22 +1,24 @@ from .TurboSHAKE128 import TurboSHAKE + def new(**kwargs): - """Create a new TurboSHAKE256 object. + """Create a new TurboSHAKE256 object. - Args: - domain (integer): - Optional - A domain separation byte, between 0x01 and 0x7F. - The default value is 0x1F. - data (bytes/bytearray/memoryview): - Optional - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. + Args: + domain (integer): + Optional - A domain separation byte, between 0x01 and 0x7F. + The default value is 0x1F. + data (bytes/bytearray/memoryview): + Optional - The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. - :Return: A :class:`TurboSHAKE` object - """ + :Return: A :class:`TurboSHAKE` object + """ - domain_separation = kwargs.get('domain', 0x1F) - if not (0x01 <= domain_separation <= 0x7F): - raise ValueError("Incorrect domain separation value (%d)" % - domain_separation) - data = kwargs.get('data') - return TurboSHAKE(64, domain_separation, data=data) + domain_separation = kwargs.get("domain", 0x1F) + if not (0x01 <= domain_separation <= 0x7F): + raise ValueError( + "Incorrect domain separation value (%d)" % domain_separation, + ) + data = kwargs.get("data") + return TurboSHAKE(64, domain_separation, data=data) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE256.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE256.pyi index 561e946c..3d3b8604 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE256.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/TurboSHAKE256.pyi @@ -6,7 +6,7 @@ from .TurboSHAKE128 import TurboSHAKE Buffer = Union[bytes, bytearray, memoryview] class Args(TypedDict): - domain: NotRequired[int] - data: NotRequired[Buffer] + domain: NotRequired[int] + data: NotRequired[Buffer] def new(**kwargs: Unpack[Args]) -> TurboSHAKE: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/__init__.py index 80446e4f..38f8cc8f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/__init__.py @@ -18,52 +18,83 @@ # SOFTWARE. # =================================================================== -__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1', - 'SHA224', 'SHA256', 'SHA384', 'SHA512', - 'SHA3_224', 'SHA3_256', 'SHA3_384', 'SHA3_512', - 'CMAC', 'Poly1305', - 'cSHAKE128', 'cSHAKE256', 'KMAC128', 'KMAC256', - 'TupleHash128', 'TupleHash256', 'KangarooTwelve', - 'TurboSHAKE128', 'TurboSHAKE256'] +__all__ = [ + "HMAC", + "MD2", + "MD4", + "MD5", + "RIPEMD160", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA3_224", + "SHA3_256", + "SHA3_384", + "SHA3_512", + "CMAC", + "Poly1305", + "cSHAKE128", + "cSHAKE256", + "KMAC128", + "KMAC256", + "TupleHash128", + "TupleHash256", + "KangarooTwelve", + "TurboSHAKE128", + "TurboSHAKE256", +] + def new(name): - """Return a new hash instance, based on its name or - on its ASN.1 Object ID""" + """Return a new hash instance, based on its name or + on its ASN.1 Object ID""" + + name = name.upper() + if name in ("1.3.14.3.2.26", "SHA1", "SHA-1"): + from . import SHA1 + + return SHA1.new() + if name in ("2.16.840.1.101.3.4.2.4", "SHA224", "SHA-224"): + from . import SHA224 + + return SHA224.new() + if name in ("2.16.840.1.101.3.4.2.1", "SHA256", "SHA-256"): + from . import SHA256 + + return SHA256.new() + if name in ("2.16.840.1.101.3.4.2.2", "SHA384", "SHA-384"): + from . import SHA384 + + return SHA384.new() + if name in ("2.16.840.1.101.3.4.2.3", "SHA512", "SHA-512"): + from . import SHA512 + + return SHA512.new() + if name in ("2.16.840.1.101.3.4.2.5", "SHA512-224", "SHA-512-224"): + from . import SHA512 + + return SHA512.new(truncate="224") + if name in ("2.16.840.1.101.3.4.2.6", "SHA512-256", "SHA-512-256"): + from . import SHA512 + + return SHA512.new(truncate="256") + if name in ("2.16.840.1.101.3.4.2.7", "SHA3-224", "SHA-3-224"): + from . import SHA3_224 + + return SHA3_224.new() + if name in ("2.16.840.1.101.3.4.2.8", "SHA3-256", "SHA-3-256"): + from . import SHA3_256 + + return SHA3_256.new() + if name in ("2.16.840.1.101.3.4.2.9", "SHA3-384", "SHA-3-384"): + from . import SHA3_384 - name = name.upper() - if name in ("1.3.14.3.2.26", "SHA1", "SHA-1"): - from . import SHA1 - return SHA1.new() - if name in ("2.16.840.1.101.3.4.2.4", "SHA224", "SHA-224"): - from . import SHA224 - return SHA224.new() - if name in ("2.16.840.1.101.3.4.2.1", "SHA256", "SHA-256"): - from . import SHA256 - return SHA256.new() - if name in ("2.16.840.1.101.3.4.2.2", "SHA384", "SHA-384"): - from . import SHA384 - return SHA384.new() - if name in ("2.16.840.1.101.3.4.2.3", "SHA512", "SHA-512"): - from . import SHA512 - return SHA512.new() - if name in ("2.16.840.1.101.3.4.2.5", "SHA512-224", "SHA-512-224"): - from . import SHA512 - return SHA512.new(truncate='224') - if name in ("2.16.840.1.101.3.4.2.6", "SHA512-256", "SHA-512-256"): - from . import SHA512 - return SHA512.new(truncate='256') - if name in ("2.16.840.1.101.3.4.2.7", "SHA3-224", "SHA-3-224"): - from . import SHA3_224 - return SHA3_224.new() - if name in ("2.16.840.1.101.3.4.2.8", "SHA3-256", "SHA-3-256"): - from . import SHA3_256 - return SHA3_256.new() - if name in ("2.16.840.1.101.3.4.2.9", "SHA3-384", "SHA-3-384"): - from . import SHA3_384 - return SHA3_384.new() - if name in ("2.16.840.1.101.3.4.2.10", "SHA3-512", "SHA-3-512"): - from . import SHA3_512 - return SHA3_512.new() - else: - raise ValueError("Unknown hash %s" % str(name)) + return SHA3_384.new() + if name in ("2.16.840.1.101.3.4.2.10", "SHA3-512", "SHA-3-512"): + from . import SHA3_512 + return SHA3_512.new() + else: + raise ValueError("Unknown hash %s" % str(name)) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE128.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE128.py index 064b3d67..ac6373cc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE128.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE128.py @@ -30,10 +30,15 @@ from Cryptodome.Util.py3compat import bchr, concat_buffers -from Cryptodome.Util._raw_api import (VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) +from Cryptodome.Util._raw_api import ( + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) from Cryptodome.Util.number import long_to_bytes @@ -41,147 +46,158 @@ def _left_encode(x): - """Left encode function as defined in NIST SP 800-185""" + """Left encode function as defined in NIST SP 800-185""" - assert (x < (1 << 2040) and x >= 0) + assert x < (1 << 2040) and x >= 0 - # Get number of bytes needed to represent this integer. - num = 1 if x == 0 else (x.bit_length() + 7) // 8 + # Get number of bytes needed to represent this integer. + num = 1 if x == 0 else (x.bit_length() + 7) // 8 - return bchr(num) + long_to_bytes(x) + return bchr(num) + long_to_bytes(x) def _right_encode(x): - """Right encode function as defined in NIST SP 800-185""" + """Right encode function as defined in NIST SP 800-185""" - assert (x < (1 << 2040) and x >= 0) + assert x < (1 << 2040) and x >= 0 - # Get number of bytes needed to represent this integer. - num = 1 if x == 0 else (x.bit_length() + 7) // 8 + # Get number of bytes needed to represent this integer. + num = 1 if x == 0 else (x.bit_length() + 7) // 8 - return long_to_bytes(x) + bchr(num) + return long_to_bytes(x) + bchr(num) def _encode_str(x): - """Encode string function as defined in NIST SP 800-185""" + """Encode string function as defined in NIST SP 800-185""" - bitlen = len(x) * 8 - if bitlen >= (1 << 2040): - raise ValueError("String too large to encode in cSHAKE") + bitlen = len(x) * 8 + if bitlen >= (1 << 2040): + raise ValueError("String too large to encode in cSHAKE") - return concat_buffers(_left_encode(bitlen), x) + return concat_buffers(_left_encode(bitlen), x) def _bytepad(x, length): - """Zero pad byte string as defined in NIST SP 800-185""" + """Zero pad byte string as defined in NIST SP 800-185""" - to_pad = concat_buffers(_left_encode(length), x) + to_pad = concat_buffers(_left_encode(length), x) - # Note: this implementation works with byte aligned strings, - # hence no additional bit padding is needed at this point. - npad = (length - len(to_pad) % length) % length + # Note: this implementation works with byte aligned strings, + # hence no additional bit padding is needed at this point. + npad = (length - len(to_pad) % length) % length - return to_pad + b'\x00' * npad + return to_pad + b"\x00" * npad class cSHAKE_XOF(object): - """A cSHAKE hash object. - Do not instantiate directly. - Use the :func:`new` function. - """ - - def __init__(self, data, custom, capacity, function): - state = VoidPointer() - - if custom or function: - prefix_unpad = _encode_str(function) + _encode_str(custom) - prefix = _bytepad(prefix_unpad, (1600 - capacity)//8) - self._padding = 0x04 - else: - prefix = None - self._padding = 0x1F # for SHAKE - - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(capacity//8), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating cSHAKE" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - self._is_squeezing = False - - if prefix: - self.update(prefix) - - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating %s state" - % (result, self.name)) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while extracting from %s" - % (result, self.name)) - - return get_raw_buffer(bfr) + """A cSHAKE hash object. + Do not instantiate directly. + Use the :func:`new` function. + """ + + def __init__(self, data, custom, capacity, function): + state = VoidPointer() + + if custom or function: + prefix_unpad = _encode_str(function) + _encode_str(custom) + prefix = _bytepad(prefix_unpad, (1600 - capacity) // 8) + self._padding = 0x04 + else: + prefix = None + self._padding = 0x1F # for SHAKE + + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(capacity // 8), + c_ubyte(24), + ) + if result: + raise ValueError( + "Error %d while instantiating cSHAKE" % result, + ) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + self._is_squeezing = False + + if prefix: + self.update(prefix) + + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._is_squeezing: + raise TypeError("You cannot call 'update' after the first 'read'") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError( + "Error %d while updating %s state" % (result, self.name), + ) + return self + + def read(self, length): + """ + Compute the next piece of XOF output. + + .. note:: + You cannot use :meth:`update` anymore after the first call to + :meth:`read`. + + Args: + length (integer): the amount of bytes this method must return + + :return: the next piece of XOF output (of the given length) + :rtype: byte string + """ + + self._is_squeezing = True + bfr = create_string_buffer(length) + result = _raw_keccak_lib.keccak_squeeze( + self._state.get(), + bfr, + c_size_t(length), + c_ubyte(self._padding), + ) + if result: + raise ValueError( + "Error %d while extracting from %s" % (result, self.name), + ) + + return get_raw_buffer(bfr) def _new(data, custom, function): - # Use Keccak[256] - return cSHAKE_XOF(data, custom, 256, function) + # Use Keccak[256] + return cSHAKE_XOF(data, custom, 256, function) def new(data=None, custom=None): - """Return a fresh instance of a cSHAKE128 object. - - Args: - data (bytes/bytearray/memoryview): - Optional. - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - custom (bytes): - Optional. - A customization bytestring (``S`` in SP 800-185). - - :Return: A :class:`cSHAKE_XOF` object - """ - - # Use Keccak[256] - return cSHAKE_XOF(data, custom, 256, b'') + """Return a fresh instance of a cSHAKE128 object. + + Args: + data (bytes/bytearray/memoryview): + Optional. + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + custom (bytes): + Optional. + A customization bytestring (``S`` in SP 800-185). + + :Return: A :class:`cSHAKE_XOF` object + """ + + # Use Keccak[256] + return cSHAKE_XOF(data, custom, 256, b"") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE128.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE128.pyi index 1452feaf..6e6225b1 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE128.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE128.pyi @@ -3,12 +3,10 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] class cSHAKE_XOF(object): - def __init__(self, - data: Optional[Buffer] = ..., - function: Optional[bytes] = ..., - custom: Optional[bytes] = ...) -> None: ... - def update(self, data: Buffer) -> cSHAKE_XOF: ... - def read(self, length: int) -> bytes: ... + def __init__( + self, data: Optional[Buffer] = ..., function: Optional[bytes] = ..., custom: Optional[bytes] = ... + ) -> None: ... + def update(self, data: Buffer) -> cSHAKE_XOF: ... + def read(self, length: int) -> bytes: ... -def new(data: Optional[Buffer] = ..., - custom: Optional[Buffer] = ...) -> cSHAKE_XOF: ... +def new(data: Optional[Buffer] = ..., custom: Optional[Buffer] = ...) -> cSHAKE_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE256.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE256.py index a5b87012..4906ed00 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE256.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE256.py @@ -28,29 +28,28 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util._raw_api import c_size_t from Cryptodome.Hash.cSHAKE128 import cSHAKE_XOF def _new(data, custom, function): - # Use Keccak[512] - return cSHAKE_XOF(data, custom, 512, function) + # Use Keccak[512] + return cSHAKE_XOF(data, custom, 512, function) def new(data=None, custom=None): - """Return a fresh instance of a cSHAKE256 object. - - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - Optional. - custom (bytes): - Optional. - A customization bytestring (``S`` in SP 800-185). - - :Return: A :class:`cSHAKE_XOF` object - """ - - # Use Keccak[512] - return cSHAKE_XOF(data, custom, 512, b'') + """Return a fresh instance of a cSHAKE256 object. + + Args: + data (bytes/bytearray/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`update`. + Optional. + custom (bytes): + Optional. + A customization bytestring (``S`` in SP 800-185). + + :Return: A :class:`cSHAKE_XOF` object + """ + + # Use Keccak[512] + return cSHAKE_XOF(data, custom, 512, b"") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE256.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE256.pyi index b910bb6f..955c4c35 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE256.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/cSHAKE256.pyi @@ -4,5 +4,4 @@ from Cryptodome.Hash.cSHAKE128 import cSHAKE_XOF Buffer = Union[bytes, bytearray, memoryview] -def new(data: Optional[Buffer] = ..., - custom: Optional[Buffer] = ...) -> cSHAKE_XOF: ... +def new(data: Optional[Buffer] = ..., custom: Optional[Buffer] = ...) -> cSHAKE_XOF: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/keccak.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/keccak.py index f2af2024..3f9780e7 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/keccak.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/keccak.py @@ -30,14 +30,20 @@ from Cryptodome.Util.py3compat import bord -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr, c_ubyte) - -_raw_keccak_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._keccak", - """ +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + create_string_buffer, + get_raw_buffer, + c_size_t, + c_uint8_ptr, + c_ubyte, +) + +_raw_keccak_lib = load_pycryptodome_raw_lib( + "Cryptodome.Hash._keccak", + """ int keccak_init(void **state, size_t capacity_bytes, uint8_t rounds); @@ -55,127 +61,137 @@ uint8_t padding); int keccak_copy(const void *src, void *dst); int keccak_reset(void *state); - """) + """, +) -class Keccak_Hash(object): - """A Keccak hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - def __init__(self, data, digest_bytes, update_after_digest): - # The size of the resulting hash in bytes. - self.digest_size = digest_bytes - - self._update_after_digest = update_after_digest - self._digest_done = False - self._padding = 0x01 - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - c_ubyte(24)) - if result: - raise ValueError("Error %d while instantiating keccak" % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating keccak" % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size), - c_ubyte(self._padding)) - if result: - raise ValueError("Error %d while squeezing keccak" % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def new(self, **kwargs): - """Create a fresh Keccak hash object.""" - - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) +class Keccak_Hash(object): + """A Keccak hash object. + Do not instantiate directly. + Use the :func:`new` function. + + :ivar digest_size: the size in bytes of the resulting hash + :vartype digest_size: integer + """ + + def __init__(self, data, digest_bytes, update_after_digest): + # The size of the resulting hash in bytes. + self.digest_size = digest_bytes + + self._update_after_digest = update_after_digest + self._digest_done = False + self._padding = 0x01 + + state = VoidPointer() + result = _raw_keccak_lib.keccak_init( + state.address_of(), + c_size_t(self.digest_size * 2), + c_ubyte(24), + ) + if result: + raise ValueError("Error %d while instantiating keccak" % result) + self._state = SmartPointer( + state.get(), + _raw_keccak_lib.keccak_destroy, + ) + if data: + self.update(data) + + def update(self, data): + """Continue hashing of a message by consuming the next chunk of data. + + Args: + data (byte string/byte array/memoryview): The next chunk of the message being hashed. + """ + + if self._digest_done and not self._update_after_digest: + raise TypeError("You can only call 'digest' or 'hexdigest' on this object") + + result = _raw_keccak_lib.keccak_absorb( + self._state.get(), + c_uint8_ptr(data), + c_size_t(len(data)), + ) + if result: + raise ValueError("Error %d while updating keccak" % result) + return self + + def digest(self): + """Return the **binary** (non-printable) digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Binary form. + :rtype: byte string + """ + + self._digest_done = True + bfr = create_string_buffer(self.digest_size) + result = _raw_keccak_lib.keccak_digest( + self._state.get(), + bfr, + c_size_t(self.digest_size), + c_ubyte(self._padding), + ) + if result: + raise ValueError("Error %d while squeezing keccak" % result) + + return get_raw_buffer(bfr) + + def hexdigest(self): + """Return the **printable** digest of the message that has been hashed so far. + + :return: The hash digest, computed over the data processed so far. + Hexadecimal encoded. + :rtype: string + """ + + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def new(self, **kwargs): + """Create a fresh Keccak hash object.""" + + if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: + kwargs["digest_bytes"] = self.digest_size + + return new(**kwargs) def new(**kwargs): - """Create a new hash object. - - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`Keccak_Hash.update`. - digest_bytes (integer): - The size of the digest, in bytes (28, 32, 48, 64). - digest_bits (integer): - The size of the digest, in bits (224, 256, 384, 512). - update_after_digest (boolean): - Whether :meth:`Keccak.digest` can be followed by another - :meth:`Keccak.update` (default: ``False``). - - :Return: A :class:`Keccak_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - raise TypeError("Digest size (bits, bytes) not provided") - if digest_bytes is not None: - if digest_bytes not in (28, 32, 48, 64): - raise ValueError("'digest_bytes' must be: 28, 32, 48 or 64") - else: - if digest_bits not in (224, 256, 384, 512): - raise ValueError("'digest_bytes' must be: 224, 256, 384 or 512") - digest_bytes = digest_bits // 8 - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return Keccak_Hash(data, digest_bytes, update_after_digest) + """Create a new hash object. + + Args: + data (bytes/bytearray/memoryview): + The very first chunk of the message to hash. + It is equivalent to an early call to :meth:`Keccak_Hash.update`. + digest_bytes (integer): + The size of the digest, in bytes (28, 32, 48, 64). + digest_bits (integer): + The size of the digest, in bits (224, 256, 384, 512). + update_after_digest (boolean): + Whether :meth:`Keccak.digest` can be followed by another + :meth:`Keccak.update` (default: ``False``). + + :Return: A :class:`Keccak_Hash` hash object + """ + + data = kwargs.pop("data", None) + update_after_digest = kwargs.pop("update_after_digest", False) + + digest_bytes = kwargs.pop("digest_bytes", None) + digest_bits = kwargs.pop("digest_bits", None) + if None not in (digest_bytes, digest_bits): + raise TypeError("Only one digest parameter must be provided") + if (None, None) == (digest_bytes, digest_bits): + raise TypeError("Digest size (bits, bytes) not provided") + if digest_bytes is not None: + if digest_bytes not in (28, 32, 48, 64): + raise ValueError("'digest_bytes' must be: 28, 32, 48 or 64") + else: + if digest_bits not in (224, 256, 384, 512): + raise ValueError("'digest_bytes' must be: 224, 256, 384 or 512") + digest_bytes = digest_bits // 8 + + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + return Keccak_Hash(data, digest_bytes, update_after_digest) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/keccak.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/keccak.pyi index 844d2565..f620ffc0 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/keccak.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Hash/keccak.pyi @@ -1,23 +1,21 @@ -from typing import Union, Any +from typing import Union Buffer = Union[bytes, bytearray, memoryview] class Keccak_Hash(object): - digest_size: int - def __init__(self, - data: Buffer, - digest_bytes: int, - update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> Keccak_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def new(self, - data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - update_after_digest: bool = ...) -> Keccak_Hash: ... + digest_size: int + def __init__(self, data: Buffer, digest_bytes: int, update_after_digest: bool) -> None: ... + def update(self, data: Buffer) -> Keccak_Hash: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def new( + self, + data: Buffer = ..., + digest_bytes: int = ..., + digest_bits: int = ..., + update_after_digest: bool = ..., + ) -> Keccak_Hash: ... -def new(data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - update_after_digest: bool = ...) -> Keccak_Hash: ... +def new( + data: Buffer = ..., digest_bytes: int = ..., digest_bits: int = ..., update_after_digest: bool = ... +) -> Keccak_Hash: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PEM.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PEM.py index 61fe920f..f0a37e5d 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PEM.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PEM.py @@ -31,7 +31,7 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = ['encode', 'decode'] +__all__ = ["encode", "decode"] import re from binascii import a2b_base64, b2a_base64, hexlify, unhexlify @@ -45,147 +45,145 @@ def encode(data, marker, passphrase=None, randfunc=None): - """Encode a piece of binary data into PEM format. - - Args: - data (byte string): - The piece of binary data to encode. - marker (string): - The marker for the PEM block (e.g. "PUBLIC KEY"). - Note that there is no official master list for all allowed markers. - Still, you can refer to the OpenSSL_ source code. - passphrase (byte string): - If given, the PEM block will be encrypted. The key is derived from - the passphrase. - randfunc (callable): - Random number generation function; it accepts an integer N and returns - a byte string of random data, N bytes long. If not given, a new one is - instantiated. - - Returns: - The PEM block, as a string. - - .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h - """ - - if randfunc is None: - randfunc = get_random_bytes - - out = "-----BEGIN %s-----\n" % marker - if passphrase: - # We only support 3DES for encryption - salt = randfunc(8) - key = PBKDF1(passphrase, salt, 16, 1, MD5) - key += PBKDF1(key + passphrase, salt, 8, 1, MD5) - objenc = DES3.new(key, DES3.MODE_CBC, salt) - out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" %\ - tostr(hexlify(salt).upper()) - # Encrypt with PKCS#7 padding - data = objenc.encrypt(pad(data, objenc.block_size)) - elif passphrase is not None: - raise ValueError("Empty password") - - # Each BASE64 line can take up to 64 characters (=48 bytes of data) - # b2a_base64 adds a new line character! - chunks = [tostr(b2a_base64(data[i:i + 48])) - for i in range(0, len(data), 48)] - out += "".join(chunks) - out += "-----END %s-----" % marker - return out + """Encode a piece of binary data into PEM format. + + Args: + data (byte string): + The piece of binary data to encode. + marker (string): + The marker for the PEM block (e.g. "PUBLIC KEY"). + Note that there is no official master list for all allowed markers. + Still, you can refer to the OpenSSL_ source code. + passphrase (byte string): + If given, the PEM block will be encrypted. The key is derived from + the passphrase. + randfunc (callable): + Random number generation function; it accepts an integer N and returns + a byte string of random data, N bytes long. If not given, a new one is + instantiated. + + Returns: + The PEM block, as a string. + + .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h + """ + + if randfunc is None: + randfunc = get_random_bytes + + out = "-----BEGIN %s-----\n" % marker + if passphrase: + # We only support 3DES for encryption + salt = randfunc(8) + key = PBKDF1(passphrase, salt, 16, 1, MD5) + key += PBKDF1(key + passphrase, salt, 8, 1, MD5) + objenc = DES3.new(key, DES3.MODE_CBC, salt) + out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" % tostr(hexlify(salt).upper()) + # Encrypt with PKCS#7 padding + data = objenc.encrypt(pad(data, objenc.block_size)) + elif passphrase is not None: + raise ValueError("Empty password") + + # Each BASE64 line can take up to 64 characters (=48 bytes of data) + # b2a_base64 adds a new line character! + chunks = [tostr(b2a_base64(data[i : i + 48])) for i in range(0, len(data), 48)] + out += "".join(chunks) + out += "-----END %s-----" % marker + return out def _EVP_BytesToKey(data, salt, key_len): - d = [ b'' ] - m = (key_len + 15 ) // 16 - for _ in range(m): - nd = MD5.new(d[-1] + data + salt).digest() - d.append(nd) - return b"".join(d)[:key_len] + d = [b""] + m = (key_len + 15) // 16 + for _ in range(m): + nd = MD5.new(d[-1] + data + salt).digest() + d.append(nd) + return b"".join(d)[:key_len] def decode(pem_data, passphrase=None): - """Decode a PEM block into binary. - - Args: - pem_data (string): - The PEM block. - passphrase (byte string): - If given and the PEM block is encrypted, - the key will be derived from the passphrase. - - Returns: - A tuple with the binary data, the marker string, and a boolean to - indicate if decryption was performed. - - Raises: - ValueError: if decoding fails, if the PEM file is encrypted and no passphrase has - been provided or if the passphrase is incorrect. - """ - - # Verify Pre-Encapsulation Boundary - r = re.compile(r"\s*-----BEGIN (.*)-----\s+") - m = r.match(pem_data) - if not m: - raise ValueError("Not a valid PEM pre boundary") - marker = m.group(1) - - # Verify Post-Encapsulation Boundary - r = re.compile(r"-----END (.*)-----\s*$") - m = r.search(pem_data) - if not m or m.group(1) != marker: - raise ValueError("Not a valid PEM post boundary") - - # Removes spaces and slit on lines - lines = pem_data.replace(" ", '').split() - if len(lines) < 3: - raise ValueError("A PEM file must have at least 3 lines") - - # Decrypts, if necessary - if lines[1].startswith('Proc-Type:4,ENCRYPTED'): - if not passphrase: - raise ValueError("PEM is encrypted, but no passphrase available") - DEK = lines[2].split(':') - if len(DEK) != 2 or DEK[0] != 'DEK-Info': - raise ValueError("PEM encryption format not supported.") - algo, salt = DEK[1].split(',') - salt = unhexlify(tobytes(salt)) - - padding = True - - if algo == "DES-CBC": - key = _EVP_BytesToKey(passphrase, salt, 8) - objdec = DES.new(key, DES.MODE_CBC, salt) - elif algo == "DES-EDE3-CBC": - key = _EVP_BytesToKey(passphrase, salt, 24) - objdec = DES3.new(key, DES3.MODE_CBC, salt) - elif algo == "AES-128-CBC": - key = _EVP_BytesToKey(passphrase, salt[:8], 16) - objdec = AES.new(key, AES.MODE_CBC, salt) - elif algo == "AES-192-CBC": - key = _EVP_BytesToKey(passphrase, salt[:8], 24) - objdec = AES.new(key, AES.MODE_CBC, salt) - elif algo == "AES-256-CBC": - key = _EVP_BytesToKey(passphrase, salt[:8], 32) - objdec = AES.new(key, AES.MODE_CBC, salt) - elif algo.lower() == "id-aes256-gcm": - key = _EVP_BytesToKey(passphrase, salt[:8], 32) - objdec = AES.new(key, AES.MODE_GCM, nonce=salt) - padding = False - else: - raise ValueError("Unsupport PEM encryption algorithm (%s)." % algo) - lines = lines[2:] - else: - objdec = None - - # Decode body - data = a2b_base64(''.join(lines[1:-1])) - enc_flag = False - if objdec: - if padding: - data = unpad(objdec.decrypt(data), objdec.block_size) - else: - # There is no tag, so we don't use decrypt_and_verify - data = objdec.decrypt(data) - enc_flag = True - - return (data, marker, enc_flag) + """Decode a PEM block into binary. + + Args: + pem_data (string): + The PEM block. + passphrase (byte string): + If given and the PEM block is encrypted, + the key will be derived from the passphrase. + + Returns: + A tuple with the binary data, the marker string, and a boolean to + indicate if decryption was performed. + + Raises: + ValueError: if decoding fails, if the PEM file is encrypted and no passphrase has + been provided or if the passphrase is incorrect. + """ + + # Verify Pre-Encapsulation Boundary + r = re.compile(r"\s*-----BEGIN (.*)-----\s+") + m = r.match(pem_data) + if not m: + raise ValueError("Not a valid PEM pre boundary") + marker = m.group(1) + + # Verify Post-Encapsulation Boundary + r = re.compile(r"-----END (.*)-----\s*$") + m = r.search(pem_data) + if not m or m.group(1) != marker: + raise ValueError("Not a valid PEM post boundary") + + # Removes spaces and slit on lines + lines = pem_data.replace(" ", "").split() + if len(lines) < 3: + raise ValueError("A PEM file must have at least 3 lines") + + # Decrypts, if necessary + if lines[1].startswith("Proc-Type:4,ENCRYPTED"): + if not passphrase: + raise ValueError("PEM is encrypted, but no passphrase available") + DEK = lines[2].split(":") + if len(DEK) != 2 or DEK[0] != "DEK-Info": + raise ValueError("PEM encryption format not supported.") + algo, salt = DEK[1].split(",") + salt = unhexlify(tobytes(salt)) + + padding = True + + if algo == "DES-CBC": + key = _EVP_BytesToKey(passphrase, salt, 8) + objdec = DES.new(key, DES.MODE_CBC, salt) + elif algo == "DES-EDE3-CBC": + key = _EVP_BytesToKey(passphrase, salt, 24) + objdec = DES3.new(key, DES3.MODE_CBC, salt) + elif algo == "AES-128-CBC": + key = _EVP_BytesToKey(passphrase, salt[:8], 16) + objdec = AES.new(key, AES.MODE_CBC, salt) + elif algo == "AES-192-CBC": + key = _EVP_BytesToKey(passphrase, salt[:8], 24) + objdec = AES.new(key, AES.MODE_CBC, salt) + elif algo == "AES-256-CBC": + key = _EVP_BytesToKey(passphrase, salt[:8], 32) + objdec = AES.new(key, AES.MODE_CBC, salt) + elif algo.lower() == "id-aes256-gcm": + key = _EVP_BytesToKey(passphrase, salt[:8], 32) + objdec = AES.new(key, AES.MODE_GCM, nonce=salt) + padding = False + else: + raise ValueError("Unsupport PEM encryption algorithm (%s)." % algo) + lines = lines[2:] + else: + objdec = None + + # Decode body + data = a2b_base64("".join(lines[1:-1])) + enc_flag = False + if objdec: + if padding: + data = unpad(objdec.decrypt(data), objdec.block_size) + else: + # There is no tag, so we don't use decrypt_and_verify + data = objdec.decrypt(data) + enc_flag = True + + return (data, marker, enc_flag) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PEM.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PEM.pyi index 2e324c45..0d1500bf 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PEM.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PEM.pyi @@ -1,10 +1,9 @@ from typing import Tuple, Optional, Callable -def encode(data: bytes, - marke: str, - passphrase: Optional[bytes] = ..., - randfunc: Optional[Callable[[int],bytes]] = ...) -> str: ... - - -def decode(pem_data: str, - passphrase: Optional[bytes] = ...) -> Tuple[bytes, str, bool]: ... +def encode( + data: bytes, + marke: str, + passphrase: Optional[bytes] = ..., + randfunc: Optional[Callable[[int], bytes]] = ..., +) -> str: ... +def decode(pem_data: str, passphrase: Optional[bytes] = ...) -> Tuple[bytes, str, bool]: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PKCS8.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PKCS8.py index e7701993..9c000a1f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PKCS8.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PKCS8.py @@ -35,192 +35,207 @@ from Cryptodome.Util.py3compat import * from Cryptodome.Util.asn1 import ( - DerNull, - DerSequence, - DerObjectId, - DerOctetString, - ) + DerNull, + DerSequence, + DerObjectId, + DerOctetString, +) from Cryptodome.IO._PBES import PBES1, PBES2, PbesError -__all__ = ['wrap', 'unwrap'] - - -def wrap(private_key, key_oid, passphrase=None, protection=None, - prot_params=None, key_params=DerNull(), randfunc=None): - """Wrap a private key into a PKCS#8 blob (clear or encrypted). - - Args: - - private_key (bytes): - The private key encoded in binary form. The actual encoding is - algorithm specific. In most cases, it is DER. - - key_oid (string): - The object identifier (OID) of the private key to wrap. - It is a dotted string, like ``'1.2.840.113549.1.1.1'`` (for RSA keys) - or ``'1.2.840.10045.2.1'`` (for ECC keys). - - Keyword Args: - - passphrase (bytes or string): - The secret passphrase from which the wrapping key is derived. - Set it only if encryption is required. - - protection (string): - The identifier of the algorithm to use for securely wrapping the key. - Refer to :ref:`the encryption parameters` . - The default value is ``'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'``. - - prot_params (dictionary): - Parameters for the key derivation function (KDF). - Refer to :ref:`the encryption parameters` . - - key_params (DER object or None): - The ``parameters`` field to use in the ``AlgorithmIdentifier`` - SEQUENCE. If ``None``, no ``parameters`` field will be added. - By default, the ASN.1 type ``NULL`` is used. - - randfunc (callable): - Random number generation function; it should accept a single integer - N and return a string of random data, N bytes long. - If not specified, a new RNG will be instantiated - from :mod:`Cryptodome.Random`. - - Returns: - bytes: The PKCS#8-wrapped private key (possibly encrypted). - """ - - # - # PrivateKeyInfo ::= SEQUENCE { - # version Version, - # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - # privateKey PrivateKey, - # attributes [0] IMPLICIT Attributes OPTIONAL - # } - # - if key_params is None: - algorithm = DerSequence([DerObjectId(key_oid)]) - else: - algorithm = DerSequence([DerObjectId(key_oid), key_params]) - - pk_info = DerSequence([ - 0, - algorithm, - DerOctetString(private_key) - ]) - pk_info_der = pk_info.encode() - - if passphrase is None: - return pk_info_der - - if not passphrase: - raise ValueError("Empty passphrase") - - # Encryption with PBES2 - passphrase = tobytes(passphrase) - if protection is None: - protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' - return PBES2.encrypt(pk_info_der, passphrase, - protection, prot_params, randfunc) +__all__ = ["wrap", "unwrap"] + + +def wrap( + private_key, + key_oid, + passphrase=None, + protection=None, + prot_params=None, + key_params=DerNull(), + randfunc=None, +): + """Wrap a private key into a PKCS#8 blob (clear or encrypted). + + Args: + + private_key (bytes): + The private key encoded in binary form. The actual encoding is + algorithm specific. In most cases, it is DER. + + key_oid (string): + The object identifier (OID) of the private key to wrap. + It is a dotted string, like ``'1.2.840.113549.1.1.1'`` (for RSA keys) + or ``'1.2.840.10045.2.1'`` (for ECC keys). + + Keyword Args: + + passphrase (bytes or string): + The secret passphrase from which the wrapping key is derived. + Set it only if encryption is required. + + protection (string): + The identifier of the algorithm to use for securely wrapping the key. + Refer to :ref:`the encryption parameters` . + The default value is ``'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'``. + + prot_params (dictionary): + Parameters for the key derivation function (KDF). + Refer to :ref:`the encryption parameters` . + + key_params (DER object or None): + The ``parameters`` field to use in the ``AlgorithmIdentifier`` + SEQUENCE. If ``None``, no ``parameters`` field will be added. + By default, the ASN.1 type ``NULL`` is used. + + randfunc (callable): + Random number generation function; it should accept a single integer + N and return a string of random data, N bytes long. + If not specified, a new RNG will be instantiated + from :mod:`Cryptodome.Random`. + + Returns: + bytes: The PKCS#8-wrapped private key (possibly encrypted). + """ + + # + # PrivateKeyInfo ::= SEQUENCE { + # version Version, + # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + # privateKey PrivateKey, + # attributes [0] IMPLICIT Attributes OPTIONAL + # } + # + if key_params is None: + algorithm = DerSequence([DerObjectId(key_oid)]) + else: + algorithm = DerSequence([DerObjectId(key_oid), key_params]) + + pk_info = DerSequence( + [ + 0, + algorithm, + DerOctetString(private_key), + ] + ) + pk_info_der = pk_info.encode() + + if passphrase is None: + return pk_info_der + + if not passphrase: + raise ValueError("Empty passphrase") + + # Encryption with PBES2 + passphrase = tobytes(passphrase) + if protection is None: + protection = "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC" + return PBES2.encrypt( + pk_info_der, + passphrase, + protection, + prot_params, + randfunc, + ) def unwrap(p8_private_key, passphrase=None): - """Unwrap a private key from a PKCS#8 blob (clear or encrypted). - - Args: - p8_private_key (bytes): - The private key wrapped into a PKCS#8 container, DER encoded. - - Keyword Args: - passphrase (byte string or string): - The passphrase to use to decrypt the blob (if it is encrypted). - - Return: - A tuple containing - - #. the algorithm identifier of the wrapped key (OID, dotted string) - #. the private key (bytes, DER encoded) - #. the associated parameters (bytes, DER encoded) or ``None`` - - Raises: - ValueError : if decoding fails - """ - - if passphrase is not None: - passphrase = tobytes(passphrase) - - found = False - try: - p8_private_key = PBES1.decrypt(p8_private_key, passphrase) - found = True - except PbesError as e: - error_str = "PBES1[%s]" % str(e) - except ValueError: - error_str = "PBES1[Invalid]" - - if not found: - try: - p8_private_key = PBES2.decrypt(p8_private_key, passphrase) - found = True - except PbesError as e: - error_str += ",PBES2[%s]" % str(e) - except ValueError: - error_str += ",PBES2[Invalid]" - - if not found: - raise ValueError("Error decoding PKCS#8 (%s)" % error_str) - - pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4, 5)) - if len(pk_info) == 2 and not passphrase: - raise ValueError("Not a valid clear PKCS#8 structure " - "(maybe it is encrypted?)") - - # RFC5208, PKCS#8, version is v1(0) - # - # PrivateKeyInfo ::= SEQUENCE { - # version Version, - # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - # privateKey PrivateKey, - # attributes [0] IMPLICIT Attributes OPTIONAL - # } - # - # RFC5915, Asymmetric Key Package, version is v2(1) - # - # OneAsymmetricKey ::= SEQUENCE { - # version Version, - # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - # privateKey PrivateKey, - # attributes [0] Attributes OPTIONAL, - # ..., - # [[2: publicKey [1] PublicKey OPTIONAL ]], - # ... - # } - - if pk_info[0] == 0: - if len(pk_info) not in (3, 4): - raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") - elif pk_info[0] == 1: - if len(pk_info) not in (3, 4, 5): - raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") - else: - raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") - - algo = DerSequence().decode(pk_info[1], nr_elements=(1, 2)) - algo_oid = DerObjectId().decode(algo[0]).value - if len(algo) == 1: - algo_params = None - else: - try: - DerNull().decode(algo[1]) - algo_params = None - except: - algo_params = algo[1] - - # PrivateKey ::= OCTET STRING - private_key = DerOctetString().decode(pk_info[2]).payload - - # We ignore attributes and (for v2 only) publickey - - return (algo_oid, private_key, algo_params) + """Unwrap a private key from a PKCS#8 blob (clear or encrypted). + + Args: + p8_private_key (bytes): + The private key wrapped into a PKCS#8 container, DER encoded. + + Keyword Args: + passphrase (byte string or string): + The passphrase to use to decrypt the blob (if it is encrypted). + + Return: + A tuple containing + + #. the algorithm identifier of the wrapped key (OID, dotted string) + #. the private key (bytes, DER encoded) + #. the associated parameters (bytes, DER encoded) or ``None`` + + Raises: + ValueError : if decoding fails + """ + + if passphrase is not None: + passphrase = tobytes(passphrase) + + found = False + try: + p8_private_key = PBES1.decrypt(p8_private_key, passphrase) + found = True + except PbesError as e: + error_str = "PBES1[%s]" % str(e) + except ValueError: + error_str = "PBES1[Invalid]" + + if not found: + try: + p8_private_key = PBES2.decrypt(p8_private_key, passphrase) + found = True + except PbesError as e: + error_str += ",PBES2[%s]" % str(e) + except ValueError: + error_str += ",PBES2[Invalid]" + + if not found: + raise ValueError("Error decoding PKCS#8 (%s)" % error_str) + + pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4, 5)) + if len(pk_info) == 2 and not passphrase: + raise ValueError( + "Not a valid clear PKCS#8 structure (maybe it is encrypted?)", + ) + + # RFC5208, PKCS#8, version is v1(0) + # + # PrivateKeyInfo ::= SEQUENCE { + # version Version, + # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + # privateKey PrivateKey, + # attributes [0] IMPLICIT Attributes OPTIONAL + # } + # + # RFC5915, Asymmetric Key Package, version is v2(1) + # + # OneAsymmetricKey ::= SEQUENCE { + # version Version, + # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + # privateKey PrivateKey, + # attributes [0] Attributes OPTIONAL, + # ..., + # [[2: publicKey [1] PublicKey OPTIONAL ]], + # ... + # } + + if pk_info[0] == 0: + if len(pk_info) not in (3, 4): + raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") + elif pk_info[0] == 1: + if len(pk_info) not in (3, 4, 5): + raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") + else: + raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") + + algo = DerSequence().decode(pk_info[1], nr_elements=(1, 2)) + algo_oid = DerObjectId().decode(algo[0]).value + if len(algo) == 1: + algo_params = None + else: + try: + DerNull().decode(algo[1]) + algo_params = None + except: + algo_params = algo[1] + + # PrivateKey ::= OCTET STRING + private_key = DerOctetString().decode(pk_info[2]).payload + + # We ignore attributes and (for v2 only) publickey + + return (algo_oid, private_key, algo_params) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PKCS8.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PKCS8.pyi index c8d0c104..00bc6be9 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PKCS8.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/PKCS8.pyi @@ -1,17 +1,17 @@ from typing import Tuple, Optional, Union, Callable -from typing_extensions import NotRequired from Cryptodome.Util.asn1 import DerObject from Cryptodome.IO._PBES import ProtParams - -def wrap(private_key: bytes, - key_oid: str, - passphrase: Union[bytes, str] = ..., - protection: str = ..., - prot_params: Optional[ProtParams] = ..., - key_params: Optional[DerObject] = ..., - randfunc: Optional[Callable[[int], str]] = ...) -> bytes: ... - - -def unwrap(p8_private_key: bytes, passphrase: Optional[Union[bytes, str]] = ...) -> Tuple[str, bytes, Optional[bytes]]: ... +def wrap( + private_key: bytes, + key_oid: str, + passphrase: Union[bytes, str] = ..., + protection: str = ..., + prot_params: Optional[ProtParams] = ..., + key_params: Optional[DerObject] = ..., + randfunc: Optional[Callable[[int], str]] = ..., +) -> bytes: ... +def unwrap( + p8_private_key: bytes, passphrase: Optional[Union[bytes, str]] = ... +) -> Tuple[str, bytes, Optional[bytes]]: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/_PBES.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/_PBES.py index 75d8cdeb..da44d726 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/_PBES.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/_PBES.py @@ -36,9 +36,11 @@ from Cryptodome import Hash from Cryptodome import Random from Cryptodome.Util.asn1 import ( - DerSequence, DerOctetString, - DerObjectId, DerInteger, - ) + DerSequence, + DerOctetString, + DerObjectId, + DerInteger, +) from Cryptodome.Cipher import AES from Cryptodome.Util.Padding import pad, unpad @@ -64,8 +66,10 @@ _OID_AES192_GCM = "2.16.840.1.101.3.4.1.26" _OID_AES256_GCM = "2.16.840.1.101.3.4.1.46" + class PbesError(ValueError): - pass + pass + # These are the ASN.1 definitions used by the PBES1/2 logic: # @@ -123,424 +127,462 @@ class PbesError(ValueError): class PBES1(object): - """Deprecated encryption scheme with password-based key derivation - (originally defined in PKCS#5 v1.5, but still present in `v2.0`__). - - .. __: http://www.ietf.org/rfc/rfc2898.txt - """ - - @staticmethod - def decrypt(data, passphrase): - """Decrypt a piece of data using a passphrase and *PBES1*. - - The algorithm to use is automatically detected. - - :Parameters: - data : byte string - The piece of data to decrypt. - passphrase : byte string - The passphrase to use for decrypting the data. - :Returns: - The decrypted data, as a binary string. - """ - - enc_private_key_info = DerSequence().decode(data) - encrypted_algorithm = DerSequence().decode(enc_private_key_info[0]) - encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload - - pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value - cipher_params = {} - if pbe_oid == _OID_PBE_WITH_MD5_AND_DES_CBC: - # PBE_MD5_DES_CBC - from Cryptodome.Hash import MD5 - from Cryptodome.Cipher import DES - hashmod = MD5 - module = DES - elif pbe_oid == _OID_PBE_WITH_MD5_AND_RC2_CBC: - # PBE_MD5_RC2_CBC - from Cryptodome.Hash import MD5 - from Cryptodome.Cipher import ARC2 - hashmod = MD5 - module = ARC2 - cipher_params['effective_keylen'] = 64 - elif pbe_oid == _OID_PBE_WITH_SHA1_AND_DES_CBC: - # PBE_SHA1_DES_CBC - from Cryptodome.Hash import SHA1 - from Cryptodome.Cipher import DES - hashmod = SHA1 - module = DES - elif pbe_oid == _OID_PBE_WITH_SHA1_AND_RC2_CBC: - # PBE_SHA1_RC2_CBC - from Cryptodome.Hash import SHA1 - from Cryptodome.Cipher import ARC2 - hashmod = SHA1 - module = ARC2 - cipher_params['effective_keylen'] = 64 - else: - raise PbesError("Unknown OID for PBES1") - - pbe_params = DerSequence().decode(encrypted_algorithm[1], nr_elements=2) - salt = DerOctetString().decode(pbe_params[0]).payload - iterations = pbe_params[1] - - key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod) - key, iv = key_iv[:8], key_iv[8:] - - cipher = module.new(key, module.MODE_CBC, iv, **cipher_params) - pt = cipher.decrypt(encrypted_data) - return unpad(pt, cipher.block_size) + """Deprecated encryption scheme with password-based key derivation + (originally defined in PKCS#5 v1.5, but still present in `v2.0`__). + + .. __: http://www.ietf.org/rfc/rfc2898.txt + """ + + @staticmethod + def decrypt(data, passphrase): + """Decrypt a piece of data using a passphrase and *PBES1*. + + The algorithm to use is automatically detected. + + :Parameters: + data : byte string + The piece of data to decrypt. + passphrase : byte string + The passphrase to use for decrypting the data. + :Returns: + The decrypted data, as a binary string. + """ + + enc_private_key_info = DerSequence().decode(data) + encrypted_algorithm = DerSequence().decode(enc_private_key_info[0]) + encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload + + pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value + cipher_params = {} + if pbe_oid == _OID_PBE_WITH_MD5_AND_DES_CBC: + # PBE_MD5_DES_CBC + from Cryptodome.Hash import MD5 + from Cryptodome.Cipher import DES + + hashmod = MD5 + module = DES + elif pbe_oid == _OID_PBE_WITH_MD5_AND_RC2_CBC: + # PBE_MD5_RC2_CBC + from Cryptodome.Hash import MD5 + from Cryptodome.Cipher import ARC2 + + hashmod = MD5 + module = ARC2 + cipher_params["effective_keylen"] = 64 + elif pbe_oid == _OID_PBE_WITH_SHA1_AND_DES_CBC: + # PBE_SHA1_DES_CBC + from Cryptodome.Hash import SHA1 + from Cryptodome.Cipher import DES + + hashmod = SHA1 + module = DES + elif pbe_oid == _OID_PBE_WITH_SHA1_AND_RC2_CBC: + # PBE_SHA1_RC2_CBC + from Cryptodome.Hash import SHA1 + from Cryptodome.Cipher import ARC2 + + hashmod = SHA1 + module = ARC2 + cipher_params["effective_keylen"] = 64 + else: + raise PbesError("Unknown OID for PBES1") + + pbe_params = DerSequence().decode(encrypted_algorithm[1], nr_elements=2) + salt = DerOctetString().decode(pbe_params[0]).payload + iterations = pbe_params[1] + + key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod) + key, iv = key_iv[:8], key_iv[8:] + + cipher = module.new(key, module.MODE_CBC, iv, **cipher_params) + pt = cipher.decrypt(encrypted_data) + return unpad(pt, cipher.block_size) class PBES2(object): - """Encryption scheme with password-based key derivation - (defined in `PKCS#5 v2.0`__). - - .. __: http://www.ietf.org/rfc/rfc2898.txt.""" - - @staticmethod - def encrypt(data, passphrase, protection, prot_params=None, randfunc=None): - """Encrypt a piece of data using a passphrase and *PBES2*. - - :Parameters: - data : byte string - The piece of data to encrypt. - passphrase : byte string - The passphrase to use for encrypting the data. - protection : string - The identifier of the encryption algorithm to use. - The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'. - prot_params : dictionary - Parameters of the protection algorithm. - - +------------------+-----------------------------------------------+ - | Key | Description | - +==================+===============================================+ - | iteration_count | The KDF algorithm is repeated several times to| - | | slow down brute force attacks on passwords | - | | (called *N* or CPU/memory cost in scrypt). | - | | | - | | The default value for PBKDF2 is 1 000. | - | | The default value for scrypt is 16 384. | - +------------------+-----------------------------------------------+ - | salt_size | Salt is used to thwart dictionary and rainbow | - | | attacks on passwords. The default value is 8 | - | | bytes. | - +------------------+-----------------------------------------------+ - | block_size | *(scrypt only)* Memory-cost (r). The default | - | | value is 8. | - +------------------+-----------------------------------------------+ - | parallelization | *(scrypt only)* CPU-cost (p). The default | - | | value is 1. | - +------------------+-----------------------------------------------+ - - - randfunc : callable - Random number generation function; it should accept - a single integer N and return a string of random data, - N bytes long. If not specified, a new RNG will be - instantiated from ``Cryptodome.Random``. - - :Returns: - The encrypted data, as a binary string. - """ - - if prot_params is None: - prot_params = {} - - if randfunc is None: - randfunc = Random.new().read - - pattern = re.compile(r'^(PBKDF2WithHMAC-([0-9A-Z-]+)|scrypt)And([0-9A-Z-]+)$') - res = pattern.match(protection) - if res is None: - raise ValueError("Unknown protection %s" % protection) - - if protection.startswith("PBKDF"): - pbkdf = "pbkdf2" - pbkdf2_hmac_algo = res.group(2) - enc_algo = res.group(3) - else: - pbkdf = "scrypt" - enc_algo = res.group(3) - - aead = False - if enc_algo == 'DES-EDE3-CBC': - from Cryptodome.Cipher import DES3 - key_size = 24 - module = DES3 - cipher_mode = DES3.MODE_CBC - enc_oid = _OID_DES_EDE3_CBC - enc_param = {'iv': randfunc(8)} - elif enc_algo == 'AES128-CBC': - key_size = 16 - module = AES - cipher_mode = AES.MODE_CBC - enc_oid = _OID_AES128_CBC - enc_param = {'iv': randfunc(16)} - elif enc_algo == 'AES192-CBC': - key_size = 24 - module = AES - cipher_mode = AES.MODE_CBC - enc_oid = _OID_AES192_CBC - enc_param = {'iv': randfunc(16)} - elif enc_algo == 'AES256-CBC': - key_size = 32 - module = AES - cipher_mode = AES.MODE_CBC - enc_oid = _OID_AES256_CBC - enc_param = {'iv': randfunc(16)} - elif enc_algo == 'AES128-GCM': - key_size = 16 - module = AES - cipher_mode = AES.MODE_GCM - enc_oid = _OID_AES128_GCM - enc_param = {'nonce': randfunc(12)} - aead = True - elif enc_algo == 'AES192-GCM': - key_size = 24 - module = AES - cipher_mode = AES.MODE_GCM - enc_oid = _OID_AES192_GCM - enc_param = {'nonce': randfunc(12)} - aead = True - elif enc_algo == 'AES256-GCM': - key_size = 32 - module = AES - cipher_mode = AES.MODE_GCM - enc_oid = _OID_AES256_GCM - enc_param = {'nonce': randfunc(12)} - aead = True - else: - raise ValueError("Unknown encryption mode '%s'" % enc_algo) - - iv_nonce = list(enc_param.values())[0] - salt = randfunc(prot_params.get("salt_size", 8)) - - # Derive key from password - if pbkdf == 'pbkdf2': - - count = prot_params.get("iteration_count", 1000) - digestmod = Hash.new(pbkdf2_hmac_algo) - - key = PBKDF2(passphrase, - salt, - key_size, - count, - hmac_hash_module=digestmod) - - pbkdf2_params = DerSequence([ - DerOctetString(salt), - DerInteger(count) - ]) - - if pbkdf2_hmac_algo != 'SHA1': - try: - hmac_oid = Hash.HMAC.new(b'', digestmod=digestmod).oid - except KeyError: - raise ValueError("No OID for HMAC hash algorithm") - pbkdf2_params.append(DerSequence([DerObjectId(hmac_oid)])) - - kdf_info = DerSequence([ - DerObjectId(_OID_PBKDF2), # PBKDF2 - pbkdf2_params - ]) - - elif pbkdf == 'scrypt': - - count = prot_params.get("iteration_count", 16384) - scrypt_r = prot_params.get('block_size', 8) - scrypt_p = prot_params.get('parallelization', 1) - key = scrypt(passphrase, salt, key_size, - count, scrypt_r, scrypt_p) - kdf_info = DerSequence([ - DerObjectId(_OID_SCRYPT), # scrypt - DerSequence([ - DerOctetString(salt), - DerInteger(count), - DerInteger(scrypt_r), - DerInteger(scrypt_p) - ]) - ]) - - else: - raise ValueError("Unknown KDF " + res.group(1)) - - # Create cipher and use it - cipher = module.new(key, cipher_mode, **enc_param) - if aead: - ct, tag = cipher.encrypt_and_digest(data) - encrypted_data = ct + tag - else: - encrypted_data = cipher.encrypt(pad(data, cipher.block_size)) - enc_info = DerSequence([ - DerObjectId(enc_oid), - DerOctetString(iv_nonce) - ]) - - # Result - enc_private_key_info = DerSequence([ - # encryptionAlgorithm - DerSequence([ - DerObjectId(_OID_PBES2), - DerSequence([ - kdf_info, - enc_info - ]), - ]), - DerOctetString(encrypted_data) - ]) - return enc_private_key_info.encode() - - @staticmethod - def decrypt(data, passphrase): - """Decrypt a piece of data using a passphrase and *PBES2*. - - The algorithm to use is automatically detected. - - :Parameters: - data : byte string - The piece of data to decrypt. - passphrase : byte string - The passphrase to use for decrypting the data. - :Returns: - The decrypted data, as a binary string. - """ - - enc_private_key_info = DerSequence().decode(data, nr_elements=2) - enc_algo = DerSequence().decode(enc_private_key_info[0]) - encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload - - pbe_oid = DerObjectId().decode(enc_algo[0]).value - if pbe_oid != _OID_PBES2: - raise PbesError("Not a PBES2 object") - - pbes2_params = DerSequence().decode(enc_algo[1], nr_elements=2) - - # Key Derivation Function selection - kdf_info = DerSequence().decode(pbes2_params[0], nr_elements=2) - kdf_oid = DerObjectId().decode(kdf_info[0]).value - - kdf_key_length = None - - # We only support PBKDF2 or scrypt - if kdf_oid == _OID_PBKDF2: - - pbkdf2_params = DerSequence().decode(kdf_info[1], nr_elements=(2, 3, 4)) - salt = DerOctetString().decode(pbkdf2_params[0]).payload - iteration_count = pbkdf2_params[1] - - left = len(pbkdf2_params) - 2 - idx = 2 - - if left > 0: - try: - # Check if it's an INTEGER - kdf_key_length = pbkdf2_params[idx] - 0 - left -= 1 - idx += 1 - except TypeError: - # keyLength is not present - pass - - # Default is HMAC-SHA1 - pbkdf2_prf_oid = _OID_HMAC_SHA1 - if left > 0: - pbkdf2_prf_algo_id = DerSequence().decode(pbkdf2_params[idx]) - pbkdf2_prf_oid = DerObjectId().decode(pbkdf2_prf_algo_id[0]).value - - elif kdf_oid == _OID_SCRYPT: - - scrypt_params = DerSequence().decode(kdf_info[1], nr_elements=(4, 5)) - salt = DerOctetString().decode(scrypt_params[0]).payload - iteration_count, scrypt_r, scrypt_p = [scrypt_params[x] - for x in (1, 2, 3)] - if len(scrypt_params) > 4: - kdf_key_length = scrypt_params[4] - else: - kdf_key_length = None - else: - raise PbesError("Unsupported PBES2 KDF") - - # Cipher selection - enc_info = DerSequence().decode(pbes2_params[1]) - enc_oid = DerObjectId().decode(enc_info[0]).value - - aead = False - if enc_oid == _OID_DES_EDE3_CBC: - # DES_EDE3_CBC - from Cryptodome.Cipher import DES3 - module = DES3 - cipher_mode = DES3.MODE_CBC - key_size = 24 - cipher_param = 'iv' - elif enc_oid == _OID_AES128_CBC: - module = AES - cipher_mode = AES.MODE_CBC - key_size = 16 - cipher_param = 'iv' - elif enc_oid == _OID_AES192_CBC: - module = AES - cipher_mode = AES.MODE_CBC - key_size = 24 - cipher_param = 'iv' - elif enc_oid == _OID_AES256_CBC: - module = AES - cipher_mode = AES.MODE_CBC - key_size = 32 - cipher_param = 'iv' - elif enc_oid == _OID_AES128_GCM: - module = AES - cipher_mode = AES.MODE_GCM - key_size = 16 - cipher_param = 'nonce' - aead = True - elif enc_oid == _OID_AES192_GCM: - module = AES - cipher_mode = AES.MODE_GCM - key_size = 24 - cipher_param = 'nonce' - aead = True - elif enc_oid == _OID_AES256_GCM: - module = AES - cipher_mode = AES.MODE_GCM - key_size = 32 - cipher_param = 'nonce' - aead = True - else: - raise PbesError("Unsupported PBES2 cipher " + enc_algo) - - if kdf_key_length and kdf_key_length != key_size: - raise PbesError("Mismatch between PBES2 KDF parameters" - " and selected cipher") - - iv_nonce = DerOctetString().decode(enc_info[1]).payload - - # Create cipher - if kdf_oid == _OID_PBKDF2: - - try: - hmac_hash_module_oid = Hash.HMAC._hmac2hash_oid[pbkdf2_prf_oid] - except KeyError: - raise PbesError("Unsupported HMAC %s" % pbkdf2_prf_oid) - hmac_hash_module = Hash.new(hmac_hash_module_oid) - - key = PBKDF2(passphrase, salt, key_size, iteration_count, - hmac_hash_module=hmac_hash_module) - else: - key = scrypt(passphrase, salt, key_size, iteration_count, - scrypt_r, scrypt_p) - cipher = module.new(key, cipher_mode, **{cipher_param:iv_nonce}) - - # Decrypt data - if len(encrypted_data) < cipher.block_size: - raise ValueError("Too little data to decrypt") - - if aead: - tag_len = cipher.block_size - pt = cipher.decrypt_and_verify(encrypted_data[:-tag_len], - encrypted_data[-tag_len:]) - else: - pt_padded = cipher.decrypt(encrypted_data) - pt = unpad(pt_padded, cipher.block_size) - - return pt + """Encryption scheme with password-based key derivation + (defined in `PKCS#5 v2.0`__). + + .. __: http://www.ietf.org/rfc/rfc2898.txt.""" + + @staticmethod + def encrypt(data, passphrase, protection, prot_params=None, randfunc=None): + """Encrypt a piece of data using a passphrase and *PBES2*. + + :Parameters: + data : byte string + The piece of data to encrypt. + passphrase : byte string + The passphrase to use for encrypting the data. + protection : string + The identifier of the encryption algorithm to use. + The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'. + prot_params : dictionary + Parameters of the protection algorithm. + + +------------------+-----------------------------------------------+ + | Key | Description | + +==================+===============================================+ + | iteration_count | The KDF algorithm is repeated several times to| + | | slow down brute force attacks on passwords | + | | (called *N* or CPU/memory cost in scrypt). | + | | | + | | The default value for PBKDF2 is 1 000. | + | | The default value for scrypt is 16 384. | + +------------------+-----------------------------------------------+ + | salt_size | Salt is used to thwart dictionary and rainbow | + | | attacks on passwords. The default value is 8 | + | | bytes. | + +------------------+-----------------------------------------------+ + | block_size | *(scrypt only)* Memory-cost (r). The default | + | | value is 8. | + +------------------+-----------------------------------------------+ + | parallelization | *(scrypt only)* CPU-cost (p). The default | + | | value is 1. | + +------------------+-----------------------------------------------+ + + + randfunc : callable + Random number generation function; it should accept + a single integer N and return a string of random data, + N bytes long. If not specified, a new RNG will be + instantiated from ``Cryptodome.Random``. + + :Returns: + The encrypted data, as a binary string. + """ + + if prot_params is None: + prot_params = {} + + if randfunc is None: + randfunc = Random.new().read + + pattern = re.compile(r"^(PBKDF2WithHMAC-([0-9A-Z-]+)|scrypt)And([0-9A-Z-]+)$") + res = pattern.match(protection) + if res is None: + raise ValueError("Unknown protection %s" % protection) + + if protection.startswith("PBKDF"): + pbkdf = "pbkdf2" + pbkdf2_hmac_algo = res.group(2) + enc_algo = res.group(3) + else: + pbkdf = "scrypt" + enc_algo = res.group(3) + + aead = False + if enc_algo == "DES-EDE3-CBC": + from Cryptodome.Cipher import DES3 + + key_size = 24 + module = DES3 + cipher_mode = DES3.MODE_CBC + enc_oid = _OID_DES_EDE3_CBC + enc_param = {"iv": randfunc(8)} + elif enc_algo == "AES128-CBC": + key_size = 16 + module = AES + cipher_mode = AES.MODE_CBC + enc_oid = _OID_AES128_CBC + enc_param = {"iv": randfunc(16)} + elif enc_algo == "AES192-CBC": + key_size = 24 + module = AES + cipher_mode = AES.MODE_CBC + enc_oid = _OID_AES192_CBC + enc_param = {"iv": randfunc(16)} + elif enc_algo == "AES256-CBC": + key_size = 32 + module = AES + cipher_mode = AES.MODE_CBC + enc_oid = _OID_AES256_CBC + enc_param = {"iv": randfunc(16)} + elif enc_algo == "AES128-GCM": + key_size = 16 + module = AES + cipher_mode = AES.MODE_GCM + enc_oid = _OID_AES128_GCM + enc_param = {"nonce": randfunc(12)} + aead = True + elif enc_algo == "AES192-GCM": + key_size = 24 + module = AES + cipher_mode = AES.MODE_GCM + enc_oid = _OID_AES192_GCM + enc_param = {"nonce": randfunc(12)} + aead = True + elif enc_algo == "AES256-GCM": + key_size = 32 + module = AES + cipher_mode = AES.MODE_GCM + enc_oid = _OID_AES256_GCM + enc_param = {"nonce": randfunc(12)} + aead = True + else: + raise ValueError("Unknown encryption mode '%s'" % enc_algo) + + iv_nonce = list(enc_param.values())[0] + salt = randfunc(prot_params.get("salt_size", 8)) + + # Derive key from password + if pbkdf == "pbkdf2": + count = prot_params.get("iteration_count", 1000) + digestmod = Hash.new(pbkdf2_hmac_algo) + + key = PBKDF2( + passphrase, + salt, + key_size, + count, + hmac_hash_module=digestmod, + ) + + pbkdf2_params = DerSequence( + [ + DerOctetString(salt), + DerInteger(count), + ] + ) + + if pbkdf2_hmac_algo != "SHA1": + try: + hmac_oid = Hash.HMAC.new(b"", digestmod=digestmod).oid + except KeyError: + raise ValueError("No OID for HMAC hash algorithm") + pbkdf2_params.append(DerSequence([DerObjectId(hmac_oid)])) + + kdf_info = DerSequence( + [ + DerObjectId(_OID_PBKDF2), # PBKDF2 + pbkdf2_params, + ] + ) + + elif pbkdf == "scrypt": + count = prot_params.get("iteration_count", 16384) + scrypt_r = prot_params.get("block_size", 8) + scrypt_p = prot_params.get("parallelization", 1) + key = scrypt( + passphrase, + salt, + key_size, + count, + scrypt_r, + scrypt_p, + ) + kdf_info = DerSequence( + [ + DerObjectId(_OID_SCRYPT), # scrypt + DerSequence( + [ + DerOctetString(salt), + DerInteger(count), + DerInteger(scrypt_r), + DerInteger(scrypt_p), + ] + ), + ] + ) + + else: + raise ValueError("Unknown KDF " + res.group(1)) + + # Create cipher and use it + cipher = module.new(key, cipher_mode, **enc_param) + if aead: + ct, tag = cipher.encrypt_and_digest(data) + encrypted_data = ct + tag + else: + encrypted_data = cipher.encrypt(pad(data, cipher.block_size)) + enc_info = DerSequence( + [ + DerObjectId(enc_oid), + DerOctetString(iv_nonce), + ] + ) + + # Result + enc_private_key_info = DerSequence( + [ + # encryptionAlgorithm + DerSequence( + [ + DerObjectId(_OID_PBES2), + DerSequence( + [ + kdf_info, + enc_info, + ] + ), + ] + ), + DerOctetString(encrypted_data), + ] + ) + return enc_private_key_info.encode() + + @staticmethod + def decrypt(data, passphrase): + """Decrypt a piece of data using a passphrase and *PBES2*. + + The algorithm to use is automatically detected. + + :Parameters: + data : byte string + The piece of data to decrypt. + passphrase : byte string + The passphrase to use for decrypting the data. + :Returns: + The decrypted data, as a binary string. + """ + + enc_private_key_info = DerSequence().decode(data, nr_elements=2) + enc_algo = DerSequence().decode(enc_private_key_info[0]) + encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload + + pbe_oid = DerObjectId().decode(enc_algo[0]).value + if pbe_oid != _OID_PBES2: + raise PbesError("Not a PBES2 object") + + pbes2_params = DerSequence().decode(enc_algo[1], nr_elements=2) + + # Key Derivation Function selection + kdf_info = DerSequence().decode(pbes2_params[0], nr_elements=2) + kdf_oid = DerObjectId().decode(kdf_info[0]).value + + kdf_key_length = None + + # We only support PBKDF2 or scrypt + if kdf_oid == _OID_PBKDF2: + pbkdf2_params = DerSequence().decode(kdf_info[1], nr_elements=(2, 3, 4)) + salt = DerOctetString().decode(pbkdf2_params[0]).payload + iteration_count = pbkdf2_params[1] + + left = len(pbkdf2_params) - 2 + idx = 2 + + if left > 0: + try: + # Check if it's an INTEGER + kdf_key_length = pbkdf2_params[idx] - 0 + left -= 1 + idx += 1 + except TypeError: + # keyLength is not present + pass + + # Default is HMAC-SHA1 + pbkdf2_prf_oid = _OID_HMAC_SHA1 + if left > 0: + pbkdf2_prf_algo_id = DerSequence().decode(pbkdf2_params[idx]) + pbkdf2_prf_oid = DerObjectId().decode(pbkdf2_prf_algo_id[0]).value + + elif kdf_oid == _OID_SCRYPT: + scrypt_params = DerSequence().decode(kdf_info[1], nr_elements=(4, 5)) + salt = DerOctetString().decode(scrypt_params[0]).payload + iteration_count, scrypt_r, scrypt_p = [scrypt_params[x] for x in (1, 2, 3)] + if len(scrypt_params) > 4: + kdf_key_length = scrypt_params[4] + else: + kdf_key_length = None + else: + raise PbesError("Unsupported PBES2 KDF") + + # Cipher selection + enc_info = DerSequence().decode(pbes2_params[1]) + enc_oid = DerObjectId().decode(enc_info[0]).value + + aead = False + if enc_oid == _OID_DES_EDE3_CBC: + # DES_EDE3_CBC + from Cryptodome.Cipher import DES3 + + module = DES3 + cipher_mode = DES3.MODE_CBC + key_size = 24 + cipher_param = "iv" + elif enc_oid == _OID_AES128_CBC: + module = AES + cipher_mode = AES.MODE_CBC + key_size = 16 + cipher_param = "iv" + elif enc_oid == _OID_AES192_CBC: + module = AES + cipher_mode = AES.MODE_CBC + key_size = 24 + cipher_param = "iv" + elif enc_oid == _OID_AES256_CBC: + module = AES + cipher_mode = AES.MODE_CBC + key_size = 32 + cipher_param = "iv" + elif enc_oid == _OID_AES128_GCM: + module = AES + cipher_mode = AES.MODE_GCM + key_size = 16 + cipher_param = "nonce" + aead = True + elif enc_oid == _OID_AES192_GCM: + module = AES + cipher_mode = AES.MODE_GCM + key_size = 24 + cipher_param = "nonce" + aead = True + elif enc_oid == _OID_AES256_GCM: + module = AES + cipher_mode = AES.MODE_GCM + key_size = 32 + cipher_param = "nonce" + aead = True + else: + raise PbesError("Unsupported PBES2 cipher " + enc_algo) + + if kdf_key_length and kdf_key_length != key_size: + raise PbesError( + "Mismatch between PBES2 KDF parameters and selected cipher", + ) + + iv_nonce = DerOctetString().decode(enc_info[1]).payload + + # Create cipher + if kdf_oid == _OID_PBKDF2: + try: + hmac_hash_module_oid = Hash.HMAC._hmac2hash_oid[pbkdf2_prf_oid] + except KeyError: + raise PbesError("Unsupported HMAC %s" % pbkdf2_prf_oid) + hmac_hash_module = Hash.new(hmac_hash_module_oid) + + key = PBKDF2( + passphrase, + salt, + key_size, + iteration_count, + hmac_hash_module=hmac_hash_module, + ) + else: + key = scrypt( + passphrase, + salt, + key_size, + iteration_count, + scrypt_r, + scrypt_p, + ) + cipher = module.new(key, cipher_mode, **{cipher_param: iv_nonce}) + + # Decrypt data + if len(encrypted_data) < cipher.block_size: + raise ValueError("Too little data to decrypt") + + if aead: + tag_len = cipher.block_size + pt = cipher.decrypt_and_verify( + encrypted_data[:-tag_len], + encrypted_data[-tag_len:], + ) + else: + pt_padded = cipher.decrypt(encrypted_data) + pt = unpad(pt_padded, cipher.block_size) + + return pt diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/_PBES.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/_PBES.pyi index 06733640..ca27e7fd 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/_PBES.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/_PBES.pyi @@ -1,26 +1,26 @@ from typing import Optional, Callable, TypedDict from typing_extensions import NotRequired -class PbesError(ValueError): - ... +class PbesError(ValueError): ... class PBES1(object): - @staticmethod - def decrypt(data: bytes, passphrase: bytes) -> bytes: ... + @staticmethod + def decrypt(data: bytes, passphrase: bytes) -> bytes: ... class ProtParams(TypedDict): - iteration_count: NotRequired[int] - salt_size: NotRequired[int] - block_size: NotRequired[int] - parallelization: NotRequired[int] + iteration_count: NotRequired[int] + salt_size: NotRequired[int] + block_size: NotRequired[int] + parallelization: NotRequired[int] class PBES2(object): - @staticmethod - def encrypt(data: bytes, - passphrase: bytes, - protection: str, - prot_params: Optional[ProtParams] = ..., - randfunc: Optional[Callable[[int],bytes]] = ...) -> bytes: ... - - @staticmethod - def decrypt(data:bytes, passphrase: bytes) -> bytes: ... + @staticmethod + def encrypt( + data: bytes, + passphrase: bytes, + protection: str, + prot_params: Optional[ProtParams] = ..., + randfunc: Optional[Callable[[int], bytes]] = ..., + ) -> bytes: ... + @staticmethod + def decrypt(data: bytes, passphrase: bytes) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/__init__.py index 85a0d0b1..794fb76e 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/IO/__init__.py @@ -28,4 +28,4 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = ['PEM', 'PKCS8'] +__all__ = ["PEM", "PKCS8"] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Numbers.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Numbers.py index 9e96686b..0724e9f0 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Numbers.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Numbers.py @@ -33,15 +33,16 @@ import os try: - if os.getenv("PYCRYPTODOME_DISABLE_GMP"): - raise ImportError() + if os.getenv("PYCRYPTODOME_DISABLE_GMP"): + raise ImportError() - from Cryptodome.Math._IntegerGMP import IntegerGMP as Integer - from Cryptodome.Math._IntegerGMP import implementation as _implementation + from Cryptodome.Math._IntegerGMP import IntegerGMP as Integer + from Cryptodome.Math._IntegerGMP import implementation as _implementation except (ImportError, OSError, AttributeError): - try: - from Cryptodome.Math._IntegerCustom import IntegerCustom as Integer - from Cryptodome.Math._IntegerCustom import implementation as _implementation - except (ImportError, OSError): - from Cryptodome.Math._IntegerNative import IntegerNative as Integer - _implementation = {} + try: + from Cryptodome.Math._IntegerCustom import IntegerCustom as Integer + from Cryptodome.Math._IntegerCustom import implementation as _implementation + except (ImportError, OSError): + from Cryptodome.Math._IntegerNative import IntegerNative as Integer + + _implementation = {} diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Numbers.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Numbers.pyi index b0206ca4..4cb0a758 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Numbers.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Numbers.pyi @@ -1,2 +1,3 @@ from Cryptodome.Math._IntegerBase import IntegerBase as Integer -__all__ = ['Integer'] + +__all__ = ["Integer"] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Primality.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Primality.py index 33814fa8..ae81b658 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Primality.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Primality.py @@ -43,327 +43,353 @@ def miller_rabin_test(candidate, iterations, randfunc=None): - """Perform a Miller-Rabin primality test on an integer. - - The test is specified in Section C.3.1 of `FIPS PUB 186-4`__. - - :Parameters: - candidate : integer - The number to test for primality. - iterations : integer - The maximum number of iterations to perform before - declaring a candidate a probable prime. - randfunc : callable - An RNG function where bases are taken from. - - :Returns: - ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. - - .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if not isinstance(candidate, Integer): - candidate = Integer(candidate) - - if candidate in (1, 2, 3, 5): - return PROBABLY_PRIME - - if candidate.is_even(): - return COMPOSITE - - one = Integer(1) - minus_one = Integer(candidate - 1) - - if randfunc is None: - randfunc = Random.new().read - - # Step 1 and 2 - m = Integer(minus_one) - a = 0 - while m.is_even(): - m >>= 1 - a += 1 - - # Skip step 3 - - # Step 4 - for i in iter_range(iterations): - - # Step 4.1-2 - base = 1 - while base in (one, minus_one): - base = Integer.random_range(min_inclusive=2, - max_inclusive=candidate - 2, - randfunc=randfunc) - assert(2 <= base <= candidate - 2) - - # Step 4.3-4.4 - z = pow(base, m, candidate) - if z in (one, minus_one): - continue - - # Step 4.5 - for j in iter_range(1, a): - z = pow(z, 2, candidate) - if z == minus_one: - break - if z == one: - return COMPOSITE - else: - return COMPOSITE - - # Step 5 - return PROBABLY_PRIME + """Perform a Miller-Rabin primality test on an integer. + + The test is specified in Section C.3.1 of `FIPS PUB 186-4`__. + + :Parameters: + candidate : integer + The number to test for primality. + iterations : integer + The maximum number of iterations to perform before + declaring a candidate a probable prime. + randfunc : callable + An RNG function where bases are taken from. + + :Returns: + ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. + + .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ + + if not isinstance(candidate, Integer): + candidate = Integer(candidate) + + if candidate in (1, 2, 3, 5): + return PROBABLY_PRIME + + if candidate.is_even(): + return COMPOSITE + + one = Integer(1) + minus_one = Integer(candidate - 1) + + if randfunc is None: + randfunc = Random.new().read + + # Step 1 and 2 + m = Integer(minus_one) + a = 0 + while m.is_even(): + m >>= 1 + a += 1 + + # Skip step 3 + + # Step 4 + for i in iter_range(iterations): + # Step 4.1-2 + base = 1 + while base in (one, minus_one): + base = Integer.random_range( + min_inclusive=2, + max_inclusive=candidate - 2, + randfunc=randfunc, + ) + assert 2 <= base <= candidate - 2 + + # Step 4.3-4.4 + z = pow(base, m, candidate) + if z in (one, minus_one): + continue + + # Step 4.5 + for j in iter_range(1, a): + z = pow(z, 2, candidate) + if z == minus_one: + break + if z == one: + return COMPOSITE + else: + return COMPOSITE + + # Step 5 + return PROBABLY_PRIME def lucas_test(candidate): - """Perform a Lucas primality test on an integer. - - The test is specified in Section C.3.3 of `FIPS PUB 186-4`__. - - :Parameters: - candidate : integer - The number to test for primality. - - :Returns: - ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. - - .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if not isinstance(candidate, Integer): - candidate = Integer(candidate) - - # Step 1 - if candidate in (1, 2, 3, 5): - return PROBABLY_PRIME - if candidate.is_even() or candidate.is_perfect_square(): - return COMPOSITE - - # Step 2 - def alternate(): - value = 5 - while True: - yield value - if value > 0: - value += 2 - else: - value -= 2 - value = -value - - for D in alternate(): - if candidate in (D, -D): - continue - js = Integer.jacobi_symbol(D, candidate) - if js == 0: - return COMPOSITE - if js == -1: - break - # Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer) - - # Step 3 - # This is \delta(n) = n - jacobi(D/n) - K = candidate + 1 - # Step 4 - r = K.size_in_bits() - 1 - # Step 5 - # U_1=1 and V_1=P - U_i = Integer(1) - V_i = Integer(1) - U_temp = Integer(0) - V_temp = Integer(0) - # Step 6 - for i in iter_range(r - 1, -1, -1): - # Square - # U_temp = U_i * V_i % candidate - U_temp.set(U_i) - U_temp *= V_i - U_temp %= candidate - # V_temp = (((V_i ** 2 + (U_i ** 2 * D)) * K) >> 1) % candidate - V_temp.set(U_i) - V_temp *= U_i - V_temp *= D - V_temp.multiply_accumulate(V_i, V_i) - if V_temp.is_odd(): - V_temp += candidate - V_temp >>= 1 - V_temp %= candidate - # Multiply - if K.get_bit(i): - # U_i = (((U_temp + V_temp) * K) >> 1) % candidate - U_i.set(U_temp) - U_i += V_temp - if U_i.is_odd(): - U_i += candidate - U_i >>= 1 - U_i %= candidate - # V_i = (((V_temp + U_temp * D) * K) >> 1) % candidate - V_i.set(V_temp) - V_i.multiply_accumulate(U_temp, D) - if V_i.is_odd(): - V_i += candidate - V_i >>= 1 - V_i %= candidate - else: - U_i.set(U_temp) - V_i.set(V_temp) - # Step 7 - if U_i == 0: - return PROBABLY_PRIME - return COMPOSITE + """Perform a Lucas primality test on an integer. + + The test is specified in Section C.3.3 of `FIPS PUB 186-4`__. + + :Parameters: + candidate : integer + The number to test for primality. + + :Returns: + ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. + + .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ + + if not isinstance(candidate, Integer): + candidate = Integer(candidate) + + # Step 1 + if candidate in (1, 2, 3, 5): + return PROBABLY_PRIME + if candidate.is_even() or candidate.is_perfect_square(): + return COMPOSITE + + # Step 2 + def alternate(): + value = 5 + while True: + yield value + if value > 0: + value += 2 + else: + value -= 2 + value = -value + + for D in alternate(): + if candidate in (D, -D): + continue + js = Integer.jacobi_symbol(D, candidate) + if js == 0: + return COMPOSITE + if js == -1: + break + # Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer) + + # Step 3 + # This is \delta(n) = n - jacobi(D/n) + K = candidate + 1 + # Step 4 + r = K.size_in_bits() - 1 + # Step 5 + # U_1=1 and V_1=P + U_i = Integer(1) + V_i = Integer(1) + U_temp = Integer(0) + V_temp = Integer(0) + # Step 6 + for i in iter_range(r - 1, -1, -1): + # Square + # U_temp = U_i * V_i % candidate + U_temp.set(U_i) + U_temp *= V_i + U_temp %= candidate + # V_temp = (((V_i ** 2 + (U_i ** 2 * D)) * K) >> 1) % candidate + V_temp.set(U_i) + V_temp *= U_i + V_temp *= D + V_temp.multiply_accumulate(V_i, V_i) + if V_temp.is_odd(): + V_temp += candidate + V_temp >>= 1 + V_temp %= candidate + # Multiply + if K.get_bit(i): + # U_i = (((U_temp + V_temp) * K) >> 1) % candidate + U_i.set(U_temp) + U_i += V_temp + if U_i.is_odd(): + U_i += candidate + U_i >>= 1 + U_i %= candidate + # V_i = (((V_temp + U_temp * D) * K) >> 1) % candidate + V_i.set(V_temp) + V_i.multiply_accumulate(U_temp, D) + if V_i.is_odd(): + V_i += candidate + V_i >>= 1 + V_i %= candidate + else: + U_i.set(U_temp) + V_i.set(V_temp) + # Step 7 + if U_i == 0: + return PROBABLY_PRIME + return COMPOSITE from Cryptodome.Util.number import sieve_base as _sieve_base_large + ## The optimal number of small primes to use for the sieve ## is probably dependent on the platform and the candidate size _sieve_base = set(_sieve_base_large[:100]) def test_probable_prime(candidate, randfunc=None): - """Test if a number is prime. - - A number is qualified as prime if it passes a certain - number of Miller-Rabin tests (dependent on the size - of the number, but such that probability of a false - positive is less than 10^-30) and a single Lucas test. - - For instance, a 1024-bit candidate will need to pass - 4 Miller-Rabin tests. - - :Parameters: - candidate : integer - The number to test for primality. - randfunc : callable - The routine to draw random bytes from to select Miller-Rabin bases. - :Returns: - ``PROBABLE_PRIME`` if the number if prime with very high probability. - ``COMPOSITE`` if the number is a composite. - For efficiency reasons, ``COMPOSITE`` is also returned for small primes. - """ - - if randfunc is None: - randfunc = Random.new().read - - if not isinstance(candidate, Integer): - candidate = Integer(candidate) - - # First, check trial division by the smallest primes - if int(candidate) in _sieve_base: - return PROBABLY_PRIME - try: - map(candidate.fail_if_divisible_by, _sieve_base) - except ValueError: - return COMPOSITE - - # These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30, - # with p(k, t) being the probability that a randomly chosen k-bit number - # is composite but still survives t MR iterations. - mr_ranges = ((220, 30), (280, 20), (390, 15), (512, 10), - (620, 7), (740, 6), (890, 5), (1200, 4), - (1700, 3), (3700, 2)) - - bit_size = candidate.size_in_bits() - try: - mr_iterations = list(filter(lambda x: bit_size < x[0], - mr_ranges))[0][1] - except IndexError: - mr_iterations = 1 - - if miller_rabin_test(candidate, mr_iterations, - randfunc=randfunc) == COMPOSITE: - return COMPOSITE - if lucas_test(candidate) == COMPOSITE: - return COMPOSITE - return PROBABLY_PRIME + """Test if a number is prime. + + A number is qualified as prime if it passes a certain + number of Miller-Rabin tests (dependent on the size + of the number, but such that probability of a false + positive is less than 10^-30) and a single Lucas test. + + For instance, a 1024-bit candidate will need to pass + 4 Miller-Rabin tests. + + :Parameters: + candidate : integer + The number to test for primality. + randfunc : callable + The routine to draw random bytes from to select Miller-Rabin bases. + :Returns: + ``PROBABLE_PRIME`` if the number if prime with very high probability. + ``COMPOSITE`` if the number is a composite. + For efficiency reasons, ``COMPOSITE`` is also returned for small primes. + """ + + if randfunc is None: + randfunc = Random.new().read + + if not isinstance(candidate, Integer): + candidate = Integer(candidate) + + # First, check trial division by the smallest primes + if int(candidate) in _sieve_base: + return PROBABLY_PRIME + try: + map(candidate.fail_if_divisible_by, _sieve_base) + except ValueError: + return COMPOSITE + + # These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30, + # with p(k, t) being the probability that a randomly chosen k-bit number + # is composite but still survives t MR iterations. + mr_ranges = ( + (220, 30), + (280, 20), + (390, 15), + (512, 10), + (620, 7), + (740, 6), + (890, 5), + (1200, 4), + (1700, 3), + (3700, 2), + ) + + bit_size = candidate.size_in_bits() + try: + mr_iterations = list( + filter( + lambda x: bit_size < x[0], + mr_ranges, + ), + )[0][1] + except IndexError: + mr_iterations = 1 + + if ( + miller_rabin_test( + candidate, + mr_iterations, + randfunc=randfunc, + ) + == COMPOSITE + ): + return COMPOSITE + if lucas_test(candidate) == COMPOSITE: + return COMPOSITE + return PROBABLY_PRIME def generate_probable_prime(**kwargs): - """Generate a random probable prime. - - The prime will not have any specific properties - (e.g. it will not be a *strong* prime). - - Random numbers are evaluated for primality until one - passes all tests, consisting of a certain number of - Miller-Rabin tests with random bases followed by - a single Lucas test. - - The number of Miller-Rabin iterations is chosen such that - the probability that the output number is a non-prime is - less than 1E-30 (roughly 2^{-100}). - - This approach is compliant to `FIPS PUB 186-4`__. - - :Keywords: - exact_bits : integer - The desired size in bits of the probable prime. - It must be at least 160. - randfunc : callable - An RNG function where candidate primes are taken from. - prime_filter : callable - A function that takes an Integer as parameter and returns - True if the number can be passed to further primality tests, - False if it should be immediately discarded. - - :Return: - A probable prime in the range 2^exact_bits > p > 2^(exact_bits-1). - - .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - exact_bits = kwargs.pop("exact_bits", None) - randfunc = kwargs.pop("randfunc", None) - prime_filter = kwargs.pop("prime_filter", lambda x: True) - if kwargs: - raise ValueError("Unknown parameters: " + kwargs.keys()) - - if exact_bits is None: - raise ValueError("Missing exact_bits parameter") - if exact_bits < 160: - raise ValueError("Prime number is not big enough.") - - if randfunc is None: - randfunc = Random.new().read - - result = COMPOSITE - while result == COMPOSITE: - candidate = Integer.random(exact_bits=exact_bits, - randfunc=randfunc) | 1 - if not prime_filter(candidate): - continue - result = test_probable_prime(candidate, randfunc) - return candidate + """Generate a random probable prime. + + The prime will not have any specific properties + (e.g. it will not be a *strong* prime). + + Random numbers are evaluated for primality until one + passes all tests, consisting of a certain number of + Miller-Rabin tests with random bases followed by + a single Lucas test. + + The number of Miller-Rabin iterations is chosen such that + the probability that the output number is a non-prime is + less than 1E-30 (roughly 2^{-100}). + + This approach is compliant to `FIPS PUB 186-4`__. + + :Keywords: + exact_bits : integer + The desired size in bits of the probable prime. + It must be at least 160. + randfunc : callable + An RNG function where candidate primes are taken from. + prime_filter : callable + A function that takes an Integer as parameter and returns + True if the number can be passed to further primality tests, + False if it should be immediately discarded. + + :Return: + A probable prime in the range 2^exact_bits > p > 2^(exact_bits-1). + + .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ + + exact_bits = kwargs.pop("exact_bits", None) + randfunc = kwargs.pop("randfunc", None) + prime_filter = kwargs.pop("prime_filter", lambda x: True) + if kwargs: + raise ValueError("Unknown parameters: " + kwargs.keys()) + + if exact_bits is None: + raise ValueError("Missing exact_bits parameter") + if exact_bits < 160: + raise ValueError("Prime number is not big enough.") + + if randfunc is None: + randfunc = Random.new().read + + result = COMPOSITE + while result == COMPOSITE: + candidate = ( + Integer.random( + exact_bits=exact_bits, + randfunc=randfunc, + ) + | 1 + ) + if not prime_filter(candidate): + continue + result = test_probable_prime(candidate, randfunc) + return candidate def generate_probable_safe_prime(**kwargs): - """Generate a random, probable safe prime. - - Note this operation is much slower than generating a simple prime. - - :Keywords: - exact_bits : integer - The desired size in bits of the probable safe prime. - randfunc : callable - An RNG function where candidate primes are taken from. - - :Return: - A probable safe prime in the range - 2^exact_bits > p > 2^(exact_bits-1). - """ - - exact_bits = kwargs.pop("exact_bits", None) - randfunc = kwargs.pop("randfunc", None) - if kwargs: - raise ValueError("Unknown parameters: " + kwargs.keys()) - - if randfunc is None: - randfunc = Random.new().read - - result = COMPOSITE - while result == COMPOSITE: - q = generate_probable_prime(exact_bits=exact_bits - 1, randfunc=randfunc) - candidate = q * 2 + 1 - if candidate.size_in_bits() != exact_bits: - continue - result = test_probable_prime(candidate, randfunc=randfunc) - return candidate + """Generate a random, probable safe prime. + + Note this operation is much slower than generating a simple prime. + + :Keywords: + exact_bits : integer + The desired size in bits of the probable safe prime. + randfunc : callable + An RNG function where candidate primes are taken from. + + :Return: + A probable safe prime in the range + 2^exact_bits > p > 2^(exact_bits-1). + """ + + exact_bits = kwargs.pop("exact_bits", None) + randfunc = kwargs.pop("randfunc", None) + if kwargs: + raise ValueError("Unknown parameters: " + kwargs.keys()) + + if randfunc is None: + randfunc = Random.new().read + + result = COMPOSITE + while result == COMPOSITE: + q = generate_probable_prime(exact_bits=exact_bits - 1, randfunc=randfunc) + candidate = q * 2 + 1 + if candidate.size_in_bits() != exact_bits: + continue + result = test_probable_prime(candidate, randfunc=randfunc) + return candidate diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Primality.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Primality.pyi index 78134830..efa634d3 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Primality.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/Primality.pyi @@ -1,18 +1,22 @@ -from typing import Callable, Optional, Union, Set +from typing import Callable, Optional, Set PrimeResult = int COMPOSITE: PrimeResult PROBABLY_PRIME: PrimeResult -def miller_rabin_test(candidate: int, iterations: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ... +def miller_rabin_test( + candidate: int, iterations: int, randfunc: Optional[Callable[[int], bytes]] = None +) -> PrimeResult: ... def lucas_test(candidate: int) -> PrimeResult: ... + _sieve_base: Set[int] -def test_probable_prime(candidate: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ... -def generate_probable_prime(*, - exact_bits: int = ..., - randfunc: Callable[[int],bytes] = ..., - prime_filter: Callable[[int],bool] = ...) -> int: ... -def generate_probable_safe_prime(*, - exact_bits: int = ..., - randfunc: Callable[[int],bytes] = ...) -> int: ... + +def test_probable_prime(candidate: int, randfunc: Optional[Callable[[int], bytes]] = None) -> PrimeResult: ... +def generate_probable_prime( + *, + exact_bits: int = ..., + randfunc: Callable[[int], bytes] = ..., + prime_filter: Callable[[int], bool] = ..., +) -> int: ... +def generate_probable_safe_prime(*, exact_bits: int = ..., randfunc: Callable[[int], bytes] = ...) -> int: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerBase.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerBase.py index 03dd5916..7898b142 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerBase.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerBase.py @@ -36,377 +36,378 @@ class IntegerBase(ABC): + # Conversions + @abc.abstractmethod + def __int__(self): + pass + + @abc.abstractmethod + def __str__(self): + pass + + @abc.abstractmethod + def __repr__(self): + pass + + @abc.abstractmethod + def to_bytes(self, block_size=0, byteorder="big"): + pass + + @staticmethod + @abc.abstractmethod + def from_bytes(byte_string, byteorder="big"): + pass + + # Relations + @abc.abstractmethod + def __eq__(self, term): + pass - # Conversions - @abc.abstractmethod - def __int__(self): - pass + @abc.abstractmethod + def __ne__(self, term): + pass - @abc.abstractmethod - def __str__(self): - pass + @abc.abstractmethod + def __lt__(self, term): + pass - @abc.abstractmethod - def __repr__(self): - pass - - @abc.abstractmethod - def to_bytes(self, block_size=0, byteorder='big'): - pass - - @staticmethod - @abc.abstractmethod - def from_bytes(byte_string, byteorder='big'): - pass + @abc.abstractmethod + def __le__(self, term): + pass - # Relations - @abc.abstractmethod - def __eq__(self, term): - pass - - @abc.abstractmethod - def __ne__(self, term): - pass - - @abc.abstractmethod - def __lt__(self, term): - pass - - @abc.abstractmethod - def __le__(self, term): - pass - - @abc.abstractmethod - def __gt__(self, term): - pass - - @abc.abstractmethod - def __ge__(self, term): - pass - - @abc.abstractmethod - def __nonzero__(self): - pass - __bool__ = __nonzero__ - - @abc.abstractmethod - def is_negative(self): - pass - - # Arithmetic operations - @abc.abstractmethod - def __add__(self, term): - pass - - @abc.abstractmethod - def __sub__(self, term): - pass - - @abc.abstractmethod - def __mul__(self, factor): - pass - - @abc.abstractmethod - def __floordiv__(self, divisor): - pass - - @abc.abstractmethod - def __mod__(self, divisor): - pass - - @abc.abstractmethod - def inplace_pow(self, exponent, modulus=None): - pass - - @abc.abstractmethod - def __pow__(self, exponent, modulus=None): - pass - - @abc.abstractmethod - def __abs__(self): - pass - - @abc.abstractmethod - def sqrt(self, modulus=None): - pass - - @abc.abstractmethod - def __iadd__(self, term): - pass - - @abc.abstractmethod - def __isub__(self, term): - pass - - @abc.abstractmethod - def __imul__(self, term): - pass - - @abc.abstractmethod - def __imod__(self, term): - pass + @abc.abstractmethod + def __gt__(self, term): + pass + + @abc.abstractmethod + def __ge__(self, term): + pass + + @abc.abstractmethod + def __nonzero__(self): + pass + + __bool__ = __nonzero__ + + @abc.abstractmethod + def is_negative(self): + pass + + # Arithmetic operations + @abc.abstractmethod + def __add__(self, term): + pass + + @abc.abstractmethod + def __sub__(self, term): + pass + + @abc.abstractmethod + def __mul__(self, factor): + pass + + @abc.abstractmethod + def __floordiv__(self, divisor): + pass + + @abc.abstractmethod + def __mod__(self, divisor): + pass + + @abc.abstractmethod + def inplace_pow(self, exponent, modulus=None): + pass + + @abc.abstractmethod + def __pow__(self, exponent, modulus=None): + pass + + @abc.abstractmethod + def __abs__(self): + pass + + @abc.abstractmethod + def sqrt(self, modulus=None): + pass + + @abc.abstractmethod + def __iadd__(self, term): + pass + + @abc.abstractmethod + def __isub__(self, term): + pass + + @abc.abstractmethod + def __imul__(self, term): + pass + + @abc.abstractmethod + def __imod__(self, term): + pass - # Boolean/bit operations - @abc.abstractmethod - def __and__(self, term): - pass - - @abc.abstractmethod - def __or__(self, term): - pass - - @abc.abstractmethod - def __rshift__(self, pos): - pass - - @abc.abstractmethod - def __irshift__(self, pos): - pass - - @abc.abstractmethod - def __lshift__(self, pos): - pass - - @abc.abstractmethod - def __ilshift__(self, pos): - pass - - @abc.abstractmethod - def get_bit(self, n): - pass - - # Extra - @abc.abstractmethod - def is_odd(self): - pass - - @abc.abstractmethod - def is_even(self): - pass - - @abc.abstractmethod - def size_in_bits(self): - pass - - @abc.abstractmethod - def size_in_bytes(self): - pass - - @abc.abstractmethod - def is_perfect_square(self): - pass - - @abc.abstractmethod - def fail_if_divisible_by(self, small_prime): - pass - - @abc.abstractmethod - def multiply_accumulate(self, a, b): - pass - - @abc.abstractmethod - def set(self, source): - pass - - @abc.abstractmethod - def inplace_inverse(self, modulus): - pass - - @abc.abstractmethod - def inverse(self, modulus): - pass - - @abc.abstractmethod - def gcd(self, term): - pass - - @abc.abstractmethod - def lcm(self, term): - pass - - @staticmethod - @abc.abstractmethod - def jacobi_symbol(a, n): - pass - - @staticmethod - def _tonelli_shanks(n, p): - """Tonelli-shanks algorithm for computing the square root - of n modulo a prime p. - - n must be in the range [0..p-1]. - p must be at least even. - - The return value r is the square root of modulo p. If non-zero, - another solution will also exist (p-r). - - Note we cannot assume that p is really a prime: if it's not, - we can either raise an exception or return the correct value. - """ - - # See https://rosettacode.org/wiki/Tonelli-Shanks_algorithm - - if n in (0, 1): - return n - - if p % 4 == 3: - root = pow(n, (p + 1) // 4, p) - if pow(root, 2, p) != n: - raise ValueError("Cannot compute square root") - return root - - s = 1 - q = (p - 1) // 2 - while not (q & 1): - s += 1 - q >>= 1 - - z = n.__class__(2) - while True: - euler = pow(z, (p - 1) // 2, p) - if euler == 1: - z += 1 - continue - if euler == p - 1: - break - # Most probably p is not a prime - raise ValueError("Cannot compute square root") - - m = s - c = pow(z, q, p) - t = pow(n, q, p) - r = pow(n, (q + 1) // 2, p) - - while t != 1: - for i in iter_range(0, m): - if pow(t, 2**i, p) == 1: - break - if i == m: - raise ValueError("Cannot compute square root of %d mod %d" % (n, p)) - b = pow(c, 2**(m - i - 1), p) - m = i - c = b**2 % p - t = (t * b**2) % p - r = (r * b) % p - - if pow(r, 2, p) != n: - raise ValueError("Cannot compute square root") - - return r - - @classmethod - def random(cls, **kwargs): - """Generate a random natural integer of a certain size. - - :Keywords: - exact_bits : positive integer - The length in bits of the resulting random Integer number. - The number is guaranteed to fulfil the relation: - - 2^bits > result >= 2^(bits - 1) - - max_bits : positive integer - The maximum length in bits of the resulting random Integer number. - The number is guaranteed to fulfil the relation: - - 2^bits > result >=0 - - randfunc : callable - A function that returns a random byte string. The length of the - byte string is passed as parameter. Optional. - If not provided (or ``None``), randomness is read from the system RNG. - - :Return: a Integer object - """ - - exact_bits = kwargs.pop("exact_bits", None) - max_bits = kwargs.pop("max_bits", None) - randfunc = kwargs.pop("randfunc", None) - - if randfunc is None: - randfunc = Random.new().read - - if exact_bits is None and max_bits is None: - raise ValueError("Either 'exact_bits' or 'max_bits' must be specified") - - if exact_bits is not None and max_bits is not None: - raise ValueError("'exact_bits' and 'max_bits' are mutually exclusive") - - bits = exact_bits or max_bits - bytes_needed = ((bits - 1) // 8) + 1 - significant_bits_msb = 8 - (bytes_needed * 8 - bits) - msb = bord(randfunc(1)[0]) - if exact_bits is not None: - msb |= 1 << (significant_bits_msb - 1) - msb &= (1 << significant_bits_msb) - 1 - - return cls.from_bytes(bchr(msb) + randfunc(bytes_needed - 1)) - - @classmethod - def random_range(cls, **kwargs): - """Generate a random integer within a given internal. - - :Keywords: - min_inclusive : integer - The lower end of the interval (inclusive). - max_inclusive : integer - The higher end of the interval (inclusive). - max_exclusive : integer - The higher end of the interval (exclusive). - randfunc : callable - A function that returns a random byte string. The length of the - byte string is passed as parameter. Optional. - If not provided (or ``None``), randomness is read from the system RNG. - :Returns: - An Integer randomly taken in the given interval. - """ - - min_inclusive = kwargs.pop("min_inclusive", None) - max_inclusive = kwargs.pop("max_inclusive", None) - max_exclusive = kwargs.pop("max_exclusive", None) - randfunc = kwargs.pop("randfunc", None) - - if kwargs: - raise ValueError("Unknown keywords: " + str(kwargs.keys)) - if None not in (max_inclusive, max_exclusive): - raise ValueError("max_inclusive and max_exclusive cannot be both" - " specified") - if max_exclusive is not None: - max_inclusive = max_exclusive - 1 - if None in (min_inclusive, max_inclusive): - raise ValueError("Missing keyword to identify the interval") - - if randfunc is None: - randfunc = Random.new().read - - norm_maximum = max_inclusive - min_inclusive - bits_needed = cls(norm_maximum).size_in_bits() - - norm_candidate = -1 - while not 0 <= norm_candidate <= norm_maximum: - norm_candidate = cls.random( - max_bits=bits_needed, - randfunc=randfunc - ) - return norm_candidate + min_inclusive - - @staticmethod - @abc.abstractmethod - def _mult_modulo_bytes(term1, term2, modulus): - """Multiply two integers, take the modulo, and encode as big endian. - This specialized method is used for RSA decryption. - - Args: - term1 : integer - The first term of the multiplication, non-negative. - term2 : integer - The second term of the multiplication, non-negative. - modulus: integer - The modulus, a positive odd number. - :Returns: - A byte string, with the result of the modular multiplication - encoded in big endian mode. - It is as long as the modulus would be, with zero padding - on the left if needed. - """ - pass + # Boolean/bit operations + @abc.abstractmethod + def __and__(self, term): + pass + + @abc.abstractmethod + def __or__(self, term): + pass + + @abc.abstractmethod + def __rshift__(self, pos): + pass + + @abc.abstractmethod + def __irshift__(self, pos): + pass + + @abc.abstractmethod + def __lshift__(self, pos): + pass + + @abc.abstractmethod + def __ilshift__(self, pos): + pass + + @abc.abstractmethod + def get_bit(self, n): + pass + + # Extra + @abc.abstractmethod + def is_odd(self): + pass + + @abc.abstractmethod + def is_even(self): + pass + + @abc.abstractmethod + def size_in_bits(self): + pass + + @abc.abstractmethod + def size_in_bytes(self): + pass + + @abc.abstractmethod + def is_perfect_square(self): + pass + + @abc.abstractmethod + def fail_if_divisible_by(self, small_prime): + pass + + @abc.abstractmethod + def multiply_accumulate(self, a, b): + pass + + @abc.abstractmethod + def set(self, source): + pass + + @abc.abstractmethod + def inplace_inverse(self, modulus): + pass + + @abc.abstractmethod + def inverse(self, modulus): + pass + + @abc.abstractmethod + def gcd(self, term): + pass + + @abc.abstractmethod + def lcm(self, term): + pass + + @staticmethod + @abc.abstractmethod + def jacobi_symbol(a, n): + pass + + @staticmethod + def _tonelli_shanks(n, p): + """Tonelli-shanks algorithm for computing the square root + of n modulo a prime p. + + n must be in the range [0..p-1]. + p must be at least even. + + The return value r is the square root of modulo p. If non-zero, + another solution will also exist (p-r). + + Note we cannot assume that p is really a prime: if it's not, + we can either raise an exception or return the correct value. + """ + + # See https://rosettacode.org/wiki/Tonelli-Shanks_algorithm + + if n in (0, 1): + return n + + if p % 4 == 3: + root = pow(n, (p + 1) // 4, p) + if pow(root, 2, p) != n: + raise ValueError("Cannot compute square root") + return root + + s = 1 + q = (p - 1) // 2 + while not (q & 1): + s += 1 + q >>= 1 + + z = n.__class__(2) + while True: + euler = pow(z, (p - 1) // 2, p) + if euler == 1: + z += 1 + continue + if euler == p - 1: + break + # Most probably p is not a prime + raise ValueError("Cannot compute square root") + + m = s + c = pow(z, q, p) + t = pow(n, q, p) + r = pow(n, (q + 1) // 2, p) + + while t != 1: + for i in iter_range(0, m): + if pow(t, 2**i, p) == 1: + break + if i == m: + raise ValueError("Cannot compute square root of %d mod %d" % (n, p)) + b = pow(c, 2 ** (m - i - 1), p) + m = i + c = b**2 % p + t = (t * b**2) % p + r = (r * b) % p + + if pow(r, 2, p) != n: + raise ValueError("Cannot compute square root") + + return r + + @classmethod + def random(cls, **kwargs): + """Generate a random natural integer of a certain size. + + :Keywords: + exact_bits : positive integer + The length in bits of the resulting random Integer number. + The number is guaranteed to fulfil the relation: + + 2^bits > result >= 2^(bits - 1) + + max_bits : positive integer + The maximum length in bits of the resulting random Integer number. + The number is guaranteed to fulfil the relation: + + 2^bits > result >=0 + + randfunc : callable + A function that returns a random byte string. The length of the + byte string is passed as parameter. Optional. + If not provided (or ``None``), randomness is read from the system RNG. + + :Return: a Integer object + """ + + exact_bits = kwargs.pop("exact_bits", None) + max_bits = kwargs.pop("max_bits", None) + randfunc = kwargs.pop("randfunc", None) + + if randfunc is None: + randfunc = Random.new().read + + if exact_bits is None and max_bits is None: + raise ValueError("Either 'exact_bits' or 'max_bits' must be specified") + + if exact_bits is not None and max_bits is not None: + raise ValueError("'exact_bits' and 'max_bits' are mutually exclusive") + + bits = exact_bits or max_bits + bytes_needed = ((bits - 1) // 8) + 1 + significant_bits_msb = 8 - (bytes_needed * 8 - bits) + msb = bord(randfunc(1)[0]) + if exact_bits is not None: + msb |= 1 << (significant_bits_msb - 1) + msb &= (1 << significant_bits_msb) - 1 + + return cls.from_bytes(bchr(msb) + randfunc(bytes_needed - 1)) + + @classmethod + def random_range(cls, **kwargs): + """Generate a random integer within a given internal. + + :Keywords: + min_inclusive : integer + The lower end of the interval (inclusive). + max_inclusive : integer + The higher end of the interval (inclusive). + max_exclusive : integer + The higher end of the interval (exclusive). + randfunc : callable + A function that returns a random byte string. The length of the + byte string is passed as parameter. Optional. + If not provided (or ``None``), randomness is read from the system RNG. + :Returns: + An Integer randomly taken in the given interval. + """ + + min_inclusive = kwargs.pop("min_inclusive", None) + max_inclusive = kwargs.pop("max_inclusive", None) + max_exclusive = kwargs.pop("max_exclusive", None) + randfunc = kwargs.pop("randfunc", None) + + if kwargs: + raise ValueError("Unknown keywords: " + str(kwargs.keys)) + if None not in (max_inclusive, max_exclusive): + raise ValueError( + "max_inclusive and max_exclusive cannot be both specified", + ) + if max_exclusive is not None: + max_inclusive = max_exclusive - 1 + if None in (min_inclusive, max_inclusive): + raise ValueError("Missing keyword to identify the interval") + + if randfunc is None: + randfunc = Random.new().read + + norm_maximum = max_inclusive - min_inclusive + bits_needed = cls(norm_maximum).size_in_bits() + + norm_candidate = -1 + while not 0 <= norm_candidate <= norm_maximum: + norm_candidate = cls.random( + max_bits=bits_needed, + randfunc=randfunc, + ) + return norm_candidate + min_inclusive + + @staticmethod + @abc.abstractmethod + def _mult_modulo_bytes(term1, term2, modulus): + """Multiply two integers, take the modulo, and encode as big endian. + This specialized method is used for RSA decryption. + + Args: + term1 : integer + The first term of the multiplication, non-negative. + term2 : integer + The second term of the multiplication, non-negative. + modulus: integer + The modulus, a positive odd number. + :Returns: + A byte string, with the result of the modular multiplication + encoded in big endian mode. + It is as long as the modulus would be, with zero padding + on the left if needed. + """ + pass diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerBase.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerBase.pyi index ea235326..6a8baf03 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerBase.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerBase.pyi @@ -1,67 +1,66 @@ from typing import Optional, Union, Callable -RandFunc = Callable[[int],int] +RandFunc = Callable[[int], int] class IntegerBase: - - def __init__(self, value: Union[IntegerBase, int]): ... - - def __int__(self) -> int: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... - def to_bytes(self, block_size: Optional[int]=0, byteorder: str= ...) -> bytes: ... - @staticmethod - def from_bytes(byte_string: bytes, byteorder: Optional[str] = ...) -> IntegerBase: ... - def __eq__(self, term: object) -> bool: ... - def __ne__(self, term: object) -> bool: ... - def __lt__(self, term: Union[IntegerBase, int]) -> bool: ... - def __le__(self, term: Union[IntegerBase, int]) -> bool: ... - def __gt__(self, term: Union[IntegerBase, int]) -> bool: ... - def __ge__(self, term: Union[IntegerBase, int]) -> bool: ... - def __nonzero__(self) -> bool: ... - def is_negative(self) -> bool: ... - def __add__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __sub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __mul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __floordiv__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... - def __mod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... - def inplace_pow(self, exponent: int, modulus: Optional[Union[IntegerBase, int]]=None) -> IntegerBase: ... - def __pow__(self, exponent: int, modulus: Optional[int]) -> IntegerBase: ... - def __abs__(self) -> IntegerBase: ... - def sqrt(self, modulus: Optional[int]) -> IntegerBase: ... - def __iadd__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __isub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __imul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __imod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... - def __and__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __or__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __rshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def __irshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def __lshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def __ilshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def get_bit(self, n: int) -> bool: ... - def is_odd(self) -> bool: ... - def is_even(self) -> bool: ... - def size_in_bits(self) -> int: ... - def size_in_bytes(self) -> int: ... - def is_perfect_square(self) -> bool: ... - def fail_if_divisible_by(self, small_prime: Union[IntegerBase, int]) -> None: ... - def multiply_accumulate(self, a: Union[IntegerBase, int], b: Union[IntegerBase, int]) -> IntegerBase: ... - def set(self, source: Union[IntegerBase, int]) -> IntegerBase: ... - def inplace_inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... - def inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... - def gcd(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def lcm(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - @staticmethod - def jacobi_symbol(a: Union[IntegerBase, int], n: Union[IntegerBase, int]) -> IntegerBase: ... - @staticmethod - def _tonelli_shanks(n: Union[IntegerBase, int], p: Union[IntegerBase, int]) -> IntegerBase : ... - @classmethod - def random(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ... - @classmethod - def random_range(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ... - @staticmethod - def _mult_modulo_bytes(term1: Union[IntegerBase, int], - term2: Union[IntegerBase, int], - modulus: Union[IntegerBase, int]) -> bytes: ... - + def __init__(self, value: Union[IntegerBase, int]): ... + def __int__(self) -> int: ... + def __str__(self) -> str: ... + def __repr__(self) -> str: ... + def to_bytes(self, block_size: Optional[int] = 0, byteorder: str = ...) -> bytes: ... + @staticmethod + def from_bytes(byte_string: bytes, byteorder: Optional[str] = ...) -> IntegerBase: ... + def __eq__(self, term: object) -> bool: ... + def __ne__(self, term: object) -> bool: ... + def __lt__(self, term: Union[IntegerBase, int]) -> bool: ... + def __le__(self, term: Union[IntegerBase, int]) -> bool: ... + def __gt__(self, term: Union[IntegerBase, int]) -> bool: ... + def __ge__(self, term: Union[IntegerBase, int]) -> bool: ... + def __nonzero__(self) -> bool: ... + def is_negative(self) -> bool: ... + def __add__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __sub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __mul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __floordiv__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... + def __mod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... + def inplace_pow( + self, exponent: int, modulus: Optional[Union[IntegerBase, int]] = None + ) -> IntegerBase: ... + def __pow__(self, exponent: int, modulus: Optional[int]) -> IntegerBase: ... + def __abs__(self) -> IntegerBase: ... + def sqrt(self, modulus: Optional[int]) -> IntegerBase: ... + def __iadd__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __isub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __imul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __imod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... + def __and__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __or__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def __rshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... + def __irshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... + def __lshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... + def __ilshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... + def get_bit(self, n: int) -> bool: ... + def is_odd(self) -> bool: ... + def is_even(self) -> bool: ... + def size_in_bits(self) -> int: ... + def size_in_bytes(self) -> int: ... + def is_perfect_square(self) -> bool: ... + def fail_if_divisible_by(self, small_prime: Union[IntegerBase, int]) -> None: ... + def multiply_accumulate(self, a: Union[IntegerBase, int], b: Union[IntegerBase, int]) -> IntegerBase: ... + def set(self, source: Union[IntegerBase, int]) -> IntegerBase: ... + def inplace_inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... + def inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... + def gcd(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + def lcm(self, term: Union[IntegerBase, int]) -> IntegerBase: ... + @staticmethod + def jacobi_symbol(a: Union[IntegerBase, int], n: Union[IntegerBase, int]) -> IntegerBase: ... + @staticmethod + def _tonelli_shanks(n: Union[IntegerBase, int], p: Union[IntegerBase, int]) -> IntegerBase: ... + @classmethod + def random(cls, **kwargs: Union[int, RandFunc]) -> IntegerBase: ... + @classmethod + def random_range(cls, **kwargs: Union[int, RandFunc]) -> IntegerBase: ... + @staticmethod + def _mult_modulo_bytes( + term1: Union[IntegerBase, int], term2: Union[IntegerBase, int], modulus: Union[IntegerBase, int] + ) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerCustom.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerCustom.py index 20eadcad..592b7d3a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerCustom.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerCustom.py @@ -32,10 +32,14 @@ from Cryptodome.Util.number import long_to_bytes, bytes_to_long -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, backend, - c_size_t, c_ulonglong) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + create_string_buffer, + get_raw_buffer, + backend, + c_size_t, + c_ulonglong, +) from Cryptodome.Random.random import getrandbits @@ -61,102 +65,100 @@ class IntegerCustom(IntegerNative): - - @staticmethod - def from_bytes(byte_string, byteorder='big'): - if byteorder == 'big': - pass - elif byteorder == 'little': - byte_string = bytearray(byte_string) - byte_string.reverse() - else: - raise ValueError("Incorrect byteorder") - return IntegerCustom(bytes_to_long(byte_string)) - - def inplace_pow(self, exponent, modulus=None): - exp_value = int(exponent) - if exp_value < 0: - raise ValueError("Exponent must not be negative") - - # No modular reduction - if modulus is None: - self._value = pow(self._value, exp_value) - return self - - # With modular reduction - mod_value = int(modulus) - if mod_value < 0: - raise ValueError("Modulus must be positive") - if mod_value == 0: - raise ZeroDivisionError("Modulus cannot be zero") - - # C extension only works with odd moduli - if (mod_value & 1) == 0: - self._value = pow(self._value, exp_value, mod_value) - return self - - # C extension only works with bases smaller than modulus - if self._value >= mod_value: - self._value %= mod_value - - max_len = len(long_to_bytes(max(self._value, exp_value, mod_value))) - - base_b = long_to_bytes(self._value, max_len) - exp_b = long_to_bytes(exp_value, max_len) - modulus_b = long_to_bytes(mod_value, max_len) - - out = create_string_buffer(max_len) - - error = _raw_montgomery.monty_pow( - out, - base_b, - exp_b, - modulus_b, - c_size_t(max_len), - c_ulonglong(getrandbits(64)) - ) - - if error: - raise ValueError("monty_pow failed with error: %d" % error) - - result = bytes_to_long(get_raw_buffer(out)) - self._value = result - return self - - @staticmethod - def _mult_modulo_bytes(term1, term2, modulus): - - # With modular reduction - mod_value = int(modulus) - if mod_value < 0: - raise ValueError("Modulus must be positive") - if mod_value == 0: - raise ZeroDivisionError("Modulus cannot be zero") - - # C extension only works with odd moduli - if (mod_value & 1) == 0: - raise ValueError("Odd modulus is required") - - # C extension only works with non-negative terms smaller than modulus - if term1 >= mod_value or term1 < 0: - term1 %= mod_value - if term2 >= mod_value or term2 < 0: - term2 %= mod_value - - modulus_b = long_to_bytes(mod_value) - numbers_len = len(modulus_b) - term1_b = long_to_bytes(term1, numbers_len) - term2_b = long_to_bytes(term2, numbers_len) - out = create_string_buffer(numbers_len) - - error = _raw_montgomery.monty_multiply( - out, - term1_b, - term2_b, - modulus_b, - c_size_t(numbers_len) - ) - if error: - raise ValueError("monty_multiply failed with error: %d" % error) - - return get_raw_buffer(out) + @staticmethod + def from_bytes(byte_string, byteorder="big"): + if byteorder == "big": + pass + elif byteorder == "little": + byte_string = bytearray(byte_string) + byte_string.reverse() + else: + raise ValueError("Incorrect byteorder") + return IntegerCustom(bytes_to_long(byte_string)) + + def inplace_pow(self, exponent, modulus=None): + exp_value = int(exponent) + if exp_value < 0: + raise ValueError("Exponent must not be negative") + + # No modular reduction + if modulus is None: + self._value = pow(self._value, exp_value) + return self + + # With modular reduction + mod_value = int(modulus) + if mod_value < 0: + raise ValueError("Modulus must be positive") + if mod_value == 0: + raise ZeroDivisionError("Modulus cannot be zero") + + # C extension only works with odd moduli + if (mod_value & 1) == 0: + self._value = pow(self._value, exp_value, mod_value) + return self + + # C extension only works with bases smaller than modulus + if self._value >= mod_value: + self._value %= mod_value + + max_len = len(long_to_bytes(max(self._value, exp_value, mod_value))) + + base_b = long_to_bytes(self._value, max_len) + exp_b = long_to_bytes(exp_value, max_len) + modulus_b = long_to_bytes(mod_value, max_len) + + out = create_string_buffer(max_len) + + error = _raw_montgomery.monty_pow( + out, + base_b, + exp_b, + modulus_b, + c_size_t(max_len), + c_ulonglong(getrandbits(64)), + ) + + if error: + raise ValueError("monty_pow failed with error: %d" % error) + + result = bytes_to_long(get_raw_buffer(out)) + self._value = result + return self + + @staticmethod + def _mult_modulo_bytes(term1, term2, modulus): + # With modular reduction + mod_value = int(modulus) + if mod_value < 0: + raise ValueError("Modulus must be positive") + if mod_value == 0: + raise ZeroDivisionError("Modulus cannot be zero") + + # C extension only works with odd moduli + if (mod_value & 1) == 0: + raise ValueError("Odd modulus is required") + + # C extension only works with non-negative terms smaller than modulus + if term1 >= mod_value or term1 < 0: + term1 %= mod_value + if term2 >= mod_value or term2 < 0: + term2 %= mod_value + + modulus_b = long_to_bytes(mod_value) + numbers_len = len(modulus_b) + term1_b = long_to_bytes(term1, numbers_len) + term2_b = long_to_bytes(term2, numbers_len) + out = create_string_buffer(numbers_len) + + error = _raw_montgomery.monty_multiply( + out, + term1_b, + term2_b, + modulus_b, + c_size_t(numbers_len), + ) + if error: + raise ValueError("monty_multiply failed with error: %d" % error) + + return get_raw_buffer(out) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerCustom.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerCustom.pyi index 2dd75c74..16a2bead 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerCustom.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerCustom.pyi @@ -5,4 +5,4 @@ from ._IntegerNative import IntegerNative _raw_montgomery = Any class IntegerCustom(IntegerNative): - pass + pass diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerGMP.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerGMP.py index be773722..b7a2423c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerGMP.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerGMP.py @@ -33,8 +33,13 @@ from Cryptodome.Util.py3compat import is_native_int -from Cryptodome.Util._raw_api import (backend, load_lib, - c_ulong, c_size_t, c_uint8_ptr) +from Cryptodome.Util._raw_api import ( + backend, + load_lib, + c_ulong, + c_size_t, + c_uint8_ptr, +) from ._IntegerBase import IntegerBase @@ -97,28 +102,27 @@ """ if sys.platform == "win32": - raise ImportError("Not using GMP on Windows") + raise ImportError("Not using GMP on Windows") lib = load_lib("gmp", gmp_defs) implementation = {"library": "gmp", "api": backend} if hasattr(lib, "__mpir_version"): - raise ImportError("MPIR library detected") + raise ImportError("MPIR library detected") # Lazy creation of GMP methods class _GMP(object): - - def __getattr__(self, name): - if name.startswith("mpz_"): - func_name = "__gmpz_" + name[4:] - elif name.startswith("gmp_"): - func_name = "__gmp_" + name[4:] - else: - raise AttributeError("Attribute %s is invalid" % name) - func = getattr(lib, func_name) - setattr(self, name, func) - return func + def __getattr__(self, name): + if name.startswith("mpz_"): + func_name = "__gmpz_" + name[4:] + elif name.startswith("gmp_"): + func_name = "__gmp_" + name[4:] + else: + raise AttributeError("Attribute %s is invalid" % name) + func = getattr(lib, func_name) + setattr(self, name, func) + return func _gmp = _GMP() @@ -128,24 +132,26 @@ def __getattr__(self, name): # a new MPZ structure, we need to break the abstraction # and know exactly what ffi backend we have if implementation["api"] == "ctypes": - from ctypes import Structure, c_int, c_void_p, byref + from ctypes import Structure, c_int, c_void_p, byref - class _MPZ(Structure): - _fields_ = [('_mp_alloc', c_int), - ('_mp_size', c_int), - ('_mp_d', c_void_p)] + class _MPZ(Structure): + _fields_ = [ + ("_mp_alloc", c_int), + ("_mp_size", c_int), + ("_mp_d", c_void_p), + ] - def new_mpz(): - return byref(_MPZ()) + def new_mpz(): + return byref(_MPZ()) - _gmp.mpz_getlimbn.restype = c_ulong + _gmp.mpz_getlimbn.restype = c_ulong else: - # We are using CFFI - from Cryptodome.Util._raw_api import ffi + # We are using CFFI + from Cryptodome.Util._raw_api import ffi - def new_mpz(): - return ffi.new("MPZ*") + def new_mpz(): + return ffi.new("MPZ*") # Size of a native word @@ -153,647 +159,730 @@ def new_mpz(): class IntegerGMP(IntegerBase): - """A fast, arbitrary precision integer""" - - _zero_mpz_p = new_mpz() - _gmp.mpz_init_set_ui(_zero_mpz_p, c_ulong(0)) - - def __init__(self, value): - """Initialize the integer to the given value.""" - - self._mpz_p = new_mpz() - self._initialized = False - - if isinstance(value, float): - raise ValueError("A floating point type is not a natural number") - - if is_native_int(value): - _gmp.mpz_init(self._mpz_p) - self._initialized = True - if value == 0: - return - - tmp = new_mpz() - _gmp.mpz_init(tmp) - - try: - positive = value >= 0 - reduce = abs(value) - slots = (reduce.bit_length() - 1) // 32 + 1 - - while slots > 0: - slots = slots - 1 - _gmp.mpz_set_ui(tmp, - c_ulong(0xFFFFFFFF & (reduce >> (slots * 32)))) - _gmp.mpz_mul_2exp(tmp, tmp, c_ulong(slots * 32)) - _gmp.mpz_add(self._mpz_p, self._mpz_p, tmp) - finally: - _gmp.mpz_clear(tmp) - - if not positive: - _gmp.mpz_neg(self._mpz_p, self._mpz_p) - - elif isinstance(value, IntegerGMP): - _gmp.mpz_init_set(self._mpz_p, value._mpz_p) - self._initialized = True - else: - raise NotImplementedError - - # Conversions - def __int__(self): - tmp = new_mpz() - _gmp.mpz_init_set(tmp, self._mpz_p) - - try: - value = 0 - slot = 0 - while _gmp.mpz_cmp(tmp, self._zero_mpz_p) != 0: - lsb = _gmp.mpz_get_ui(tmp) & 0xFFFFFFFF - value |= lsb << (slot * 32) - _gmp.mpz_tdiv_q_2exp(tmp, tmp, c_ulong(32)) - slot = slot + 1 - finally: - _gmp.mpz_clear(tmp) - - if self < 0: - value = -value - return int(value) - - def __str__(self): - return str(int(self)) - - def __repr__(self): - return "Integer(%s)" % str(self) - - # Only Python 2.x - def __hex__(self): - return hex(int(self)) - - # Only Python 3.x - def __index__(self): - return int(self) - - def to_bytes(self, block_size=0, byteorder='big'): - """Convert the number into a byte string. - - This method encodes the number in network order and prepends - as many zero bytes as required. It only works for non-negative - values. - - :Parameters: - block_size : integer - The exact size the output byte string must have. - If zero, the string has the minimal length. - byteorder : string - 'big' for big-endian integers (default), 'little' for litte-endian. - :Returns: - A byte string. - :Raise ValueError: - If the value is negative or if ``block_size`` is - provided and the length of the byte string would exceed it. - """ - - if self < 0: - raise ValueError("Conversion only valid for non-negative numbers") - - num_limbs = _gmp.mpz_size(self._mpz_p) - if _sys_bits == 32: - spchar = "L" - num_limbs = max(1, num_limbs, (block_size + 3) // 4) - elif _sys_bits == 64: - spchar = "Q" - num_limbs = max(1, num_limbs, (block_size + 7) // 8) - else: - raise ValueError("Unknown limb size") - - # mpz_getlimbn returns 0 if i is larger than the number of actual limbs - limbs = [_gmp.mpz_getlimbn(self._mpz_p, num_limbs - i - 1) for i in range(num_limbs)] - - result = struct.pack(">" + spchar * num_limbs, *limbs) - cutoff_len = len(result) - block_size - if block_size == 0: - result = result.lstrip(b'\x00') - elif cutoff_len > 0: - if result[:cutoff_len] != b'\x00' * (cutoff_len): - raise ValueError("Number is too big to convert to " - "byte string of prescribed length") - result = result[cutoff_len:] - elif cutoff_len < 0: - result = b'\x00' * (-cutoff_len) + result - - if byteorder == 'little': - result = result[::-1] - elif byteorder == 'big': - pass - else: - raise ValueError("Incorrect byteorder") - - if len(result) == 0: - result = b'\x00' - - return result - - @staticmethod - def from_bytes(byte_string, byteorder='big'): - """Convert a byte string into a number. - - :Parameters: - byte_string : byte string - The input number, encoded in network order. - It can only be non-negative. - byteorder : string - 'big' for big-endian integers (default), 'little' for litte-endian. - - :Return: - The ``Integer`` object carrying the same value as the input. - """ - result = IntegerGMP(0) - if byteorder == 'big': - pass - elif byteorder == 'little': - byte_string = bytearray(byte_string) - byte_string.reverse() - else: - raise ValueError("Incorrect byteorder") - _gmp.mpz_import( - result._mpz_p, - c_size_t(len(byte_string)), # Amount of words to read - 1, # Big endian - c_size_t(1), # Each word is 1 byte long - 0, # Endianess within a word - not relevant - c_size_t(0), # No nails - c_uint8_ptr(byte_string)) - return result - - # Relations - def _apply_and_return(self, func, term): - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - return func(self._mpz_p, term._mpz_p) - - def __eq__(self, term): - if not (isinstance(term, IntegerGMP) or is_native_int(term)): - return False - return self._apply_and_return(_gmp.mpz_cmp, term) == 0 - - def __ne__(self, term): - if not (isinstance(term, IntegerGMP) or is_native_int(term)): - return True - return self._apply_and_return(_gmp.mpz_cmp, term) != 0 - - def __lt__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) < 0 - - def __le__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) <= 0 - - def __gt__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) > 0 - - def __ge__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) >= 0 - - def __nonzero__(self): - return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) != 0 - __bool__ = __nonzero__ - - def is_negative(self): - return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) < 0 - - # Arithmetic operations - def __add__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - try: - term = IntegerGMP(term) - except NotImplementedError: - return NotImplemented - _gmp.mpz_add(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __sub__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - try: - term = IntegerGMP(term) - except NotImplementedError: - return NotImplemented - _gmp.mpz_sub(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __mul__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - try: - term = IntegerGMP(term) - except NotImplementedError: - return NotImplemented - _gmp.mpz_mul(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __floordiv__(self, divisor): - if not isinstance(divisor, IntegerGMP): - divisor = IntegerGMP(divisor) - if _gmp.mpz_cmp(divisor._mpz_p, - self._zero_mpz_p) == 0: - raise ZeroDivisionError("Division by zero") - result = IntegerGMP(0) - _gmp.mpz_fdiv_q(result._mpz_p, - self._mpz_p, - divisor._mpz_p) - return result - - def __mod__(self, divisor): - if not isinstance(divisor, IntegerGMP): - divisor = IntegerGMP(divisor) - comp = _gmp.mpz_cmp(divisor._mpz_p, - self._zero_mpz_p) - if comp == 0: - raise ZeroDivisionError("Division by zero") - if comp < 0: - raise ValueError("Modulus must be positive") - result = IntegerGMP(0) - _gmp.mpz_mod(result._mpz_p, - self._mpz_p, - divisor._mpz_p) - return result - - def inplace_pow(self, exponent, modulus=None): - - if modulus is None: - if exponent < 0: - raise ValueError("Exponent must not be negative") - - # Normal exponentiation - if exponent > 256: - raise ValueError("Exponent is too big") - _gmp.mpz_pow_ui(self._mpz_p, - self._mpz_p, # Base - c_ulong(int(exponent)) - ) - else: - # Modular exponentiation - if not isinstance(modulus, IntegerGMP): - modulus = IntegerGMP(modulus) - if not modulus: - raise ZeroDivisionError("Division by zero") - if modulus.is_negative(): - raise ValueError("Modulus must be positive") - if is_native_int(exponent): - if exponent < 0: - raise ValueError("Exponent must not be negative") - if exponent < 65536: - _gmp.mpz_powm_ui(self._mpz_p, - self._mpz_p, - c_ulong(exponent), - modulus._mpz_p) - return self - exponent = IntegerGMP(exponent) - elif exponent.is_negative(): - raise ValueError("Exponent must not be negative") - _gmp.mpz_powm(self._mpz_p, - self._mpz_p, - exponent._mpz_p, - modulus._mpz_p) - return self - - def __pow__(self, exponent, modulus=None): - result = IntegerGMP(self) - return result.inplace_pow(exponent, modulus) - - def __abs__(self): - result = IntegerGMP(0) - _gmp.mpz_abs(result._mpz_p, self._mpz_p) - return result - - def sqrt(self, modulus=None): - """Return the largest Integer that does not - exceed the square root""" - - if modulus is None: - if self < 0: - raise ValueError("Square root of negative value") - result = IntegerGMP(0) - _gmp.mpz_sqrt(result._mpz_p, - self._mpz_p) - else: - if modulus <= 0: - raise ValueError("Modulus must be positive") - modulus = int(modulus) - result = IntegerGMP(self._tonelli_shanks(int(self) % modulus, modulus)) - - return result - - def __iadd__(self, term): - if is_native_int(term): - if 0 <= term < 65536: - _gmp.mpz_add_ui(self._mpz_p, - self._mpz_p, - c_ulong(term)) - return self - if -65535 < term < 0: - _gmp.mpz_sub_ui(self._mpz_p, - self._mpz_p, - c_ulong(-term)) - return self - term = IntegerGMP(term) - _gmp.mpz_add(self._mpz_p, - self._mpz_p, - term._mpz_p) - return self - - def __isub__(self, term): - if is_native_int(term): - if 0 <= term < 65536: - _gmp.mpz_sub_ui(self._mpz_p, - self._mpz_p, - c_ulong(term)) - return self - if -65535 < term < 0: - _gmp.mpz_add_ui(self._mpz_p, - self._mpz_p, - c_ulong(-term)) - return self - term = IntegerGMP(term) - _gmp.mpz_sub(self._mpz_p, - self._mpz_p, - term._mpz_p) - return self - - def __imul__(self, term): - if is_native_int(term): - if 0 <= term < 65536: - _gmp.mpz_mul_ui(self._mpz_p, - self._mpz_p, - c_ulong(term)) - return self - if -65535 < term < 0: - _gmp.mpz_mul_ui(self._mpz_p, - self._mpz_p, - c_ulong(-term)) - _gmp.mpz_neg(self._mpz_p, self._mpz_p) - return self - term = IntegerGMP(term) - _gmp.mpz_mul(self._mpz_p, - self._mpz_p, - term._mpz_p) - return self - - def __imod__(self, divisor): - if not isinstance(divisor, IntegerGMP): - divisor = IntegerGMP(divisor) - comp = _gmp.mpz_cmp(divisor._mpz_p, - divisor._zero_mpz_p) - if comp == 0: - raise ZeroDivisionError("Division by zero") - if comp < 0: - raise ValueError("Modulus must be positive") - _gmp.mpz_mod(self._mpz_p, - self._mpz_p, - divisor._mpz_p) - return self - - # Boolean/bit operations - def __and__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - _gmp.mpz_and(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __or__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - _gmp.mpz_ior(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __rshift__(self, pos): - result = IntegerGMP(0) - if pos < 0: - raise ValueError("negative shift count") - if pos > 65536: - if self < 0: - return -1 - else: - return 0 - _gmp.mpz_tdiv_q_2exp(result._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return result - - def __irshift__(self, pos): - if pos < 0: - raise ValueError("negative shift count") - if pos > 65536: - if self < 0: - return -1 - else: - return 0 - _gmp.mpz_tdiv_q_2exp(self._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return self - - def __lshift__(self, pos): - result = IntegerGMP(0) - if not 0 <= pos < 65536: - raise ValueError("Incorrect shift count") - _gmp.mpz_mul_2exp(result._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return result - - def __ilshift__(self, pos): - if not 0 <= pos < 65536: - raise ValueError("Incorrect shift count") - _gmp.mpz_mul_2exp(self._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return self - - def get_bit(self, n): - """Return True if the n-th bit is set to 1. - Bit 0 is the least significant.""" - - if self < 0: - raise ValueError("no bit representation for negative values") - if n < 0: - raise ValueError("negative bit count") - if n > 65536: - return 0 - return bool(_gmp.mpz_tstbit(self._mpz_p, - c_ulong(int(n)))) - - # Extra - def is_odd(self): - return _gmp.mpz_tstbit(self._mpz_p, 0) == 1 - - def is_even(self): - return _gmp.mpz_tstbit(self._mpz_p, 0) == 0 - - def size_in_bits(self): - """Return the minimum number of bits that can encode the number.""" - - if self < 0: - raise ValueError("Conversion only valid for non-negative numbers") - return _gmp.mpz_sizeinbase(self._mpz_p, 2) - - def size_in_bytes(self): - """Return the minimum number of bytes that can encode the number.""" - return (self.size_in_bits() - 1) // 8 + 1 - - def is_perfect_square(self): - return _gmp.mpz_perfect_square_p(self._mpz_p) != 0 - - def fail_if_divisible_by(self, small_prime): - """Raise an exception if the small prime is a divisor.""" - - if is_native_int(small_prime): - if 0 < small_prime < 65536: - if _gmp.mpz_divisible_ui_p(self._mpz_p, - c_ulong(small_prime)): - raise ValueError("The value is composite") - return - small_prime = IntegerGMP(small_prime) - if _gmp.mpz_divisible_p(self._mpz_p, - small_prime._mpz_p): - raise ValueError("The value is composite") - - def multiply_accumulate(self, a, b): - """Increment the number by the product of a and b.""" - - if not isinstance(a, IntegerGMP): - a = IntegerGMP(a) - if is_native_int(b): - if 0 < b < 65536: - _gmp.mpz_addmul_ui(self._mpz_p, - a._mpz_p, - c_ulong(b)) - return self - if -65535 < b < 0: - _gmp.mpz_submul_ui(self._mpz_p, - a._mpz_p, - c_ulong(-b)) - return self - b = IntegerGMP(b) - _gmp.mpz_addmul(self._mpz_p, - a._mpz_p, - b._mpz_p) - return self - - def set(self, source): - """Set the Integer to have the given value""" - - if not isinstance(source, IntegerGMP): - source = IntegerGMP(source) - _gmp.mpz_set(self._mpz_p, - source._mpz_p) - return self - - def inplace_inverse(self, modulus): - """Compute the inverse of this number in the ring of - modulo integers. - - Raise an exception if no inverse exists. - """ - - if not isinstance(modulus, IntegerGMP): - modulus = IntegerGMP(modulus) - - comp = _gmp.mpz_cmp(modulus._mpz_p, - self._zero_mpz_p) - if comp == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if comp < 0: - raise ValueError("Modulus must be positive") - - result = _gmp.mpz_invert(self._mpz_p, - self._mpz_p, - modulus._mpz_p) - if not result: - raise ValueError("No inverse value can be computed") - return self - - def inverse(self, modulus): - result = IntegerGMP(self) - result.inplace_inverse(modulus) - return result - - def gcd(self, term): - """Compute the greatest common denominator between this - number and another term.""" - - result = IntegerGMP(0) - if is_native_int(term): - if 0 < term < 65535: - _gmp.mpz_gcd_ui(result._mpz_p, - self._mpz_p, - c_ulong(term)) - return result - term = IntegerGMP(term) - _gmp.mpz_gcd(result._mpz_p, self._mpz_p, term._mpz_p) - return result - - def lcm(self, term): - """Compute the least common multiplier between this - number and another term.""" - - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - _gmp.mpz_lcm(result._mpz_p, self._mpz_p, term._mpz_p) - return result - - @staticmethod - def jacobi_symbol(a, n): - """Compute the Jacobi symbol""" - - if not isinstance(a, IntegerGMP): - a = IntegerGMP(a) - if not isinstance(n, IntegerGMP): - n = IntegerGMP(n) - if n <= 0 or n.is_even(): - raise ValueError("n must be positive odd for the Jacobi symbol") - return _gmp.mpz_jacobi(a._mpz_p, n._mpz_p) - - @staticmethod - def _mult_modulo_bytes(term1, term2, modulus): - if not isinstance(term1, IntegerGMP): - term1 = IntegerGMP(term1) - if not isinstance(term2, IntegerGMP): - term2 = IntegerGMP(term2) - if not isinstance(modulus, IntegerGMP): - modulus = IntegerGMP(modulus) - - if modulus < 0: - raise ValueError("Modulus must be positive") - if modulus == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if (modulus & 1) == 0: - raise ValueError("Odd modulus is required") - - product = (term1 * term2) % modulus - return product.to_bytes(modulus.size_in_bytes()) - - # Clean-up - def __del__(self): - - try: - if self._mpz_p is not None: - if self._initialized: - _gmp.mpz_clear(self._mpz_p) - - self._mpz_p = None - except AttributeError: - pass + """A fast, arbitrary precision integer""" + + _zero_mpz_p = new_mpz() + _gmp.mpz_init_set_ui(_zero_mpz_p, c_ulong(0)) + + def __init__(self, value): + """Initialize the integer to the given value.""" + + self._mpz_p = new_mpz() + self._initialized = False + + if isinstance(value, float): + raise ValueError("A floating point type is not a natural number") + + if is_native_int(value): + _gmp.mpz_init(self._mpz_p) + self._initialized = True + if value == 0: + return + + tmp = new_mpz() + _gmp.mpz_init(tmp) + + try: + positive = value >= 0 + reduce = abs(value) + slots = (reduce.bit_length() - 1) // 32 + 1 + + while slots > 0: + slots = slots - 1 + _gmp.mpz_set_ui( + tmp, + c_ulong(0xFFFFFFFF & (reduce >> (slots * 32))), + ) + _gmp.mpz_mul_2exp(tmp, tmp, c_ulong(slots * 32)) + _gmp.mpz_add(self._mpz_p, self._mpz_p, tmp) + finally: + _gmp.mpz_clear(tmp) + + if not positive: + _gmp.mpz_neg(self._mpz_p, self._mpz_p) + + elif isinstance(value, IntegerGMP): + _gmp.mpz_init_set(self._mpz_p, value._mpz_p) + self._initialized = True + else: + raise NotImplementedError + + # Conversions + def __int__(self): + tmp = new_mpz() + _gmp.mpz_init_set(tmp, self._mpz_p) + + try: + value = 0 + slot = 0 + while _gmp.mpz_cmp(tmp, self._zero_mpz_p) != 0: + lsb = _gmp.mpz_get_ui(tmp) & 0xFFFFFFFF + value |= lsb << (slot * 32) + _gmp.mpz_tdiv_q_2exp(tmp, tmp, c_ulong(32)) + slot = slot + 1 + finally: + _gmp.mpz_clear(tmp) + + if self < 0: + value = -value + return int(value) + + def __str__(self): + return str(int(self)) + + def __repr__(self): + return "Integer(%s)" % str(self) + + # Only Python 2.x + def __hex__(self): + return hex(int(self)) + + # Only Python 3.x + def __index__(self): + return int(self) + + def to_bytes(self, block_size=0, byteorder="big"): + """Convert the number into a byte string. + + This method encodes the number in network order and prepends + as many zero bytes as required. It only works for non-negative + values. + + :Parameters: + block_size : integer + The exact size the output byte string must have. + If zero, the string has the minimal length. + byteorder : string + 'big' for big-endian integers (default), 'little' for litte-endian. + :Returns: + A byte string. + :Raise ValueError: + If the value is negative or if ``block_size`` is + provided and the length of the byte string would exceed it. + """ + + if self < 0: + raise ValueError("Conversion only valid for non-negative numbers") + + num_limbs = _gmp.mpz_size(self._mpz_p) + if _sys_bits == 32: + spchar = "L" + num_limbs = max(1, num_limbs, (block_size + 3) // 4) + elif _sys_bits == 64: + spchar = "Q" + num_limbs = max(1, num_limbs, (block_size + 7) // 8) + else: + raise ValueError("Unknown limb size") + + # mpz_getlimbn returns 0 if i is larger than the number of actual limbs + limbs = [_gmp.mpz_getlimbn(self._mpz_p, num_limbs - i - 1) for i in range(num_limbs)] + + result = struct.pack(">" + spchar * num_limbs, *limbs) + cutoff_len = len(result) - block_size + if block_size == 0: + result = result.lstrip(b"\x00") + elif cutoff_len > 0: + if result[:cutoff_len] != b"\x00" * (cutoff_len): + raise ValueError( + "Number is too big to convert to byte string of prescribed length", + ) + result = result[cutoff_len:] + elif cutoff_len < 0: + result = b"\x00" * (-cutoff_len) + result + + if byteorder == "little": + result = result[::-1] + elif byteorder == "big": + pass + else: + raise ValueError("Incorrect byteorder") + + if len(result) == 0: + result = b"\x00" + + return result + + @staticmethod + def from_bytes(byte_string, byteorder="big"): + """Convert a byte string into a number. + + :Parameters: + byte_string : byte string + The input number, encoded in network order. + It can only be non-negative. + byteorder : string + 'big' for big-endian integers (default), 'little' for litte-endian. + + :Return: + The ``Integer`` object carrying the same value as the input. + """ + result = IntegerGMP(0) + if byteorder == "big": + pass + elif byteorder == "little": + byte_string = bytearray(byte_string) + byte_string.reverse() + else: + raise ValueError("Incorrect byteorder") + _gmp.mpz_import( + result._mpz_p, + c_size_t(len(byte_string)), # Amount of words to read + 1, # Big endian + c_size_t(1), # Each word is 1 byte long + 0, # Endianess within a word - not relevant + c_size_t(0), # No nails + c_uint8_ptr(byte_string), + ) + return result + + # Relations + def _apply_and_return(self, func, term): + if not isinstance(term, IntegerGMP): + term = IntegerGMP(term) + return func(self._mpz_p, term._mpz_p) + + def __eq__(self, term): + if not (isinstance(term, IntegerGMP) or is_native_int(term)): + return False + return self._apply_and_return(_gmp.mpz_cmp, term) == 0 + + def __ne__(self, term): + if not (isinstance(term, IntegerGMP) or is_native_int(term)): + return True + return self._apply_and_return(_gmp.mpz_cmp, term) != 0 + + def __lt__(self, term): + return self._apply_and_return(_gmp.mpz_cmp, term) < 0 + + def __le__(self, term): + return self._apply_and_return(_gmp.mpz_cmp, term) <= 0 + + def __gt__(self, term): + return self._apply_and_return(_gmp.mpz_cmp, term) > 0 + + def __ge__(self, term): + return self._apply_and_return(_gmp.mpz_cmp, term) >= 0 + + def __nonzero__(self): + return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) != 0 + + __bool__ = __nonzero__ + + def is_negative(self): + return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) < 0 + + # Arithmetic operations + def __add__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + try: + term = IntegerGMP(term) + except NotImplementedError: + return NotImplemented + _gmp.mpz_add( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __sub__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + try: + term = IntegerGMP(term) + except NotImplementedError: + return NotImplemented + _gmp.mpz_sub( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __mul__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + try: + term = IntegerGMP(term) + except NotImplementedError: + return NotImplemented + _gmp.mpz_mul( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __floordiv__(self, divisor): + if not isinstance(divisor, IntegerGMP): + divisor = IntegerGMP(divisor) + if ( + _gmp.mpz_cmp( + divisor._mpz_p, + self._zero_mpz_p, + ) + == 0 + ): + raise ZeroDivisionError("Division by zero") + result = IntegerGMP(0) + _gmp.mpz_fdiv_q( + result._mpz_p, + self._mpz_p, + divisor._mpz_p, + ) + return result + + def __mod__(self, divisor): + if not isinstance(divisor, IntegerGMP): + divisor = IntegerGMP(divisor) + comp = _gmp.mpz_cmp( + divisor._mpz_p, + self._zero_mpz_p, + ) + if comp == 0: + raise ZeroDivisionError("Division by zero") + if comp < 0: + raise ValueError("Modulus must be positive") + result = IntegerGMP(0) + _gmp.mpz_mod( + result._mpz_p, + self._mpz_p, + divisor._mpz_p, + ) + return result + + def inplace_pow(self, exponent, modulus=None): + if modulus is None: + if exponent < 0: + raise ValueError("Exponent must not be negative") + + # Normal exponentiation + if exponent > 256: + raise ValueError("Exponent is too big") + _gmp.mpz_pow_ui( + self._mpz_p, + self._mpz_p, # Base + c_ulong(int(exponent)), + ) + else: + # Modular exponentiation + if not isinstance(modulus, IntegerGMP): + modulus = IntegerGMP(modulus) + if not modulus: + raise ZeroDivisionError("Division by zero") + if modulus.is_negative(): + raise ValueError("Modulus must be positive") + if is_native_int(exponent): + if exponent < 0: + raise ValueError("Exponent must not be negative") + if exponent < 65536: + _gmp.mpz_powm_ui( + self._mpz_p, + self._mpz_p, + c_ulong(exponent), + modulus._mpz_p, + ) + return self + exponent = IntegerGMP(exponent) + elif exponent.is_negative(): + raise ValueError("Exponent must not be negative") + _gmp.mpz_powm( + self._mpz_p, + self._mpz_p, + exponent._mpz_p, + modulus._mpz_p, + ) + return self + + def __pow__(self, exponent, modulus=None): + result = IntegerGMP(self) + return result.inplace_pow(exponent, modulus) + + def __abs__(self): + result = IntegerGMP(0) + _gmp.mpz_abs(result._mpz_p, self._mpz_p) + return result + + def sqrt(self, modulus=None): + """Return the largest Integer that does not + exceed the square root""" + + if modulus is None: + if self < 0: + raise ValueError("Square root of negative value") + result = IntegerGMP(0) + _gmp.mpz_sqrt( + result._mpz_p, + self._mpz_p, + ) + else: + if modulus <= 0: + raise ValueError("Modulus must be positive") + modulus = int(modulus) + result = IntegerGMP(self._tonelli_shanks(int(self) % modulus, modulus)) + + return result + + def __iadd__(self, term): + if is_native_int(term): + if 0 <= term < 65536: + _gmp.mpz_add_ui( + self._mpz_p, + self._mpz_p, + c_ulong(term), + ) + return self + if -65535 < term < 0: + _gmp.mpz_sub_ui( + self._mpz_p, + self._mpz_p, + c_ulong(-term), + ) + return self + term = IntegerGMP(term) + _gmp.mpz_add( + self._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return self + + def __isub__(self, term): + if is_native_int(term): + if 0 <= term < 65536: + _gmp.mpz_sub_ui( + self._mpz_p, + self._mpz_p, + c_ulong(term), + ) + return self + if -65535 < term < 0: + _gmp.mpz_add_ui( + self._mpz_p, + self._mpz_p, + c_ulong(-term), + ) + return self + term = IntegerGMP(term) + _gmp.mpz_sub( + self._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return self + + def __imul__(self, term): + if is_native_int(term): + if 0 <= term < 65536: + _gmp.mpz_mul_ui( + self._mpz_p, + self._mpz_p, + c_ulong(term), + ) + return self + if -65535 < term < 0: + _gmp.mpz_mul_ui( + self._mpz_p, + self._mpz_p, + c_ulong(-term), + ) + _gmp.mpz_neg(self._mpz_p, self._mpz_p) + return self + term = IntegerGMP(term) + _gmp.mpz_mul( + self._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return self + + def __imod__(self, divisor): + if not isinstance(divisor, IntegerGMP): + divisor = IntegerGMP(divisor) + comp = _gmp.mpz_cmp( + divisor._mpz_p, + divisor._zero_mpz_p, + ) + if comp == 0: + raise ZeroDivisionError("Division by zero") + if comp < 0: + raise ValueError("Modulus must be positive") + _gmp.mpz_mod( + self._mpz_p, + self._mpz_p, + divisor._mpz_p, + ) + return self + + # Boolean/bit operations + def __and__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + term = IntegerGMP(term) + _gmp.mpz_and( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __or__(self, term): + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + term = IntegerGMP(term) + _gmp.mpz_ior( + result._mpz_p, + self._mpz_p, + term._mpz_p, + ) + return result + + def __rshift__(self, pos): + result = IntegerGMP(0) + if pos < 0: + raise ValueError("negative shift count") + if pos > 65536: + if self < 0: + return -1 + else: + return 0 + _gmp.mpz_tdiv_q_2exp( + result._mpz_p, + self._mpz_p, + c_ulong(int(pos)), + ) + return result + + def __irshift__(self, pos): + if pos < 0: + raise ValueError("negative shift count") + if pos > 65536: + if self < 0: + return -1 + else: + return 0 + _gmp.mpz_tdiv_q_2exp( + self._mpz_p, + self._mpz_p, + c_ulong(int(pos)), + ) + return self + + def __lshift__(self, pos): + result = IntegerGMP(0) + if not 0 <= pos < 65536: + raise ValueError("Incorrect shift count") + _gmp.mpz_mul_2exp( + result._mpz_p, + self._mpz_p, + c_ulong(int(pos)), + ) + return result + + def __ilshift__(self, pos): + if not 0 <= pos < 65536: + raise ValueError("Incorrect shift count") + _gmp.mpz_mul_2exp( + self._mpz_p, + self._mpz_p, + c_ulong(int(pos)), + ) + return self + + def get_bit(self, n): + """Return True if the n-th bit is set to 1. + Bit 0 is the least significant.""" + + if self < 0: + raise ValueError("no bit representation for negative values") + if n < 0: + raise ValueError("negative bit count") + if n > 65536: + return 0 + return bool( + _gmp.mpz_tstbit( + self._mpz_p, + c_ulong(int(n)), + ), + ) + + # Extra + def is_odd(self): + return _gmp.mpz_tstbit(self._mpz_p, 0) == 1 + + def is_even(self): + return _gmp.mpz_tstbit(self._mpz_p, 0) == 0 + + def size_in_bits(self): + """Return the minimum number of bits that can encode the number.""" + + if self < 0: + raise ValueError("Conversion only valid for non-negative numbers") + return _gmp.mpz_sizeinbase(self._mpz_p, 2) + + def size_in_bytes(self): + """Return the minimum number of bytes that can encode the number.""" + return (self.size_in_bits() - 1) // 8 + 1 + + def is_perfect_square(self): + return _gmp.mpz_perfect_square_p(self._mpz_p) != 0 + + def fail_if_divisible_by(self, small_prime): + """Raise an exception if the small prime is a divisor.""" + + if is_native_int(small_prime): + if 0 < small_prime < 65536: + if _gmp.mpz_divisible_ui_p( + self._mpz_p, + c_ulong(small_prime), + ): + raise ValueError("The value is composite") + return + small_prime = IntegerGMP(small_prime) + if _gmp.mpz_divisible_p( + self._mpz_p, + small_prime._mpz_p, + ): + raise ValueError("The value is composite") + + def multiply_accumulate(self, a, b): + """Increment the number by the product of a and b.""" + + if not isinstance(a, IntegerGMP): + a = IntegerGMP(a) + if is_native_int(b): + if 0 < b < 65536: + _gmp.mpz_addmul_ui( + self._mpz_p, + a._mpz_p, + c_ulong(b), + ) + return self + if -65535 < b < 0: + _gmp.mpz_submul_ui( + self._mpz_p, + a._mpz_p, + c_ulong(-b), + ) + return self + b = IntegerGMP(b) + _gmp.mpz_addmul( + self._mpz_p, + a._mpz_p, + b._mpz_p, + ) + return self + + def set(self, source): + """Set the Integer to have the given value""" + + if not isinstance(source, IntegerGMP): + source = IntegerGMP(source) + _gmp.mpz_set( + self._mpz_p, + source._mpz_p, + ) + return self + + def inplace_inverse(self, modulus): + """Compute the inverse of this number in the ring of + modulo integers. + + Raise an exception if no inverse exists. + """ + + if not isinstance(modulus, IntegerGMP): + modulus = IntegerGMP(modulus) + + comp = _gmp.mpz_cmp( + modulus._mpz_p, + self._zero_mpz_p, + ) + if comp == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if comp < 0: + raise ValueError("Modulus must be positive") + + result = _gmp.mpz_invert( + self._mpz_p, + self._mpz_p, + modulus._mpz_p, + ) + if not result: + raise ValueError("No inverse value can be computed") + return self + + def inverse(self, modulus): + result = IntegerGMP(self) + result.inplace_inverse(modulus) + return result + + def gcd(self, term): + """Compute the greatest common denominator between this + number and another term.""" + + result = IntegerGMP(0) + if is_native_int(term): + if 0 < term < 65535: + _gmp.mpz_gcd_ui( + result._mpz_p, + self._mpz_p, + c_ulong(term), + ) + return result + term = IntegerGMP(term) + _gmp.mpz_gcd(result._mpz_p, self._mpz_p, term._mpz_p) + return result + + def lcm(self, term): + """Compute the least common multiplier between this + number and another term.""" + + result = IntegerGMP(0) + if not isinstance(term, IntegerGMP): + term = IntegerGMP(term) + _gmp.mpz_lcm(result._mpz_p, self._mpz_p, term._mpz_p) + return result + + @staticmethod + def jacobi_symbol(a, n): + """Compute the Jacobi symbol""" + + if not isinstance(a, IntegerGMP): + a = IntegerGMP(a) + if not isinstance(n, IntegerGMP): + n = IntegerGMP(n) + if n <= 0 or n.is_even(): + raise ValueError("n must be positive odd for the Jacobi symbol") + return _gmp.mpz_jacobi(a._mpz_p, n._mpz_p) + + @staticmethod + def _mult_modulo_bytes(term1, term2, modulus): + if not isinstance(term1, IntegerGMP): + term1 = IntegerGMP(term1) + if not isinstance(term2, IntegerGMP): + term2 = IntegerGMP(term2) + if not isinstance(modulus, IntegerGMP): + modulus = IntegerGMP(modulus) + + if modulus < 0: + raise ValueError("Modulus must be positive") + if modulus == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if (modulus & 1) == 0: + raise ValueError("Odd modulus is required") + + product = (term1 * term2) % modulus + return product.to_bytes(modulus.size_in_bytes()) + + # Clean-up + def __del__(self): + try: + if self._mpz_p is not None: + if self._initialized: + _gmp.mpz_clear(self._mpz_p) + + self._mpz_p = None + except AttributeError: + pass diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerGMP.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerGMP.pyi index 2181b470..9775fa59 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerGMP.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerGMP.pyi @@ -1,3 +1,4 @@ from ._IntegerBase import IntegerBase + class IntegerGMP(IntegerBase): - pass + pass diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerNative.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerNative.py index 5f768e26..bfaded4c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerNative.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerNative.py @@ -34,349 +34,348 @@ class IntegerNative(IntegerBase): - """A class to model a natural integer (including zero)""" - - def __init__(self, value): - if isinstance(value, float): - raise ValueError("A floating point type is not a natural number") - try: - self._value = value._value - except AttributeError: - self._value = value - - # Conversions - def __int__(self): - return self._value - - def __str__(self): - return str(int(self)) - - def __repr__(self): - return "Integer(%s)" % str(self) - - # Only Python 2.x - def __hex__(self): - return hex(self._value) - - # Only Python 3.x - def __index__(self): - return int(self._value) - - def to_bytes(self, block_size=0, byteorder='big'): - if self._value < 0: - raise ValueError("Conversion only valid for non-negative numbers") - result = long_to_bytes(self._value, block_size) - if len(result) > block_size > 0: - raise ValueError("Value too large to encode") - if byteorder == 'big': - pass - elif byteorder == 'little': - result = bytearray(result) - result.reverse() - result = bytes(result) - else: - raise ValueError("Incorrect byteorder") - return result - - @classmethod - def from_bytes(cls, byte_string, byteorder='big'): - if byteorder == 'big': - pass - elif byteorder == 'little': - byte_string = bytearray(byte_string) - byte_string.reverse() - else: - raise ValueError("Incorrect byteorder") - return cls(bytes_to_long(byte_string)) - - # Relations - def __eq__(self, term): - if term is None: - return False - return self._value == int(term) - - def __ne__(self, term): - return not self.__eq__(term) - - def __lt__(self, term): - return self._value < int(term) - - def __le__(self, term): - return self.__lt__(term) or self.__eq__(term) - - def __gt__(self, term): - return not self.__le__(term) - - def __ge__(self, term): - return not self.__lt__(term) - - def __nonzero__(self): - return self._value != 0 - __bool__ = __nonzero__ - - def is_negative(self): - return self._value < 0 - - # Arithmetic operations - def __add__(self, term): - try: - return self.__class__(self._value + int(term)) - except (ValueError, AttributeError, TypeError): - return NotImplemented - - def __sub__(self, term): - try: - return self.__class__(self._value - int(term)) - except (ValueError, AttributeError, TypeError): - return NotImplemented - - def __mul__(self, factor): - try: - return self.__class__(self._value * int(factor)) - except (ValueError, AttributeError, TypeError): - return NotImplemented - - def __floordiv__(self, divisor): - return self.__class__(self._value // int(divisor)) - - def __mod__(self, divisor): - divisor_value = int(divisor) - if divisor_value < 0: - raise ValueError("Modulus must be positive") - return self.__class__(self._value % divisor_value) - - def inplace_pow(self, exponent, modulus=None): - exp_value = int(exponent) - if exp_value < 0: - raise ValueError("Exponent must not be negative") - - if modulus is not None: - mod_value = int(modulus) - if mod_value < 0: - raise ValueError("Modulus must be positive") - if mod_value == 0: - raise ZeroDivisionError("Modulus cannot be zero") - else: - mod_value = None - self._value = pow(self._value, exp_value, mod_value) - return self - - def __pow__(self, exponent, modulus=None): - result = self.__class__(self) - return result.inplace_pow(exponent, modulus) - - def __abs__(self): - return abs(self._value) - - def sqrt(self, modulus=None): - - value = self._value - if modulus is None: - if value < 0: - raise ValueError("Square root of negative value") - # http://stackoverflow.com/questions/15390807/integer-square-root-in-python - - x = value - y = (x + 1) // 2 - while y < x: - x = y - y = (x + value // x) // 2 - result = x - else: - if modulus <= 0: - raise ValueError("Modulus must be positive") - result = self._tonelli_shanks(self % modulus, modulus) - - return self.__class__(result) - - def __iadd__(self, term): - self._value += int(term) - return self - - def __isub__(self, term): - self._value -= int(term) - return self - - def __imul__(self, term): - self._value *= int(term) - return self - - def __imod__(self, term): - modulus = int(term) - if modulus == 0: - raise ZeroDivisionError("Division by zero") - if modulus < 0: - raise ValueError("Modulus must be positive") - self._value %= modulus - return self - - # Boolean/bit operations - def __and__(self, term): - return self.__class__(self._value & int(term)) - - def __or__(self, term): - return self.__class__(self._value | int(term)) - - def __rshift__(self, pos): - try: - return self.__class__(self._value >> int(pos)) - except OverflowError: - if self._value >= 0: - return 0 - else: - return -1 - - def __irshift__(self, pos): - try: - self._value >>= int(pos) - except OverflowError: - if self._value >= 0: - return 0 - else: - return -1 - return self - - def __lshift__(self, pos): - try: - return self.__class__(self._value << int(pos)) - except OverflowError: - raise ValueError("Incorrect shift count") - - def __ilshift__(self, pos): - try: - self._value <<= int(pos) - except OverflowError: - raise ValueError("Incorrect shift count") - return self - - def get_bit(self, n): - if self._value < 0: - raise ValueError("no bit representation for negative values") - try: - try: - result = (self._value >> n._value) & 1 - if n._value < 0: - raise ValueError("negative bit count") - except AttributeError: - result = (self._value >> n) & 1 - if n < 0: - raise ValueError("negative bit count") - except OverflowError: - result = 0 - return result - - # Extra - def is_odd(self): - return (self._value & 1) == 1 - - def is_even(self): - return (self._value & 1) == 0 - - def size_in_bits(self): - - if self._value < 0: - raise ValueError("Conversion only valid for non-negative numbers") - - if self._value == 0: - return 1 - - return self._value.bit_length() - - def size_in_bytes(self): - return (self.size_in_bits() - 1) // 8 + 1 - - def is_perfect_square(self): - if self._value < 0: - return False - if self._value in (0, 1): - return True - - x = self._value // 2 - square_x = x ** 2 - - while square_x > self._value: - x = (square_x + self._value) // (2 * x) - square_x = x ** 2 - - return self._value == x ** 2 - - def fail_if_divisible_by(self, small_prime): - if (self._value % int(small_prime)) == 0: - raise ValueError("Value is composite") - - def multiply_accumulate(self, a, b): - self._value += int(a) * int(b) - return self - - def set(self, source): - self._value = int(source) - - def inplace_inverse(self, modulus): - self._value = inverse(self._value, int(modulus)) - return self - - def inverse(self, modulus): - result = self.__class__(self) - result.inplace_inverse(modulus) - return result - - def gcd(self, term): - return self.__class__(GCD(abs(self._value), abs(int(term)))) - - def lcm(self, term): - term = int(term) - if self._value == 0 or term == 0: - return self.__class__(0) - return self.__class__(abs((self._value * term) // self.gcd(term)._value)) - - @staticmethod - def jacobi_symbol(a, n): - a = int(a) - n = int(n) - - if n <= 0: - raise ValueError("n must be a positive integer") - - if (n & 1) == 0: - raise ValueError("n must be odd for the Jacobi symbol") - - # Step 1 - a = a % n - # Step 2 - if a == 1 or n == 1: - return 1 - # Step 3 - if a == 0: - return 0 - # Step 4 - e = 0 - a1 = a - while (a1 & 1) == 0: - a1 >>= 1 - e += 1 - # Step 5 - if (e & 1) == 0: - s = 1 - elif n % 8 in (1, 7): - s = 1 - else: - s = -1 - # Step 6 - if n % 4 == 3 and a1 % 4 == 3: - s = -s - # Step 7 - n1 = n % a1 - # Step 8 - return s * IntegerNative.jacobi_symbol(n1, a1) - - @staticmethod - def _mult_modulo_bytes(term1, term2, modulus): - if modulus < 0: - raise ValueError("Modulus must be positive") - if modulus == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if (modulus & 1) == 0: - raise ValueError("Odd modulus is required") - - number_len = len(long_to_bytes(modulus)) - return long_to_bytes((term1 * term2) % modulus, number_len) + """A class to model a natural integer (including zero)""" + + def __init__(self, value): + if isinstance(value, float): + raise ValueError("A floating point type is not a natural number") + try: + self._value = value._value + except AttributeError: + self._value = value + + # Conversions + def __int__(self): + return self._value + + def __str__(self): + return str(int(self)) + + def __repr__(self): + return "Integer(%s)" % str(self) + + # Only Python 2.x + def __hex__(self): + return hex(self._value) + + # Only Python 3.x + def __index__(self): + return int(self._value) + + def to_bytes(self, block_size=0, byteorder="big"): + if self._value < 0: + raise ValueError("Conversion only valid for non-negative numbers") + result = long_to_bytes(self._value, block_size) + if len(result) > block_size > 0: + raise ValueError("Value too large to encode") + if byteorder == "big": + pass + elif byteorder == "little": + result = bytearray(result) + result.reverse() + result = bytes(result) + else: + raise ValueError("Incorrect byteorder") + return result + + @classmethod + def from_bytes(cls, byte_string, byteorder="big"): + if byteorder == "big": + pass + elif byteorder == "little": + byte_string = bytearray(byte_string) + byte_string.reverse() + else: + raise ValueError("Incorrect byteorder") + return cls(bytes_to_long(byte_string)) + + # Relations + def __eq__(self, term): + if term is None: + return False + return self._value == int(term) + + def __ne__(self, term): + return not self.__eq__(term) + + def __lt__(self, term): + return self._value < int(term) + + def __le__(self, term): + return self.__lt__(term) or self.__eq__(term) + + def __gt__(self, term): + return not self.__le__(term) + + def __ge__(self, term): + return not self.__lt__(term) + + def __nonzero__(self): + return self._value != 0 + + __bool__ = __nonzero__ + + def is_negative(self): + return self._value < 0 + + # Arithmetic operations + def __add__(self, term): + try: + return self.__class__(self._value + int(term)) + except (ValueError, AttributeError, TypeError): + return NotImplemented + + def __sub__(self, term): + try: + return self.__class__(self._value - int(term)) + except (ValueError, AttributeError, TypeError): + return NotImplemented + + def __mul__(self, factor): + try: + return self.__class__(self._value * int(factor)) + except (ValueError, AttributeError, TypeError): + return NotImplemented + + def __floordiv__(self, divisor): + return self.__class__(self._value // int(divisor)) + + def __mod__(self, divisor): + divisor_value = int(divisor) + if divisor_value < 0: + raise ValueError("Modulus must be positive") + return self.__class__(self._value % divisor_value) + + def inplace_pow(self, exponent, modulus=None): + exp_value = int(exponent) + if exp_value < 0: + raise ValueError("Exponent must not be negative") + + if modulus is not None: + mod_value = int(modulus) + if mod_value < 0: + raise ValueError("Modulus must be positive") + if mod_value == 0: + raise ZeroDivisionError("Modulus cannot be zero") + else: + mod_value = None + self._value = pow(self._value, exp_value, mod_value) + return self + + def __pow__(self, exponent, modulus=None): + result = self.__class__(self) + return result.inplace_pow(exponent, modulus) + + def __abs__(self): + return abs(self._value) + + def sqrt(self, modulus=None): + value = self._value + if modulus is None: + if value < 0: + raise ValueError("Square root of negative value") + # http://stackoverflow.com/questions/15390807/integer-square-root-in-python + + x = value + y = (x + 1) // 2 + while y < x: + x = y + y = (x + value // x) // 2 + result = x + else: + if modulus <= 0: + raise ValueError("Modulus must be positive") + result = self._tonelli_shanks(self % modulus, modulus) + + return self.__class__(result) + + def __iadd__(self, term): + self._value += int(term) + return self + + def __isub__(self, term): + self._value -= int(term) + return self + + def __imul__(self, term): + self._value *= int(term) + return self + + def __imod__(self, term): + modulus = int(term) + if modulus == 0: + raise ZeroDivisionError("Division by zero") + if modulus < 0: + raise ValueError("Modulus must be positive") + self._value %= modulus + return self + + # Boolean/bit operations + def __and__(self, term): + return self.__class__(self._value & int(term)) + + def __or__(self, term): + return self.__class__(self._value | int(term)) + + def __rshift__(self, pos): + try: + return self.__class__(self._value >> int(pos)) + except OverflowError: + if self._value >= 0: + return 0 + else: + return -1 + + def __irshift__(self, pos): + try: + self._value >>= int(pos) + except OverflowError: + if self._value >= 0: + return 0 + else: + return -1 + return self + + def __lshift__(self, pos): + try: + return self.__class__(self._value << int(pos)) + except OverflowError: + raise ValueError("Incorrect shift count") + + def __ilshift__(self, pos): + try: + self._value <<= int(pos) + except OverflowError: + raise ValueError("Incorrect shift count") + return self + + def get_bit(self, n): + if self._value < 0: + raise ValueError("no bit representation for negative values") + try: + try: + result = (self._value >> n._value) & 1 + if n._value < 0: + raise ValueError("negative bit count") + except AttributeError: + result = (self._value >> n) & 1 + if n < 0: + raise ValueError("negative bit count") + except OverflowError: + result = 0 + return result + + # Extra + def is_odd(self): + return (self._value & 1) == 1 + + def is_even(self): + return (self._value & 1) == 0 + + def size_in_bits(self): + if self._value < 0: + raise ValueError("Conversion only valid for non-negative numbers") + + if self._value == 0: + return 1 + + return self._value.bit_length() + + def size_in_bytes(self): + return (self.size_in_bits() - 1) // 8 + 1 + + def is_perfect_square(self): + if self._value < 0: + return False + if self._value in (0, 1): + return True + + x = self._value // 2 + square_x = x**2 + + while square_x > self._value: + x = (square_x + self._value) // (2 * x) + square_x = x**2 + + return self._value == x**2 + + def fail_if_divisible_by(self, small_prime): + if (self._value % int(small_prime)) == 0: + raise ValueError("Value is composite") + + def multiply_accumulate(self, a, b): + self._value += int(a) * int(b) + return self + + def set(self, source): + self._value = int(source) + + def inplace_inverse(self, modulus): + self._value = inverse(self._value, int(modulus)) + return self + + def inverse(self, modulus): + result = self.__class__(self) + result.inplace_inverse(modulus) + return result + + def gcd(self, term): + return self.__class__(GCD(abs(self._value), abs(int(term)))) + + def lcm(self, term): + term = int(term) + if self._value == 0 or term == 0: + return self.__class__(0) + return self.__class__(abs((self._value * term) // self.gcd(term)._value)) + + @staticmethod + def jacobi_symbol(a, n): + a = int(a) + n = int(n) + + if n <= 0: + raise ValueError("n must be a positive integer") + + if (n & 1) == 0: + raise ValueError("n must be odd for the Jacobi symbol") + + # Step 1 + a = a % n + # Step 2 + if a == 1 or n == 1: + return 1 + # Step 3 + if a == 0: + return 0 + # Step 4 + e = 0 + a1 = a + while (a1 & 1) == 0: + a1 >>= 1 + e += 1 + # Step 5 + if (e & 1) == 0: + s = 1 + elif n % 8 in (1, 7): + s = 1 + else: + s = -1 + # Step 6 + if n % 4 == 3 and a1 % 4 == 3: + s = -s + # Step 7 + n1 = n % a1 + # Step 8 + return s * IntegerNative.jacobi_symbol(n1, a1) + + @staticmethod + def _mult_modulo_bytes(term1, term2, modulus): + if modulus < 0: + raise ValueError("Modulus must be positive") + if modulus == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if (modulus & 1) == 0: + raise ValueError("Odd modulus is required") + + number_len = len(long_to_bytes(modulus)) + return long_to_bytes((term1 * term2) % modulus, number_len) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerNative.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerNative.pyi index 3f65a39e..b8bbecb5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerNative.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Math/_IntegerNative.pyi @@ -1,3 +1,4 @@ from ._IntegerBase import IntegerBase + class IntegerNative(IntegerBase): - pass + pass diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/DH.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/DH.py index 41793c1f..b95d7b38 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/DH.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/DH.py @@ -1,192 +1,194 @@ from Cryptodome.Util.number import long_to_bytes -from Cryptodome.PublicKey.ECC import (EccKey, - construct, - _import_curve25519_public_key, - _import_curve448_public_key) +from Cryptodome.PublicKey.ECC import ( + EccKey, + construct, + _import_curve25519_public_key, + _import_curve448_public_key, +) def _compute_ecdh(key_priv, key_pub): - pointP = key_pub.pointQ * key_priv.d - if pointP.is_point_at_infinity(): - raise ValueError("Invalid ECDH point") + pointP = key_pub.pointQ * key_priv.d + if pointP.is_point_at_infinity(): + raise ValueError("Invalid ECDH point") - if key_priv.curve == "Curve25519": - z = bytearray(pointP.x.to_bytes(32, byteorder='little')) - elif key_priv.curve == "Curve448": - z = bytearray(pointP.x.to_bytes(56, byteorder='little')) - else: - # See Section 5.7.1.2 in NIST SP 800-56Ar3 - z = long_to_bytes(pointP.x, pointP.size_in_bytes()) - return z + if key_priv.curve == "Curve25519": + z = bytearray(pointP.x.to_bytes(32, byteorder="little")) + elif key_priv.curve == "Curve448": + z = bytearray(pointP.x.to_bytes(56, byteorder="little")) + else: + # See Section 5.7.1.2 in NIST SP 800-56Ar3 + z = long_to_bytes(pointP.x, pointP.size_in_bytes()) + return z def import_x25519_public_key(encoded): - """Create a new X25519 public key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC7748. + """Create a new X25519 public key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC7748. - Args: - encoded (bytes): - The x25519 public key to import. - It must be 32 bytes. + Args: + encoded (bytes): + The x25519 public key to import. + It must be 32 bytes. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - x = _import_curve25519_public_key(encoded) - return construct(curve='Curve25519', point_x=x) + x = _import_curve25519_public_key(encoded) + return construct(curve="Curve25519", point_x=x) def import_x25519_private_key(encoded): - """Create a new X25519 private key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC7748. + """Create a new X25519 private key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC7748. - Args: - encoded (bytes): - The X25519 private key to import. - It must be 32 bytes. + Args: + encoded (bytes): + The X25519 private key to import. + It must be 32 bytes. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - return construct(seed=encoded, curve="Curve25519") + return construct(seed=encoded, curve="Curve25519") def import_x448_public_key(encoded): - """Create a new X448 public key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC7748. + """Create a new X448 public key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC7748. - Args: - encoded (bytes): - The x448 public key to import. - It must be 56 bytes. + Args: + encoded (bytes): + The x448 public key to import. + It must be 56 bytes. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - x = _import_curve448_public_key(encoded) - return construct(curve='Curve448', point_x=x) + x = _import_curve448_public_key(encoded) + return construct(curve="Curve448", point_x=x) def import_x448_private_key(encoded): - """Create a new X448 private key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC7748. + """Create a new X448 private key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC7748. - Args: - encoded (bytes): - The X448 private key to import. - It must be 56 bytes. + Args: + encoded (bytes): + The X448 private key to import. + It must be 56 bytes. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - return construct(seed=encoded, curve="Curve448") + return construct(seed=encoded, curve="Curve448") def key_agreement(**kwargs): - """Perform a Diffie-Hellman key agreement. - - Keywords: - kdf (callable): - A key derivation function that accepts ``bytes`` as input and returns - ``bytes``. - static_priv (EccKey): - The local static private key. Optional. - static_pub (EccKey): - The static public key that belongs to the peer. Optional. - eph_priv (EccKey): - The local ephemeral private key, generated for this session. Optional. - eph_pub (EccKey): - The ephemeral public key, received from the peer for this session. Optional. - - At least two keys must be passed, of which one is a private key and one - a public key. - - Returns (bytes): - The derived secret key material. - """ - - static_priv = kwargs.get('static_priv', None) - static_pub = kwargs.get('static_pub', None) - eph_priv = kwargs.get('eph_priv', None) - eph_pub = kwargs.get('eph_pub', None) - kdf = kwargs.get('kdf', None) - - if kdf is None: - raise ValueError("'kdf' is mandatory") - - count_priv = 0 - count_pub = 0 - curve = None - - def check_curve(curve, key, name, private): - if not isinstance(key, EccKey): - raise TypeError("'%s' must be an ECC key" % name) - if private and not key.has_private(): - raise TypeError("'%s' must be a private ECC key" % name) - if curve is None: - curve = key.curve - elif curve != key.curve: - raise TypeError("'%s' is defined on an incompatible curve" % name) - return curve - - if static_priv is not None: - curve = check_curve(curve, static_priv, 'static_priv', True) - count_priv += 1 - - if static_pub is not None: - curve = check_curve(curve, static_pub, 'static_pub', False) - count_pub += 1 - - if eph_priv is not None: - curve = check_curve(curve, eph_priv, 'eph_priv', True) - count_priv += 1 - - if eph_pub is not None: - curve = check_curve(curve, eph_pub, 'eph_pub', False) - count_pub += 1 - - if (count_priv + count_pub) < 2 or count_priv == 0 or count_pub == 0: - raise ValueError("Too few keys for the ECDH key agreement") - - Zs = b'' - Ze = b'' - - if static_priv and static_pub: - # C(*, 2s) - Zs = _compute_ecdh(static_priv, static_pub) - - if eph_priv and eph_pub: - # C(2e, 0s) or C(2e, 2s) - if bool(static_priv) != bool(static_pub): - raise ValueError("DH mode C(2e, 1s) is not supported") - Ze = _compute_ecdh(eph_priv, eph_pub) - elif eph_priv and static_pub: - # C(1e, 2s) or C(1e, 1s) - Ze = _compute_ecdh(eph_priv, static_pub) - elif eph_pub and static_priv: - # C(1e, 2s) or C(1e, 1s) - Ze = _compute_ecdh(static_priv, eph_pub) - - Z = Ze + Zs - - return kdf(Z) + """Perform a Diffie-Hellman key agreement. + + Keywords: + kdf (callable): + A key derivation function that accepts ``bytes`` as input and returns + ``bytes``. + static_priv (EccKey): + The local static private key. Optional. + static_pub (EccKey): + The static public key that belongs to the peer. Optional. + eph_priv (EccKey): + The local ephemeral private key, generated for this session. Optional. + eph_pub (EccKey): + The ephemeral public key, received from the peer for this session. Optional. + + At least two keys must be passed, of which one is a private key and one + a public key. + + Returns (bytes): + The derived secret key material. + """ + + static_priv = kwargs.get("static_priv", None) + static_pub = kwargs.get("static_pub", None) + eph_priv = kwargs.get("eph_priv", None) + eph_pub = kwargs.get("eph_pub", None) + kdf = kwargs.get("kdf", None) + + if kdf is None: + raise ValueError("'kdf' is mandatory") + + count_priv = 0 + count_pub = 0 + curve = None + + def check_curve(curve, key, name, private): + if not isinstance(key, EccKey): + raise TypeError("'%s' must be an ECC key" % name) + if private and not key.has_private(): + raise TypeError("'%s' must be a private ECC key" % name) + if curve is None: + curve = key.curve + elif curve != key.curve: + raise TypeError("'%s' is defined on an incompatible curve" % name) + return curve + + if static_priv is not None: + curve = check_curve(curve, static_priv, "static_priv", True) + count_priv += 1 + + if static_pub is not None: + curve = check_curve(curve, static_pub, "static_pub", False) + count_pub += 1 + + if eph_priv is not None: + curve = check_curve(curve, eph_priv, "eph_priv", True) + count_priv += 1 + + if eph_pub is not None: + curve = check_curve(curve, eph_pub, "eph_pub", False) + count_pub += 1 + + if (count_priv + count_pub) < 2 or count_priv == 0 or count_pub == 0: + raise ValueError("Too few keys for the ECDH key agreement") + + Zs = b"" + Ze = b"" + + if static_priv and static_pub: + # C(*, 2s) + Zs = _compute_ecdh(static_priv, static_pub) + + if eph_priv and eph_pub: + # C(2e, 0s) or C(2e, 2s) + if bool(static_priv) != bool(static_pub): + raise ValueError("DH mode C(2e, 1s) is not supported") + Ze = _compute_ecdh(eph_priv, eph_pub) + elif eph_priv and static_pub: + # C(1e, 2s) or C(1e, 1s) + Ze = _compute_ecdh(eph_priv, static_pub) + elif eph_pub and static_priv: + # C(1e, 2s) or C(1e, 1s) + Ze = _compute_ecdh(static_priv, eph_pub) + + Z = Ze + Zs + + return kdf(Z) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/DH.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/DH.pyi index 017d8637..d495ccae 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/DH.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/DH.pyi @@ -3,14 +3,14 @@ from typing_extensions import Unpack, NotRequired from Cryptodome.PublicKey.ECC import EccKey -T = TypeVar('T') +T = TypeVar("T") class RequestParams(TypedDict, Generic[T]): - kdf: Callable[[bytes|bytearray|memoryview], T] - static_priv: NotRequired[EccKey] - static_pub: NotRequired[EccKey] - eph_priv: NotRequired[EccKey] - eph_pub: NotRequired[EccKey] + kdf: Callable[[bytes | bytearray | memoryview], T] + static_priv: NotRequired[EccKey] + static_pub: NotRequired[EccKey] + eph_priv: NotRequired[EccKey] + eph_pub: NotRequired[EccKey] def import_x25519_public_key(encoded: bytes) -> EccKey: ... def import_x25519_private_key(encoded: bytes) -> EccKey: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/HPKE.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/HPKE.py index 13823ec6..ed77f338 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/HPKE.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/HPKE.py @@ -14,470 +14,522 @@ class MODE(IntEnum): - """HPKE modes""" - BASE = 0x00 - PSK = 0x01 - AUTH = 0x02 - AUTH_PSK = 0x03 + """HPKE modes""" + + BASE = 0x00 + PSK = 0x01 + AUTH = 0x02 + AUTH_PSK = 0x03 class AEAD(IntEnum): - """Authenticated Encryption with Associated Data (AEAD) Functions""" - AES128_GCM = 0x0001 - AES256_GCM = 0x0002 - CHACHA20_POLY1305 = 0x0003 + """Authenticated Encryption with Associated Data (AEAD) Functions""" + + AES128_GCM = 0x0001 + AES256_GCM = 0x0002 + CHACHA20_POLY1305 = 0x0003 class DeserializeError(ValueError): - pass + pass + class MessageLimitReachedError(ValueError): - pass + pass + # CURVE to (KEM ID, KDF ID, HASH) _Curve_Config = { - "NIST P-256": (0x0010, 0x0001, SHA256), - "NIST P-384": (0x0011, 0x0002, SHA384), - "NIST P-521": (0x0012, 0x0003, SHA512), - "Curve25519": (0x0020, 0x0001, SHA256), - "Curve448": (0x0021, 0x0003, SHA512), + "NIST P-256": (0x0010, 0x0001, SHA256), + "NIST P-384": (0x0011, 0x0002, SHA384), + "NIST P-521": (0x0012, 0x0003, SHA512), + "Curve25519": (0x0020, 0x0001, SHA256), + "Curve448": (0x0021, 0x0003, SHA512), } -def _labeled_extract(salt: bytes, - label: bytes, - ikm: bytes, - suite_id: bytes, - hashmod: ModuleType): - labeled_ikm = b"HPKE-v1" + suite_id + label + ikm - return _HKDF_extract(salt, labeled_ikm, hashmod) - - -def _labeled_expand(prk: bytes, - label: bytes, - info: bytes, - L: int, - suite_id: bytes, - hashmod: ModuleType): - labeled_info = struct.pack('>H', L) + b"HPKE-v1" + suite_id + \ - label + info - return _HKDF_expand(prk, labeled_info, L, hashmod) - - -def _extract_and_expand(dh: bytes, - kem_context: bytes, - suite_id: bytes, - hashmod: ModuleType): - Nsecret = hashmod.digest_size - - eae_prk = _labeled_extract(b"", - b"eae_prk", - dh, - suite_id, - hashmod) - - shared_secret = _labeled_expand(eae_prk, - b"shared_secret", - kem_context, - Nsecret, - suite_id, - hashmod) - return shared_secret +def _labeled_extract( + salt: bytes, + label: bytes, + ikm: bytes, + suite_id: bytes, + hashmod: ModuleType, +): + labeled_ikm = b"HPKE-v1" + suite_id + label + ikm + return _HKDF_extract(salt, labeled_ikm, hashmod) + + +def _labeled_expand( + prk: bytes, + label: bytes, + info: bytes, + L: int, + suite_id: bytes, + hashmod: ModuleType, +): + labeled_info = struct.pack(">H", L) + b"HPKE-v1" + suite_id + label + info + return _HKDF_expand(prk, labeled_info, L, hashmod) + + +def _extract_and_expand( + dh: bytes, + kem_context: bytes, + suite_id: bytes, + hashmod: ModuleType, +): + Nsecret = hashmod.digest_size + + eae_prk = _labeled_extract( + b"", + b"eae_prk", + dh, + suite_id, + hashmod, + ) + + shared_secret = _labeled_expand( + eae_prk, + b"shared_secret", + kem_context, + Nsecret, + suite_id, + hashmod, + ) + return shared_secret class HPKE_Cipher: - - def __init__(self, - receiver_key: EccKey, - enc: Optional[bytes], - sender_key: Optional[EccKey], - psk_pair: tuple[bytes, bytes], - info: bytes, - aead_id: AEAD, - mode: MODE): - - self.enc: bytes = b'' if enc is None else enc - """The encapsulated session key.""" - - self._verify_psk_inputs(mode, psk_pair) - - self._curve = receiver_key.curve - self._aead_id = aead_id - self._mode = mode - - try: - self._kem_id, \ - self._kdf_id, \ - self._hashmod = _Curve_Config[self._curve] - except KeyError as ke: - raise ValueError("Curve {} is not supported by HPKE".format(self._curve)) from ke - - self._Nk = 16 if self._aead_id == AEAD.AES128_GCM else 32 - self._Nn = 12 - self._Nt = 16 - self._Nh = self._hashmod.digest_size - - self._encrypt = not receiver_key.has_private() - - if self._encrypt: - # SetupBaseS (encryption) - if enc is not None: - raise ValueError("Parameter 'enc' cannot be an input when sealing") - shared_secret, self.enc = self._encap(receiver_key, - self._kem_id, - self._hashmod, - sender_key) - else: - # SetupBaseR (decryption) - if enc is None: - raise ValueError("Parameter 'enc' required when unsealing") - shared_secret = self._decap(enc, - receiver_key, - self._kem_id, - self._hashmod, - sender_key) - - self._sequence = 0 - self._max_sequence = (1 << (8 * self._Nn)) - 1 - - self._key, \ - self._base_nonce, \ - self._export_secret = self._key_schedule(shared_secret, - info, - *psk_pair) - - @staticmethod - def _encap(receiver_key: EccKey, - kem_id: int, - hashmod: ModuleType, - sender_key: Optional[EccKey] = None, - eph_key: Optional[EccKey] = None): - - assert (sender_key is None) or sender_key.has_private() - assert (eph_key is None) or eph_key.has_private() - - if eph_key is None: - eph_key = ECC.generate(curve=receiver_key.curve) - enc = eph_key.public_key().export_key(format='raw') - - pkRm = receiver_key.public_key().export_key(format='raw') - kem_context = enc + pkRm - extra_param = {} - if sender_key: - kem_context += sender_key.public_key().export_key(format='raw') - extra_param = {'static_priv': sender_key} - - suite_id = b"KEM" + struct.pack('>H', kem_id) - - def kdf(dh, - kem_context=kem_context, - suite_id=suite_id, - hashmod=hashmod): - return _extract_and_expand(dh, kem_context, suite_id, hashmod) - - shared_secret = key_agreement(eph_priv=eph_key, - static_pub=receiver_key, - kdf=kdf, - **extra_param) - return shared_secret, enc - - @staticmethod - def _decap(enc: bytes, - receiver_key: EccKey, - kem_id: int, - hashmod: ModuleType, - sender_key: Optional[EccKey] = None): - - assert receiver_key.has_private() - - try: - if receiver_key.curve == 'Curve25519': - pkE = import_x25519_public_key(enc) - elif receiver_key.curve == 'Curve448': - pkE = import_x448_public_key(enc) - else: - pkE = ECC.import_key(enc, curve_name=receiver_key.curve) - except ValueError as ve: - raise DeserializeError("'enc' is not a valid encapsulated HPKE key") from ve - - pkRm = receiver_key.public_key().export_key(format='raw') - kem_context = enc + pkRm - extra_param = {} - if sender_key: - kem_context += sender_key.public_key().export_key(format='raw') - extra_param = {'static_pub': sender_key} - - suite_id = b"KEM" + struct.pack('>H', kem_id) - - def kdf(dh, - kem_context=kem_context, - suite_id=suite_id, - hashmod=hashmod): - return _extract_and_expand(dh, kem_context, suite_id, hashmod) - - shared_secret = key_agreement(eph_pub=pkE, - static_priv=receiver_key, - kdf=kdf, - **extra_param) - return shared_secret - - @staticmethod - def _verify_psk_inputs(mode: MODE, psk_pair: tuple[bytes, bytes]): - psk_id, psk = psk_pair - - if (psk == b'') ^ (psk_id == b''): - raise ValueError("Inconsistent PSK inputs") - - if (psk == b''): - if mode in (MODE.PSK, MODE.AUTH_PSK): - raise ValueError(f"PSK is required with mode {mode.name}") - else: - if len(psk) < 32: - raise ValueError("PSK must be at least 32 byte long") - if mode in (MODE.BASE, MODE.AUTH): - raise ValueError("PSK is not compatible with this mode") - - def _key_schedule(self, - shared_secret: bytes, - info: bytes, - psk_id: bytes, - psk: bytes): - - suite_id = b"HPKE" + struct.pack('>HHH', - self._kem_id, - self._kdf_id, - self._aead_id) - - psk_id_hash = _labeled_extract(b'', - b'psk_id_hash', - psk_id, - suite_id, - self._hashmod) - - info_hash = _labeled_extract(b'', - b'info_hash', - info, - suite_id, - self._hashmod) - - key_schedule_context = self._mode.to_bytes(1, 'big') + psk_id_hash + info_hash - - secret = _labeled_extract(shared_secret, - b'secret', - psk, - suite_id, - self._hashmod) - - key = _labeled_expand(secret, - b'key', - key_schedule_context, - self._Nk, - suite_id, - self._hashmod) - - base_nonce = _labeled_expand(secret, - b'base_nonce', - key_schedule_context, - self._Nn, - suite_id, - self._hashmod) - - exporter_secret = _labeled_expand(secret, - b'exp', - key_schedule_context, - self._Nh, - suite_id, - self._hashmod) - - return key, base_nonce, exporter_secret - - def _new_cipher(self): - nonce = strxor(self._base_nonce, self._sequence.to_bytes(self._Nn, 'big')) - if self._aead_id in (AEAD.AES128_GCM, AEAD.AES256_GCM): - cipher = AES.new(self._key, AES.MODE_GCM, nonce=nonce, mac_len=self._Nt) - elif self._aead_id == AEAD.CHACHA20_POLY1305: - cipher = ChaCha20_Poly1305.new(key=self._key, nonce=nonce) - else: - raise ValueError(f"Unknown AEAD cipher ID {self._aead_id:#x}") - if self._sequence >= self._max_sequence: - raise MessageLimitReachedError() - self._sequence += 1 - return cipher - - def seal(self, plaintext: bytes, auth_data: Optional[bytes] = None): - """Encrypt and authenticate a message. - - This method can be invoked multiple times - to seal an ordered sequence of messages. - - Arguments: - plaintext: bytes - The message to seal. - auth_data: bytes - Optional. Additional Authenticated data (AAD) that is not encrypted - but that will be also covered by the authentication tag. - - Returns: - The ciphertext concatenated with the authentication tag. - """ - - if not self._encrypt: - raise ValueError("This cipher can only be used to seal") - cipher = self._new_cipher() - if auth_data: - cipher.update(auth_data) - ct, tag = cipher.encrypt_and_digest(plaintext) - return ct + tag - - def unseal(self, ciphertext: bytes, auth_data: Optional[bytes] = None): - """Decrypt a message and validate its authenticity. - - This method can be invoked multiple times - to unseal an ordered sequence of messages. - - Arguments: - cipertext: bytes - The message to unseal. - auth_data: bytes - Optional. Additional Authenticated data (AAD) that - was also covered by the authentication tag. - - Returns: - The original plaintext. - - Raises: ValueError - If the ciphertext (in combination with the AAD) is not valid. - - But if it is the first time you call ``unseal()`` this - exception may also mean that any of the parameters or keys - used to establish the session is wrong or that one is missing. - """ - - if self._encrypt: - raise ValueError("This cipher can only be used to unseal") - if len(ciphertext) < self._Nt: - raise ValueError("Ciphertext is too small") - cipher = self._new_cipher() - if auth_data: - cipher.update(auth_data) - - try: - pt = cipher.decrypt_and_verify(ciphertext[:-self._Nt], - ciphertext[-self._Nt:]) - except ValueError: - if self._sequence == 1: - raise ValueError("Incorrect HPKE keys/parameters or invalid message (wrong MAC tag)") - raise ValueError("Invalid message (wrong MAC tag)") - return pt - - -def new(*, receiver_key: EccKey, - aead_id: AEAD, - enc: Optional[bytes] = None, - sender_key: Optional[EccKey] = None, - psk: Optional[tuple[bytes, bytes]] = None, - info: Optional[bytes] = None) -> HPKE_Cipher: - """Create an HPKE context which can be used: - - - by the sender to seal (encrypt) a message or - - by the receiver to unseal (decrypt) it. - - As a minimum, the two parties agree on the receiver's asymmetric key - (of which the sender will only know the public half). - - Additionally, for authentication purposes, they may also agree on: - - * the sender's asymmetric key (of which the receiver will only know the public half) - - * a shared secret (e.g., a symmetric key derived from a password) - - Args: - receiver_key: - The ECC key of the receiver. - It must be on one of the following curves: ``NIST P-256``, - ``NIST P-384``, ``NIST P-521``, ``X25519`` or ``X448``. - - If this is a **public** key, the HPKE context can only be used to - **seal** (**encrypt**). - - If this is a **private** key, the HPKE context can only be used to - **unseal** (**decrypt**). - - aead_id: - The HPKE identifier of the symmetric cipher. - The possible values are: - - * ``HPKE.AEAD.AES128_GCM`` - * ``HPKE.AEAD.AES256_GCM`` - * ``HPKE.AEAD.CHACHA20_POLY1305`` - - enc: - The encapsulated session key (i.e., the KEM shared secret). - - The receiver must always specify this parameter. - - The sender must always omit this parameter. - - sender_key: - The ECC key of the sender. - It must be on the same curve as the ``receiver_key``. - If the ``receiver_key`` is a public key, ``sender_key`` must be a - private key, and vice versa. - - psk: - A Pre-Shared Key (PSK) as a 2-tuple of non-empty - byte strings: the identifier and the actual secret value. - Sender and receiver must use the same PSK (or none). - - The secret value must be at least 32 bytes long, - but it must not be a low-entropy password - (use a KDF like PBKDF2 or scrypt to derive a secret - from a password). - - info: - A non-secret parameter that contributes - to the generation of all session keys. - Sender and receive must use the same **info** parameter (or none). - - Returns: - An object that can be used for - sealing (if ``receiver_key`` is a public key) or - unsealing (if ``receiver_key`` is a private key). - In the latter case, - correctness of all the keys and parameters will only - be assessed with the first call to ``unseal()``. - """ - - if aead_id not in AEAD: - raise ValueError(f"Unknown AEAD cipher ID {aead_id:#x}") - - curve = receiver_key.curve - if curve not in ('NIST P-256', 'NIST P-384', 'NIST P-521', - 'Curve25519', 'Curve448'): - raise ValueError(f"Unsupported curve {curve}") - - if sender_key: - count_private_keys = int(receiver_key.has_private()) + \ - int(sender_key.has_private()) - if count_private_keys != 1: - raise ValueError("Exactly 1 private key required") - if sender_key.curve != curve: - raise ValueError("Sender key uses {} but recipient key {}". - format(sender_key.curve, curve)) - mode = MODE.AUTH if psk is None else MODE.AUTH_PSK - else: - mode = MODE.BASE if psk is None else MODE.PSK - - if psk is None: - psk = b'', b'' - - if info is None: - info = b'' - - return HPKE_Cipher(receiver_key, - enc, - sender_key, - psk, - info, - aead_id, - mode) + def __init__( + self, + receiver_key: EccKey, + enc: Optional[bytes], + sender_key: Optional[EccKey], + psk_pair: tuple[bytes, bytes], + info: bytes, + aead_id: AEAD, + mode: MODE, + ): + self.enc: bytes = b"" if enc is None else enc + """The encapsulated session key.""" + + self._verify_psk_inputs(mode, psk_pair) + + self._curve = receiver_key.curve + self._aead_id = aead_id + self._mode = mode + + try: + self._kem_id, self._kdf_id, self._hashmod = _Curve_Config[self._curve] + except KeyError as ke: + raise ValueError("Curve {} is not supported by HPKE".format(self._curve)) from ke + + self._Nk = 16 if self._aead_id == AEAD.AES128_GCM else 32 + self._Nn = 12 + self._Nt = 16 + self._Nh = self._hashmod.digest_size + + self._encrypt = not receiver_key.has_private() + + if self._encrypt: + # SetupBaseS (encryption) + if enc is not None: + raise ValueError("Parameter 'enc' cannot be an input when sealing") + shared_secret, self.enc = self._encap( + receiver_key, + self._kem_id, + self._hashmod, + sender_key, + ) + else: + # SetupBaseR (decryption) + if enc is None: + raise ValueError("Parameter 'enc' required when unsealing") + shared_secret = self._decap( + enc, + receiver_key, + self._kem_id, + self._hashmod, + sender_key, + ) + + self._sequence = 0 + self._max_sequence = (1 << (8 * self._Nn)) - 1 + + self._key, self._base_nonce, self._export_secret = self._key_schedule( + shared_secret, + info, + *psk_pair, + ) + + @staticmethod + def _encap( + receiver_key: EccKey, + kem_id: int, + hashmod: ModuleType, + sender_key: Optional[EccKey] = None, + eph_key: Optional[EccKey] = None, + ): + assert (sender_key is None) or sender_key.has_private() + assert (eph_key is None) or eph_key.has_private() + + if eph_key is None: + eph_key = ECC.generate(curve=receiver_key.curve) + enc = eph_key.public_key().export_key(format="raw") + + pkRm = receiver_key.public_key().export_key(format="raw") + kem_context = enc + pkRm + extra_param = {} + if sender_key: + kem_context += sender_key.public_key().export_key(format="raw") + extra_param = {"static_priv": sender_key} + + suite_id = b"KEM" + struct.pack(">H", kem_id) + + def kdf( + dh, + kem_context=kem_context, + suite_id=suite_id, + hashmod=hashmod, + ): + return _extract_and_expand(dh, kem_context, suite_id, hashmod) + + shared_secret = key_agreement( + eph_priv=eph_key, + static_pub=receiver_key, + kdf=kdf, + **extra_param, + ) + return shared_secret, enc + + @staticmethod + def _decap( + enc: bytes, + receiver_key: EccKey, + kem_id: int, + hashmod: ModuleType, + sender_key: Optional[EccKey] = None, + ): + assert receiver_key.has_private() + + try: + if receiver_key.curve == "Curve25519": + pkE = import_x25519_public_key(enc) + elif receiver_key.curve == "Curve448": + pkE = import_x448_public_key(enc) + else: + pkE = ECC.import_key(enc, curve_name=receiver_key.curve) + except ValueError as ve: + raise DeserializeError("'enc' is not a valid encapsulated HPKE key") from ve + + pkRm = receiver_key.public_key().export_key(format="raw") + kem_context = enc + pkRm + extra_param = {} + if sender_key: + kem_context += sender_key.public_key().export_key(format="raw") + extra_param = {"static_pub": sender_key} + + suite_id = b"KEM" + struct.pack(">H", kem_id) + + def kdf( + dh, + kem_context=kem_context, + suite_id=suite_id, + hashmod=hashmod, + ): + return _extract_and_expand(dh, kem_context, suite_id, hashmod) + + shared_secret = key_agreement( + eph_pub=pkE, + static_priv=receiver_key, + kdf=kdf, + **extra_param, + ) + return shared_secret + + @staticmethod + def _verify_psk_inputs(mode: MODE, psk_pair: tuple[bytes, bytes]): + psk_id, psk = psk_pair + + if (psk == b"") ^ (psk_id == b""): + raise ValueError("Inconsistent PSK inputs") + + if psk == b"": + if mode in (MODE.PSK, MODE.AUTH_PSK): + raise ValueError(f"PSK is required with mode {mode.name}") + else: + if len(psk) < 32: + raise ValueError("PSK must be at least 32 byte long") + if mode in (MODE.BASE, MODE.AUTH): + raise ValueError("PSK is not compatible with this mode") + + def _key_schedule( + self, + shared_secret: bytes, + info: bytes, + psk_id: bytes, + psk: bytes, + ): + suite_id = b"HPKE" + struct.pack( + ">HHH", + self._kem_id, + self._kdf_id, + self._aead_id, + ) + + psk_id_hash = _labeled_extract( + b"", + b"psk_id_hash", + psk_id, + suite_id, + self._hashmod, + ) + + info_hash = _labeled_extract( + b"", + b"info_hash", + info, + suite_id, + self._hashmod, + ) + + key_schedule_context = self._mode.to_bytes(1, "big") + psk_id_hash + info_hash + + secret = _labeled_extract( + shared_secret, + b"secret", + psk, + suite_id, + self._hashmod, + ) + + key = _labeled_expand( + secret, + b"key", + key_schedule_context, + self._Nk, + suite_id, + self._hashmod, + ) + + base_nonce = _labeled_expand( + secret, + b"base_nonce", + key_schedule_context, + self._Nn, + suite_id, + self._hashmod, + ) + + exporter_secret = _labeled_expand( + secret, + b"exp", + key_schedule_context, + self._Nh, + suite_id, + self._hashmod, + ) + + return key, base_nonce, exporter_secret + + def _new_cipher(self): + nonce = strxor(self._base_nonce, self._sequence.to_bytes(self._Nn, "big")) + if self._aead_id in (AEAD.AES128_GCM, AEAD.AES256_GCM): + cipher = AES.new(self._key, AES.MODE_GCM, nonce=nonce, mac_len=self._Nt) + elif self._aead_id == AEAD.CHACHA20_POLY1305: + cipher = ChaCha20_Poly1305.new(key=self._key, nonce=nonce) + else: + raise ValueError(f"Unknown AEAD cipher ID {self._aead_id:#x}") + if self._sequence >= self._max_sequence: + raise MessageLimitReachedError() + self._sequence += 1 + return cipher + + def seal(self, plaintext: bytes, auth_data: Optional[bytes] = None): + """Encrypt and authenticate a message. + + This method can be invoked multiple times + to seal an ordered sequence of messages. + + Arguments: + plaintext: bytes + The message to seal. + auth_data: bytes + Optional. Additional Authenticated data (AAD) that is not encrypted + but that will be also covered by the authentication tag. + + Returns: + The ciphertext concatenated with the authentication tag. + """ + + if not self._encrypt: + raise ValueError("This cipher can only be used to seal") + cipher = self._new_cipher() + if auth_data: + cipher.update(auth_data) + ct, tag = cipher.encrypt_and_digest(plaintext) + return ct + tag + + def unseal(self, ciphertext: bytes, auth_data: Optional[bytes] = None): + """Decrypt a message and validate its authenticity. + + This method can be invoked multiple times + to unseal an ordered sequence of messages. + + Arguments: + cipertext: bytes + The message to unseal. + auth_data: bytes + Optional. Additional Authenticated data (AAD) that + was also covered by the authentication tag. + + Returns: + The original plaintext. + + Raises: ValueError + If the ciphertext (in combination with the AAD) is not valid. + + But if it is the first time you call ``unseal()`` this + exception may also mean that any of the parameters or keys + used to establish the session is wrong or that one is missing. + """ + + if self._encrypt: + raise ValueError("This cipher can only be used to unseal") + if len(ciphertext) < self._Nt: + raise ValueError("Ciphertext is too small") + cipher = self._new_cipher() + if auth_data: + cipher.update(auth_data) + + try: + pt = cipher.decrypt_and_verify( + ciphertext[: -self._Nt], + ciphertext[-self._Nt :], + ) + except ValueError: + if self._sequence == 1: + raise ValueError("Incorrect HPKE keys/parameters or invalid message (wrong MAC tag)") + raise ValueError("Invalid message (wrong MAC tag)") + return pt + + +def new( + *, + receiver_key: EccKey, + aead_id: AEAD, + enc: Optional[bytes] = None, + sender_key: Optional[EccKey] = None, + psk: Optional[tuple[bytes, bytes]] = None, + info: Optional[bytes] = None, +) -> HPKE_Cipher: + """Create an HPKE context which can be used: + + - by the sender to seal (encrypt) a message or + - by the receiver to unseal (decrypt) it. + + As a minimum, the two parties agree on the receiver's asymmetric key + (of which the sender will only know the public half). + + Additionally, for authentication purposes, they may also agree on: + + * the sender's asymmetric key (of which the receiver will only know the public half) + + * a shared secret (e.g., a symmetric key derived from a password) + + Args: + receiver_key: + The ECC key of the receiver. + It must be on one of the following curves: ``NIST P-256``, + ``NIST P-384``, ``NIST P-521``, ``X25519`` or ``X448``. + + If this is a **public** key, the HPKE context can only be used to + **seal** (**encrypt**). + + If this is a **private** key, the HPKE context can only be used to + **unseal** (**decrypt**). + + aead_id: + The HPKE identifier of the symmetric cipher. + The possible values are: + + * ``HPKE.AEAD.AES128_GCM`` + * ``HPKE.AEAD.AES256_GCM`` + * ``HPKE.AEAD.CHACHA20_POLY1305`` + + enc: + The encapsulated session key (i.e., the KEM shared secret). + + The receiver must always specify this parameter. + + The sender must always omit this parameter. + + sender_key: + The ECC key of the sender. + It must be on the same curve as the ``receiver_key``. + If the ``receiver_key`` is a public key, ``sender_key`` must be a + private key, and vice versa. + + psk: + A Pre-Shared Key (PSK) as a 2-tuple of non-empty + byte strings: the identifier and the actual secret value. + Sender and receiver must use the same PSK (or none). + + The secret value must be at least 32 bytes long, + but it must not be a low-entropy password + (use a KDF like PBKDF2 or scrypt to derive a secret + from a password). + + info: + A non-secret parameter that contributes + to the generation of all session keys. + Sender and receive must use the same **info** parameter (or none). + + Returns: + An object that can be used for + sealing (if ``receiver_key`` is a public key) or + unsealing (if ``receiver_key`` is a private key). + In the latter case, + correctness of all the keys and parameters will only + be assessed with the first call to ``unseal()``. + """ + + if aead_id not in AEAD: + raise ValueError(f"Unknown AEAD cipher ID {aead_id:#x}") + + curve = receiver_key.curve + if curve not in ( + "NIST P-256", + "NIST P-384", + "NIST P-521", + "Curve25519", + "Curve448", + ): + raise ValueError(f"Unsupported curve {curve}") + + if sender_key: + count_private_keys = int(receiver_key.has_private()) + int(sender_key.has_private()) + if count_private_keys != 1: + raise ValueError("Exactly 1 private key required") + if sender_key.curve != curve: + raise ValueError( + "Sender key uses {} but recipient key {}".format(sender_key.curve, curve), + ) + mode = MODE.AUTH if psk is None else MODE.AUTH_PSK + else: + mode = MODE.BASE if psk is None else MODE.PSK + + if psk is None: + psk = b"", b"" + + if info is None: + info = b"" + + return HPKE_Cipher( + receiver_key, + enc, + sender_key, + psk, + info, + aead_id, + mode, + ) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/KDF.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/KDF.py index 5f8170a0..c67f071c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/KDF.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/KDF.py @@ -26,622 +26,640 @@ import struct from functools import reduce -from Cryptodome.Util.py3compat import (tobytes, bord, _copy_bytes, iter_range, - tostr, bchr, bstr) +from Cryptodome.Util.py3compat import ( + tobytes, + bord, + _copy_bytes, + iter_range, + tostr, + bchr, + bstr, +) from Cryptodome.Hash import SHA1, SHA256, HMAC, CMAC, BLAKE2s from Cryptodome.Util.strxor import strxor from Cryptodome.Random import get_random_bytes from Cryptodome.Util.number import size as bit_size, long_to_bytes, bytes_to_long -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, c_size_t) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + create_string_buffer, + get_raw_buffer, + c_size_t, +) _raw_salsa20_lib = load_pycryptodome_raw_lib( - "Cryptodome.Cipher._Salsa20", - """ + "Cryptodome.Cipher._Salsa20", + """ int Salsa20_8_core(const uint8_t *x, const uint8_t *y, uint8_t *out); - """) + """, +) _raw_scrypt_lib = load_pycryptodome_raw_lib( - "Cryptodome.Protocol._scrypt", - """ + "Cryptodome.Protocol._scrypt", + """ typedef int (core_t)(const uint8_t [64], const uint8_t [64], uint8_t [64]); int scryptROMix(const uint8_t *data_in, uint8_t *data_out, size_t data_len, unsigned N, core_t *core); - """) + """, +) def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None): - """Derive one key from a password (or passphrase). - - This function performs key derivation according to an old version of - the PKCS#5 standard (v1.5) or `RFC2898 - `_. - - Args: - password (string): - The secret password to generate the key from. - salt (byte string): - An 8 byte string to use for better protection from dictionary attacks. - This value does not need to be kept secret, but it should be randomly - chosen for each derivation. - dkLen (integer): - The length of the desired key. The default is 16 bytes, suitable for - instance for :mod:`Cryptodome.Cipher.AES`. - count (integer): - The number of iterations to carry out. The recommendation is 1000 or - more. - hashAlgo (module): - The hash algorithm to use, as a module or an object from the :mod:`Cryptodome.Hash` package. - The digest length must be no shorter than ``dkLen``. - The default algorithm is :mod:`Cryptodome.Hash.SHA1`. - - Return: - A byte string of length ``dkLen`` that can be used as key. - """ - - if not hashAlgo: - hashAlgo = SHA1 - password = tobytes(password) - pHash = hashAlgo.new(password+salt) - digest = pHash.digest_size - if dkLen > digest: - raise TypeError("Selected hash algorithm has a too short digest (%d bytes)." % digest) - if len(salt) != 8: - raise ValueError("Salt is not 8 bytes long (%d bytes instead)." % len(salt)) - for i in iter_range(count-1): - pHash = pHash.new(pHash.digest()) - return pHash.digest()[:dkLen] + """Derive one key from a password (or passphrase). + + This function performs key derivation according to an old version of + the PKCS#5 standard (v1.5) or `RFC2898 + `_. + + Args: + password (string): + The secret password to generate the key from. + salt (byte string): + An 8 byte string to use for better protection from dictionary attacks. + This value does not need to be kept secret, but it should be randomly + chosen for each derivation. + dkLen (integer): + The length of the desired key. The default is 16 bytes, suitable for + instance for :mod:`Cryptodome.Cipher.AES`. + count (integer): + The number of iterations to carry out. The recommendation is 1000 or + more. + hashAlgo (module): + The hash algorithm to use, as a module or an object from the :mod:`Cryptodome.Hash` package. + The digest length must be no shorter than ``dkLen``. + The default algorithm is :mod:`Cryptodome.Hash.SHA1`. + + Return: + A byte string of length ``dkLen`` that can be used as key. + """ + + if not hashAlgo: + hashAlgo = SHA1 + password = tobytes(password) + pHash = hashAlgo.new(password + salt) + digest = pHash.digest_size + if dkLen > digest: + raise TypeError("Selected hash algorithm has a too short digest (%d bytes)." % digest) + if len(salt) != 8: + raise ValueError("Salt is not 8 bytes long (%d bytes instead)." % len(salt)) + for i in iter_range(count - 1): + pHash = pHash.new(pHash.digest()) + return pHash.digest()[:dkLen] def PBKDF2(password, salt, dkLen=16, count=1000, prf=None, hmac_hash_module=None): - """Derive one or more keys from a password (or passphrase). - - This function performs key derivation according to the PKCS#5 standard (v2.0). - - Args: - password (string or byte string): - The secret password to generate the key from. - - Strings will be encoded as ISO 8859-1 (also known as Latin-1), - which does not allow any characters with codepoints > 255. - salt (string or byte string): - A (byte) string to use for better protection from dictionary attacks. - This value does not need to be kept secret, but it should be randomly - chosen for each derivation. It is recommended to use at least 16 bytes. - - Strings will be encoded as ISO 8859-1 (also known as Latin-1), - which does not allow any characters with codepoints > 255. - dkLen (integer): - The cumulative length of the keys to produce. - - Due to a flaw in the PBKDF2 design, you should not request more bytes - than the ``prf`` can output. For instance, ``dkLen`` should not exceed - 20 bytes in combination with ``HMAC-SHA1``. - count (integer): - The number of iterations to carry out. The higher the value, the slower - and the more secure the function becomes. - - You should find the maximum number of iterations that keeps the - key derivation still acceptable on the slowest hardware you must support. - - Although the default value is 1000, **it is recommended to use at least - 1000000 (1 million) iterations**. - prf (callable): - A pseudorandom function. It must be a function that returns a - pseudorandom byte string from two parameters: a secret and a salt. - The slower the algorithm, the more secure the derivation function. - If not specified, **HMAC-SHA1** is used. - hmac_hash_module (module): - A module from ``Cryptodome.Hash`` implementing a Merkle-Damgard cryptographic - hash, which PBKDF2 must use in combination with HMAC. - This parameter is mutually exclusive with ``prf``. - - Return: - A byte string of length ``dkLen`` that can be used as key material. - If you want multiple keys, just break up this string into segments of the desired length. - """ - - password = tobytes(password) - salt = tobytes(salt) - - if prf and hmac_hash_module: - raise ValueError("'prf' and 'hmac_hash_module' are mutually exlusive") - - if prf is None and hmac_hash_module is None: - hmac_hash_module = SHA1 - - if prf or not hasattr(hmac_hash_module, "_pbkdf2_hmac_assist"): - # Generic (and slow) implementation - - if prf is None: - prf = lambda p, s: HMAC.new(p, s, hmac_hash_module).digest() - - def link(s): - s[0], s[1] = s[1], prf(password, s[1]) - return s[0] - - key = b'' - i = 1 - while len(key) < dkLen: - s = [prf(password, salt + struct.pack(">I", i))] * 2 - key += reduce(strxor, (link(s) for j in range(count))) - i += 1 - - else: - # Optimized implementation - key = b'' - i = 1 - while len(key) < dkLen: - base = HMAC.new(password, b"", hmac_hash_module) - first_digest = base.copy().update(salt + struct.pack(">I", i)).digest() - key += base._pbkdf2_hmac_assist(first_digest, count) - i += 1 - - return key[:dkLen] + """Derive one or more keys from a password (or passphrase). + + This function performs key derivation according to the PKCS#5 standard (v2.0). + + Args: + password (string or byte string): + The secret password to generate the key from. + + Strings will be encoded as ISO 8859-1 (also known as Latin-1), + which does not allow any characters with codepoints > 255. + salt (string or byte string): + A (byte) string to use for better protection from dictionary attacks. + This value does not need to be kept secret, but it should be randomly + chosen for each derivation. It is recommended to use at least 16 bytes. + + Strings will be encoded as ISO 8859-1 (also known as Latin-1), + which does not allow any characters with codepoints > 255. + dkLen (integer): + The cumulative length of the keys to produce. + + Due to a flaw in the PBKDF2 design, you should not request more bytes + than the ``prf`` can output. For instance, ``dkLen`` should not exceed + 20 bytes in combination with ``HMAC-SHA1``. + count (integer): + The number of iterations to carry out. The higher the value, the slower + and the more secure the function becomes. + + You should find the maximum number of iterations that keeps the + key derivation still acceptable on the slowest hardware you must support. + + Although the default value is 1000, **it is recommended to use at least + 1000000 (1 million) iterations**. + prf (callable): + A pseudorandom function. It must be a function that returns a + pseudorandom byte string from two parameters: a secret and a salt. + The slower the algorithm, the more secure the derivation function. + If not specified, **HMAC-SHA1** is used. + hmac_hash_module (module): + A module from ``Cryptodome.Hash`` implementing a Merkle-Damgard cryptographic + hash, which PBKDF2 must use in combination with HMAC. + This parameter is mutually exclusive with ``prf``. + + Return: + A byte string of length ``dkLen`` that can be used as key material. + If you want multiple keys, just break up this string into segments of the desired length. + """ + + password = tobytes(password) + salt = tobytes(salt) + + if prf and hmac_hash_module: + raise ValueError("'prf' and 'hmac_hash_module' are mutually exlusive") + + if prf is None and hmac_hash_module is None: + hmac_hash_module = SHA1 + + if prf or not hasattr(hmac_hash_module, "_pbkdf2_hmac_assist"): + # Generic (and slow) implementation + + if prf is None: + prf = lambda p, s: HMAC.new(p, s, hmac_hash_module).digest() + + def link(s): + s[0], s[1] = s[1], prf(password, s[1]) + return s[0] + + key = b"" + i = 1 + while len(key) < dkLen: + s = [prf(password, salt + struct.pack(">I", i))] * 2 + key += reduce(strxor, (link(s) for j in range(count))) + i += 1 + + else: + # Optimized implementation + key = b"" + i = 1 + while len(key) < dkLen: + base = HMAC.new(password, b"", hmac_hash_module) + first_digest = base.copy().update(salt + struct.pack(">I", i)).digest() + key += base._pbkdf2_hmac_assist(first_digest, count) + i += 1 + + return key[:dkLen] class _S2V(object): - """String-to-vector PRF as defined in `RFC5297`_. - - This class implements a pseudorandom function family - based on CMAC that takes as input a vector of strings. - - .. _RFC5297: http://tools.ietf.org/html/rfc5297 - """ - - def __init__(self, key, ciphermod, cipher_params=None): - """Initialize the S2V PRF. - - :Parameters: - key : byte string - A secret that can be used as key for CMACs - based on ciphers from ``ciphermod``. - ciphermod : module - A block cipher module from `Cryptodome.Cipher`. - cipher_params : dictionary - A set of extra parameters to use to create a cipher instance. - """ - - self._key = _copy_bytes(None, None, key) - self._ciphermod = ciphermod - self._last_string = self._cache = b'\x00' * ciphermod.block_size - - # Max number of update() call we can process - self._n_updates = ciphermod.block_size * 8 - 1 - - if cipher_params is None: - self._cipher_params = {} - else: - self._cipher_params = dict(cipher_params) - - @staticmethod - def new(key, ciphermod): - """Create a new S2V PRF. - - :Parameters: - key : byte string - A secret that can be used as key for CMACs - based on ciphers from ``ciphermod``. - ciphermod : module - A block cipher module from `Cryptodome.Cipher`. - """ - return _S2V(key, ciphermod) - - def _double(self, bs): - doubled = bytes_to_long(bs) << 1 - if bord(bs[0]) & 0x80: - doubled ^= 0x87 - return long_to_bytes(doubled, len(bs))[-len(bs):] - - def update(self, item): - """Pass the next component of the vector. - - The maximum number of components you can pass is equal to the block - length of the cipher (in bits) minus 1. - - :Parameters: - item : byte string - The next component of the vector. - :Raise TypeError: when the limit on the number of components has been reached. - """ - - if self._n_updates == 0: - raise TypeError("Too many components passed to S2V") - self._n_updates -= 1 - - mac = CMAC.new(self._key, - msg=self._last_string, - ciphermod=self._ciphermod, - cipher_params=self._cipher_params) - self._cache = strxor(self._double(self._cache), mac.digest()) - self._last_string = _copy_bytes(None, None, item) - - def derive(self): - """"Derive a secret from the vector of components. - - :Return: a byte string, as long as the block length of the cipher. - """ - - if len(self._last_string) >= 16: - # xorend - final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache) - else: - # zero-pad & xor - padded = (self._last_string + b'\x80' + b'\x00' * 15)[:16] - final = strxor(padded, self._double(self._cache)) - mac = CMAC.new(self._key, - msg=final, - ciphermod=self._ciphermod, - cipher_params=self._cipher_params) - return mac.digest() + """String-to-vector PRF as defined in `RFC5297`_. + + This class implements a pseudorandom function family + based on CMAC that takes as input a vector of strings. + + .. _RFC5297: http://tools.ietf.org/html/rfc5297 + """ + + def __init__(self, key, ciphermod, cipher_params=None): + """Initialize the S2V PRF. + + :Parameters: + key : byte string + A secret that can be used as key for CMACs + based on ciphers from ``ciphermod``. + ciphermod : module + A block cipher module from `Cryptodome.Cipher`. + cipher_params : dictionary + A set of extra parameters to use to create a cipher instance. + """ + + self._key = _copy_bytes(None, None, key) + self._ciphermod = ciphermod + self._last_string = self._cache = b"\x00" * ciphermod.block_size + + # Max number of update() call we can process + self._n_updates = ciphermod.block_size * 8 - 1 + + if cipher_params is None: + self._cipher_params = {} + else: + self._cipher_params = dict(cipher_params) + + @staticmethod + def new(key, ciphermod): + """Create a new S2V PRF. + + :Parameters: + key : byte string + A secret that can be used as key for CMACs + based on ciphers from ``ciphermod``. + ciphermod : module + A block cipher module from `Cryptodome.Cipher`. + """ + return _S2V(key, ciphermod) + + def _double(self, bs): + doubled = bytes_to_long(bs) << 1 + if bord(bs[0]) & 0x80: + doubled ^= 0x87 + return long_to_bytes(doubled, len(bs))[-len(bs) :] + + def update(self, item): + """Pass the next component of the vector. + + The maximum number of components you can pass is equal to the block + length of the cipher (in bits) minus 1. + + :Parameters: + item : byte string + The next component of the vector. + :Raise TypeError: when the limit on the number of components has been reached. + """ + + if self._n_updates == 0: + raise TypeError("Too many components passed to S2V") + self._n_updates -= 1 + + mac = CMAC.new( + self._key, + msg=self._last_string, + ciphermod=self._ciphermod, + cipher_params=self._cipher_params, + ) + self._cache = strxor(self._double(self._cache), mac.digest()) + self._last_string = _copy_bytes(None, None, item) + + def derive(self): + """ "Derive a secret from the vector of components. + + :Return: a byte string, as long as the block length of the cipher. + """ + + if len(self._last_string) >= 16: + # xorend + final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache) + else: + # zero-pad & xor + padded = (self._last_string + b"\x80" + b"\x00" * 15)[:16] + final = strxor(padded, self._double(self._cache)) + mac = CMAC.new( + self._key, + msg=final, + ciphermod=self._ciphermod, + cipher_params=self._cipher_params, + ) + return mac.digest() def _HKDF_extract(salt, ikm, hashmod): - prk = HMAC.new(salt, ikm, digestmod=hashmod).digest() - return prk + prk = HMAC.new(salt, ikm, digestmod=hashmod).digest() + return prk def _HKDF_expand(prk, info, L, hashmod): - t = [b""] - n = 1 - tlen = 0 - while tlen < L: - hmac = HMAC.new(prk, t[-1] + info + struct.pack('B', n), digestmod=hashmod) - t.append(hmac.digest()) - tlen += hashmod.digest_size - n += 1 - okm = b"".join(t) - return okm[:L] + t = [b""] + n = 1 + tlen = 0 + while tlen < L: + hmac = HMAC.new(prk, t[-1] + info + struct.pack("B", n), digestmod=hashmod) + t.append(hmac.digest()) + tlen += hashmod.digest_size + n += 1 + okm = b"".join(t) + return okm[:L] def HKDF(master, key_len, salt, hashmod, num_keys=1, context=None): - """Derive one or more keys from a master secret using - the HMAC-based KDF defined in RFC5869_. - - Args: - master (byte string): - The unguessable value used by the KDF to generate the other keys. - It must be a high-entropy secret, though not necessarily uniform. - It must not be a password. - key_len (integer): - The length in bytes of every derived key. - salt (byte string): - A non-secret, reusable value that strengthens the randomness - extraction step. - Ideally, it is as long as the digest size of the chosen hash. - If empty, a string of zeroes in used. - hashmod (module): - A cryptographic hash algorithm from :mod:`Cryptodome.Hash`. - :mod:`Cryptodome.Hash.SHA512` is a good choice. - num_keys (integer): - The number of keys to derive. Every key is :data:`key_len` bytes long. - The maximum cumulative length of all keys is - 255 times the digest size. - context (byte string): - Optional identifier describing what the keys are used for. - - Return: - A byte string or a tuple of byte strings. - - .. _RFC5869: http://tools.ietf.org/html/rfc5869 - """ - - output_len = key_len * num_keys - if output_len > (255 * hashmod.digest_size): - raise ValueError("Too much secret data to derive") - if not salt: - salt = b'\x00' * hashmod.digest_size - if context is None: - context = b"" - - prk = _HKDF_extract(salt, master, hashmod) - okm = _HKDF_expand(prk, context, output_len, hashmod) - - if num_keys == 1: - return okm[:key_len] - kol = [okm[idx:idx + key_len] - for idx in iter_range(0, output_len, key_len)] - return list(kol[:num_keys]) + """Derive one or more keys from a master secret using + the HMAC-based KDF defined in RFC5869_. + + Args: + master (byte string): + The unguessable value used by the KDF to generate the other keys. + It must be a high-entropy secret, though not necessarily uniform. + It must not be a password. + key_len (integer): + The length in bytes of every derived key. + salt (byte string): + A non-secret, reusable value that strengthens the randomness + extraction step. + Ideally, it is as long as the digest size of the chosen hash. + If empty, a string of zeroes in used. + hashmod (module): + A cryptographic hash algorithm from :mod:`Cryptodome.Hash`. + :mod:`Cryptodome.Hash.SHA512` is a good choice. + num_keys (integer): + The number of keys to derive. Every key is :data:`key_len` bytes long. + The maximum cumulative length of all keys is + 255 times the digest size. + context (byte string): + Optional identifier describing what the keys are used for. + + Return: + A byte string or a tuple of byte strings. + + .. _RFC5869: http://tools.ietf.org/html/rfc5869 + """ + + output_len = key_len * num_keys + if output_len > (255 * hashmod.digest_size): + raise ValueError("Too much secret data to derive") + if not salt: + salt = b"\x00" * hashmod.digest_size + if context is None: + context = b"" + + prk = _HKDF_extract(salt, master, hashmod) + okm = _HKDF_expand(prk, context, output_len, hashmod) + + if num_keys == 1: + return okm[:key_len] + kol = [okm[idx : idx + key_len] for idx in iter_range(0, output_len, key_len)] + return list(kol[:num_keys]) def scrypt(password, salt, key_len, N, r, p, num_keys=1): - """Derive one or more keys from a passphrase. - - Args: - password (string): - The secret pass phrase to generate the keys from. - salt (string): - A string to use for better protection from dictionary attacks. - This value does not need to be kept secret, - but it should be randomly chosen for each derivation. - It is recommended to be at least 16 bytes long. - key_len (integer): - The length in bytes of each derived key. - N (integer): - CPU/Memory cost parameter. It must be a power of 2 and less - than :math:`2^{32}`. - r (integer): - Block size parameter. - p (integer): - Parallelization parameter. - It must be no greater than :math:`(2^{32}-1)/(4r)`. - num_keys (integer): - The number of keys to derive. Every key is :data:`key_len` bytes long. - By default, only 1 key is generated. - The maximum cumulative length of all keys is :math:`(2^{32}-1)*32` - (that is, 128TB). - - A good choice of parameters *(N, r , p)* was suggested - by Colin Percival in his `presentation in 2009`__: - - - *( 2¹⁴, 8, 1 )* for interactive logins (≤100ms) - - *( 2²⁰, 8, 1 )* for file encryption (≤5s) - - Return: - A byte string or a tuple of byte strings. - - .. __: http://www.tarsnap.com/scrypt/scrypt-slides.pdf - """ - - if 2 ** (bit_size(N) - 1) != N: - raise ValueError("N must be a power of 2") - if N >= 2 ** 32: - raise ValueError("N is too big") - if p > ((2 ** 32 - 1) * 32) // (128 * r): - raise ValueError("p or r are too big") - - prf_hmac_sha256 = lambda p, s: HMAC.new(p, s, SHA256).digest() - - stage_1 = PBKDF2(password, salt, p * 128 * r, 1, prf=prf_hmac_sha256) - - scryptROMix = _raw_scrypt_lib.scryptROMix - core = _raw_salsa20_lib.Salsa20_8_core - - # Parallelize into p flows - data_out = [] - for flow in iter_range(p): - idx = flow * 128 * r - buffer_out = create_string_buffer(128 * r) - result = scryptROMix(stage_1[idx: idx + 128 * r], - buffer_out, - c_size_t(128 * r), - N, - core) - if result: - raise ValueError("Error %X while running scrypt" % result) - data_out += [get_raw_buffer(buffer_out)] - - dk = PBKDF2(password, - b"".join(data_out), - key_len * num_keys, 1, - prf=prf_hmac_sha256) - - if num_keys == 1: - return dk - - kol = [dk[idx:idx + key_len] - for idx in iter_range(0, key_len * num_keys, key_len)] - return kol + """Derive one or more keys from a passphrase. + + Args: + password (string): + The secret pass phrase to generate the keys from. + salt (string): + A string to use for better protection from dictionary attacks. + This value does not need to be kept secret, + but it should be randomly chosen for each derivation. + It is recommended to be at least 16 bytes long. + key_len (integer): + The length in bytes of each derived key. + N (integer): + CPU/Memory cost parameter. It must be a power of 2 and less + than :math:`2^{32}`. + r (integer): + Block size parameter. + p (integer): + Parallelization parameter. + It must be no greater than :math:`(2^{32}-1)/(4r)`. + num_keys (integer): + The number of keys to derive. Every key is :data:`key_len` bytes long. + By default, only 1 key is generated. + The maximum cumulative length of all keys is :math:`(2^{32}-1)*32` + (that is, 128TB). + + A good choice of parameters *(N, r , p)* was suggested + by Colin Percival in his `presentation in 2009`__: + + - *( 2¹⁴, 8, 1 )* for interactive logins (≤100ms) + - *( 2²⁰, 8, 1 )* for file encryption (≤5s) + + Return: + A byte string or a tuple of byte strings. + + .. __: http://www.tarsnap.com/scrypt/scrypt-slides.pdf + """ + + if 2 ** (bit_size(N) - 1) != N: + raise ValueError("N must be a power of 2") + if N >= 2**32: + raise ValueError("N is too big") + if p > ((2**32 - 1) * 32) // (128 * r): + raise ValueError("p or r are too big") + + prf_hmac_sha256 = lambda p, s: HMAC.new(p, s, SHA256).digest() + + stage_1 = PBKDF2(password, salt, p * 128 * r, 1, prf=prf_hmac_sha256) + + scryptROMix = _raw_scrypt_lib.scryptROMix + core = _raw_salsa20_lib.Salsa20_8_core + + # Parallelize into p flows + data_out = [] + for flow in iter_range(p): + idx = flow * 128 * r + buffer_out = create_string_buffer(128 * r) + result = scryptROMix( + stage_1[idx : idx + 128 * r], + buffer_out, + c_size_t(128 * r), + N, + core, + ) + if result: + raise ValueError("Error %X while running scrypt" % result) + data_out += [get_raw_buffer(buffer_out)] + + dk = PBKDF2( + password, + b"".join(data_out), + key_len * num_keys, + 1, + prf=prf_hmac_sha256, + ) + + if num_keys == 1: + return dk + + kol = [dk[idx : idx + key_len] for idx in iter_range(0, key_len * num_keys, key_len)] + return kol def _bcrypt_encode(data): - s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - bits = [] - for c in data: - bits_c = bin(bord(c))[2:].zfill(8) - bits.append(bstr(bits_c)) - bits = b"".join(bits) + bits = [] + for c in data: + bits_c = bin(bord(c))[2:].zfill(8) + bits.append(bstr(bits_c)) + bits = b"".join(bits) - bits6 = [bits[idx:idx+6] for idx in range(0, len(bits), 6)] + bits6 = [bits[idx : idx + 6] for idx in range(0, len(bits), 6)] - result = [] - for g in bits6[:-1]: - idx = int(g, 2) - result.append(s[idx]) + result = [] + for g in bits6[:-1]: + idx = int(g, 2) + result.append(s[idx]) - g = bits6[-1] - idx = int(g, 2) << (6 - len(g)) - result.append(s[idx]) - result = "".join(result) + g = bits6[-1] + idx = int(g, 2) << (6 - len(g)) + result.append(s[idx]) + result = "".join(result) - return tobytes(result) + return tobytes(result) def _bcrypt_decode(data): - s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - bits = [] - for c in tostr(data): - idx = s.find(c) - bits6 = bin(idx)[2:].zfill(6) - bits.append(bits6) - bits = "".join(bits) + bits = [] + for c in tostr(data): + idx = s.find(c) + bits6 = bin(idx)[2:].zfill(6) + bits.append(bits6) + bits = "".join(bits) - modulo4 = len(data) % 4 - if modulo4 == 1: - raise ValueError("Incorrect length") - elif modulo4 == 2: - bits = bits[:-4] - elif modulo4 == 3: - bits = bits[:-2] + modulo4 = len(data) % 4 + if modulo4 == 1: + raise ValueError("Incorrect length") + elif modulo4 == 2: + bits = bits[:-4] + elif modulo4 == 3: + bits = bits[:-2] - bits8 = [bits[idx:idx+8] for idx in range(0, len(bits), 8)] + bits8 = [bits[idx : idx + 8] for idx in range(0, len(bits), 8)] - result = [] - for g in bits8: - result.append(bchr(int(g, 2))) - result = b"".join(result) + result = [] + for g in bits8: + result.append(bchr(int(g, 2))) + result = b"".join(result) - return result + return result def _bcrypt_hash(password, cost, salt, constant, invert): - from Cryptodome.Cipher import _EKSBlowfish + from Cryptodome.Cipher import _EKSBlowfish - if len(password) > 72: - raise ValueError("The password is too long. It must be 72 bytes at most.") + if len(password) > 72: + raise ValueError("The password is too long. It must be 72 bytes at most.") - if not (4 <= cost <= 31): - raise ValueError("bcrypt cost factor must be in the range 4..31") + if not (4 <= cost <= 31): + raise ValueError("bcrypt cost factor must be in the range 4..31") - cipher = _EKSBlowfish.new(password, _EKSBlowfish.MODE_ECB, salt, cost, invert) - ctext = constant - for _ in range(64): - ctext = cipher.encrypt(ctext) - return ctext + cipher = _EKSBlowfish.new(password, _EKSBlowfish.MODE_ECB, salt, cost, invert) + ctext = constant + for _ in range(64): + ctext = cipher.encrypt(ctext) + return ctext def bcrypt(password, cost, salt=None): - """Hash a password into a key, using the OpenBSD bcrypt protocol. + """Hash a password into a key, using the OpenBSD bcrypt protocol. - Args: - password (byte string or string): - The secret password or pass phrase. - It must be at most 72 bytes long. - It must not contain the zero byte. - Unicode strings will be encoded as UTF-8. - cost (integer): - The exponential factor that makes it slower to compute the hash. - It must be in the range 4 to 31. - A value of at least 12 is recommended. - salt (byte string): - Optional. Random byte string to thwarts dictionary and rainbow table - attacks. It must be 16 bytes long. - If not passed, a random value is generated. + Args: + password (byte string or string): + The secret password or pass phrase. + It must be at most 72 bytes long. + It must not contain the zero byte. + Unicode strings will be encoded as UTF-8. + cost (integer): + The exponential factor that makes it slower to compute the hash. + It must be in the range 4 to 31. + A value of at least 12 is recommended. + salt (byte string): + Optional. Random byte string to thwarts dictionary and rainbow table + attacks. It must be 16 bytes long. + If not passed, a random value is generated. - Return (byte string): - The bcrypt hash + Return (byte string): + The bcrypt hash - Raises: - ValueError: if password is longer than 72 bytes or if it contains the zero byte + Raises: + ValueError: if password is longer than 72 bytes or if it contains the zero byte - """ + """ - password = tobytes(password, "utf-8") + password = tobytes(password, "utf-8") - if password.find(bchr(0)[0]) != -1: - raise ValueError("The password contains the zero byte") + if password.find(bchr(0)[0]) != -1: + raise ValueError("The password contains the zero byte") - if len(password) < 72: - password += b"\x00" + if len(password) < 72: + password += b"\x00" - if salt is None: - salt = get_random_bytes(16) - if len(salt) != 16: - raise ValueError("bcrypt salt must be 16 bytes long") + if salt is None: + salt = get_random_bytes(16) + if len(salt) != 16: + raise ValueError("bcrypt salt must be 16 bytes long") - ctext = _bcrypt_hash(password, cost, salt, b"OrpheanBeholderScryDoubt", True) + ctext = _bcrypt_hash(password, cost, salt, b"OrpheanBeholderScryDoubt", True) - cost_enc = b"$" + bstr(str(cost).zfill(2)) - salt_enc = b"$" + _bcrypt_encode(salt) - hash_enc = _bcrypt_encode(ctext[:-1]) # only use 23 bytes, not 24 - return b"$2a" + cost_enc + salt_enc + hash_enc + cost_enc = b"$" + bstr(str(cost).zfill(2)) + salt_enc = b"$" + _bcrypt_encode(salt) + hash_enc = _bcrypt_encode(ctext[:-1]) # only use 23 bytes, not 24 + return b"$2a" + cost_enc + salt_enc + hash_enc def bcrypt_check(password, bcrypt_hash): - """Verify if the provided password matches the given bcrypt hash. - - Args: - password (byte string or string): - The secret password or pass phrase to test. - It must be at most 72 bytes long. - It must not contain the zero byte. - Unicode strings will be encoded as UTF-8. - bcrypt_hash (byte string, bytearray): - The reference bcrypt hash the password needs to be checked against. - - Raises: - ValueError: if the password does not match - """ - - bcrypt_hash = tobytes(bcrypt_hash) - - if len(bcrypt_hash) != 60: - raise ValueError("Incorrect length of the bcrypt hash: %d bytes instead of 60" % len(bcrypt_hash)) - - if bcrypt_hash[:4] != b'$2a$': - raise ValueError("Unsupported prefix") - - p = re.compile(br'\$2a\$([0-9][0-9])\$([A-Za-z0-9./]{22,22})([A-Za-z0-9./]{31,31})') - r = p.match(bcrypt_hash) - if not r: - raise ValueError("Incorrect bcrypt hash format") - - cost = int(r.group(1)) - if not (4 <= cost <= 31): - raise ValueError("Incorrect cost") - - salt = _bcrypt_decode(r.group(2)) - - bcrypt_hash2 = bcrypt(password, cost, salt) - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash).digest() - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash2).digest() - if mac1 != mac2: - raise ValueError("Incorrect bcrypt hash") - - -def SP800_108_Counter(master, key_len, prf, num_keys=None, label=b'', context=b''): - """Derive one or more keys from a master secret using - a pseudorandom function in Counter Mode, as specified in - `NIST SP 800-108r1 `_. - - Args: - master (byte string): - The secret value used by the KDF to derive the other keys. - It must not be a password. - The length on the secret must be consistent with the input expected by - the :data:`prf` function. - key_len (integer): - The length in bytes of each derived key. - prf (function): - A pseudorandom function that takes two byte strings as parameters: - the secret and an input. It returns another byte string. - num_keys (integer): - The number of keys to derive. Every key is :data:`key_len` bytes long. - By default, only 1 key is derived. - label (byte string): - Optional description of the purpose of the derived keys. - It must not contain zero bytes. - context (byte string): - Optional information pertaining to - the protocol that uses the keys, such as the identity of the - participants, nonces, session IDs, etc. - It must not contain zero bytes. - - Return: - - a byte string (if ``num_keys`` is not specified), or - - a tuple of byte strings (if ``num_key`` is specified). - """ - - if num_keys is None: - num_keys = 1 - - if context.find(b'\x00') != -1: - raise ValueError("Null byte found in context") - - key_len_enc = long_to_bytes(key_len * num_keys * 8, 4) - output_len = key_len * num_keys - - i = 1 - dk = b"" - while len(dk) < output_len: - info = long_to_bytes(i, 4) + label + b'\x00' + context + key_len_enc - dk += prf(master, info) - i += 1 - if i > 0xFFFFFFFF: - raise ValueError("Overflow in SP800 108 counter") - - if num_keys == 1: - return dk[:key_len] - else: - kol = [dk[idx:idx + key_len] - for idx in iter_range(0, output_len, key_len)] - return kol + """Verify if the provided password matches the given bcrypt hash. + + Args: + password (byte string or string): + The secret password or pass phrase to test. + It must be at most 72 bytes long. + It must not contain the zero byte. + Unicode strings will be encoded as UTF-8. + bcrypt_hash (byte string, bytearray): + The reference bcrypt hash the password needs to be checked against. + + Raises: + ValueError: if the password does not match + """ + + bcrypt_hash = tobytes(bcrypt_hash) + + if len(bcrypt_hash) != 60: + raise ValueError("Incorrect length of the bcrypt hash: %d bytes instead of 60" % len(bcrypt_hash)) + + if bcrypt_hash[:4] != b"$2a$": + raise ValueError("Unsupported prefix") + + p = re.compile(rb"\$2a\$([0-9][0-9])\$([A-Za-z0-9./]{22,22})([A-Za-z0-9./]{31,31})") + r = p.match(bcrypt_hash) + if not r: + raise ValueError("Incorrect bcrypt hash format") + + cost = int(r.group(1)) + if not (4 <= cost <= 31): + raise ValueError("Incorrect cost") + + salt = _bcrypt_decode(r.group(2)) + + bcrypt_hash2 = bcrypt(password, cost, salt) + + secret = get_random_bytes(16) + + mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash).digest() + mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash2).digest() + if mac1 != mac2: + raise ValueError("Incorrect bcrypt hash") + + +def SP800_108_Counter(master, key_len, prf, num_keys=None, label=b"", context=b""): + """Derive one or more keys from a master secret using + a pseudorandom function in Counter Mode, as specified in + `NIST SP 800-108r1 `_. + + Args: + master (byte string): + The secret value used by the KDF to derive the other keys. + It must not be a password. + The length on the secret must be consistent with the input expected by + the :data:`prf` function. + key_len (integer): + The length in bytes of each derived key. + prf (function): + A pseudorandom function that takes two byte strings as parameters: + the secret and an input. It returns another byte string. + num_keys (integer): + The number of keys to derive. Every key is :data:`key_len` bytes long. + By default, only 1 key is derived. + label (byte string): + Optional description of the purpose of the derived keys. + It must not contain zero bytes. + context (byte string): + Optional information pertaining to + the protocol that uses the keys, such as the identity of the + participants, nonces, session IDs, etc. + It must not contain zero bytes. + + Return: + - a byte string (if ``num_keys`` is not specified), or + - a tuple of byte strings (if ``num_key`` is specified). + """ + + if num_keys is None: + num_keys = 1 + + if context.find(b"\x00") != -1: + raise ValueError("Null byte found in context") + + key_len_enc = long_to_bytes(key_len * num_keys * 8, 4) + output_len = key_len * num_keys + + i = 1 + dk = b"" + while len(dk) < output_len: + info = long_to_bytes(i, 4) + label + b"\x00" + context + key_len_enc + dk += prf(master, info) + i += 1 + if i > 0xFFFFFFFF: + raise ValueError("Overflow in SP800 108 counter") + + if num_keys == 1: + return dk[:key_len] + else: + kol = [dk[idx : idx + key_len] for idx in iter_range(0, output_len, key_len)] + return kol diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/KDF.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/KDF.pyi index 80691e0f..21289389 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/KDF.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/KDF.pyi @@ -2,43 +2,59 @@ from types import ModuleType from typing import Optional, Callable, Tuple, Union, Dict, Any, overload from typing_extensions import Literal -Buffer=bytes|bytearray|memoryview +Buffer = bytes | bytearray | memoryview RNG = Callable[[int], bytes] PRF = Callable[[bytes, bytes], bytes] -def PBKDF1(password: str, salt: bytes, dkLen: int, count: Optional[int]=1000, hashAlgo: Optional[ModuleType]=None) -> bytes: ... -def PBKDF2(password: str, salt: bytes, dkLen: Optional[int]=16, count: Optional[int]=1000, prf: Optional[RNG]=None, hmac_hash_module: Optional[ModuleType]=None) -> bytes: ... +def PBKDF1( + password: str, salt: bytes, dkLen: int, count: Optional[int] = 1000, hashAlgo: Optional[ModuleType] = None +) -> bytes: ... +def PBKDF2( + password: str, + salt: bytes, + dkLen: Optional[int] = 16, + count: Optional[int] = 1000, + prf: Optional[RNG] = None, + hmac_hash_module: Optional[ModuleType] = None, +) -> bytes: ... class _S2V(object): - def __init__(self, key: bytes, ciphermod: ModuleType, cipher_params: Optional[Dict[Any, Any]]=None) -> None: ... - - @staticmethod - def new(key: bytes, ciphermod: ModuleType) -> None: ... - def update(self, item: bytes) -> None: ... - def derive(self) -> bytes: ... + def __init__( + self, key: bytes, ciphermod: ModuleType, cipher_params: Optional[Dict[Any, Any]] = None + ) -> None: ... + @staticmethod + def new(key: bytes, ciphermod: ModuleType) -> None: ... + def update(self, item: bytes) -> None: ... + def derive(self) -> bytes: ... def _HKDF_extract(salt: Buffer, ikm: Buffer, hashmod: ModuleType) -> bytes: ... -def _HKDF_expand(prk: Buffer, info: Buffer, L: int, hashmod) -> bytes : ... -def HKDF(master: bytes, key_len: int, salt: bytes, hashmod: ModuleType, num_keys: Optional[int]=1, context: Optional[bytes]=None) -> Union[bytes, Tuple[bytes, ...]]: ... - -def scrypt(password: str, salt: str, key_len: int, N: int, r: int, p: int, num_keys: Optional[int]=1) -> Union[bytes, Tuple[bytes, ...]]: ... - +def _HKDF_expand(prk: Buffer, info: Buffer, L: int, hashmod) -> bytes: ... +def HKDF( + master: bytes, + key_len: int, + salt: bytes, + hashmod: ModuleType, + num_keys: Optional[int] = 1, + context: Optional[bytes] = None, +) -> Union[bytes, Tuple[bytes, ...]]: ... +def scrypt( + password: str, salt: str, key_len: int, N: int, r: int, p: int, num_keys: Optional[int] = 1 +) -> Union[bytes, Tuple[bytes, ...]]: ... def _bcrypt_decode(data: bytes) -> bytes: ... -def _bcrypt_hash(password:bytes , cost: int, salt: bytes, constant:bytes, invert:bool) -> bytes: ... -def bcrypt(password: Union[bytes, str], cost: int, salt: Optional[bytes]=None) -> bytes: ... +def _bcrypt_hash(password: bytes, cost: int, salt: bytes, constant: bytes, invert: bool) -> bytes: ... +def bcrypt(password: Union[bytes, str], cost: int, salt: Optional[bytes] = None) -> bytes: ... def bcrypt_check(password: Union[bytes, str], bcrypt_hash: Union[bytes, bytearray, str]) -> None: ... - @overload -def SP800_108_Counter(master: Buffer, - key_len: int, - prf: PRF, - num_keys: Literal[None] = None, - label: Buffer = b'', context: Buffer = b'') -> bytes: ... - +def SP800_108_Counter( + master: Buffer, + key_len: int, + prf: PRF, + num_keys: Literal[None] = None, + label: Buffer = b"", + context: Buffer = b"", +) -> bytes: ... @overload -def SP800_108_Counter(master: Buffer, - key_len: int, - prf: PRF, - num_keys: int, - label: Buffer = b'', context: Buffer = b'') -> Tuple[bytes]: ... +def SP800_108_Counter( + master: Buffer, key_len: int, prf: PRF, num_keys: int, label: Buffer = b"", context: Buffer = b"" +) -> Tuple[bytes]: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/SecretSharing.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/SecretSharing.py index 1034909f..2d07c5f1 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/SecretSharing.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/SecretSharing.py @@ -38,260 +38,259 @@ def _mult_gf2(f1, f2): - """Multiply two polynomials in GF(2)""" + """Multiply two polynomials in GF(2)""" - # Ensure f2 is the smallest - if f2 > f1: - f1, f2 = f2, f1 - z = 0 - while f2: - if f2 & 1: - z ^= f1 - f1 <<= 1 - f2 >>= 1 - return z + # Ensure f2 is the smallest + if f2 > f1: + f1, f2 = f2, f1 + z = 0 + while f2: + if f2 & 1: + z ^= f1 + f1 <<= 1 + f2 >>= 1 + return z def _div_gf2(a, b): - """ - Compute division of polynomials over GF(2). - Given a and b, it finds two polynomials q and r such that: + """ + Compute division of polynomials over GF(2). + Given a and b, it finds two polynomials q and r such that: - a = b*q + r with deg(r)= d: - s = 1 << (deg(r) - d) - q ^= s - r ^= _mult_gf2(b, s) - return (q, r) + deg = number.size + q = 0 + r = a + d = deg(b) + while deg(r) >= d: + s = 1 << (deg(r) - d) + q ^= s + r ^= _mult_gf2(b, s) + return (q, r) class _Element(object): - """Element of GF(2^128) field""" - - # The irreducible polynomial defining - # this field is 1 + x + x^2 + x^7 + x^128 - irr_poly = 1 + 2 + 4 + 128 + 2 ** 128 - - def __init__(self, encoded_value): - """Initialize the element to a certain value. - - The value passed as parameter is internally encoded as - a 128-bit integer, where each bit represents a polynomial - coefficient. The LSB is the constant coefficient. - """ - - if is_native_int(encoded_value): - self._value = encoded_value - elif len(encoded_value) == 16: - self._value = bytes_to_long(encoded_value) - else: - raise ValueError("The encoded value must be an integer or a 16 byte string") - - def __eq__(self, other): - return self._value == other._value - - def __int__(self): - """Return the field element, encoded as a 128-bit integer.""" - return self._value - - def encode(self): - """Return the field element, encoded as a 16 byte string.""" - return long_to_bytes(self._value, 16) - - def __mul__(self, factor): - - f1 = self._value - f2 = factor._value - - # Make sure that f2 is the smallest, to speed up the loop - if f2 > f1: - f1, f2 = f2, f1 - - if self.irr_poly in (f1, f2): - return _Element(0) - - mask1 = 2 ** 128 - v, z = f1, 0 - while f2: - # if f2 ^ 1: z ^= v - mask2 = int(bin(f2 & 1)[2:] * 128, base=2) - z = (mask2 & (z ^ v)) | ((mask1 - mask2 - 1) & z) - v <<= 1 - # if v & mask1: v ^= self.irr_poly - mask3 = int(bin((v >> 128) & 1)[2:] * 128, base=2) - v = (mask3 & (v ^ self.irr_poly)) | ((mask1 - mask3 - 1) & v) - f2 >>= 1 - return _Element(z) - - def __add__(self, term): - return _Element(self._value ^ term._value) - - def inverse(self): - """Return the inverse of this element in GF(2^128).""" - - # We use the Extended GCD algorithm - # http://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor - - if self._value == 0: - raise ValueError("Inversion of zero") - - r0, r1 = self._value, self.irr_poly - s0, s1 = 1, 0 - while r1 > 0: - q = _div_gf2(r0, r1)[0] - r0, r1 = r1, r0 ^ _mult_gf2(q, r1) - s0, s1 = s1, s0 ^ _mult_gf2(q, s1) - return _Element(s0) - - def __pow__(self, exponent): - result = _Element(self._value) - for _ in range(exponent - 1): - result = result * self - return result + """Element of GF(2^128) field""" + + # The irreducible polynomial defining + # this field is 1 + x + x^2 + x^7 + x^128 + irr_poly = 1 + 2 + 4 + 128 + 2**128 + + def __init__(self, encoded_value): + """Initialize the element to a certain value. + + The value passed as parameter is internally encoded as + a 128-bit integer, where each bit represents a polynomial + coefficient. The LSB is the constant coefficient. + """ + + if is_native_int(encoded_value): + self._value = encoded_value + elif len(encoded_value) == 16: + self._value = bytes_to_long(encoded_value) + else: + raise ValueError("The encoded value must be an integer or a 16 byte string") + + def __eq__(self, other): + return self._value == other._value + + def __int__(self): + """Return the field element, encoded as a 128-bit integer.""" + return self._value + + def encode(self): + """Return the field element, encoded as a 16 byte string.""" + return long_to_bytes(self._value, 16) + + def __mul__(self, factor): + f1 = self._value + f2 = factor._value + + # Make sure that f2 is the smallest, to speed up the loop + if f2 > f1: + f1, f2 = f2, f1 + + if self.irr_poly in (f1, f2): + return _Element(0) + + mask1 = 2**128 + v, z = f1, 0 + while f2: + # if f2 ^ 1: z ^= v + mask2 = int(bin(f2 & 1)[2:] * 128, base=2) + z = (mask2 & (z ^ v)) | ((mask1 - mask2 - 1) & z) + v <<= 1 + # if v & mask1: v ^= self.irr_poly + mask3 = int(bin((v >> 128) & 1)[2:] * 128, base=2) + v = (mask3 & (v ^ self.irr_poly)) | ((mask1 - mask3 - 1) & v) + f2 >>= 1 + return _Element(z) + + def __add__(self, term): + return _Element(self._value ^ term._value) + + def inverse(self): + """Return the inverse of this element in GF(2^128).""" + + # We use the Extended GCD algorithm + # http://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor + + if self._value == 0: + raise ValueError("Inversion of zero") + + r0, r1 = self._value, self.irr_poly + s0, s1 = 1, 0 + while r1 > 0: + q = _div_gf2(r0, r1)[0] + r0, r1 = r1, r0 ^ _mult_gf2(q, r1) + s0, s1 = s1, s0 ^ _mult_gf2(q, s1) + return _Element(s0) + + def __pow__(self, exponent): + result = _Element(self._value) + for _ in range(exponent - 1): + result = result * self + return result class Shamir(object): - """Shamir's secret sharing scheme. - - A secret is split into ``n`` shares, and it is sufficient to collect - ``k`` of them to reconstruct the secret. - """ - - @staticmethod - def split(k, n, secret, ssss=False): - """Split a secret into ``n`` shares. - - The secret can be reconstructed later using just ``k`` shares - out of the original ``n``. - Each share must be kept confidential to the person it was - assigned to. - - Each share is associated to an index (starting from 1). - - Args: - k (integer): - The number of shares needed to reconstruct the secret. - n (integer): - The number of shares to create (at least ``k``). - secret (byte string): - A byte string of 16 bytes (e.g. an AES 128 key). - ssss (bool): - If ``True``, the shares can be used with the ``ssss`` utility - (without using the "diffusion layer"). - Default: ``False``. - - Return (tuples): - ``n`` tuples, one per participant. - A tuple contains two items: - - 1. the unique index (an integer) - 2. the share (16 bytes) - """ - - # - # We create a polynomial with random coefficients in GF(2^128): - # - # p(x) = c_0 + \sum_{i=1}^{k-1} c_i * x^i - # - # c_0 is the secret. - # - - coeffs = [_Element(rng(16)) for i in range(k - 1)] - coeffs.append(_Element(secret)) - - # Each share is y_i = p(x_i) where x_i - # is the index assigned to the share. - - def make_share(user, coeffs, ssss): - idx = _Element(user) - - # Horner's method - share = _Element(0) - for coeff in coeffs: - share = idx * share + coeff - - # The ssss utility actually uses: - # - # p(x) = c_0 + \sum_{i=1}^{k-1} c_i * x^i + x^k - # - if ssss: - share += _Element(user) ** len(coeffs) - - return share.encode() - - return [(i, make_share(i, coeffs, ssss)) for i in range(1, n + 1)] - - @staticmethod - def combine(shares, ssss=False): - """Recombine a secret, if enough shares are presented. - - Args: - shares (tuples): - The *k* tuples, each containing the index (an integer) and - the share (a byte string, 16 bytes long) that were assigned to - a participant. - - .. note:: - - Pass exactly as many share as they are required, - and no more. - - ssss (bool): - If ``True``, the shares were produced by the ``ssss`` utility - (without using the "diffusion layer"). - Default: ``False``. - - Return: - The original secret, as a byte string (16 bytes long). - """ - - # - # Given k points (x,y), the interpolation polynomial of degree k-1 is: - # - # L(x) = \sum_{j=0}^{k-1} y_i * l_j(x) - # - # where: - # - # l_j(x) = \prod_{ \overset{0 \le m \le k-1}{m \ne j} } - # \frac{x - x_m}{x_j - x_m} - # - # However, in this case we are purely interested in the constant - # coefficient of L(x). - # - - k = len(shares) - - gf_shares = [] - for x in shares: - idx = _Element(x[0]) - value = _Element(x[1]) - if any(y[0] == idx for y in gf_shares): - raise ValueError("Duplicate share") - if ssss: - value += idx ** k - gf_shares.append((idx, value)) - - result = _Element(0) - for j in range(k): - x_j, y_j = gf_shares[j] - - numerator = _Element(1) - denominator = _Element(1) - - for m in range(k): - x_m = gf_shares[m][0] - if m != j: - numerator *= x_m - denominator *= x_j + x_m - result += y_j * numerator * denominator.inverse() - - return result.encode() + """Shamir's secret sharing scheme. + + A secret is split into ``n`` shares, and it is sufficient to collect + ``k`` of them to reconstruct the secret. + """ + + @staticmethod + def split(k, n, secret, ssss=False): + """Split a secret into ``n`` shares. + + The secret can be reconstructed later using just ``k`` shares + out of the original ``n``. + Each share must be kept confidential to the person it was + assigned to. + + Each share is associated to an index (starting from 1). + + Args: + k (integer): + The number of shares needed to reconstruct the secret. + n (integer): + The number of shares to create (at least ``k``). + secret (byte string): + A byte string of 16 bytes (e.g. an AES 128 key). + ssss (bool): + If ``True``, the shares can be used with the ``ssss`` utility + (without using the "diffusion layer"). + Default: ``False``. + + Return (tuples): + ``n`` tuples, one per participant. + A tuple contains two items: + + 1. the unique index (an integer) + 2. the share (16 bytes) + """ + + # + # We create a polynomial with random coefficients in GF(2^128): + # + # p(x) = c_0 + \sum_{i=1}^{k-1} c_i * x^i + # + # c_0 is the secret. + # + + coeffs = [_Element(rng(16)) for i in range(k - 1)] + coeffs.append(_Element(secret)) + + # Each share is y_i = p(x_i) where x_i + # is the index assigned to the share. + + def make_share(user, coeffs, ssss): + idx = _Element(user) + + # Horner's method + share = _Element(0) + for coeff in coeffs: + share = idx * share + coeff + + # The ssss utility actually uses: + # + # p(x) = c_0 + \sum_{i=1}^{k-1} c_i * x^i + x^k + # + if ssss: + share += _Element(user) ** len(coeffs) + + return share.encode() + + return [(i, make_share(i, coeffs, ssss)) for i in range(1, n + 1)] + + @staticmethod + def combine(shares, ssss=False): + """Recombine a secret, if enough shares are presented. + + Args: + shares (tuples): + The *k* tuples, each containing the index (an integer) and + the share (a byte string, 16 bytes long) that were assigned to + a participant. + + .. note:: + + Pass exactly as many share as they are required, + and no more. + + ssss (bool): + If ``True``, the shares were produced by the ``ssss`` utility + (without using the "diffusion layer"). + Default: ``False``. + + Return: + The original secret, as a byte string (16 bytes long). + """ + + # + # Given k points (x,y), the interpolation polynomial of degree k-1 is: + # + # L(x) = \sum_{j=0}^{k-1} y_i * l_j(x) + # + # where: + # + # l_j(x) = \prod_{ \overset{0 \le m \le k-1}{m \ne j} } + # \frac{x - x_m}{x_j - x_m} + # + # However, in this case we are purely interested in the constant + # coefficient of L(x). + # + + k = len(shares) + + gf_shares = [] + for x in shares: + idx = _Element(x[0]) + value = _Element(x[1]) + if any(y[0] == idx for y in gf_shares): + raise ValueError("Duplicate share") + if ssss: + value += idx**k + gf_shares.append((idx, value)) + + result = _Element(0) + for j in range(k): + x_j, y_j = gf_shares[j] + + numerator = _Element(1) + denominator = _Element(1) + + for m in range(k): + x_m = gf_shares[m][0] + if m != j: + numerator *= x_m + denominator *= x_j + x_m + result += y_j * numerator * denominator.inverse() + + return result.encode() diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/SecretSharing.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/SecretSharing.pyi index 5952c993..ff200854 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/SecretSharing.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/SecretSharing.pyi @@ -1,22 +1,21 @@ from typing import Union, List, Tuple, Optional -def _mult_gf2(f1: int, f2: int) -> int : ... -def _div_gf2(a: int, b: int) -> int : ... +def _mult_gf2(f1: int, f2: int) -> int: ... +def _div_gf2(a: int, b: int) -> int: ... class _Element(object): - irr_poly: int - def __init__(self, encoded_value: Union[int, bytes]) -> None: ... - def __eq__(self, other) -> bool: ... - def __int__(self) -> int: ... - def encode(self) -> bytes: ... - def __mul__(self, factor: int) -> _Element: ... - def __add__(self, term: _Element) -> _Element: ... - def inverse(self) -> _Element: ... - def __pow__(self, exponent) -> _Element: ... + irr_poly: int + def __init__(self, encoded_value: Union[int, bytes]) -> None: ... + def __eq__(self, other) -> bool: ... + def __int__(self) -> int: ... + def encode(self) -> bytes: ... + def __mul__(self, factor: int) -> _Element: ... + def __add__(self, term: _Element) -> _Element: ... + def inverse(self) -> _Element: ... + def __pow__(self, exponent) -> _Element: ... class Shamir(object): - @staticmethod - def split(k: int, n: int, secret: bytes, ssss: Optional[bool]) -> List[Tuple[int, bytes]]: ... - @staticmethod - def combine(shares: List[Tuple[int, bytes]], ssss: Optional[bool]) -> bytes: ... - + @staticmethod + def split(k: int, n: int, secret: bytes, ssss: Optional[bool]) -> List[Tuple[int, bytes]]: ... + @staticmethod + def combine(shares: List[Tuple[int, bytes]], ssss: Optional[bool]) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/__init__.py index 76e22bf6..7d0721dc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/__init__.py @@ -28,4 +28,4 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = ['KDF', 'SecretSharing', 'DH'] +__all__ = ["KDF", "SecretSharing", "DH"] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/__init__.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/__init__.pyi index 377ed901..4e66b321 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/__init__.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Protocol/__init__.pyi @@ -1 +1 @@ -__all__ = ['KDF.pyi', 'SecretSharing.pyi'] +__all__ = ["KDF.pyi", "SecretSharing.pyi"] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/DSA.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/DSA.py index dddd304b..d0994e48 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/DSA.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/DSA.py @@ -22,7 +22,7 @@ # SOFTWARE. # =================================================================== -__all__ = ['generate', 'construct', 'DsaKey', 'import_key' ] +__all__ = ["generate", "construct", "DsaKey", "import_key"] import binascii import struct @@ -34,18 +34,22 @@ from Cryptodome.IO import PKCS8, PEM from Cryptodome.Hash import SHA256 from Cryptodome.Util.asn1 import ( - DerObject, DerSequence, - DerInteger, DerObjectId, - DerBitString, - ) + DerSequence, + DerInteger, +) from Cryptodome.Math.Numbers import Integer -from Cryptodome.Math.Primality import (test_probable_prime, COMPOSITE, - PROBABLY_PRIME) - -from Cryptodome.PublicKey import (_expand_subject_public_key_info, - _create_subject_public_key_info, - _extract_subject_public_key_info) +from Cryptodome.Math.Primality import ( + test_probable_prime, + COMPOSITE, + PROBABLY_PRIME, +) + +from Cryptodome.PublicKey import ( + _expand_subject_public_key_info, + _create_subject_public_key_info, + _extract_subject_public_key_info, +) # ; The following ASN.1 types are relevant for DSA # @@ -75,464 +79,489 @@ # } # + class DsaKey(object): - r"""Class defining an actual DSA key. - Do not instantiate directly. - Use :func:`generate`, :func:`construct` or :func:`import_key` instead. - - :ivar p: DSA modulus - :vartype p: integer + r"""Class defining an actual DSA key. + Do not instantiate directly. + Use :func:`generate`, :func:`construct` or :func:`import_key` instead. + + :ivar p: DSA modulus + :vartype p: integer + + :ivar q: Order of the subgroup + :vartype q: integer - :ivar q: Order of the subgroup - :vartype q: integer + :ivar g: Generator + :vartype g: integer + + :ivar y: Public key + :vartype y: integer - :ivar g: Generator - :vartype g: integer + :ivar x: Private key + :vartype x: integer - :ivar y: Public key - :vartype y: integer - - :ivar x: Private key - :vartype x: integer - - :undocumented: exportKey, publickey - """ - - _keydata = ['y', 'g', 'p', 'q', 'x'] - - def __init__(self, key_dict): - input_set = set(key_dict.keys()) - public_set = set(('y' , 'g', 'p', 'q')) - if not public_set.issubset(input_set): - raise ValueError("Some DSA components are missing = %s" % - str(public_set - input_set)) - extra_set = input_set - public_set - if extra_set and extra_set != set(('x',)): - raise ValueError("Unknown DSA components = %s" % - str(extra_set - set(('x',)))) - self._key = dict(key_dict) - - def _sign(self, m, k): - if not self.has_private(): - raise TypeError("DSA public key cannot be used for signing") - if not (1 < k < self.q): - raise ValueError("k is not between 2 and q-1") - - x, q, p, g = [self._key[comp] for comp in ['x', 'q', 'p', 'g']] - - blind_factor = Integer.random_range(min_inclusive=1, - max_exclusive=q) - inv_blind_k = (blind_factor * k).inverse(q) - blind_x = x * blind_factor - - r = pow(g, k, p) % q # r = (g**k mod p) mod q - s = (inv_blind_k * (blind_factor * m + blind_x * r)) % q - return map(int, (r, s)) - - def _verify(self, m, sig): - r, s = sig - y, q, p, g = [self._key[comp] for comp in ['y', 'q', 'p', 'g']] - if not (0 < r < q) or not (0 < s < q): - return False - w = Integer(s).inverse(q) - u1 = (w * m) % q - u2 = (w * r) % q - v = (pow(g, u1, p) * pow(y, u2, p) % p) % q - return v == r - - def has_private(self): - """Whether this is a DSA private key""" - - return 'x' in self._key - - def can_encrypt(self): # legacy - return False - - def can_sign(self): # legacy - return True - - def public_key(self): - """A matching DSA public key. - - Returns: - a new :class:`DsaKey` object - """ - - public_components = dict((k, self._key[k]) for k in ('y', 'g', 'p', 'q')) - return DsaKey(public_components) - - def __eq__(self, other): - if bool(self.has_private()) != bool(other.has_private()): - return False - - result = True - for comp in self._keydata: - result = result and (getattr(self._key, comp, None) == - getattr(other._key, comp, None)) - return result - - def __ne__(self, other): - return not self.__eq__(other) - - def __getstate__(self): - # DSA key is not pickable - from pickle import PicklingError - raise PicklingError - - def domain(self): - """The DSA domain parameters. - - Returns - tuple : (p,q,g) - """ - - return [int(self._key[comp]) for comp in ('p', 'q', 'g')] - - def __repr__(self): - attrs = [] - for k in self._keydata: - if k == 'p': - bits = Integer(self.p).size_in_bits() - attrs.append("p(%d)" % (bits,)) - elif hasattr(self, k): - attrs.append(k) - if self.has_private(): - attrs.append("private") - # PY3K: This is meant to be text, do not change to bytes (data) - return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs)) - - def __getattr__(self, item): - try: - return int(self._key[item]) - except KeyError: - raise AttributeError(item) - - def export_key(self, format='PEM', pkcs8=None, passphrase=None, - protection=None, randfunc=None): - """Export this DSA key. - - Args: - format (string): - The encoding for the output: - - - *'PEM'* (default). ASCII as per `RFC1421`_/ `RFC1423`_. - - *'DER'*. Binary ASN.1 encoding. - - *'OpenSSH'*. ASCII one-liner as per `RFC4253`_. - Only suitable for public keys, not for private keys. - - passphrase (string): - *Private keys only*. The pass phrase to protect the output. - - pkcs8 (boolean): - *Private keys only*. If ``True`` (default), the key is encoded - with `PKCS#8`_. If ``False``, it is encoded in the custom - OpenSSL/OpenSSH container. - - protection (string): - *Only in combination with a pass phrase*. - The encryption scheme to use to protect the output. - - If :data:`pkcs8` takes value ``True``, this is the PKCS#8 - algorithm to use for deriving the secret and encrypting - the private DSA key. - For a complete list of algorithms, see :mod:`Cryptodome.IO.PKCS8`. - The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*. - - If :data:`pkcs8` is ``False``, the obsolete PEM encryption scheme is - used. It is based on MD5 for key derivation, and Triple DES for - encryption. Parameter :data:`protection` is then ignored. - - The combination ``format='DER'`` and ``pkcs8=False`` is not allowed - if a passphrase is present. - - randfunc (callable): - A function that returns random bytes. - By default it is :func:`Cryptodome.Random.get_random_bytes`. - - Returns: - byte string : the encoded key - - Raises: - ValueError : when the format is unknown or when you try to encrypt a private - key with *DER* format and OpenSSL/OpenSSH. - - .. warning:: - If you don't provide a pass phrase, the private key will be - exported in the clear! - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - """ - - if passphrase is not None: - passphrase = tobytes(passphrase) - - if randfunc is None: - randfunc = Random.get_random_bytes - - if format == 'OpenSSH': - tup1 = [self._key[x].to_bytes() for x in ('p', 'q', 'g', 'y')] - - def func(x): - if (bord(x[0]) & 0x80): - return bchr(0) + x - else: - return x - - tup2 = [func(x) for x in tup1] - keyparts = [b'ssh-dss'] + tup2 - keystring = b''.join( - [struct.pack(">I", len(kp)) + kp for kp in keyparts] - ) - return b'ssh-dss ' + binascii.b2a_base64(keystring)[:-1] - - # DER format is always used, even in case of PEM, which simply - # encodes it into BASE64. - params = DerSequence([self.p, self.q, self.g]) - if self.has_private(): - if pkcs8 is None: - pkcs8 = True - if pkcs8: - if not protection: - protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' - private_key = DerInteger(self.x).encode() - binary_key = PKCS8.wrap( - private_key, oid, passphrase, - protection, key_params=params, - randfunc=randfunc - ) - if passphrase: - key_type = 'ENCRYPTED PRIVATE' - else: - key_type = 'PRIVATE' - passphrase = None - else: - if format != 'PEM' and passphrase: - raise ValueError("DSA private key cannot be encrypted") - ints = [0, self.p, self.q, self.g, self.y, self.x] - binary_key = DerSequence(ints).encode() - key_type = "DSA PRIVATE" - else: - if pkcs8: - raise ValueError("PKCS#8 is only meaningful for private keys") - - binary_key = _create_subject_public_key_info(oid, - DerInteger(self.y), params) - key_type = "PUBLIC" - - if format == 'DER': - return binary_key - if format == 'PEM': - pem_str = PEM.encode( - binary_key, key_type + " KEY", - passphrase, randfunc - ) - return tobytes(pem_str) - raise ValueError("Unknown key format '%s'. Cannot export the DSA key." % format) - - # Backward-compatibility - exportKey = export_key - publickey = public_key - - # Methods defined in PyCryptodome that we don't support anymore - - def sign(self, M, K): - raise NotImplementedError("Use module Cryptodome.Signature.DSS instead") - - def verify(self, M, signature): - raise NotImplementedError("Use module Cryptodome.Signature.DSS instead") - - def encrypt(self, plaintext, K): - raise NotImplementedError - - def decrypt(self, ciphertext): - raise NotImplementedError - - def blind(self, M, B): - raise NotImplementedError - - def unblind(self, M, B): - raise NotImplementedError - - def size(self): - raise NotImplementedError + :undocumented: exportKey, publickey + """ + + _keydata = ["y", "g", "p", "q", "x"] + + def __init__(self, key_dict): + input_set = set(key_dict.keys()) + public_set = set(("y", "g", "p", "q")) + if not public_set.issubset(input_set): + raise ValueError( + "Some DSA components are missing = %s" % str(public_set - input_set), + ) + extra_set = input_set - public_set + if extra_set and extra_set != set(("x",)): + raise ValueError( + "Unknown DSA components = %s" % str(extra_set - set(("x",))), + ) + self._key = dict(key_dict) + + def _sign(self, m, k): + if not self.has_private(): + raise TypeError("DSA public key cannot be used for signing") + if not (1 < k < self.q): + raise ValueError("k is not between 2 and q-1") + + x, q, p, g = [self._key[comp] for comp in ["x", "q", "p", "g"]] + + blind_factor = Integer.random_range( + min_inclusive=1, + max_exclusive=q, + ) + inv_blind_k = (blind_factor * k).inverse(q) + blind_x = x * blind_factor + + r = pow(g, k, p) % q # r = (g**k mod p) mod q + s = (inv_blind_k * (blind_factor * m + blind_x * r)) % q + return map(int, (r, s)) + + def _verify(self, m, sig): + r, s = sig + y, q, p, g = [self._key[comp] for comp in ["y", "q", "p", "g"]] + if not (0 < r < q) or not (0 < s < q): + return False + w = Integer(s).inverse(q) + u1 = (w * m) % q + u2 = (w * r) % q + v = (pow(g, u1, p) * pow(y, u2, p) % p) % q + return v == r + + def has_private(self): + """Whether this is a DSA private key""" + + return "x" in self._key + + def can_encrypt(self): # legacy + return False + + def can_sign(self): # legacy + return True + + def public_key(self): + """A matching DSA public key. + + Returns: + a new :class:`DsaKey` object + """ + + public_components = dict((k, self._key[k]) for k in ("y", "g", "p", "q")) + return DsaKey(public_components) + + def __eq__(self, other): + if bool(self.has_private()) != bool(other.has_private()): + return False + + result = True + for comp in self._keydata: + result = result and (getattr(self._key, comp, None) == getattr(other._key, comp, None)) + return result + + def __ne__(self, other): + return not self.__eq__(other) + + def __getstate__(self): + # DSA key is not pickable + from pickle import PicklingError + + raise PicklingError + + def domain(self): + """The DSA domain parameters. + + Returns + tuple : (p,q,g) + """ + + return [int(self._key[comp]) for comp in ("p", "q", "g")] + + def __repr__(self): + attrs = [] + for k in self._keydata: + if k == "p": + bits = Integer(self.p).size_in_bits() + attrs.append("p(%d)" % (bits,)) + elif hasattr(self, k): + attrs.append(k) + if self.has_private(): + attrs.append("private") + # PY3K: This is meant to be text, do not change to bytes (data) + return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs)) + + def __getattr__(self, item): + try: + return int(self._key[item]) + except KeyError: + raise AttributeError(item) + + def export_key( + self, + format="PEM", + pkcs8=None, + passphrase=None, + protection=None, + randfunc=None, + ): + """Export this DSA key. + + Args: + format (string): + The encoding for the output: + + - *'PEM'* (default). ASCII as per `RFC1421`_/ `RFC1423`_. + - *'DER'*. Binary ASN.1 encoding. + - *'OpenSSH'*. ASCII one-liner as per `RFC4253`_. + Only suitable for public keys, not for private keys. + + passphrase (string): + *Private keys only*. The pass phrase to protect the output. + + pkcs8 (boolean): + *Private keys only*. If ``True`` (default), the key is encoded + with `PKCS#8`_. If ``False``, it is encoded in the custom + OpenSSL/OpenSSH container. + + protection (string): + *Only in combination with a pass phrase*. + The encryption scheme to use to protect the output. + + If :data:`pkcs8` takes value ``True``, this is the PKCS#8 + algorithm to use for deriving the secret and encrypting + the private DSA key. + For a complete list of algorithms, see :mod:`Cryptodome.IO.PKCS8`. + The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*. + + If :data:`pkcs8` is ``False``, the obsolete PEM encryption scheme is + used. It is based on MD5 for key derivation, and Triple DES for + encryption. Parameter :data:`protection` is then ignored. + + The combination ``format='DER'`` and ``pkcs8=False`` is not allowed + if a passphrase is present. + + randfunc (callable): + A function that returns random bytes. + By default it is :func:`Cryptodome.Random.get_random_bytes`. + + Returns: + byte string : the encoded key + + Raises: + ValueError : when the format is unknown or when you try to encrypt a private + key with *DER* format and OpenSSL/OpenSSH. + + .. warning:: + If you don't provide a pass phrase, the private key will be + exported in the clear! + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt + .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + """ + + if passphrase is not None: + passphrase = tobytes(passphrase) + + if randfunc is None: + randfunc = Random.get_random_bytes + + if format == "OpenSSH": + tup1 = [self._key[x].to_bytes() for x in ("p", "q", "g", "y")] + + def func(x): + if bord(x[0]) & 0x80: + return bchr(0) + x + else: + return x + + tup2 = [func(x) for x in tup1] + keyparts = [b"ssh-dss"] + tup2 + keystring = b"".join( + [struct.pack(">I", len(kp)) + kp for kp in keyparts], + ) + return b"ssh-dss " + binascii.b2a_base64(keystring)[:-1] + + # DER format is always used, even in case of PEM, which simply + # encodes it into BASE64. + params = DerSequence([self.p, self.q, self.g]) + if self.has_private(): + if pkcs8 is None: + pkcs8 = True + if pkcs8: + if not protection: + protection = "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC" + private_key = DerInteger(self.x).encode() + binary_key = PKCS8.wrap( + private_key, + oid, + passphrase, + protection, + key_params=params, + randfunc=randfunc, + ) + if passphrase: + key_type = "ENCRYPTED PRIVATE" + else: + key_type = "PRIVATE" + passphrase = None + else: + if format != "PEM" and passphrase: + raise ValueError("DSA private key cannot be encrypted") + ints = [0, self.p, self.q, self.g, self.y, self.x] + binary_key = DerSequence(ints).encode() + key_type = "DSA PRIVATE" + else: + if pkcs8: + raise ValueError("PKCS#8 is only meaningful for private keys") + + binary_key = _create_subject_public_key_info( + oid, + DerInteger(self.y), + params, + ) + key_type = "PUBLIC" + + if format == "DER": + return binary_key + if format == "PEM": + pem_str = PEM.encode( + binary_key, + key_type + " KEY", + passphrase, + randfunc, + ) + return tobytes(pem_str) + raise ValueError("Unknown key format '%s'. Cannot export the DSA key." % format) + + # Backward-compatibility + exportKey = export_key + publickey = public_key + + # Methods defined in PyCryptodome that we don't support anymore + + def sign(self, M, K): + raise NotImplementedError("Use module Cryptodome.Signature.DSS instead") + + def verify(self, M, signature): + raise NotImplementedError("Use module Cryptodome.Signature.DSS instead") + + def encrypt(self, plaintext, K): + raise NotImplementedError + + def decrypt(self, ciphertext): + raise NotImplementedError + + def blind(self, M, B): + raise NotImplementedError + + def unblind(self, M, B): + raise NotImplementedError + + def size(self): + raise NotImplementedError def _generate_domain(L, randfunc): - """Generate a new set of DSA domain parameters""" - - N = { 1024:160, 2048:224, 3072:256 }.get(L) - if N is None: - raise ValueError("Invalid modulus length (%d)" % L) - - outlen = SHA256.digest_size * 8 - n = (L + outlen - 1) // outlen - 1 # ceil(L/outlen) -1 - b_ = L - 1 - (n * outlen) - - # Generate q (A.1.1.2) - q = Integer(4) - upper_bit = 1 << (N - 1) - while test_probable_prime(q, randfunc) != PROBABLY_PRIME: - seed = randfunc(64) - U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1) - q = U | upper_bit | 1 - - assert(q.size_in_bits() == N) - - # Generate p (A.1.1.2) - offset = 1 - upper_bit = 1 << (L - 1) - while True: - V = [ SHA256.new(seed + Integer(offset + j).to_bytes()).digest() - for j in iter_range(n + 1) ] - V = [ Integer.from_bytes(v) for v in V ] - W = sum([V[i] * (1 << (i * outlen)) for i in iter_range(n)], - (V[n] & ((1 << b_) - 1)) * (1 << (n * outlen))) - - X = Integer(W + upper_bit) # 2^{L-1} < X < 2^{L} - assert(X.size_in_bits() == L) - - c = X % (q * 2) - p = X - (c - 1) # 2q divides (p-1) - if p.size_in_bits() == L and \ - test_probable_prime(p, randfunc) == PROBABLY_PRIME: - break - offset += n + 1 - - # Generate g (A.2.3, index=1) - e = (p - 1) // q - for count in itertools.count(1): - U = seed + b"ggen" + bchr(1) + Integer(count).to_bytes() - W = Integer.from_bytes(SHA256.new(U).digest()) - g = pow(W, e, p) - if g != 1: - break - - return (p, q, g, seed) + """Generate a new set of DSA domain parameters""" + + N = {1024: 160, 2048: 224, 3072: 256}.get(L) + if N is None: + raise ValueError("Invalid modulus length (%d)" % L) + + outlen = SHA256.digest_size * 8 + n = (L + outlen - 1) // outlen - 1 # ceil(L/outlen) -1 + b_ = L - 1 - (n * outlen) + + # Generate q (A.1.1.2) + q = Integer(4) + upper_bit = 1 << (N - 1) + while test_probable_prime(q, randfunc) != PROBABLY_PRIME: + seed = randfunc(64) + U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1) + q = U | upper_bit | 1 + + assert q.size_in_bits() == N + + # Generate p (A.1.1.2) + offset = 1 + upper_bit = 1 << (L - 1) + while True: + V = [SHA256.new(seed + Integer(offset + j).to_bytes()).digest() for j in iter_range(n + 1)] + V = [Integer.from_bytes(v) for v in V] + W = sum( + [V[i] * (1 << (i * outlen)) for i in iter_range(n)], + (V[n] & ((1 << b_) - 1)) * (1 << (n * outlen)), + ) + + X = Integer(W + upper_bit) # 2^{L-1} < X < 2^{L} + assert X.size_in_bits() == L + + c = X % (q * 2) + p = X - (c - 1) # 2q divides (p-1) + if p.size_in_bits() == L and test_probable_prime(p, randfunc) == PROBABLY_PRIME: + break + offset += n + 1 + + # Generate g (A.2.3, index=1) + e = (p - 1) // q + for count in itertools.count(1): + U = seed + b"ggen" + bchr(1) + Integer(count).to_bytes() + W = Integer.from_bytes(SHA256.new(U).digest()) + g = pow(W, e, p) + if g != 1: + break + + return (p, q, g, seed) def generate(bits, randfunc=None, domain=None): - """Generate a new DSA key pair. - - The algorithm follows Appendix A.1/A.2 and B.1 of `FIPS 186-4`_, - respectively for domain generation and key pair generation. - - Args: - bits (integer): - Key length, or size (in bits) of the DSA modulus *p*. - It must be 1024, 2048 or 3072. - - randfunc (callable): - Random number generation function; it accepts a single integer N - and return a string of random data N bytes long. - If not specified, :func:`Cryptodome.Random.get_random_bytes` is used. - - domain (tuple): - The DSA domain parameters *p*, *q* and *g* as a list of 3 - integers. Size of *p* and *q* must comply to `FIPS 186-4`_. - If not specified, the parameters are created anew. - - Returns: - :class:`DsaKey` : a new DSA key object - - Raises: - ValueError : when **bits** is too little, too big, or not a multiple of 64. - - .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if randfunc is None: - randfunc = Random.get_random_bytes - - if domain: - p, q, g = map(Integer, domain) - - ## Perform consistency check on domain parameters - # P and Q must be prime - fmt_error = test_probable_prime(p) == COMPOSITE - fmt_error |= test_probable_prime(q) == COMPOSITE - # Verify Lagrange's theorem for sub-group - fmt_error |= ((p - 1) % q) != 0 - fmt_error |= g <= 1 or g >= p - fmt_error |= pow(g, q, p) != 1 - if fmt_error: - raise ValueError("Invalid DSA domain parameters") - else: - p, q, g, _ = _generate_domain(bits, randfunc) - - L = p.size_in_bits() - N = q.size_in_bits() - - if L != bits: - raise ValueError("Mismatch between size of modulus (%d)" - " and 'bits' parameter (%d)" % (L, bits)) - - if (L, N) not in [(1024, 160), (2048, 224), - (2048, 256), (3072, 256)]: - raise ValueError("Lengths of p and q (%d, %d) are not compatible" - "to FIPS 186-3" % (L, N)) - - if not 1 < g < p: - raise ValueError("Incorrent DSA generator") - - # B.1.1 - c = Integer.random(exact_bits=N + 64, randfunc=randfunc) - x = c % (q - 1) + 1 # 1 <= x <= q-1 - y = pow(g, x, p) - - key_dict = { 'y':y, 'g':g, 'p':p, 'q':q, 'x':x } - return DsaKey(key_dict) + """Generate a new DSA key pair. + + The algorithm follows Appendix A.1/A.2 and B.1 of `FIPS 186-4`_, + respectively for domain generation and key pair generation. + + Args: + bits (integer): + Key length, or size (in bits) of the DSA modulus *p*. + It must be 1024, 2048 or 3072. + + randfunc (callable): + Random number generation function; it accepts a single integer N + and return a string of random data N bytes long. + If not specified, :func:`Cryptodome.Random.get_random_bytes` is used. + + domain (tuple): + The DSA domain parameters *p*, *q* and *g* as a list of 3 + integers. Size of *p* and *q* must comply to `FIPS 186-4`_. + If not specified, the parameters are created anew. + + Returns: + :class:`DsaKey` : a new DSA key object + + Raises: + ValueError : when **bits** is too little, too big, or not a multiple of 64. + + .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ + + if randfunc is None: + randfunc = Random.get_random_bytes + + if domain: + p, q, g = map(Integer, domain) + + ## Perform consistency check on domain parameters + # P and Q must be prime + fmt_error = test_probable_prime(p) == COMPOSITE + fmt_error |= test_probable_prime(q) == COMPOSITE + # Verify Lagrange's theorem for sub-group + fmt_error |= ((p - 1) % q) != 0 + fmt_error |= g <= 1 or g >= p + fmt_error |= pow(g, q, p) != 1 + if fmt_error: + raise ValueError("Invalid DSA domain parameters") + else: + p, q, g, _ = _generate_domain(bits, randfunc) + + L = p.size_in_bits() + N = q.size_in_bits() + + if L != bits: + raise ValueError( + "Mismatch between size of modulus (%d) and 'bits' parameter (%d)" % (L, bits), + ) + + if (L, N) not in [ + (1024, 160), + (2048, 224), + (2048, 256), + (3072, 256), + ]: + raise ValueError( + "Lengths of p and q (%d, %d) are not compatibleto FIPS 186-3" % (L, N), + ) + + if not 1 < g < p: + raise ValueError("Incorrent DSA generator") + + # B.1.1 + c = Integer.random(exact_bits=N + 64, randfunc=randfunc) + x = c % (q - 1) + 1 # 1 <= x <= q-1 + y = pow(g, x, p) + + key_dict = {"y": y, "g": g, "p": p, "q": q, "x": x} + return DsaKey(key_dict) def construct(tup, consistency_check=True): - """Construct a DSA key from a tuple of valid DSA components. - - Args: - tup (tuple): - A tuple of long integers, with 4 or 5 items - in the following order: - - 1. Public key (*y*). - 2. Sub-group generator (*g*). - 3. Modulus, finite field order (*p*). - 4. Sub-group order (*q*). - 5. Private key (*x*). Optional. - - consistency_check (boolean): - If ``True``, the library will verify that the provided components - fulfil the main DSA properties. - - Raises: - ValueError: when the key being imported fails the most basic DSA validity checks. - - Returns: - :class:`DsaKey` : a DSA key object - """ - - key_dict = dict(zip(('y', 'g', 'p', 'q', 'x'), map(Integer, tup))) - key = DsaKey(key_dict) - - fmt_error = False - if consistency_check: - # P and Q must be prime - fmt_error = test_probable_prime(key.p) == COMPOSITE - fmt_error |= test_probable_prime(key.q) == COMPOSITE - # Verify Lagrange's theorem for sub-group - fmt_error |= ((key.p - 1) % key.q) != 0 - fmt_error |= key.g <= 1 or key.g >= key.p - fmt_error |= pow(key.g, key.q, key.p) != 1 - # Public key - fmt_error |= key.y <= 0 or key.y >= key.p - if hasattr(key, 'x'): - fmt_error |= key.x <= 0 or key.x >= key.q - fmt_error |= pow(key.g, key.x, key.p) != key.y - - if fmt_error: - raise ValueError("Invalid DSA key components") - - return key + """Construct a DSA key from a tuple of valid DSA components. + + Args: + tup (tuple): + A tuple of long integers, with 4 or 5 items + in the following order: + + 1. Public key (*y*). + 2. Sub-group generator (*g*). + 3. Modulus, finite field order (*p*). + 4. Sub-group order (*q*). + 5. Private key (*x*). Optional. + + consistency_check (boolean): + If ``True``, the library will verify that the provided components + fulfil the main DSA properties. + + Raises: + ValueError: when the key being imported fails the most basic DSA validity checks. + + Returns: + :class:`DsaKey` : a DSA key object + """ + + key_dict = dict(zip(("y", "g", "p", "q", "x"), map(Integer, tup))) + key = DsaKey(key_dict) + + fmt_error = False + if consistency_check: + # P and Q must be prime + fmt_error = test_probable_prime(key.p) == COMPOSITE + fmt_error |= test_probable_prime(key.q) == COMPOSITE + # Verify Lagrange's theorem for sub-group + fmt_error |= ((key.p - 1) % key.q) != 0 + fmt_error |= key.g <= 1 or key.g >= key.p + fmt_error |= pow(key.g, key.q, key.p) != 1 + # Public key + fmt_error |= key.y <= 0 or key.y >= key.p + if hasattr(key, "x"): + fmt_error |= key.x <= 0 or key.x >= key.q + fmt_error |= pow(key.g, key.x, key.p) != key.y + + if fmt_error: + raise ValueError("Invalid DSA key components") + + return key # Dss-Parms ::= SEQUENCE { @@ -542,133 +571,134 @@ def construct(tup, consistency_check=True): # } # DSAPublicKey ::= INTEGER -- public key, y + def _import_openssl_private(encoded, passphrase, params): - if params: - raise ValueError("DSA private key already comes with parameters") - der = DerSequence().decode(encoded, nr_elements=6, only_ints_expected=True) - if der[0] != 0: - raise ValueError("No version found") - tup = [der[comp] for comp in (4, 3, 1, 2, 5)] - return construct(tup) + if params: + raise ValueError("DSA private key already comes with parameters") + der = DerSequence().decode(encoded, nr_elements=6, only_ints_expected=True) + if der[0] != 0: + raise ValueError("No version found") + tup = [der[comp] for comp in (4, 3, 1, 2, 5)] + return construct(tup) def _import_subjectPublicKeyInfo(encoded, passphrase, params): + algoid, encoded_key, emb_params = _expand_subject_public_key_info(encoded) + if algoid != oid: + raise ValueError("No DSA subjectPublicKeyInfo") + if params and emb_params: + raise ValueError("Too many DSA parameters") - algoid, encoded_key, emb_params = _expand_subject_public_key_info(encoded) - if algoid != oid: - raise ValueError("No DSA subjectPublicKeyInfo") - if params and emb_params: - raise ValueError("Too many DSA parameters") - - y = DerInteger().decode(encoded_key).value - p, q, g = list(DerSequence().decode(params or emb_params)) - tup = (y, g, p, q) - return construct(tup) + y = DerInteger().decode(encoded_key).value + p, q, g = list(DerSequence().decode(params or emb_params)) + tup = (y, g, p, q) + return construct(tup) def _import_x509_cert(encoded, passphrase, params): - - sp_info = _extract_subject_public_key_info(encoded) - return _import_subjectPublicKeyInfo(sp_info, None, params) + sp_info = _extract_subject_public_key_info(encoded) + return _import_subjectPublicKeyInfo(sp_info, None, params) def _import_pkcs8(encoded, passphrase, params): - if params: - raise ValueError("PKCS#8 already includes parameters") - k = PKCS8.unwrap(encoded, passphrase) - if k[0] != oid: - raise ValueError("No PKCS#8 encoded DSA key") - x = DerInteger().decode(k[1]).value - p, q, g = list(DerSequence().decode(k[2])) - tup = (pow(g, x, p), g, p, q, x) - return construct(tup) + if params: + raise ValueError("PKCS#8 already includes parameters") + k = PKCS8.unwrap(encoded, passphrase) + if k[0] != oid: + raise ValueError("No PKCS#8 encoded DSA key") + x = DerInteger().decode(k[1]).value + p, q, g = list(DerSequence().decode(k[2])) + tup = (pow(g, x, p), g, p, q, x) + return construct(tup) def _import_key_der(key_data, passphrase, params): - """Import a DSA key (public or private half), encoded in DER form.""" + """Import a DSA key (public or private half), encoded in DER form.""" - decodings = (_import_openssl_private, - _import_subjectPublicKeyInfo, - _import_x509_cert, - _import_pkcs8) + decodings = ( + _import_openssl_private, + _import_subjectPublicKeyInfo, + _import_x509_cert, + _import_pkcs8, + ) - for decoding in decodings: - try: - return decoding(key_data, passphrase, params) - except ValueError: - pass + for decoding in decodings: + try: + return decoding(key_data, passphrase, params) + except ValueError: + pass - raise ValueError("DSA key format is not supported") + raise ValueError("DSA key format is not supported") def import_key(extern_key, passphrase=None): - """Import a DSA key. + """Import a DSA key. - Args: - extern_key (string or byte string): - The DSA key to import. + Args: + extern_key (string or byte string): + The DSA key to import. - The following formats are supported for a DSA **public** key: + The following formats are supported for a DSA **public** key: - - X.509 certificate (binary DER or PEM) - - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM) - - OpenSSH (ASCII one-liner, see `RFC4253`_) + - X.509 certificate (binary DER or PEM) + - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM) + - OpenSSH (ASCII one-liner, see `RFC4253`_) - The following formats are supported for a DSA **private** key: + The following formats are supported for a DSA **private** key: - - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` - DER SEQUENCE (binary or PEM) - - OpenSSL/OpenSSH custom format (binary or PEM) + - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` + DER SEQUENCE (binary or PEM) + - OpenSSL/OpenSSH custom format (binary or PEM) - For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. + For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. - passphrase (string): - In case of an encrypted private key, this is the pass phrase - from which the decryption key is derived. + passphrase (string): + In case of an encrypted private key, this is the pass phrase + from which the decryption key is derived. - Encryption may be applied either at the `PKCS#8`_ or at the PEM level. + Encryption may be applied either at the `PKCS#8`_ or at the PEM level. - Returns: - :class:`DsaKey` : a DSA key object + Returns: + :class:`DsaKey` : a DSA key object - Raises: - ValueError : when the given key cannot be parsed (possibly because - the pass phrase is wrong). + Raises: + ValueError : when the given key cannot be parsed (possibly because + the pass phrase is wrong). - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt - .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt - """ + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt + .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt + """ - extern_key = tobytes(extern_key) - if passphrase is not None: - passphrase = tobytes(passphrase) + extern_key = tobytes(extern_key) + if passphrase is not None: + passphrase = tobytes(passphrase) - if extern_key.startswith(b'-----'): - # This is probably a PEM encoded key - (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) - if enc_flag: - passphrase = None - return _import_key_der(der, passphrase, None) + if extern_key.startswith(b"-----"): + # This is probably a PEM encoded key + (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) + if enc_flag: + passphrase = None + return _import_key_der(der, passphrase, None) - if extern_key.startswith(b'ssh-dss '): - # This is probably a public OpenSSH key - keystring = binascii.a2b_base64(extern_key.split(b' ')[1]) - keyparts = [] - while len(keystring) > 4: - length = struct.unpack(">I", keystring[:4])[0] - keyparts.append(keystring[4:4 + length]) - keystring = keystring[4 + length:] - if keyparts[0] == b"ssh-dss": - tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)] - return construct(tup) + if extern_key.startswith(b"ssh-dss "): + # This is probably a public OpenSSH key + keystring = binascii.a2b_base64(extern_key.split(b" ")[1]) + keyparts = [] + while len(keystring) > 4: + length = struct.unpack(">I", keystring[:4])[0] + keyparts.append(keystring[4 : 4 + length]) + keystring = keystring[4 + length :] + if keyparts[0] == b"ssh-dss": + tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)] + return construct(tup) - if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: - # This is probably a DER encoded key - return _import_key_der(extern_key, passphrase, None) + if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: + # This is probably a DER encoded key + return _import_key_der(extern_key, passphrase, None) - raise ValueError("DSA key format is not supported") + raise ValueError("DSA key format is not supported") # Backward compatibility diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/DSA.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/DSA.pyi index 354ac1f0..92db8596 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/DSA.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/DSA.pyi @@ -1,30 +1,42 @@ from typing import Dict, Tuple, Callable, Union, Optional -__all__ = ['generate', 'construct', 'DsaKey', 'import_key' ] +__all__ = ["generate", "construct", "DsaKey", "import_key"] RNG = Callable[[int], bytes] class DsaKey(object): - def __init__(self, key_dict: Dict[str, int]) -> None: ... - def has_private(self) -> bool: ... - def can_encrypt(self) -> bool: ... # legacy - def can_sign(self) -> bool: ... # legacy - def public_key(self) -> DsaKey: ... - def __eq__(self, other: object) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __getstate__(self) -> None: ... - def domain(self) -> Tuple[int, int, int]: ... - def __repr__(self) -> str: ... - def __getattr__(self, item: str) -> int: ... - def export_key(self, format: Optional[str]="PEM", pkcs8: Optional[bool]=None, passphrase: Optional[str]=None, - protection: Optional[str]=None, randfunc: Optional[RNG]=None) -> bytes: ... - # Backward-compatibility - exportKey = export_key - publickey = public_key + def __init__(self, key_dict: Dict[str, int]) -> None: ... + def has_private(self) -> bool: ... + def can_encrypt(self) -> bool: ... # legacy + def can_sign(self) -> bool: ... # legacy + def public_key(self) -> DsaKey: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def __getstate__(self) -> None: ... + def domain(self) -> Tuple[int, int, int]: ... + def __repr__(self) -> str: ... + def __getattr__(self, item: str) -> int: ... + def export_key( + self, + format: Optional[str] = "PEM", + pkcs8: Optional[bool] = None, + passphrase: Optional[str] = None, + protection: Optional[str] = None, + randfunc: Optional[RNG] = None, + ) -> bytes: ... + # Backward-compatibility + exportKey = export_key + publickey = public_key + +def generate( + bits: int, randfunc: Optional[RNG] = None, domain: Optional[Tuple[int, int, int]] = None +) -> DsaKey: ... +def construct( + tup: Union[Tuple[int, int, int, int], Tuple[int, int, int, int, int]], + consistency_check: Optional[bool] = True, +) -> DsaKey: ... +def import_key(extern_key: Union[str, bytes], passphrase: Optional[str] = None) -> DsaKey: ... -def generate(bits: int, randfunc: Optional[RNG]=None, domain: Optional[Tuple[int, int, int]]=None) -> DsaKey: ... -def construct(tup: Union[Tuple[int, int, int, int], Tuple[int, int, int, int, int]], consistency_check: Optional[bool]=True) -> DsaKey: ... -def import_key(extern_key: Union[str, bytes], passphrase: Optional[str]=None) -> DsaKey: ... # Backward compatibility importKey = import_key diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ECC.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ECC.py index bd9c8cb8..48dd9ff4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ECC.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ECC.py @@ -37,12 +37,18 @@ from Cryptodome.Util.py3compat import bord, tobytes, tostr, bchr, is_string from Cryptodome.Math.Numbers import Integer -from Cryptodome.Util.asn1 import (DerObjectId, DerOctetString, DerSequence, - DerBitString) - -from Cryptodome.PublicKey import (_expand_subject_public_key_info, - _create_subject_public_key_info, - _extract_subject_public_key_info) +from Cryptodome.Util.asn1 import ( + DerObjectId, + DerOctetString, + DerSequence, + DerBitString, +) + +from Cryptodome.PublicKey import ( + _expand_subject_public_key_info, + _create_subject_public_key_info, + _extract_subject_public_key_info, +) from Cryptodome.Hash import SHA512, SHAKE256 @@ -53,1290 +59,1294 @@ class UnsupportedEccFeature(ValueError): - pass + pass class EccKey(object): - r"""Class defining an ECC key. - Do not instantiate directly. - Use :func:`generate`, :func:`construct` or :func:`import_key` instead. - - :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. - :vartype curve: string - - :ivar pointQ: an ECC point representing the public component. - :vartype pointQ: :class:`EccPoint` or :class:`EccXPoint` - - :ivar d: A scalar that represents the private component - in NIST P curves. It is smaller than the - order of the generator point. - :vartype d: integer - - :ivar seed: A seed that represents the private component - in Ed22519 (32 bytes), Curve25519 (32 bytes), - Curve448 (56 bytes), Ed448 (57 bytes). - :vartype seed: bytes - """ - - def __init__(self, **kwargs): - """Create a new ECC key - - Keywords: - curve : string - The name of the curve. - d : integer - Mandatory for a private key one NIST P curves. - It must be in the range ``[1..order-1]``. - seed : bytes - Mandatory for a private key on Ed25519 (32 bytes), - Curve25519 (32 bytes), Curve448 (56 bytes) or Ed448 (57 bytes). - point : EccPoint or EccXPoint - Mandatory for a public key. If provided for a private key, - the implementation will NOT check whether it matches ``d``. - - Only one parameter among ``d``, ``seed`` or ``point`` may be used. - """ - - kwargs_ = dict(kwargs) - curve_name = kwargs_.pop("curve", None) - self._d = kwargs_.pop("d", None) - self._seed = kwargs_.pop("seed", None) - self._point = kwargs_.pop("point", None) - if curve_name is None and self._point: - curve_name = self._point.curve - if kwargs_: - raise TypeError("Unknown parameters: " + str(kwargs_)) - - if curve_name not in _curves: - raise ValueError("Unsupported curve (%s)" % curve_name) - self._curve = _curves[curve_name] - self.curve = self._curve.canonical - - count = int(self._d is not None) + int(self._seed is not None) - - if count == 0: - if self._point is None: - raise ValueError("At lest one between parameters 'point', 'd' or 'seed' must be specified") - return - - if count == 2: - raise ValueError("Parameters d and seed are mutually exclusive") - - # NIST P curves work with d, EdDSA works with seed - - # RFC 8032, 5.1.5 - if self._curve.id == _CurveID.ED25519: - if self._d is not None: - raise ValueError("Parameter d can only be used with NIST P curves") - if len(self._seed) != 32: - raise ValueError("Parameter seed must be 32 bytes long for Ed25519") - seed_hash = SHA512.new(self._seed).digest() # h - self._prefix = seed_hash[32:] - tmp = bytearray(seed_hash[:32]) - tmp[0] &= 0xF8 - tmp[31] = (tmp[31] & 0x7F) | 0x40 - self._d = Integer.from_bytes(tmp, byteorder='little') - # RFC 8032, 5.2.5 - elif self._curve.id == _CurveID.ED448: - if self._d is not None: - raise ValueError("Parameter d can only be used with NIST P curves") - if len(self._seed) != 57: - raise ValueError("Parameter seed must be 57 bytes long for Ed448") - seed_hash = SHAKE256.new(self._seed).read(114) # h - self._prefix = seed_hash[57:] - tmp = bytearray(seed_hash[:57]) - tmp[0] &= 0xFC - tmp[55] |= 0x80 - tmp[56] = 0 - self._d = Integer.from_bytes(tmp, byteorder='little') - # RFC 7748, 5 - elif self._curve.id == _CurveID.CURVE25519: - if self._d is not None: - raise ValueError("Parameter d can only be used with NIST P curves") - if len(self._seed) != 32: - raise ValueError("Parameter seed must be 32 bytes long for Curve25519") - tmp = bytearray(self._seed) - tmp[0] &= 0xF8 - tmp[31] = (tmp[31] & 0x7F) | 0x40 - self._d = Integer.from_bytes(tmp, byteorder='little') - elif self._curve.id == _CurveID.CURVE448: - if self._d is not None: - raise ValueError("Parameter d can only be used with NIST P curves") - if len(self._seed) != 56: - raise ValueError("Parameter seed must be 56 bytes long for Curve448") - tmp = bytearray(self._seed) - tmp[0] &= 0xFC - tmp[55] |= 0x80 - self._d = Integer.from_bytes(tmp, byteorder='little') - - else: - if self._seed is not None: - raise ValueError("Parameter 'seed' cannot be used with NIST P-curves") - self._d = Integer(self._d) - if not 1 <= self._d < self._curve.order: - raise ValueError("Parameter d must be an integer smaller than the curve order") - - def __eq__(self, other): - if not isinstance(other, EccKey): - return False - - if other.has_private() != self.has_private(): - return False - - return other.pointQ == self.pointQ - - def __repr__(self): - if self.has_private(): - if self._curve.is_edwards: - extra = ", seed=%s" % tostr(binascii.hexlify(self._seed)) - else: - extra = ", d=%d" % int(self._d) - else: - extra = "" - if self._curve.id in (_CurveID.CURVE25519, - _CurveID.CURVE448): - x = self.pointQ.x - result = "EccKey(curve='%s', point_x=%d%s)" % (self._curve.canonical, x, extra) - else: - x, y = self.pointQ.xy - result = "EccKey(curve='%s', point_x=%d, point_y=%d%s)" % (self._curve.canonical, x, y, extra) - return result - - def has_private(self): - """``True`` if this key can be used for making signatures or decrypting data.""" - - return self._d is not None - - # ECDSA - def _sign(self, z, k): - assert 0 < k < self._curve.order - - order = self._curve.order - blind = Integer.random_range(min_inclusive=1, - max_exclusive=order) - - blind_d = self._d * blind - inv_blind_k = (blind * k).inverse(order) - - r = (self._curve.G * k).x % order - s = inv_blind_k * (blind * z + blind_d * r) % order - return (r, s) - - # ECDSA - def _verify(self, z, rs): - order = self._curve.order - sinv = rs[1].inverse(order) - point1 = self._curve.G * ((sinv * z) % order) - point2 = self.pointQ * ((sinv * rs[0]) % order) - return (point1 + point2).x == rs[0] - - @property - def d(self): - if not self.has_private(): - raise ValueError("This is not a private ECC key") - return self._d - - @property - def seed(self): - if not self.has_private(): - raise ValueError("This is not a private ECC key") - return self._seed - - @property - def pointQ(self): - if self._point is None: - self._point = self._curve.G * self._d - return self._point - - def public_key(self): - """A matching ECC public key. - - Returns: - a new :class:`EccKey` object - """ - - return EccKey(curve=self._curve.canonical, point=self.pointQ) - - def _export_SEC1(self, compress): - if not self._curve.is_weierstrass: - raise ValueError("SEC1 format is only supported for NIST P curves") - - # See 2.2 in RFC5480 and 2.3.3 in SEC1 - # - # The first byte is: - # - 0x02: compressed, only X-coordinate, Y-coordinate is even - # - 0x03: compressed, only X-coordinate, Y-coordinate is odd - # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate - # - # PAI is in theory encoded as 0x00. - - modulus_bytes = self.pointQ.size_in_bytes() - - if compress: - if self.pointQ.y.is_odd(): - first_byte = b'\x03' - else: - first_byte = b'\x02' - public_key = (first_byte + - self.pointQ.x.to_bytes(modulus_bytes)) - else: - public_key = (b'\x04' + - self.pointQ.x.to_bytes(modulus_bytes) + - self.pointQ.y.to_bytes(modulus_bytes)) - return public_key - - def _export_eddsa_public(self): - x, y = self.pointQ.xy - if self._curve.id == _CurveID.ED25519: - result = bytearray(y.to_bytes(32, byteorder='little')) - result[31] = ((x & 1) << 7) | result[31] - elif self._curve.id == _CurveID.ED448: - result = bytearray(y.to_bytes(57, byteorder='little')) - result[56] = (x & 1) << 7 - else: - raise ValueError("Not an EdDSA key to export") - return bytes(result) - - def _export_montgomery_public(self): - if not self._curve.is_montgomery: - raise ValueError("Not a Montgomery key to export") - x = self.pointQ.x - field_size = self.pointQ.size_in_bytes() - result = bytearray(x.to_bytes(field_size, byteorder='little')) - return bytes(result) - - def _export_subjectPublicKeyInfo(self, compress): - if self._curve.is_edwards: - oid = self._curve.oid - public_key = self._export_eddsa_public() - params = None - elif self._curve.is_montgomery: - oid = self._curve.oid - public_key = self._export_montgomery_public() - params = None - else: - oid = "1.2.840.10045.2.1" # unrestricted - public_key = self._export_SEC1(compress) - params = DerObjectId(self._curve.oid) - - return _create_subject_public_key_info(oid, - public_key, - params) - - def _export_rfc5915_private_der(self, include_ec_params=True): - - assert self.has_private() - - # ECPrivateKey ::= SEQUENCE { - # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - # privateKey OCTET STRING, - # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - # publicKey [1] BIT STRING OPTIONAL - # } - - # Public key - uncompressed form - modulus_bytes = self.pointQ.size_in_bytes() - public_key = (b'\x04' + - self.pointQ.x.to_bytes(modulus_bytes) + - self.pointQ.y.to_bytes(modulus_bytes)) - - seq = [1, - DerOctetString(self.d.to_bytes(modulus_bytes)), - DerObjectId(self._curve.oid, explicit=0), - DerBitString(public_key, explicit=1)] - - if not include_ec_params: - del seq[2] - - return DerSequence(seq).encode() - - def _export_pkcs8(self, **kwargs): - from Cryptodome.IO import PKCS8 - - if kwargs.get('passphrase', None) is not None and 'protection' not in kwargs: - raise ValueError("At least the 'protection' parameter must be present") - - if self._seed is not None: - oid = self._curve.oid - private_key = DerOctetString(self._seed).encode() - params = None - else: - oid = "1.2.840.10045.2.1" # unrestricted - private_key = self._export_rfc5915_private_der(include_ec_params=False) - params = DerObjectId(self._curve.oid) - - result = PKCS8.wrap(private_key, - oid, - key_params=params, - **kwargs) - return result - - def _export_public_pem(self, compress): - from Cryptodome.IO import PEM - - encoded_der = self._export_subjectPublicKeyInfo(compress) - return PEM.encode(encoded_der, "PUBLIC KEY") - - def _export_private_pem(self, passphrase, **kwargs): - from Cryptodome.IO import PEM - - encoded_der = self._export_rfc5915_private_der() - return PEM.encode(encoded_der, "EC PRIVATE KEY", passphrase, **kwargs) - - def _export_private_clear_pkcs8_in_clear_pem(self): - from Cryptodome.IO import PEM - - encoded_der = self._export_pkcs8() - return PEM.encode(encoded_der, "PRIVATE KEY") - - def _export_private_encrypted_pkcs8_in_clear_pem(self, passphrase, **kwargs): - from Cryptodome.IO import PEM - - assert passphrase - if 'protection' not in kwargs: - raise ValueError("At least the 'protection' parameter should be present") - encoded_der = self._export_pkcs8(passphrase=passphrase, **kwargs) - return PEM.encode(encoded_der, "ENCRYPTED PRIVATE KEY") - - def _export_openssh(self, compress): - if self.has_private(): - raise ValueError("Cannot export OpenSSH private keys") - - desc = self._curve.openssh - - if desc is None: - raise ValueError("Cannot export %s keys as OpenSSH" % self.curve) - elif desc == "ssh-ed25519": - public_key = self._export_eddsa_public() - comps = (tobytes(desc), tobytes(public_key)) - else: - modulus_bytes = self.pointQ.size_in_bytes() - - if compress: - first_byte = 2 + self.pointQ.y.is_odd() - public_key = (bchr(first_byte) + - self.pointQ.x.to_bytes(modulus_bytes)) - else: - public_key = (b'\x04' + - self.pointQ.x.to_bytes(modulus_bytes) + - self.pointQ.y.to_bytes(modulus_bytes)) - - middle = desc.split("-")[2] - comps = (tobytes(desc), tobytes(middle), public_key) - - blob = b"".join([struct.pack(">I", len(x)) + x for x in comps]) - return desc + " " + tostr(binascii.b2a_base64(blob)) - - def export_key(self, **kwargs): - """Export this ECC key. - - Args: - format (string): - The output format: - - - ``'DER'``. The key will be encoded in ASN.1 DER format (binary). - For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure - defined in `RFC5480`_ will be used. - For a private key, the ASN.1 ``ECPrivateKey`` structure defined - in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope, - see the ``use_pkcs8`` flag below). - - ``'PEM'``. The key will be encoded in a PEM_ envelope (ASCII). - - ``'OpenSSH'``. The key will be encoded in the OpenSSH_ format - (ASCII, public keys only). - - ``'SEC1'``. The public key (i.e., the EC point) will be encoded - into ``bytes`` according to Section 2.3.3 of `SEC1`_ - (which is a subset of the older X9.62 ITU standard). - Only for NIST P-curves. - - ``'raw'``. The public key will be encoded as ``bytes``, - without any metadata. - - * For NIST P-curves: equivalent to ``'SEC1'``. - * For Ed25519 and Ed448: ``bytes`` in the format - defined in `RFC8032`_. - * For Curve25519 and Curve448: ``bytes`` in the format - defined in `RFC7748`_. - - passphrase (bytes or string): - (*Private keys only*) The passphrase to protect the - private key. - - use_pkcs8 (boolean): - (*Private keys only*) - If ``True`` (default and recommended), the `PKCS#8`_ representation - will be used. - It must be ``True`` for Ed25519, Ed448, Curve25519, and Curve448. - - If ``False`` and a passphrase is present, the obsolete PEM - encryption will be used. - - protection (string): - When a private key is exported with password-protection - and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be - present, - For all possible protection schemes, - refer to :ref:`the encryption parameters of PKCS#8`. - It is recommended to use ``'PBKDF2WithHMAC-SHA512AndAES128-CBC'``. - - compress (boolean): - If ``True``, the method returns a more compact representation - of the public key, with the X-coordinate only. - - If ``False`` (default), the method returns the full public key. - - This parameter is ignored for Ed25519/Ed448/Curve25519/Curve448, - as compression is mandatory. - - prot_params (dict): - When a private key is exported with password-protection - and PKCS#8 (both ``DER`` and ``PEM`` formats), this dictionary - contains the parameters to use to derive the encryption key - from the passphrase. - For all possible values, - refer to :ref:`the encryption parameters of PKCS#8`. - The recommendation is to use ``{'iteration_count':21000}`` for PBKDF2, - and ``{'iteration_count':131072}`` for scrypt. - - .. warning:: - If you don't provide a passphrase, the private key will be - exported in the clear! - - .. note:: - When exporting a private key with password-protection and `PKCS#8`_ - (both ``DER`` and ``PEM`` formats), any extra parameters - to ``export_key()`` will be passed to :mod:`Cryptodome.IO.PKCS8`. - - .. _PEM: http://www.ietf.org/rfc/rfc1421.txt - .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt - .. _OpenSSH: http://www.openssh.com/txt/rfc5656.txt - .. _RFC5480: https://tools.ietf.org/html/rfc5480 - .. _SEC1: https://www.secg.org/sec1-v2.pdf - .. _RFC7748: https://tools.ietf.org/html/rfc7748 - - Returns: - A multi-line string (for ``'PEM'`` and ``'OpenSSH'``) or - ``bytes`` (for ``'DER'``, ``'SEC1'``, and ``'raw'``) with the encoded key. - """ - - args = kwargs.copy() - ext_format = args.pop("format") - if ext_format not in ("PEM", "DER", "OpenSSH", "SEC1", "raw"): - raise ValueError("Unknown format '%s'" % ext_format) - - compress = args.pop("compress", False) - - if self.has_private(): - passphrase = args.pop("passphrase", None) - if is_string(passphrase): - passphrase = tobytes(passphrase) - if not passphrase: - raise ValueError("Empty passphrase") - - use_pkcs8 = args.pop("use_pkcs8", True) - if use_pkcs8 is False: - if self._curve.is_edwards: - raise ValueError("'pkcs8' must be True for EdDSA curves") - if self._curve.is_montgomery: - raise ValueError("'pkcs8' must be True for Curve25519") - if 'protection' in args: - raise ValueError("'protection' is only supported for PKCS#8") - - if ext_format == "PEM": - if use_pkcs8: - if passphrase: - return self._export_private_encrypted_pkcs8_in_clear_pem(passphrase, **args) - else: - return self._export_private_clear_pkcs8_in_clear_pem() - else: - return self._export_private_pem(passphrase, **args) - elif ext_format == "DER": - # DER - if passphrase and not use_pkcs8: - raise ValueError("Private keys can only be encrpyted with DER using PKCS#8") - if use_pkcs8: - return self._export_pkcs8(passphrase=passphrase, **args) - else: - return self._export_rfc5915_private_der() - else: - raise ValueError("Private keys cannot be exported " - "in the '%s' format" % ext_format) - else: # Public key - if args: - raise ValueError("Unexpected parameters: '%s'" % args) - if ext_format == "PEM": - return self._export_public_pem(compress) - elif ext_format == "DER": - return self._export_subjectPublicKeyInfo(compress) - elif ext_format == "SEC1": - return self._export_SEC1(compress) - elif ext_format == "raw": - if self._curve.is_edwards: - return self._export_eddsa_public() - elif self._curve.is_montgomery: - return self._export_montgomery_public() - else: - return self._export_SEC1(compress) - else: - return self._export_openssh(compress) + r"""Class defining an ECC key. + Do not instantiate directly. + Use :func:`generate`, :func:`construct` or :func:`import_key` instead. + + :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. + :vartype curve: string + + :ivar pointQ: an ECC point representing the public component. + :vartype pointQ: :class:`EccPoint` or :class:`EccXPoint` + + :ivar d: A scalar that represents the private component + in NIST P curves. It is smaller than the + order of the generator point. + :vartype d: integer + + :ivar seed: A seed that represents the private component + in Ed22519 (32 bytes), Curve25519 (32 bytes), + Curve448 (56 bytes), Ed448 (57 bytes). + :vartype seed: bytes + """ + + def __init__(self, **kwargs): + """Create a new ECC key + + Keywords: + curve : string + The name of the curve. + d : integer + Mandatory for a private key one NIST P curves. + It must be in the range ``[1..order-1]``. + seed : bytes + Mandatory for a private key on Ed25519 (32 bytes), + Curve25519 (32 bytes), Curve448 (56 bytes) or Ed448 (57 bytes). + point : EccPoint or EccXPoint + Mandatory for a public key. If provided for a private key, + the implementation will NOT check whether it matches ``d``. + + Only one parameter among ``d``, ``seed`` or ``point`` may be used. + """ + + kwargs_ = dict(kwargs) + curve_name = kwargs_.pop("curve", None) + self._d = kwargs_.pop("d", None) + self._seed = kwargs_.pop("seed", None) + self._point = kwargs_.pop("point", None) + if curve_name is None and self._point: + curve_name = self._point.curve + if kwargs_: + raise TypeError("Unknown parameters: " + str(kwargs_)) + + if curve_name not in _curves: + raise ValueError("Unsupported curve (%s)" % curve_name) + self._curve = _curves[curve_name] + self.curve = self._curve.canonical + + count = int(self._d is not None) + int(self._seed is not None) + + if count == 0: + if self._point is None: + raise ValueError("At lest one between parameters 'point', 'd' or 'seed' must be specified") + return + + if count == 2: + raise ValueError("Parameters d and seed are mutually exclusive") + + # NIST P curves work with d, EdDSA works with seed + + # RFC 8032, 5.1.5 + if self._curve.id == _CurveID.ED25519: + if self._d is not None: + raise ValueError("Parameter d can only be used with NIST P curves") + if len(self._seed) != 32: + raise ValueError("Parameter seed must be 32 bytes long for Ed25519") + seed_hash = SHA512.new(self._seed).digest() # h + self._prefix = seed_hash[32:] + tmp = bytearray(seed_hash[:32]) + tmp[0] &= 0xF8 + tmp[31] = (tmp[31] & 0x7F) | 0x40 + self._d = Integer.from_bytes(tmp, byteorder="little") + # RFC 8032, 5.2.5 + elif self._curve.id == _CurveID.ED448: + if self._d is not None: + raise ValueError("Parameter d can only be used with NIST P curves") + if len(self._seed) != 57: + raise ValueError("Parameter seed must be 57 bytes long for Ed448") + seed_hash = SHAKE256.new(self._seed).read(114) # h + self._prefix = seed_hash[57:] + tmp = bytearray(seed_hash[:57]) + tmp[0] &= 0xFC + tmp[55] |= 0x80 + tmp[56] = 0 + self._d = Integer.from_bytes(tmp, byteorder="little") + # RFC 7748, 5 + elif self._curve.id == _CurveID.CURVE25519: + if self._d is not None: + raise ValueError("Parameter d can only be used with NIST P curves") + if len(self._seed) != 32: + raise ValueError("Parameter seed must be 32 bytes long for Curve25519") + tmp = bytearray(self._seed) + tmp[0] &= 0xF8 + tmp[31] = (tmp[31] & 0x7F) | 0x40 + self._d = Integer.from_bytes(tmp, byteorder="little") + elif self._curve.id == _CurveID.CURVE448: + if self._d is not None: + raise ValueError("Parameter d can only be used with NIST P curves") + if len(self._seed) != 56: + raise ValueError("Parameter seed must be 56 bytes long for Curve448") + tmp = bytearray(self._seed) + tmp[0] &= 0xFC + tmp[55] |= 0x80 + self._d = Integer.from_bytes(tmp, byteorder="little") + + else: + if self._seed is not None: + raise ValueError("Parameter 'seed' cannot be used with NIST P-curves") + self._d = Integer(self._d) + if not 1 <= self._d < self._curve.order: + raise ValueError("Parameter d must be an integer smaller than the curve order") + + def __eq__(self, other): + if not isinstance(other, EccKey): + return False + + if other.has_private() != self.has_private(): + return False + + return other.pointQ == self.pointQ + + def __repr__(self): + if self.has_private(): + if self._curve.is_edwards: + extra = ", seed=%s" % tostr(binascii.hexlify(self._seed)) + else: + extra = ", d=%d" % int(self._d) + else: + extra = "" + if self._curve.id in ( + _CurveID.CURVE25519, + _CurveID.CURVE448, + ): + x = self.pointQ.x + result = "EccKey(curve='%s', point_x=%d%s)" % (self._curve.canonical, x, extra) + else: + x, y = self.pointQ.xy + result = "EccKey(curve='%s', point_x=%d, point_y=%d%s)" % (self._curve.canonical, x, y, extra) + return result + + def has_private(self): + """``True`` if this key can be used for making signatures or decrypting data.""" + + return self._d is not None + + # ECDSA + def _sign(self, z, k): + assert 0 < k < self._curve.order + + order = self._curve.order + blind = Integer.random_range( + min_inclusive=1, + max_exclusive=order, + ) + + blind_d = self._d * blind + inv_blind_k = (blind * k).inverse(order) + + r = (self._curve.G * k).x % order + s = inv_blind_k * (blind * z + blind_d * r) % order + return (r, s) + + # ECDSA + def _verify(self, z, rs): + order = self._curve.order + sinv = rs[1].inverse(order) + point1 = self._curve.G * ((sinv * z) % order) + point2 = self.pointQ * ((sinv * rs[0]) % order) + return (point1 + point2).x == rs[0] + + @property + def d(self): + if not self.has_private(): + raise ValueError("This is not a private ECC key") + return self._d + + @property + def seed(self): + if not self.has_private(): + raise ValueError("This is not a private ECC key") + return self._seed + + @property + def pointQ(self): + if self._point is None: + self._point = self._curve.G * self._d + return self._point + + def public_key(self): + """A matching ECC public key. + + Returns: + a new :class:`EccKey` object + """ + + return EccKey(curve=self._curve.canonical, point=self.pointQ) + + def _export_SEC1(self, compress): + if not self._curve.is_weierstrass: + raise ValueError("SEC1 format is only supported for NIST P curves") + + # See 2.2 in RFC5480 and 2.3.3 in SEC1 + # + # The first byte is: + # - 0x02: compressed, only X-coordinate, Y-coordinate is even + # - 0x03: compressed, only X-coordinate, Y-coordinate is odd + # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate + # + # PAI is in theory encoded as 0x00. + + modulus_bytes = self.pointQ.size_in_bytes() + + if compress: + if self.pointQ.y.is_odd(): + first_byte = b"\x03" + else: + first_byte = b"\x02" + public_key = first_byte + self.pointQ.x.to_bytes(modulus_bytes) + else: + public_key = ( + b"\x04" + self.pointQ.x.to_bytes(modulus_bytes) + self.pointQ.y.to_bytes(modulus_bytes) + ) + return public_key + + def _export_eddsa_public(self): + x, y = self.pointQ.xy + if self._curve.id == _CurveID.ED25519: + result = bytearray(y.to_bytes(32, byteorder="little")) + result[31] = ((x & 1) << 7) | result[31] + elif self._curve.id == _CurveID.ED448: + result = bytearray(y.to_bytes(57, byteorder="little")) + result[56] = (x & 1) << 7 + else: + raise ValueError("Not an EdDSA key to export") + return bytes(result) + + def _export_montgomery_public(self): + if not self._curve.is_montgomery: + raise ValueError("Not a Montgomery key to export") + x = self.pointQ.x + field_size = self.pointQ.size_in_bytes() + result = bytearray(x.to_bytes(field_size, byteorder="little")) + return bytes(result) + + def _export_subjectPublicKeyInfo(self, compress): + if self._curve.is_edwards: + oid = self._curve.oid + public_key = self._export_eddsa_public() + params = None + elif self._curve.is_montgomery: + oid = self._curve.oid + public_key = self._export_montgomery_public() + params = None + else: + oid = "1.2.840.10045.2.1" # unrestricted + public_key = self._export_SEC1(compress) + params = DerObjectId(self._curve.oid) + + return _create_subject_public_key_info( + oid, + public_key, + params, + ) + + def _export_rfc5915_private_der(self, include_ec_params=True): + assert self.has_private() + + # ECPrivateKey ::= SEQUENCE { + # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + # privateKey OCTET STRING, + # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + # publicKey [1] BIT STRING OPTIONAL + # } + + # Public key - uncompressed form + modulus_bytes = self.pointQ.size_in_bytes() + public_key = b"\x04" + self.pointQ.x.to_bytes(modulus_bytes) + self.pointQ.y.to_bytes(modulus_bytes) + + seq = [ + 1, + DerOctetString(self.d.to_bytes(modulus_bytes)), + DerObjectId(self._curve.oid, explicit=0), + DerBitString(public_key, explicit=1), + ] + + if not include_ec_params: + del seq[2] + + return DerSequence(seq).encode() + + def _export_pkcs8(self, **kwargs): + from Cryptodome.IO import PKCS8 + + if kwargs.get("passphrase", None) is not None and "protection" not in kwargs: + raise ValueError("At least the 'protection' parameter must be present") + + if self._seed is not None: + oid = self._curve.oid + private_key = DerOctetString(self._seed).encode() + params = None + else: + oid = "1.2.840.10045.2.1" # unrestricted + private_key = self._export_rfc5915_private_der(include_ec_params=False) + params = DerObjectId(self._curve.oid) + + result = PKCS8.wrap( + private_key, + oid, + key_params=params, + **kwargs, + ) + return result + + def _export_public_pem(self, compress): + from Cryptodome.IO import PEM + + encoded_der = self._export_subjectPublicKeyInfo(compress) + return PEM.encode(encoded_der, "PUBLIC KEY") + + def _export_private_pem(self, passphrase, **kwargs): + from Cryptodome.IO import PEM + + encoded_der = self._export_rfc5915_private_der() + return PEM.encode(encoded_der, "EC PRIVATE KEY", passphrase, **kwargs) + + def _export_private_clear_pkcs8_in_clear_pem(self): + from Cryptodome.IO import PEM + + encoded_der = self._export_pkcs8() + return PEM.encode(encoded_der, "PRIVATE KEY") + + def _export_private_encrypted_pkcs8_in_clear_pem(self, passphrase, **kwargs): + from Cryptodome.IO import PEM + + assert passphrase + if "protection" not in kwargs: + raise ValueError("At least the 'protection' parameter should be present") + encoded_der = self._export_pkcs8(passphrase=passphrase, **kwargs) + return PEM.encode(encoded_der, "ENCRYPTED PRIVATE KEY") + + def _export_openssh(self, compress): + if self.has_private(): + raise ValueError("Cannot export OpenSSH private keys") + + desc = self._curve.openssh + + if desc is None: + raise ValueError("Cannot export %s keys as OpenSSH" % self.curve) + elif desc == "ssh-ed25519": + public_key = self._export_eddsa_public() + comps = (tobytes(desc), tobytes(public_key)) + else: + modulus_bytes = self.pointQ.size_in_bytes() + + if compress: + first_byte = 2 + self.pointQ.y.is_odd() + public_key = bchr(first_byte) + self.pointQ.x.to_bytes(modulus_bytes) + else: + public_key = ( + b"\x04" + self.pointQ.x.to_bytes(modulus_bytes) + self.pointQ.y.to_bytes(modulus_bytes) + ) + + middle = desc.split("-")[2] + comps = (tobytes(desc), tobytes(middle), public_key) + + blob = b"".join([struct.pack(">I", len(x)) + x for x in comps]) + return desc + " " + tostr(binascii.b2a_base64(blob)) + + def export_key(self, **kwargs): + """Export this ECC key. + + Args: + format (string): + The output format: + + - ``'DER'``. The key will be encoded in ASN.1 DER format (binary). + For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure + defined in `RFC5480`_ will be used. + For a private key, the ASN.1 ``ECPrivateKey`` structure defined + in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope, + see the ``use_pkcs8`` flag below). + - ``'PEM'``. The key will be encoded in a PEM_ envelope (ASCII). + - ``'OpenSSH'``. The key will be encoded in the OpenSSH_ format + (ASCII, public keys only). + - ``'SEC1'``. The public key (i.e., the EC point) will be encoded + into ``bytes`` according to Section 2.3.3 of `SEC1`_ + (which is a subset of the older X9.62 ITU standard). + Only for NIST P-curves. + - ``'raw'``. The public key will be encoded as ``bytes``, + without any metadata. + + * For NIST P-curves: equivalent to ``'SEC1'``. + * For Ed25519 and Ed448: ``bytes`` in the format + defined in `RFC8032`_. + * For Curve25519 and Curve448: ``bytes`` in the format + defined in `RFC7748`_. + + passphrase (bytes or string): + (*Private keys only*) The passphrase to protect the + private key. + + use_pkcs8 (boolean): + (*Private keys only*) + If ``True`` (default and recommended), the `PKCS#8`_ representation + will be used. + It must be ``True`` for Ed25519, Ed448, Curve25519, and Curve448. + + If ``False`` and a passphrase is present, the obsolete PEM + encryption will be used. + + protection (string): + When a private key is exported with password-protection + and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be + present, + For all possible protection schemes, + refer to :ref:`the encryption parameters of PKCS#8`. + It is recommended to use ``'PBKDF2WithHMAC-SHA512AndAES128-CBC'``. + + compress (boolean): + If ``True``, the method returns a more compact representation + of the public key, with the X-coordinate only. + + If ``False`` (default), the method returns the full public key. + + This parameter is ignored for Ed25519/Ed448/Curve25519/Curve448, + as compression is mandatory. + + prot_params (dict): + When a private key is exported with password-protection + and PKCS#8 (both ``DER`` and ``PEM`` formats), this dictionary + contains the parameters to use to derive the encryption key + from the passphrase. + For all possible values, + refer to :ref:`the encryption parameters of PKCS#8`. + The recommendation is to use ``{'iteration_count':21000}`` for PBKDF2, + and ``{'iteration_count':131072}`` for scrypt. + + .. warning:: + If you don't provide a passphrase, the private key will be + exported in the clear! + + .. note:: + When exporting a private key with password-protection and `PKCS#8`_ + (both ``DER`` and ``PEM`` formats), any extra parameters + to ``export_key()`` will be passed to :mod:`Cryptodome.IO.PKCS8`. + + .. _PEM: http://www.ietf.org/rfc/rfc1421.txt + .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt + .. _OpenSSH: http://www.openssh.com/txt/rfc5656.txt + .. _RFC5480: https://tools.ietf.org/html/rfc5480 + .. _SEC1: https://www.secg.org/sec1-v2.pdf + .. _RFC7748: https://tools.ietf.org/html/rfc7748 + + Returns: + A multi-line string (for ``'PEM'`` and ``'OpenSSH'``) or + ``bytes`` (for ``'DER'``, ``'SEC1'``, and ``'raw'``) with the encoded key. + """ + + args = kwargs.copy() + ext_format = args.pop("format") + if ext_format not in ("PEM", "DER", "OpenSSH", "SEC1", "raw"): + raise ValueError("Unknown format '%s'" % ext_format) + + compress = args.pop("compress", False) + + if self.has_private(): + passphrase = args.pop("passphrase", None) + if is_string(passphrase): + passphrase = tobytes(passphrase) + if not passphrase: + raise ValueError("Empty passphrase") + + use_pkcs8 = args.pop("use_pkcs8", True) + if use_pkcs8 is False: + if self._curve.is_edwards: + raise ValueError("'pkcs8' must be True for EdDSA curves") + if self._curve.is_montgomery: + raise ValueError("'pkcs8' must be True for Curve25519") + if "protection" in args: + raise ValueError("'protection' is only supported for PKCS#8") + + if ext_format == "PEM": + if use_pkcs8: + if passphrase: + return self._export_private_encrypted_pkcs8_in_clear_pem(passphrase, **args) + else: + return self._export_private_clear_pkcs8_in_clear_pem() + else: + return self._export_private_pem(passphrase, **args) + elif ext_format == "DER": + # DER + if passphrase and not use_pkcs8: + raise ValueError("Private keys can only be encrpyted with DER using PKCS#8") + if use_pkcs8: + return self._export_pkcs8(passphrase=passphrase, **args) + else: + return self._export_rfc5915_private_der() + else: + raise ValueError( + "Private keys cannot be exported in the '%s' format" % ext_format, + ) + else: # Public key + if args: + raise ValueError("Unexpected parameters: '%s'" % args) + if ext_format == "PEM": + return self._export_public_pem(compress) + elif ext_format == "DER": + return self._export_subjectPublicKeyInfo(compress) + elif ext_format == "SEC1": + return self._export_SEC1(compress) + elif ext_format == "raw": + if self._curve.is_edwards: + return self._export_eddsa_public() + elif self._curve.is_montgomery: + return self._export_montgomery_public() + else: + return self._export_SEC1(compress) + else: + return self._export_openssh(compress) def generate(**kwargs): - """Generate a new private key on the given curve. - - Args: - - curve (string): - Mandatory. It must be a curve name defined in the `ECC table`_. - - randfunc (callable): - Optional. The RNG to read randomness from. - If ``None``, :func:`Cryptodome.Random.get_random_bytes` is used. - """ - - curve_name = kwargs.pop("curve") - curve = _curves[curve_name] - randfunc = kwargs.pop("randfunc", get_random_bytes) - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - if _curves[curve_name].id == _CurveID.ED25519: - seed = randfunc(32) - new_key = EccKey(curve=curve_name, seed=seed) - elif _curves[curve_name].id == _CurveID.ED448: - seed = randfunc(57) - new_key = EccKey(curve=curve_name, seed=seed) - elif _curves[curve_name].id == _CurveID.CURVE25519: - seed = randfunc(32) - new_key = EccKey(curve=curve_name, seed=seed) - _curves[curve_name].validate(new_key.pointQ) - elif _curves[curve_name].id == _CurveID.CURVE448: - seed = randfunc(56) - new_key = EccKey(curve=curve_name, seed=seed) - _curves[curve_name].validate(new_key.pointQ) - else: - d = Integer.random_range(min_inclusive=1, - max_exclusive=curve.order, - randfunc=randfunc) - new_key = EccKey(curve=curve_name, d=d) - - return new_key + """Generate a new private key on the given curve. + + Args: + + curve (string): + Mandatory. It must be a curve name defined in the `ECC table`_. + + randfunc (callable): + Optional. The RNG to read randomness from. + If ``None``, :func:`Cryptodome.Random.get_random_bytes` is used. + """ + + curve_name = kwargs.pop("curve") + curve = _curves[curve_name] + randfunc = kwargs.pop("randfunc", get_random_bytes) + if kwargs: + raise TypeError("Unknown parameters: " + str(kwargs)) + + if _curves[curve_name].id == _CurveID.ED25519: + seed = randfunc(32) + new_key = EccKey(curve=curve_name, seed=seed) + elif _curves[curve_name].id == _CurveID.ED448: + seed = randfunc(57) + new_key = EccKey(curve=curve_name, seed=seed) + elif _curves[curve_name].id == _CurveID.CURVE25519: + seed = randfunc(32) + new_key = EccKey(curve=curve_name, seed=seed) + _curves[curve_name].validate(new_key.pointQ) + elif _curves[curve_name].id == _CurveID.CURVE448: + seed = randfunc(56) + new_key = EccKey(curve=curve_name, seed=seed) + _curves[curve_name].validate(new_key.pointQ) + else: + d = Integer.random_range( + min_inclusive=1, + max_exclusive=curve.order, + randfunc=randfunc, + ) + new_key = EccKey(curve=curve_name, d=d) + + return new_key def construct(**kwargs): - """Build a new ECC key (private or public) starting - from some base components. - - In most cases, you will already have an existing key - which you can read in with :func:`import_key` instead - of this function. - - Args: - curve (string): - Mandatory. The name of the elliptic curve, as defined in the `ECC table`_. + """Build a new ECC key (private or public) starting + from some base components. - d (integer): - Mandatory for a private key and a NIST P-curve (e.g., P-256). - It must be an integer in the range ``[1..order-1]``. + In most cases, you will already have an existing key + which you can read in with :func:`import_key` instead + of this function. - seed (bytes): - Mandatory for a private key and curves Ed25519 (32 bytes), - Curve25519 (32 bytes), Curve448 (56 bytes) and Ed448 (57 bytes). + Args: + curve (string): + Mandatory. The name of the elliptic curve, as defined in the `ECC table`_. - point_x (integer): - The X coordinate (affine) of the ECC point. - Mandatory for a public key. + d (integer): + Mandatory for a private key and a NIST P-curve (e.g., P-256). + It must be an integer in the range ``[1..order-1]``. - point_y (integer): - The Y coordinate (affine) of the ECC point. - Mandatory for a public key, - except for Curve25519 and Curve448. + seed (bytes): + Mandatory for a private key and curves Ed25519 (32 bytes), + Curve25519 (32 bytes), Curve448 (56 bytes) and Ed448 (57 bytes). - Returns: - :class:`EccKey` : a new ECC key object - """ + point_x (integer): + The X coordinate (affine) of the ECC point. + Mandatory for a public key. - curve_name = kwargs["curve"] - curve = _curves[curve_name] - point_x = kwargs.pop("point_x", None) - point_y = kwargs.pop("point_y", None) + point_y (integer): + The Y coordinate (affine) of the ECC point. + Mandatory for a public key, + except for Curve25519 and Curve448. - if "point" in kwargs: - raise TypeError("Unknown keyword: point") + Returns: + :class:`EccKey` : a new ECC key object + """ - if curve.id == _CurveID.CURVE25519: + curve_name = kwargs["curve"] + curve = _curves[curve_name] + point_x = kwargs.pop("point_x", None) + point_y = kwargs.pop("point_y", None) - if point_x is not None: - kwargs["point"] = EccXPoint(point_x, curve_name) - new_key = EccKey(**kwargs) - curve.validate(new_key.pointQ) + if "point" in kwargs: + raise TypeError("Unknown keyword: point") - elif curve.id == _CurveID.CURVE448: + if curve.id == _CurveID.CURVE25519: + if point_x is not None: + kwargs["point"] = EccXPoint(point_x, curve_name) + new_key = EccKey(**kwargs) + curve.validate(new_key.pointQ) - if point_x is not None: - kwargs["point"] = EccXPoint(point_x, curve_name) - new_key = EccKey(**kwargs) - curve.validate(new_key.pointQ) + elif curve.id == _CurveID.CURVE448: + if point_x is not None: + kwargs["point"] = EccXPoint(point_x, curve_name) + new_key = EccKey(**kwargs) + curve.validate(new_key.pointQ) - else: + else: + if None not in (point_x, point_y): + kwargs["point"] = EccPoint(point_x, point_y, curve_name) + new_key = EccKey(**kwargs) - if None not in (point_x, point_y): - kwargs["point"] = EccPoint(point_x, point_y, curve_name) - new_key = EccKey(**kwargs) + # Validate that the private key matches the public one + # because EccKey will not do that automatically + if new_key.has_private() and "point" in kwargs: + pub_key = curve.G * new_key.d + if pub_key.xy != (point_x, point_y): + raise ValueError("Private and public ECC keys do not match") - # Validate that the private key matches the public one - # because EccKey will not do that automatically - if new_key.has_private() and 'point' in kwargs: - pub_key = curve.G * new_key.d - if pub_key.xy != (point_x, point_y): - raise ValueError("Private and public ECC keys do not match") - - return new_key + return new_key def _import_public_der(ec_point, curve_oid=None, curve_name=None): - """Convert an encoded EC point into an EccKey object - - ec_point: byte string with the EC point (SEC1-encoded) - curve_oid: string with the name the curve - curve_name: string with the OID of the curve - - Either curve_id or curve_name must be specified - - """ - - for _curve_name, curve in _curves.items(): - if curve_oid and curve.oid == curve_oid: - break - if curve_name == _curve_name: - break - else: - if curve_oid: - raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) - else: - raise UnsupportedEccFeature("Unsupported ECC curve (%s)" % curve_name) - - # See 2.2 in RFC5480 and 2.3.3 in SEC1 - # The first byte is: - # - 0x02: compressed, only X-coordinate, Y-coordinate is even - # - 0x03: compressed, only X-coordinate, Y-coordinate is odd - # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate - # - # PAI is in theory encoded as 0x00. - - modulus_bytes = curve.p.size_in_bytes() - point_type = bord(ec_point[0]) - - # Uncompressed point - if point_type == 0x04: - if len(ec_point) != (1 + 2 * modulus_bytes): - raise ValueError("Incorrect EC point length") - x = Integer.from_bytes(ec_point[1:modulus_bytes+1]) - y = Integer.from_bytes(ec_point[modulus_bytes+1:]) - # Compressed point - elif point_type in (0x02, 0x03): - if len(ec_point) != (1 + modulus_bytes): - raise ValueError("Incorrect EC point length") - x = Integer.from_bytes(ec_point[1:]) - # Right now, we only support Short Weierstrass curves - y = (x**3 - x*3 + curve.b).sqrt(curve.p) - if point_type == 0x02 and y.is_odd(): - y = curve.p - y - if point_type == 0x03 and y.is_even(): - y = curve.p - y - else: - raise ValueError("Incorrect EC point encoding") - - return construct(curve=_curve_name, point_x=x, point_y=y) + """Convert an encoded EC point into an EccKey object + + ec_point: byte string with the EC point (SEC1-encoded) + curve_oid: string with the name the curve + curve_name: string with the OID of the curve + + Either curve_id or curve_name must be specified + + """ + + for _curve_name, curve in _curves.items(): + if curve_oid and curve.oid == curve_oid: + break + if curve_name == _curve_name: + break + else: + if curve_oid: + raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) + else: + raise UnsupportedEccFeature("Unsupported ECC curve (%s)" % curve_name) + + # See 2.2 in RFC5480 and 2.3.3 in SEC1 + # The first byte is: + # - 0x02: compressed, only X-coordinate, Y-coordinate is even + # - 0x03: compressed, only X-coordinate, Y-coordinate is odd + # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate + # + # PAI is in theory encoded as 0x00. + + modulus_bytes = curve.p.size_in_bytes() + point_type = bord(ec_point[0]) + + # Uncompressed point + if point_type == 0x04: + if len(ec_point) != (1 + 2 * modulus_bytes): + raise ValueError("Incorrect EC point length") + x = Integer.from_bytes(ec_point[1 : modulus_bytes + 1]) + y = Integer.from_bytes(ec_point[modulus_bytes + 1 :]) + # Compressed point + elif point_type in (0x02, 0x03): + if len(ec_point) != (1 + modulus_bytes): + raise ValueError("Incorrect EC point length") + x = Integer.from_bytes(ec_point[1:]) + # Right now, we only support Short Weierstrass curves + y = (x**3 - x * 3 + curve.b).sqrt(curve.p) + if point_type == 0x02 and y.is_odd(): + y = curve.p - y + if point_type == 0x03 and y.is_even(): + y = curve.p - y + else: + raise ValueError("Incorrect EC point encoding") + + return construct(curve=_curve_name, point_x=x, point_y=y) def _import_subjectPublicKeyInfo(encoded, *kwargs): - """Convert a subjectPublicKeyInfo into an EccKey object""" - - # See RFC5480 - - # Parse the generic subjectPublicKeyInfo structure - oid, ec_point, params = _expand_subject_public_key_info(encoded) - - nist_p_oids = ( - "1.2.840.10045.2.1", # id-ecPublicKey (unrestricted) - "1.3.132.1.12", # id-ecDH - "1.3.132.1.13" # id-ecMQV - ) - eddsa_oids = { - "1.3.101.112": ("Ed25519", _import_ed25519_public_key), # id-Ed25519 - "1.3.101.113": ("Ed448", _import_ed448_public_key) # id-Ed448 - } - xdh_oids = { - "1.3.101.110": ("Curve25519", _import_curve25519_public_key), # id-X25519 - "1.3.101.111": ("Curve448", _import_curve448_public_key), # id-X448 - } - - if oid in nist_p_oids: - # See RFC5480 - - # Parameters are mandatory and encoded as ECParameters - # ECParameters ::= CHOICE { - # namedCurve OBJECT IDENTIFIER - # -- implicitCurve NULL - # -- specifiedCurve SpecifiedECDomain - # } - # implicitCurve and specifiedCurve are not supported (as per RFC) - if not params: - raise ValueError("Missing ECC parameters for ECC OID %s" % oid) - try: - curve_oid = DerObjectId().decode(params).value - except ValueError: - raise ValueError("Error decoding namedCurve") - - # ECPoint ::= OCTET STRING - return _import_public_der(ec_point, curve_oid=curve_oid) - - elif oid in eddsa_oids: - # See RFC8410 - curve_name, import_eddsa_public_key = eddsa_oids[oid] - - # Parameters must be absent - if params: - raise ValueError("Unexpected ECC parameters for ECC OID %s" % oid) - - x, y = import_eddsa_public_key(ec_point) - return construct(point_x=x, point_y=y, curve=curve_name) - - elif oid in xdh_oids: - curve_name, import_xdh_public_key = xdh_oids[oid] - - # Parameters must be absent - if params: - raise ValueError("Unexpected ECC parameters for ECC OID %s" % oid) - - x = import_xdh_public_key(ec_point) - return construct(point_x=x, curve=curve_name) - - else: - raise UnsupportedEccFeature("Unsupported ECC OID: %s" % oid) + """Convert a subjectPublicKeyInfo into an EccKey object""" + + # See RFC5480 + + # Parse the generic subjectPublicKeyInfo structure + oid, ec_point, params = _expand_subject_public_key_info(encoded) + + nist_p_oids = ( + "1.2.840.10045.2.1", # id-ecPublicKey (unrestricted) + "1.3.132.1.12", # id-ecDH + "1.3.132.1.13", # id-ecMQV + ) + eddsa_oids = { + "1.3.101.112": ("Ed25519", _import_ed25519_public_key), # id-Ed25519 + "1.3.101.113": ("Ed448", _import_ed448_public_key), # id-Ed448 + } + xdh_oids = { + "1.3.101.110": ("Curve25519", _import_curve25519_public_key), # id-X25519 + "1.3.101.111": ("Curve448", _import_curve448_public_key), # id-X448 + } + + if oid in nist_p_oids: + # See RFC5480 + + # Parameters are mandatory and encoded as ECParameters + # ECParameters ::= CHOICE { + # namedCurve OBJECT IDENTIFIER + # -- implicitCurve NULL + # -- specifiedCurve SpecifiedECDomain + # } + # implicitCurve and specifiedCurve are not supported (as per RFC) + if not params: + raise ValueError("Missing ECC parameters for ECC OID %s" % oid) + try: + curve_oid = DerObjectId().decode(params).value + except ValueError: + raise ValueError("Error decoding namedCurve") + + # ECPoint ::= OCTET STRING + return _import_public_der(ec_point, curve_oid=curve_oid) + + elif oid in eddsa_oids: + # See RFC8410 + curve_name, import_eddsa_public_key = eddsa_oids[oid] + + # Parameters must be absent + if params: + raise ValueError("Unexpected ECC parameters for ECC OID %s" % oid) + + x, y = import_eddsa_public_key(ec_point) + return construct(point_x=x, point_y=y, curve=curve_name) + + elif oid in xdh_oids: + curve_name, import_xdh_public_key = xdh_oids[oid] + + # Parameters must be absent + if params: + raise ValueError("Unexpected ECC parameters for ECC OID %s" % oid) + + x = import_xdh_public_key(ec_point) + return construct(point_x=x, curve=curve_name) + + else: + raise UnsupportedEccFeature("Unsupported ECC OID: %s" % oid) def _import_rfc5915_der(encoded, passphrase, curve_oid=None): - - # See RFC5915 https://tools.ietf.org/html/rfc5915 - # - # ECPrivateKey ::= SEQUENCE { - # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - # privateKey OCTET STRING, - # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - # publicKey [1] BIT STRING OPTIONAL - # } - - ec_private_key = DerSequence().decode(encoded, nr_elements=(2, 3, 4)) - if ec_private_key[0] != 1: - raise ValueError("Incorrect ECC private key version") - - scalar_bytes = DerOctetString().decode(ec_private_key[1]).payload - - next_element = 2 - - # Try to decode 'parameters' - if next_element < len(ec_private_key): - try: - parameters = DerObjectId(explicit=0).decode(ec_private_key[next_element]).value - if curve_oid is not None and parameters != curve_oid: - raise ValueError("Curve mismatch") - curve_oid = parameters - next_element += 1 - except ValueError: - pass - - if curve_oid is None: - raise ValueError("No curve found") - - for curve_name, curve in _curves.items(): - if curve.oid == curve_oid: - break - else: - raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) - - modulus_bytes = curve.p.size_in_bytes() - if len(scalar_bytes) != modulus_bytes: - raise ValueError("Private key is too small") - - # Try to decode 'publicKey' - point_x = point_y = None - if next_element < len(ec_private_key): - try: - public_key_enc = DerBitString(explicit=1).decode(ec_private_key[next_element]).value - public_key = _import_public_der(public_key_enc, curve_oid=curve_oid) - point_x = public_key.pointQ.x - point_y = public_key.pointQ.y - next_element += 1 - except ValueError: - pass - - d = Integer.from_bytes(scalar_bytes) - return construct(curve=curve_name, d=d, point_x=point_x, point_y=point_y) + # See RFC5915 https://tools.ietf.org/html/rfc5915 + # + # ECPrivateKey ::= SEQUENCE { + # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + # privateKey OCTET STRING, + # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + # publicKey [1] BIT STRING OPTIONAL + # } + + ec_private_key = DerSequence().decode(encoded, nr_elements=(2, 3, 4)) + if ec_private_key[0] != 1: + raise ValueError("Incorrect ECC private key version") + + scalar_bytes = DerOctetString().decode(ec_private_key[1]).payload + + next_element = 2 + + # Try to decode 'parameters' + if next_element < len(ec_private_key): + try: + parameters = DerObjectId(explicit=0).decode(ec_private_key[next_element]).value + if curve_oid is not None and parameters != curve_oid: + raise ValueError("Curve mismatch") + curve_oid = parameters + next_element += 1 + except ValueError: + pass + + if curve_oid is None: + raise ValueError("No curve found") + + for curve_name, curve in _curves.items(): + if curve.oid == curve_oid: + break + else: + raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) + + modulus_bytes = curve.p.size_in_bytes() + if len(scalar_bytes) != modulus_bytes: + raise ValueError("Private key is too small") + + # Try to decode 'publicKey' + point_x = point_y = None + if next_element < len(ec_private_key): + try: + public_key_enc = DerBitString(explicit=1).decode(ec_private_key[next_element]).value + public_key = _import_public_der(public_key_enc, curve_oid=curve_oid) + point_x = public_key.pointQ.x + point_y = public_key.pointQ.y + next_element += 1 + except ValueError: + pass + + d = Integer.from_bytes(scalar_bytes) + return construct(curve=curve_name, d=d, point_x=point_x, point_y=point_y) def _import_pkcs8(encoded, passphrase): - from Cryptodome.IO import PKCS8 - - algo_oid, private_key, params = PKCS8.unwrap(encoded, passphrase) - - nist_p_oids = ( - "1.2.840.10045.2.1", # id-ecPublicKey (unrestricted) - "1.3.132.1.12", # id-ecDH - "1.3.132.1.13" # id-ecMQV - ) - eddsa_oids = { - "1.3.101.112": "Ed25519", # id-Ed25519 - "1.3.101.113": "Ed448", # id-Ed448 - } - xdh_oids = { - "1.3.101.110": "Curve25519", # id-X25519 - "1.3.101.111": "Curve448", # id-X448 - } - - if algo_oid in nist_p_oids: - curve_oid = DerObjectId().decode(params).value - return _import_rfc5915_der(private_key, passphrase, curve_oid) - elif algo_oid in eddsa_oids: - if params is not None: - raise ValueError("EdDSA ECC private key must not have parameters") - curve_oid = None - seed = DerOctetString().decode(private_key).payload - return construct(curve=eddsa_oids[algo_oid], seed=seed) - elif algo_oid in xdh_oids: - curve_name = xdh_oids[algo_oid] - if params is not None: - raise ValueError("%s ECC private key must not have parameters" % - curve_name) - curve_oid = None - seed = DerOctetString().decode(private_key).payload - return construct(curve=xdh_oids[algo_oid], seed=seed) - else: - raise UnsupportedEccFeature("Unsupported ECC purpose (OID: %s)" % algo_oid) + from Cryptodome.IO import PKCS8 + + algo_oid, private_key, params = PKCS8.unwrap(encoded, passphrase) + + nist_p_oids = ( + "1.2.840.10045.2.1", # id-ecPublicKey (unrestricted) + "1.3.132.1.12", # id-ecDH + "1.3.132.1.13", # id-ecMQV + ) + eddsa_oids = { + "1.3.101.112": "Ed25519", # id-Ed25519 + "1.3.101.113": "Ed448", # id-Ed448 + } + xdh_oids = { + "1.3.101.110": "Curve25519", # id-X25519 + "1.3.101.111": "Curve448", # id-X448 + } + + if algo_oid in nist_p_oids: + curve_oid = DerObjectId().decode(params).value + return _import_rfc5915_der(private_key, passphrase, curve_oid) + elif algo_oid in eddsa_oids: + if params is not None: + raise ValueError("EdDSA ECC private key must not have parameters") + curve_oid = None + seed = DerOctetString().decode(private_key).payload + return construct(curve=eddsa_oids[algo_oid], seed=seed) + elif algo_oid in xdh_oids: + curve_name = xdh_oids[algo_oid] + if params is not None: + raise ValueError( + "%s ECC private key must not have parameters" % curve_name, + ) + curve_oid = None + seed = DerOctetString().decode(private_key).payload + return construct(curve=xdh_oids[algo_oid], seed=seed) + else: + raise UnsupportedEccFeature("Unsupported ECC purpose (OID: %s)" % algo_oid) def _import_x509_cert(encoded, *kwargs): - - sp_info = _extract_subject_public_key_info(encoded) - return _import_subjectPublicKeyInfo(sp_info) + sp_info = _extract_subject_public_key_info(encoded) + return _import_subjectPublicKeyInfo(sp_info) def _import_der(encoded, passphrase): - - try: - return _import_subjectPublicKeyInfo(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - try: - return _import_x509_cert(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - try: - return _import_rfc5915_der(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - try: - return _import_pkcs8(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - raise ValueError("Not an ECC DER key") + try: + return _import_subjectPublicKeyInfo(encoded, passphrase) + except UnsupportedEccFeature as err: + raise err + except (ValueError, TypeError, IndexError): + pass + + try: + return _import_x509_cert(encoded, passphrase) + except UnsupportedEccFeature as err: + raise err + except (ValueError, TypeError, IndexError): + pass + + try: + return _import_rfc5915_der(encoded, passphrase) + except UnsupportedEccFeature as err: + raise err + except (ValueError, TypeError, IndexError): + pass + + try: + return _import_pkcs8(encoded, passphrase) + except UnsupportedEccFeature as err: + raise err + except (ValueError, TypeError, IndexError): + pass + + raise ValueError("Not an ECC DER key") def _import_openssh_public(encoded): - parts = encoded.split(b' ') - if len(parts) not in (2, 3): - raise ValueError("Not an openssh public key") - - try: - keystring = binascii.a2b_base64(parts[1]) - - keyparts = [] - while len(keystring) > 4: - lk = struct.unpack(">I", keystring[:4])[0] - keyparts.append(keystring[4:4 + lk]) - keystring = keystring[4 + lk:] - - if parts[0] != keyparts[0]: - raise ValueError("Mismatch in openssh public key") - - # NIST P curves - if parts[0].startswith(b"ecdsa-sha2-"): - - for curve_name, curve in _curves.items(): - if curve.openssh is None: - continue - if not curve.openssh.startswith("ecdsa-sha2"): - continue - middle = tobytes(curve.openssh.split("-")[2]) - if keyparts[1] == middle: - break - else: - raise ValueError("Unsupported ECC curve: " + middle) - - ecc_key = _import_public_der(keyparts[2], curve_oid=curve.oid) - - # EdDSA - elif parts[0] == b"ssh-ed25519": - x, y = _import_ed25519_public_key(keyparts[1]) - ecc_key = construct(curve="Ed25519", point_x=x, point_y=y) - else: - raise ValueError("Unsupported SSH key type: " + parts[0]) - - except (IndexError, TypeError, binascii.Error): - raise ValueError("Error parsing SSH key type: " + parts[0]) - - return ecc_key + parts = encoded.split(b" ") + if len(parts) not in (2, 3): + raise ValueError("Not an openssh public key") + + try: + keystring = binascii.a2b_base64(parts[1]) + + keyparts = [] + while len(keystring) > 4: + lk = struct.unpack(">I", keystring[:4])[0] + keyparts.append(keystring[4 : 4 + lk]) + keystring = keystring[4 + lk :] + + if parts[0] != keyparts[0]: + raise ValueError("Mismatch in openssh public key") + + # NIST P curves + if parts[0].startswith(b"ecdsa-sha2-"): + for curve_name, curve in _curves.items(): + if curve.openssh is None: + continue + if not curve.openssh.startswith("ecdsa-sha2"): + continue + middle = tobytes(curve.openssh.split("-")[2]) + if keyparts[1] == middle: + break + else: + raise ValueError("Unsupported ECC curve: " + middle) + + ecc_key = _import_public_der(keyparts[2], curve_oid=curve.oid) + + # EdDSA + elif parts[0] == b"ssh-ed25519": + x, y = _import_ed25519_public_key(keyparts[1]) + ecc_key = construct(curve="Ed25519", point_x=x, point_y=y) + else: + raise ValueError("Unsupported SSH key type: " + parts[0]) + + except (IndexError, TypeError, binascii.Error): + raise ValueError("Error parsing SSH key type: " + parts[0]) + + return ecc_key def _import_openssh_private_ecc(data, password): + from ._openssh import ( + import_openssh_private_generic, + read_bytes, + read_string, + check_padding, + ) - from ._openssh import (import_openssh_private_generic, - read_bytes, read_string, check_padding) - - key_type, decrypted = import_openssh_private_generic(data, password) + key_type, decrypted = import_openssh_private_generic(data, password) - eddsa_keys = { - "ssh-ed25519": ("Ed25519", _import_ed25519_public_key, 32), - } + eddsa_keys = { + "ssh-ed25519": ("Ed25519", _import_ed25519_public_key, 32), + } - # https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04 - if key_type.startswith("ecdsa-sha2"): + # https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04 + if key_type.startswith("ecdsa-sha2"): + ecdsa_curve_name, decrypted = read_string(decrypted) + if ecdsa_curve_name not in _curves: + raise UnsupportedEccFeature("Unsupported ECC curve %s" % ecdsa_curve_name) + curve = _curves[ecdsa_curve_name] + modulus_bytes = (curve.modulus_bits + 7) // 8 - ecdsa_curve_name, decrypted = read_string(decrypted) - if ecdsa_curve_name not in _curves: - raise UnsupportedEccFeature("Unsupported ECC curve %s" % ecdsa_curve_name) - curve = _curves[ecdsa_curve_name] - modulus_bytes = (curve.modulus_bits + 7) // 8 + public_key, decrypted = read_bytes(decrypted) - public_key, decrypted = read_bytes(decrypted) + if bord(public_key[0]) != 4: + raise ValueError("Only uncompressed OpenSSH EC keys are supported") + if len(public_key) != 2 * modulus_bytes + 1: + raise ValueError("Incorrect public key length") - if bord(public_key[0]) != 4: - raise ValueError("Only uncompressed OpenSSH EC keys are supported") - if len(public_key) != 2 * modulus_bytes + 1: - raise ValueError("Incorrect public key length") + point_x = Integer.from_bytes(public_key[1 : 1 + modulus_bytes]) + point_y = Integer.from_bytes(public_key[1 + modulus_bytes :]) - point_x = Integer.from_bytes(public_key[1:1+modulus_bytes]) - point_y = Integer.from_bytes(public_key[1+modulus_bytes:]) + private_key, decrypted = read_bytes(decrypted) + d = Integer.from_bytes(private_key) - private_key, decrypted = read_bytes(decrypted) - d = Integer.from_bytes(private_key) + params = {"d": d, "curve": ecdsa_curve_name} - params = {'d': d, 'curve': ecdsa_curve_name} + elif key_type in eddsa_keys: + curve_name, import_eddsa_public_key, seed_len = eddsa_keys[key_type] - elif key_type in eddsa_keys: + public_key, decrypted = read_bytes(decrypted) + point_x, point_y = import_eddsa_public_key(public_key) - curve_name, import_eddsa_public_key, seed_len = eddsa_keys[key_type] + private_public_key, decrypted = read_bytes(decrypted) + seed = private_public_key[:seed_len] - public_key, decrypted = read_bytes(decrypted) - point_x, point_y = import_eddsa_public_key(public_key) + params = {"seed": seed, "curve": curve_name} + else: + raise ValueError("Unsupport SSH agent key type:" + key_type) - private_public_key, decrypted = read_bytes(decrypted) - seed = private_public_key[:seed_len] + _, padded = read_string(decrypted) # Comment + check_padding(padded) - params = {'seed': seed, 'curve': curve_name} - else: - raise ValueError("Unsupport SSH agent key type:" + key_type) - - _, padded = read_string(decrypted) # Comment - check_padding(padded) - - return construct(point_x=point_x, point_y=point_y, **params) + return construct(point_x=point_x, point_y=point_y, **params) def _import_ed25519_public_key(encoded): - """Import an Ed25519 ECC public key, encoded as raw bytes as described - in RFC8032_. - - Args: - encoded (bytes): - The Ed25519 public key to import. It must be 32 bytes long. - - Returns: - x and y (integer) - - Raises: - ValueError: when the given key cannot be parsed. - - .. _RFC8032: https://datatracker.ietf.org/doc/html/rfc8032 - """ - - if len(encoded) != 32: - raise ValueError("Incorrect length. Only Ed25519 public keys are supported.") - - p = Integer(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed) # 2**255 - 19 - d = 37095705934669439343138083508754565189542113879843219016388785533085940283555 - - y = bytearray(encoded) - x_lsb = y[31] >> 7 - y[31] &= 0x7F - point_y = Integer.from_bytes(y, byteorder='little') - if point_y >= p: - raise ValueError("Invalid Ed25519 key (y)") - if point_y == 1: - return 0, 1 - - u = (point_y**2 - 1) % p - v = ((point_y**2 % p) * d + 1) % p - try: - v_inv = v.inverse(p) - x2 = (u * v_inv) % p - point_x = Integer._tonelli_shanks(x2, p) - if (point_x & 1) != x_lsb: - point_x = p - point_x - except ValueError: - raise ValueError("Invalid Ed25519 public key") - return point_x, point_y + """Import an Ed25519 ECC public key, encoded as raw bytes as described + in RFC8032_. + + Args: + encoded (bytes): + The Ed25519 public key to import. It must be 32 bytes long. + + Returns: + x and y (integer) + + Raises: + ValueError: when the given key cannot be parsed. + + .. _RFC8032: https://datatracker.ietf.org/doc/html/rfc8032 + """ + + if len(encoded) != 32: + raise ValueError("Incorrect length. Only Ed25519 public keys are supported.") + + p = Integer(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED) # 2**255 - 19 + d = 37095705934669439343138083508754565189542113879843219016388785533085940283555 + + y = bytearray(encoded) + x_lsb = y[31] >> 7 + y[31] &= 0x7F + point_y = Integer.from_bytes(y, byteorder="little") + if point_y >= p: + raise ValueError("Invalid Ed25519 key (y)") + if point_y == 1: + return 0, 1 + + u = (point_y**2 - 1) % p + v = ((point_y**2 % p) * d + 1) % p + try: + v_inv = v.inverse(p) + x2 = (u * v_inv) % p + point_x = Integer._tonelli_shanks(x2, p) + if (point_x & 1) != x_lsb: + point_x = p - point_x + except ValueError: + raise ValueError("Invalid Ed25519 public key") + return point_x, point_y def _import_curve25519_public_key(encoded): - """Import a Curve25519 ECC public key, - encoded as raw bytes as described in RFC7748_. + """Import a Curve25519 ECC public key, + encoded as raw bytes as described in RFC7748_. - Args: - encoded (bytes): - The Curve25519 public key to import. It must be 32 bytes long. + Args: + encoded (bytes): + The Curve25519 public key to import. It must be 32 bytes long. - Returns: - x (integer) + Returns: + x (integer) - Raises: - ValueError: when the given key cannot be parsed. + Raises: + ValueError: when the given key cannot be parsed. - .. _RFC7748: https://datatracker.ietf.org/doc/html/rfc7748 - """ + .. _RFC7748: https://datatracker.ietf.org/doc/html/rfc7748 + """ - if len(encoded) != 32: - raise ValueError("Incorrect Curve25519 key length") + if len(encoded) != 32: + raise ValueError("Incorrect Curve25519 key length") - x = bytearray(encoded) - # RFC 7741, Section 5 - x[31] &= 0x7F - point_x = Integer.from_bytes(x, byteorder='little') + x = bytearray(encoded) + # RFC 7741, Section 5 + x[31] &= 0x7F + point_x = Integer.from_bytes(x, byteorder="little") - return point_x + return point_x def _import_curve448_public_key(encoded): - """Import a Curve448 ECC public key, - encoded as raw bytes as described in RFC7748_. + """Import a Curve448 ECC public key, + encoded as raw bytes as described in RFC7748_. - Args: - encoded (bytes): - The Curve448 public key to import. It must be 56 bytes long. + Args: + encoded (bytes): + The Curve448 public key to import. It must be 56 bytes long. - Returns: - x (integer) + Returns: + x (integer) - Raises: - ValueError: when the given key cannot be parsed. + Raises: + ValueError: when the given key cannot be parsed. - .. _RFC7748: https://datatracker.ietf.org/doc/html/rfc7748 - """ + .. _RFC7748: https://datatracker.ietf.org/doc/html/rfc7748 + """ - if len(encoded) != 56: - raise ValueError("Incorrect Curve448 key length") + if len(encoded) != 56: + raise ValueError("Incorrect Curve448 key length") - point_x = Integer.from_bytes(encoded, byteorder='little') + point_x = Integer.from_bytes(encoded, byteorder="little") - return point_x + return point_x def _import_ed448_public_key(encoded): - """Import an Ed448 ECC public key, encoded as raw bytes as described - in RFC8032_. + """Import an Ed448 ECC public key, encoded as raw bytes as described + in RFC8032_. - Args: - encoded (bytes): - The Ed448 public key to import. It must be 57 bytes long. + Args: + encoded (bytes): + The Ed448 public key to import. It must be 57 bytes long. - Returns: - x and y (integer) + Returns: + x and y (integer) - Raises: - ValueError: when the given key cannot be parsed. + Raises: + ValueError: when the given key cannot be parsed. - .. _RFC8032: https://datatracker.ietf.org/doc/html/rfc8032 - """ + .. _RFC8032: https://datatracker.ietf.org/doc/html/rfc8032 + """ - if len(encoded) != 57: - raise ValueError("Incorrect length. Only Ed448 public keys are supported.") + if len(encoded) != 57: + raise ValueError("Incorrect length. Only Ed448 public keys are supported.") - p = _curves['curve448'].p - d = p - 39081 + p = _curves["curve448"].p + d = p - 39081 - y = encoded[:56] - x_lsb = bord(encoded[56]) >> 7 - point_y = Integer.from_bytes(y, byteorder='little') - if point_y >= p: - raise ValueError("Invalid Ed448 key (y)") - if point_y == 1: - return 0, 1 + y = encoded[:56] + x_lsb = bord(encoded[56]) >> 7 + point_y = Integer.from_bytes(y, byteorder="little") + if point_y >= p: + raise ValueError("Invalid Ed448 key (y)") + if point_y == 1: + return 0, 1 - u = (point_y**2 - 1) % p - v = ((point_y**2 % p) * d - 1) % p - try: - v_inv = v.inverse(p) - x2 = (u * v_inv) % p - point_x = Integer._tonelli_shanks(x2, p) - if (point_x & 1) != x_lsb: - point_x = p - point_x - except ValueError: - raise ValueError("Invalid Ed448 public key") - return point_x, point_y + u = (point_y**2 - 1) % p + v = ((point_y**2 % p) * d - 1) % p + try: + v_inv = v.inverse(p) + x2 = (u * v_inv) % p + point_x = Integer._tonelli_shanks(x2, p) + if (point_x & 1) != x_lsb: + point_x = p - point_x + except ValueError: + raise ValueError("Invalid Ed448 public key") + return point_x, point_y def import_key(encoded, passphrase=None, curve_name=None): - """Import an ECC key (public or private). - - Args: - encoded (bytes or multi-line string): - The ECC key to import. - The function will try to automatically detect the right format. - - Supported formats for an ECC **public** key: - - * X.509 certificate: binary (DER) or ASCII (PEM). - * X.509 ``subjectPublicKeyInfo``: binary (DER) or ASCII (PEM). - * SEC1_ (or X9.62), as ``bytes``. NIST P curves only. - You must also provide the ``curve_name`` (with a value from the `ECC table`_) - * OpenSSH line, defined in RFC5656_ and RFC8709_ (ASCII). - This is normally the content of files like ``~/.ssh/id_ecdsa.pub``. - - Supported formats for an ECC **private** key: - - * A binary ``ECPrivateKey`` structure, as defined in `RFC5915`_ (DER). - NIST P curves only. - * A `PKCS#8`_ structure (or the more recent Asymmetric Key - Package, RFC5958_): binary (DER) or ASCII (PEM). - * `OpenSSH 6.5`_ and newer versions (ASCII). - - Private keys can be in the clear or password-protected. - - For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. - - passphrase (byte string): - The passphrase to use for decrypting a private key. - Encryption may be applied protected at the PEM level (not recommended) - or at the PKCS#8 level (recommended). - This parameter is ignored if the key in input is not encrypted. - - curve_name (string): - For a SEC1 encoding only. This is the name of the curve, - as defined in the `ECC table`_. - - .. note:: - - To import EdDSA private and public keys, when encoded as raw ``bytes``, use: - - * :func:`Cryptodome.Signature.eddsa.import_public_key`, or - * :func:`Cryptodome.Signature.eddsa.import_private_key`. - - .. note:: - - To import X25519/X448 private and public keys, when encoded as raw ``bytes``, use: - - * :func:`Cryptodome.Protocol.DH.import_x25519_public_key` - * :func:`Cryptodome.Protocol.DH.import_x25519_private_key` - * :func:`Cryptodome.Protocol.DH.import_x448_public_key` - * :func:`Cryptodome.Protocol.DH.import_x448_private_key` - - Returns: - :class:`EccKey` : a new ECC key object - - Raises: - ValueError: when the given key cannot be parsed (possibly because - the pass phrase is wrong). - - .. _RFC1421: https://datatracker.ietf.org/doc/html/rfc1421 - .. _RFC1423: https://datatracker.ietf.org/doc/html/rfc1423 - .. _RFC5915: https://datatracker.ietf.org/doc/html/rfc5915 - .. _RFC5656: https://datatracker.ietf.org/doc/html/rfc5656 - .. _RFC8709: https://datatracker.ietf.org/doc/html/rfc8709 - .. _RFC5958: https://datatracker.ietf.org/doc/html/rfc5958 - .. _`PKCS#8`: https://datatracker.ietf.org/doc/html/rfc5208 - .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf - .. _SEC1: https://www.secg.org/sec1-v2.pdf - """ - - from Cryptodome.IO import PEM - - encoded = tobytes(encoded) - if passphrase is not None: - passphrase = tobytes(passphrase) - - # PEM - if encoded.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'): - text_encoded = tostr(encoded) - openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) - result = _import_openssh_private_ecc(openssh_encoded, passphrase) - return result - - elif encoded.startswith(b'-----'): - - text_encoded = tostr(encoded) - - # Remove any EC PARAMETERS section - # Ignore its content because the curve type must be already given in the key - ecparams_start = "-----BEGIN EC PARAMETERS-----" - ecparams_end = "-----END EC PARAMETERS-----" - text_encoded = re.sub(ecparams_start + ".*?" + ecparams_end, "", - text_encoded, - flags=re.DOTALL) - - der_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) - if enc_flag: - passphrase = None - try: - result = _import_der(der_encoded, passphrase) - except UnsupportedEccFeature as uef: - raise uef - except ValueError: - raise ValueError("Invalid DER encoding inside the PEM file") - return result - - # OpenSSH - if encoded.startswith((b'ecdsa-sha2-', b'ssh-ed25519')): - return _import_openssh_public(encoded) - - # DER - if len(encoded) > 0 and bord(encoded[0]) == 0x30: - return _import_der(encoded, passphrase) - - # SEC1 - if len(encoded) > 0 and bord(encoded[0]) in (0x02, 0x03, 0x04): - if curve_name is None: - raise ValueError("No curve name was provided") - return _import_public_der(encoded, curve_name=curve_name) - - raise ValueError("ECC key format is not supported") + """Import an ECC key (public or private). + + Args: + encoded (bytes or multi-line string): + The ECC key to import. + The function will try to automatically detect the right format. + + Supported formats for an ECC **public** key: + + * X.509 certificate: binary (DER) or ASCII (PEM). + * X.509 ``subjectPublicKeyInfo``: binary (DER) or ASCII (PEM). + * SEC1_ (or X9.62), as ``bytes``. NIST P curves only. + You must also provide the ``curve_name`` (with a value from the `ECC table`_) + * OpenSSH line, defined in RFC5656_ and RFC8709_ (ASCII). + This is normally the content of files like ``~/.ssh/id_ecdsa.pub``. + + Supported formats for an ECC **private** key: + + * A binary ``ECPrivateKey`` structure, as defined in `RFC5915`_ (DER). + NIST P curves only. + * A `PKCS#8`_ structure (or the more recent Asymmetric Key + Package, RFC5958_): binary (DER) or ASCII (PEM). + * `OpenSSH 6.5`_ and newer versions (ASCII). + + Private keys can be in the clear or password-protected. + + For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. + + passphrase (byte string): + The passphrase to use for decrypting a private key. + Encryption may be applied protected at the PEM level (not recommended) + or at the PKCS#8 level (recommended). + This parameter is ignored if the key in input is not encrypted. + + curve_name (string): + For a SEC1 encoding only. This is the name of the curve, + as defined in the `ECC table`_. + + .. note:: + + To import EdDSA private and public keys, when encoded as raw ``bytes``, use: + + * :func:`Cryptodome.Signature.eddsa.import_public_key`, or + * :func:`Cryptodome.Signature.eddsa.import_private_key`. + + .. note:: + + To import X25519/X448 private and public keys, when encoded as raw ``bytes``, use: + + * :func:`Cryptodome.Protocol.DH.import_x25519_public_key` + * :func:`Cryptodome.Protocol.DH.import_x25519_private_key` + * :func:`Cryptodome.Protocol.DH.import_x448_public_key` + * :func:`Cryptodome.Protocol.DH.import_x448_private_key` + + Returns: + :class:`EccKey` : a new ECC key object + + Raises: + ValueError: when the given key cannot be parsed (possibly because + the pass phrase is wrong). + + .. _RFC1421: https://datatracker.ietf.org/doc/html/rfc1421 + .. _RFC1423: https://datatracker.ietf.org/doc/html/rfc1423 + .. _RFC5915: https://datatracker.ietf.org/doc/html/rfc5915 + .. _RFC5656: https://datatracker.ietf.org/doc/html/rfc5656 + .. _RFC8709: https://datatracker.ietf.org/doc/html/rfc8709 + .. _RFC5958: https://datatracker.ietf.org/doc/html/rfc5958 + .. _`PKCS#8`: https://datatracker.ietf.org/doc/html/rfc5208 + .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf + .. _SEC1: https://www.secg.org/sec1-v2.pdf + """ + + from Cryptodome.IO import PEM + + encoded = tobytes(encoded) + if passphrase is not None: + passphrase = tobytes(passphrase) + + # PEM + if encoded.startswith(b"-----BEGIN OPENSSH PRIVATE KEY"): + text_encoded = tostr(encoded) + openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) + result = _import_openssh_private_ecc(openssh_encoded, passphrase) + return result + + elif encoded.startswith(b"-----"): + text_encoded = tostr(encoded) + + # Remove any EC PARAMETERS section + # Ignore its content because the curve type must be already given in the key + ecparams_start = "-----BEGIN EC PARAMETERS-----" + ecparams_end = "-----END EC PARAMETERS-----" + text_encoded = re.sub( + ecparams_start + ".*?" + ecparams_end, + "", + text_encoded, + flags=re.DOTALL, + ) + + der_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) + if enc_flag: + passphrase = None + try: + result = _import_der(der_encoded, passphrase) + except UnsupportedEccFeature as uef: + raise uef + except ValueError: + raise ValueError("Invalid DER encoding inside the PEM file") + return result + + # OpenSSH + if encoded.startswith((b"ecdsa-sha2-", b"ssh-ed25519")): + return _import_openssh_public(encoded) + + # DER + if len(encoded) > 0 and bord(encoded[0]) == 0x30: + return _import_der(encoded, passphrase) + + # SEC1 + if len(encoded) > 0 and bord(encoded[0]) in (0x02, 0x03, 0x04): + if curve_name is None: + raise ValueError("No curve name was provided") + return _import_public_der(encoded, curve_name=curve_name) + + raise ValueError("ECC key format is not supported") if __name__ == "__main__": + import time - import time - - d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd + d = 0xC51E4753AFDEC1E6B6C6A5B992F43F8DD0C7A8933072708B6522468B2FFB06FD - point = _curves['p256'].G.copy() - count = 3000 + point = _curves["p256"].G.copy() + count = 3000 - start = time.time() - for x in range(count): - pointX = point * d - print("(P-256 G)", (time.time() - start) / count * 1000, "ms") + start = time.time() + for x in range(count): + pointX = point * d + print("(P-256 G)", (time.time() - start) / count * 1000, "ms") - start = time.time() - for x in range(count): - pointX = pointX * d - print("(P-256 arbitrary point)", (time.time() - start) / count * 1000, "ms") + start = time.time() + for x in range(count): + pointX = pointX * d + print("(P-256 arbitrary point)", (time.time() - start) / count * 1000, "ms") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ECC.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ECC.pyi index 3d647277..dd40d169 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ECC.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ECC.pyi @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Union, Callable, Optional, Tuple, Dict, NamedTuple, Any, overload, Literal +from typing import Union, Callable, Optional, Dict, NamedTuple, Any, overload, Literal from typing_extensions import TypedDict, Unpack, NotRequired from Cryptodome.Math.Numbers import Integer @@ -11,70 +11,59 @@ from ._point import EccXPoint as EccXPoint RNG = Callable[[int], bytes] - -class UnsupportedEccFeature(ValueError): - ... +class UnsupportedEccFeature(ValueError): ... class ExportParams(TypedDict): - passphrase: NotRequired[Union[bytes, str]] - use_pkcs8: NotRequired[bool] - protection: NotRequired[str] - compress: NotRequired[bool] - prot_params: NotRequired[ProtParams] - + passphrase: NotRequired[Union[bytes, str]] + use_pkcs8: NotRequired[bool] + protection: NotRequired[str] + compress: NotRequired[bool] + prot_params: NotRequired[ProtParams] class EccKey(object): - curve: str - def __init__(self, *, curve: str = ..., d: int = ..., point: EccPoint = ...) -> None: ... - def __eq__(self, other: object) -> bool: ... - def __repr__(self) -> str: ... - def has_private(self) -> bool: ... - @property - def d(self) -> int: ... - @property - def pointQ(self) -> EccPoint: ... - def public_key(self) -> EccKey: ... - - @overload - def export_key(self, - *, - format: Literal['PEM', 'OpenSSH'], - **kwargs: Unpack[ExportParams]) -> str: ... - - @overload - def export_key(self, - *, - format: Literal['DER', 'SEC1', 'raw'], - **kwargs: Unpack[ExportParams]) -> bytes: ... - - -_Curve = NamedTuple("_Curve", [('p', Integer), - ('order', Integer), - ('b', Integer), - ('Gx', Integer), - ('Gy', Integer), - ('G', EccPoint), - ('modulus_bits', int), - ('oid', str), - ('context', Any), - ('desc', str), - ('openssh', Union[str, None]), - ]) + curve: str + def __init__(self, *, curve: str = ..., d: int = ..., point: EccPoint = ...) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __repr__(self) -> str: ... + def has_private(self) -> bool: ... + @property + def d(self) -> int: ... + @property + def pointQ(self) -> EccPoint: ... + def public_key(self) -> EccKey: ... + @overload + def export_key(self, *, format: Literal["PEM", "OpenSSH"], **kwargs: Unpack[ExportParams]) -> str: ... + @overload + def export_key( + self, *, format: Literal["DER", "SEC1", "raw"], **kwargs: Unpack[ExportParams] + ) -> bytes: ... + +_Curve = NamedTuple( + "_Curve", + [ + ("p", Integer), + ("order", Integer), + ("b", Integer), + ("Gx", Integer), + ("Gy", Integer), + ("G", EccPoint), + ("modulus_bits", int), + ("oid", str), + ("context", Any), + ("desc", str), + ("openssh", Union[str, None]), + ], +) _curves: Dict[str, _Curve] -def _import_rfc5915_der(encoded: bytes, - passphrase: Optional[str] = None, - curve_oid: Optional[str] = None) -> EccKey: ... - +def _import_rfc5915_der( + encoded: bytes, passphrase: Optional[str] = None, curve_oid: Optional[str] = None +) -> EccKey: ... def generate(**kwargs: Union[str, RNG]) -> EccKey: ... def construct(**kwargs: Union[str, int]) -> EccKey: ... - - -def import_key(encoded: Union[bytes, str], - passphrase: Optional[str] = None, - curve_name: Optional[str] = None) -> EccKey: ... - - +def import_key( + encoded: Union[bytes, str], passphrase: Optional[str] = None, curve_name: Optional[str] = None +) -> EccKey: ... def _import_ed25519_public_key(encoded: bytes) -> EccKey: ... def _import_ed448_public_key(encoded: bytes) -> EccKey: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ElGamal.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ElGamal.py index 95c219e6..a26ce68b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ElGamal.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ElGamal.py @@ -23,78 +23,91 @@ # SOFTWARE. # =================================================================== -__all__ = ['generate', 'construct', 'ElGamalKey'] +__all__ = ["generate", "construct", "ElGamalKey"] from Cryptodome import Random -from Cryptodome.Math.Primality import ( generate_probable_safe_prime, - test_probable_prime, COMPOSITE ) +from Cryptodome.Math.Primality import ( + generate_probable_safe_prime, + test_probable_prime, + COMPOSITE, +) from Cryptodome.Math.Numbers import Integer + # Generate an ElGamal key with N bits def generate(bits, randfunc): - """Randomly generate a fresh, new ElGamal key. + """Randomly generate a fresh, new ElGamal key. + + The key will be safe for use for both encryption and signature + (although it should be used for **only one** purpose). + + Args: + bits (int): + Key length, or size (in bits) of the modulus *p*. + The recommended value is 2048. + randfunc (callable): + Random number generation function; it should accept + a single integer *N* and return a string of random + *N* random bytes. + + Return: + an :class:`ElGamalKey` object + """ + + obj = ElGamalKey() + + # Generate a safe prime p + # See Algorithm 4.86 in Handbook of Applied Cryptography + obj.p = generate_probable_safe_prime(exact_bits=bits, randfunc=randfunc) + q = (obj.p - 1) >> 1 + + # Generate generator g + while 1: + # Choose a square residue; it will generate a cyclic group of order q. + obj.g = pow( + Integer.random_range( + min_inclusive=2, + max_exclusive=obj.p, + randfunc=randfunc, + ), + 2, + obj.p, + ) + + # We must avoid g=2 because of Bleichenbacher's attack described + # in "Generating ElGamal signatures without knowning the secret key", + # 1996 + if obj.g in (1, 2): + continue + + # Discard g if it divides p-1 because of the attack described + # in Note 11.67 (iii) in HAC + if (obj.p - 1) % obj.g == 0: + continue + + # g^{-1} must not divide p-1 because of Khadir's attack + # described in "Conditions of the generator for forging ElGamal + # signature", 2011 + ginv = obj.g.inverse(obj.p) + if (obj.p - 1) % ginv == 0: + continue + + # Found + break + + # Generate private key x + obj.x = Integer.random_range( + min_inclusive=2, + max_exclusive=obj.p - 1, + randfunc=randfunc, + ) + # Generate public key y + obj.y = pow(obj.g, obj.x, obj.p) + return obj - The key will be safe for use for both encryption and signature - (although it should be used for **only one** purpose). - - Args: - bits (int): - Key length, or size (in bits) of the modulus *p*. - The recommended value is 2048. - randfunc (callable): - Random number generation function; it should accept - a single integer *N* and return a string of random - *N* random bytes. - - Return: - an :class:`ElGamalKey` object - """ - - obj=ElGamalKey() - - # Generate a safe prime p - # See Algorithm 4.86 in Handbook of Applied Cryptography - obj.p = generate_probable_safe_prime(exact_bits=bits, randfunc=randfunc) - q = (obj.p - 1) >> 1 - - # Generate generator g - while 1: - # Choose a square residue; it will generate a cyclic group of order q. - obj.g = pow(Integer.random_range(min_inclusive=2, - max_exclusive=obj.p, - randfunc=randfunc), 2, obj.p) - - # We must avoid g=2 because of Bleichenbacher's attack described - # in "Generating ElGamal signatures without knowning the secret key", - # 1996 - if obj.g in (1, 2): - continue - - # Discard g if it divides p-1 because of the attack described - # in Note 11.67 (iii) in HAC - if (obj.p - 1) % obj.g == 0: - continue - - # g^{-1} must not divide p-1 because of Khadir's attack - # described in "Conditions of the generator for forging ElGamal - # signature", 2011 - ginv = obj.g.inverse(obj.p) - if (obj.p - 1) % ginv == 0: - continue - - # Found - break - - # Generate private key x - obj.x = Integer.random_range(min_inclusive=2, - max_exclusive=obj.p-1, - randfunc=randfunc) - # Generate public key y - obj.y = pow(obj.g, obj.x, obj.p) - return obj def construct(tup): - r"""Construct an ElGamal key from a tuple of valid ElGamal components. + r"""Construct an ElGamal key from a tuple of valid ElGamal components. The modulus *p* must be a prime. The following conditions must apply: @@ -125,162 +138,166 @@ def construct(tup): an :class:`ElGamalKey` object """ - obj=ElGamalKey() - if len(tup) not in [3,4]: - raise ValueError('argument for construct() wrong length') - for i in range(len(tup)): - field = obj._keydata[i] - setattr(obj, field, Integer(tup[i])) + obj = ElGamalKey() + if len(tup) not in [3, 4]: + raise ValueError("argument for construct() wrong length") + for i in range(len(tup)): + field = obj._keydata[i] + setattr(obj, field, Integer(tup[i])) - fmt_error = test_probable_prime(obj.p) == COMPOSITE - fmt_error |= obj.g<=1 or obj.g>=obj.p - fmt_error |= pow(obj.g, obj.p-1, obj.p)!=1 - fmt_error |= obj.y<1 or obj.y>=obj.p - if len(tup)==4: - fmt_error |= obj.x<=1 or obj.x>=obj.p - fmt_error |= pow(obj.g, obj.x, obj.p)!=obj.y + fmt_error = test_probable_prime(obj.p) == COMPOSITE + fmt_error |= obj.g <= 1 or obj.g >= obj.p + fmt_error |= pow(obj.g, obj.p - 1, obj.p) != 1 + fmt_error |= obj.y < 1 or obj.y >= obj.p + if len(tup) == 4: + fmt_error |= obj.x <= 1 or obj.x >= obj.p + fmt_error |= pow(obj.g, obj.x, obj.p) != obj.y - if fmt_error: - raise ValueError("Invalid ElGamal key components") + if fmt_error: + raise ValueError("Invalid ElGamal key components") - return obj + return obj -class ElGamalKey(object): - r"""Class defining an ElGamal key. - Do not instantiate directly. - Use :func:`generate` or :func:`construct` instead. - :ivar p: Modulus - :vartype d: integer - - :ivar g: Generator - :vartype e: integer - - :ivar y: Public key component - :vartype y: integer - - :ivar x: Private key component - :vartype x: integer - """ - - #: Dictionary of ElGamal parameters. - #: - #: A public key will only have the following entries: - #: - #: - **y**, the public key. - #: - **g**, the generator. - #: - **p**, the modulus. - #: - #: A private key will also have: - #: - #: - **x**, the private key. - _keydata=['p', 'g', 'y', 'x'] - - def __init__(self, randfunc=None): - if randfunc is None: - randfunc = Random.new().read - self._randfunc = randfunc - - def _encrypt(self, M, K): - a=pow(self.g, K, self.p) - b=( pow(self.y, K, self.p)*M ) % self.p - return [int(a), int(b)] - - def _decrypt(self, M): - if (not hasattr(self, 'x')): - raise TypeError('Private key not available in this object') - r = Integer.random_range(min_inclusive=2, - max_exclusive=self.p-1, - randfunc=self._randfunc) - a_blind = (pow(self.g, r, self.p) * M[0]) % self.p - ax=pow(a_blind, self.x, self.p) - plaintext_blind = (ax.inverse(self.p) * M[1] ) % self.p - plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p - return int(plaintext) - - def _sign(self, M, K): - if (not hasattr(self, 'x')): - raise TypeError('Private key not available in this object') - p1=self.p-1 - K = Integer(K) - if (K.gcd(p1)!=1): - raise ValueError('Bad K value: GCD(K,p-1)!=1') - a=pow(self.g, K, self.p) - t=(Integer(M)-self.x*a) % p1 - while t<0: t=t+p1 - b=(t*K.inverse(p1)) % p1 - return [int(a), int(b)] - - def _verify(self, M, sig): - sig = [Integer(x) for x in sig] - if sig[0]<1 or sig[0]>self.p-1: - return 0 - v1=pow(self.y, sig[0], self.p) - v1=(v1*pow(sig[0], sig[1], self.p)) % self.p - v2=pow(self.g, M, self.p) - if v1==v2: - return 1 - return 0 - - def has_private(self): - """Whether this is an ElGamal private key""" - - if hasattr(self, 'x'): - return 1 - else: - return 0 - - def can_encrypt(self): - return True - - def can_sign(self): - return True - - def publickey(self): - """A matching ElGamal public key. - - Returns: - a new :class:`ElGamalKey` object - """ - return construct((self.p, self.g, self.y)) - - def __eq__(self, other): - if bool(self.has_private()) != bool(other.has_private()): - return False - - result = True - for comp in self._keydata: - result = result and (getattr(self.key, comp, None) == - getattr(other.key, comp, None)) - return result - - def __ne__(self, other): - return not self.__eq__(other) - - def __getstate__(self): - # ElGamal key is not pickable - from pickle import PicklingError - raise PicklingError - - # Methods defined in PyCryptodome that we don't support anymore - - def sign(self, M, K): - raise NotImplementedError - - def verify(self, M, signature): - raise NotImplementedError - - def encrypt(self, plaintext, K): - raise NotImplementedError - - def decrypt(self, ciphertext): - raise NotImplementedError - - def blind(self, M, B): - raise NotImplementedError - - def unblind(self, M, B): - raise NotImplementedError - - def size(self): - raise NotImplementedError +class ElGamalKey(object): + r"""Class defining an ElGamal key. + Do not instantiate directly. + Use :func:`generate` or :func:`construct` instead. + + :ivar p: Modulus + :vartype d: integer + + :ivar g: Generator + :vartype e: integer + + :ivar y: Public key component + :vartype y: integer + + :ivar x: Private key component + :vartype x: integer + """ + + #: Dictionary of ElGamal parameters. + #: + #: A public key will only have the following entries: + #: + #: - **y**, the public key. + #: - **g**, the generator. + #: - **p**, the modulus. + #: + #: A private key will also have: + #: + #: - **x**, the private key. + _keydata = ["p", "g", "y", "x"] + + def __init__(self, randfunc=None): + if randfunc is None: + randfunc = Random.new().read + self._randfunc = randfunc + + def _encrypt(self, M, K): + a = pow(self.g, K, self.p) + b = (pow(self.y, K, self.p) * M) % self.p + return [int(a), int(b)] + + def _decrypt(self, M): + if not hasattr(self, "x"): + raise TypeError("Private key not available in this object") + r = Integer.random_range( + min_inclusive=2, + max_exclusive=self.p - 1, + randfunc=self._randfunc, + ) + a_blind = (pow(self.g, r, self.p) * M[0]) % self.p + ax = pow(a_blind, self.x, self.p) + plaintext_blind = (ax.inverse(self.p) * M[1]) % self.p + plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p + return int(plaintext) + + def _sign(self, M, K): + if not hasattr(self, "x"): + raise TypeError("Private key not available in this object") + p1 = self.p - 1 + K = Integer(K) + if K.gcd(p1) != 1: + raise ValueError("Bad K value: GCD(K,p-1)!=1") + a = pow(self.g, K, self.p) + t = (Integer(M) - self.x * a) % p1 + while t < 0: + t = t + p1 + b = (t * K.inverse(p1)) % p1 + return [int(a), int(b)] + + def _verify(self, M, sig): + sig = [Integer(x) for x in sig] + if sig[0] < 1 or sig[0] > self.p - 1: + return 0 + v1 = pow(self.y, sig[0], self.p) + v1 = (v1 * pow(sig[0], sig[1], self.p)) % self.p + v2 = pow(self.g, M, self.p) + if v1 == v2: + return 1 + return 0 + + def has_private(self): + """Whether this is an ElGamal private key""" + + if hasattr(self, "x"): + return 1 + else: + return 0 + + def can_encrypt(self): + return True + + def can_sign(self): + return True + + def publickey(self): + """A matching ElGamal public key. + + Returns: + a new :class:`ElGamalKey` object + """ + return construct((self.p, self.g, self.y)) + + def __eq__(self, other): + if bool(self.has_private()) != bool(other.has_private()): + return False + + result = True + for comp in self._keydata: + result = result and (getattr(self.key, comp, None) == getattr(other.key, comp, None)) + return result + + def __ne__(self, other): + return not self.__eq__(other) + + def __getstate__(self): + # ElGamal key is not pickable + from pickle import PicklingError + + raise PicklingError + + # Methods defined in PyCryptodome that we don't support anymore + + def sign(self, M, K): + raise NotImplementedError + + def verify(self, M, signature): + raise NotImplementedError + + def encrypt(self, plaintext, K): + raise NotImplementedError + + def decrypt(self, ciphertext): + raise NotImplementedError + + def blind(self, M, B): + raise NotImplementedError + + def unblind(self, M, B): + raise NotImplementedError + + def size(self): + raise NotImplementedError diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ElGamal.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ElGamal.pyi index 90485313..310257e1 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ElGamal.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/ElGamal.pyi @@ -1,6 +1,6 @@ from typing import Callable, Union, Tuple, Optional -__all__ = ['generate', 'construct', 'ElGamalKey'] +__all__ = ["generate", "construct", "ElGamalKey"] RNG = Callable[[int], bytes] @@ -8,11 +8,11 @@ def generate(bits: int, randfunc: RNG) -> ElGamalKey: ... def construct(tup: Union[Tuple[int, int, int], Tuple[int, int, int, int]]) -> ElGamalKey: ... class ElGamalKey(object): - def __init__(self, randfunc: Optional[RNG]=None) -> None: ... - def has_private(self) -> bool: ... - def can_encrypt(self) -> bool: ... - def can_sign(self) -> bool: ... - def publickey(self) -> ElGamalKey: ... - def __eq__(self, other: object) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __getstate__(self) -> None: ... + def __init__(self, randfunc: Optional[RNG] = None) -> None: ... + def has_private(self) -> bool: ... + def can_encrypt(self) -> bool: ... + def can_sign(self) -> bool: ... + def publickey(self) -> ElGamalKey: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def __getstate__(self) -> None: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/RSA.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/RSA.py index 476785e2..0ca71e15 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/RSA.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/RSA.py @@ -29,8 +29,13 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = ['generate', 'construct', 'import_key', - 'RsaKey', 'oid'] +__all__ = [ + "generate", + "construct", + "import_key", + "RsaKey", + "oid", +] import binascii import struct @@ -41,503 +46,539 @@ from Cryptodome.Util.number import bytes_to_long from Cryptodome.Math.Numbers import Integer -from Cryptodome.Math.Primality import (test_probable_prime, - generate_probable_prime, COMPOSITE) +from Cryptodome.Math.Primality import ( + test_probable_prime, + generate_probable_prime, + COMPOSITE, +) -from Cryptodome.PublicKey import (_expand_subject_public_key_info, - _create_subject_public_key_info, - _extract_subject_public_key_info) +from Cryptodome.PublicKey import ( + _expand_subject_public_key_info, + _create_subject_public_key_info, + _extract_subject_public_key_info, +) class RsaKey(object): - r"""Class defining an RSA key, private or public. - Do not instantiate directly. - Use :func:`generate`, :func:`construct` or :func:`import_key` instead. + r"""Class defining an RSA key, private or public. + Do not instantiate directly. + Use :func:`generate`, :func:`construct` or :func:`import_key` instead. + + :ivar n: RSA modulus + :vartype n: integer + + :ivar e: RSA public exponent + :vartype e: integer + + :ivar d: RSA private exponent + :vartype d: integer + + :ivar p: First factor of the RSA modulus + :vartype p: integer + + :ivar q: Second factor of the RSA modulus + :vartype q: integer + + :ivar invp: Chinese remainder component (:math:`p^{-1} \text{mod } q`) + :vartype invp: integer + + :ivar invq: Chinese remainder component (:math:`q^{-1} \text{mod } p`) + :vartype invq: integer + + :ivar u: Same as ``invp`` + :vartype u: integer + """ + + def __init__(self, **kwargs): + """Build an RSA key. + + :Keywords: + n : integer + The modulus. + e : integer + The public exponent. + d : integer + The private exponent. Only required for private keys. + p : integer + The first factor of the modulus. Only required for private keys. + q : integer + The second factor of the modulus. Only required for private keys. + u : integer + The CRT coefficient (inverse of p modulo q). Only required for + private keys. + """ + + input_set = set(kwargs.keys()) + public_set = set(("n", "e")) + private_set = public_set | set(("p", "q", "d", "u")) + if input_set not in (private_set, public_set): + raise ValueError("Some RSA components are missing") + for component, value in kwargs.items(): + setattr(self, "_" + component, value) + if input_set == private_set: + self._dp = self._d % (self._p - 1) # = (e⁻¹) mod (p-1) + self._dq = self._d % (self._q - 1) # = (e⁻¹) mod (q-1) + self._invq = None # will be computed on demand + + @property + def n(self): + return int(self._n) + + @property + def e(self): + return int(self._e) + + @property + def d(self): + if not self.has_private(): + raise AttributeError("No private exponent available for public keys") + return int(self._d) + + @property + def p(self): + if not self.has_private(): + raise AttributeError("No CRT component 'p' available for public keys") + return int(self._p) + + @property + def q(self): + if not self.has_private(): + raise AttributeError("No CRT component 'q' available for public keys") + return int(self._q) + + @property + def dp(self): + if not self.has_private(): + raise AttributeError("No CRT component 'dp' available for public keys") + return int(self._dp) + + @property + def dq(self): + if not self.has_private(): + raise AttributeError("No CRT component 'dq' available for public keys") + return int(self._dq) + + @property + def invq(self): + if not self.has_private(): + raise AttributeError("No CRT component 'invq' available for public keys") + if self._invq is None: + self._invq = self._q.inverse(self._p) + return int(self._invq) + + @property + def invp(self): + return self.u + + @property + def u(self): + if not self.has_private(): + raise AttributeError("No CRT component 'u' available for public keys") + return int(self._u) + + def size_in_bits(self): + """Size of the RSA modulus in bits""" + return self._n.size_in_bits() + + def size_in_bytes(self): + """The minimal amount of bytes that can hold the RSA modulus""" + return (self._n.size_in_bits() - 1) // 8 + 1 + + def _encrypt(self, plaintext): + if not 0 <= plaintext < self._n: + raise ValueError("Plaintext too large") + return int(pow(Integer(plaintext), self._e, self._n)) + + def _decrypt_to_bytes(self, ciphertext): + if not 0 <= ciphertext < self._n: + raise ValueError("Ciphertext too large") + if not self.has_private(): + raise TypeError("This is not a private key") + + # Blinded RSA decryption (to prevent timing attacks): + # Step 1: Generate random secret blinding factor r, + # such that 0 < r < n-1 + r = Integer.random_range(min_inclusive=1, max_exclusive=self._n) + # Step 2: Compute c' = c * r**e mod n + cp = Integer(ciphertext) * pow(r, self._e, self._n) % self._n + # Step 3: Compute m' = c'**d mod n (normal RSA decryption) + m1 = pow(cp, self._dp, self._p) + m2 = pow(cp, self._dq, self._q) + h = ((m2 - m1) * self._u) % self._q + mp = h * self._p + m1 + # Step 4: Compute m = m' * (r**(-1)) mod n + # then encode into a big endian byte string + result = Integer._mult_modulo_bytes( + r.inverse(self._n), + mp, + self._n, + ) + return result + + def _decrypt(self, ciphertext): + """Legacy private method""" + + return bytes_to_long(self._decrypt_to_bytes(ciphertext)) + + def has_private(self): + """Whether this is an RSA private key""" + + return hasattr(self, "_d") + + def can_encrypt(self): # legacy + return True + + def can_sign(self): # legacy + return True + + def public_key(self): + """A matching RSA public key. + + Returns: + a new :class:`RsaKey` object + """ + return RsaKey(n=self._n, e=self._e) + + def __eq__(self, other): + if self.has_private() != other.has_private(): + return False + if self.n != other.n or self.e != other.e: + return False + if not self.has_private(): + return True + return self.d == other.d + + def __ne__(self, other): + return not (self == other) + + def __getstate__(self): + # RSA key is not pickable + from pickle import PicklingError + + raise PicklingError + + def __repr__(self): + if self.has_private(): + extra = ", d=%d, p=%d, q=%d, u=%d" % ( + int(self._d), + int(self._p), + int(self._q), + int(self._u), + ) + else: + extra = "" + return "RsaKey(n=%d, e=%d%s)" % (int(self._n), int(self._e), extra) + + def __str__(self): + if self.has_private(): + key_type = "Private" + else: + key_type = "Public" + return "%s RSA key at 0x%X" % (key_type, id(self)) + + def export_key( + self, + format="PEM", + passphrase=None, + pkcs=1, + protection=None, + randfunc=None, + prot_params=None, + ): + """Export this RSA key. + + Keyword Args: + format (string): + The desired output format: + + - ``'PEM'``. (default) Text output, according to `RFC1421`_/`RFC1423`_. + - ``'DER'``. Binary output. + - ``'OpenSSH'``. Text output, according to the OpenSSH specification. + Only suitable for public keys (not private keys). + + Note that PEM contains a DER structure. + + passphrase (bytes or string): + (*Private keys only*) The passphrase to protect the + private key. + + pkcs (integer): + (*Private keys only*) The standard to use for + serializing the key: PKCS#1 or PKCS#8. + + With ``pkcs=1`` (*default*), the private key is encoded with a + simple `PKCS#1`_ structure (``RSAPrivateKey``). The key cannot be + securely encrypted. + + With ``pkcs=8``, the private key is encoded with a `PKCS#8`_ structure + (``PrivateKeyInfo``). PKCS#8 offers the best ways to securely + encrypt the key. + + .. note:: + This parameter is ignored for a public key. + For DER and PEM, the output is always an + ASN.1 DER ``SubjectPublicKeyInfo`` structure. + + protection (string): + (*For private keys only*) + The encryption scheme to use for protecting the private key + using the passphrase. + + You can only specify a value if ``pkcs=8``. + For all possible protection schemes, + refer to :ref:`the encryption parameters of PKCS#8`. + The recommended value is + ``'PBKDF2WithHMAC-SHA512AndAES256-CBC'``. + + If ``None`` (default), the behavior depends on :attr:`format`: + + - if ``format='PEM'``, the obsolete PEM encryption scheme is used. + It is based on MD5 for key derivation, and 3DES for encryption. + + - if ``format='DER'``, the ``'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'`` + scheme is used. + + prot_params (dict): + (*For private keys only*) + + The parameters to use to derive the encryption key + from the passphrase. ``'protection'`` must be also specified. + For all possible values, + refer to :ref:`the encryption parameters of PKCS#8`. + The recommendation is to use ``{'iteration_count':21000}`` for PBKDF2, + and ``{'iteration_count':131072}`` for scrypt. + + randfunc (callable): + A function that provides random bytes. Only used for PEM encoding. + The default is :func:`Cryptodome.Random.get_random_bytes`. + + Returns: + bytes: the encoded key + + Raises: + ValueError:when the format is unknown or when you try to encrypt a private + key with *DER* format and PKCS#1. + + .. warning:: + If you don't provide a pass phrase, the private key will be + exported in the clear! + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt + .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + """ + + if passphrase is not None: + passphrase = tobytes(passphrase) + + if randfunc is None: + randfunc = Random.get_random_bytes + + if format == "OpenSSH": + e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)] + if bord(e_bytes[0]) & 0x80: + e_bytes = b"\x00" + e_bytes + if bord(n_bytes[0]) & 0x80: + n_bytes = b"\x00" + n_bytes + keyparts = [b"ssh-rsa", e_bytes, n_bytes] + keystring = b"".join([struct.pack(">I", len(kp)) + kp for kp in keyparts]) + return b"ssh-rsa " + binascii.b2a_base64(keystring)[:-1] + + # DER format is always used, even in case of PEM, which simply + # encodes it into BASE64. + if self.has_private(): + binary_key = DerSequence( + [ + 0, + self.n, + self.e, + self.d, + self.p, + self.q, + self.d % (self.p - 1), + self.d % (self.q - 1), + Integer(self.q).inverse(self.p), + ] + ).encode() + if pkcs == 1: + key_type = "RSA PRIVATE KEY" + if format == "DER" and passphrase: + raise ValueError("PKCS#1 private key cannot be encrypted") + else: # PKCS#8 + from Cryptodome.IO import PKCS8 + + if format == "PEM" and protection is None: + key_type = "PRIVATE KEY" + binary_key = PKCS8.wrap( + binary_key, + oid, + None, + key_params=DerNull(), + ) + else: + key_type = "ENCRYPTED PRIVATE KEY" + if not protection: + if prot_params: + raise ValueError("'protection' parameter must be set") + protection = "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC" + binary_key = PKCS8.wrap( + binary_key, + oid, + passphrase, + protection, + prot_params=prot_params, + key_params=DerNull(), + ) + passphrase = None + else: + key_type = "PUBLIC KEY" + binary_key = _create_subject_public_key_info( + oid, + DerSequence( + [ + self.n, + self.e, + ] + ), + DerNull(), + ) + + if format == "DER": + return binary_key + if format == "PEM": + from Cryptodome.IO import PEM + + pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc) + return tobytes(pem_str) + + raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format) + + # Backward compatibility + def exportKey(self, *args, **kwargs): + """:meta private:""" + return self.export_key(*args, **kwargs) + + def publickey(self): + """:meta private:""" + return self.public_key() + + # Methods defined in PyCryptodome that we don't support anymore + def sign(self, M, K): + """:meta private:""" + raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead") + + def verify(self, M, signature): + """:meta private:""" + raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead") + + def encrypt(self, plaintext, K): + """:meta private:""" + raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead") + + def decrypt(self, ciphertext): + """:meta private:""" + raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead") + + def blind(self, M, B): + """:meta private:""" + raise NotImplementedError + + def unblind(self, M, B): + """:meta private:""" + raise NotImplementedError + + def size(self): + """:meta private:""" + raise NotImplementedError - :ivar n: RSA modulus - :vartype n: integer - :ivar e: RSA public exponent - :vartype e: integer - - :ivar d: RSA private exponent - :vartype d: integer - - :ivar p: First factor of the RSA modulus - :vartype p: integer - - :ivar q: Second factor of the RSA modulus - :vartype q: integer - - :ivar invp: Chinese remainder component (:math:`p^{-1} \text{mod } q`) - :vartype invp: integer - - :ivar invq: Chinese remainder component (:math:`q^{-1} \text{mod } p`) - :vartype invq: integer - - :ivar u: Same as ``invp`` - :vartype u: integer - """ - - def __init__(self, **kwargs): - """Build an RSA key. - - :Keywords: - n : integer - The modulus. - e : integer - The public exponent. - d : integer - The private exponent. Only required for private keys. - p : integer - The first factor of the modulus. Only required for private keys. - q : integer - The second factor of the modulus. Only required for private keys. - u : integer - The CRT coefficient (inverse of p modulo q). Only required for - private keys. - """ - - input_set = set(kwargs.keys()) - public_set = set(('n', 'e')) - private_set = public_set | set(('p', 'q', 'd', 'u')) - if input_set not in (private_set, public_set): - raise ValueError("Some RSA components are missing") - for component, value in kwargs.items(): - setattr(self, "_" + component, value) - if input_set == private_set: - self._dp = self._d % (self._p - 1) # = (e⁻¹) mod (p-1) - self._dq = self._d % (self._q - 1) # = (e⁻¹) mod (q-1) - self._invq = None # will be computed on demand - - @property - def n(self): - return int(self._n) - - @property - def e(self): - return int(self._e) - - @property - def d(self): - if not self.has_private(): - raise AttributeError("No private exponent available for public keys") - return int(self._d) - - @property - def p(self): - if not self.has_private(): - raise AttributeError("No CRT component 'p' available for public keys") - return int(self._p) - - @property - def q(self): - if not self.has_private(): - raise AttributeError("No CRT component 'q' available for public keys") - return int(self._q) - - @property - def dp(self): - if not self.has_private(): - raise AttributeError("No CRT component 'dp' available for public keys") - return int(self._dp) - - @property - def dq(self): - if not self.has_private(): - raise AttributeError("No CRT component 'dq' available for public keys") - return int(self._dq) - - @property - def invq(self): - if not self.has_private(): - raise AttributeError("No CRT component 'invq' available for public keys") - if self._invq is None: - self._invq = self._q.inverse(self._p) - return int(self._invq) - - @property - def invp(self): - return self.u - - @property - def u(self): - if not self.has_private(): - raise AttributeError("No CRT component 'u' available for public keys") - return int(self._u) - - def size_in_bits(self): - """Size of the RSA modulus in bits""" - return self._n.size_in_bits() - - def size_in_bytes(self): - """The minimal amount of bytes that can hold the RSA modulus""" - return (self._n.size_in_bits() - 1) // 8 + 1 - - def _encrypt(self, plaintext): - if not 0 <= plaintext < self._n: - raise ValueError("Plaintext too large") - return int(pow(Integer(plaintext), self._e, self._n)) - - def _decrypt_to_bytes(self, ciphertext): - if not 0 <= ciphertext < self._n: - raise ValueError("Ciphertext too large") - if not self.has_private(): - raise TypeError("This is not a private key") - - # Blinded RSA decryption (to prevent timing attacks): - # Step 1: Generate random secret blinding factor r, - # such that 0 < r < n-1 - r = Integer.random_range(min_inclusive=1, max_exclusive=self._n) - # Step 2: Compute c' = c * r**e mod n - cp = Integer(ciphertext) * pow(r, self._e, self._n) % self._n - # Step 3: Compute m' = c'**d mod n (normal RSA decryption) - m1 = pow(cp, self._dp, self._p) - m2 = pow(cp, self._dq, self._q) - h = ((m2 - m1) * self._u) % self._q - mp = h * self._p + m1 - # Step 4: Compute m = m' * (r**(-1)) mod n - # then encode into a big endian byte string - result = Integer._mult_modulo_bytes( - r.inverse(self._n), - mp, - self._n) - return result - - def _decrypt(self, ciphertext): - """Legacy private method""" - - return bytes_to_long(self._decrypt_to_bytes(ciphertext)) - - def has_private(self): - """Whether this is an RSA private key""" - - return hasattr(self, "_d") - - def can_encrypt(self): # legacy - return True - - def can_sign(self): # legacy - return True - - def public_key(self): - """A matching RSA public key. - - Returns: - a new :class:`RsaKey` object - """ - return RsaKey(n=self._n, e=self._e) - - def __eq__(self, other): - if self.has_private() != other.has_private(): - return False - if self.n != other.n or self.e != other.e: - return False - if not self.has_private(): - return True - return (self.d == other.d) - - def __ne__(self, other): - return not (self == other) - - def __getstate__(self): - # RSA key is not pickable - from pickle import PicklingError - raise PicklingError - - def __repr__(self): - if self.has_private(): - extra = ", d=%d, p=%d, q=%d, u=%d" % (int(self._d), int(self._p), - int(self._q), int(self._u)) - else: - extra = "" - return "RsaKey(n=%d, e=%d%s)" % (int(self._n), int(self._e), extra) - - def __str__(self): - if self.has_private(): - key_type = "Private" - else: - key_type = "Public" - return "%s RSA key at 0x%X" % (key_type, id(self)) - - def export_key(self, format='PEM', passphrase=None, pkcs=1, - protection=None, randfunc=None, prot_params=None): - """Export this RSA key. - - Keyword Args: - format (string): - The desired output format: - - - ``'PEM'``. (default) Text output, according to `RFC1421`_/`RFC1423`_. - - ``'DER'``. Binary output. - - ``'OpenSSH'``. Text output, according to the OpenSSH specification. - Only suitable for public keys (not private keys). - - Note that PEM contains a DER structure. - - passphrase (bytes or string): - (*Private keys only*) The passphrase to protect the - private key. - - pkcs (integer): - (*Private keys only*) The standard to use for - serializing the key: PKCS#1 or PKCS#8. - - With ``pkcs=1`` (*default*), the private key is encoded with a - simple `PKCS#1`_ structure (``RSAPrivateKey``). The key cannot be - securely encrypted. - - With ``pkcs=8``, the private key is encoded with a `PKCS#8`_ structure - (``PrivateKeyInfo``). PKCS#8 offers the best ways to securely - encrypt the key. - - .. note:: - This parameter is ignored for a public key. - For DER and PEM, the output is always an - ASN.1 DER ``SubjectPublicKeyInfo`` structure. - - protection (string): - (*For private keys only*) - The encryption scheme to use for protecting the private key - using the passphrase. - - You can only specify a value if ``pkcs=8``. - For all possible protection schemes, - refer to :ref:`the encryption parameters of PKCS#8`. - The recommended value is - ``'PBKDF2WithHMAC-SHA512AndAES256-CBC'``. - - If ``None`` (default), the behavior depends on :attr:`format`: - - - if ``format='PEM'``, the obsolete PEM encryption scheme is used. - It is based on MD5 for key derivation, and 3DES for encryption. - - - if ``format='DER'``, the ``'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'`` - scheme is used. - - prot_params (dict): - (*For private keys only*) - - The parameters to use to derive the encryption key - from the passphrase. ``'protection'`` must be also specified. - For all possible values, - refer to :ref:`the encryption parameters of PKCS#8`. - The recommendation is to use ``{'iteration_count':21000}`` for PBKDF2, - and ``{'iteration_count':131072}`` for scrypt. - - randfunc (callable): - A function that provides random bytes. Only used for PEM encoding. - The default is :func:`Cryptodome.Random.get_random_bytes`. - - Returns: - bytes: the encoded key - - Raises: - ValueError:when the format is unknown or when you try to encrypt a private - key with *DER* format and PKCS#1. - - .. warning:: - If you don't provide a pass phrase, the private key will be - exported in the clear! - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - """ - - if passphrase is not None: - passphrase = tobytes(passphrase) - - if randfunc is None: - randfunc = Random.get_random_bytes - - if format == 'OpenSSH': - e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)] - if bord(e_bytes[0]) & 0x80: - e_bytes = b'\x00' + e_bytes - if bord(n_bytes[0]) & 0x80: - n_bytes = b'\x00' + n_bytes - keyparts = [b'ssh-rsa', e_bytes, n_bytes] - keystring = b''.join([struct.pack(">I", len(kp)) + kp for kp in keyparts]) - return b'ssh-rsa ' + binascii.b2a_base64(keystring)[:-1] - - # DER format is always used, even in case of PEM, which simply - # encodes it into BASE64. - if self.has_private(): - binary_key = DerSequence([0, - self.n, - self.e, - self.d, - self.p, - self.q, - self.d % (self.p-1), - self.d % (self.q-1), - Integer(self.q).inverse(self.p) - ]).encode() - if pkcs == 1: - key_type = 'RSA PRIVATE KEY' - if format == 'DER' and passphrase: - raise ValueError("PKCS#1 private key cannot be encrypted") - else: # PKCS#8 - from Cryptodome.IO import PKCS8 - - if format == 'PEM' and protection is None: - key_type = 'PRIVATE KEY' - binary_key = PKCS8.wrap(binary_key, oid, None, - key_params=DerNull()) - else: - key_type = 'ENCRYPTED PRIVATE KEY' - if not protection: - if prot_params: - raise ValueError("'protection' parameter must be set") - protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' - binary_key = PKCS8.wrap(binary_key, oid, - passphrase, protection, - prot_params=prot_params, - key_params=DerNull()) - passphrase = None - else: - key_type = "PUBLIC KEY" - binary_key = _create_subject_public_key_info(oid, - DerSequence([self.n, - self.e]), - DerNull() - ) - - if format == 'DER': - return binary_key - if format == 'PEM': - from Cryptodome.IO import PEM - - pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc) - return tobytes(pem_str) - - raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format) - - # Backward compatibility - def exportKey(self, *args, **kwargs): - """:meta private:""" - return self.export_key(*args, **kwargs) - - def publickey(self): - """:meta private:""" - return self.public_key() - - # Methods defined in PyCryptodome that we don't support anymore - def sign(self, M, K): - """:meta private:""" - raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead") - - def verify(self, M, signature): - """:meta private:""" - raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead") - - def encrypt(self, plaintext, K): - """:meta private:""" - raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead") - - def decrypt(self, ciphertext): - """:meta private:""" - raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead") - - def blind(self, M, B): - """:meta private:""" - raise NotImplementedError - - def unblind(self, M, B): - """:meta private:""" - raise NotImplementedError - - def size(self): - """:meta private:""" - raise NotImplementedError +def generate(bits, randfunc=None, e=65537): + """Create a new RSA key pair. + The algorithm closely follows NIST `FIPS 186-4`_ in its + sections B.3.1 and B.3.3. The modulus is the product of + two non-strong probable primes. + Each prime passes a suitable number of Miller-Rabin tests + with random bases and a single Lucas test. -def generate(bits, randfunc=None, e=65537): - """Create a new RSA key pair. + Args: + bits (integer): + Key length, or size (in bits) of the RSA modulus. + It must be at least 1024, but **2048 is recommended.** + The FIPS standard only defines 1024, 2048 and 3072. + Keyword Args: + randfunc (callable): + Function that returns random bytes. + The default is :func:`Cryptodome.Random.get_random_bytes`. + e (integer): + Public RSA exponent. It must be an odd positive integer. + It is typically a small number with very few ones in its + binary representation. + The FIPS standard requires the public exponent to be + at least 65537 (the default). - The algorithm closely follows NIST `FIPS 186-4`_ in its - sections B.3.1 and B.3.3. The modulus is the product of - two non-strong probable primes. - Each prime passes a suitable number of Miller-Rabin tests - with random bases and a single Lucas test. + Returns: an RSA key object (:class:`RsaKey`, with private key). - Args: - bits (integer): - Key length, or size (in bits) of the RSA modulus. - It must be at least 1024, but **2048 is recommended.** - The FIPS standard only defines 1024, 2048 and 3072. - Keyword Args: - randfunc (callable): - Function that returns random bytes. - The default is :func:`Cryptodome.Random.get_random_bytes`. - e (integer): - Public RSA exponent. It must be an odd positive integer. - It is typically a small number with very few ones in its - binary representation. - The FIPS standard requires the public exponent to be - at least 65537 (the default). - - Returns: an RSA key object (:class:`RsaKey`, with private key). - - .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ + .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + """ - if bits < 1024: - raise ValueError("RSA modulus length must be >= 1024") - if e % 2 == 0 or e < 3: - raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.") + if bits < 1024: + raise ValueError("RSA modulus length must be >= 1024") + if e % 2 == 0 or e < 3: + raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.") - if randfunc is None: - randfunc = Random.get_random_bytes + if randfunc is None: + randfunc = Random.get_random_bytes - d = n = Integer(1) - e = Integer(e) + d = n = Integer(1) + e = Integer(e) - while n.size_in_bits() != bits and d < (1 << (bits // 2)): - # Generate the prime factors of n: p and q. - # By construciton, their product is always - # 2^{bits-1} < p*q < 2^bits. - size_q = bits // 2 - size_p = bits - size_q + while n.size_in_bits() != bits and d < (1 << (bits // 2)): + # Generate the prime factors of n: p and q. + # By construciton, their product is always + # 2^{bits-1} < p*q < 2^bits. + size_q = bits // 2 + size_p = bits - size_q - min_p = min_q = (Integer(1) << (2 * size_q - 1)).sqrt() - if size_q != size_p: - min_p = (Integer(1) << (2 * size_p - 1)).sqrt() + min_p = min_q = (Integer(1) << (2 * size_q - 1)).sqrt() + if size_q != size_p: + min_p = (Integer(1) << (2 * size_p - 1)).sqrt() - def filter_p(candidate): - return candidate > min_p and (candidate - 1).gcd(e) == 1 + def filter_p(candidate): + return candidate > min_p and (candidate - 1).gcd(e) == 1 - p = generate_probable_prime(exact_bits=size_p, - randfunc=randfunc, - prime_filter=filter_p) + p = generate_probable_prime( + exact_bits=size_p, + randfunc=randfunc, + prime_filter=filter_p, + ) - min_distance = Integer(1) << (bits // 2 - 100) + min_distance = Integer(1) << (bits // 2 - 100) - def filter_q(candidate): - return (candidate > min_q and - (candidate - 1).gcd(e) == 1 and - abs(candidate - p) > min_distance) + def filter_q(candidate): + return candidate > min_q and (candidate - 1).gcd(e) == 1 and abs(candidate - p) > min_distance - q = generate_probable_prime(exact_bits=size_q, - randfunc=randfunc, - prime_filter=filter_q) + q = generate_probable_prime( + exact_bits=size_q, + randfunc=randfunc, + prime_filter=filter_q, + ) - n = p * q - lcm = (p - 1).lcm(q - 1) - d = e.inverse(lcm) + n = p * q + lcm = (p - 1).lcm(q - 1) + d = e.inverse(lcm) - if p > q: - p, q = q, p + if p > q: + p, q = q, p - u = p.inverse(q) + u = p.inverse(q) - return RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) + return RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) def construct(rsa_components, consistency_check=True): - r"""Construct an RSA key from a tuple of valid RSA components. + r"""Construct an RSA key from a tuple of valid RSA components. The modulus **n** must be the product of two primes. The public exponent **e** must be odd and larger than 1. @@ -577,284 +618,286 @@ def construct(rsa_components, consistency_check=True): Returns: An RSA key object (:class:`RsaKey`). """ - class InputComps(object): - pass - - input_comps = InputComps() - for (comp, value) in zip(('n', 'e', 'd', 'p', 'q', 'u'), rsa_components): - setattr(input_comps, comp, Integer(value)) - - n = input_comps.n - e = input_comps.e - if not hasattr(input_comps, 'd'): - key = RsaKey(n=n, e=e) - else: - d = input_comps.d - if hasattr(input_comps, 'q'): - p = input_comps.p - q = input_comps.q - else: - # Compute factors p and q from the private exponent d. - # We assume that n has no more than two factors. - # See 8.2.2(i) in Handbook of Applied Cryptography. - ktot = d * e - 1 - # The quantity d*e-1 is a multiple of phi(n), even, - # and can be represented as t*2^s. - t = ktot - while t % 2 == 0: - t //= 2 - # Cycle through all multiplicative inverses in Zn. - # The algorithm is non-deterministic, but there is a 50% chance - # any candidate a leads to successful factoring. - # See "Digitalized Signatures and Public Key Functions as Intractable - # as Factorization", M. Rabin, 1979 - spotted = False - a = Integer(2) - while not spotted and a < 100: - k = Integer(t) - # Cycle through all values a^{t*2^i}=a^k - while k < ktot: - cand = pow(a, k, n) - # Check if a^k is a non-trivial root of unity (mod n) - if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: - # We have found a number such that (cand-1)(cand+1)=0 (mod n). - # Either of the terms divides n. - p = Integer(n).gcd(cand + 1) - spotted = True - break - k *= 2 - # This value was not any good... let's try another! - a += 2 - if not spotted: - raise ValueError("Unable to compute factors p and q from exponent d.") - # Found ! - assert ((n % p) == 0) - q = n // p - - if hasattr(input_comps, 'u'): - u = input_comps.u - else: - u = p.inverse(q) - - # Build key object - key = RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) - - # Verify consistency of the key - if consistency_check: - - # Modulus and public exponent must be coprime - if e <= 1 or e >= n: - raise ValueError("Invalid RSA public exponent") - if Integer(n).gcd(e) != 1: - raise ValueError("RSA public exponent is not coprime to modulus") - - # For RSA, modulus must be odd - if not n & 1: - raise ValueError("RSA modulus is not odd") - - if key.has_private(): - # Modulus and private exponent must be coprime - if d <= 1 or d >= n: - raise ValueError("Invalid RSA private exponent") - if Integer(n).gcd(d) != 1: - raise ValueError("RSA private exponent is not coprime to modulus") - # Modulus must be product of 2 primes - if p * q != n: - raise ValueError("RSA factors do not match modulus") - if test_probable_prime(p) == COMPOSITE: - raise ValueError("RSA factor p is composite") - if test_probable_prime(q) == COMPOSITE: - raise ValueError("RSA factor q is composite") - # See Carmichael theorem - phi = (p - 1) * (q - 1) - lcm = phi // (p - 1).gcd(q - 1) - if (e * d % int(lcm)) != 1: - raise ValueError("Invalid RSA condition") - if hasattr(key, 'u'): - # CRT coefficient - if u <= 1 or u >= q: - raise ValueError("Invalid RSA component u") - if (p * u % q) != 1: - raise ValueError("Invalid RSA component u with p") - - return key + class InputComps(object): + pass + + input_comps = InputComps() + for comp, value in zip(("n", "e", "d", "p", "q", "u"), rsa_components): + setattr(input_comps, comp, Integer(value)) + + n = input_comps.n + e = input_comps.e + if not hasattr(input_comps, "d"): + key = RsaKey(n=n, e=e) + else: + d = input_comps.d + if hasattr(input_comps, "q"): + p = input_comps.p + q = input_comps.q + else: + # Compute factors p and q from the private exponent d. + # We assume that n has no more than two factors. + # See 8.2.2(i) in Handbook of Applied Cryptography. + ktot = d * e - 1 + # The quantity d*e-1 is a multiple of phi(n), even, + # and can be represented as t*2^s. + t = ktot + while t % 2 == 0: + t //= 2 + # Cycle through all multiplicative inverses in Zn. + # The algorithm is non-deterministic, but there is a 50% chance + # any candidate a leads to successful factoring. + # See "Digitalized Signatures and Public Key Functions as Intractable + # as Factorization", M. Rabin, 1979 + spotted = False + a = Integer(2) + while not spotted and a < 100: + k = Integer(t) + # Cycle through all values a^{t*2^i}=a^k + while k < ktot: + cand = pow(a, k, n) + # Check if a^k is a non-trivial root of unity (mod n) + if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: + # We have found a number such that (cand-1)(cand+1)=0 (mod n). + # Either of the terms divides n. + p = Integer(n).gcd(cand + 1) + spotted = True + break + k *= 2 + # This value was not any good... let's try another! + a += 2 + if not spotted: + raise ValueError("Unable to compute factors p and q from exponent d.") + # Found ! + assert (n % p) == 0 + q = n // p + + if hasattr(input_comps, "u"): + u = input_comps.u + else: + u = p.inverse(q) + + # Build key object + key = RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) + + # Verify consistency of the key + if consistency_check: + # Modulus and public exponent must be coprime + if e <= 1 or e >= n: + raise ValueError("Invalid RSA public exponent") + if Integer(n).gcd(e) != 1: + raise ValueError("RSA public exponent is not coprime to modulus") + + # For RSA, modulus must be odd + if not n & 1: + raise ValueError("RSA modulus is not odd") + + if key.has_private(): + # Modulus and private exponent must be coprime + if d <= 1 or d >= n: + raise ValueError("Invalid RSA private exponent") + if Integer(n).gcd(d) != 1: + raise ValueError("RSA private exponent is not coprime to modulus") + # Modulus must be product of 2 primes + if p * q != n: + raise ValueError("RSA factors do not match modulus") + if test_probable_prime(p) == COMPOSITE: + raise ValueError("RSA factor p is composite") + if test_probable_prime(q) == COMPOSITE: + raise ValueError("RSA factor q is composite") + # See Carmichael theorem + phi = (p - 1) * (q - 1) + lcm = phi // (p - 1).gcd(q - 1) + if (e * d % int(lcm)) != 1: + raise ValueError("Invalid RSA condition") + if hasattr(key, "u"): + # CRT coefficient + if u <= 1 or u >= q: + raise ValueError("Invalid RSA component u") + if (p * u % q) != 1: + raise ValueError("Invalid RSA component u with p") + + return key def _import_pkcs1_private(encoded, *kwargs): - # RSAPrivateKey ::= SEQUENCE { - # version Version, - # modulus INTEGER, -- n - # publicExponent INTEGER, -- e - # privateExponent INTEGER, -- d - # prime1 INTEGER, -- p - # prime2 INTEGER, -- q - # exponent1 INTEGER, -- d mod (p-1) - # exponent2 INTEGER, -- d mod (q-1) - # coefficient INTEGER -- (inverse of q) mod p - # } - # - # Version ::= INTEGER - der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True) - if der[0] != 0: - raise ValueError("No PKCS#1 encoding of an RSA private key") - return construct(der[1:6] + [Integer(der[4]).inverse(der[5])]) + # RSAPrivateKey ::= SEQUENCE { + # version Version, + # modulus INTEGER, -- n + # publicExponent INTEGER, -- e + # privateExponent INTEGER, -- d + # prime1 INTEGER, -- p + # prime2 INTEGER, -- q + # exponent1 INTEGER, -- d mod (p-1) + # exponent2 INTEGER, -- d mod (q-1) + # coefficient INTEGER -- (inverse of q) mod p + # } + # + # Version ::= INTEGER + der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True) + if der[0] != 0: + raise ValueError("No PKCS#1 encoding of an RSA private key") + return construct(der[1:6] + [Integer(der[4]).inverse(der[5])]) def _import_pkcs1_public(encoded, *kwargs): - # RSAPublicKey ::= SEQUENCE { - # modulus INTEGER, -- n - # publicExponent INTEGER -- e - # } - der = DerSequence().decode(encoded, nr_elements=2, only_ints_expected=True) - return construct(der) + # RSAPublicKey ::= SEQUENCE { + # modulus INTEGER, -- n + # publicExponent INTEGER -- e + # } + der = DerSequence().decode(encoded, nr_elements=2, only_ints_expected=True) + return construct(der) def _import_subjectPublicKeyInfo(encoded, *kwargs): + oids = (oid, "1.2.840.113549.1.1.10") - oids = (oid, "1.2.840.113549.1.1.10") - - algoid, encoded_key, params = _expand_subject_public_key_info(encoded) - if algoid not in oids or params is not None: - raise ValueError("No RSA subjectPublicKeyInfo") - return _import_pkcs1_public(encoded_key) + algoid, encoded_key, params = _expand_subject_public_key_info(encoded) + if algoid not in oids or params is not None: + raise ValueError("No RSA subjectPublicKeyInfo") + return _import_pkcs1_public(encoded_key) def _import_x509_cert(encoded, *kwargs): - - sp_info = _extract_subject_public_key_info(encoded) - return _import_subjectPublicKeyInfo(sp_info) + sp_info = _extract_subject_public_key_info(encoded) + return _import_subjectPublicKeyInfo(sp_info) def _import_pkcs8(encoded, passphrase): - from Cryptodome.IO import PKCS8 + from Cryptodome.IO import PKCS8 - oids = (oid, "1.2.840.113549.1.1.10") + oids = (oid, "1.2.840.113549.1.1.10") - k = PKCS8.unwrap(encoded, passphrase) - if k[0] not in oids: - raise ValueError("No PKCS#8 encoded RSA key") - return _import_keyDER(k[1], passphrase) + k = PKCS8.unwrap(encoded, passphrase) + if k[0] not in oids: + raise ValueError("No PKCS#8 encoded RSA key") + return _import_keyDER(k[1], passphrase) def _import_keyDER(extern_key, passphrase): - """Import an RSA key (public or private half), encoded in DER form.""" + """Import an RSA key (public or private half), encoded in DER form.""" - decodings = (_import_pkcs1_private, - _import_pkcs1_public, - _import_subjectPublicKeyInfo, - _import_x509_cert, - _import_pkcs8) + decodings = ( + _import_pkcs1_private, + _import_pkcs1_public, + _import_subjectPublicKeyInfo, + _import_x509_cert, + _import_pkcs8, + ) - for decoding in decodings: - try: - return decoding(extern_key, passphrase) - except ValueError: - pass + for decoding in decodings: + try: + return decoding(extern_key, passphrase) + except ValueError: + pass - raise ValueError("RSA key format is not supported") + raise ValueError("RSA key format is not supported") def _import_openssh_private_rsa(data, password): + from ._openssh import ( + import_openssh_private_generic, + read_bytes, + read_string, + check_padding, + ) - from ._openssh import (import_openssh_private_generic, - read_bytes, read_string, check_padding) + ssh_name, decrypted = import_openssh_private_generic(data, password) - ssh_name, decrypted = import_openssh_private_generic(data, password) + if ssh_name != "ssh-rsa": + raise ValueError("This SSH key is not RSA") - if ssh_name != "ssh-rsa": - raise ValueError("This SSH key is not RSA") + n, decrypted = read_bytes(decrypted) + e, decrypted = read_bytes(decrypted) + d, decrypted = read_bytes(decrypted) + iqmp, decrypted = read_bytes(decrypted) + p, decrypted = read_bytes(decrypted) + q, decrypted = read_bytes(decrypted) - n, decrypted = read_bytes(decrypted) - e, decrypted = read_bytes(decrypted) - d, decrypted = read_bytes(decrypted) - iqmp, decrypted = read_bytes(decrypted) - p, decrypted = read_bytes(decrypted) - q, decrypted = read_bytes(decrypted) + _, padded = read_string(decrypted) # Comment + check_padding(padded) - _, padded = read_string(decrypted) # Comment - check_padding(padded) - - build = [Integer.from_bytes(x) for x in (n, e, d, q, p, iqmp)] - return construct(build) + build = [Integer.from_bytes(x) for x in (n, e, d, q, p, iqmp)] + return construct(build) def import_key(extern_key, passphrase=None): - """Import an RSA key (public or private). - - Args: - extern_key (string or byte string): - The RSA key to import. - - The following formats are supported for an RSA **public key**: - - - X.509 certificate (binary or PEM format) - - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM - encoding) - - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding) - - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII) - - The following formats are supported for an RSA **private key**: - - - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding) - - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` - DER SEQUENCE (binary or PEM encoding) - - OpenSSH (text format, introduced in `OpenSSH 6.5`_) - - For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. - - passphrase (string or byte string): - For private keys only, the pass phrase that encrypts the key. - - Returns: An RSA key object (:class:`RsaKey`). - - Raises: - ValueError/IndexError/TypeError: - When the given key cannot be parsed (possibly because the pass - phrase is wrong). - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf - """ - - from Cryptodome.IO import PEM - - extern_key = tobytes(extern_key) - if passphrase is not None: - passphrase = tobytes(passphrase) - - if extern_key.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'): - text_encoded = tostr(extern_key) - openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) - result = _import_openssh_private_rsa(openssh_encoded, passphrase) - return result - - if extern_key.startswith(b'-----'): - # This is probably a PEM encoded key. - (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) - if enc_flag: - passphrase = None - return _import_keyDER(der, passphrase) - - if extern_key.startswith(b'ssh-rsa '): - # This is probably an OpenSSH key - keystring = binascii.a2b_base64(extern_key.split(b' ')[1]) - keyparts = [] - while len(keystring) > 4: - length = struct.unpack(">I", keystring[:4])[0] - keyparts.append(keystring[4:4 + length]) - keystring = keystring[4 + length:] - e = Integer.from_bytes(keyparts[1]) - n = Integer.from_bytes(keyparts[2]) - return construct([n, e]) - - if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: - # This is probably a DER encoded key - return _import_keyDER(extern_key, passphrase) - - raise ValueError("RSA key format is not supported") + """Import an RSA key (public or private). + + Args: + extern_key (string or byte string): + The RSA key to import. + + The following formats are supported for an RSA **public key**: + + - X.509 certificate (binary or PEM format) + - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM + encoding) + - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding) + - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII) + + The following formats are supported for an RSA **private key**: + + - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding) + - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` + DER SEQUENCE (binary or PEM encoding) + - OpenSSH (text format, introduced in `OpenSSH 6.5`_) + + For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. + + passphrase (string or byte string): + For private keys only, the pass phrase that encrypts the key. + + Returns: An RSA key object (:class:`RsaKey`). + + Raises: + ValueError/IndexError/TypeError: + When the given key cannot be parsed (possibly because the pass + phrase is wrong). + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt + .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf + """ + + from Cryptodome.IO import PEM + + extern_key = tobytes(extern_key) + if passphrase is not None: + passphrase = tobytes(passphrase) + + if extern_key.startswith(b"-----BEGIN OPENSSH PRIVATE KEY"): + text_encoded = tostr(extern_key) + openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) + result = _import_openssh_private_rsa(openssh_encoded, passphrase) + return result + + if extern_key.startswith(b"-----"): + # This is probably a PEM encoded key. + (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) + if enc_flag: + passphrase = None + return _import_keyDER(der, passphrase) + + if extern_key.startswith(b"ssh-rsa "): + # This is probably an OpenSSH key + keystring = binascii.a2b_base64(extern_key.split(b" ")[1]) + keyparts = [] + while len(keystring) > 4: + length = struct.unpack(">I", keystring[:4])[0] + keyparts.append(keystring[4 : 4 + length]) + keystring = keystring[4 + length :] + e = Integer.from_bytes(keyparts[1]) + n = Integer.from_bytes(keyparts[2]) + return construct([n, e]) + + if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: + # This is probably a DER encoded key + return _import_keyDER(extern_key, passphrase) + + raise ValueError("RSA key format is not supported") # Backward compatibility diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/RSA.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/RSA.pyi index 85f6c4a3..c0183c74 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/RSA.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/RSA.pyi @@ -3,74 +3,77 @@ from typing import Callable, Union, Tuple, Optional, overload, Literal from Cryptodome.Math.Numbers import Integer from Cryptodome.IO._PBES import ProtParams -__all__ = ['generate', 'construct', 'import_key', - 'RsaKey', 'oid'] +__all__ = ["generate", "construct", "import_key", "RsaKey", "oid"] RNG = Callable[[int], bytes] class RsaKey(object): - def __init__(self, **kwargs: int) -> None: ... + def __init__(self, **kwargs: int) -> None: ... + @property + def n(self) -> int: ... + @property + def e(self) -> int: ... + @property + def d(self) -> int: ... + @property + def p(self) -> int: ... + @property + def q(self) -> int: ... + @property + def u(self) -> int: ... + @property + def invp(self) -> int: ... + @property + def invq(self) -> int: ... + def size_in_bits(self) -> int: ... + def size_in_bytes(self) -> int: ... + def has_private(self) -> bool: ... + def can_encrypt(self) -> bool: ... # legacy + def can_sign(self) -> bool: ... # legacy + def public_key(self) -> RsaKey: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def __getstate__(self) -> None: ... + def __repr__(self) -> str: ... + def __str__(self) -> str: ... + @overload + def export_key( + self, + format: Optional[str] = "PEM", + passphrase: Optional[str] = None, + pkcs: Optional[int] = 1, + protection: Optional[str] = None, + randfunc: Optional[RNG] = None, + ) -> bytes: ... + @overload + def export_key( + self, + *, + format: Optional[str] = "PEM", + passphrase: str, + pkcs: Literal[8], + protection: str, + randfunc: Optional[RNG] = None, + prot_params: ProtParams, + ) -> bytes: ... - @property - def n(self) -> int: ... - @property - def e(self) -> int: ... - @property - def d(self) -> int: ... - @property - def p(self) -> int: ... - @property - def q(self) -> int: ... - @property - def u(self) -> int: ... - @property - def invp(self) -> int: ... - @property - def invq(self) -> int: ... - - def size_in_bits(self) -> int: ... - def size_in_bytes(self) -> int: ... - def has_private(self) -> bool: ... - def can_encrypt(self) -> bool: ... # legacy - def can_sign(self) -> bool:... # legacy - def public_key(self) -> RsaKey: ... - def __eq__(self, other: object) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __getstate__(self) -> None: ... - def __repr__(self) -> str: ... - def __str__(self) -> str: ... - - @overload - def export_key(self, - format: Optional[str]="PEM", - passphrase: Optional[str]=None, - pkcs: Optional[int]=1, - protection: Optional[str]=None, - randfunc: Optional[RNG]=None - ) -> bytes: ... - @overload - def export_key(self, *, - format: Optional[str]="PEM", - passphrase: str, - pkcs: Literal[8], - protection: str, - randfunc: Optional[RNG]=None, - prot_params: ProtParams, - ) -> bytes: ... - - # Backward compatibility - exportKey = export_key - publickey = public_key + # Backward compatibility + exportKey = export_key + publickey = public_key Int = Union[int, Integer] -def generate(bits: int, randfunc: Optional[RNG]=None, e: Optional[int]=65537) -> RsaKey: ... -def construct(rsa_components: Union[Tuple[Int, Int], # n, e - Tuple[Int, Int, Int], # n, e, d - Tuple[Int, Int, Int, Int, Int], # n, e, d, p, q - Tuple[Int, Int, Int, Int, Int, Int]], # n, e, d, p, q, crt_q - consistency_check: Optional[bool]=True) -> RsaKey: ... -def import_key(extern_key: Union[str, bytes], passphrase: Optional[str]=None) -> RsaKey: ... +def generate(bits: int, randfunc: Optional[RNG] = None, e: Optional[int] = 65537) -> RsaKey: ... +def construct( + rsa_components: Union[ + Tuple[Int, Int], # n, e + Tuple[Int, Int, Int], # n, e, d + Tuple[Int, Int, Int, Int, Int], # n, e, d, p, q + Tuple[Int, Int, Int, Int, Int, Int], + ], # n, e, d, p, q, crt_q + consistency_check: Optional[bool] = True, +) -> RsaKey: ... +def import_key(extern_key: Union[str, bytes], passphrase: Optional[str] = None) -> RsaKey: ... # Backward compatibility importKey = import_key diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/__init__.py index 99b67a43..eba06cd6 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/__init__.py @@ -18,77 +18,86 @@ # SOFTWARE. # =================================================================== -from Cryptodome.Util.asn1 import (DerSequence, DerInteger, DerBitString, - DerObjectId, DerNull) +from Cryptodome.Util.asn1 import ( + DerSequence, + DerInteger, + DerBitString, + DerObjectId, + DerNull, +) def _expand_subject_public_key_info(encoded): - """Parse a SubjectPublicKeyInfo structure. - - It returns a triple with: - * OID (string) - * encoded public key (bytes) - * Algorithm parameters (bytes or None) - """ - - # - # SubjectPublicKeyInfo ::= SEQUENCE { - # algorithm AlgorithmIdentifier, - # subjectPublicKey BIT STRING - # } - # - # AlgorithmIdentifier ::= SEQUENCE { - # algorithm OBJECT IDENTIFIER, - # parameters ANY DEFINED BY algorithm OPTIONAL - # } - # - - spki = DerSequence().decode(encoded, nr_elements=2) - algo = DerSequence().decode(spki[0], nr_elements=(1,2)) - algo_oid = DerObjectId().decode(algo[0]) - spk = DerBitString().decode(spki[1]).value - - if len(algo) == 1: - algo_params = None - else: - try: - DerNull().decode(algo[1]) - algo_params = None - except: - algo_params = algo[1] - - return algo_oid.value, spk, algo_params + """Parse a SubjectPublicKeyInfo structure. + + It returns a triple with: + * OID (string) + * encoded public key (bytes) + * Algorithm parameters (bytes or None) + """ + + # + # SubjectPublicKeyInfo ::= SEQUENCE { + # algorithm AlgorithmIdentifier, + # subjectPublicKey BIT STRING + # } + # + # AlgorithmIdentifier ::= SEQUENCE { + # algorithm OBJECT IDENTIFIER, + # parameters ANY DEFINED BY algorithm OPTIONAL + # } + # + + spki = DerSequence().decode(encoded, nr_elements=2) + algo = DerSequence().decode(spki[0], nr_elements=(1, 2)) + algo_oid = DerObjectId().decode(algo[0]) + spk = DerBitString().decode(spki[1]).value + + if len(algo) == 1: + algo_params = None + else: + try: + DerNull().decode(algo[1]) + algo_params = None + except: + algo_params = algo[1] + + return algo_oid.value, spk, algo_params def _create_subject_public_key_info(algo_oid, public_key, params): + if params is None: + algorithm = DerSequence([DerObjectId(algo_oid)]) + else: + algorithm = DerSequence([DerObjectId(algo_oid), params]) - if params is None: - algorithm = DerSequence([DerObjectId(algo_oid)]) - else: - algorithm = DerSequence([DerObjectId(algo_oid), params]) - - spki = DerSequence([algorithm, - DerBitString(public_key) - ]) - return spki.encode() + spki = DerSequence( + [ + algorithm, + DerBitString(public_key), + ] + ) + return spki.encode() def _extract_subject_public_key_info(x509_certificate): - """Extract subjectPublicKeyInfo from a DER X.509 certificate.""" - - certificate = DerSequence().decode(x509_certificate, nr_elements=3) - tbs_certificate = DerSequence().decode(certificate[0], - nr_elements=range(6, 11)) - - index = 5 - try: - tbs_certificate[0] + 1 - # Version not present - version = 1 - except TypeError: - version = DerInteger(explicit=0).decode(tbs_certificate[0]).value - if version not in (2, 3): - raise ValueError("Incorrect X.509 certificate version") - index = 6 - - return tbs_certificate[index] + """Extract subjectPublicKeyInfo from a DER X.509 certificate.""" + + certificate = DerSequence().decode(x509_certificate, nr_elements=3) + tbs_certificate = DerSequence().decode( + certificate[0], + nr_elements=range(6, 11), + ) + + index = 5 + try: + tbs_certificate[0] + 1 + # Version not present + version = 1 + except TypeError: + version = DerInteger(explicit=0).decode(tbs_certificate[0]).value + if version not in (2, 3): + raise ValueError("Incorrect X.509 certificate version") + index = 6 + + return tbs_certificate[index] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_curve.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_curve.py index 0027f611..17d60c92 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_curve.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_curve.py @@ -18,20 +18,34 @@ # - rawlib the reference to the dynamic libary with the low-level functions # - validate a function that raises an exception if the the input point is invalid -class _Curve(object): - def __init__(self, p, b, order, Gx, Gy, G, modulus_bits, oid, context, - canonical, openssh, rawlib, validate=None): - self.p = p - self.b = b - self.order = order - self.Gx = Gx - self.Gy = Gy - self.G = G - self.modulus_bits = modulus_bits - self.oid = oid - self.context = context - self.canonical = canonical - self.openssh = openssh - self.rawlib = rawlib - self.validate = validate +class _Curve(object): + def __init__( + self, + p, + b, + order, + Gx, + Gy, + G, + modulus_bits, + oid, + context, + canonical, + openssh, + rawlib, + validate=None, + ): + self.p = p + self.b = b + self.order = order + self.Gx = Gx + self.Gy = Gy + self.G = G + self.modulus_bits = modulus_bits + self.oid = oid + self.context = context + self.canonical = canonical + self.openssh = openssh + self.rawlib = rawlib + self.validate = validate diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_edwards.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_edwards.py index 55de7b78..463dccfd 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_edwards.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_edwards.py @@ -3,17 +3,22 @@ from ._curve import _Curve from Cryptodome.Math.Numbers import Integer -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - SmartPointer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, +) def ed25519_curve(): - p = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed # 2**255 - 19 - order = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed - Gx = 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a - Gy = 0x6666666666666666666666666666666666666666666666666666666666666658 + p = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED # 2**255 - 19 + order = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED + Gx = 0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A + Gy = 0x6666666666666666666666666666666666666666666666666666666666666658 - _ed25519_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._ed25519", """ + _ed25519_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._ed25519", + """ typedef void Point; int ed25519_new_point(Point **out, const uint8_t x[32], @@ -28,41 +33,46 @@ def ed25519_curve(): int ed25519_double(Point *p); int ed25519_add(Point *P1, const Point *P2); int ed25519_scalar(Point *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed); -""") +""", + ) - class EcLib(object): - new_point = _ed25519_lib.ed25519_new_point - clone = _ed25519_lib.ed25519_clone - free_point = _ed25519_lib.ed25519_free_point - cmp = _ed25519_lib.ed25519_cmp - neg = _ed25519_lib.ed25519_neg - get_xy = _ed25519_lib.ed25519_get_xy - double = _ed25519_lib.ed25519_double - add = _ed25519_lib.ed25519_add - scalar = _ed25519_lib.ed25519_scalar + class EcLib(object): + new_point = _ed25519_lib.ed25519_new_point + clone = _ed25519_lib.ed25519_clone + free_point = _ed25519_lib.ed25519_free_point + cmp = _ed25519_lib.ed25519_cmp + neg = _ed25519_lib.ed25519_neg + get_xy = _ed25519_lib.ed25519_get_xy + double = _ed25519_lib.ed25519_double + add = _ed25519_lib.ed25519_add + scalar = _ed25519_lib.ed25519_scalar - ed25519 = _Curve(Integer(p), - None, - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 255, - "1.3.101.112", # RFC8410 - None, - "Ed25519", - "ssh-ed25519", - EcLib) - return ed25519 + ed25519 = _Curve( + Integer(p), + None, + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 255, + "1.3.101.112", # RFC8410 + None, + "Ed25519", + "ssh-ed25519", + EcLib, + ) + return ed25519 def ed448_curve(): - p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff # 2**448 - 2**224 - 1 - order = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3 - Gx = 0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e - Gy = 0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF # 2**448 - 2**224 - 1 + order = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3 + Gx = 0x4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E + Gy = 0x693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14 - _ed448_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._ed448", """ + _ed448_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._ed448", + """ typedef void EcContext; typedef void PointEd448; int ed448_new_context(EcContext **pec_ctx); @@ -81,36 +91,39 @@ def ed448_curve(): int ed448_double(PointEd448 *p); int ed448_add(PointEd448 *P1, const PointEd448 *P2); int ed448_scalar(PointEd448 *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed); -""") +""", + ) - class EcLib(object): - new_point = _ed448_lib.ed448_new_point - clone = _ed448_lib.ed448_clone - free_point = _ed448_lib.ed448_free_point - cmp = _ed448_lib.ed448_cmp - neg = _ed448_lib.ed448_neg - get_xy = _ed448_lib.ed448_get_xy - double = _ed448_lib.ed448_double - add = _ed448_lib.ed448_add - scalar = _ed448_lib.ed448_scalar + class EcLib(object): + new_point = _ed448_lib.ed448_new_point + clone = _ed448_lib.ed448_clone + free_point = _ed448_lib.ed448_free_point + cmp = _ed448_lib.ed448_cmp + neg = _ed448_lib.ed448_neg + get_xy = _ed448_lib.ed448_get_xy + double = _ed448_lib.ed448_double + add = _ed448_lib.ed448_add + scalar = _ed448_lib.ed448_scalar - ed448_context = VoidPointer() - result = _ed448_lib.ed448_new_context(ed448_context.address_of()) - if result: - raise ImportError("Error %d initializing Ed448 context" % result) + ed448_context = VoidPointer() + result = _ed448_lib.ed448_new_context(ed448_context.address_of()) + if result: + raise ImportError("Error %d initializing Ed448 context" % result) - context = SmartPointer(ed448_context.get(), _ed448_lib.ed448_free_context) + context = SmartPointer(ed448_context.get(), _ed448_lib.ed448_free_context) - ed448 = _Curve(Integer(p), - None, - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 448, - "1.3.101.113", # RFC8410 - context, - "Ed448", - None, - EcLib) - return ed448 + ed448 = _Curve( + Integer(p), + None, + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 448, + "1.3.101.113", # RFC8410 + context, + "Ed448", + None, + EcLib, + ) + return ed448 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_montgomery.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_montgomery.py index 5e5fd51d..b1010d0b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_montgomery.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_montgomery.py @@ -3,15 +3,20 @@ from ._curve import _Curve from Cryptodome.Math.Numbers import Integer -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - SmartPointer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, +) def curve25519_curve(): - p = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed # 2**255 - 19 - order = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed + p = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED # 2**255 - 19 + order = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED - _curve25519_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._curve25519", """ + _curve25519_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._curve25519", + """ typedef void Point; int curve25519_new_point(Point **out, @@ -23,69 +28,72 @@ def curve25519_curve(): int curve25519_get_x(uint8_t *xb, size_t modsize, Point *p); int curve25519_scalar(Point *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed); int curve25519_cmp(const Point *ecp1, const Point *ecp2); -""") - - class EcLib(object): - new_point = _curve25519_lib.curve25519_new_point - clone = _curve25519_lib.curve25519_clone - free_point = _curve25519_lib.curve25519_free_point - get_x = _curve25519_lib.curve25519_get_x - scalar = _curve25519_lib.curve25519_scalar - cmp = _curve25519_lib.curve25519_cmp - - def _validate_x25519_point(point): - - p2 = p * 2 - x1 = 325606250916557431795983626356110631294008115727848805560023387167927233504 - x2 = 39382357235489614581723060781553021112529911719440698176882885853963445705823 - - # http://cr.yp.to/ecdh.html#validate - deny_list = ( - 0, - 1, - x1, - x2, - p - 1, - p, - p + 1, - p + x1, - p + x2, - p2 - 1, - p2, - p2 + 1, - ) - - try: - valid = point.x not in deny_list - except ValueError: - valid = False - - if not valid: - raise ValueError("Invalid Curve25519 public key") - - curve25519 = _Curve(Integer(p), - None, - Integer(order), - Integer(9), - None, - None, - 255, - "1.3.101.110", # RFC8410 - None, - "Curve25519", - None, - EcLib, - _validate_x25519_point, - ) - - return curve25519 +""", + ) + + class EcLib(object): + new_point = _curve25519_lib.curve25519_new_point + clone = _curve25519_lib.curve25519_clone + free_point = _curve25519_lib.curve25519_free_point + get_x = _curve25519_lib.curve25519_get_x + scalar = _curve25519_lib.curve25519_scalar + cmp = _curve25519_lib.curve25519_cmp + + def _validate_x25519_point(point): + p2 = p * 2 + x1 = 325606250916557431795983626356110631294008115727848805560023387167927233504 + x2 = 39382357235489614581723060781553021112529911719440698176882885853963445705823 + + # http://cr.yp.to/ecdh.html#validate + deny_list = ( + 0, + 1, + x1, + x2, + p - 1, + p, + p + 1, + p + x1, + p + x2, + p2 - 1, + p2, + p2 + 1, + ) + + try: + valid = point.x not in deny_list + except ValueError: + valid = False + + if not valid: + raise ValueError("Invalid Curve25519 public key") + + curve25519 = _Curve( + Integer(p), + None, + Integer(order), + Integer(9), + None, + None, + 255, + "1.3.101.110", # RFC8410 + None, + "Curve25519", + None, + EcLib, + _validate_x25519_point, + ) + + return curve25519 def curve448_curve(): - p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff # 2**448 - 2**224 - 1 - order = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF # 2**448 - 2**224 - 1 + order = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3 - _curve448_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._curve448", """ + _curve448_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._curve448", + """ typedef void Curve448Context; typedef void Curve448Point; @@ -100,53 +108,55 @@ def curve448_curve(): int curve448_get_x(uint8_t *xb, size_t modsize, const Curve448Point *p); int curve448_scalar(Curve448Point *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed); int curve448_cmp(const Curve448Point *ecp1, const Curve448Point *ecp2); -""") - - class EcLib(object): - new_context = _curve448_lib.curve448_new_context - free_context = _curve448_lib.curve448_free_context - new_point = _curve448_lib.curve448_new_point - clone = _curve448_lib.curve448_clone - free_point = _curve448_lib.curve448_free_point - get_x = _curve448_lib.curve448_get_x - scalar = _curve448_lib.curve448_scalar - cmp = _curve448_lib.curve448_cmp - - curve448_context = VoidPointer() - result = EcLib.new_context(curve448_context.address_of()) - if result: - raise ImportError("Error %d initializing Curve448 context" % result) - - def _validate_x448_point(point): - deny_list = ( - 0, - 1, - p - 1, - p, - p + 1, - ) - - try: - valid = point.x not in deny_list - except ValueError: - valid = False - - if not valid: - raise ValueError("Invalid Curve448 public key") - - curve448 = _Curve(Integer(p), - None, - Integer(order), - Integer(5), - None, - None, - 448, - "1.3.101.111", # RFC8410 - SmartPointer(curve448_context.get(), EcLib.free_context), - "Curve448", - None, - EcLib, - _validate_x448_point, - ) - - return curve448 +""", + ) + + class EcLib(object): + new_context = _curve448_lib.curve448_new_context + free_context = _curve448_lib.curve448_free_context + new_point = _curve448_lib.curve448_new_point + clone = _curve448_lib.curve448_clone + free_point = _curve448_lib.curve448_free_point + get_x = _curve448_lib.curve448_get_x + scalar = _curve448_lib.curve448_scalar + cmp = _curve448_lib.curve448_cmp + + curve448_context = VoidPointer() + result = EcLib.new_context(curve448_context.address_of()) + if result: + raise ImportError("Error %d initializing Curve448 context" % result) + + def _validate_x448_point(point): + deny_list = ( + 0, + 1, + p - 1, + p, + p + 1, + ) + + try: + valid = point.x not in deny_list + except ValueError: + valid = False + + if not valid: + raise ValueError("Invalid Curve448 public key") + + curve448 = _Curve( + Integer(p), + None, + Integer(order), + Integer(5), + None, + None, + 448, + "1.3.101.111", # RFC8410 + SmartPointer(curve448_context.get(), EcLib.free_context), + "Curve448", + None, + EcLib, + _validate_x448_point, + ) + + return curve448 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_nist_ecc.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_nist_ecc.py index 3065c65b..affeb670 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_nist_ecc.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_nist_ecc.py @@ -3,14 +3,21 @@ from ._curve import _Curve from Cryptodome.Math.Numbers import Integer -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - SmartPointer, c_size_t, c_uint8_ptr, - c_ulonglong) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + VoidPointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + c_ulonglong, +) from Cryptodome.Util.number import long_to_bytes from Cryptodome.Random.random import getrandbits -_ec_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._ec_ws", """ +_ec_lib = load_pycryptodome_raw_lib( + "Cryptodome.PublicKey._ec_ws", + """ typedef void EcContext; typedef void EcPoint; int ec_ws_new_context(EcContext **pec_ctx, @@ -39,208 +46,224 @@ int ec_ws_clone(EcPoint **pecp2, const EcPoint *ecp); int ec_ws_cmp(const EcPoint *ecp1, const EcPoint *ecp2); int ec_ws_neg(EcPoint *p); -""") +""", +) class EcLib(object): - new_context = _ec_lib.ec_ws_new_context - free_context = _ec_lib.ec_ws_free_context - new_point = _ec_lib.ec_ws_new_point - free_point = _ec_lib.ec_ws_free_point - get_xy = _ec_lib.ec_ws_get_xy - double = _ec_lib.ec_ws_double - add = _ec_lib.ec_ws_add - scalar = _ec_lib.ec_ws_scalar - clone = _ec_lib.ec_ws_clone - cmp = _ec_lib.ec_ws_cmp - neg = _ec_lib.ec_ws_neg + new_context = _ec_lib.ec_ws_new_context + free_context = _ec_lib.ec_ws_free_context + new_point = _ec_lib.ec_ws_new_point + free_point = _ec_lib.ec_ws_free_point + get_xy = _ec_lib.ec_ws_get_xy + double = _ec_lib.ec_ws_double + add = _ec_lib.ec_ws_add + scalar = _ec_lib.ec_ws_scalar + clone = _ec_lib.ec_ws_clone + cmp = _ec_lib.ec_ws_cmp + neg = _ec_lib.ec_ws_neg def p192_curve(): - p = 0xfffffffffffffffffffffffffffffffeffffffffffffffff - b = 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1 - order = 0xffffffffffffffffffffffff99def836146bc9b1b4d22831 - Gx = 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 - Gy = 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811 - - p192_modulus = long_to_bytes(p, 24) - p192_b = long_to_bytes(b, 24) - p192_order = long_to_bytes(order, 24) - - ec_p192_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p192_context.address_of(), - c_uint8_ptr(p192_modulus), - c_uint8_ptr(p192_b), - c_uint8_ptr(p192_order), - c_size_t(len(p192_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-192 context" % result) - - context = SmartPointer(ec_p192_context.get(), _ec_lib.ec_ws_free_context) - p192 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 192, - "1.2.840.10045.3.1.1", # ANSI X9.62 / SEC2 - context, - "NIST P-192", - "ecdsa-sha2-nistp192", - EcLib) - return p192 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF + b = 0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1 + order = 0xFFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831 + Gx = 0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012 + Gy = 0x07192B95FFC8DA78631011ED6B24CDD573F977A11E794811 + + p192_modulus = long_to_bytes(p, 24) + p192_b = long_to_bytes(b, 24) + p192_order = long_to_bytes(order, 24) + + ec_p192_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p192_context.address_of(), + c_uint8_ptr(p192_modulus), + c_uint8_ptr(p192_b), + c_uint8_ptr(p192_order), + c_size_t(len(p192_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-192 context" % result) + + context = SmartPointer(ec_p192_context.get(), _ec_lib.ec_ws_free_context) + p192 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 192, + "1.2.840.10045.3.1.1", # ANSI X9.62 / SEC2 + context, + "NIST P-192", + "ecdsa-sha2-nistp192", + EcLib, + ) + return p192 def p224_curve(): - p = 0xffffffffffffffffffffffffffffffff000000000000000000000001 - b = 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4 - order = 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d - Gx = 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21 - Gy = 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34 - - p224_modulus = long_to_bytes(p, 28) - p224_b = long_to_bytes(b, 28) - p224_order = long_to_bytes(order, 28) - - ec_p224_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p224_context.address_of(), - c_uint8_ptr(p224_modulus), - c_uint8_ptr(p224_b), - c_uint8_ptr(p224_order), - c_size_t(len(p224_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-224 context" % result) - - context = SmartPointer(ec_p224_context.get(), _ec_lib.ec_ws_free_context) - p224 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 224, - "1.3.132.0.33", # SEC 2 - context, - "NIST P-224", - "ecdsa-sha2-nistp224", - EcLib) - return p224 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001 + b = 0xB4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4 + order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D + Gx = 0xB70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21 + Gy = 0xBD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34 + + p224_modulus = long_to_bytes(p, 28) + p224_b = long_to_bytes(b, 28) + p224_order = long_to_bytes(order, 28) + + ec_p224_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p224_context.address_of(), + c_uint8_ptr(p224_modulus), + c_uint8_ptr(p224_b), + c_uint8_ptr(p224_order), + c_size_t(len(p224_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-224 context" % result) + + context = SmartPointer(ec_p224_context.get(), _ec_lib.ec_ws_free_context) + p224 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 224, + "1.3.132.0.33", # SEC 2 + context, + "NIST P-224", + "ecdsa-sha2-nistp224", + EcLib, + ) + return p224 def p256_curve(): - p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff - b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b - order = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 - Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 - Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 - - p256_modulus = long_to_bytes(p, 32) - p256_b = long_to_bytes(b, 32) - p256_order = long_to_bytes(order, 32) - - ec_p256_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p256_context.address_of(), - c_uint8_ptr(p256_modulus), - c_uint8_ptr(p256_b), - c_uint8_ptr(p256_order), - c_size_t(len(p256_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-256 context" % result) - - context = SmartPointer(ec_p256_context.get(), _ec_lib.ec_ws_free_context) - p256 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 256, - "1.2.840.10045.3.1.7", # ANSI X9.62 / SEC2 - context, - "NIST P-256", - "ecdsa-sha2-nistp256", - EcLib) - return p256 + p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF + b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B + order = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 + Gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296 + Gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5 + + p256_modulus = long_to_bytes(p, 32) + p256_b = long_to_bytes(b, 32) + p256_order = long_to_bytes(order, 32) + + ec_p256_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p256_context.address_of(), + c_uint8_ptr(p256_modulus), + c_uint8_ptr(p256_b), + c_uint8_ptr(p256_order), + c_size_t(len(p256_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-256 context" % result) + + context = SmartPointer(ec_p256_context.get(), _ec_lib.ec_ws_free_context) + p256 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 256, + "1.2.840.10045.3.1.7", # ANSI X9.62 / SEC2 + context, + "NIST P-256", + "ecdsa-sha2-nistp256", + EcLib, + ) + return p256 def p384_curve(): - p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff - b = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef - order = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 - Gx = 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7 - Gy = 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F - - p384_modulus = long_to_bytes(p, 48) - p384_b = long_to_bytes(b, 48) - p384_order = long_to_bytes(order, 48) - - ec_p384_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p384_context.address_of(), - c_uint8_ptr(p384_modulus), - c_uint8_ptr(p384_b), - c_uint8_ptr(p384_order), - c_size_t(len(p384_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-384 context" % result) - - context = SmartPointer(ec_p384_context.get(), _ec_lib.ec_ws_free_context) - p384 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 384, - "1.3.132.0.34", # SEC 2 - context, - "NIST P-384", - "ecdsa-sha2-nistp384", - EcLib) - return p384 + p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF + b = 0xB3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF + order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973 + Gx = 0xAA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7 + Gy = 0x3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F + + p384_modulus = long_to_bytes(p, 48) + p384_b = long_to_bytes(b, 48) + p384_order = long_to_bytes(order, 48) + + ec_p384_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p384_context.address_of(), + c_uint8_ptr(p384_modulus), + c_uint8_ptr(p384_b), + c_uint8_ptr(p384_order), + c_size_t(len(p384_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-384 context" % result) + + context = SmartPointer(ec_p384_context.get(), _ec_lib.ec_ws_free_context) + p384 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 384, + "1.3.132.0.34", # SEC 2 + context, + "NIST P-384", + "ecdsa-sha2-nistp384", + EcLib, + ) + return p384 def p521_curve(): - p = 0x000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - b = 0x00000051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00 - order = 0x000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409 - Gx = 0x000000c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66 - Gy = 0x0000011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650 - - p521_modulus = long_to_bytes(p, 66) - p521_b = long_to_bytes(b, 66) - p521_order = long_to_bytes(order, 66) - - ec_p521_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p521_context.address_of(), - c_uint8_ptr(p521_modulus), - c_uint8_ptr(p521_b), - c_uint8_ptr(p521_order), - c_size_t(len(p521_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-521 context" % result) - - context = SmartPointer(ec_p521_context.get(), _ec_lib.ec_ws_free_context) - p521 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 521, - "1.3.132.0.35", # SEC 2 - context, - "NIST P-521", - "ecdsa-sha2-nistp521", - EcLib) - return p521 + p = 0x000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + b = 0x00000051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00 + order = 0x000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409 + Gx = 0x000000C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66 + Gy = 0x0000011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650 + + p521_modulus = long_to_bytes(p, 66) + p521_b = long_to_bytes(b, 66) + p521_order = long_to_bytes(order, 66) + + ec_p521_context = VoidPointer() + result = _ec_lib.ec_ws_new_context( + ec_p521_context.address_of(), + c_uint8_ptr(p521_modulus), + c_uint8_ptr(p521_b), + c_uint8_ptr(p521_order), + c_size_t(len(p521_modulus)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ImportError("Error %d initializing P-521 context" % result) + + context = SmartPointer(ec_p521_context.get(), _ec_lib.ec_ws_free_context) + p521 = _Curve( + Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 521, + "1.3.132.0.35", # SEC 2 + context, + "NIST P-521", + "ecdsa-sha2-nistp521", + EcLib, + ) + return p521 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_openssh.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_openssh.py index 53b16df5..a6f060f0 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_openssh.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_openssh.py @@ -38,98 +38,100 @@ def read_int4(data): - if len(data) < 4: - raise ValueError("Insufficient data") - value = struct.unpack(">I", data[:4])[0] - return value, data[4:] + if len(data) < 4: + raise ValueError("Insufficient data") + value = struct.unpack(">I", data[:4])[0] + return value, data[4:] def read_bytes(data): - size, data = read_int4(data) - if len(data) < size: - raise ValueError("Insufficient data (V)") - return data[:size], data[size:] + size, data = read_int4(data) + if len(data) < size: + raise ValueError("Insufficient data (V)") + return data[:size], data[size:] def read_string(data): - s, d = read_bytes(data) - return tostr(s), d + s, d = read_bytes(data) + return tostr(s), d def check_padding(pad): - for v, x in enumerate(pad): - if bord(x) != ((v + 1) & 0xFF): - raise ValueError("Incorrect padding") + for v, x in enumerate(pad): + if bord(x) != ((v + 1) & 0xFF): + raise ValueError("Incorrect padding") def import_openssh_private_generic(data, password): - # https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD - # https://github.com/openssh/openssh-portable/blob/master/sshkey.c - # https://coolaj86.com/articles/the-openssh-private-key-format/ - # https://coolaj86.com/articles/the-ssh-public-key-format/ - - if not data.startswith(b'openssh-key-v1\x00'): - raise ValueError("Incorrect magic value") - data = data[15:] - - ciphername, data = read_string(data) - kdfname, data = read_string(data) - kdfoptions, data = read_bytes(data) - number_of_keys, data = read_int4(data) - - if number_of_keys != 1: - raise ValueError("We only handle 1 key at a time") - - _, data = read_string(data) # Public key - encrypted, data = read_bytes(data) - if data: - raise ValueError("Too much data") - - if len(encrypted) % 8 != 0: - raise ValueError("Incorrect payload length") - - # Decrypt if necessary - if ciphername == 'none': - decrypted = encrypted - else: - if (ciphername, kdfname) != ('aes256-ctr', 'bcrypt'): - raise ValueError("Unsupported encryption scheme %s/%s" % (ciphername, kdfname)) - - salt, kdfoptions = read_bytes(kdfoptions) - iterations, kdfoptions = read_int4(kdfoptions) - - if len(salt) != 16: - raise ValueError("Incorrect salt length") - if kdfoptions: - raise ValueError("Too much data in kdfoptions") - - pwd_sha512 = SHA512.new(password).digest() - # We need 32+16 = 48 bytes, therefore 2 bcrypt outputs are sufficient - stripes = [] - constant = b"OxychromaticBlowfishSwatDynamite" - for count in range(1, 3): - salt_sha512 = SHA512.new(salt + struct.pack(">I", count)).digest() - out_le = _bcrypt_hash(pwd_sha512, 6, salt_sha512, constant, False) - out = struct.pack("IIIIIIII", out_le)) - acc = bytearray(out) - for _ in range(1, iterations): - out_le = _bcrypt_hash(pwd_sha512, 6, SHA512.new(out).digest(), constant, False) - out = struct.pack("IIIIIIII", out_le)) - strxor(acc, out, output=acc) - stripes.append(acc[:24]) - - result = b"".join([bchr(a)+bchr(b) for (a, b) in zip(*stripes)]) - - cipher = AES.new(result[:32], - AES.MODE_CTR, - nonce=b"", - initial_value=result[32:32+16]) - decrypted = cipher.decrypt(encrypted) - - checkint1, decrypted = read_int4(decrypted) - checkint2, decrypted = read_int4(decrypted) - if checkint1 != checkint2: - raise ValueError("Incorrect checksum") - ssh_name, decrypted = read_string(decrypted) - - return ssh_name, decrypted + # https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD + # https://github.com/openssh/openssh-portable/blob/master/sshkey.c + # https://coolaj86.com/articles/the-openssh-private-key-format/ + # https://coolaj86.com/articles/the-ssh-public-key-format/ + + if not data.startswith(b"openssh-key-v1\x00"): + raise ValueError("Incorrect magic value") + data = data[15:] + + ciphername, data = read_string(data) + kdfname, data = read_string(data) + kdfoptions, data = read_bytes(data) + number_of_keys, data = read_int4(data) + + if number_of_keys != 1: + raise ValueError("We only handle 1 key at a time") + + _, data = read_string(data) # Public key + encrypted, data = read_bytes(data) + if data: + raise ValueError("Too much data") + + if len(encrypted) % 8 != 0: + raise ValueError("Incorrect payload length") + + # Decrypt if necessary + if ciphername == "none": + decrypted = encrypted + else: + if (ciphername, kdfname) != ("aes256-ctr", "bcrypt"): + raise ValueError("Unsupported encryption scheme %s/%s" % (ciphername, kdfname)) + + salt, kdfoptions = read_bytes(kdfoptions) + iterations, kdfoptions = read_int4(kdfoptions) + + if len(salt) != 16: + raise ValueError("Incorrect salt length") + if kdfoptions: + raise ValueError("Too much data in kdfoptions") + + pwd_sha512 = SHA512.new(password).digest() + # We need 32+16 = 48 bytes, therefore 2 bcrypt outputs are sufficient + stripes = [] + constant = b"OxychromaticBlowfishSwatDynamite" + for count in range(1, 3): + salt_sha512 = SHA512.new(salt + struct.pack(">I", count)).digest() + out_le = _bcrypt_hash(pwd_sha512, 6, salt_sha512, constant, False) + out = struct.pack("IIIIIIII", out_le)) + acc = bytearray(out) + for _ in range(1, iterations): + out_le = _bcrypt_hash(pwd_sha512, 6, SHA512.new(out).digest(), constant, False) + out = struct.pack("IIIIIIII", out_le)) + strxor(acc, out, output=acc) + stripes.append(acc[:24]) + + result = b"".join([bchr(a) + bchr(b) for (a, b) in zip(*stripes)]) + + cipher = AES.new( + result[:32], + AES.MODE_CTR, + nonce=b"", + initial_value=result[32 : 32 + 16], + ) + decrypted = cipher.decrypt(encrypted) + + checkint1, decrypted = read_int4(decrypted) + checkint2, decrypted = read_int4(decrypted) + if checkint1 != checkint2: + raise ValueError("Incorrect checksum") + ssh_name, decrypted = read_string(decrypted) + + return ssh_name, decrypted diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_point.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_point.py index 2afce9bc..79911eee 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_point.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_point.py @@ -4,490 +4,558 @@ import threading from Cryptodome.Util.number import bytes_to_long, long_to_bytes -from Cryptodome.Util._raw_api import (VoidPointer, null_pointer, - SmartPointer, c_size_t, c_uint8_ptr, - c_ulonglong) +from Cryptodome.Util._raw_api import ( + VoidPointer, + null_pointer, + SmartPointer, + c_size_t, + c_uint8_ptr, + c_ulonglong, +) from Cryptodome.Math.Numbers import Integer from Cryptodome.Random.random import getrandbits class CurveID(object): - P192 = 1 - P224 = 2 - P256 = 3 - P384 = 4 - P521 = 5 - ED25519 = 6 - ED448 = 7 - CURVE25519 = 8 - CURVE448 = 9 + P192 = 1 + P224 = 2 + P256 = 3 + P384 = 4 + P521 = 5 + ED25519 = 6 + ED448 = 7 + CURVE25519 = 8 + CURVE448 = 9 class _Curves(object): - - curves = {} - curves_lock = threading.RLock() - - p192_names = ["p192", "NIST P-192", "P-192", "prime192v1", "secp192r1", - "nistp192"] - p224_names = ["p224", "NIST P-224", "P-224", "prime224v1", "secp224r1", - "nistp224"] - p256_names = ["p256", "NIST P-256", "P-256", "prime256v1", "secp256r1", - "nistp256"] - p384_names = ["p384", "NIST P-384", "P-384", "prime384v1", "secp384r1", - "nistp384"] - p521_names = ["p521", "NIST P-521", "P-521", "prime521v1", "secp521r1", - "nistp521"] - ed25519_names = ["ed25519", "Ed25519"] - ed448_names = ["ed448", "Ed448"] - curve25519_names = ["curve25519", "Curve25519", "X25519"] - curve448_names = ["curve448", "Curve448", "X448"] - - all_names = p192_names + p224_names + p256_names + p384_names + p521_names + \ - ed25519_names + ed448_names + curve25519_names + curve448_names - - def __contains__(self, item): - return item in self.all_names - - def __dir__(self): - return self.all_names - - def load(self, name): - if name in self.p192_names: - from . import _nist_ecc - p192 = _nist_ecc.p192_curve() - p192.id = CurveID.P192 - self.curves.update(dict.fromkeys(self.p192_names, p192)) - elif name in self.p224_names: - from . import _nist_ecc - p224 = _nist_ecc.p224_curve() - p224.id = CurveID.P224 - self.curves.update(dict.fromkeys(self.p224_names, p224)) - elif name in self.p256_names: - from . import _nist_ecc - p256 = _nist_ecc.p256_curve() - p256.id = CurveID.P256 - self.curves.update(dict.fromkeys(self.p256_names, p256)) - elif name in self.p384_names: - from . import _nist_ecc - p384 = _nist_ecc.p384_curve() - p384.id = CurveID.P384 - self.curves.update(dict.fromkeys(self.p384_names, p384)) - elif name in self.p521_names: - from . import _nist_ecc - p521 = _nist_ecc.p521_curve() - p521.id = CurveID.P521 - self.curves.update(dict.fromkeys(self.p521_names, p521)) - elif name in self.ed25519_names: - from . import _edwards - ed25519 = _edwards.ed25519_curve() - ed25519.id = CurveID.ED25519 - self.curves.update(dict.fromkeys(self.ed25519_names, ed25519)) - elif name in self.ed448_names: - from . import _edwards - ed448 = _edwards.ed448_curve() - ed448.id = CurveID.ED448 - self.curves.update(dict.fromkeys(self.ed448_names, ed448)) - elif name in self.curve25519_names: - from . import _montgomery - curve25519 = _montgomery.curve25519_curve() - curve25519.id = CurveID.CURVE25519 - self.curves.update(dict.fromkeys(self.curve25519_names, curve25519)) - elif name in self.curve448_names: - from . import _montgomery - curve448 = _montgomery.curve448_curve() - curve448.id = CurveID.CURVE448 - self.curves.update(dict.fromkeys(self.curve448_names, curve448)) - else: - raise ValueError("Unsupported curve '%s'" % name) - return self.curves[name] - - def __getitem__(self, name): - with self.curves_lock: - curve = self.curves.get(name) - if curve is None: - curve = self.load(name) - if name in self.curve25519_names or name in self.curve448_names: - curve.G = EccXPoint(curve.Gx, name) - else: - curve.G = EccPoint(curve.Gx, curve.Gy, name) - curve.is_edwards = curve.id in (CurveID.ED25519, CurveID.ED448) - curve.is_montgomery = curve.id in (CurveID.CURVE25519, - CurveID.CURVE448) - curve.is_weierstrass = not (curve.is_edwards or - curve.is_montgomery) - return curve - - def items(self): - # Load all curves - for name in self.all_names: - _ = self[name] - return self.curves.items() + curves = {} + curves_lock = threading.RLock() + + p192_names = [ + "p192", + "NIST P-192", + "P-192", + "prime192v1", + "secp192r1", + "nistp192", + ] + p224_names = [ + "p224", + "NIST P-224", + "P-224", + "prime224v1", + "secp224r1", + "nistp224", + ] + p256_names = [ + "p256", + "NIST P-256", + "P-256", + "prime256v1", + "secp256r1", + "nistp256", + ] + p384_names = [ + "p384", + "NIST P-384", + "P-384", + "prime384v1", + "secp384r1", + "nistp384", + ] + p521_names = [ + "p521", + "NIST P-521", + "P-521", + "prime521v1", + "secp521r1", + "nistp521", + ] + ed25519_names = ["ed25519", "Ed25519"] + ed448_names = ["ed448", "Ed448"] + curve25519_names = ["curve25519", "Curve25519", "X25519"] + curve448_names = ["curve448", "Curve448", "X448"] + + all_names = ( + p192_names + + p224_names + + p256_names + + p384_names + + p521_names + + ed25519_names + + ed448_names + + curve25519_names + + curve448_names + ) + + def __contains__(self, item): + return item in self.all_names + + def __dir__(self): + return self.all_names + + def load(self, name): + if name in self.p192_names: + from . import _nist_ecc + + p192 = _nist_ecc.p192_curve() + p192.id = CurveID.P192 + self.curves.update(dict.fromkeys(self.p192_names, p192)) + elif name in self.p224_names: + from . import _nist_ecc + + p224 = _nist_ecc.p224_curve() + p224.id = CurveID.P224 + self.curves.update(dict.fromkeys(self.p224_names, p224)) + elif name in self.p256_names: + from . import _nist_ecc + + p256 = _nist_ecc.p256_curve() + p256.id = CurveID.P256 + self.curves.update(dict.fromkeys(self.p256_names, p256)) + elif name in self.p384_names: + from . import _nist_ecc + + p384 = _nist_ecc.p384_curve() + p384.id = CurveID.P384 + self.curves.update(dict.fromkeys(self.p384_names, p384)) + elif name in self.p521_names: + from . import _nist_ecc + + p521 = _nist_ecc.p521_curve() + p521.id = CurveID.P521 + self.curves.update(dict.fromkeys(self.p521_names, p521)) + elif name in self.ed25519_names: + from . import _edwards + + ed25519 = _edwards.ed25519_curve() + ed25519.id = CurveID.ED25519 + self.curves.update(dict.fromkeys(self.ed25519_names, ed25519)) + elif name in self.ed448_names: + from . import _edwards + + ed448 = _edwards.ed448_curve() + ed448.id = CurveID.ED448 + self.curves.update(dict.fromkeys(self.ed448_names, ed448)) + elif name in self.curve25519_names: + from . import _montgomery + + curve25519 = _montgomery.curve25519_curve() + curve25519.id = CurveID.CURVE25519 + self.curves.update(dict.fromkeys(self.curve25519_names, curve25519)) + elif name in self.curve448_names: + from . import _montgomery + + curve448 = _montgomery.curve448_curve() + curve448.id = CurveID.CURVE448 + self.curves.update(dict.fromkeys(self.curve448_names, curve448)) + else: + raise ValueError("Unsupported curve '%s'" % name) + return self.curves[name] + + def __getitem__(self, name): + with self.curves_lock: + curve = self.curves.get(name) + if curve is None: + curve = self.load(name) + if name in self.curve25519_names or name in self.curve448_names: + curve.G = EccXPoint(curve.Gx, name) + else: + curve.G = EccPoint(curve.Gx, curve.Gy, name) + curve.is_edwards = curve.id in (CurveID.ED25519, CurveID.ED448) + curve.is_montgomery = curve.id in ( + CurveID.CURVE25519, + CurveID.CURVE448, + ) + curve.is_weierstrass = not (curve.is_edwards or curve.is_montgomery) + return curve + + def items(self): + # Load all curves + for name in self.all_names: + _ = self[name] + return self.curves.items() _curves = _Curves() class EccPoint(object): - """A class to model a point on an Elliptic Curve. - - The class supports operators for: - - * Adding two points: ``R = S + T`` - * In-place addition: ``S += T`` - * Negating a point: ``R = -T`` - * Comparing two points: ``if S == T: ...`` or ``if S != T: ...`` - * Multiplying a point by a scalar: ``R = S*k`` - * In-place multiplication by a scalar: ``T *= k`` - - :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. - :vartype curve: string - - :ivar x: The affine X-coordinate of the ECC point - :vartype x: integer - - :ivar y: The affine Y-coordinate of the ECC point - :vartype y: integer - - :ivar xy: The tuple with affine X- and Y- coordinates - """ - - def __init__(self, x, y, curve="p256"): - - try: - self._curve = _curves[curve] - except KeyError: - raise ValueError("Unknown curve name %s" % str(curve)) - self.curve = self._curve.canonical - - if self._curve.id == CurveID.CURVE25519: - raise ValueError("EccPoint cannot be created for Curve25519") - - modulus_bytes = self.size_in_bytes() - - xb = long_to_bytes(x, modulus_bytes) - yb = long_to_bytes(y, modulus_bytes) - if len(xb) != modulus_bytes or len(yb) != modulus_bytes: - raise ValueError("Incorrect coordinate length") - - new_point = self._curve.rawlib.new_point - free_func = self._curve.rawlib.free_point - - self._point = VoidPointer() - try: - context = self._curve.context.get() - except AttributeError: - context = null_pointer - result = new_point(self._point.address_of(), - c_uint8_ptr(xb), - c_uint8_ptr(yb), - c_size_t(modulus_bytes), - context) - - if result: - if result == 15: - raise ValueError("The EC point does not belong to the curve") - raise ValueError("Error %d while instantiating an EC point" % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the EC point - self._point = SmartPointer(self._point.get(), free_func) - - def set(self, point): - clone = self._curve.rawlib.clone - free_func = self._curve.rawlib.free_point - - self._point = VoidPointer() - result = clone(self._point.address_of(), - point._point.get()) - - if result: - raise ValueError("Error %d while cloning an EC point" % result) - - self._point = SmartPointer(self._point.get(), free_func) - return self - - def __eq__(self, point): - if not isinstance(point, EccPoint): - return False - - cmp_func = self._curve.rawlib.cmp - return 0 == cmp_func(self._point.get(), point._point.get()) - - # Only needed for Python 2 - def __ne__(self, point): - return not self == point - - def __neg__(self): - neg_func = self._curve.rawlib.neg - np = self.copy() - result = neg_func(np._point.get()) - if result: - raise ValueError("Error %d while inverting an EC point" % result) - return np - - def copy(self): - """Return a copy of this point.""" - x, y = self.xy - np = EccPoint(x, y, self.curve) - return np - - def is_point_at_infinity(self): - """``True`` if this is the *point-at-infinity*.""" - - if self._curve.is_edwards: - return self.x == 0 - else: - return self.xy == (0, 0) - - def point_at_infinity(self): - """Return the *point-at-infinity* for the curve.""" - - if self._curve.is_edwards: - return EccPoint(0, 1, self.curve) - else: - return EccPoint(0, 0, self.curve) - - @property - def x(self): - return self.xy[0] - - @property - def y(self): - return self.xy[1] - - @property - def xy(self): - modulus_bytes = self.size_in_bytes() - xb = bytearray(modulus_bytes) - yb = bytearray(modulus_bytes) - get_xy = self._curve.rawlib.get_xy - result = get_xy(c_uint8_ptr(xb), - c_uint8_ptr(yb), - c_size_t(modulus_bytes), - self._point.get()) - if result: - raise ValueError("Error %d while encoding an EC point" % result) - - return (Integer(bytes_to_long(xb)), Integer(bytes_to_long(yb))) - - def size_in_bytes(self): - """Size of each coordinate, in bytes.""" - return (self.size_in_bits() + 7) // 8 - - def size_in_bits(self): - """Size of each coordinate, in bits.""" - return self._curve.modulus_bits - - def double(self): - """Double this point (in-place operation). - - Returns: - This same object (to enable chaining). - """ - - double_func = self._curve.rawlib.double - result = double_func(self._point.get()) - if result: - raise ValueError("Error %d while doubling an EC point" % result) - return self - - def __iadd__(self, point): - """Add a second point to this one""" - - add_func = self._curve.rawlib.add - result = add_func(self._point.get(), point._point.get()) - if result: - if result == 16: - raise ValueError("EC points are not on the same curve") - raise ValueError("Error %d while adding two EC points" % result) - return self - - def __add__(self, point): - """Return a new point, the addition of this one and another""" - - np = self.copy() - np += point - return np - - def __imul__(self, scalar): - """Multiply this point by a scalar""" - - scalar_func = self._curve.rawlib.scalar - if scalar < 0: - raise ValueError("Scalar multiplication is only defined for non-negative integers") - sb = long_to_bytes(scalar) - result = scalar_func(self._point.get(), - c_uint8_ptr(sb), - c_size_t(len(sb)), - c_ulonglong(getrandbits(64))) - if result: - raise ValueError("Error %d during scalar multiplication" % result) - return self - - def __mul__(self, scalar): - """Return a new point, the scalar product of this one""" - - np = self.copy() - np *= scalar - return np - - def __rmul__(self, left_hand): - return self.__mul__(left_hand) + """A class to model a point on an Elliptic Curve. + + The class supports operators for: + + * Adding two points: ``R = S + T`` + * In-place addition: ``S += T`` + * Negating a point: ``R = -T`` + * Comparing two points: ``if S == T: ...`` or ``if S != T: ...`` + * Multiplying a point by a scalar: ``R = S*k`` + * In-place multiplication by a scalar: ``T *= k`` + + :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. + :vartype curve: string + + :ivar x: The affine X-coordinate of the ECC point + :vartype x: integer + + :ivar y: The affine Y-coordinate of the ECC point + :vartype y: integer + + :ivar xy: The tuple with affine X- and Y- coordinates + """ + + def __init__(self, x, y, curve="p256"): + try: + self._curve = _curves[curve] + except KeyError: + raise ValueError("Unknown curve name %s" % str(curve)) + self.curve = self._curve.canonical + + if self._curve.id == CurveID.CURVE25519: + raise ValueError("EccPoint cannot be created for Curve25519") + + modulus_bytes = self.size_in_bytes() + + xb = long_to_bytes(x, modulus_bytes) + yb = long_to_bytes(y, modulus_bytes) + if len(xb) != modulus_bytes or len(yb) != modulus_bytes: + raise ValueError("Incorrect coordinate length") + + new_point = self._curve.rawlib.new_point + free_func = self._curve.rawlib.free_point + + self._point = VoidPointer() + try: + context = self._curve.context.get() + except AttributeError: + context = null_pointer + result = new_point( + self._point.address_of(), + c_uint8_ptr(xb), + c_uint8_ptr(yb), + c_size_t(modulus_bytes), + context, + ) + + if result: + if result == 15: + raise ValueError("The EC point does not belong to the curve") + raise ValueError("Error %d while instantiating an EC point" % result) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the EC point + self._point = SmartPointer(self._point.get(), free_func) + + def set(self, point): + clone = self._curve.rawlib.clone + free_func = self._curve.rawlib.free_point + + self._point = VoidPointer() + result = clone( + self._point.address_of(), + point._point.get(), + ) + + if result: + raise ValueError("Error %d while cloning an EC point" % result) + + self._point = SmartPointer(self._point.get(), free_func) + return self + + def __eq__(self, point): + if not isinstance(point, EccPoint): + return False + + cmp_func = self._curve.rawlib.cmp + return 0 == cmp_func(self._point.get(), point._point.get()) + + # Only needed for Python 2 + def __ne__(self, point): + return not self == point + + def __neg__(self): + neg_func = self._curve.rawlib.neg + np = self.copy() + result = neg_func(np._point.get()) + if result: + raise ValueError("Error %d while inverting an EC point" % result) + return np + + def copy(self): + """Return a copy of this point.""" + x, y = self.xy + np = EccPoint(x, y, self.curve) + return np + + def is_point_at_infinity(self): + """``True`` if this is the *point-at-infinity*.""" + + if self._curve.is_edwards: + return self.x == 0 + else: + return self.xy == (0, 0) + + def point_at_infinity(self): + """Return the *point-at-infinity* for the curve.""" + + if self._curve.is_edwards: + return EccPoint(0, 1, self.curve) + else: + return EccPoint(0, 0, self.curve) + + @property + def x(self): + return self.xy[0] + + @property + def y(self): + return self.xy[1] + + @property + def xy(self): + modulus_bytes = self.size_in_bytes() + xb = bytearray(modulus_bytes) + yb = bytearray(modulus_bytes) + get_xy = self._curve.rawlib.get_xy + result = get_xy( + c_uint8_ptr(xb), + c_uint8_ptr(yb), + c_size_t(modulus_bytes), + self._point.get(), + ) + if result: + raise ValueError("Error %d while encoding an EC point" % result) + + return (Integer(bytes_to_long(xb)), Integer(bytes_to_long(yb))) + + def size_in_bytes(self): + """Size of each coordinate, in bytes.""" + return (self.size_in_bits() + 7) // 8 + + def size_in_bits(self): + """Size of each coordinate, in bits.""" + return self._curve.modulus_bits + + def double(self): + """Double this point (in-place operation). + + Returns: + This same object (to enable chaining). + """ + + double_func = self._curve.rawlib.double + result = double_func(self._point.get()) + if result: + raise ValueError("Error %d while doubling an EC point" % result) + return self + + def __iadd__(self, point): + """Add a second point to this one""" + + add_func = self._curve.rawlib.add + result = add_func(self._point.get(), point._point.get()) + if result: + if result == 16: + raise ValueError("EC points are not on the same curve") + raise ValueError("Error %d while adding two EC points" % result) + return self + + def __add__(self, point): + """Return a new point, the addition of this one and another""" + + np = self.copy() + np += point + return np + + def __imul__(self, scalar): + """Multiply this point by a scalar""" + + scalar_func = self._curve.rawlib.scalar + if scalar < 0: + raise ValueError("Scalar multiplication is only defined for non-negative integers") + sb = long_to_bytes(scalar) + result = scalar_func( + self._point.get(), + c_uint8_ptr(sb), + c_size_t(len(sb)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ValueError("Error %d during scalar multiplication" % result) + return self + + def __mul__(self, scalar): + """Return a new point, the scalar product of this one""" + + np = self.copy() + np *= scalar + return np + + def __rmul__(self, left_hand): + return self.__mul__(left_hand) class EccXPoint(object): - """A class to model a point on an Elliptic Curve, - where only the X-coordinate is exposed. - - The class supports operators for: - - * Multiplying a point by a scalar: ``R = S*k`` - * In-place multiplication by a scalar: ``T *= k`` - - :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. - :vartype curve: string - - :ivar x: The affine X-coordinate of the ECC point - :vartype x: integer - """ - - def __init__(self, x, curve): - # Once encoded, x must not exceed the length of the modulus, - # but its value may match or exceed the modulus itself - # (i.e., non-canonical value) - - try: - self._curve = _curves[curve] - except KeyError: - raise ValueError("Unknown curve name %s" % str(curve)) - self.curve = self._curve.canonical - - if self._curve.id not in (CurveID.CURVE25519, CurveID.CURVE448): - raise ValueError("EccXPoint can only be created for Curve25519/Curve448") - - new_point = self._curve.rawlib.new_point - free_func = self._curve.rawlib.free_point - - self._point = VoidPointer() - try: - context = self._curve.context.get() - except AttributeError: - context = null_pointer - - modulus_bytes = self.size_in_bytes() - - if x is None: - xb = null_pointer - else: - xb = c_uint8_ptr(long_to_bytes(x, modulus_bytes)) - if len(xb) != modulus_bytes: - raise ValueError("Incorrect coordinate length") - - self._point = VoidPointer() - result = new_point(self._point.address_of(), - xb, - c_size_t(modulus_bytes), - context) - - if result == 15: - raise ValueError("The EC point does not belong to the curve") - if result: - raise ValueError("Error %d while instantiating an EC point" % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the EC point - self._point = SmartPointer(self._point.get(), free_func) - - def set(self, point): - clone = self._curve.rawlib.clone - free_func = self._curve.rawlib.free_point - - self._point = VoidPointer() - result = clone(self._point.address_of(), - point._point.get()) - if result: - raise ValueError("Error %d while cloning an EC point" % result) - - self._point = SmartPointer(self._point.get(), free_func) - return self - - def __eq__(self, point): - if not isinstance(point, EccXPoint): - return False - - cmp_func = self._curve.rawlib.cmp - p1 = self._point.get() - p2 = point._point.get() - res = cmp_func(p1, p2) - return 0 == res - - def copy(self): - """Return a copy of this point.""" - - try: - x = self.x - except ValueError: - return self.point_at_infinity() - return EccXPoint(x, self.curve) - - def is_point_at_infinity(self): - """``True`` if this is the *point-at-infinity*.""" - - try: - _ = self.x - except ValueError: - return True - return False - - def point_at_infinity(self): - """Return the *point-at-infinity* for the curve.""" - - return EccXPoint(None, self.curve) - - @property - def x(self): - modulus_bytes = self.size_in_bytes() - xb = bytearray(modulus_bytes) - get_x = self._curve.rawlib.get_x - result = get_x(c_uint8_ptr(xb), - c_size_t(modulus_bytes), - self._point.get()) - if result == 19: # ERR_ECC_PAI - raise ValueError("No X coordinate for the point at infinity") - if result: - raise ValueError("Error %d while getting X of an EC point" % result) - return Integer(bytes_to_long(xb)) - - def size_in_bytes(self): - """Size of each coordinate, in bytes.""" - return (self.size_in_bits() + 7) // 8 - - def size_in_bits(self): - """Size of each coordinate, in bits.""" - return self._curve.modulus_bits - - def __imul__(self, scalar): - """Multiply this point by a scalar""" - - scalar_func = self._curve.rawlib.scalar - if scalar < 0: - raise ValueError("Scalar multiplication is only defined for non-negative integers") - sb = long_to_bytes(scalar) - result = scalar_func(self._point.get(), - c_uint8_ptr(sb), - c_size_t(len(sb)), - c_ulonglong(getrandbits(64))) - if result: - raise ValueError("Error %d during scalar multiplication" % result) - return self - - def __mul__(self, scalar): - """Return a new point, the scalar product of this one""" - - np = self.copy() - np *= scalar - return np - - def __rmul__(self, left_hand): - return self.__mul__(left_hand) + """A class to model a point on an Elliptic Curve, + where only the X-coordinate is exposed. + + The class supports operators for: + + * Multiplying a point by a scalar: ``R = S*k`` + * In-place multiplication by a scalar: ``T *= k`` + + :ivar curve: The **canonical** name of the curve as defined in the `ECC table`_. + :vartype curve: string + + :ivar x: The affine X-coordinate of the ECC point + :vartype x: integer + """ + + def __init__(self, x, curve): + # Once encoded, x must not exceed the length of the modulus, + # but its value may match or exceed the modulus itself + # (i.e., non-canonical value) + + try: + self._curve = _curves[curve] + except KeyError: + raise ValueError("Unknown curve name %s" % str(curve)) + self.curve = self._curve.canonical + + if self._curve.id not in (CurveID.CURVE25519, CurveID.CURVE448): + raise ValueError("EccXPoint can only be created for Curve25519/Curve448") + + new_point = self._curve.rawlib.new_point + free_func = self._curve.rawlib.free_point + + self._point = VoidPointer() + try: + context = self._curve.context.get() + except AttributeError: + context = null_pointer + + modulus_bytes = self.size_in_bytes() + + if x is None: + xb = null_pointer + else: + xb = c_uint8_ptr(long_to_bytes(x, modulus_bytes)) + if len(xb) != modulus_bytes: + raise ValueError("Incorrect coordinate length") + + self._point = VoidPointer() + result = new_point( + self._point.address_of(), + xb, + c_size_t(modulus_bytes), + context, + ) + + if result == 15: + raise ValueError("The EC point does not belong to the curve") + if result: + raise ValueError("Error %d while instantiating an EC point" % result) + + # Ensure that object disposal of this Python object will (eventually) + # free the memory allocated by the raw library for the EC point + self._point = SmartPointer(self._point.get(), free_func) + + def set(self, point): + clone = self._curve.rawlib.clone + free_func = self._curve.rawlib.free_point + + self._point = VoidPointer() + result = clone( + self._point.address_of(), + point._point.get(), + ) + if result: + raise ValueError("Error %d while cloning an EC point" % result) + + self._point = SmartPointer(self._point.get(), free_func) + return self + + def __eq__(self, point): + if not isinstance(point, EccXPoint): + return False + + cmp_func = self._curve.rawlib.cmp + p1 = self._point.get() + p2 = point._point.get() + res = cmp_func(p1, p2) + return 0 == res + + def copy(self): + """Return a copy of this point.""" + + try: + x = self.x + except ValueError: + return self.point_at_infinity() + return EccXPoint(x, self.curve) + + def is_point_at_infinity(self): + """``True`` if this is the *point-at-infinity*.""" + + try: + _ = self.x + except ValueError: + return True + return False + + def point_at_infinity(self): + """Return the *point-at-infinity* for the curve.""" + + return EccXPoint(None, self.curve) + + @property + def x(self): + modulus_bytes = self.size_in_bytes() + xb = bytearray(modulus_bytes) + get_x = self._curve.rawlib.get_x + result = get_x( + c_uint8_ptr(xb), + c_size_t(modulus_bytes), + self._point.get(), + ) + if result == 19: # ERR_ECC_PAI + raise ValueError("No X coordinate for the point at infinity") + if result: + raise ValueError("Error %d while getting X of an EC point" % result) + return Integer(bytes_to_long(xb)) + + def size_in_bytes(self): + """Size of each coordinate, in bytes.""" + return (self.size_in_bits() + 7) // 8 + + def size_in_bits(self): + """Size of each coordinate, in bits.""" + return self._curve.modulus_bits + + def __imul__(self, scalar): + """Multiply this point by a scalar""" + + scalar_func = self._curve.rawlib.scalar + if scalar < 0: + raise ValueError("Scalar multiplication is only defined for non-negative integers") + sb = long_to_bytes(scalar) + result = scalar_func( + self._point.get(), + c_uint8_ptr(sb), + c_size_t(len(sb)), + c_ulonglong(getrandbits(64)), + ) + if result: + raise ValueError("Error %d during scalar multiplication" % result) + return self + + def __mul__(self, scalar): + """Return a new point, the scalar product of this one""" + + np = self.copy() + np *= scalar + return np + + def __rmul__(self, left_hand): + return self.__mul__(left_hand) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_point.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_point.pyi index 2518e2e4..3a9ac6cd 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_point.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/PublicKey/_point.pyi @@ -3,47 +3,42 @@ from typing import Union, Optional, Tuple from Cryptodome.Math.Numbers import Integer class EccPoint(object): - curve: str - def __init__(self, - x: Union[int, Integer], - y: Union[int, Integer], - curve: Optional[str] = ...) -> None: ... - - def set(self, point: EccPoint) -> EccPoint: ... - def __eq__(self, point: object) -> bool: ... - def __neg__(self) -> EccPoint: ... - def copy(self) -> EccPoint: ... - def is_point_at_infinity(self) -> bool: ... - def point_at_infinity(self) -> EccPoint: ... - @property - def x(self) -> int: ... - @property - def y(self) -> int: ... - @property - def xy(self) -> Tuple[int, int]: ... - def size_in_bytes(self) -> int: ... - def size_in_bits(self) -> int: ... - def double(self) -> EccPoint: ... - def __iadd__(self, point: EccPoint) -> EccPoint: ... - def __add__(self, point: EccPoint) -> EccPoint: ... - def __imul__(self, scalar: int) -> EccPoint: ... - def __mul__(self, scalar: int) -> EccPoint: ... - + curve: str + def __init__( + self, x: Union[int, Integer], y: Union[int, Integer], curve: Optional[str] = ... + ) -> None: ... + def set(self, point: EccPoint) -> EccPoint: ... + def __eq__(self, point: object) -> bool: ... + def __neg__(self) -> EccPoint: ... + def copy(self) -> EccPoint: ... + def is_point_at_infinity(self) -> bool: ... + def point_at_infinity(self) -> EccPoint: ... + @property + def x(self) -> int: ... + @property + def y(self) -> int: ... + @property + def xy(self) -> Tuple[int, int]: ... + def size_in_bytes(self) -> int: ... + def size_in_bits(self) -> int: ... + def double(self) -> EccPoint: ... + def __iadd__(self, point: EccPoint) -> EccPoint: ... + def __add__(self, point: EccPoint) -> EccPoint: ... + def __imul__(self, scalar: int) -> EccPoint: ... + def __mul__(self, scalar: int) -> EccPoint: ... class EccXPoint(object): - curve: str - def __init__(self, - x: Union[int, Integer], - curve: Optional[str] = ...) -> None: ... - def set(self, point: EccXPoint) -> EccXPoint: ... - def __eq__(self, point: object) -> bool: ... - def copy(self) -> EccXPoint: ... - def is_point_at_infinity(self) -> bool: ... - def point_at_infinity(self) -> EccXPoint: ... - @property - def x(self) -> int: ... - def size_in_bytes(self) -> int: ... - def size_in_bits(self) -> int: ... - def __imul__(self, scalar: int) -> EccXPoint: ... - def __mul__(self, scalar: int) -> EccXPoint: ... - def __rmul__(self, left_hand: int) -> EccXPoint: ... + curve: str + def __init__(self, x: Union[int, Integer], curve: Optional[str] = ...) -> None: ... + def set(self, point: EccXPoint) -> EccXPoint: ... + def __eq__(self, point: object) -> bool: ... + def copy(self) -> EccXPoint: ... + def is_point_at_infinity(self) -> bool: ... + def point_at_infinity(self) -> EccXPoint: ... + @property + def x(self) -> int: ... + def size_in_bytes(self) -> int: ... + def size_in_bits(self) -> int: ... + def __imul__(self, scalar: int) -> EccXPoint: ... + def __mul__(self, scalar: int) -> EccXPoint: ... + def __rmul__(self, left_hand: int) -> EccXPoint: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/__init__.py index fd18d864..860ef73c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/__init__.py @@ -20,38 +20,37 @@ # SOFTWARE. # =================================================================== -__all__ = ['new', 'get_random_bytes'] +__all__ = ["new", "get_random_bytes"] from os import urandom + class _UrandomRNG(object): + def read(self, n): + """Return a random byte string of the desired size.""" + return urandom(n) - def read(self, n): - """Return a random byte string of the desired size.""" - return urandom(n) + def flush(self): + """Method provided for backward compatibility only.""" + pass - def flush(self): - """Method provided for backward compatibility only.""" - pass + def reinit(self): + """Method provided for backward compatibility only.""" + pass - def reinit(self): - """Method provided for backward compatibility only.""" - pass + def close(self): + """Method provided for backward compatibility only.""" + pass - def close(self): - """Method provided for backward compatibility only.""" - pass - def new(*args, **kwargs): - """Return a file-like object that outputs cryptographically random bytes.""" - return _UrandomRNG() + """Return a file-like object that outputs cryptographically random bytes.""" + return _UrandomRNG() def atfork(): - pass + pass #: Function that returns a random byte string of the desired size. get_random_bytes = urandom - diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/__init__.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/__init__.pyi index ddc5b9b0..1cb3dd15 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/__init__.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/__init__.pyi @@ -1,19 +1,16 @@ from typing import Any -__all__ = ['new', 'get_random_bytes'] +__all__ = ["new", "get_random_bytes"] from os import urandom class _UrandomRNG(object): - - def read(self, n: int) -> bytes:... - def flush(self) -> None: ... - def reinit(self) -> None: ... - def close(self) -> None: ... + def read(self, n: int) -> bytes: ... + def flush(self) -> None: ... + def reinit(self) -> None: ... + def close(self) -> None: ... def new(*args: Any, **kwargs: Any) -> _UrandomRNG: ... - def atfork() -> None: ... get_random_bytes = urandom - diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/random.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/random.py index da307957..bc096715 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/random.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/random.py @@ -22,107 +22,108 @@ # SOFTWARE. # =================================================================== -__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample'] +__all__ = ["StrongRandom", "getrandbits", "randrange", "randint", "choice", "shuffle", "sample"] from Cryptodome import Random from Cryptodome.Util.py3compat import is_native_int + class StrongRandom(object): - def __init__(self, rng=None, randfunc=None): - if randfunc is None and rng is None: - self._randfunc = None - elif randfunc is not None and rng is None: - self._randfunc = randfunc - elif randfunc is None and rng is not None: - self._randfunc = rng.read - else: - raise ValueError("Cannot specify both 'rng' and 'randfunc'") - - def getrandbits(self, k): - """Return an integer with k random bits.""" - - if self._randfunc is None: - self._randfunc = Random.new().read - mask = (1 << k) - 1 - return mask & bytes_to_long(self._randfunc(ceil_div(k, 8))) - - def randrange(self, *args): - """randrange([start,] stop[, step]): - Return a randomly-selected element from range(start, stop, step).""" - if len(args) == 3: - (start, stop, step) = args - elif len(args) == 2: - (start, stop) = args - step = 1 - elif len(args) == 1: - (stop,) = args - start = 0 - step = 1 - else: - raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),)) - if (not is_native_int(start) or not is_native_int(stop) or not - is_native_int(step)): - raise TypeError("randrange requires integer arguments") - if step == 0: - raise ValueError("randrange step argument must not be zero") - - num_choices = ceil_div(stop - start, step) - if num_choices < 0: - num_choices = 0 - if num_choices < 1: - raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step)) - - # Pick a random number in the range of possible numbers - r = num_choices - while r >= num_choices: - r = self.getrandbits(size(num_choices)) - - return start + (step * r) - - def randint(self, a, b): - """Return a random integer N such that a <= N <= b.""" - if not is_native_int(a) or not is_native_int(b): - raise TypeError("randint requires integer arguments") - N = self.randrange(a, b+1) - assert a <= N <= b - return N - - def choice(self, seq): - """Return a random element from a (non-empty) sequence. - - If the seqence is empty, raises IndexError. - """ - if len(seq) == 0: - raise IndexError("empty sequence") - return seq[self.randrange(len(seq))] - - def shuffle(self, x): - """Shuffle the sequence in place.""" - # Fisher-Yates shuffle. O(n) - # See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle - # Working backwards from the end of the array, we choose a random item - # from the remaining items until all items have been chosen. - for i in range(len(x)-1, 0, -1): # iterate from len(x)-1 downto 1 - j = self.randrange(0, i+1) # choose random j such that 0 <= j <= i - x[i], x[j] = x[j], x[i] # exchange x[i] and x[j] - - def sample(self, population, k): - """Return a k-length list of unique elements chosen from the population sequence.""" - - num_choices = len(population) - if k > num_choices: - raise ValueError("sample larger than population") - - retval = [] - selected = {} # we emulate a set using a dict here - for i in range(k): - r = None - while r is None or r in selected: - r = self.randrange(num_choices) - retval.append(population[r]) - selected[r] = 1 - return retval + def __init__(self, rng=None, randfunc=None): + if randfunc is None and rng is None: + self._randfunc = None + elif randfunc is not None and rng is None: + self._randfunc = randfunc + elif randfunc is None and rng is not None: + self._randfunc = rng.read + else: + raise ValueError("Cannot specify both 'rng' and 'randfunc'") + + def getrandbits(self, k): + """Return an integer with k random bits.""" + + if self._randfunc is None: + self._randfunc = Random.new().read + mask = (1 << k) - 1 + return mask & bytes_to_long(self._randfunc(ceil_div(k, 8))) + + def randrange(self, *args): + """randrange([start,] stop[, step]): + Return a randomly-selected element from range(start, stop, step).""" + if len(args) == 3: + (start, stop, step) = args + elif len(args) == 2: + (start, stop) = args + step = 1 + elif len(args) == 1: + (stop,) = args + start = 0 + step = 1 + else: + raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),)) + if not is_native_int(start) or not is_native_int(stop) or not is_native_int(step): + raise TypeError("randrange requires integer arguments") + if step == 0: + raise ValueError("randrange step argument must not be zero") + + num_choices = ceil_div(stop - start, step) + if num_choices < 0: + num_choices = 0 + if num_choices < 1: + raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step)) + + # Pick a random number in the range of possible numbers + r = num_choices + while r >= num_choices: + r = self.getrandbits(size(num_choices)) + + return start + (step * r) + + def randint(self, a, b): + """Return a random integer N such that a <= N <= b.""" + if not is_native_int(a) or not is_native_int(b): + raise TypeError("randint requires integer arguments") + N = self.randrange(a, b + 1) + assert a <= N <= b + return N + + def choice(self, seq): + """Return a random element from a (non-empty) sequence. + + If the seqence is empty, raises IndexError. + """ + if len(seq) == 0: + raise IndexError("empty sequence") + return seq[self.randrange(len(seq))] + + def shuffle(self, x): + """Shuffle the sequence in place.""" + # Fisher-Yates shuffle. O(n) + # See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + # Working backwards from the end of the array, we choose a random item + # from the remaining items until all items have been chosen. + for i in range(len(x) - 1, 0, -1): # iterate from len(x)-1 downto 1 + j = self.randrange(0, i + 1) # choose random j such that 0 <= j <= i + x[i], x[j] = x[j], x[i] # exchange x[i] and x[j] + + def sample(self, population, k): + """Return a k-length list of unique elements chosen from the population sequence.""" + + num_choices = len(population) + if k > num_choices: + raise ValueError("sample larger than population") + + retval = [] + selected = {} # we emulate a set using a dict here + for i in range(k): + r = None + while r is None or r in selected: + r = self.randrange(num_choices) + retval.append(population[r]) + selected[r] = 1 + return retval + _r = StrongRandom() getrandbits = _r.getrandbits @@ -133,6 +134,6 @@ def sample(self, population, k): sample = _r.sample # These are at the bottom to avoid problems with recursive imports -from Cryptodome.Util.number import ceil_div, bytes_to_long, long_to_bytes, size +from Cryptodome.Util.number import ceil_div, bytes_to_long, size # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/random.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/random.pyi index 9b7cf7ee..dac98082 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/random.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Random/random.pyi @@ -1,17 +1,19 @@ -from typing import Callable, Tuple, Union, Sequence, Any, Optional, TypeVar +from typing import Callable, Sequence, Any, Optional, TypeVar -__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample'] +__all__ = ["StrongRandom", "getrandbits", "randrange", "randint", "choice", "shuffle", "sample"] -T = TypeVar('T') +T = TypeVar("T") class StrongRandom(object): - def __init__(self, rng: Optional[Any]=None, randfunc: Optional[Callable]=None) -> None: ... # TODO What is rng? - def getrandbits(self, k: int) -> int: ... - def randrange(self, start: int, stop: int = ..., step: int = ...) -> int: ... - def randint(self, a: int, b: int) -> int: ... - def choice(self, seq: Sequence[T]) -> T: ... - def shuffle(self, x: Sequence) -> None: ... - def sample(self, population: Sequence, k: int) -> list: ... + def __init__( + self, rng: Optional[Any] = None, randfunc: Optional[Callable] = None + ) -> None: ... # TODO What is rng? + def getrandbits(self, k: int) -> int: ... + def randrange(self, start: int, stop: int = ..., step: int = ...) -> int: ... + def randint(self, a: int, b: int) -> int: ... + def choice(self, seq: Sequence[T]) -> T: ... + def shuffle(self, x: Sequence) -> None: ... + def sample(self, population: Sequence, k: int) -> list: ... _r = StrongRandom() getrandbits = _r.getrandbits diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/__init__.py index 40f865d1..ff43a4a3 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/__init__.py @@ -28,37 +28,84 @@ def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Cipher import test_AES; tests += test_AES.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_ARC2; tests += test_ARC2.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_ARC4; tests += test_ARC4.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_Blowfish; tests += test_Blowfish.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CAST; tests += test_CAST.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_DES3; tests += test_DES3.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_DES; tests += test_DES.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_Salsa20; tests += test_Salsa20.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_ChaCha20; tests += test_ChaCha20.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_ChaCha20_Poly1305; tests += test_ChaCha20_Poly1305.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_pkcs1_15; tests += test_pkcs1_15.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_pkcs1_oaep; tests += test_pkcs1_oaep.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_OCB; tests += test_OCB.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CBC; tests += test_CBC.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CFB; tests += test_CFB.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_OpenPGP; tests += test_OpenPGP.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_OFB; tests += test_OFB.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CTR; tests += test_CTR.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_CCM; tests += test_CCM.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_EAX; tests += test_EAX.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_GCM; tests += test_GCM.get_tests(config=config) - from Cryptodome.SelfTest.Cipher import test_SIV; tests += test_SIV.get_tests(config=config) - - if sys.version_info >= (3, 9): - from Cryptodome.SelfTest.Cipher import test_KW - tests += test_KW.get_tests(config=config) - - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + from Cryptodome.SelfTest.Cipher import test_AES + + tests += test_AES.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_ARC2 + + tests += test_ARC2.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_ARC4 + + tests += test_ARC4.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_Blowfish + + tests += test_Blowfish.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CAST + + tests += test_CAST.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_DES3 + + tests += test_DES3.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_DES + + tests += test_DES.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_Salsa20 + + tests += test_Salsa20.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_ChaCha20 + + tests += test_ChaCha20.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_ChaCha20_Poly1305 + + tests += test_ChaCha20_Poly1305.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_pkcs1_15 + + tests += test_pkcs1_15.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_pkcs1_oaep + + tests += test_pkcs1_oaep.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_OCB + + tests += test_OCB.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CBC + + tests += test_CBC.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CFB + + tests += test_CFB.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_OpenPGP + + tests += test_OpenPGP.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_OFB + + tests += test_OFB.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CTR + + tests += test_CTR.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_CCM + + tests += test_CCM.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_EAX + + tests += test_EAX.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_GCM + + tests += test_GCM.get_tests(config=config) + from Cryptodome.SelfTest.Cipher import test_SIV + + tests += test_SIV.get_tests(config=config) + + if sys.version_info >= (3, 9): + from Cryptodome.SelfTest.Cipher import test_KW + + tests += test_KW.get_tests(config=config) + + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/common.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/common.py index a13d4fbe..303fdecb 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/common.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/common.py @@ -25,486 +25,506 @@ """Self-testing for PyCryptodome hash modules""" import unittest -from binascii import a2b_hex, b2a_hex, hexlify +from binascii import a2b_hex, b2a_hex from Cryptodome.Util.py3compat import b -from Cryptodome.Util.strxor import strxor_c -class _NoDefault: pass # sentinel object -def _extract(d, k, default=_NoDefault): - """Get an item from a dictionary, and remove it from the dictionary.""" - try: - retval = d[k] - except KeyError: - if default is _NoDefault: - raise - return default - del d[k] - return retval - -# Generic cipher test case -class CipherSelfTest(unittest.TestCase): - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - - # Extract the parameters - params = params.copy() - self.description = _extract(params, 'description') - self.key = b(_extract(params, 'key')) - self.plaintext = b(_extract(params, 'plaintext')) - self.ciphertext = b(_extract(params, 'ciphertext')) - self.module_name = _extract(params, 'module_name', None) - self.assoc_data = _extract(params, 'assoc_data', None) - self.mac = _extract(params, 'mac', None) - if self.assoc_data: - self.mac = b(self.mac) - - mode = _extract(params, 'mode', None) - self.mode_name = str(mode) - - if mode is not None: - # Block cipher - self.mode = getattr(self.module, "MODE_" + mode) - - self.iv = _extract(params, 'iv', None) - if self.iv is None: - self.iv = _extract(params, 'nonce', None) - if self.iv is not None: - self.iv = b(self.iv) - - else: - # Stream cipher - self.mode = None - self.iv = _extract(params, 'iv', None) - if self.iv is not None: - self.iv = b(self.iv) - - self.extra_params = params - - def shortDescription(self): - return self.description - - def _new(self): - params = self.extra_params.copy() - key = a2b_hex(self.key) - - old_style = [] - if self.mode is not None: - old_style = [ self.mode ] - if self.iv is not None: - old_style += [ a2b_hex(self.iv) ] - - return self.module.new(key, *old_style, **params) - - def isMode(self, name): - if not hasattr(self.module, "MODE_"+name): - return False - return self.mode == getattr(self.module, "MODE_"+name) - - def runTest(self): - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) - assoc_data = [] - if self.assoc_data: - assoc_data = [ a2b_hex(b(x)) for x in self.assoc_data] - - ct = None - pt = None - - # - # Repeat the same encryption or decryption twice and verify - # that the result is always the same - # - for i in range(2): - cipher = self._new() - decipher = self._new() - - # Only AEAD modes - for comp in assoc_data: - cipher.update(comp) - decipher.update(comp) - - ctX = b2a_hex(cipher.encrypt(plaintext)) - ptX = b2a_hex(decipher.decrypt(ciphertext)) - - if ct: - self.assertEqual(ct, ctX) - self.assertEqual(pt, ptX) - ct, pt = ctX, ptX - - self.assertEqual(self.ciphertext, ct) # encrypt - self.assertEqual(self.plaintext, pt) # decrypt - - if self.mac: - mac = b2a_hex(cipher.digest()) - self.assertEqual(self.mac, mac) - decipher.verify(a2b_hex(self.mac)) +class _NoDefault: + pass # sentinel object -class CipherStreamingSelfTest(CipherSelfTest): - def shortDescription(self): - desc = self.module_name - if self.mode is not None: - desc += " in %s mode" % (self.mode_name,) - return "%s should behave like a stream cipher" % (desc,) +def _extract(d, k, default=_NoDefault): + """Get an item from a dictionary, and remove it from the dictionary.""" + try: + retval = d[k] + except KeyError: + if default is _NoDefault: + raise + return default + del d[k] + return retval - def runTest(self): - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) - # The cipher should work like a stream cipher +# Generic cipher test case +class CipherSelfTest(unittest.TestCase): + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + + # Extract the parameters + params = params.copy() + self.description = _extract(params, "description") + self.key = b(_extract(params, "key")) + self.plaintext = b(_extract(params, "plaintext")) + self.ciphertext = b(_extract(params, "ciphertext")) + self.module_name = _extract(params, "module_name", None) + self.assoc_data = _extract(params, "assoc_data", None) + self.mac = _extract(params, "mac", None) + if self.assoc_data: + self.mac = b(self.mac) + + mode = _extract(params, "mode", None) + self.mode_name = str(mode) + + if mode is not None: + # Block cipher + self.mode = getattr(self.module, "MODE_" + mode) + + self.iv = _extract(params, "iv", None) + if self.iv is None: + self.iv = _extract(params, "nonce", None) + if self.iv is not None: + self.iv = b(self.iv) + + else: + # Stream cipher + self.mode = None + self.iv = _extract(params, "iv", None) + if self.iv is not None: + self.iv = b(self.iv) + + self.extra_params = params + + def shortDescription(self): + return self.description + + def _new(self): + params = self.extra_params.copy() + key = a2b_hex(self.key) + + old_style = [] + if self.mode is not None: + old_style = [self.mode] + if self.iv is not None: + old_style += [a2b_hex(self.iv)] + + return self.module.new(key, *old_style, **params) + + def isMode(self, name): + if not hasattr(self.module, "MODE_" + name): + return False + return self.mode == getattr(self.module, "MODE_" + name) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + assoc_data = [] + if self.assoc_data: + assoc_data = [a2b_hex(b(x)) for x in self.assoc_data] + + ct = None + pt = None + + # + # Repeat the same encryption or decryption twice and verify + # that the result is always the same + # + for i in range(2): + cipher = self._new() + decipher = self._new() + + # Only AEAD modes + for comp in assoc_data: + cipher.update(comp) + decipher.update(comp) + + ctX = b2a_hex(cipher.encrypt(plaintext)) + ptX = b2a_hex(decipher.decrypt(ciphertext)) + + if ct: + self.assertEqual(ct, ctX) + self.assertEqual(pt, ptX) + ct, pt = ctX, ptX + + self.assertEqual(self.ciphertext, ct) # encrypt + self.assertEqual(self.plaintext, pt) # decrypt + + if self.mac: + mac = b2a_hex(cipher.digest()) + self.assertEqual(self.mac, mac) + decipher.verify(a2b_hex(self.mac)) - # Test counter mode encryption, 3 bytes at a time - ct3 = [] - cipher = self._new() - for i in range(0, len(plaintext), 3): - ct3.append(cipher.encrypt(plaintext[i:i+3])) - ct3 = b2a_hex(b("").join(ct3)) - self.assertEqual(self.ciphertext, ct3) # encryption (3 bytes at a time) - # Test counter mode decryption, 3 bytes at a time - pt3 = [] - cipher = self._new() - for i in range(0, len(ciphertext), 3): - pt3.append(cipher.encrypt(ciphertext[i:i+3])) - # PY3K: This is meant to be text, do not change to bytes (data) - pt3 = b2a_hex(b("").join(pt3)) - self.assertEqual(self.plaintext, pt3) # decryption (3 bytes at a time) +class CipherStreamingSelfTest(CipherSelfTest): + def shortDescription(self): + desc = self.module_name + if self.mode is not None: + desc += " in %s mode" % (self.mode_name,) + return "%s should behave like a stream cipher" % (desc,) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + + # The cipher should work like a stream cipher + + # Test counter mode encryption, 3 bytes at a time + ct3 = [] + cipher = self._new() + for i in range(0, len(plaintext), 3): + ct3.append(cipher.encrypt(plaintext[i : i + 3])) + ct3 = b2a_hex(b("").join(ct3)) + self.assertEqual(self.ciphertext, ct3) # encryption (3 bytes at a time) + + # Test counter mode decryption, 3 bytes at a time + pt3 = [] + cipher = self._new() + for i in range(0, len(ciphertext), 3): + pt3.append(cipher.encrypt(ciphertext[i : i + 3])) + # PY3K: This is meant to be text, do not change to bytes (data) + pt3 = b2a_hex(b("").join(pt3)) + self.assertEqual(self.plaintext, pt3) # decryption (3 bytes at a time) class RoundtripTest(unittest.TestCase): - def __init__(self, module, params): - from Cryptodome import Random - unittest.TestCase.__init__(self) - self.module = module - self.iv = Random.get_random_bytes(module.block_size) - self.key = b(params['key']) - self.plaintext = 100 * b(params['plaintext']) - self.module_name = params.get('module_name', None) + def __init__(self, module, params): + from Cryptodome import Random - def shortDescription(self): - return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,) + unittest.TestCase.__init__(self) + self.module = module + self.iv = Random.get_random_bytes(module.block_size) + self.key = b(params["key"]) + self.plaintext = 100 * b(params["plaintext"]) + self.module_name = params.get("module_name", None) - def runTest(self): + def shortDescription(self): + return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,) - ## ECB mode - mode = self.module.MODE_ECB - encryption_cipher = self.module.new(a2b_hex(self.key), mode) - ciphertext = encryption_cipher.encrypt(self.plaintext) - decryption_cipher = self.module.new(a2b_hex(self.key), mode) - decrypted_plaintext = decryption_cipher.decrypt(ciphertext) - self.assertEqual(self.plaintext, decrypted_plaintext) + def runTest(self): + ## ECB mode + mode = self.module.MODE_ECB + encryption_cipher = self.module.new(a2b_hex(self.key), mode) + ciphertext = encryption_cipher.encrypt(self.plaintext) + decryption_cipher = self.module.new(a2b_hex(self.key), mode) + decrypted_plaintext = decryption_cipher.decrypt(ciphertext) + self.assertEqual(self.plaintext, decrypted_plaintext) class IVLengthTest(unittest.TestCase): - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - self.key = b(params['key']) + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = b(params["key"]) - def shortDescription(self): - return "Check that all modes except MODE_ECB and MODE_CTR require an IV of the proper length" + def shortDescription(self): + return "Check that all modes except MODE_ECB and MODE_CTR require an IV of the proper length" - def runTest(self): - self.assertRaises(TypeError, self.module.new, a2b_hex(self.key), - self.module.MODE_ECB, b("")) + def runTest(self): + self.assertRaises( + TypeError, + self.module.new, + a2b_hex(self.key), + self.module.MODE_ECB, + b(""), + ) - def _dummy_counter(self): - return "\0" * self.module.block_size + def _dummy_counter(self): + return "\0" * self.module.block_size class NoDefaultECBTest(unittest.TestCase): - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - self.key = b(params['key']) + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = b(params["key"]) - def runTest(self): - self.assertRaises(TypeError, self.module.new, a2b_hex(self.key)) + def runTest(self): + self.assertRaises(TypeError, self.module.new, a2b_hex(self.key)) class BlockSizeTest(unittest.TestCase): - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - self.key = a2b_hex(b(params['key'])) + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = a2b_hex(b(params["key"])) - def runTest(self): - cipher = self.module.new(self.key, self.module.MODE_ECB) - self.assertEqual(cipher.block_size, self.module.block_size) + def runTest(self): + cipher = self.module.new(self.key, self.module.MODE_ECB) + self.assertEqual(cipher.block_size, self.module.block_size) class ByteArrayTest(unittest.TestCase): - """Verify we can use bytearray's for encrypting and decrypting""" - - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - - # Extract the parameters - params = params.copy() - self.description = _extract(params, 'description') - self.key = b(_extract(params, 'key')) - self.plaintext = b(_extract(params, 'plaintext')) - self.ciphertext = b(_extract(params, 'ciphertext')) - self.module_name = _extract(params, 'module_name', None) - self.assoc_data = _extract(params, 'assoc_data', None) - self.mac = _extract(params, 'mac', None) - if self.assoc_data: - self.mac = b(self.mac) - - mode = _extract(params, 'mode', None) - self.mode_name = str(mode) - - if mode is not None: - # Block cipher - self.mode = getattr(self.module, "MODE_" + mode) - - self.iv = _extract(params, 'iv', None) - if self.iv is None: - self.iv = _extract(params, 'nonce', None) - if self.iv is not None: - self.iv = b(self.iv) - else: - # Stream cipher - self.mode = None - self.iv = _extract(params, 'iv', None) - if self.iv is not None: - self.iv = b(self.iv) - - self.extra_params = params - - def _new(self): - params = self.extra_params.copy() - key = a2b_hex(self.key) - - old_style = [] - if self.mode is not None: - old_style = [ self.mode ] - if self.iv is not None: - old_style += [ a2b_hex(self.iv) ] - - return self.module.new(key, *old_style, **params) - - def runTest(self): - - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) - assoc_data = [] - if self.assoc_data: - assoc_data = [ bytearray(a2b_hex(b(x))) for x in self.assoc_data] - - cipher = self._new() - decipher = self._new() - - # Only AEAD modes - for comp in assoc_data: - cipher.update(comp) - decipher.update(comp) - - ct = b2a_hex(cipher.encrypt(bytearray(plaintext))) - pt = b2a_hex(decipher.decrypt(bytearray(ciphertext))) - - self.assertEqual(self.ciphertext, ct) # encrypt - self.assertEqual(self.plaintext, pt) # decrypt - - if self.mac: - mac = b2a_hex(cipher.digest()) - self.assertEqual(self.mac, mac) - decipher.verify(bytearray(a2b_hex(self.mac))) + """Verify we can use bytearray's for encrypting and decrypting""" + + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + + # Extract the parameters + params = params.copy() + self.description = _extract(params, "description") + self.key = b(_extract(params, "key")) + self.plaintext = b(_extract(params, "plaintext")) + self.ciphertext = b(_extract(params, "ciphertext")) + self.module_name = _extract(params, "module_name", None) + self.assoc_data = _extract(params, "assoc_data", None) + self.mac = _extract(params, "mac", None) + if self.assoc_data: + self.mac = b(self.mac) + + mode = _extract(params, "mode", None) + self.mode_name = str(mode) + + if mode is not None: + # Block cipher + self.mode = getattr(self.module, "MODE_" + mode) + + self.iv = _extract(params, "iv", None) + if self.iv is None: + self.iv = _extract(params, "nonce", None) + if self.iv is not None: + self.iv = b(self.iv) + else: + # Stream cipher + self.mode = None + self.iv = _extract(params, "iv", None) + if self.iv is not None: + self.iv = b(self.iv) + + self.extra_params = params + + def _new(self): + params = self.extra_params.copy() + key = a2b_hex(self.key) + + old_style = [] + if self.mode is not None: + old_style = [self.mode] + if self.iv is not None: + old_style += [a2b_hex(self.iv)] + + return self.module.new(key, *old_style, **params) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + assoc_data = [] + if self.assoc_data: + assoc_data = [bytearray(a2b_hex(b(x))) for x in self.assoc_data] + + cipher = self._new() + decipher = self._new() + + # Only AEAD modes + for comp in assoc_data: + cipher.update(comp) + decipher.update(comp) + + ct = b2a_hex(cipher.encrypt(bytearray(plaintext))) + pt = b2a_hex(decipher.decrypt(bytearray(ciphertext))) + + self.assertEqual(self.ciphertext, ct) # encrypt + self.assertEqual(self.plaintext, pt) # decrypt + + if self.mac: + mac = b2a_hex(cipher.digest()) + self.assertEqual(self.mac, mac) + decipher.verify(bytearray(a2b_hex(self.mac))) class MemoryviewTest(unittest.TestCase): - """Verify we can use memoryviews for encrypting and decrypting""" - - def __init__(self, module, params): - unittest.TestCase.__init__(self) - self.module = module - - # Extract the parameters - params = params.copy() - self.description = _extract(params, 'description') - self.key = b(_extract(params, 'key')) - self.plaintext = b(_extract(params, 'plaintext')) - self.ciphertext = b(_extract(params, 'ciphertext')) - self.module_name = _extract(params, 'module_name', None) - self.assoc_data = _extract(params, 'assoc_data', None) - self.mac = _extract(params, 'mac', None) - if self.assoc_data: - self.mac = b(self.mac) - - mode = _extract(params, 'mode', None) - self.mode_name = str(mode) - - if mode is not None: - # Block cipher - self.mode = getattr(self.module, "MODE_" + mode) - - self.iv = _extract(params, 'iv', None) - if self.iv is None: - self.iv = _extract(params, 'nonce', None) - if self.iv is not None: - self.iv = b(self.iv) - else: - # Stream cipher - self.mode = None - self.iv = _extract(params, 'iv', None) - if self.iv is not None: - self.iv = b(self.iv) - - self.extra_params = params - - def _new(self): - params = self.extra_params.copy() - key = a2b_hex(self.key) - - old_style = [] - if self.mode is not None: - old_style = [ self.mode ] - if self.iv is not None: - old_style += [ a2b_hex(self.iv) ] - - return self.module.new(key, *old_style, **params) - - def runTest(self): - - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) - assoc_data = [] - if self.assoc_data: - assoc_data = [ memoryview(a2b_hex(b(x))) for x in self.assoc_data] - - cipher = self._new() - decipher = self._new() - - # Only AEAD modes - for comp in assoc_data: - cipher.update(comp) - decipher.update(comp) - - ct = b2a_hex(cipher.encrypt(memoryview(plaintext))) - pt = b2a_hex(decipher.decrypt(memoryview(ciphertext))) - - self.assertEqual(self.ciphertext, ct) # encrypt - self.assertEqual(self.plaintext, pt) # decrypt - - if self.mac: - mac = b2a_hex(cipher.digest()) - self.assertEqual(self.mac, mac) - decipher.verify(memoryview(a2b_hex(self.mac))) + """Verify we can use memoryviews for encrypting and decrypting""" + + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + + # Extract the parameters + params = params.copy() + self.description = _extract(params, "description") + self.key = b(_extract(params, "key")) + self.plaintext = b(_extract(params, "plaintext")) + self.ciphertext = b(_extract(params, "ciphertext")) + self.module_name = _extract(params, "module_name", None) + self.assoc_data = _extract(params, "assoc_data", None) + self.mac = _extract(params, "mac", None) + if self.assoc_data: + self.mac = b(self.mac) + + mode = _extract(params, "mode", None) + self.mode_name = str(mode) + + if mode is not None: + # Block cipher + self.mode = getattr(self.module, "MODE_" + mode) + + self.iv = _extract(params, "iv", None) + if self.iv is None: + self.iv = _extract(params, "nonce", None) + if self.iv is not None: + self.iv = b(self.iv) + else: + # Stream cipher + self.mode = None + self.iv = _extract(params, "iv", None) + if self.iv is not None: + self.iv = b(self.iv) + + self.extra_params = params + + def _new(self): + params = self.extra_params.copy() + key = a2b_hex(self.key) + + old_style = [] + if self.mode is not None: + old_style = [self.mode] + if self.iv is not None: + old_style += [a2b_hex(self.iv)] + + return self.module.new(key, *old_style, **params) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + assoc_data = [] + if self.assoc_data: + assoc_data = [memoryview(a2b_hex(b(x))) for x in self.assoc_data] + + cipher = self._new() + decipher = self._new() + + # Only AEAD modes + for comp in assoc_data: + cipher.update(comp) + decipher.update(comp) + + ct = b2a_hex(cipher.encrypt(memoryview(plaintext))) + pt = b2a_hex(decipher.decrypt(memoryview(ciphertext))) + + self.assertEqual(self.ciphertext, ct) # encrypt + self.assertEqual(self.plaintext, pt) # decrypt + + if self.mac: + mac = b2a_hex(cipher.digest()) + self.assertEqual(self.mac, mac) + decipher.verify(memoryview(a2b_hex(self.mac))) def make_block_tests(module, module_name, test_data, additional_params=dict()): - tests = [] - extra_tests_added = False - for i in range(len(test_data)): - row = test_data[i] - - # Build the "params" dictionary with - # - plaintext - # - ciphertext - # - key - # - mode (default is ECB) - # - (optionally) description - # - (optionally) any other parameter that this cipher mode requires - params = {} - if len(row) == 3: - (params['plaintext'], params['ciphertext'], params['key']) = row - elif len(row) == 4: - (params['plaintext'], params['ciphertext'], params['key'], params['description']) = row - elif len(row) == 5: - (params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row - params.update(extra_params) - else: - raise AssertionError("Unsupported tuple size %d" % (len(row),)) - - if not "mode" in params: - params["mode"] = "ECB" - - # Build the display-name for the test - p2 = params.copy() - p_key = _extract(p2, 'key') - p_plaintext = _extract(p2, 'plaintext') - p_ciphertext = _extract(p2, 'ciphertext') - p_mode = _extract(p2, 'mode') - p_description = _extract(p2, 'description', None) - - if p_description is not None: - description = p_description - elif p_mode == 'ECB' and not p2: - description = "p=%s, k=%s" % (p_plaintext, p_key) - else: - description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) - name = "%s #%d: %s" % (module_name, i+1, description) - params['description'] = name - params['module_name'] = module_name - params.update(additional_params) - - # Add extra test(s) to the test suite before the current test - if not extra_tests_added: - tests += [ - RoundtripTest(module, params), - IVLengthTest(module, params), - NoDefaultECBTest(module, params), - ByteArrayTest(module, params), - BlockSizeTest(module, params), - ] - extra_tests_added = True - - # Add the current test to the test suite - tests.append(CipherSelfTest(module, params)) - - return tests + tests = [] + extra_tests_added = False + for i in range(len(test_data)): + row = test_data[i] + + # Build the "params" dictionary with + # - plaintext + # - ciphertext + # - key + # - mode (default is ECB) + # - (optionally) description + # - (optionally) any other parameter that this cipher mode requires + params = {} + if len(row) == 3: + (params["plaintext"], params["ciphertext"], params["key"]) = row + elif len(row) == 4: + (params["plaintext"], params["ciphertext"], params["key"], params["description"]) = row + elif len(row) == 5: + ( + params["plaintext"], + params["ciphertext"], + params["key"], + params["description"], + extra_params, + ) = row + params.update(extra_params) + else: + raise AssertionError("Unsupported tuple size %d" % (len(row),)) + + if "mode" not in params: + params["mode"] = "ECB" + + # Build the display-name for the test + p2 = params.copy() + p_key = _extract(p2, "key") + p_plaintext = _extract(p2, "plaintext") + p_ciphertext = _extract(p2, "ciphertext") + p_mode = _extract(p2, "mode") + p_description = _extract(p2, "description", None) + + if p_description is not None: + description = p_description + elif p_mode == "ECB" and not p2: + description = "p=%s, k=%s" % (p_plaintext, p_key) + else: + description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) + name = "%s #%d: %s" % (module_name, i + 1, description) + params["description"] = name + params["module_name"] = module_name + params.update(additional_params) + + # Add extra test(s) to the test suite before the current test + if not extra_tests_added: + tests += [ + RoundtripTest(module, params), + IVLengthTest(module, params), + NoDefaultECBTest(module, params), + ByteArrayTest(module, params), + BlockSizeTest(module, params), + ] + extra_tests_added = True + + # Add the current test to the test suite + tests.append(CipherSelfTest(module, params)) + + return tests + def make_stream_tests(module, module_name, test_data): - tests = [] - extra_tests_added = False - for i in range(len(test_data)): - row = test_data[i] - - # Build the "params" dictionary - params = {} - if len(row) == 3: - (params['plaintext'], params['ciphertext'], params['key']) = row - elif len(row) == 4: - (params['plaintext'], params['ciphertext'], params['key'], params['description']) = row - elif len(row) == 5: - (params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row - params.update(extra_params) - else: - raise AssertionError("Unsupported tuple size %d" % (len(row),)) - - # Build the display-name for the test - p2 = params.copy() - p_key = _extract(p2, 'key') - p_plaintext = _extract(p2, 'plaintext') - p_ciphertext = _extract(p2, 'ciphertext') - p_description = _extract(p2, 'description', None) - - if p_description is not None: - description = p_description - elif not p2: - description = "p=%s, k=%s" % (p_plaintext, p_key) - else: - description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) - name = "%s #%d: %s" % (module_name, i+1, description) - params['description'] = name - params['module_name'] = module_name - - # Add extra test(s) to the test suite before the current test - if not extra_tests_added: - tests += [ - ByteArrayTest(module, params), - ] - - tests.append(MemoryviewTest(module, params)) - extra_tests_added = True - - # Add the test to the test suite - tests.append(CipherSelfTest(module, params)) - tests.append(CipherStreamingSelfTest(module, params)) - return tests + tests = [] + extra_tests_added = False + for i in range(len(test_data)): + row = test_data[i] + + # Build the "params" dictionary + params = {} + if len(row) == 3: + (params["plaintext"], params["ciphertext"], params["key"]) = row + elif len(row) == 4: + (params["plaintext"], params["ciphertext"], params["key"], params["description"]) = row + elif len(row) == 5: + ( + params["plaintext"], + params["ciphertext"], + params["key"], + params["description"], + extra_params, + ) = row + params.update(extra_params) + else: + raise AssertionError("Unsupported tuple size %d" % (len(row),)) + + # Build the display-name for the test + p2 = params.copy() + p_key = _extract(p2, "key") + p_plaintext = _extract(p2, "plaintext") + p_ciphertext = _extract(p2, "ciphertext") + p_description = _extract(p2, "description", None) + + if p_description is not None: + description = p_description + elif not p2: + description = "p=%s, k=%s" % (p_plaintext, p_key) + else: + description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) + name = "%s #%d: %s" % (module_name, i + 1, description) + params["description"] = name + params["module_name"] = module_name + + # Add extra test(s) to the test suite before the current test + if not extra_tests_added: + tests += [ + ByteArrayTest(module, params), + ] + + tests.append(MemoryviewTest(module, params)) + extra_tests_added = True + + # Add the test to the test suite + tests.append(CipherSelfTest(module, params)) + tests.append(CipherStreamingSelfTest(module, params)) + return tests + # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_AES.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_AES.py index bd6c40ea..3edd8fd6 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_AES.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_AES.py @@ -30,1322 +30,2488 @@ from Cryptodome.Hash import SHA256 from Cryptodome.Cipher import AES from Cryptodome.Util.py3compat import * -from binascii import hexlify # This is a list of (plaintext, ciphertext, key[, description[, params]]) tuples. test_data = [ - # FIPS PUB 197 test vectors - # http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - - ('00112233445566778899aabbccddeeff', '69c4e0d86a7b0430d8cdb78070b4c55a', - '000102030405060708090a0b0c0d0e0f', 'FIPS 197 C.1 (AES-128)'), - - ('00112233445566778899aabbccddeeff', 'dda97ca4864cdfe06eaf70a0ec0d7191', - '000102030405060708090a0b0c0d0e0f1011121314151617', - 'FIPS 197 C.2 (AES-192)'), - - ('00112233445566778899aabbccddeeff', '8ea2b7ca516745bfeafc49904b496089', - '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - 'FIPS 197 C.3 (AES-256)'), - - # Rijndael128 test vectors - # Downloaded 2008-09-13 from - # http://www.iaik.tugraz.at/Research/krypto/AES/old/~rijmen/rijndael/testvalues.tar.gz - - # ecb_tbl.txt, KEYSIZE=128 - ('506812a45f08c889b97f5980038b8359', 'd8f532538289ef7d06b506a4fd5be9c9', - '00010203050607080a0b0c0d0f101112', - 'ecb-tbl-128: I=1'), - ('5c6d71ca30de8b8b00549984d2ec7d4b', '59ab30f4d4ee6e4ff9907ef65b1fb68c', - '14151617191a1b1c1e1f202123242526', - 'ecb-tbl-128: I=2'), - ('53f3f4c64f8616e4e7c56199f48f21f6', 'bf1ed2fcb2af3fd41443b56d85025cb1', - '28292a2b2d2e2f30323334353738393a', - 'ecb-tbl-128: I=3'), - ('a1eb65a3487165fb0f1c27ff9959f703', '7316632d5c32233edcb0780560eae8b2', - '3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-128: I=4'), - ('3553ecf0b1739558b08e350a98a39bfa', '408c073e3e2538072b72625e68b8364b', - '50515253555657585a5b5c5d5f606162', - 'ecb-tbl-128: I=5'), - ('67429969490b9711ae2b01dc497afde8', 'e1f94dfa776597beaca262f2f6366fea', - '64656667696a6b6c6e6f707173747576', - 'ecb-tbl-128: I=6'), - ('93385c1f2aec8bed192f5a8e161dd508', 'f29e986c6a1c27d7b29ffd7ee92b75f1', - '78797a7b7d7e7f80828384858788898a', - 'ecb-tbl-128: I=7'), - ('b5bf946be19beb8db3983b5f4c6e8ddb', '131c886a57f8c2e713aba6955e2b55b5', - '8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-128: I=8'), - ('41321ee10e21bd907227c4450ff42324', 'd2ab7662df9b8c740210e5eeb61c199d', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-128: I=9'), - ('00a82f59c91c8486d12c0a80124f6089', '14c10554b2859c484cab5869bbe7c470', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-128: I=10'), - ('7ce0fd076754691b4bbd9faf8a1372fe', 'db4d498f0a49cf55445d502c1f9ab3b5', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', - 'ecb-tbl-128: I=11'), - ('23605a8243d07764541bc5ad355b3129', '6d96fef7d66590a77a77bb2056667f7f', - 'dcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-128: I=12'), - ('12a8cfa23ea764fd876232b4e842bc44', '316fb68edba736c53e78477bf913725c', - 'f0f1f2f3f5f6f7f8fafbfcfdfe010002', - 'ecb-tbl-128: I=13'), - ('bcaf32415e8308b3723e5fdd853ccc80', '6936f2b93af8397fd3a771fc011c8c37', - '04050607090a0b0c0e0f101113141516', - 'ecb-tbl-128: I=14'), - ('89afae685d801ad747ace91fc49adde0', 'f3f92f7a9c59179c1fcc2c2ba0b082cd', - '2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-128: I=15'), - ('f521d07b484357c4a69e76124a634216', '6a95ea659ee3889158e7a9152ff04ebc', - '40414243454647484a4b4c4d4f505152', - 'ecb-tbl-128: I=16'), - ('3e23b3bc065bcc152407e23896d77783', '1959338344e945670678a5d432c90b93', - '54555657595a5b5c5e5f606163646566', - 'ecb-tbl-128: I=17'), - ('79f0fba002be1744670e7e99290d8f52', 'e49bddd2369b83ee66e6c75a1161b394', - '68696a6b6d6e6f70727374757778797a', - 'ecb-tbl-128: I=18'), - ('da23fe9d5bd63e1d72e3dafbe21a6c2a', 'd3388f19057ff704b70784164a74867d', - '7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-128: I=19'), - ('e3f5698ba90b6a022efd7db2c7e6c823', '23aa03e2d5e4cd24f3217e596480d1e1', - 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-128: I=20'), - ('bdc2691d4f1b73d2700679c3bcbf9c6e', 'c84113d68b666ab2a50a8bdb222e91b9', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2', - 'ecb-tbl-128: I=21'), - ('ba74e02093217ee1ba1b42bd5624349a', 'ac02403981cd4340b507963db65cb7b6', - '08090a0b0d0e0f10121314151718191a', - 'ecb-tbl-128: I=22'), - ('b5c593b5851c57fbf8b3f57715e8f680', '8d1299236223359474011f6bf5088414', - '6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-128: I=23'), - ('3da9bd9cec072381788f9387c3bbf4ee', '5a1d6ab8605505f7977e55b9a54d9b90', - '80818283858687888a8b8c8d8f909192', - 'ecb-tbl-128: I=24'), - ('4197f3051121702ab65d316b3c637374', '72e9c2d519cf555e4208805aabe3b258', - '94959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-128: I=25'), - ('9f46c62ec4f6ee3f6e8c62554bc48ab7', 'a8f3e81c4a23a39ef4d745dffe026e80', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', - 'ecb-tbl-128: I=26'), - ('0220673fe9e699a4ebc8e0dbeb6979c8', '546f646449d31458f9eb4ef5483aee6c', - 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-128: I=27'), - ('b2b99171337ded9bc8c2c23ff6f18867', '4dbe4bc84ac797c0ee4efb7f1a07401c', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', - 'ecb-tbl-128: I=28'), - ('a7facf4e301e984e5efeefd645b23505', '25e10bfb411bbd4d625ac8795c8ca3b3', - 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-128: I=29'), - ('f7c762e4a9819160fd7acfb6c4eedcdd', '315637405054ec803614e43def177579', - 'f8f9fafbfdfefe00020304050708090a', - 'ecb-tbl-128: I=30'), - ('9b64fc21ea08709f4915436faa70f1be', '60c5bc8a1410247295c6386c59e572a8', - '0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-128: I=31'), - ('52af2c3de07ee6777f55a4abfc100b3f', '01366fc8ca52dfe055d6a00a76471ba6', - '20212223252627282a2b2c2d2f303132', - 'ecb-tbl-128: I=32'), - ('2fca001224386c57aa3f968cbe2c816f', 'ecc46595516ec612449c3f581e7d42ff', - '34353637393a3b3c3e3f404143444546', - 'ecb-tbl-128: I=33'), - ('4149c73658a4a9c564342755ee2c132f', '6b7ffe4c602a154b06ee9c7dab5331c9', - '48494a4b4d4e4f50525354555758595a', - 'ecb-tbl-128: I=34'), - ('af60005a00a1772f7c07a48a923c23d2', '7da234c14039a240dd02dd0fbf84eb67', - '5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-128: I=35'), - ('6fccbc28363759914b6f0280afaf20c6', 'c7dc217d9e3604ffe7e91f080ecd5a3a', - '70717273757677787a7b7c7d7f808182', - 'ecb-tbl-128: I=36'), - ('7d82a43ddf4fefa2fc5947499884d386', '37785901863f5c81260ea41e7580cda5', - '84858687898a8b8c8e8f909193949596', - 'ecb-tbl-128: I=37'), - ('5d5a990eaab9093afe4ce254dfa49ef9', 'a07b9338e92ed105e6ad720fccce9fe4', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aa', - 'ecb-tbl-128: I=38'), - ('4cd1e2fd3f4434b553aae453f0ed1a02', 'ae0fb9722418cc21a7da816bbc61322c', - 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-128: I=39'), - ('5a2c9a9641d4299125fa1b9363104b5e', 'c826a193080ff91ffb21f71d3373c877', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', - 'ecb-tbl-128: I=40'), - ('b517fe34c0fa217d341740bfd4fe8dd4', '1181b11b0e494e8d8b0aa6b1d5ac2c48', - 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-128: I=41'), - ('014baf2278a69d331d5180103643e99a', '6743c3d1519ab4f2cd9a78ab09a511bd', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fa', - 'ecb-tbl-128: I=42'), - ('b529bd8164f20d0aa443d4932116841c', 'dc55c076d52bacdf2eefd952946a439d', - 'fcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-128: I=43'), - ('2e596dcbb2f33d4216a1176d5bd1e456', '711b17b590ffc72b5c8e342b601e8003', - '10111213151617181a1b1c1d1f202122', - 'ecb-tbl-128: I=44'), - ('7274a1ea2b7ee2424e9a0e4673689143', '19983bb0950783a537e1339f4aa21c75', - '24252627292a2b2c2e2f303133343536', - 'ecb-tbl-128: I=45'), - ('ae20020bd4f13e9d90140bee3b5d26af', '3ba7762e15554169c0f4fa39164c410c', - '38393a3b3d3e3f40424344454748494a', - 'ecb-tbl-128: I=46'), - ('baac065da7ac26e855e79c8849d75a02', 'a0564c41245afca7af8aa2e0e588ea89', - '4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-128: I=47'), - ('7c917d8d1d45fab9e2540e28832540cc', '5e36a42a2e099f54ae85ecd92e2381ed', - '60616263656667686a6b6c6d6f707172', - 'ecb-tbl-128: I=48'), - ('bde6f89e16daadb0e847a2a614566a91', '770036f878cd0f6ca2268172f106f2fe', - '74757677797a7b7c7e7f808183848586', - 'ecb-tbl-128: I=49'), - ('c9de163725f1f5be44ebb1db51d07fbc', '7e4e03908b716116443ccf7c94e7c259', - '88898a8b8d8e8f90929394959798999a', - 'ecb-tbl-128: I=50'), - ('3af57a58f0c07dffa669572b521e2b92', '482735a48c30613a242dd494c7f9185d', - '9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-128: I=51'), - ('3d5ebac306dde4604f1b4fbbbfcdae55', 'b4c0f6c9d4d7079addf9369fc081061d', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', - 'ecb-tbl-128: I=52'), - ('c2dfa91bceb76a1183c995020ac0b556', 'd5810fe0509ac53edcd74f89962e6270', - 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-128: I=53'), - ('c70f54305885e9a0746d01ec56c8596b', '03f17a16b3f91848269ecdd38ebb2165', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9ea', - 'ecb-tbl-128: I=54'), - ('c4f81b610e98012ce000182050c0c2b2', 'da1248c3180348bad4a93b4d9856c9df', - 'ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-128: I=55'), - ('eaab86b1d02a95d7404eff67489f97d4', '3d10d7b63f3452c06cdf6cce18be0c2c', - '00010203050607080a0b0c0d0f101112', - 'ecb-tbl-128: I=56'), - ('7c55bdb40b88870b52bec3738de82886', '4ab823e7477dfddc0e6789018fcb6258', - '14151617191a1b1c1e1f202123242526', - 'ecb-tbl-128: I=57'), - ('ba6eaa88371ff0a3bd875e3f2a975ce0', 'e6478ba56a77e70cfdaa5c843abde30e', - '28292a2b2d2e2f30323334353738393a', - 'ecb-tbl-128: I=58'), - ('08059130c4c24bd30cf0575e4e0373dc', '1673064895fbeaf7f09c5429ff75772d', - '3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-128: I=59'), - ('9a8eab004ef53093dfcf96f57e7eda82', '4488033ae9f2efd0ca9383bfca1a94e9', - '50515253555657585a5b5c5d5f606162', - 'ecb-tbl-128: I=60'), - ('0745b589e2400c25f117b1d796c28129', '978f3b8c8f9d6f46626cac3c0bcb9217', - '64656667696a6b6c6e6f707173747576', - 'ecb-tbl-128: I=61'), - ('2f1777781216cec3f044f134b1b92bbe', 'e08c8a7e582e15e5527f1d9e2eecb236', - '78797a7b7d7e7f80828384858788898a', - 'ecb-tbl-128: I=62'), - ('353a779ffc541b3a3805d90ce17580fc', 'cec155b76ac5ffda4cf4f9ca91e49a7a', - '8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-128: I=63'), - ('1a1eae4415cefcf08c4ac1c8f68bea8f', 'd5ac7165763225dd2a38cdc6862c29ad', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-128: I=64'), - ('e6e7e4e5b0b3b2b5d4d5aaab16111013', '03680fe19f7ce7275452020be70e8204', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-128: I=65'), - ('f8f9fafbfbf8f9e677767170efe0e1e2', '461df740c9781c388e94bb861ceb54f6', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', - 'ecb-tbl-128: I=66'), - ('63626160a1a2a3a445444b4a75727370', '451bd60367f96483042742219786a074', - 'dcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-128: I=67'), - ('717073720605040b2d2c2b2a05fafbf9', 'e4dfa42671a02e57ef173b85c0ea9f2b', - 'f0f1f2f3f5f6f7f8fafbfcfdfe010002', - 'ecb-tbl-128: I=68'), - ('78797a7beae9e8ef3736292891969794', 'ed11b89e76274282227d854700a78b9e', - '04050607090a0b0c0e0f101113141516', - 'ecb-tbl-128: I=69'), - ('838281803231300fdddcdbdaa0afaead', '433946eaa51ea47af33895f2b90b3b75', - '18191a1b1d1e1f20222324252728292a', - 'ecb-tbl-128: I=70'), - ('18191a1bbfbcbdba75747b7a7f78797a', '6bc6d616a5d7d0284a5910ab35022528', - '2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-128: I=71'), - ('848586879b989996a3a2a5a4849b9a99', 'd2a920ecfe919d354b5f49eae9719c98', - '40414243454647484a4b4c4d4f505152', - 'ecb-tbl-128: I=72'), - ('0001020322212027cacbf4f551565754', '3a061b17f6a92885efbd0676985b373d', - '54555657595a5b5c5e5f606163646566', - 'ecb-tbl-128: I=73'), - ('cecfcccdafacadb2515057564a454447', 'fadeec16e33ea2f4688499d157e20d8f', - '68696a6b6d6e6f70727374757778797a', - 'ecb-tbl-128: I=74'), - ('92939091cdcecfc813121d1c80878685', '5cdefede59601aa3c3cda36fa6b1fa13', - '7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-128: I=75'), - ('d2d3d0d16f6c6d6259585f5ed1eeefec', '9574b00039844d92ebba7ee8719265f8', - '90919293959697989a9b9c9d9fa0a1a2', - 'ecb-tbl-128: I=76'), - ('acadaeaf878485820f0e1110d5d2d3d0', '9a9cf33758671787e5006928188643fa', - 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-128: I=77'), - ('9091929364676619e6e7e0e1757a7b78', '2cddd634c846ba66bb46cbfea4a674f9', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9ca', - 'ecb-tbl-128: I=78'), - ('babbb8b98a89888f74757a7b92959497', 'd28bae029393c3e7e26e9fafbbb4b98f', - 'cccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-128: I=79'), - ('8d8c8f8e6e6d6c633b3a3d3ccad5d4d7', 'ec27529b1bee0a9ab6a0d73ebc82e9b7', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2', - 'ecb-tbl-128: I=80'), - ('86878485010203040808f7f767606162', '3cb25c09472aff6ee7e2b47ccd7ccb17', - 'f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-128: I=81'), - ('8e8f8c8d656667788a8b8c8d010e0f0c', 'dee33103a7283370d725e44ca38f8fe5', - '08090a0b0d0e0f10121314151718191a', - 'ecb-tbl-128: I=82'), - ('c8c9cacb858687807a7b7475e7e0e1e2', '27f9bcd1aac64bffc11e7815702c1a69', - '1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-128: I=83'), - ('6d6c6f6e5053525d8c8d8a8badd2d3d0', '5df534ffad4ed0749a9988e9849d0021', - '30313233353637383a3b3c3d3f404142', - 'ecb-tbl-128: I=84'), - ('28292a2b393a3b3c0607181903040506', 'a48bee75db04fb60ca2b80f752a8421b', - '44454647494a4b4c4e4f505153545556', - 'ecb-tbl-128: I=85'), - ('a5a4a7a6b0b3b28ddbdadddcbdb2b3b0', '024c8cf70bc86ee5ce03678cb7af45f9', - '58595a5b5d5e5f60626364656768696a', - 'ecb-tbl-128: I=86'), - ('323330316467666130313e3f2c2b2a29', '3c19ac0f8a3a3862ce577831301e166b', - '6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-128: I=87'), - ('27262524080b0a05171611100b141516', 'c5e355b796a57421d59ca6be82e73bca', - '80818283858687888a8b8c8d8f909192', - 'ecb-tbl-128: I=88'), - ('040506074142434435340b0aa3a4a5a6', 'd94033276417abfb05a69d15b6e386e2', - '94959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-128: I=89'), - ('242526271112130c61606766bdb2b3b0', '24b36559ea3a9b9b958fe6da3e5b8d85', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', - 'ecb-tbl-128: I=90'), - ('4b4a4948252627209e9f9091cec9c8cb', '20fd4feaa0e8bf0cce7861d74ef4cb72', - 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-128: I=91'), - ('68696a6b6665646b9f9e9998d9e6e7e4', '350e20d5174277b9ec314c501570a11d', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', - 'ecb-tbl-128: I=92'), - ('34353637c5c6c7c0f0f1eeef7c7b7a79', '87a29d61b7c604d238fe73045a7efd57', - 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-128: I=93'), - ('32333031c2c1c13f0d0c0b0a050a0b08', '2c3164c1cc7d0064816bdc0faa362c52', - 'f8f9fafbfdfefe00020304050708090a', - 'ecb-tbl-128: I=94'), - ('cdcccfcebebdbcbbabaaa5a4181f1e1d', '195fe5e8a05a2ed594f6e4400eee10b3', - '0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-128: I=95'), - ('212023223635343ba0a1a6a7445b5a59', 'e4663df19b9a21a5a284c2bd7f905025', - '20212223252627282a2b2c2d2f303132', - 'ecb-tbl-128: I=96'), - ('0e0f0c0da8abaaad2f2e515002050407', '21b88714cfb4e2a933bd281a2c4743fd', - '34353637393a3b3c3e3f404143444546', - 'ecb-tbl-128: I=97'), - ('070605042a2928378e8f8889bdb2b3b0', 'cbfc3980d704fd0fc54378ab84e17870', - '48494a4b4d4e4f50525354555758595a', - 'ecb-tbl-128: I=98'), - ('cbcac9c893909196a9a8a7a6a5a2a3a0', 'bc5144baa48bdeb8b63e22e03da418ef', - '5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-128: I=99'), - ('80818283c1c2c3cc9c9d9a9b0cf3f2f1', '5a1dbaef1ee2984b8395da3bdffa3ccc', - '70717273757677787a7b7c7d7f808182', - 'ecb-tbl-128: I=100'), - ('1213101125262720fafbe4e5b1b6b7b4', 'f0b11cd0729dfcc80cec903d97159574', - '84858687898a8b8c8e8f909193949596', - 'ecb-tbl-128: I=101'), - ('7f7e7d7c3033320d97969190222d2c2f', '9f95314acfddc6d1914b7f19a9cc8209', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aa', - 'ecb-tbl-128: I=102'), - ('4e4f4c4d484b4a4d81808f8e53545556', '595736f6f0f70914a94e9e007f022519', - 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-128: I=103'), - ('dcdddedfb0b3b2bd15141312a1bebfbc', '1f19f57892cae586fcdfb4c694deb183', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', - 'ecb-tbl-128: I=104'), - ('93929190282b2a2dc4c5fafb92959497', '540700ee1f6f3dab0b3eddf6caee1ef5', - 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-128: I=105'), - ('f5f4f7f6c4c7c6d9373631307e717073', '14a342a91019a331687a2254e6626ca2', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fa', - 'ecb-tbl-128: I=106'), - ('93929190b6b5b4b364656a6b05020300', '7b25f3c3b2eea18d743ef283140f29ff', - 'fcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-128: I=107'), - ('babbb8b90d0e0f00a4a5a2a3043b3a39', '46c2587d66e5e6fa7f7ca6411ad28047', - '10111213151617181a1b1c1d1f202122', - 'ecb-tbl-128: I=108'), - ('d8d9dadb7f7c7d7a10110e0f787f7e7d', '09470e72229d954ed5ee73886dfeeba9', - '24252627292a2b2c2e2f303133343536', - 'ecb-tbl-128: I=109'), - ('fefffcfdefeced923b3a3d3c6768696a', 'd77c03de92d4d0d79ef8d4824ef365eb', - '38393a3b3d3e3f40424344454748494a', - 'ecb-tbl-128: I=110'), - ('d6d7d4d58a89888f96979899a5a2a3a0', '1d190219f290e0f1715d152d41a23593', - '4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-128: I=111'), - ('18191a1ba8abaaa5303136379b848586', 'a2cd332ce3a0818769616292e87f757b', - '60616263656667686a6b6c6d6f707172', - 'ecb-tbl-128: I=112'), - ('6b6a6968a4a7a6a1d6d72829b0b7b6b5', 'd54afa6ce60fbf9341a3690e21385102', - '74757677797a7b7c7e7f808183848586', - 'ecb-tbl-128: I=113'), - ('000102038a89889755545352a6a9a8ab', '06e5c364ded628a3f5e05e613e356f46', - '88898a8b8d8e8f90929394959798999a', - 'ecb-tbl-128: I=114'), - ('2d2c2f2eb3b0b1b6b6b7b8b9f2f5f4f7', 'eae63c0e62556dac85d221099896355a', - '9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-128: I=115'), - ('979695943536373856575051e09f9e9d', '1fed060e2c6fc93ee764403a889985a2', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', - 'ecb-tbl-128: I=116'), - ('a4a5a6a7989b9a9db1b0afae7a7d7c7f', 'c25235c1a30fdec1c7cb5c5737b2a588', - 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-128: I=117'), - ('c1c0c3c2686b6a55a8a9aeafeae5e4e7', '796dbef95147d4d30873ad8b7b92efc0', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9ea', - 'ecb-tbl-128: I=118'), - ('c1c0c3c2141716118c8d828364636261', 'cbcf0fb34d98d0bd5c22ce37211a46bf', - 'ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-128: I=119'), - ('93929190cccfcec196979091e0fffefd', '94b44da6466126cafa7c7fd09063fc24', - '00010203050607080a0b0c0d0f101112', - 'ecb-tbl-128: I=120'), - ('b4b5b6b7f9fafbfc25241b1a6e69686b', 'd78c5b5ebf9b4dbda6ae506c5074c8fe', - '14151617191a1b1c1e1f202123242526', - 'ecb-tbl-128: I=121'), - ('868784850704051ac7c6c1c08788898a', '6c27444c27204b043812cf8cf95f9769', - '28292a2b2d2e2f30323334353738393a', - 'ecb-tbl-128: I=122'), - ('f4f5f6f7aaa9a8affdfcf3f277707172', 'be94524ee5a2aa50bba8b75f4c0aebcf', - '3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-128: I=123'), - ('d3d2d1d00605040bc3c2c5c43e010003', 'a0aeaae91ba9f31f51aeb3588cf3a39e', - '50515253555657585a5b5c5d5f606162', - 'ecb-tbl-128: I=124'), - ('73727170424140476a6b74750d0a0b08', '275297779c28266ef9fe4c6a13c08488', - '64656667696a6b6c6e6f707173747576', - 'ecb-tbl-128: I=125'), - ('c2c3c0c10a0908f754555253a1aeafac', '86523d92bb8672cb01cf4a77fd725882', - '78797a7b7d7e7f80828384858788898a', - 'ecb-tbl-128: I=126'), - ('6d6c6f6ef8fbfafd82838c8df8fffefd', '4b8327640e9f33322a04dd96fcbf9a36', - '8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-128: I=127'), - ('f5f4f7f684878689a6a7a0a1d2cdcccf', 'ce52af650d088ca559425223f4d32694', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-128: I=128'), - - # ecb_tbl.txt, KEYSIZE=192 - ('2d33eef2c0430a8a9ebf45e809c40bb6', 'dff4945e0336df4c1c56bc700eff837f', - '00010203050607080a0b0c0d0f10111214151617191a1b1c', - 'ecb-tbl-192: I=1'), - ('6aa375d1fa155a61fb72353e0a5a8756', 'b6fddef4752765e347d5d2dc196d1252', - '1e1f20212324252628292a2b2d2e2f30323334353738393a', - 'ecb-tbl-192: I=2'), - ('bc3736518b9490dcb8ed60eb26758ed4', 'd23684e3d963b3afcf1a114aca90cbd6', - '3c3d3e3f41424344464748494b4c4d4e5051525355565758', - 'ecb-tbl-192: I=3'), - ('aa214402b46cffb9f761ec11263a311e', '3a7ac027753e2a18c2ceab9e17c11fd0', - '5a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-192: I=4'), - ('02aea86e572eeab66b2c3af5e9a46fd6', '8f6786bd007528ba26603c1601cdd0d8', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394', - 'ecb-tbl-192: I=5'), - ('e2aef6acc33b965c4fa1f91c75ff6f36', 'd17d073b01e71502e28b47ab551168b3', - '969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-192: I=6'), - ('0659df46427162b9434865dd9499f91d', 'a469da517119fab95876f41d06d40ffa', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0', - 'ecb-tbl-192: I=7'), - ('49a44239c748feb456f59c276a5658df', '6091aa3b695c11f5c0b6ad26d3d862ff', - 'd2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-192: I=8'), - ('66208f6e9d04525bdedb2733b6a6be37', '70f9e67f9f8df1294131662dc6e69364', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c', - 'ecb-tbl-192: I=9'), - ('3393f8dfc729c97f5480b950bc9666b0', 'd154dcafad8b207fa5cbc95e9996b559', - '0e0f10111314151618191a1b1d1e1f20222324252728292a', - 'ecb-tbl-192: I=10'), - ('606834c8ce063f3234cf1145325dbd71', '4934d541e8b46fa339c805a7aeb9e5da', - '2c2d2e2f31323334363738393b3c3d3e4041424345464748', - 'ecb-tbl-192: I=11'), - ('fec1c04f529bbd17d8cecfcc4718b17f', '62564c738f3efe186e1a127a0c4d3c61', - '4a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-192: I=12'), - ('32df99b431ed5dc5acf8caf6dc6ce475', '07805aa043986eb23693e23bef8f3438', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384', - 'ecb-tbl-192: I=13'), - ('7fdc2b746f3f665296943b83710d1f82', 'df0b4931038bade848dee3b4b85aa44b', - '868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2', - 'ecb-tbl-192: I=14'), - ('8fba1510a3c5b87e2eaa3f7a91455ca2', '592d5fded76582e4143c65099309477c', - 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6b8b9babbbdbebfc0', - 'ecb-tbl-192: I=15'), - ('2c9b468b1c2eed92578d41b0716b223b', 'c9b8d6545580d3dfbcdd09b954ed4e92', - 'c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-192: I=16'), - ('0a2bbf0efc6bc0034f8a03433fca1b1a', '5dccd5d6eb7c1b42acb008201df707a0', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfc', - 'ecb-tbl-192: I=17'), - ('25260e1f31f4104d387222e70632504b', 'a2a91682ffeb6ed1d34340946829e6f9', - 'fefe01010304050608090a0b0d0e0f10121314151718191a', - 'ecb-tbl-192: I=18'), - ('c527d25a49f08a5228d338642ae65137', 'e45d185b797000348d9267960a68435d', - '1c1d1e1f21222324262728292b2c2d2e3031323335363738', - 'ecb-tbl-192: I=19'), - ('3b49fc081432f5890d0e3d87e884a69e', '45e060dae5901cda8089e10d4f4c246b', - '3a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-192: I=20'), - ('d173f9ed1e57597e166931df2754a083', 'f6951afacc0079a369c71fdcff45df50', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374', - 'ecb-tbl-192: I=21'), - ('8c2b7cafa5afe7f13562daeae1adede0', '9e95e00f351d5b3ac3d0e22e626ddad6', - '767778797b7c7d7e80818283858687888a8b8c8d8f909192', - 'ecb-tbl-192: I=22'), - ('aaf4ec8c1a815aeb826cab741339532c', '9cb566ff26d92dad083b51fdc18c173c', - '94959697999a9b9c9e9fa0a1a3a4a5a6a8a9aaabadaeafb0', - 'ecb-tbl-192: I=23'), - ('40be8c5d9108e663f38f1a2395279ecf', 'c9c82766176a9b228eb9a974a010b4fb', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebec', - 'ecb-tbl-192: I=24'), - ('0c8ad9bc32d43e04716753aa4cfbe351', 'd8e26aa02945881d5137f1c1e1386e88', - '2a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-192: I=25'), - ('1407b1d5f87d63357c8dc7ebbaebbfee', 'c0e024ccd68ff5ffa4d139c355a77c55', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364', - 'ecb-tbl-192: I=26'), - ('e62734d1ae3378c4549e939e6f123416', '0b18b3d16f491619da338640df391d43', - '84858687898a8b8c8e8f90919394959698999a9b9d9e9fa0', - 'ecb-tbl-192: I=27'), - ('5a752cff2a176db1a1de77f2d2cdee41', 'dbe09ac8f66027bf20cb6e434f252efc', - 'a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-192: I=28'), - ('a9c8c3a4eabedc80c64730ddd018cd88', '6d04e5e43c5b9cbe05feb9606b6480fe', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdc', - 'ecb-tbl-192: I=29'), - ('ee9b3dbbdb86180072130834d305999a', 'dd1d6553b96be526d9fee0fbd7176866', - '1a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-192: I=30'), - ('a7fa8c3586b8ebde7568ead6f634a879', '0260ca7e3f979fd015b0dd4690e16d2a', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354', - 'ecb-tbl-192: I=31'), - ('37e0f4a87f127d45ac936fe7ad88c10a', '9893734de10edcc8a67c3b110b8b8cc6', - '929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-192: I=32'), - ('3f77d8b5d92bac148e4e46f697a535c5', '93b30b750516b2d18808d710c2ee84ef', - '464748494b4c4d4e50515253555657585a5b5c5d5f606162', - 'ecb-tbl-192: I=33'), - ('d25ebb686c40f7e2c4da1014936571ca', '16f65fa47be3cb5e6dfe7c6c37016c0e', - '828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-192: I=34'), - ('4f1c769d1e5b0552c7eca84dea26a549', 'f3847210d5391e2360608e5acb560581', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbc', - 'ecb-tbl-192: I=35'), - ('8548e2f882d7584d0fafc54372b6633a', '8754462cd223366d0753913e6af2643d', - 'bebfc0c1c3c4c5c6c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', - 'ecb-tbl-192: I=36'), - ('87d7a336cb476f177cd2a51af2a62cdf', '1ea20617468d1b806a1fd58145462017', - 'dcdddedfe1e2e3e4e6e7e8e9ebecedeef0f1f2f3f5f6f7f8', - 'ecb-tbl-192: I=37'), - ('03b1feac668c4e485c1065dfc22b44ee', '3b155d927355d737c6be9dda60136e2e', - 'fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-192: I=38'), - ('bda15e66819fa72d653a6866aa287962', '26144f7b66daa91b6333dbd3850502b3', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334', - 'ecb-tbl-192: I=39'), - ('4d0c7a0d2505b80bf8b62ceb12467f0a', 'e4f9a4ab52ced8134c649bf319ebcc90', - '363738393b3c3d3e40414243454647484a4b4c4d4f505152', - 'ecb-tbl-192: I=40'), - ('626d34c9429b37211330986466b94e5f', 'b9ddd29ac6128a6cab121e34a4c62b36', - '54555657595a5b5c5e5f60616364656668696a6b6d6e6f70', - 'ecb-tbl-192: I=41'), - ('333c3e6bf00656b088a17e5ff0e7f60a', '6fcddad898f2ce4eff51294f5eaaf5c9', - '727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-192: I=42'), - ('687ed0cdc0d2a2bc8c466d05ef9d2891', 'c9a6fe2bf4028080bea6f7fc417bd7e3', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabac', - 'ecb-tbl-192: I=43'), - ('487830e78cc56c1693e64b2a6660c7b6', '6a2026846d8609d60f298a9c0673127f', - 'aeafb0b1b3b4b5b6b8b9babbbdbebfc0c2c3c4c5c7c8c9ca', - 'ecb-tbl-192: I=44'), - ('7a48d6b7b52b29392aa2072a32b66160', '2cb25c005e26efea44336c4c97a4240b', - 'cccdcecfd1d2d3d4d6d7d8d9dbdcdddee0e1e2e3e5e6e7e8', - 'ecb-tbl-192: I=45'), - ('907320e64c8c5314d10f8d7a11c8618d', '496967ab8680ddd73d09a0e4c7dcc8aa', - 'eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-192: I=46'), - ('b561f2ca2d6e65a4a98341f3ed9ff533', 'd5af94de93487d1f3a8c577cb84a66a4', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324', - 'ecb-tbl-192: I=47'), - ('df769380d212792d026f049e2e3e48ef', '84bdac569cae2828705f267cc8376e90', - '262728292b2c2d2e30313233353637383a3b3c3d3f404142', - 'ecb-tbl-192: I=48'), - ('79f374bc445bdabf8fccb8843d6054c6', 'f7401dda5ad5ab712b7eb5d10c6f99b6', - '44454647494a4b4c4e4f50515354555658595a5b5d5e5f60', - 'ecb-tbl-192: I=49'), - ('4e02f1242fa56b05c68dbae8fe44c9d6', '1c9d54318539ebd4c3b5b7e37bf119f0', - '626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-192: I=50'), - ('cf73c93cbff57ac635a6f4ad2a4a1545', 'aca572d65fb2764cffd4a6eca090ea0d', - '80818283858687888a8b8c8d8f90919294959697999a9b9c', - 'ecb-tbl-192: I=51'), - ('9923548e2875750725b886566784c625', '36d9c627b8c2a886a10ccb36eae3dfbb', - '9e9fa0a1a3a4a5a6a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', - 'ecb-tbl-192: I=52'), - ('4888336b723a022c9545320f836a4207', '010edbf5981e143a81d646e597a4a568', - 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdced0d1d2d3d5d6d7d8', - 'ecb-tbl-192: I=53'), - ('f84d9a5561b0608b1160dee000c41ba8', '8db44d538dc20cc2f40f3067fd298e60', - 'dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-192: I=54'), - ('c23192a0418e30a19b45ae3e3625bf22', '930eb53bc71e6ac4b82972bdcd5aafb3', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314', - 'ecb-tbl-192: I=55'), - ('b84e0690b28b0025381ad82a15e501a7', '6c42a81edcbc9517ccd89c30c95597b4', - '161718191b1c1d1e20212223252627282a2b2c2d2f303132', - 'ecb-tbl-192: I=56'), - ('acef5e5c108876c4f06269f865b8f0b0', 'da389847ad06df19d76ee119c71e1dd3', - '34353637393a3b3c3e3f40414344454648494a4b4d4e4f50', - 'ecb-tbl-192: I=57'), - ('0f1b3603e0f5ddea4548246153a5e064', 'e018fdae13d3118f9a5d1a647a3f0462', - '525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-192: I=58'), - ('fbb63893450d42b58c6d88cd3c1809e3', '2aa65db36264239d3846180fabdfad20', - '70717273757677787a7b7c7d7f80818284858687898a8b8c', - 'ecb-tbl-192: I=59'), - ('4bef736df150259dae0c91354e8a5f92', '1472163e9a4f780f1ceb44b07ecf4fdb', - '8e8f90919394959698999a9b9d9e9fa0a2a3a4a5a7a8a9aa', - 'ecb-tbl-192: I=60'), - ('7d2d46242056ef13d3c3fc93c128f4c7', 'c8273fdc8f3a9f72e91097614b62397c', - 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8', - 'ecb-tbl-192: I=61'), - ('e9c1ba2df415657a256edb33934680fd', '66c8427dcd733aaf7b3470cb7d976e3f', - 'cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-192: I=62'), - ('e23ee277b0aa0a1dfb81f7527c3514f1', '146131cb17f1424d4f8da91e6f80c1d0', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304', - 'ecb-tbl-192: I=63'), - ('3e7445b0b63caaf75e4a911e12106b4c', '2610d0ad83659081ae085266a88770dc', - '060708090b0c0d0e10111213151617181a1b1c1d1f202122', - 'ecb-tbl-192: I=64'), - ('767774752023222544455a5be6e1e0e3', '38a2b5a974b0575c5d733917fb0d4570', - '24252627292a2b2c2e2f30313334353638393a3b3d3e3f40', - 'ecb-tbl-192: I=65'), - ('72737475717e7f7ce9e8ebea696a6b6c', 'e21d401ebc60de20d6c486e4f39a588b', - '424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-192: I=66'), - ('dfdedddc25262728c9c8cfcef1eeefec', 'e51d5f88c670b079c0ca1f0c2c4405a2', - '60616263656667686a6b6c6d6f70717274757677797a7b7c', - 'ecb-tbl-192: I=67'), - ('fffe0100707776755f5e5d5c7675746b', '246a94788a642fb3d1b823c8762380c8', - '7e7f80818384858688898a8b8d8e8f90929394959798999a', - 'ecb-tbl-192: I=68'), - ('e0e1e2e3424140479f9e9190292e2f2c', 'b80c391c5c41a4c3b30c68e0e3d7550f', - '9c9d9e9fa1a2a3a4a6a7a8a9abacadaeb0b1b2b3b5b6b7b8', - 'ecb-tbl-192: I=69'), - ('2120272690efeeed3b3a39384e4d4c4b', 'b77c4754fc64eb9a1154a9af0bb1f21c', - 'babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-192: I=70'), - ('ecedeeef5350516ea1a0a7a6a3acadae', 'fb554de520d159a06bf219fc7f34a02f', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4', - 'ecb-tbl-192: I=71'), - ('32333c3d25222320e9e8ebeacecdccc3', 'a89fba152d76b4927beed160ddb76c57', - 'f6f7f8f9fbfcfdfe00010203050607080a0b0c0d0f101112', - 'ecb-tbl-192: I=72'), - ('40414243626160678a8bb4b511161714', '5676eab4a98d2e8473b3f3d46424247c', - '14151617191a1b1c1e1f20212324252628292a2b2d2e2f30', - 'ecb-tbl-192: I=73'), - ('94959293f5fafbf81f1e1d1c7c7f7e79', '4e8f068bd7ede52a639036ec86c33568', - '323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-192: I=74'), - ('bebfbcbd191a1b14cfcec9c8546b6a69', 'f0193c4d7aff1791ee4c07eb4a1824fc', - '50515253555657585a5b5c5d5f60616264656667696a6b6c', - 'ecb-tbl-192: I=75'), - ('2c2d3233898e8f8cbbbab9b8333031ce', 'ac8686eeca9ba761afe82d67b928c33f', - '6e6f70717374757678797a7b7d7e7f80828384858788898a', - 'ecb-tbl-192: I=76'), - ('84858687bfbcbdba37363938fdfafbf8', '5faf8573e33b145b6a369cd3606ab2c9', - '8c8d8e8f91929394969798999b9c9d9ea0a1a2a3a5a6a7a8', - 'ecb-tbl-192: I=77'), - ('828384857669686b909192930b08090e', '31587e9944ab1c16b844ecad0df2e7da', - 'aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-192: I=78'), - ('bebfbcbd9695948b707176779e919093', 'd017fecd91148aba37f6f3068aa67d8a', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4', - 'ecb-tbl-192: I=79'), - ('8b8a85846067666521202322d0d3d2dd', '788ef2f021a73cba2794b616078a8500', - 'e6e7e8e9ebecedeef0f1f2f3f5f6f7f8fafbfcfdfe010002', - 'ecb-tbl-192: I=80'), - ('76777475f1f2f3f4f8f9e6e777707172', '5d1ef20dced6bcbc12131ac7c54788aa', - '04050607090a0b0c0e0f10111314151618191a1b1d1e1f20', - 'ecb-tbl-192: I=81'), - ('a4a5a2a34f404142b4b5b6b727242522', 'b3c8cf961faf9ea05fdde6d1e4d8f663', - '222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-192: I=82'), - ('94959697e1e2e3ec16171011839c9d9e', '143075c70605861c7fac6526199e459f', - '40414243454647484a4b4c4d4f50515254555657595a5b5c', - 'ecb-tbl-192: I=83'), - ('03023d3c06010003dedfdcddfffcfde2', 'a5ae12eade9a87268d898bfc8fc0252a', - '5e5f60616364656668696a6b6d6e6f70727374757778797a', - 'ecb-tbl-192: I=84'), - ('10111213f1f2f3f4cecfc0c1dbdcddde', '0924f7cf2e877a4819f5244a360dcea9', - '7c7d7e7f81828384868788898b8c8d8e9091929395969798', - 'ecb-tbl-192: I=85'), - ('67666160724d4c4f1d1c1f1e73707176', '3d9e9635afcc3e291cc7ab3f27d1c99a', - '9a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-192: I=86'), - ('e6e7e4e5a8abaad584858283909f9e9d', '9d80feebf87510e2b8fb98bb54fd788c', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4', - 'ecb-tbl-192: I=87'), - ('71707f7e565150537d7c7f7e6162636c', '5f9d1a082a1a37985f174002eca01309', - 'd6d7d8d9dbdcdddee0e1e2e3e5e6e7e8eaebecedeff0f1f2', - 'ecb-tbl-192: I=88'), - ('64656667212223245555aaaa03040506', 'a390ebb1d1403930184a44b4876646e4', - 'f4f5f6f7f9fafbfcfefe01010304050608090a0b0d0e0f10', - 'ecb-tbl-192: I=89'), - ('9e9f9899aba4a5a6cfcecdcc2b28292e', '700fe918981c3195bb6c4bcb46b74e29', - '121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-192: I=90'), - ('c7c6c5c4d1d2d3dc626364653a454447', '907984406f7bf2d17fb1eb15b673d747', - '30313233353637383a3b3c3d3f40414244454647494a4b4c', - 'ecb-tbl-192: I=91'), - ('f6f7e8e9e0e7e6e51d1c1f1e5b585966', 'c32a956dcfc875c2ac7c7cc8b8cc26e1', - '4e4f50515354555658595a5b5d5e5f60626364656768696a', - 'ecb-tbl-192: I=92'), - ('bcbdbebf5d5e5f5868696667f4f3f2f1', '02646e2ebfa9b820cf8424e9b9b6eb51', - '6c6d6e6f71727374767778797b7c7d7e8081828385868788', - 'ecb-tbl-192: I=93'), - ('40414647b0afaead9b9a99989b98999e', '621fda3a5bbd54c6d3c685816bd4ead8', - '8a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-192: I=94'), - ('69686b6a0201001f0f0e0908b4bbbab9', 'd4e216040426dfaf18b152469bc5ac2f', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4', - 'ecb-tbl-192: I=95'), - ('c7c6c9c8d8dfdedd5a5b5859bebdbcb3', '9d0635b9d33b6cdbd71f5d246ea17cc8', - 'c6c7c8c9cbcccdced0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', - 'ecb-tbl-192: I=96'), - ('dedfdcdd787b7a7dfffee1e0b2b5b4b7', '10abad1bd9bae5448808765583a2cc1a', - 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6f8f9fafbfdfefe00', - 'ecb-tbl-192: I=97'), - ('4d4c4b4a606f6e6dd0d1d2d3fbf8f9fe', '6891889e16544e355ff65a793c39c9a8', - '020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-192: I=98'), - ('b7b6b5b4d7d4d5dae5e4e3e2e1fefffc', 'cc735582e68072c163cd9ddf46b91279', - '20212223252627282a2b2c2d2f30313234353637393a3b3c', - 'ecb-tbl-192: I=99'), - ('cecfb0b1f7f0f1f2aeafacad3e3d3c23', 'c5c68b9aeeb7f878df578efa562f9574', - '3e3f40414344454648494a4b4d4e4f50525354555758595a', - 'ecb-tbl-192: I=100'), - ('cacbc8c9cdcecfc812131c1d494e4f4c', '5f4764395a667a47d73452955d0d2ce8', - '5c5d5e5f61626364666768696b6c6d6e7071727375767778', - 'ecb-tbl-192: I=101'), - ('9d9c9b9ad22d2c2fb1b0b3b20c0f0e09', '701448331f66106cefddf1eb8267c357', - '7a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-192: I=102'), - ('7a7b787964676659959493924f404142', 'cb3ee56d2e14b4e1941666f13379d657', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4', - 'ecb-tbl-192: I=103'), - ('aaaba4a5cec9c8cb1f1e1d1caba8a9a6', '9fe16efd18ab6e1981191851fedb0764', - 'b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', - 'ecb-tbl-192: I=104'), - ('93929190282b2a2dc4c5fafb92959497', '3dc9ba24e1b223589b147adceb4c8e48', - 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6e8e9eaebedeeeff0', - 'ecb-tbl-192: I=105'), - ('efeee9e8ded1d0d339383b3a888b8a8d', '1c333032682e7d4de5e5afc05c3e483c', - 'f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-192: I=106'), - ('7f7e7d7ca2a1a0af78797e7f112e2f2c', 'd593cc99a95afef7e92038e05a59d00a', - '10111213151617181a1b1c1d1f20212224252627292a2b2c', - 'ecb-tbl-192: I=107'), - ('84859a9b2b2c2d2e868784852625245b', '51e7f96f53b4353923452c222134e1ec', - '2e2f30313334353638393a3b3d3e3f40424344454748494a', - 'ecb-tbl-192: I=108'), - ('b0b1b2b3070405026869666710171615', '4075b357a1a2b473400c3b25f32f81a4', - '4c4d4e4f51525354565758595b5c5d5e6061626365666768', - 'ecb-tbl-192: I=109'), - ('acadaaabbda2a3a00d0c0f0e595a5b5c', '302e341a3ebcd74f0d55f61714570284', - '6a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-192: I=110'), - ('121310115655544b5253545569666764', '57abdd8231280da01c5042b78cf76522', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4', - 'ecb-tbl-192: I=111'), - ('dedfd0d166616063eaebe8e94142434c', '17f9ea7eea17ac1adf0e190fef799e92', - 'a6a7a8a9abacadaeb0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', - 'ecb-tbl-192: I=112'), - ('dbdad9d81417161166677879e0e7e6e5', '2e1bdd563dd87ee5c338dd6d098d0a7a', - 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6d8d9dadbdddedfe0', - 'ecb-tbl-192: I=113'), - ('6a6b6c6de0efeeed2b2a2928c0c3c2c5', 'eb869996e6f8bfb2bfdd9e0c4504dbb2', - 'e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-192: I=114'), - ('b1b0b3b21714151a1a1b1c1d5649484b', 'c2e01549e9decf317468b3e018c61ba8', - '00010203050607080a0b0c0d0f10111214151617191a1b1c', - 'ecb-tbl-192: I=115'), - ('39380706a3a4a5a6c4c5c6c77271706f', '8da875d033c01dd463b244a1770f4a22', - '1e1f20212324252628292a2b2d2e2f30323334353738393a', - 'ecb-tbl-192: I=116'), - ('5c5d5e5f1013121539383736e2e5e4e7', '8ba0dcf3a186844f026d022f8839d696', - '3c3d3e3f41424344464748494b4c4d4e5051525355565758', - 'ecb-tbl-192: I=117'), - ('43424544ead5d4d72e2f2c2d64676661', 'e9691ff9a6cc6970e51670a0fd5b88c1', - '5a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-192: I=118'), - ('55545756989b9a65f8f9feff18171615', 'f2baec06faeed30f88ee63ba081a6e5b', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394', - 'ecb-tbl-192: I=119'), - ('05040b0a525554573c3d3e3f4a494847', '9c39d4c459ae5753394d6094adc21e78', - '969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-192: I=120'), - ('14151617595a5b5c8584fbfa8e89888b', '6345b532a11904502ea43ba99c6bd2b2', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0', - 'ecb-tbl-192: I=121'), - ('7c7d7a7bfdf2f3f029282b2a51525354', '5ffae3061a95172e4070cedce1e428c8', - 'd2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-192: I=122'), - ('38393a3b1e1d1c1341404746c23d3c3e', '0a4566be4cdf9adce5dec865b5ab34cd', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c', - 'ecb-tbl-192: I=123'), - ('8d8c939240474645818083827c7f7e41', 'ca17fcce79b7404f2559b22928f126fb', - '0e0f10111314151618191a1b1d1e1f20222324252728292a', - 'ecb-tbl-192: I=124'), - ('3b3a39381a19181f32333c3d45424340', '97ca39b849ed73a6470a97c821d82f58', - '2c2d2e2f31323334363738393b3c3d3e4041424345464748', - 'ecb-tbl-192: I=125'), - ('f0f1f6f738272625828380817f7c7d7a', '8198cb06bc684c6d3e9b7989428dcf7a', - '4a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-192: I=126'), - ('89888b8a0407061966676061141b1a19', 'f53c464c705ee0f28d9a4c59374928bd', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384', - 'ecb-tbl-192: I=127'), - ('d3d2dddcaaadacaf9c9d9e9fe8ebeae5', '9adb3d4cca559bb98c3e2ed73dbf1154', - '868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2', - 'ecb-tbl-192: I=128'), - - # ecb_tbl.txt, KEYSIZE=256 - ('834eadfccac7e1b30664b1aba44815ab', '1946dabf6a03a2a2c3d0b05080aed6fc', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=1'), - ('d9dc4dba3021b05d67c0518f72b62bf1', '5ed301d747d3cc715445ebdec62f2fb4', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=2'), - ('a291d86301a4a739f7392173aa3c604c', '6585c8f43d13a6beab6419fc5935b9d0', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=3'), - ('4264b2696498de4df79788a9f83e9390', '2a5b56a596680fcc0e05f5e0f151ecae', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=4'), - ('ee9932b3721804d5a83ef5949245b6f6', 'f5d6ff414fd2c6181494d20c37f2b8c4', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=5'), - ('e6248f55c5fdcbca9cbbb01c88a2ea77', '85399c01f59fffb5204f19f8482f00b8', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=6'), - ('b8358e41b9dff65fd461d55a99266247', '92097b4c88a041ddf98144bc8d22e8e7', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=7'), - ('f0e2d72260af58e21e015ab3a4c0d906', '89bd5b73b356ab412aef9f76cea2d65c', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=8'), - ('475b8b823ce8893db3c44a9f2a379ff7', '2536969093c55ff9454692f2fac2f530', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=9'), - ('688f5281945812862f5f3076cf80412f', '07fc76a872843f3f6e0081ee9396d637', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=10'), - ('08d1d2bc750af553365d35e75afaceaa', 'e38ba8ec2aa741358dcc93e8f141c491', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=11'), - ('8707121f47cc3efceca5f9a8474950a1', 'd028ee23e4a89075d0b03e868d7d3a42', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=12'), - ('e51aa0b135dba566939c3b6359a980c5', '8cd9423dfc459e547155c5d1d522e540', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=13'), - ('069a007fc76a459f98baf917fedf9521', '080e9517eb1677719acf728086040ae3', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=14'), - ('726165c1723fbcf6c026d7d00b091027', '7c1700211a3991fc0ecded0ab3e576b0', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=15'), - ('d7c544de91d55cfcde1f84ca382200ce', 'dabcbcc855839251db51e224fbe87435', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=16'), - ('fed3c9a161b9b5b2bd611b41dc9da357', '68d56fad0406947a4dd27a7448c10f1d', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=17'), - ('4f634cdc6551043409f30b635832cf82', 'da9a11479844d1ffee24bbf3719a9925', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=18'), - ('109ce98db0dfb36734d9f3394711b4e6', '5e4ba572f8d23e738da9b05ba24b8d81', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=19'), - ('4ea6dfaba2d8a02ffdffa89835987242', 'a115a2065d667e3f0b883837a6e903f8', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=20'), - ('5ae094f54af58e6e3cdbf976dac6d9ef', '3e9e90dc33eac2437d86ad30b137e66e', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=21'), - ('764d8e8e0f29926dbe5122e66354fdbe', '01ce82d8fbcdae824cb3c48e495c3692', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=22'), - ('3f0418f888cdf29a982bf6b75410d6a9', '0c9cff163ce936faaf083cfd3dea3117', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=23'), - ('e4a3e7cb12cdd56aa4a75197a9530220', '5131ba9bd48f2bba85560680df504b52', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=24'), - ('211677684aac1ec1a160f44c4ebf3f26', '9dc503bbf09823aec8a977a5ad26ccb2', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=25'), - ('d21e439ff749ac8f18d6d4b105e03895', '9a6db0c0862e506a9e397225884041d7', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=26'), - ('d9f6ff44646c4725bd4c0103ff5552a7', '430bf9570804185e1ab6365fc6a6860c', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=27'), - ('0b1256c2a00b976250cfc5b0c37ed382', '3525ebc02f4886e6a5a3762813e8ce8a', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=28'), - ('b056447ffc6dc4523a36cc2e972a3a79', '07fa265c763779cce224c7bad671027b', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=29'), - ('5e25ca78f0de55802524d38da3fe4456', 'e8b72b4e8be243438c9fff1f0e205872', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=30'), - ('a5bcf4728fa5eaad8567c0dc24675f83', '109d4f999a0e11ace1f05e6b22cbcb50', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=31'), - ('814e59f97ed84646b78b2ca022e9ca43', '45a5e8d4c3ed58403ff08d68a0cc4029', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=32'), - ('15478beec58f4775c7a7f5d4395514d7', '196865964db3d417b6bd4d586bcb7634', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=33'), - ('253548ffca461c67c8cbc78cd59f4756', '60436ad45ac7d30d99195f815d98d2ae', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=34'), - ('fd7ad8d73b9b0f8cc41600640f503d65', 'bb07a23f0b61014b197620c185e2cd75', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=35'), - ('06199de52c6cbf8af954cd65830bcd56', '5bc0b2850129c854423aff0751fe343b', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=36'), - ('f17c4ffe48e44c61bd891e257e725794', '7541a78f96738e6417d2a24bd2beca40', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=37'), - ('9a5b4a402a3e8a59be6bf5cd8154f029', 'b0a303054412882e464591f1546c5b9e', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=38'), - ('79bd40b91a7e07dc939d441782ae6b17', '778c06d8a355eeee214fcea14b4e0eef', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=39'), - ('d8ceaaf8976e5fbe1012d8c84f323799', '09614206d15cbace63227d06db6beebb', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=40'), - ('3316e2751e2e388b083da23dd6ac3fbe', '41b97fb20e427a9fdbbb358d9262255d', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=41'), - ('8b7cfbe37de7dca793521819242c5816', 'c1940f703d845f957652c2d64abd7adf', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=42'), - ('f23f033c0eebf8ec55752662fd58ce68', 'd2d44fcdae5332343366db297efcf21b', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=43'), - ('59eb34f6c8bdbacc5fc6ad73a59a1301', 'ea8196b79dbe167b6aa9896e287eed2b', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=44'), - ('dcde8b6bd5cf7cc22d9505e3ce81261a', 'd6b0b0c4ba6c7dbe5ed467a1e3f06c2d', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=45'), - ('e33cf7e524fed781e7042ff9f4b35dc7', 'ec51eb295250c22c2fb01816fb72bcae', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=46'), - ('27963c8facdf73062867d164df6d064c', 'aded6630a07ce9c7408a155d3bd0d36f', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=47'), - ('77b1ce386b551b995f2f2a1da994eef8', '697c9245b9937f32f5d1c82319f0363a', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=48'), - ('f083388b013679efcf0bb9b15d52ae5c', 'aad5ad50c6262aaec30541a1b7b5b19c', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-256: I=49'), - ('c5009e0dab55db0abdb636f2600290c8', '7d34b893855341ec625bd6875ac18c0d', - '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-256: I=50'), - ('7804881e26cd532d8514d3683f00f1b9', '7ef05105440f83862f5d780e88f02b41', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-256: I=51'), - ('46cddcd73d1eb53e675ca012870a92a3', 'c377c06403382061af2c9c93a8e70df6', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=52'), - ('a9fb44062bb07fe130a8e8299eacb1ab', '1dbdb3ffdc052dacc83318853abc6de5', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=53'), - ('2b6ff8d7a5cc3a28a22d5a6f221af26b', '69a6eab00432517d0bf483c91c0963c7', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=54'), - ('1a9527c29b8add4b0e3e656dbb2af8b4', '0797f41dc217c80446e1d514bd6ab197', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=55'), - ('7f99cf2c75244df015eb4b0c1050aeae', '9dfd76575902a637c01343c58e011a03', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=56'), - ('e84ff85b0d9454071909c1381646c4ed', 'acf4328ae78f34b9fa9b459747cc2658', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=57'), - ('89afd40f99521280d5399b12404f6db4', 'b0479aea12bac4fe2384cf98995150c6', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=58'), - ('a09ef32dbc5119a35ab7fa38656f0329', '9dd52789efe3ffb99f33b3da5030109a', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=59'), - ('61773457f068c376c7829b93e696e716', 'abbb755e4621ef8f1214c19f649fb9fd', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=60'), - ('a34f0cae726cce41dd498747d891b967', 'da27fb8174357bce2bed0e7354f380f9', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=61'), - ('856f59496c7388ee2d2b1a27b7697847', 'c59a0663f0993838f6e5856593bdc5ef', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=62'), - ('cb090c593ef7720bd95908fb93b49df4', 'ed60b264b5213e831607a99c0ce5e57e', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=63'), - ('a0ac75cd2f1923d460fc4d457ad95baf', 'e50548746846f3eb77b8c520640884ed', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=64'), - ('2a2b282974777689e8e9eeef525d5c5f', '28282cc7d21d6a2923641e52d188ef0c', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=65'), - ('909192939390919e0f0e09089788898a', '0dfa5b02abb18e5a815305216d6d4f8e', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=66'), - ('777675748d8e8f907170777649464744', '7359635c0eecefe31d673395fb46fb99', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=67'), - ('717073720605040b2d2c2b2a05fafbf9', '73c679f7d5aef2745c9737bb4c47fb36', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=68'), - ('64656667fefdfcc31b1a1d1ca5aaaba8', 'b192bd472a4d2eafb786e97458967626', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=69'), - ('dbdad9d86a696867b5b4b3b2c8d7d6d5', '0ec327f6c8a2b147598ca3fde61dc6a4', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=70'), - ('5c5d5e5fe3e0e1fe31303736333c3d3e', 'fc418eb3c41b859b38d4b6f646629729', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=71'), - ('545556574b48494673727574546b6a69', '30249e5ac282b1c981ea64b609f3a154', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=72'), - ('ecedeeefc6c5c4bb56575051f5fafbf8', '5e6e08646d12150776bb43c2d78a9703', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=73'), - ('464744452724252ac9c8cfced2cdcccf', 'faeb3d5de652cd3447dceb343f30394a', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=74'), - ('e6e7e4e54142435c878681801c131211', 'a8e88706823f6993ef80d05c1c7b2cf0', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=75'), - ('72737071cfcccdc2f9f8fffe710e0f0c', '8ced86677e6e00a1a1b15968f2d3cce6', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=76'), - ('505152537370714ec3c2c5c4010e0f0c', '9fc7c23858be03bdebb84e90db6786a9', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=77'), - ('a8a9aaab5c5f5e51aeafa8a93d222320', 'b4fbd65b33f70d8cf7f1111ac4649c36', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=78'), - ('dedfdcddf6f5f4eb10111617fef1f0f3', 'c5c32d5ed03c4b53cc8c1bd0ef0dbbf6', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=79'), - ('bdbcbfbe5e5d5c530b0a0d0cfac5c4c7', 'd1a7f03b773e5c212464b63709c6a891', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=80'), - ('8a8b8889050606f8f4f5f2f3636c6d6e', '6b7161d8745947ac6950438ea138d028', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-256: I=81'), - ('a6a7a4a54d4e4f40b2b3b4b539262724', 'fd47a9f7e366ee7a09bc508b00460661', - '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-256: I=82'), - ('9c9d9e9fe9eaebf40e0f08099b949596', '00d40b003dc3a0d9310b659b98c7e416', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-256: I=83'), - ('2d2c2f2e1013121dcccdcacbed121310', 'eea4c79dcc8e2bda691f20ac48be0717', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=84'), - ('f4f5f6f7edeeefd0eaebecedf7f8f9fa', 'e78f43b11c204403e5751f89d05a2509', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=85'), - ('3d3c3f3e282b2a2573727574150a0b08', 'd0f0e3d1f1244bb979931e38dd1786ef', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=86'), - ('b6b7b4b5f8fbfae5b4b5b2b3a0afaead', '042e639dc4e1e4dde7b75b749ea6f765', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=87'), - ('b7b6b5b4989b9a95878681809ba4a5a6', 'bc032fdd0efe29503a980a7d07ab46a8', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=88'), - ('a8a9aaabe5e6e798e9e8efee4748494a', '0c93ac949c0da6446effb86183b6c910', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=89'), - ('ecedeeefd9dadbd4b9b8bfbe657a7b78', 'e0d343e14da75c917b4a5cec4810d7c2', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=90'), - ('7f7e7d7c696a6b74cacbcccd929d9c9f', '0eafb821748408279b937b626792e619', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=91'), - ('08090a0b0605040bfffef9f8b9c6c7c4', 'fa1ac6e02d23b106a1fef18b274a553f', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=92'), - ('08090a0bf1f2f3ccfcfdfafb68676665', '0dadfe019cd12368075507df33c1a1e9', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=93'), - ('cacbc8c93a393837050403020d121310', '3a0879b414465d9ffbaf86b33a63a1b9', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=94'), - ('e9e8ebea8281809f8f8e8988343b3a39', '62199fadc76d0be1805d3ba0b7d914bf', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=95'), - ('515053524645444bd0d1d6d7340b0a09', '1b06d6c5d333e742730130cf78e719b4', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=96'), - ('42434041ecefee1193929594c6c9c8cb', 'f1f848824c32e9dcdcbf21580f069329', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=97'), - ('efeeedecc2c1c0cf76777071455a5b58', '1a09050cbd684f784d8e965e0782f28a', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=98'), - ('5f5e5d5c3f3c3d221d1c1b1a19161714', '79c2969e7ded2ba7d088f3f320692360', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=99'), - ('000102034142434c1c1d1a1b8d727371', '091a658a2f7444c16accb669450c7b63', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=100'), - ('8e8f8c8db1b2b38c56575051050a0b08', '97c1e3a72cca65fa977d5ed0e8a7bbfc', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=101'), - ('a7a6a5a4e8ebeae57f7e7978cad5d4d7', '70c430c6db9a17828937305a2df91a2a', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=102'), - ('8a8b888994979689454443429f909192', '629553457fbe2479098571c7c903fde8', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=103'), - ('8c8d8e8fe0e3e2ed45444342f1cecfcc', 'a25b25a61f612669e7d91265c7d476ba', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=104'), - ('fffefdfc4c4f4e31d8d9dedfb6b9b8bb', 'eb7e4e49b8ae0f024570dda293254fed', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=105'), - ('fdfcfffecccfcec12f2e29286679787b', '38fe15d61cca84516e924adce5014f67', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=106'), - ('67666564bab9b8a77071767719161714', '3ad208492249108c9f3ebeb167ad0583', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=107'), - ('9a9b98992d2e2f2084858283245b5a59', '299ba9f9bf5ab05c3580fc26edd1ed12', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=108'), - ('a4a5a6a70b0809365c5d5a5b2c232221', '19dc705b857a60fb07717b2ea5717781', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=109'), - ('464744455754555af3f2f5f4afb0b1b2', 'ffc8aeb885b5efcad06b6dbebf92e76b', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=110'), - ('323330317675746b7273747549464744', 'f58900c5e0b385253ff2546250a0142b', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=111'), - ('a8a9aaab181b1a15808186872b141516', '2ee67b56280bc462429cee6e3370cbc1', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=112'), - ('e7e6e5e4202323ddaaabacad343b3a39', '20db650a9c8e9a84ab4d25f7edc8f03f', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-256: I=113'), - ('a8a9aaab2221202fedecebea1e010003', '3c36da169525cf818843805f25b78ae5', - '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-256: I=114'), - ('f9f8fbfa5f5c5d42424344450e010003', '9a781d960db9e45e37779042fea51922', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-256: I=115'), - ('57565554f5f6f7f89697909120dfdedd', '6560395ec269c672a3c288226efdba77', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=116'), - ('f8f9fafbcccfcef1dddcdbda0e010003', '8c772b7a189ac544453d5916ebb27b9a', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=117'), - ('d9d8dbda7073727d80818687c2dddcdf', '77ca5468cc48e843d05f78eed9d6578f', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=118'), - ('c5c4c7c6080b0a1588898e8f68676665', '72cdcc71dc82c60d4429c9e2d8195baa', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=119'), - ('83828180dcdfded186878081f0cfcecd', '8080d68ce60e94b40b5b8b69eeb35afa', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=120'), - ('98999a9bdddedfa079787f7e0a050407', '44222d3cde299c04369d58ac0eba1e8e', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=121'), - ('cecfcccd4f4c4d429f9e9998dfc0c1c2', '9b8721b0a8dfc691c5bc5885dbfcb27a', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=122'), - ('404142436665647b29282f2eaba4a5a6', '0dc015ce9a3a3414b5e62ec643384183', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=123'), - ('33323130e6e5e4eb23222524dea1a0a3', '705715448a8da412025ce38345c2a148', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=124'), - ('cfcecdccf6f5f4cbe6e7e0e199969794', 'c32b5b0b6fbae165266c569f4b6ecf0b', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=125'), - ('babbb8b97271707fdcdddadb29363734', '4dca6c75192a01ddca9476af2a521e87', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=126'), - ('c9c8cbca4447465926272021545b5a59', '058691e627ecbc36ac07b6db423bd698', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=127'), - ('050407067477767956575051221d1c1f', '7444527095838fe080fc2bcdd30847eb', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=128'), - - # FIPS PUB 800-38A test vectors, 2001 edition. Annex F. - - ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', - '3ad77bb40d7a3660a89ecaf32466ef97'+'f5d3d58503b9699de785895a96fdbaaf'+ - '43b1cd7f598ece23881b00e3ed030688'+'7b0c785e27e8ad3f8223207104725dd4', - '2b7e151628aed2a6abf7158809cf4f3c', - 'NIST 800-38A, F.1.1, ECB and AES-128'), - - ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', - 'bd334f1d6e45f25ff712a214571fa5cc'+'974104846d0ad3ad7734ecb3ecee4eef'+ - 'ef7afd2270e2e60adce0ba2face6444e'+'9a4b41ba738d6c72fb16691603c18e0e', - '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', - 'NIST 800-38A, F.1.3, ECB and AES-192'), - - ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', - 'f3eed1bdb5d2a03c064b5a7e3db181f8'+'591ccb10d410ed26dc5ba74a31362870'+ - 'b6ed21b99ca6f4f9f153e7b1beafed1d'+'23304b7a39f9f3ff067d8d8f9e24ecc7', - '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', - 'NIST 800-38A, F.1.3, ECB and AES-256'), - + # FIPS PUB 197 test vectors + # http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + ( + "00112233445566778899aabbccddeeff", + "69c4e0d86a7b0430d8cdb78070b4c55a", + "000102030405060708090a0b0c0d0e0f", + "FIPS 197 C.1 (AES-128)", + ), + ( + "00112233445566778899aabbccddeeff", + "dda97ca4864cdfe06eaf70a0ec0d7191", + "000102030405060708090a0b0c0d0e0f1011121314151617", + "FIPS 197 C.2 (AES-192)", + ), + ( + "00112233445566778899aabbccddeeff", + "8ea2b7ca516745bfeafc49904b496089", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "FIPS 197 C.3 (AES-256)", + ), + # Rijndael128 test vectors + # Downloaded 2008-09-13 from + # http://www.iaik.tugraz.at/Research/krypto/AES/old/~rijmen/rijndael/testvalues.tar.gz + # ecb_tbl.txt, KEYSIZE=128 + ( + "506812a45f08c889b97f5980038b8359", + "d8f532538289ef7d06b506a4fd5be9c9", + "00010203050607080a0b0c0d0f101112", + "ecb-tbl-128: I=1", + ), + ( + "5c6d71ca30de8b8b00549984d2ec7d4b", + "59ab30f4d4ee6e4ff9907ef65b1fb68c", + "14151617191a1b1c1e1f202123242526", + "ecb-tbl-128: I=2", + ), + ( + "53f3f4c64f8616e4e7c56199f48f21f6", + "bf1ed2fcb2af3fd41443b56d85025cb1", + "28292a2b2d2e2f30323334353738393a", + "ecb-tbl-128: I=3", + ), + ( + "a1eb65a3487165fb0f1c27ff9959f703", + "7316632d5c32233edcb0780560eae8b2", + "3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-128: I=4", + ), + ( + "3553ecf0b1739558b08e350a98a39bfa", + "408c073e3e2538072b72625e68b8364b", + "50515253555657585a5b5c5d5f606162", + "ecb-tbl-128: I=5", + ), + ( + "67429969490b9711ae2b01dc497afde8", + "e1f94dfa776597beaca262f2f6366fea", + "64656667696a6b6c6e6f707173747576", + "ecb-tbl-128: I=6", + ), + ( + "93385c1f2aec8bed192f5a8e161dd508", + "f29e986c6a1c27d7b29ffd7ee92b75f1", + "78797a7b7d7e7f80828384858788898a", + "ecb-tbl-128: I=7", + ), + ( + "b5bf946be19beb8db3983b5f4c6e8ddb", + "131c886a57f8c2e713aba6955e2b55b5", + "8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-128: I=8", + ), + ( + "41321ee10e21bd907227c4450ff42324", + "d2ab7662df9b8c740210e5eeb61c199d", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-128: I=9", + ), + ( + "00a82f59c91c8486d12c0a80124f6089", + "14c10554b2859c484cab5869bbe7c470", + "b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-128: I=10", + ), + ( + "7ce0fd076754691b4bbd9faf8a1372fe", + "db4d498f0a49cf55445d502c1f9ab3b5", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9da", + "ecb-tbl-128: I=11", + ), + ( + "23605a8243d07764541bc5ad355b3129", + "6d96fef7d66590a77a77bb2056667f7f", + "dcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-128: I=12", + ), + ( + "12a8cfa23ea764fd876232b4e842bc44", + "316fb68edba736c53e78477bf913725c", + "f0f1f2f3f5f6f7f8fafbfcfdfe010002", + "ecb-tbl-128: I=13", + ), + ( + "bcaf32415e8308b3723e5fdd853ccc80", + "6936f2b93af8397fd3a771fc011c8c37", + "04050607090a0b0c0e0f101113141516", + "ecb-tbl-128: I=14", + ), + ( + "89afae685d801ad747ace91fc49adde0", + "f3f92f7a9c59179c1fcc2c2ba0b082cd", + "2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-128: I=15", + ), + ( + "f521d07b484357c4a69e76124a634216", + "6a95ea659ee3889158e7a9152ff04ebc", + "40414243454647484a4b4c4d4f505152", + "ecb-tbl-128: I=16", + ), + ( + "3e23b3bc065bcc152407e23896d77783", + "1959338344e945670678a5d432c90b93", + "54555657595a5b5c5e5f606163646566", + "ecb-tbl-128: I=17", + ), + ( + "79f0fba002be1744670e7e99290d8f52", + "e49bddd2369b83ee66e6c75a1161b394", + "68696a6b6d6e6f70727374757778797a", + "ecb-tbl-128: I=18", + ), + ( + "da23fe9d5bd63e1d72e3dafbe21a6c2a", + "d3388f19057ff704b70784164a74867d", + "7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-128: I=19", + ), + ( + "e3f5698ba90b6a022efd7db2c7e6c823", + "23aa03e2d5e4cd24f3217e596480d1e1", + "a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-128: I=20", + ), + ( + "bdc2691d4f1b73d2700679c3bcbf9c6e", + "c84113d68b666ab2a50a8bdb222e91b9", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2", + "ecb-tbl-128: I=21", + ), + ( + "ba74e02093217ee1ba1b42bd5624349a", + "ac02403981cd4340b507963db65cb7b6", + "08090a0b0d0e0f10121314151718191a", + "ecb-tbl-128: I=22", + ), + ( + "b5c593b5851c57fbf8b3f57715e8f680", + "8d1299236223359474011f6bf5088414", + "6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-128: I=23", + ), + ( + "3da9bd9cec072381788f9387c3bbf4ee", + "5a1d6ab8605505f7977e55b9a54d9b90", + "80818283858687888a8b8c8d8f909192", + "ecb-tbl-128: I=24", + ), + ( + "4197f3051121702ab65d316b3c637374", + "72e9c2d519cf555e4208805aabe3b258", + "94959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-128: I=25", + ), + ( + "9f46c62ec4f6ee3f6e8c62554bc48ab7", + "a8f3e81c4a23a39ef4d745dffe026e80", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9ba", + "ecb-tbl-128: I=26", + ), + ( + "0220673fe9e699a4ebc8e0dbeb6979c8", + "546f646449d31458f9eb4ef5483aee6c", + "bcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-128: I=27", + ), + ( + "b2b99171337ded9bc8c2c23ff6f18867", + "4dbe4bc84ac797c0ee4efb7f1a07401c", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2", + "ecb-tbl-128: I=28", + ), + ( + "a7facf4e301e984e5efeefd645b23505", + "25e10bfb411bbd4d625ac8795c8ca3b3", + "e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-128: I=29", + ), + ( + "f7c762e4a9819160fd7acfb6c4eedcdd", + "315637405054ec803614e43def177579", + "f8f9fafbfdfefe00020304050708090a", + "ecb-tbl-128: I=30", + ), + ( + "9b64fc21ea08709f4915436faa70f1be", + "60c5bc8a1410247295c6386c59e572a8", + "0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-128: I=31", + ), + ( + "52af2c3de07ee6777f55a4abfc100b3f", + "01366fc8ca52dfe055d6a00a76471ba6", + "20212223252627282a2b2c2d2f303132", + "ecb-tbl-128: I=32", + ), + ( + "2fca001224386c57aa3f968cbe2c816f", + "ecc46595516ec612449c3f581e7d42ff", + "34353637393a3b3c3e3f404143444546", + "ecb-tbl-128: I=33", + ), + ( + "4149c73658a4a9c564342755ee2c132f", + "6b7ffe4c602a154b06ee9c7dab5331c9", + "48494a4b4d4e4f50525354555758595a", + "ecb-tbl-128: I=34", + ), + ( + "af60005a00a1772f7c07a48a923c23d2", + "7da234c14039a240dd02dd0fbf84eb67", + "5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-128: I=35", + ), + ( + "6fccbc28363759914b6f0280afaf20c6", + "c7dc217d9e3604ffe7e91f080ecd5a3a", + "70717273757677787a7b7c7d7f808182", + "ecb-tbl-128: I=36", + ), + ( + "7d82a43ddf4fefa2fc5947499884d386", + "37785901863f5c81260ea41e7580cda5", + "84858687898a8b8c8e8f909193949596", + "ecb-tbl-128: I=37", + ), + ( + "5d5a990eaab9093afe4ce254dfa49ef9", + "a07b9338e92ed105e6ad720fccce9fe4", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aa", + "ecb-tbl-128: I=38", + ), + ( + "4cd1e2fd3f4434b553aae453f0ed1a02", + "ae0fb9722418cc21a7da816bbc61322c", + "acadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-128: I=39", + ), + ( + "5a2c9a9641d4299125fa1b9363104b5e", + "c826a193080ff91ffb21f71d3373c877", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2", + "ecb-tbl-128: I=40", + ), + ( + "b517fe34c0fa217d341740bfd4fe8dd4", + "1181b11b0e494e8d8b0aa6b1d5ac2c48", + "d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-128: I=41", + ), + ( + "014baf2278a69d331d5180103643e99a", + "6743c3d1519ab4f2cd9a78ab09a511bd", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fa", + "ecb-tbl-128: I=42", + ), + ( + "b529bd8164f20d0aa443d4932116841c", + "dc55c076d52bacdf2eefd952946a439d", + "fcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-128: I=43", + ), + ( + "2e596dcbb2f33d4216a1176d5bd1e456", + "711b17b590ffc72b5c8e342b601e8003", + "10111213151617181a1b1c1d1f202122", + "ecb-tbl-128: I=44", + ), + ( + "7274a1ea2b7ee2424e9a0e4673689143", + "19983bb0950783a537e1339f4aa21c75", + "24252627292a2b2c2e2f303133343536", + "ecb-tbl-128: I=45", + ), + ( + "ae20020bd4f13e9d90140bee3b5d26af", + "3ba7762e15554169c0f4fa39164c410c", + "38393a3b3d3e3f40424344454748494a", + "ecb-tbl-128: I=46", + ), + ( + "baac065da7ac26e855e79c8849d75a02", + "a0564c41245afca7af8aa2e0e588ea89", + "4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-128: I=47", + ), + ( + "7c917d8d1d45fab9e2540e28832540cc", + "5e36a42a2e099f54ae85ecd92e2381ed", + "60616263656667686a6b6c6d6f707172", + "ecb-tbl-128: I=48", + ), + ( + "bde6f89e16daadb0e847a2a614566a91", + "770036f878cd0f6ca2268172f106f2fe", + "74757677797a7b7c7e7f808183848586", + "ecb-tbl-128: I=49", + ), + ( + "c9de163725f1f5be44ebb1db51d07fbc", + "7e4e03908b716116443ccf7c94e7c259", + "88898a8b8d8e8f90929394959798999a", + "ecb-tbl-128: I=50", + ), + ( + "3af57a58f0c07dffa669572b521e2b92", + "482735a48c30613a242dd494c7f9185d", + "9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-128: I=51", + ), + ( + "3d5ebac306dde4604f1b4fbbbfcdae55", + "b4c0f6c9d4d7079addf9369fc081061d", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2", + "ecb-tbl-128: I=52", + ), + ( + "c2dfa91bceb76a1183c995020ac0b556", + "d5810fe0509ac53edcd74f89962e6270", + "c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-128: I=53", + ), + ( + "c70f54305885e9a0746d01ec56c8596b", + "03f17a16b3f91848269ecdd38ebb2165", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9ea", + "ecb-tbl-128: I=54", + ), + ( + "c4f81b610e98012ce000182050c0c2b2", + "da1248c3180348bad4a93b4d9856c9df", + "ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-128: I=55", + ), + ( + "eaab86b1d02a95d7404eff67489f97d4", + "3d10d7b63f3452c06cdf6cce18be0c2c", + "00010203050607080a0b0c0d0f101112", + "ecb-tbl-128: I=56", + ), + ( + "7c55bdb40b88870b52bec3738de82886", + "4ab823e7477dfddc0e6789018fcb6258", + "14151617191a1b1c1e1f202123242526", + "ecb-tbl-128: I=57", + ), + ( + "ba6eaa88371ff0a3bd875e3f2a975ce0", + "e6478ba56a77e70cfdaa5c843abde30e", + "28292a2b2d2e2f30323334353738393a", + "ecb-tbl-128: I=58", + ), + ( + "08059130c4c24bd30cf0575e4e0373dc", + "1673064895fbeaf7f09c5429ff75772d", + "3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-128: I=59", + ), + ( + "9a8eab004ef53093dfcf96f57e7eda82", + "4488033ae9f2efd0ca9383bfca1a94e9", + "50515253555657585a5b5c5d5f606162", + "ecb-tbl-128: I=60", + ), + ( + "0745b589e2400c25f117b1d796c28129", + "978f3b8c8f9d6f46626cac3c0bcb9217", + "64656667696a6b6c6e6f707173747576", + "ecb-tbl-128: I=61", + ), + ( + "2f1777781216cec3f044f134b1b92bbe", + "e08c8a7e582e15e5527f1d9e2eecb236", + "78797a7b7d7e7f80828384858788898a", + "ecb-tbl-128: I=62", + ), + ( + "353a779ffc541b3a3805d90ce17580fc", + "cec155b76ac5ffda4cf4f9ca91e49a7a", + "8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-128: I=63", + ), + ( + "1a1eae4415cefcf08c4ac1c8f68bea8f", + "d5ac7165763225dd2a38cdc6862c29ad", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-128: I=64", + ), + ( + "e6e7e4e5b0b3b2b5d4d5aaab16111013", + "03680fe19f7ce7275452020be70e8204", + "b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-128: I=65", + ), + ( + "f8f9fafbfbf8f9e677767170efe0e1e2", + "461df740c9781c388e94bb861ceb54f6", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9da", + "ecb-tbl-128: I=66", + ), + ( + "63626160a1a2a3a445444b4a75727370", + "451bd60367f96483042742219786a074", + "dcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-128: I=67", + ), + ( + "717073720605040b2d2c2b2a05fafbf9", + "e4dfa42671a02e57ef173b85c0ea9f2b", + "f0f1f2f3f5f6f7f8fafbfcfdfe010002", + "ecb-tbl-128: I=68", + ), + ( + "78797a7beae9e8ef3736292891969794", + "ed11b89e76274282227d854700a78b9e", + "04050607090a0b0c0e0f101113141516", + "ecb-tbl-128: I=69", + ), + ( + "838281803231300fdddcdbdaa0afaead", + "433946eaa51ea47af33895f2b90b3b75", + "18191a1b1d1e1f20222324252728292a", + "ecb-tbl-128: I=70", + ), + ( + "18191a1bbfbcbdba75747b7a7f78797a", + "6bc6d616a5d7d0284a5910ab35022528", + "2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-128: I=71", + ), + ( + "848586879b989996a3a2a5a4849b9a99", + "d2a920ecfe919d354b5f49eae9719c98", + "40414243454647484a4b4c4d4f505152", + "ecb-tbl-128: I=72", + ), + ( + "0001020322212027cacbf4f551565754", + "3a061b17f6a92885efbd0676985b373d", + "54555657595a5b5c5e5f606163646566", + "ecb-tbl-128: I=73", + ), + ( + "cecfcccdafacadb2515057564a454447", + "fadeec16e33ea2f4688499d157e20d8f", + "68696a6b6d6e6f70727374757778797a", + "ecb-tbl-128: I=74", + ), + ( + "92939091cdcecfc813121d1c80878685", + "5cdefede59601aa3c3cda36fa6b1fa13", + "7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-128: I=75", + ), + ( + "d2d3d0d16f6c6d6259585f5ed1eeefec", + "9574b00039844d92ebba7ee8719265f8", + "90919293959697989a9b9c9d9fa0a1a2", + "ecb-tbl-128: I=76", + ), + ( + "acadaeaf878485820f0e1110d5d2d3d0", + "9a9cf33758671787e5006928188643fa", + "a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-128: I=77", + ), + ( + "9091929364676619e6e7e0e1757a7b78", + "2cddd634c846ba66bb46cbfea4a674f9", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9ca", + "ecb-tbl-128: I=78", + ), + ( + "babbb8b98a89888f74757a7b92959497", + "d28bae029393c3e7e26e9fafbbb4b98f", + "cccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-128: I=79", + ), + ( + "8d8c8f8e6e6d6c633b3a3d3ccad5d4d7", + "ec27529b1bee0a9ab6a0d73ebc82e9b7", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2", + "ecb-tbl-128: I=80", + ), + ( + "86878485010203040808f7f767606162", + "3cb25c09472aff6ee7e2b47ccd7ccb17", + "f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-128: I=81", + ), + ( + "8e8f8c8d656667788a8b8c8d010e0f0c", + "dee33103a7283370d725e44ca38f8fe5", + "08090a0b0d0e0f10121314151718191a", + "ecb-tbl-128: I=82", + ), + ( + "c8c9cacb858687807a7b7475e7e0e1e2", + "27f9bcd1aac64bffc11e7815702c1a69", + "1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-128: I=83", + ), + ( + "6d6c6f6e5053525d8c8d8a8badd2d3d0", + "5df534ffad4ed0749a9988e9849d0021", + "30313233353637383a3b3c3d3f404142", + "ecb-tbl-128: I=84", + ), + ( + "28292a2b393a3b3c0607181903040506", + "a48bee75db04fb60ca2b80f752a8421b", + "44454647494a4b4c4e4f505153545556", + "ecb-tbl-128: I=85", + ), + ( + "a5a4a7a6b0b3b28ddbdadddcbdb2b3b0", + "024c8cf70bc86ee5ce03678cb7af45f9", + "58595a5b5d5e5f60626364656768696a", + "ecb-tbl-128: I=86", + ), + ( + "323330316467666130313e3f2c2b2a29", + "3c19ac0f8a3a3862ce577831301e166b", + "6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-128: I=87", + ), + ( + "27262524080b0a05171611100b141516", + "c5e355b796a57421d59ca6be82e73bca", + "80818283858687888a8b8c8d8f909192", + "ecb-tbl-128: I=88", + ), + ( + "040506074142434435340b0aa3a4a5a6", + "d94033276417abfb05a69d15b6e386e2", + "94959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-128: I=89", + ), + ( + "242526271112130c61606766bdb2b3b0", + "24b36559ea3a9b9b958fe6da3e5b8d85", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9ba", + "ecb-tbl-128: I=90", + ), + ( + "4b4a4948252627209e9f9091cec9c8cb", + "20fd4feaa0e8bf0cce7861d74ef4cb72", + "bcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-128: I=91", + ), + ( + "68696a6b6665646b9f9e9998d9e6e7e4", + "350e20d5174277b9ec314c501570a11d", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2", + "ecb-tbl-128: I=92", + ), + ( + "34353637c5c6c7c0f0f1eeef7c7b7a79", + "87a29d61b7c604d238fe73045a7efd57", + "e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-128: I=93", + ), + ( + "32333031c2c1c13f0d0c0b0a050a0b08", + "2c3164c1cc7d0064816bdc0faa362c52", + "f8f9fafbfdfefe00020304050708090a", + "ecb-tbl-128: I=94", + ), + ( + "cdcccfcebebdbcbbabaaa5a4181f1e1d", + "195fe5e8a05a2ed594f6e4400eee10b3", + "0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-128: I=95", + ), + ( + "212023223635343ba0a1a6a7445b5a59", + "e4663df19b9a21a5a284c2bd7f905025", + "20212223252627282a2b2c2d2f303132", + "ecb-tbl-128: I=96", + ), + ( + "0e0f0c0da8abaaad2f2e515002050407", + "21b88714cfb4e2a933bd281a2c4743fd", + "34353637393a3b3c3e3f404143444546", + "ecb-tbl-128: I=97", + ), + ( + "070605042a2928378e8f8889bdb2b3b0", + "cbfc3980d704fd0fc54378ab84e17870", + "48494a4b4d4e4f50525354555758595a", + "ecb-tbl-128: I=98", + ), + ( + "cbcac9c893909196a9a8a7a6a5a2a3a0", + "bc5144baa48bdeb8b63e22e03da418ef", + "5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-128: I=99", + ), + ( + "80818283c1c2c3cc9c9d9a9b0cf3f2f1", + "5a1dbaef1ee2984b8395da3bdffa3ccc", + "70717273757677787a7b7c7d7f808182", + "ecb-tbl-128: I=100", + ), + ( + "1213101125262720fafbe4e5b1b6b7b4", + "f0b11cd0729dfcc80cec903d97159574", + "84858687898a8b8c8e8f909193949596", + "ecb-tbl-128: I=101", + ), + ( + "7f7e7d7c3033320d97969190222d2c2f", + "9f95314acfddc6d1914b7f19a9cc8209", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aa", + "ecb-tbl-128: I=102", + ), + ( + "4e4f4c4d484b4a4d81808f8e53545556", + "595736f6f0f70914a94e9e007f022519", + "acadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-128: I=103", + ), + ( + "dcdddedfb0b3b2bd15141312a1bebfbc", + "1f19f57892cae586fcdfb4c694deb183", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2", + "ecb-tbl-128: I=104", + ), + ( + "93929190282b2a2dc4c5fafb92959497", + "540700ee1f6f3dab0b3eddf6caee1ef5", + "d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-128: I=105", + ), + ( + "f5f4f7f6c4c7c6d9373631307e717073", + "14a342a91019a331687a2254e6626ca2", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fa", + "ecb-tbl-128: I=106", + ), + ( + "93929190b6b5b4b364656a6b05020300", + "7b25f3c3b2eea18d743ef283140f29ff", + "fcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-128: I=107", + ), + ( + "babbb8b90d0e0f00a4a5a2a3043b3a39", + "46c2587d66e5e6fa7f7ca6411ad28047", + "10111213151617181a1b1c1d1f202122", + "ecb-tbl-128: I=108", + ), + ( + "d8d9dadb7f7c7d7a10110e0f787f7e7d", + "09470e72229d954ed5ee73886dfeeba9", + "24252627292a2b2c2e2f303133343536", + "ecb-tbl-128: I=109", + ), + ( + "fefffcfdefeced923b3a3d3c6768696a", + "d77c03de92d4d0d79ef8d4824ef365eb", + "38393a3b3d3e3f40424344454748494a", + "ecb-tbl-128: I=110", + ), + ( + "d6d7d4d58a89888f96979899a5a2a3a0", + "1d190219f290e0f1715d152d41a23593", + "4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-128: I=111", + ), + ( + "18191a1ba8abaaa5303136379b848586", + "a2cd332ce3a0818769616292e87f757b", + "60616263656667686a6b6c6d6f707172", + "ecb-tbl-128: I=112", + ), + ( + "6b6a6968a4a7a6a1d6d72829b0b7b6b5", + "d54afa6ce60fbf9341a3690e21385102", + "74757677797a7b7c7e7f808183848586", + "ecb-tbl-128: I=113", + ), + ( + "000102038a89889755545352a6a9a8ab", + "06e5c364ded628a3f5e05e613e356f46", + "88898a8b8d8e8f90929394959798999a", + "ecb-tbl-128: I=114", + ), + ( + "2d2c2f2eb3b0b1b6b6b7b8b9f2f5f4f7", + "eae63c0e62556dac85d221099896355a", + "9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-128: I=115", + ), + ( + "979695943536373856575051e09f9e9d", + "1fed060e2c6fc93ee764403a889985a2", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2", + "ecb-tbl-128: I=116", + ), + ( + "a4a5a6a7989b9a9db1b0afae7a7d7c7f", + "c25235c1a30fdec1c7cb5c5737b2a588", + "c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-128: I=117", + ), + ( + "c1c0c3c2686b6a55a8a9aeafeae5e4e7", + "796dbef95147d4d30873ad8b7b92efc0", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9ea", + "ecb-tbl-128: I=118", + ), + ( + "c1c0c3c2141716118c8d828364636261", + "cbcf0fb34d98d0bd5c22ce37211a46bf", + "ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-128: I=119", + ), + ( + "93929190cccfcec196979091e0fffefd", + "94b44da6466126cafa7c7fd09063fc24", + "00010203050607080a0b0c0d0f101112", + "ecb-tbl-128: I=120", + ), + ( + "b4b5b6b7f9fafbfc25241b1a6e69686b", + "d78c5b5ebf9b4dbda6ae506c5074c8fe", + "14151617191a1b1c1e1f202123242526", + "ecb-tbl-128: I=121", + ), + ( + "868784850704051ac7c6c1c08788898a", + "6c27444c27204b043812cf8cf95f9769", + "28292a2b2d2e2f30323334353738393a", + "ecb-tbl-128: I=122", + ), + ( + "f4f5f6f7aaa9a8affdfcf3f277707172", + "be94524ee5a2aa50bba8b75f4c0aebcf", + "3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-128: I=123", + ), + ( + "d3d2d1d00605040bc3c2c5c43e010003", + "a0aeaae91ba9f31f51aeb3588cf3a39e", + "50515253555657585a5b5c5d5f606162", + "ecb-tbl-128: I=124", + ), + ( + "73727170424140476a6b74750d0a0b08", + "275297779c28266ef9fe4c6a13c08488", + "64656667696a6b6c6e6f707173747576", + "ecb-tbl-128: I=125", + ), + ( + "c2c3c0c10a0908f754555253a1aeafac", + "86523d92bb8672cb01cf4a77fd725882", + "78797a7b7d7e7f80828384858788898a", + "ecb-tbl-128: I=126", + ), + ( + "6d6c6f6ef8fbfafd82838c8df8fffefd", + "4b8327640e9f33322a04dd96fcbf9a36", + "8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-128: I=127", + ), + ( + "f5f4f7f684878689a6a7a0a1d2cdcccf", + "ce52af650d088ca559425223f4d32694", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-128: I=128", + ), + # ecb_tbl.txt, KEYSIZE=192 + ( + "2d33eef2c0430a8a9ebf45e809c40bb6", + "dff4945e0336df4c1c56bc700eff837f", + "00010203050607080a0b0c0d0f10111214151617191a1b1c", + "ecb-tbl-192: I=1", + ), + ( + "6aa375d1fa155a61fb72353e0a5a8756", + "b6fddef4752765e347d5d2dc196d1252", + "1e1f20212324252628292a2b2d2e2f30323334353738393a", + "ecb-tbl-192: I=2", + ), + ( + "bc3736518b9490dcb8ed60eb26758ed4", + "d23684e3d963b3afcf1a114aca90cbd6", + "3c3d3e3f41424344464748494b4c4d4e5051525355565758", + "ecb-tbl-192: I=3", + ), + ( + "aa214402b46cffb9f761ec11263a311e", + "3a7ac027753e2a18c2ceab9e17c11fd0", + "5a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-192: I=4", + ), + ( + "02aea86e572eeab66b2c3af5e9a46fd6", + "8f6786bd007528ba26603c1601cdd0d8", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394", + "ecb-tbl-192: I=5", + ), + ( + "e2aef6acc33b965c4fa1f91c75ff6f36", + "d17d073b01e71502e28b47ab551168b3", + "969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-192: I=6", + ), + ( + "0659df46427162b9434865dd9499f91d", + "a469da517119fab95876f41d06d40ffa", + "b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0", + "ecb-tbl-192: I=7", + ), + ( + "49a44239c748feb456f59c276a5658df", + "6091aa3b695c11f5c0b6ad26d3d862ff", + "d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-192: I=8", + ), + ( + "66208f6e9d04525bdedb2733b6a6be37", + "70f9e67f9f8df1294131662dc6e69364", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c", + "ecb-tbl-192: I=9", + ), + ( + "3393f8dfc729c97f5480b950bc9666b0", + "d154dcafad8b207fa5cbc95e9996b559", + "0e0f10111314151618191a1b1d1e1f20222324252728292a", + "ecb-tbl-192: I=10", + ), + ( + "606834c8ce063f3234cf1145325dbd71", + "4934d541e8b46fa339c805a7aeb9e5da", + "2c2d2e2f31323334363738393b3c3d3e4041424345464748", + "ecb-tbl-192: I=11", + ), + ( + "fec1c04f529bbd17d8cecfcc4718b17f", + "62564c738f3efe186e1a127a0c4d3c61", + "4a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-192: I=12", + ), + ( + "32df99b431ed5dc5acf8caf6dc6ce475", + "07805aa043986eb23693e23bef8f3438", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384", + "ecb-tbl-192: I=13", + ), + ( + "7fdc2b746f3f665296943b83710d1f82", + "df0b4931038bade848dee3b4b85aa44b", + "868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2", + "ecb-tbl-192: I=14", + ), + ( + "8fba1510a3c5b87e2eaa3f7a91455ca2", + "592d5fded76582e4143c65099309477c", + "a4a5a6a7a9aaabacaeafb0b1b3b4b5b6b8b9babbbdbebfc0", + "ecb-tbl-192: I=15", + ), + ( + "2c9b468b1c2eed92578d41b0716b223b", + "c9b8d6545580d3dfbcdd09b954ed4e92", + "c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-192: I=16", + ), + ( + "0a2bbf0efc6bc0034f8a03433fca1b1a", + "5dccd5d6eb7c1b42acb008201df707a0", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfc", + "ecb-tbl-192: I=17", + ), + ( + "25260e1f31f4104d387222e70632504b", + "a2a91682ffeb6ed1d34340946829e6f9", + "fefe01010304050608090a0b0d0e0f10121314151718191a", + "ecb-tbl-192: I=18", + ), + ( + "c527d25a49f08a5228d338642ae65137", + "e45d185b797000348d9267960a68435d", + "1c1d1e1f21222324262728292b2c2d2e3031323335363738", + "ecb-tbl-192: I=19", + ), + ( + "3b49fc081432f5890d0e3d87e884a69e", + "45e060dae5901cda8089e10d4f4c246b", + "3a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-192: I=20", + ), + ( + "d173f9ed1e57597e166931df2754a083", + "f6951afacc0079a369c71fdcff45df50", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374", + "ecb-tbl-192: I=21", + ), + ( + "8c2b7cafa5afe7f13562daeae1adede0", + "9e95e00f351d5b3ac3d0e22e626ddad6", + "767778797b7c7d7e80818283858687888a8b8c8d8f909192", + "ecb-tbl-192: I=22", + ), + ( + "aaf4ec8c1a815aeb826cab741339532c", + "9cb566ff26d92dad083b51fdc18c173c", + "94959697999a9b9c9e9fa0a1a3a4a5a6a8a9aaabadaeafb0", + "ecb-tbl-192: I=23", + ), + ( + "40be8c5d9108e663f38f1a2395279ecf", + "c9c82766176a9b228eb9a974a010b4fb", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebec", + "ecb-tbl-192: I=24", + ), + ( + "0c8ad9bc32d43e04716753aa4cfbe351", + "d8e26aa02945881d5137f1c1e1386e88", + "2a2b2c2d2f30313234353637393a3b3c3e3f404143444546", + "ecb-tbl-192: I=25", + ), + ( + "1407b1d5f87d63357c8dc7ebbaebbfee", + "c0e024ccd68ff5ffa4d139c355a77c55", + "48494a4b4d4e4f50525354555758595a5c5d5e5f61626364", + "ecb-tbl-192: I=26", + ), + ( + "e62734d1ae3378c4549e939e6f123416", + "0b18b3d16f491619da338640df391d43", + "84858687898a8b8c8e8f90919394959698999a9b9d9e9fa0", + "ecb-tbl-192: I=27", + ), + ( + "5a752cff2a176db1a1de77f2d2cdee41", + "dbe09ac8f66027bf20cb6e434f252efc", + "a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-192: I=28", + ), + ( + "a9c8c3a4eabedc80c64730ddd018cd88", + "6d04e5e43c5b9cbe05feb9606b6480fe", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdc", + "ecb-tbl-192: I=29", + ), + ( + "ee9b3dbbdb86180072130834d305999a", + "dd1d6553b96be526d9fee0fbd7176866", + "1a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-192: I=30", + ), + ( + "a7fa8c3586b8ebde7568ead6f634a879", + "0260ca7e3f979fd015b0dd4690e16d2a", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354", + "ecb-tbl-192: I=31", + ), + ( + "37e0f4a87f127d45ac936fe7ad88c10a", + "9893734de10edcc8a67c3b110b8b8cc6", + "929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-192: I=32", + ), + ( + "3f77d8b5d92bac148e4e46f697a535c5", + "93b30b750516b2d18808d710c2ee84ef", + "464748494b4c4d4e50515253555657585a5b5c5d5f606162", + "ecb-tbl-192: I=33", + ), + ( + "d25ebb686c40f7e2c4da1014936571ca", + "16f65fa47be3cb5e6dfe7c6c37016c0e", + "828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-192: I=34", + ), + ( + "4f1c769d1e5b0552c7eca84dea26a549", + "f3847210d5391e2360608e5acb560581", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbc", + "ecb-tbl-192: I=35", + ), + ( + "8548e2f882d7584d0fafc54372b6633a", + "8754462cd223366d0753913e6af2643d", + "bebfc0c1c3c4c5c6c8c9cacbcdcecfd0d2d3d4d5d7d8d9da", + "ecb-tbl-192: I=36", + ), + ( + "87d7a336cb476f177cd2a51af2a62cdf", + "1ea20617468d1b806a1fd58145462017", + "dcdddedfe1e2e3e4e6e7e8e9ebecedeef0f1f2f3f5f6f7f8", + "ecb-tbl-192: I=37", + ), + ( + "03b1feac668c4e485c1065dfc22b44ee", + "3b155d927355d737c6be9dda60136e2e", + "fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-192: I=38", + ), + ( + "bda15e66819fa72d653a6866aa287962", + "26144f7b66daa91b6333dbd3850502b3", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334", + "ecb-tbl-192: I=39", + ), + ( + "4d0c7a0d2505b80bf8b62ceb12467f0a", + "e4f9a4ab52ced8134c649bf319ebcc90", + "363738393b3c3d3e40414243454647484a4b4c4d4f505152", + "ecb-tbl-192: I=40", + ), + ( + "626d34c9429b37211330986466b94e5f", + "b9ddd29ac6128a6cab121e34a4c62b36", + "54555657595a5b5c5e5f60616364656668696a6b6d6e6f70", + "ecb-tbl-192: I=41", + ), + ( + "333c3e6bf00656b088a17e5ff0e7f60a", + "6fcddad898f2ce4eff51294f5eaaf5c9", + "727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-192: I=42", + ), + ( + "687ed0cdc0d2a2bc8c466d05ef9d2891", + "c9a6fe2bf4028080bea6f7fc417bd7e3", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabac", + "ecb-tbl-192: I=43", + ), + ( + "487830e78cc56c1693e64b2a6660c7b6", + "6a2026846d8609d60f298a9c0673127f", + "aeafb0b1b3b4b5b6b8b9babbbdbebfc0c2c3c4c5c7c8c9ca", + "ecb-tbl-192: I=44", + ), + ( + "7a48d6b7b52b29392aa2072a32b66160", + "2cb25c005e26efea44336c4c97a4240b", + "cccdcecfd1d2d3d4d6d7d8d9dbdcdddee0e1e2e3e5e6e7e8", + "ecb-tbl-192: I=45", + ), + ( + "907320e64c8c5314d10f8d7a11c8618d", + "496967ab8680ddd73d09a0e4c7dcc8aa", + "eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-192: I=46", + ), + ( + "b561f2ca2d6e65a4a98341f3ed9ff533", + "d5af94de93487d1f3a8c577cb84a66a4", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324", + "ecb-tbl-192: I=47", + ), + ( + "df769380d212792d026f049e2e3e48ef", + "84bdac569cae2828705f267cc8376e90", + "262728292b2c2d2e30313233353637383a3b3c3d3f404142", + "ecb-tbl-192: I=48", + ), + ( + "79f374bc445bdabf8fccb8843d6054c6", + "f7401dda5ad5ab712b7eb5d10c6f99b6", + "44454647494a4b4c4e4f50515354555658595a5b5d5e5f60", + "ecb-tbl-192: I=49", + ), + ( + "4e02f1242fa56b05c68dbae8fe44c9d6", + "1c9d54318539ebd4c3b5b7e37bf119f0", + "626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-192: I=50", + ), + ( + "cf73c93cbff57ac635a6f4ad2a4a1545", + "aca572d65fb2764cffd4a6eca090ea0d", + "80818283858687888a8b8c8d8f90919294959697999a9b9c", + "ecb-tbl-192: I=51", + ), + ( + "9923548e2875750725b886566784c625", + "36d9c627b8c2a886a10ccb36eae3dfbb", + "9e9fa0a1a3a4a5a6a8a9aaabadaeafb0b2b3b4b5b7b8b9ba", + "ecb-tbl-192: I=52", + ), + ( + "4888336b723a022c9545320f836a4207", + "010edbf5981e143a81d646e597a4a568", + "bcbdbebfc1c2c3c4c6c7c8c9cbcccdced0d1d2d3d5d6d7d8", + "ecb-tbl-192: I=53", + ), + ( + "f84d9a5561b0608b1160dee000c41ba8", + "8db44d538dc20cc2f40f3067fd298e60", + "dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-192: I=54", + ), + ( + "c23192a0418e30a19b45ae3e3625bf22", + "930eb53bc71e6ac4b82972bdcd5aafb3", + "f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314", + "ecb-tbl-192: I=55", + ), + ( + "b84e0690b28b0025381ad82a15e501a7", + "6c42a81edcbc9517ccd89c30c95597b4", + "161718191b1c1d1e20212223252627282a2b2c2d2f303132", + "ecb-tbl-192: I=56", + ), + ( + "acef5e5c108876c4f06269f865b8f0b0", + "da389847ad06df19d76ee119c71e1dd3", + "34353637393a3b3c3e3f40414344454648494a4b4d4e4f50", + "ecb-tbl-192: I=57", + ), + ( + "0f1b3603e0f5ddea4548246153a5e064", + "e018fdae13d3118f9a5d1a647a3f0462", + "525354555758595a5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-192: I=58", + ), + ( + "fbb63893450d42b58c6d88cd3c1809e3", + "2aa65db36264239d3846180fabdfad20", + "70717273757677787a7b7c7d7f80818284858687898a8b8c", + "ecb-tbl-192: I=59", + ), + ( + "4bef736df150259dae0c91354e8a5f92", + "1472163e9a4f780f1ceb44b07ecf4fdb", + "8e8f90919394959698999a9b9d9e9fa0a2a3a4a5a7a8a9aa", + "ecb-tbl-192: I=60", + ), + ( + "7d2d46242056ef13d3c3fc93c128f4c7", + "c8273fdc8f3a9f72e91097614b62397c", + "acadaeafb1b2b3b4b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8", + "ecb-tbl-192: I=61", + ), + ( + "e9c1ba2df415657a256edb33934680fd", + "66c8427dcd733aaf7b3470cb7d976e3f", + "cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-192: I=62", + ), + ( + "e23ee277b0aa0a1dfb81f7527c3514f1", + "146131cb17f1424d4f8da91e6f80c1d0", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304", + "ecb-tbl-192: I=63", + ), + ( + "3e7445b0b63caaf75e4a911e12106b4c", + "2610d0ad83659081ae085266a88770dc", + "060708090b0c0d0e10111213151617181a1b1c1d1f202122", + "ecb-tbl-192: I=64", + ), + ( + "767774752023222544455a5be6e1e0e3", + "38a2b5a974b0575c5d733917fb0d4570", + "24252627292a2b2c2e2f30313334353638393a3b3d3e3f40", + "ecb-tbl-192: I=65", + ), + ( + "72737475717e7f7ce9e8ebea696a6b6c", + "e21d401ebc60de20d6c486e4f39a588b", + "424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-192: I=66", + ), + ( + "dfdedddc25262728c9c8cfcef1eeefec", + "e51d5f88c670b079c0ca1f0c2c4405a2", + "60616263656667686a6b6c6d6f70717274757677797a7b7c", + "ecb-tbl-192: I=67", + ), + ( + "fffe0100707776755f5e5d5c7675746b", + "246a94788a642fb3d1b823c8762380c8", + "7e7f80818384858688898a8b8d8e8f90929394959798999a", + "ecb-tbl-192: I=68", + ), + ( + "e0e1e2e3424140479f9e9190292e2f2c", + "b80c391c5c41a4c3b30c68e0e3d7550f", + "9c9d9e9fa1a2a3a4a6a7a8a9abacadaeb0b1b2b3b5b6b7b8", + "ecb-tbl-192: I=69", + ), + ( + "2120272690efeeed3b3a39384e4d4c4b", + "b77c4754fc64eb9a1154a9af0bb1f21c", + "babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-192: I=70", + ), + ( + "ecedeeef5350516ea1a0a7a6a3acadae", + "fb554de520d159a06bf219fc7f34a02f", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4", + "ecb-tbl-192: I=71", + ), + ( + "32333c3d25222320e9e8ebeacecdccc3", + "a89fba152d76b4927beed160ddb76c57", + "f6f7f8f9fbfcfdfe00010203050607080a0b0c0d0f101112", + "ecb-tbl-192: I=72", + ), + ( + "40414243626160678a8bb4b511161714", + "5676eab4a98d2e8473b3f3d46424247c", + "14151617191a1b1c1e1f20212324252628292a2b2d2e2f30", + "ecb-tbl-192: I=73", + ), + ( + "94959293f5fafbf81f1e1d1c7c7f7e79", + "4e8f068bd7ede52a639036ec86c33568", + "323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-192: I=74", + ), + ( + "bebfbcbd191a1b14cfcec9c8546b6a69", + "f0193c4d7aff1791ee4c07eb4a1824fc", + "50515253555657585a5b5c5d5f60616264656667696a6b6c", + "ecb-tbl-192: I=75", + ), + ( + "2c2d3233898e8f8cbbbab9b8333031ce", + "ac8686eeca9ba761afe82d67b928c33f", + "6e6f70717374757678797a7b7d7e7f80828384858788898a", + "ecb-tbl-192: I=76", + ), + ( + "84858687bfbcbdba37363938fdfafbf8", + "5faf8573e33b145b6a369cd3606ab2c9", + "8c8d8e8f91929394969798999b9c9d9ea0a1a2a3a5a6a7a8", + "ecb-tbl-192: I=77", + ), + ( + "828384857669686b909192930b08090e", + "31587e9944ab1c16b844ecad0df2e7da", + "aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-192: I=78", + ), + ( + "bebfbcbd9695948b707176779e919093", + "d017fecd91148aba37f6f3068aa67d8a", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4", + "ecb-tbl-192: I=79", + ), + ( + "8b8a85846067666521202322d0d3d2dd", + "788ef2f021a73cba2794b616078a8500", + "e6e7e8e9ebecedeef0f1f2f3f5f6f7f8fafbfcfdfe010002", + "ecb-tbl-192: I=80", + ), + ( + "76777475f1f2f3f4f8f9e6e777707172", + "5d1ef20dced6bcbc12131ac7c54788aa", + "04050607090a0b0c0e0f10111314151618191a1b1d1e1f20", + "ecb-tbl-192: I=81", + ), + ( + "a4a5a2a34f404142b4b5b6b727242522", + "b3c8cf961faf9ea05fdde6d1e4d8f663", + "222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-192: I=82", + ), + ( + "94959697e1e2e3ec16171011839c9d9e", + "143075c70605861c7fac6526199e459f", + "40414243454647484a4b4c4d4f50515254555657595a5b5c", + "ecb-tbl-192: I=83", + ), + ( + "03023d3c06010003dedfdcddfffcfde2", + "a5ae12eade9a87268d898bfc8fc0252a", + "5e5f60616364656668696a6b6d6e6f70727374757778797a", + "ecb-tbl-192: I=84", + ), + ( + "10111213f1f2f3f4cecfc0c1dbdcddde", + "0924f7cf2e877a4819f5244a360dcea9", + "7c7d7e7f81828384868788898b8c8d8e9091929395969798", + "ecb-tbl-192: I=85", + ), + ( + "67666160724d4c4f1d1c1f1e73707176", + "3d9e9635afcc3e291cc7ab3f27d1c99a", + "9a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-192: I=86", + ), + ( + "e6e7e4e5a8abaad584858283909f9e9d", + "9d80feebf87510e2b8fb98bb54fd788c", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4", + "ecb-tbl-192: I=87", + ), + ( + "71707f7e565150537d7c7f7e6162636c", + "5f9d1a082a1a37985f174002eca01309", + "d6d7d8d9dbdcdddee0e1e2e3e5e6e7e8eaebecedeff0f1f2", + "ecb-tbl-192: I=88", + ), + ( + "64656667212223245555aaaa03040506", + "a390ebb1d1403930184a44b4876646e4", + "f4f5f6f7f9fafbfcfefe01010304050608090a0b0d0e0f10", + "ecb-tbl-192: I=89", + ), + ( + "9e9f9899aba4a5a6cfcecdcc2b28292e", + "700fe918981c3195bb6c4bcb46b74e29", + "121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-192: I=90", + ), + ( + "c7c6c5c4d1d2d3dc626364653a454447", + "907984406f7bf2d17fb1eb15b673d747", + "30313233353637383a3b3c3d3f40414244454647494a4b4c", + "ecb-tbl-192: I=91", + ), + ( + "f6f7e8e9e0e7e6e51d1c1f1e5b585966", + "c32a956dcfc875c2ac7c7cc8b8cc26e1", + "4e4f50515354555658595a5b5d5e5f60626364656768696a", + "ecb-tbl-192: I=92", + ), + ( + "bcbdbebf5d5e5f5868696667f4f3f2f1", + "02646e2ebfa9b820cf8424e9b9b6eb51", + "6c6d6e6f71727374767778797b7c7d7e8081828385868788", + "ecb-tbl-192: I=93", + ), + ( + "40414647b0afaead9b9a99989b98999e", + "621fda3a5bbd54c6d3c685816bd4ead8", + "8a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-192: I=94", + ), + ( + "69686b6a0201001f0f0e0908b4bbbab9", + "d4e216040426dfaf18b152469bc5ac2f", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4", + "ecb-tbl-192: I=95", + ), + ( + "c7c6c9c8d8dfdedd5a5b5859bebdbcb3", + "9d0635b9d33b6cdbd71f5d246ea17cc8", + "c6c7c8c9cbcccdced0d1d2d3d5d6d7d8dadbdcdddfe0e1e2", + "ecb-tbl-192: I=96", + ), + ( + "dedfdcdd787b7a7dfffee1e0b2b5b4b7", + "10abad1bd9bae5448808765583a2cc1a", + "e4e5e6e7e9eaebeceeeff0f1f3f4f5f6f8f9fafbfdfefe00", + "ecb-tbl-192: I=97", + ), + ( + "4d4c4b4a606f6e6dd0d1d2d3fbf8f9fe", + "6891889e16544e355ff65a793c39c9a8", + "020304050708090a0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-192: I=98", + ), + ( + "b7b6b5b4d7d4d5dae5e4e3e2e1fefffc", + "cc735582e68072c163cd9ddf46b91279", + "20212223252627282a2b2c2d2f30313234353637393a3b3c", + "ecb-tbl-192: I=99", + ), + ( + "cecfb0b1f7f0f1f2aeafacad3e3d3c23", + "c5c68b9aeeb7f878df578efa562f9574", + "3e3f40414344454648494a4b4d4e4f50525354555758595a", + "ecb-tbl-192: I=100", + ), + ( + "cacbc8c9cdcecfc812131c1d494e4f4c", + "5f4764395a667a47d73452955d0d2ce8", + "5c5d5e5f61626364666768696b6c6d6e7071727375767778", + "ecb-tbl-192: I=101", + ), + ( + "9d9c9b9ad22d2c2fb1b0b3b20c0f0e09", + "701448331f66106cefddf1eb8267c357", + "7a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-192: I=102", + ), + ( + "7a7b787964676659959493924f404142", + "cb3ee56d2e14b4e1941666f13379d657", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4", + "ecb-tbl-192: I=103", + ), + ( + "aaaba4a5cec9c8cb1f1e1d1caba8a9a6", + "9fe16efd18ab6e1981191851fedb0764", + "b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8cacbcccdcfd0d1d2", + "ecb-tbl-192: I=104", + ), + ( + "93929190282b2a2dc4c5fafb92959497", + "3dc9ba24e1b223589b147adceb4c8e48", + "d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6e8e9eaebedeeeff0", + "ecb-tbl-192: I=105", + ), + ( + "efeee9e8ded1d0d339383b3a888b8a8d", + "1c333032682e7d4de5e5afc05c3e483c", + "f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-192: I=106", + ), + ( + "7f7e7d7ca2a1a0af78797e7f112e2f2c", + "d593cc99a95afef7e92038e05a59d00a", + "10111213151617181a1b1c1d1f20212224252627292a2b2c", + "ecb-tbl-192: I=107", + ), + ( + "84859a9b2b2c2d2e868784852625245b", + "51e7f96f53b4353923452c222134e1ec", + "2e2f30313334353638393a3b3d3e3f40424344454748494a", + "ecb-tbl-192: I=108", + ), + ( + "b0b1b2b3070405026869666710171615", + "4075b357a1a2b473400c3b25f32f81a4", + "4c4d4e4f51525354565758595b5c5d5e6061626365666768", + "ecb-tbl-192: I=109", + ), + ( + "acadaaabbda2a3a00d0c0f0e595a5b5c", + "302e341a3ebcd74f0d55f61714570284", + "6a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-192: I=110", + ), + ( + "121310115655544b5253545569666764", + "57abdd8231280da01c5042b78cf76522", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4", + "ecb-tbl-192: I=111", + ), + ( + "dedfd0d166616063eaebe8e94142434c", + "17f9ea7eea17ac1adf0e190fef799e92", + "a6a7a8a9abacadaeb0b1b2b3b5b6b7b8babbbcbdbfc0c1c2", + "ecb-tbl-192: I=112", + ), + ( + "dbdad9d81417161166677879e0e7e6e5", + "2e1bdd563dd87ee5c338dd6d098d0a7a", + "c4c5c6c7c9cacbcccecfd0d1d3d4d5d6d8d9dadbdddedfe0", + "ecb-tbl-192: I=113", + ), + ( + "6a6b6c6de0efeeed2b2a2928c0c3c2c5", + "eb869996e6f8bfb2bfdd9e0c4504dbb2", + "e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-192: I=114", + ), + ( + "b1b0b3b21714151a1a1b1c1d5649484b", + "c2e01549e9decf317468b3e018c61ba8", + "00010203050607080a0b0c0d0f10111214151617191a1b1c", + "ecb-tbl-192: I=115", + ), + ( + "39380706a3a4a5a6c4c5c6c77271706f", + "8da875d033c01dd463b244a1770f4a22", + "1e1f20212324252628292a2b2d2e2f30323334353738393a", + "ecb-tbl-192: I=116", + ), + ( + "5c5d5e5f1013121539383736e2e5e4e7", + "8ba0dcf3a186844f026d022f8839d696", + "3c3d3e3f41424344464748494b4c4d4e5051525355565758", + "ecb-tbl-192: I=117", + ), + ( + "43424544ead5d4d72e2f2c2d64676661", + "e9691ff9a6cc6970e51670a0fd5b88c1", + "5a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-192: I=118", + ), + ( + "55545756989b9a65f8f9feff18171615", + "f2baec06faeed30f88ee63ba081a6e5b", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394", + "ecb-tbl-192: I=119", + ), + ( + "05040b0a525554573c3d3e3f4a494847", + "9c39d4c459ae5753394d6094adc21e78", + "969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2", + "ecb-tbl-192: I=120", + ), + ( + "14151617595a5b5c8584fbfa8e89888b", + "6345b532a11904502ea43ba99c6bd2b2", + "b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0", + "ecb-tbl-192: I=121", + ), + ( + "7c7d7a7bfdf2f3f029282b2a51525354", + "5ffae3061a95172e4070cedce1e428c8", + "d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-192: I=122", + ), + ( + "38393a3b1e1d1c1341404746c23d3c3e", + "0a4566be4cdf9adce5dec865b5ab34cd", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c", + "ecb-tbl-192: I=123", + ), + ( + "8d8c939240474645818083827c7f7e41", + "ca17fcce79b7404f2559b22928f126fb", + "0e0f10111314151618191a1b1d1e1f20222324252728292a", + "ecb-tbl-192: I=124", + ), + ( + "3b3a39381a19181f32333c3d45424340", + "97ca39b849ed73a6470a97c821d82f58", + "2c2d2e2f31323334363738393b3c3d3e4041424345464748", + "ecb-tbl-192: I=125", + ), + ( + "f0f1f6f738272625828380817f7c7d7a", + "8198cb06bc684c6d3e9b7989428dcf7a", + "4a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-192: I=126", + ), + ( + "89888b8a0407061966676061141b1a19", + "f53c464c705ee0f28d9a4c59374928bd", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384", + "ecb-tbl-192: I=127", + ), + ( + "d3d2dddcaaadacaf9c9d9e9fe8ebeae5", + "9adb3d4cca559bb98c3e2ed73dbf1154", + "868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2", + "ecb-tbl-192: I=128", + ), + # ecb_tbl.txt, KEYSIZE=256 + ( + "834eadfccac7e1b30664b1aba44815ab", + "1946dabf6a03a2a2c3d0b05080aed6fc", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=1", + ), + ( + "d9dc4dba3021b05d67c0518f72b62bf1", + "5ed301d747d3cc715445ebdec62f2fb4", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=2", + ), + ( + "a291d86301a4a739f7392173aa3c604c", + "6585c8f43d13a6beab6419fc5935b9d0", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=3", + ), + ( + "4264b2696498de4df79788a9f83e9390", + "2a5b56a596680fcc0e05f5e0f151ecae", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-256: I=4", + ), + ( + "ee9932b3721804d5a83ef5949245b6f6", + "f5d6ff414fd2c6181494d20c37f2b8c4", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-256: I=5", + ), + ( + "e6248f55c5fdcbca9cbbb01c88a2ea77", + "85399c01f59fffb5204f19f8482f00b8", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-256: I=6", + ), + ( + "b8358e41b9dff65fd461d55a99266247", + "92097b4c88a041ddf98144bc8d22e8e7", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-256: I=7", + ), + ( + "f0e2d72260af58e21e015ab3a4c0d906", + "89bd5b73b356ab412aef9f76cea2d65c", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-256: I=8", + ), + ( + "475b8b823ce8893db3c44a9f2a379ff7", + "2536969093c55ff9454692f2fac2f530", + "40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-256: I=9", + ), + ( + "688f5281945812862f5f3076cf80412f", + "07fc76a872843f3f6e0081ee9396d637", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-256: I=10", + ), + ( + "08d1d2bc750af553365d35e75afaceaa", + "e38ba8ec2aa741358dcc93e8f141c491", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-256: I=11", + ), + ( + "8707121f47cc3efceca5f9a8474950a1", + "d028ee23e4a89075d0b03e868d7d3a42", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-256: I=12", + ), + ( + "e51aa0b135dba566939c3b6359a980c5", + "8cd9423dfc459e547155c5d1d522e540", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-256: I=13", + ), + ( + "069a007fc76a459f98baf917fedf9521", + "080e9517eb1677719acf728086040ae3", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-256: I=14", + ), + ( + "726165c1723fbcf6c026d7d00b091027", + "7c1700211a3991fc0ecded0ab3e576b0", + "30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-256: I=15", + ), + ( + "d7c544de91d55cfcde1f84ca382200ce", + "dabcbcc855839251db51e224fbe87435", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-256: I=16", + ), + ( + "fed3c9a161b9b5b2bd611b41dc9da357", + "68d56fad0406947a4dd27a7448c10f1d", + "80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-256: I=17", + ), + ( + "4f634cdc6551043409f30b635832cf82", + "da9a11479844d1ffee24bbf3719a9925", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-256: I=18", + ), + ( + "109ce98db0dfb36734d9f3394711b4e6", + "5e4ba572f8d23e738da9b05ba24b8d81", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-256: I=19", + ), + ( + "4ea6dfaba2d8a02ffdffa89835987242", + "a115a2065d667e3f0b883837a6e903f8", + "70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-256: I=20", + ), + ( + "5ae094f54af58e6e3cdbf976dac6d9ef", + "3e9e90dc33eac2437d86ad30b137e66e", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-256: I=21", + ), + ( + "764d8e8e0f29926dbe5122e66354fdbe", + "01ce82d8fbcdae824cb3c48e495c3692", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-256: I=22", + ), + ( + "3f0418f888cdf29a982bf6b75410d6a9", + "0c9cff163ce936faaf083cfd3dea3117", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-256: I=23", + ), + ( + "e4a3e7cb12cdd56aa4a75197a9530220", + "5131ba9bd48f2bba85560680df504b52", + "10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-256: I=24", + ), + ( + "211677684aac1ec1a160f44c4ebf3f26", + "9dc503bbf09823aec8a977a5ad26ccb2", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-256: I=25", + ), + ( + "d21e439ff749ac8f18d6d4b105e03895", + "9a6db0c0862e506a9e397225884041d7", + "60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-256: I=26", + ), + ( + "d9f6ff44646c4725bd4c0103ff5552a7", + "430bf9570804185e1ab6365fc6a6860c", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-256: I=27", + ), + ( + "0b1256c2a00b976250cfc5b0c37ed382", + "3525ebc02f4886e6a5a3762813e8ce8a", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-256: I=28", + ), + ( + "b056447ffc6dc4523a36cc2e972a3a79", + "07fa265c763779cce224c7bad671027b", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-256: I=29", + ), + ( + "5e25ca78f0de55802524d38da3fe4456", + "e8b72b4e8be243438c9fff1f0e205872", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=30", + ), + ( + "a5bcf4728fa5eaad8567c0dc24675f83", + "109d4f999a0e11ace1f05e6b22cbcb50", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=31", + ), + ( + "814e59f97ed84646b78b2ca022e9ca43", + "45a5e8d4c3ed58403ff08d68a0cc4029", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=32", + ), + ( + "15478beec58f4775c7a7f5d4395514d7", + "196865964db3d417b6bd4d586bcb7634", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-256: I=33", + ), + ( + "253548ffca461c67c8cbc78cd59f4756", + "60436ad45ac7d30d99195f815d98d2ae", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-256: I=34", + ), + ( + "fd7ad8d73b9b0f8cc41600640f503d65", + "bb07a23f0b61014b197620c185e2cd75", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-256: I=35", + ), + ( + "06199de52c6cbf8af954cd65830bcd56", + "5bc0b2850129c854423aff0751fe343b", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-256: I=36", + ), + ( + "f17c4ffe48e44c61bd891e257e725794", + "7541a78f96738e6417d2a24bd2beca40", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-256: I=37", + ), + ( + "9a5b4a402a3e8a59be6bf5cd8154f029", + "b0a303054412882e464591f1546c5b9e", + "40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-256: I=38", + ), + ( + "79bd40b91a7e07dc939d441782ae6b17", + "778c06d8a355eeee214fcea14b4e0eef", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-256: I=39", + ), + ( + "d8ceaaf8976e5fbe1012d8c84f323799", + "09614206d15cbace63227d06db6beebb", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-256: I=40", + ), + ( + "3316e2751e2e388b083da23dd6ac3fbe", + "41b97fb20e427a9fdbbb358d9262255d", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-256: I=41", + ), + ( + "8b7cfbe37de7dca793521819242c5816", + "c1940f703d845f957652c2d64abd7adf", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-256: I=42", + ), + ( + "f23f033c0eebf8ec55752662fd58ce68", + "d2d44fcdae5332343366db297efcf21b", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-256: I=43", + ), + ( + "59eb34f6c8bdbacc5fc6ad73a59a1301", + "ea8196b79dbe167b6aa9896e287eed2b", + "30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-256: I=44", + ), + ( + "dcde8b6bd5cf7cc22d9505e3ce81261a", + "d6b0b0c4ba6c7dbe5ed467a1e3f06c2d", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-256: I=45", + ), + ( + "e33cf7e524fed781e7042ff9f4b35dc7", + "ec51eb295250c22c2fb01816fb72bcae", + "80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-256: I=46", + ), + ( + "27963c8facdf73062867d164df6d064c", + "aded6630a07ce9c7408a155d3bd0d36f", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-256: I=47", + ), + ( + "77b1ce386b551b995f2f2a1da994eef8", + "697c9245b9937f32f5d1c82319f0363a", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-256: I=48", + ), + ( + "f083388b013679efcf0bb9b15d52ae5c", + "aad5ad50c6262aaec30541a1b7b5b19c", + "f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-256: I=49", + ), + ( + "c5009e0dab55db0abdb636f2600290c8", + "7d34b893855341ec625bd6875ac18c0d", + "20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546", + "ecb-tbl-256: I=50", + ), + ( + "7804881e26cd532d8514d3683f00f1b9", + "7ef05105440f83862f5d780e88f02b41", + "48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-256: I=51", + ), + ( + "46cddcd73d1eb53e675ca012870a92a3", + "c377c06403382061af2c9c93a8e70df6", + "70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-256: I=52", + ), + ( + "a9fb44062bb07fe130a8e8299eacb1ab", + "1dbdb3ffdc052dacc83318853abc6de5", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-256: I=53", + ), + ( + "2b6ff8d7a5cc3a28a22d5a6f221af26b", + "69a6eab00432517d0bf483c91c0963c7", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-256: I=54", + ), + ( + "1a9527c29b8add4b0e3e656dbb2af8b4", + "0797f41dc217c80446e1d514bd6ab197", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-256: I=55", + ), + ( + "7f99cf2c75244df015eb4b0c1050aeae", + "9dfd76575902a637c01343c58e011a03", + "10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-256: I=56", + ), + ( + "e84ff85b0d9454071909c1381646c4ed", + "acf4328ae78f34b9fa9b459747cc2658", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-256: I=57", + ), + ( + "89afd40f99521280d5399b12404f6db4", + "b0479aea12bac4fe2384cf98995150c6", + "60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-256: I=58", + ), + ( + "a09ef32dbc5119a35ab7fa38656f0329", + "9dd52789efe3ffb99f33b3da5030109a", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-256: I=59", + ), + ( + "61773457f068c376c7829b93e696e716", + "abbb755e4621ef8f1214c19f649fb9fd", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-256: I=60", + ), + ( + "a34f0cae726cce41dd498747d891b967", + "da27fb8174357bce2bed0e7354f380f9", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-256: I=61", + ), + ( + "856f59496c7388ee2d2b1a27b7697847", + "c59a0663f0993838f6e5856593bdc5ef", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=62", + ), + ( + "cb090c593ef7720bd95908fb93b49df4", + "ed60b264b5213e831607a99c0ce5e57e", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=63", + ), + ( + "a0ac75cd2f1923d460fc4d457ad95baf", + "e50548746846f3eb77b8c520640884ed", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=64", + ), + ( + "2a2b282974777689e8e9eeef525d5c5f", + "28282cc7d21d6a2923641e52d188ef0c", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-256: I=65", + ), + ( + "909192939390919e0f0e09089788898a", + "0dfa5b02abb18e5a815305216d6d4f8e", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-256: I=66", + ), + ( + "777675748d8e8f907170777649464744", + "7359635c0eecefe31d673395fb46fb99", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-256: I=67", + ), + ( + "717073720605040b2d2c2b2a05fafbf9", + "73c679f7d5aef2745c9737bb4c47fb36", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-256: I=68", + ), + ( + "64656667fefdfcc31b1a1d1ca5aaaba8", + "b192bd472a4d2eafb786e97458967626", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-256: I=69", + ), + ( + "dbdad9d86a696867b5b4b3b2c8d7d6d5", + "0ec327f6c8a2b147598ca3fde61dc6a4", + "40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-256: I=70", + ), + ( + "5c5d5e5fe3e0e1fe31303736333c3d3e", + "fc418eb3c41b859b38d4b6f646629729", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-256: I=71", + ), + ( + "545556574b48494673727574546b6a69", + "30249e5ac282b1c981ea64b609f3a154", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-256: I=72", + ), + ( + "ecedeeefc6c5c4bb56575051f5fafbf8", + "5e6e08646d12150776bb43c2d78a9703", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-256: I=73", + ), + ( + "464744452724252ac9c8cfced2cdcccf", + "faeb3d5de652cd3447dceb343f30394a", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-256: I=74", + ), + ( + "e6e7e4e54142435c878681801c131211", + "a8e88706823f6993ef80d05c1c7b2cf0", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-256: I=75", + ), + ( + "72737071cfcccdc2f9f8fffe710e0f0c", + "8ced86677e6e00a1a1b15968f2d3cce6", + "30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-256: I=76", + ), + ( + "505152537370714ec3c2c5c4010e0f0c", + "9fc7c23858be03bdebb84e90db6786a9", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-256: I=77", + ), + ( + "a8a9aaab5c5f5e51aeafa8a93d222320", + "b4fbd65b33f70d8cf7f1111ac4649c36", + "80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-256: I=78", + ), + ( + "dedfdcddf6f5f4eb10111617fef1f0f3", + "c5c32d5ed03c4b53cc8c1bd0ef0dbbf6", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-256: I=79", + ), + ( + "bdbcbfbe5e5d5c530b0a0d0cfac5c4c7", + "d1a7f03b773e5c212464b63709c6a891", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-256: I=80", + ), + ( + "8a8b8889050606f8f4f5f2f3636c6d6e", + "6b7161d8745947ac6950438ea138d028", + "f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-256: I=81", + ), + ( + "a6a7a4a54d4e4f40b2b3b4b539262724", + "fd47a9f7e366ee7a09bc508b00460661", + "20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546", + "ecb-tbl-256: I=82", + ), + ( + "9c9d9e9fe9eaebf40e0f08099b949596", + "00d40b003dc3a0d9310b659b98c7e416", + "48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-256: I=83", + ), + ( + "2d2c2f2e1013121dcccdcacbed121310", + "eea4c79dcc8e2bda691f20ac48be0717", + "70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-256: I=84", + ), + ( + "f4f5f6f7edeeefd0eaebecedf7f8f9fa", + "e78f43b11c204403e5751f89d05a2509", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-256: I=85", + ), + ( + "3d3c3f3e282b2a2573727574150a0b08", + "d0f0e3d1f1244bb979931e38dd1786ef", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-256: I=86", + ), + ( + "b6b7b4b5f8fbfae5b4b5b2b3a0afaead", + "042e639dc4e1e4dde7b75b749ea6f765", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-256: I=87", + ), + ( + "b7b6b5b4989b9a95878681809ba4a5a6", + "bc032fdd0efe29503a980a7d07ab46a8", + "10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-256: I=88", + ), + ( + "a8a9aaabe5e6e798e9e8efee4748494a", + "0c93ac949c0da6446effb86183b6c910", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-256: I=89", + ), + ( + "ecedeeefd9dadbd4b9b8bfbe657a7b78", + "e0d343e14da75c917b4a5cec4810d7c2", + "60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-256: I=90", + ), + ( + "7f7e7d7c696a6b74cacbcccd929d9c9f", + "0eafb821748408279b937b626792e619", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-256: I=91", + ), + ( + "08090a0b0605040bfffef9f8b9c6c7c4", + "fa1ac6e02d23b106a1fef18b274a553f", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-256: I=92", + ), + ( + "08090a0bf1f2f3ccfcfdfafb68676665", + "0dadfe019cd12368075507df33c1a1e9", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-256: I=93", + ), + ( + "cacbc8c93a393837050403020d121310", + "3a0879b414465d9ffbaf86b33a63a1b9", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=94", + ), + ( + "e9e8ebea8281809f8f8e8988343b3a39", + "62199fadc76d0be1805d3ba0b7d914bf", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=95", + ), + ( + "515053524645444bd0d1d6d7340b0a09", + "1b06d6c5d333e742730130cf78e719b4", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=96", + ), + ( + "42434041ecefee1193929594c6c9c8cb", + "f1f848824c32e9dcdcbf21580f069329", + "78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e", + "ecb-tbl-256: I=97", + ), + ( + "efeeedecc2c1c0cf76777071455a5b58", + "1a09050cbd684f784d8e965e0782f28a", + "a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6", + "ecb-tbl-256: I=98", + ), + ( + "5f5e5d5c3f3c3d221d1c1b1a19161714", + "79c2969e7ded2ba7d088f3f320692360", + "c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee", + "ecb-tbl-256: I=99", + ), + ( + "000102034142434c1c1d1a1b8d727371", + "091a658a2f7444c16accb669450c7b63", + "f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516", + "ecb-tbl-256: I=100", + ), + ( + "8e8f8c8db1b2b38c56575051050a0b08", + "97c1e3a72cca65fa977d5ed0e8a7bbfc", + "18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e", + "ecb-tbl-256: I=101", + ), + ( + "a7a6a5a4e8ebeae57f7e7978cad5d4d7", + "70c430c6db9a17828937305a2df91a2a", + "40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566", + "ecb-tbl-256: I=102", + ), + ( + "8a8b888994979689454443429f909192", + "629553457fbe2479098571c7c903fde8", + "68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e", + "ecb-tbl-256: I=103", + ), + ( + "8c8d8e8fe0e3e2ed45444342f1cecfcc", + "a25b25a61f612669e7d91265c7d476ba", + "90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6", + "ecb-tbl-256: I=104", + ), + ( + "fffefdfc4c4f4e31d8d9dedfb6b9b8bb", + "eb7e4e49b8ae0f024570dda293254fed", + "b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde", + "ecb-tbl-256: I=105", + ), + ( + "fdfcfffecccfcec12f2e29286679787b", + "38fe15d61cca84516e924adce5014f67", + "e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506", + "ecb-tbl-256: I=106", + ), + ( + "67666564bab9b8a77071767719161714", + "3ad208492249108c9f3ebeb167ad0583", + "08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e", + "ecb-tbl-256: I=107", + ), + ( + "9a9b98992d2e2f2084858283245b5a59", + "299ba9f9bf5ab05c3580fc26edd1ed12", + "30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556", + "ecb-tbl-256: I=108", + ), + ( + "a4a5a6a70b0809365c5d5a5b2c232221", + "19dc705b857a60fb07717b2ea5717781", + "58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e", + "ecb-tbl-256: I=109", + ), + ( + "464744455754555af3f2f5f4afb0b1b2", + "ffc8aeb885b5efcad06b6dbebf92e76b", + "80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6", + "ecb-tbl-256: I=110", + ), + ( + "323330317675746b7273747549464744", + "f58900c5e0b385253ff2546250a0142b", + "a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce", + "ecb-tbl-256: I=111", + ), + ( + "a8a9aaab181b1a15808186872b141516", + "2ee67b56280bc462429cee6e3370cbc1", + "d0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6", + "ecb-tbl-256: I=112", + ), + ( + "e7e6e5e4202323ddaaabacad343b3a39", + "20db650a9c8e9a84ab4d25f7edc8f03f", + "f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e", + "ecb-tbl-256: I=113", + ), + ( + "a8a9aaab2221202fedecebea1e010003", + "3c36da169525cf818843805f25b78ae5", + "20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546", + "ecb-tbl-256: I=114", + ), + ( + "f9f8fbfa5f5c5d42424344450e010003", + "9a781d960db9e45e37779042fea51922", + "48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e", + "ecb-tbl-256: I=115", + ), + ( + "57565554f5f6f7f89697909120dfdedd", + "6560395ec269c672a3c288226efdba77", + "70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596", + "ecb-tbl-256: I=116", + ), + ( + "f8f9fafbcccfcef1dddcdbda0e010003", + "8c772b7a189ac544453d5916ebb27b9a", + "98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe", + "ecb-tbl-256: I=117", + ), + ( + "d9d8dbda7073727d80818687c2dddcdf", + "77ca5468cc48e843d05f78eed9d6578f", + "c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6", + "ecb-tbl-256: I=118", + ), + ( + "c5c4c7c6080b0a1588898e8f68676665", + "72cdcc71dc82c60d4429c9e2d8195baa", + "e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e", + "ecb-tbl-256: I=119", + ), + ( + "83828180dcdfded186878081f0cfcecd", + "8080d68ce60e94b40b5b8b69eeb35afa", + "10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536", + "ecb-tbl-256: I=120", + ), + ( + "98999a9bdddedfa079787f7e0a050407", + "44222d3cde299c04369d58ac0eba1e8e", + "38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e", + "ecb-tbl-256: I=121", + ), + ( + "cecfcccd4f4c4d429f9e9998dfc0c1c2", + "9b8721b0a8dfc691c5bc5885dbfcb27a", + "60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586", + "ecb-tbl-256: I=122", + ), + ( + "404142436665647b29282f2eaba4a5a6", + "0dc015ce9a3a3414b5e62ec643384183", + "88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae", + "ecb-tbl-256: I=123", + ), + ( + "33323130e6e5e4eb23222524dea1a0a3", + "705715448a8da412025ce38345c2a148", + "b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6", + "ecb-tbl-256: I=124", + ), + ( + "cfcecdccf6f5f4cbe6e7e0e199969794", + "c32b5b0b6fbae165266c569f4b6ecf0b", + "d8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe", + "ecb-tbl-256: I=125", + ), + ( + "babbb8b97271707fdcdddadb29363734", + "4dca6c75192a01ddca9476af2a521e87", + "00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526", + "ecb-tbl-256: I=126", + ), + ( + "c9c8cbca4447465926272021545b5a59", + "058691e627ecbc36ac07b6db423bd698", + "28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e", + "ecb-tbl-256: I=127", + ), + ( + "050407067477767956575051221d1c1f", + "7444527095838fe080fc2bcdd30847eb", + "50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576", + "ecb-tbl-256: I=128", + ), + # FIPS PUB 800-38A test vectors, 2001 edition. Annex F. + ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "3ad77bb40d7a3660a89ecaf32466ef97" + + "f5d3d58503b9699de785895a96fdbaaf" + + "43b1cd7f598ece23881b00e3ed030688" + + "7b0c785e27e8ad3f8223207104725dd4", + "2b7e151628aed2a6abf7158809cf4f3c", + "NIST 800-38A, F.1.1, ECB and AES-128", + ), + ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "bd334f1d6e45f25ff712a214571fa5cc" + + "974104846d0ad3ad7734ecb3ecee4eef" + + "ef7afd2270e2e60adce0ba2face6444e" + + "9a4b41ba738d6c72fb16691603c18e0e", + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", + "NIST 800-38A, F.1.3, ECB and AES-192", + ), + ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "f3eed1bdb5d2a03c064b5a7e3db181f8" + + "591ccb10d410ed26dc5ba74a31362870" + + "b6ed21b99ca6f4f9f153e7b1beafed1d" + + "23304b7a39f9f3ff067d8d8f9e24ecc7", + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", + "NIST 800-38A, F.1.3, ECB and AES-256", + ), ] test_data_8_lanes = [] for td in test_data: - test_data_8_lanes.append((td[0] * 8, td[1] * 8, td[2], td[3])) + test_data_8_lanes.append((td[0] * 8, td[1] * 8, td[2], td[3])) test_data += test_data_8_lanes -class TestMultipleBlocks(unittest.TestCase): - def __init__(self, use_aesni): - unittest.TestCase.__init__(self) - self.use_aesni = use_aesni - - def runTest(self): - # Encrypt data which is 8*2+4 bytes long, so as to trigger (for the - # AESNI variant) both the path that parallelizes 8 lanes and the one - # that processes data serially +class TestMultipleBlocks(unittest.TestCase): + def __init__(self, use_aesni): + unittest.TestCase.__init__(self) + self.use_aesni = use_aesni - tvs = [ - (b'a' * 16, 'c0b27011eb15bf144d2fc9fae80ea16d4c231cb230416c5fac02e6835ad9d7d0'), - (b'a' * 24, 'df8435ce361a78c535b41dcb57da952abbf9ee5954dc6fbcd75fd00fa626915d'), - (b'a' * 32, '211402de6c80db1f92ba255881178e1f70783b8cfd3b37808205e48b80486cd8') - ] + def runTest(self): + # Encrypt data which is 8*2+4 bytes long, so as to trigger (for the + # AESNI variant) both the path that parallelizes 8 lanes and the one + # that processes data serially - for key, expected in tvs: + tvs = [ + (b"a" * 16, "c0b27011eb15bf144d2fc9fae80ea16d4c231cb230416c5fac02e6835ad9d7d0"), + (b"a" * 24, "df8435ce361a78c535b41dcb57da952abbf9ee5954dc6fbcd75fd00fa626915d"), + (b"a" * 32, "211402de6c80db1f92ba255881178e1f70783b8cfd3b37808205e48b80486cd8"), + ] - cipher = AES.new(key, AES.MODE_ECB, use_aesni=self.use_aesni) - h = SHA256.new() + for key, expected in tvs: + cipher = AES.new(key, AES.MODE_ECB, use_aesni=self.use_aesni) + h = SHA256.new() - pt = b"".join([ tobytes('{0:016x}'.format(x)) for x in range(20) ]) - ct = cipher.encrypt(pt) - self.assertEqual(SHA256.new(ct).hexdigest(), expected) + pt = b"".join([tobytes("{0:016x}".format(x)) for x in range(20)]) + ct = cipher.encrypt(pt) + self.assertEqual(SHA256.new(ct).hexdigest(), expected) class TestIncompleteBlocks(unittest.TestCase): + def __init__(self, use_aesni): + unittest.TestCase.__init__(self) + self.use_aesni = use_aesni - def __init__(self, use_aesni): - unittest.TestCase.__init__(self) - self.use_aesni = use_aesni + def runTest(self): + # Encrypt data with length not multiple of 16 bytes - def runTest(self): - # Encrypt data with length not multiple of 16 bytes + cipher = AES.new(b"4" * 16, AES.MODE_ECB, use_aesni=self.use_aesni) - cipher = AES.new(b'4'*16, AES.MODE_ECB, use_aesni=self.use_aesni) + for msg_len in range(1, 16): + self.assertRaises(ValueError, cipher.encrypt, b"1" * msg_len) + self.assertRaises(ValueError, cipher.encrypt, b"1" * (msg_len + 16)) + self.assertRaises(ValueError, cipher.decrypt, b"1" * msg_len) + self.assertRaises(ValueError, cipher.decrypt, b"1" * (msg_len + 16)) - for msg_len in range(1, 16): - self.assertRaises(ValueError, cipher.encrypt, b'1' * msg_len) - self.assertRaises(ValueError, cipher.encrypt, b'1' * (msg_len+16)) - self.assertRaises(ValueError, cipher.decrypt, b'1' * msg_len) - self.assertRaises(ValueError, cipher.decrypt, b'1' * (msg_len+16)) - - self.assertEqual(cipher.encrypt(b''), b'') - self.assertEqual(cipher.decrypt(b''), b'') + self.assertEqual(cipher.encrypt(b""), b"") + self.assertEqual(cipher.decrypt(b""), b"") class TestOutput(unittest.TestCase): + def __init__(self, use_aesni): + unittest.TestCase.__init__(self) + self.use_aesni = use_aesni + + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def __init__(self, use_aesni): - unittest.TestCase.__init__(self) - self.use_aesni = use_aesni + cipher = AES.new(b"4" * 16, AES.MODE_ECB, use_aesni=self.use_aesni) - def runTest(self): - # Encrypt/Decrypt data and test output parameter + pt = b"5" * 16 + ct = cipher.encrypt(pt) - cipher = AES.new(b'4'*16, AES.MODE_ECB, use_aesni=self.use_aesni) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - shorter_output = bytearray(15) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(15) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from Cryptodome.Util import _cpu_features - from .common import make_block_tests + from Cryptodome.Util import _cpu_features + from .common import make_block_tests + + tests = make_block_tests(AES, "AES", test_data, {"use_aesni": False}) + tests += [TestMultipleBlocks(False)] + tests += [TestIncompleteBlocks(False)] + if _cpu_features.have_aes_ni(): + # Run tests with AES-NI instructions if they are available. + tests += make_block_tests(AES, "AESNI", test_data, {"use_aesni": True}) + tests += [TestMultipleBlocks(True)] + tests += [TestIncompleteBlocks(True)] + tests += [TestOutput(True)] + else: + print("Skipping AESNI tests") + return tests + - tests = make_block_tests(AES, "AES", test_data, {'use_aesni': False}) - tests += [ TestMultipleBlocks(False) ] - tests += [ TestIncompleteBlocks(False) ] - if _cpu_features.have_aes_ni(): - # Run tests with AES-NI instructions if they are available. - tests += make_block_tests(AES, "AESNI", test_data, {'use_aesni': True}) - tests += [ TestMultipleBlocks(True) ] - tests += [ TestIncompleteBlocks(True) ] - tests += [ TestOutput(True) ] - else: - print("Skipping AESNI tests") - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ARC2.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ARC2.py index 00725069..861638a6 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ARC2.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ARC2.py @@ -32,136 +32,242 @@ # This is a list of (plaintext, ciphertext, key[, description[, extra_params]]) tuples. test_data = [ - # Test vectors from RFC 2268 - - # 63-bit effective key length - ('0000000000000000', 'ebb773f993278eff', '0000000000000000', - 'RFC2268-1', dict(effective_keylen=63)), - - # 64-bit effective key length - ('ffffffffffffffff', '278b27e42e2f0d49', 'ffffffffffffffff', - 'RFC2268-2', dict(effective_keylen=64)), - ('1000000000000001', '30649edf9be7d2c2', '3000000000000000', - 'RFC2268-3', dict(effective_keylen=64)), - #('0000000000000000', '61a8a244adacccf0', '88', - # 'RFC2268-4', dict(effective_keylen=64)), - ('0000000000000000', '6ccf4308974c267f', '88bca90e90875a', - 'RFC2268-5', dict(effective_keylen=64)), - ('0000000000000000', '1a807d272bbe5db1', '88bca90e90875a7f0f79c384627bafb2', - 'RFC2268-6', dict(effective_keylen=64)), - - # 128-bit effective key length - ('0000000000000000', '2269552ab0f85ca6', '88bca90e90875a7f0f79c384627bafb2', - "RFC2268-7", dict(effective_keylen=128)), - ('0000000000000000', '5b78d3a43dfff1f1', - '88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e', - "RFC2268-8", dict(effective_keylen=129)), - - # Test vectors from PyCryptodome 2.0.1's testdata.py - # 1024-bit effective key length - ('0000000000000000', '624fb3e887419e48', '5068696c6970476c617373', - 'PCTv201-0'), - ('ffffffffffffffff', '79cadef44c4a5a85', '5068696c6970476c617373', - 'PCTv201-1'), - ('0001020304050607', '90411525b34e4c2c', '5068696c6970476c617373', - 'PCTv201-2'), - ('0011223344556677', '078656aaba61cbfb', '5068696c6970476c617373', - 'PCTv201-3'), - ('0000000000000000', 'd7bcc5dbb4d6e56a', 'ffffffffffffffff', - 'PCTv201-4'), - ('ffffffffffffffff', '7259018ec557b357', 'ffffffffffffffff', - 'PCTv201-5'), - ('0001020304050607', '93d20a497f2ccb62', 'ffffffffffffffff', - 'PCTv201-6'), - ('0011223344556677', 'cb15a7f819c0014d', 'ffffffffffffffff', - 'PCTv201-7'), - ('0000000000000000', '63ac98cdf3843a7a', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', - 'PCTv201-8'), - ('ffffffffffffffff', '3fb49e2fa12371dd', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', - 'PCTv201-9'), - ('0001020304050607', '46414781ab387d5f', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', - 'PCTv201-10'), - ('0011223344556677', 'be09dc81feaca271', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', - 'PCTv201-11'), - ('0000000000000000', 'e64221e608be30ab', '53e5ffe553', - 'PCTv201-12'), - ('ffffffffffffffff', '862bc60fdcd4d9a9', '53e5ffe553', - 'PCTv201-13'), - ('0001020304050607', '6a34da50fa5e47de', '53e5ffe553', - 'PCTv201-14'), - ('0011223344556677', '584644c34503122c', '53e5ffe553', - 'PCTv201-15'), + # Test vectors from RFC 2268 + # 63-bit effective key length + ( + "0000000000000000", + "ebb773f993278eff", + "0000000000000000", + "RFC2268-1", + dict(effective_keylen=63), + ), + # 64-bit effective key length + ( + "ffffffffffffffff", + "278b27e42e2f0d49", + "ffffffffffffffff", + "RFC2268-2", + dict(effective_keylen=64), + ), + ( + "1000000000000001", + "30649edf9be7d2c2", + "3000000000000000", + "RFC2268-3", + dict(effective_keylen=64), + ), + # ('0000000000000000', '61a8a244adacccf0', '88', + # 'RFC2268-4', dict(effective_keylen=64)), + ( + "0000000000000000", + "6ccf4308974c267f", + "88bca90e90875a", + "RFC2268-5", + dict(effective_keylen=64), + ), + ( + "0000000000000000", + "1a807d272bbe5db1", + "88bca90e90875a7f0f79c384627bafb2", + "RFC2268-6", + dict(effective_keylen=64), + ), + # 128-bit effective key length + ( + "0000000000000000", + "2269552ab0f85ca6", + "88bca90e90875a7f0f79c384627bafb2", + "RFC2268-7", + dict(effective_keylen=128), + ), + ( + "0000000000000000", + "5b78d3a43dfff1f1", + "88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e", + "RFC2268-8", + dict(effective_keylen=129), + ), + # Test vectors from PyCryptodome 2.0.1's testdata.py + # 1024-bit effective key length + ( + "0000000000000000", + "624fb3e887419e48", + "5068696c6970476c617373", + "PCTv201-0", + ), + ( + "ffffffffffffffff", + "79cadef44c4a5a85", + "5068696c6970476c617373", + "PCTv201-1", + ), + ( + "0001020304050607", + "90411525b34e4c2c", + "5068696c6970476c617373", + "PCTv201-2", + ), + ( + "0011223344556677", + "078656aaba61cbfb", + "5068696c6970476c617373", + "PCTv201-3", + ), + ( + "0000000000000000", + "d7bcc5dbb4d6e56a", + "ffffffffffffffff", + "PCTv201-4", + ), + ( + "ffffffffffffffff", + "7259018ec557b357", + "ffffffffffffffff", + "PCTv201-5", + ), + ( + "0001020304050607", + "93d20a497f2ccb62", + "ffffffffffffffff", + "PCTv201-6", + ), + ( + "0011223344556677", + "cb15a7f819c0014d", + "ffffffffffffffff", + "PCTv201-7", + ), + ( + "0000000000000000", + "63ac98cdf3843a7a", + "ffffffffffffffff5065746572477265656e6177617953e5ffe553", + "PCTv201-8", + ), + ( + "ffffffffffffffff", + "3fb49e2fa12371dd", + "ffffffffffffffff5065746572477265656e6177617953e5ffe553", + "PCTv201-9", + ), + ( + "0001020304050607", + "46414781ab387d5f", + "ffffffffffffffff5065746572477265656e6177617953e5ffe553", + "PCTv201-10", + ), + ( + "0011223344556677", + "be09dc81feaca271", + "ffffffffffffffff5065746572477265656e6177617953e5ffe553", + "PCTv201-11", + ), + ( + "0000000000000000", + "e64221e608be30ab", + "53e5ffe553", + "PCTv201-12", + ), + ( + "ffffffffffffffff", + "862bc60fdcd4d9a9", + "53e5ffe553", + "PCTv201-13", + ), + ( + "0001020304050607", + "6a34da50fa5e47de", + "53e5ffe553", + "PCTv201-14", + ), + ( + "0011223344556677", + "584644c34503122c", + "53e5ffe553", + "PCTv201-15", + ), ] + class BufferOverflowTest(unittest.TestCase): - # Test a buffer overflow found in older versions of PyCrypto + # Test a buffer overflow found in older versions of PyCrypto - def runTest(self): - """ARC2 with keylength > 128""" - key = b("x") * 16384 - self.assertRaises(ValueError, ARC2.new, key, ARC2.MODE_ECB) + def runTest(self): + """ARC2 with keylength > 128""" + key = b("x") * 16384 + self.assertRaises(ValueError, ARC2.new, key, ARC2.MODE_ECB) -class KeyLength(unittest.TestCase): - def runTest(self): - ARC2.new(b'\x00' * 16, ARC2.MODE_ECB, effective_keylen=40) - self.assertRaises(ValueError, ARC2.new, bchr(0) * 4, ARC2.MODE_ECB) - self.assertRaises(ValueError, ARC2.new, bchr(0) * 129, ARC2.MODE_ECB) +class KeyLength(unittest.TestCase): + def runTest(self): + ARC2.new(b"\x00" * 16, ARC2.MODE_ECB, effective_keylen=40) + self.assertRaises(ValueError, ARC2.new, bchr(0) * 4, ARC2.MODE_ECB) + self.assertRaises(ValueError, ARC2.new, bchr(0) * 129, ARC2.MODE_ECB) - self.assertRaises(ValueError, ARC2.new, bchr(0) * 16, ARC2.MODE_ECB, - effective_keylen=39) - self.assertRaises(ValueError, ARC2.new, bchr(0) * 16, ARC2.MODE_ECB, - effective_keylen=1025) + self.assertRaises( + ValueError, + ARC2.new, + bchr(0) * 16, + ARC2.MODE_ECB, + effective_keylen=39, + ) + self.assertRaises( + ValueError, + ARC2.new, + bchr(0) * 16, + ARC2.MODE_ECB, + effective_keylen=1025, + ) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter + cipher = ARC2.new(b"4" * 16, ARC2.MODE_ECB) - cipher = ARC2.new(b'4'*16, ARC2.MODE_ECB) + pt = b"5" * 16 + ct = cipher.encrypt(pt) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) + + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from Cryptodome.Cipher import ARC2 - from .common import make_block_tests + from Cryptodome.Cipher import ARC2 + from .common import make_block_tests + + tests = make_block_tests(ARC2, "ARC2", test_data) + tests.append(BufferOverflowTest()) + tests.append(KeyLength()) + tests += [TestOutput()] + + return tests - tests = make_block_tests(ARC2, "ARC2", test_data) - tests.append(BufferOverflowTest()) - tests.append(KeyLength()) - tests += [TestOutput()] - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ARC4.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ARC4.py index a160c983..4bbf5988 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ARC4.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ARC4.py @@ -34,438 +34,455 @@ # This is a list of (plaintext, ciphertext, key[, description]) tuples. test_data = [ - # Test vectors from Eric Rescorla's message with the subject - # "RC4 compatibility testing", sent to the cipherpunks mailing list on - # September 13, 1994. - # http://cypherpunks.venona.com/date/1994/09/msg00420.html - - ('0123456789abcdef', '75b7878099e0c596', '0123456789abcdef', - 'Test vector 0'), - - ('0000000000000000', '7494c2e7104b0879', '0123456789abcdef', - 'Test vector 1'), - - ('0000000000000000', 'de188941a3375d3a', '0000000000000000', - 'Test vector 2'), - - ('00000000000000000000', 'd6a141a7ec3c38dfbd61', 'ef012345', - 'Test vector 3'), - - ('01' * 512, - '7595c3e6114a09780c4ad452338e1ffd9a1be9498f813d76533449b6778dcad8' - + 'c78a8d2ba9ac66085d0e53d59c26c2d1c490c1ebbe0ce66d1b6b1b13b6b919b8' - + '47c25a91447a95e75e4ef16779cde8bf0a95850e32af9689444fd377108f98fd' - + 'cbd4e726567500990bcc7e0ca3c4aaa304a387d20f3b8fbbcd42a1bd311d7a43' - + '03dda5ab078896ae80c18b0af66dff319616eb784e495ad2ce90d7f772a81747' - + 'b65f62093b1e0db9e5ba532fafec47508323e671327df9444432cb7367cec82f' - + '5d44c0d00b67d650a075cd4b70dedd77eb9b10231b6b5b741347396d62897421' - + 'd43df9b42e446e358e9c11a9b2184ecbef0cd8e7a877ef968f1390ec9b3d35a5' - + '585cb009290e2fcde7b5ec66d9084be44055a619d9dd7fc3166f9487f7cb2729' - + '12426445998514c15d53a18c864ce3a2b7555793988126520eacf2e3066e230c' - + '91bee4dd5304f5fd0405b35bd99c73135d3d9bc335ee049ef69b3867bf2d7bd1' - + 'eaa595d8bfc0066ff8d31509eb0c6caa006c807a623ef84c3d33c195d23ee320' - + 'c40de0558157c822d4b8c569d849aed59d4e0fd7f379586b4b7ff684ed6a189f' - + '7486d49b9c4bad9ba24b96abf924372c8a8fffb10d55354900a77a3db5f205e1' - + 'b99fcd8660863a159ad4abe40fa48934163ddde542a6585540fd683cbfd8c00f' - + '12129a284deacc4cdefe58be7137541c047126c8d49e2755ab181ab7e940b0c0', - '0123456789abcdef', - "Test vector 4"), - # shortest key - generated with arc4 package - ('7468697320697320616e206578616d706c65', - '7260677d38495a09585d69321e17eaf3cdd0', - '01'), + # Test vectors from Eric Rescorla's message with the subject + # "RC4 compatibility testing", sent to the cipherpunks mailing list on + # September 13, 1994. + # http://cypherpunks.venona.com/date/1994/09/msg00420.html + ( + "0123456789abcdef", + "75b7878099e0c596", + "0123456789abcdef", + "Test vector 0", + ), + ( + "0000000000000000", + "7494c2e7104b0879", + "0123456789abcdef", + "Test vector 1", + ), + ( + "0000000000000000", + "de188941a3375d3a", + "0000000000000000", + "Test vector 2", + ), + ( + "00000000000000000000", + "d6a141a7ec3c38dfbd61", + "ef012345", + "Test vector 3", + ), + ( + "01" * 512, + "7595c3e6114a09780c4ad452338e1ffd9a1be9498f813d76533449b6778dcad8" + + "c78a8d2ba9ac66085d0e53d59c26c2d1c490c1ebbe0ce66d1b6b1b13b6b919b8" + + "47c25a91447a95e75e4ef16779cde8bf0a95850e32af9689444fd377108f98fd" + + "cbd4e726567500990bcc7e0ca3c4aaa304a387d20f3b8fbbcd42a1bd311d7a43" + + "03dda5ab078896ae80c18b0af66dff319616eb784e495ad2ce90d7f772a81747" + + "b65f62093b1e0db9e5ba532fafec47508323e671327df9444432cb7367cec82f" + + "5d44c0d00b67d650a075cd4b70dedd77eb9b10231b6b5b741347396d62897421" + + "d43df9b42e446e358e9c11a9b2184ecbef0cd8e7a877ef968f1390ec9b3d35a5" + + "585cb009290e2fcde7b5ec66d9084be44055a619d9dd7fc3166f9487f7cb2729" + + "12426445998514c15d53a18c864ce3a2b7555793988126520eacf2e3066e230c" + + "91bee4dd5304f5fd0405b35bd99c73135d3d9bc335ee049ef69b3867bf2d7bd1" + + "eaa595d8bfc0066ff8d31509eb0c6caa006c807a623ef84c3d33c195d23ee320" + + "c40de0558157c822d4b8c569d849aed59d4e0fd7f379586b4b7ff684ed6a189f" + + "7486d49b9c4bad9ba24b96abf924372c8a8fffb10d55354900a77a3db5f205e1" + + "b99fcd8660863a159ad4abe40fa48934163ddde542a6585540fd683cbfd8c00f" + + "12129a284deacc4cdefe58be7137541c047126c8d49e2755ab181ab7e940b0c0", + "0123456789abcdef", + "Test vector 4", + ), + # shortest key - generated with arc4 package + ( + "7468697320697320616e206578616d706c65", + "7260677d38495a09585d69321e17eaf3cdd0", + "01", + ), ] class RFC6229_Tests(unittest.TestCase): - # Test vectors from RFC 6229. Each test vector is a tuple with two items: - # the ARC4 key and a dictionary. The dictionary has keystream offsets as keys - # and the 16-byte keystream starting at the relevant offset as value. - rfc6229_data = [ - # Page 3 - ( - '0102030405', - { - 0: 'b2 39 63 05 f0 3d c0 27 cc c3 52 4a 0a 11 18 a8', - 16: '69 82 94 4f 18 fc 82 d5 89 c4 03 a4 7a 0d 09 19', - 240: '28 cb 11 32 c9 6c e2 86 42 1d ca ad b8 b6 9e ae', - 256: '1c fc f6 2b 03 ed db 64 1d 77 df cf 7f 8d 8c 93', - 496: '42 b7 d0 cd d9 18 a8 a3 3d d5 17 81 c8 1f 40 41', - 512: '64 59 84 44 32 a7 da 92 3c fb 3e b4 98 06 61 f6', - 752: 'ec 10 32 7b de 2b ee fd 18 f9 27 76 80 45 7e 22', - 768: 'eb 62 63 8d 4f 0b a1 fe 9f ca 20 e0 5b f8 ff 2b', - 1008: '45 12 90 48 e6 a0 ed 0b 56 b4 90 33 8f 07 8d a5', - 1024: '30 ab bc c7 c2 0b 01 60 9f 23 ee 2d 5f 6b b7 df', - 1520: '32 94 f7 44 d8 f9 79 05 07 e7 0f 62 e5 bb ce ea', - 1536: 'd8 72 9d b4 18 82 25 9b ee 4f 82 53 25 f5 a1 30', - 2032: '1e b1 4a 0c 13 b3 bf 47 fa 2a 0b a9 3a d4 5b 8b', - 2048: 'cc 58 2f 8b a9 f2 65 e2 b1 be 91 12 e9 75 d2 d7', - 3056: 'f2 e3 0f 9b d1 02 ec bf 75 aa ad e9 bc 35 c4 3c', - 3072: 'ec 0e 11 c4 79 dc 32 9d c8 da 79 68 fe 96 56 81', - 4080: '06 83 26 a2 11 84 16 d2 1f 9d 04 b2 cd 1c a0 50', - 4096: 'ff 25 b5 89 95 99 67 07 e5 1f bd f0 8b 34 d8 75' - } - ), - # Page 4 - ( - '01020304050607', - { - 0: '29 3f 02 d4 7f 37 c9 b6 33 f2 af 52 85 fe b4 6b', - 16: 'e6 20 f1 39 0d 19 bd 84 e2 e0 fd 75 20 31 af c1', - 240: '91 4f 02 53 1c 92 18 81 0d f6 0f 67 e3 38 15 4c', - 256: 'd0 fd b5 83 07 3c e8 5a b8 39 17 74 0e c0 11 d5', - 496: '75 f8 14 11 e8 71 cf fa 70 b9 0c 74 c5 92 e4 54', - 512: '0b b8 72 02 93 8d ad 60 9e 87 a5 a1 b0 79 e5 e4', - 752: 'c2 91 12 46 b6 12 e7 e7 b9 03 df ed a1 da d8 66', - 768: '32 82 8f 91 50 2b 62 91 36 8d e8 08 1d e3 6f c2', - 1008: 'f3 b9 a7 e3 b2 97 bf 9a d8 04 51 2f 90 63 ef f1', - 1024: '8e cb 67 a9 ba 1f 55 a5 a0 67 e2 b0 26 a3 67 6f', - 1520: 'd2 aa 90 2b d4 2d 0d 7c fd 34 0c d4 58 10 52 9f', - 1536: '78 b2 72 c9 6e 42 ea b4 c6 0b d9 14 e3 9d 06 e3', - 2032: 'f4 33 2f d3 1a 07 93 96 ee 3c ee 3f 2a 4f f0 49', - 2048: '05 45 97 81 d4 1f da 7f 30 c1 be 7e 12 46 c6 23', - 3056: 'ad fd 38 68 b8 e5 14 85 d5 e6 10 01 7e 3d d6 09', - 3072: 'ad 26 58 1c 0c 5b e4 5f 4c ea 01 db 2f 38 05 d5', - 4080: 'f3 17 2c ef fc 3b 3d 99 7c 85 cc d5 af 1a 95 0c', - 4096: 'e7 4b 0b 97 31 22 7f d3 7c 0e c0 8a 47 dd d8 b8' - } - ), - ( - '0102030405060708', - { - 0: '97 ab 8a 1b f0 af b9 61 32 f2 f6 72 58 da 15 a8', - 16: '82 63 ef db 45 c4 a1 86 84 ef 87 e6 b1 9e 5b 09', - 240: '96 36 eb c9 84 19 26 f4 f7 d1 f3 62 bd df 6e 18', - 256: 'd0 a9 90 ff 2c 05 fe f5 b9 03 73 c9 ff 4b 87 0a', - 496: '73 23 9f 1d b7 f4 1d 80 b6 43 c0 c5 25 18 ec 63', - 512: '16 3b 31 99 23 a6 bd b4 52 7c 62 61 26 70 3c 0f', - 752: '49 d6 c8 af 0f 97 14 4a 87 df 21 d9 14 72 f9 66', - 768: '44 17 3a 10 3b 66 16 c5 d5 ad 1c ee 40 c8 63 d0', - 1008: '27 3c 9c 4b 27 f3 22 e4 e7 16 ef 53 a4 7d e7 a4', - 1024: 'c6 d0 e7 b2 26 25 9f a9 02 34 90 b2 61 67 ad 1d', - 1520: '1f e8 98 67 13 f0 7c 3d 9a e1 c1 63 ff 8c f9 d3', - 1536: '83 69 e1 a9 65 61 0b e8 87 fb d0 c7 91 62 aa fb', - 2032: '0a 01 27 ab b4 44 84 b9 fb ef 5a bc ae 1b 57 9f', - 2048: 'c2 cd ad c6 40 2e 8e e8 66 e1 f3 7b db 47 e4 2c', - 3056: '26 b5 1e a3 7d f8 e1 d6 f7 6f c3 b6 6a 74 29 b3', - 3072: 'bc 76 83 20 5d 4f 44 3d c1 f2 9d da 33 15 c8 7b', - 4080: 'd5 fa 5a 34 69 d2 9a aa f8 3d 23 58 9d b8 c8 5b', - 4096: '3f b4 6e 2c 8f 0f 06 8e dc e8 cd cd 7d fc 58 62' - } - ), - # Page 5 - ( - '0102030405060708090a', - { - 0: 'ed e3 b0 46 43 e5 86 cc 90 7d c2 18 51 70 99 02', - 16: '03 51 6b a7 8f 41 3b eb 22 3a a5 d4 d2 df 67 11', - 240: '3c fd 6c b5 8e e0 fd de 64 01 76 ad 00 00 04 4d', - 256: '48 53 2b 21 fb 60 79 c9 11 4c 0f fd 9c 04 a1 ad', - 496: '3e 8c ea 98 01 71 09 97 90 84 b1 ef 92 f9 9d 86', - 512: 'e2 0f b4 9b db 33 7e e4 8b 8d 8d c0 f4 af ef fe', - 752: '5c 25 21 ea cd 79 66 f1 5e 05 65 44 be a0 d3 15', - 768: 'e0 67 a7 03 19 31 a2 46 a6 c3 87 5d 2f 67 8a cb', - 1008: 'a6 4f 70 af 88 ae 56 b6 f8 75 81 c0 e2 3e 6b 08', - 1024: 'f4 49 03 1d e3 12 81 4e c6 f3 19 29 1f 4a 05 16', - 1520: 'bd ae 85 92 4b 3c b1 d0 a2 e3 3a 30 c6 d7 95 99', - 1536: '8a 0f ed db ac 86 5a 09 bc d1 27 fb 56 2e d6 0a', - 2032: 'b5 5a 0a 5b 51 a1 2a 8b e3 48 99 c3 e0 47 51 1a', - 2048: 'd9 a0 9c ea 3c e7 5f e3 96 98 07 03 17 a7 13 39', - 3056: '55 22 25 ed 11 77 f4 45 84 ac 8c fa 6c 4e b5 fc', - 3072: '7e 82 cb ab fc 95 38 1b 08 09 98 44 21 29 c2 f8', - 4080: '1f 13 5e d1 4c e6 0a 91 36 9d 23 22 be f2 5e 3c', - 4096: '08 b6 be 45 12 4a 43 e2 eb 77 95 3f 84 dc 85 53' - } - ), - ( - '0102030405060708090a0b0c0d0e0f10', - { - 0: '9a c7 cc 9a 60 9d 1e f7 b2 93 28 99 cd e4 1b 97', - 16: '52 48 c4 95 90 14 12 6a 6e 8a 84 f1 1d 1a 9e 1c', - 240: '06 59 02 e4 b6 20 f6 cc 36 c8 58 9f 66 43 2f 2b', - 256: 'd3 9d 56 6b c6 bc e3 01 07 68 15 15 49 f3 87 3f', - 496: 'b6 d1 e6 c4 a5 e4 77 1c ad 79 53 8d f2 95 fb 11', - 512: 'c6 8c 1d 5c 55 9a 97 41 23 df 1d bc 52 a4 3b 89', - 752: 'c5 ec f8 8d e8 97 fd 57 fe d3 01 70 1b 82 a2 59', - 768: 'ec cb e1 3d e1 fc c9 1c 11 a0 b2 6c 0b c8 fa 4d', - 1008: 'e7 a7 25 74 f8 78 2a e2 6a ab cf 9e bc d6 60 65', - 1024: 'bd f0 32 4e 60 83 dc c6 d3 ce dd 3c a8 c5 3c 16', - 1520: 'b4 01 10 c4 19 0b 56 22 a9 61 16 b0 01 7e d2 97', - 1536: 'ff a0 b5 14 64 7e c0 4f 63 06 b8 92 ae 66 11 81', - 2032: 'd0 3d 1b c0 3c d3 3d 70 df f9 fa 5d 71 96 3e bd', - 2048: '8a 44 12 64 11 ea a7 8b d5 1e 8d 87 a8 87 9b f5', - 3056: 'fa be b7 60 28 ad e2 d0 e4 87 22 e4 6c 46 15 a3', - 3072: 'c0 5d 88 ab d5 03 57 f9 35 a6 3c 59 ee 53 76 23', - 4080: 'ff 38 26 5c 16 42 c1 ab e8 d3 c2 fe 5e 57 2b f8', - 4096: 'a3 6a 4c 30 1a e8 ac 13 61 0c cb c1 22 56 ca cc' - } - ), - # Page 6 - ( - '0102030405060708090a0b0c0d0e0f101112131415161718', - { - 0: '05 95 e5 7f e5 f0 bb 3c 70 6e da c8 a4 b2 db 11', - 16: 'df de 31 34 4a 1a f7 69 c7 4f 07 0a ee 9e 23 26', - 240: 'b0 6b 9b 1e 19 5d 13 d8 f4 a7 99 5c 45 53 ac 05', - 256: '6b d2 37 8e c3 41 c9 a4 2f 37 ba 79 f8 8a 32 ff', - 496: 'e7 0b ce 1d f7 64 5a db 5d 2c 41 30 21 5c 35 22', - 512: '9a 57 30 c7 fc b4 c9 af 51 ff da 89 c7 f1 ad 22', - 752: '04 85 05 5f d4 f6 f0 d9 63 ef 5a b9 a5 47 69 82', - 768: '59 1f c6 6b cd a1 0e 45 2b 03 d4 55 1f 6b 62 ac', - 1008: '27 53 cc 83 98 8a fa 3e 16 88 a1 d3 b4 2c 9a 02', - 1024: '93 61 0d 52 3d 1d 3f 00 62 b3 c2 a3 bb c7 c7 f0', - 1520: '96 c2 48 61 0a ad ed fe af 89 78 c0 3d e8 20 5a', - 1536: '0e 31 7b 3d 1c 73 b9 e9 a4 68 8f 29 6d 13 3a 19', - 2032: 'bd f0 e6 c3 cc a5 b5 b9 d5 33 b6 9c 56 ad a1 20', - 2048: '88 a2 18 b6 e2 ec e1 e6 24 6d 44 c7 59 d1 9b 10', - 3056: '68 66 39 7e 95 c1 40 53 4f 94 26 34 21 00 6e 40', - 3072: '32 cb 0a 1e 95 42 c6 b3 b8 b3 98 ab c3 b0 f1 d5', - 4080: '29 a0 b8 ae d5 4a 13 23 24 c6 2e 42 3f 54 b4 c8', - 4096: '3c b0 f3 b5 02 0a 98 b8 2a f9 fe 15 44 84 a1 68' - } - ), - ( - '0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', - { - 0: 'ea a6 bd 25 88 0b f9 3d 3f 5d 1e 4c a2 61 1d 91', - 16: 'cf a4 5c 9f 7e 71 4b 54 bd fa 80 02 7c b1 43 80', - 240: '11 4a e3 44 de d7 1b 35 f2 e6 0f eb ad 72 7f d8', - 256: '02 e1 e7 05 6b 0f 62 39 00 49 64 22 94 3e 97 b6', - 496: '91 cb 93 c7 87 96 4e 10 d9 52 7d 99 9c 6f 93 6b', - 512: '49 b1 8b 42 f8 e8 36 7c be b5 ef 10 4b a1 c7 cd', - 752: '87 08 4b 3b a7 00 ba de 95 56 10 67 27 45 b3 74', - 768: 'e7 a7 b9 e9 ec 54 0d 5f f4 3b db 12 79 2d 1b 35', - 1008: 'c7 99 b5 96 73 8f 6b 01 8c 76 c7 4b 17 59 bd 90', - 1024: '7f ec 5b fd 9f 9b 89 ce 65 48 30 90 92 d7 e9 58', - 1520: '40 f2 50 b2 6d 1f 09 6a 4a fd 4c 34 0a 58 88 15', - 1536: '3e 34 13 5c 79 db 01 02 00 76 76 51 cf 26 30 73', - 2032: 'f6 56 ab cc f8 8d d8 27 02 7b 2c e9 17 d4 64 ec', - 2048: '18 b6 25 03 bf bc 07 7f ba bb 98 f2 0d 98 ab 34', - 3056: '8a ed 95 ee 5b 0d cb fb ef 4e b2 1d 3a 3f 52 f9', - 3072: '62 5a 1a b0 0e e3 9a 53 27 34 6b dd b0 1a 9c 18', - 4080: 'a1 3a 7c 79 c7 e1 19 b5 ab 02 96 ab 28 c3 00 b9', - 4096: 'f3 e4 c0 a2 e0 2d 1d 01 f7 f0 a7 46 18 af 2b 48' - } - ), - # Page 7 - ( - '833222772a', - { - 0: '80 ad 97 bd c9 73 df 8a 2e 87 9e 92 a4 97 ef da', - 16: '20 f0 60 c2 f2 e5 12 65 01 d3 d4 fe a1 0d 5f c0', - 240: 'fa a1 48 e9 90 46 18 1f ec 6b 20 85 f3 b2 0e d9', - 256: 'f0 da f5 ba b3 d5 96 83 98 57 84 6f 73 fb fe 5a', - 496: '1c 7e 2f c4 63 92 32 fe 29 75 84 b2 96 99 6b c8', - 512: '3d b9 b2 49 40 6c c8 ed ff ac 55 cc d3 22 ba 12', - 752: 'e4 f9 f7 e0 06 61 54 bb d1 25 b7 45 56 9b c8 97', - 768: '75 d5 ef 26 2b 44 c4 1a 9c f6 3a e1 45 68 e1 b9', - 1008: '6d a4 53 db f8 1e 82 33 4a 3d 88 66 cb 50 a1 e3', - 1024: '78 28 d0 74 11 9c ab 5c 22 b2 94 d7 a9 bf a0 bb', - 1520: 'ad b8 9c ea 9a 15 fb e6 17 29 5b d0 4b 8c a0 5c', - 1536: '62 51 d8 7f d4 aa ae 9a 7e 4a d5 c2 17 d3 f3 00', - 2032: 'e7 11 9b d6 dd 9b 22 af e8 f8 95 85 43 28 81 e2', - 2048: '78 5b 60 fd 7e c4 e9 fc b6 54 5f 35 0d 66 0f ab', - 3056: 'af ec c0 37 fd b7 b0 83 8e b3 d7 0b cd 26 83 82', - 3072: 'db c1 a7 b4 9d 57 35 8c c9 fa 6d 61 d7 3b 7c f0', - 4080: '63 49 d1 26 a3 7a fc ba 89 79 4f 98 04 91 4f dc', - 4096: 'bf 42 c3 01 8c 2f 7c 66 bf de 52 49 75 76 81 15' - } - ), - ( - '1910833222772a', - { - 0: 'bc 92 22 db d3 27 4d 8f c6 6d 14 cc bd a6 69 0b', - 16: '7a e6 27 41 0c 9a 2b e6 93 df 5b b7 48 5a 63 e3', - 240: '3f 09 31 aa 03 de fb 30 0f 06 01 03 82 6f 2a 64', - 256: 'be aa 9e c8 d5 9b b6 81 29 f3 02 7c 96 36 11 81', - 496: '74 e0 4d b4 6d 28 64 8d 7d ee 8a 00 64 b0 6c fe', - 512: '9b 5e 81 c6 2f e0 23 c5 5b e4 2f 87 bb f9 32 b8', - 752: 'ce 17 8f c1 82 6e fe cb c1 82 f5 79 99 a4 61 40', - 768: '8b df 55 cd 55 06 1c 06 db a6 be 11 de 4a 57 8a', - 1008: '62 6f 5f 4d ce 65 25 01 f3 08 7d 39 c9 2c c3 49', - 1024: '42 da ac 6a 8f 9a b9 a7 fd 13 7c 60 37 82 56 82', - 1520: 'cc 03 fd b7 91 92 a2 07 31 2f 53 f5 d4 dc 33 d9', - 1536: 'f7 0f 14 12 2a 1c 98 a3 15 5d 28 b8 a0 a8 a4 1d', - 2032: '2a 3a 30 7a b2 70 8a 9c 00 fe 0b 42 f9 c2 d6 a1', - 2048: '86 26 17 62 7d 22 61 ea b0 b1 24 65 97 ca 0a e9', - 3056: '55 f8 77 ce 4f 2e 1d db bf 8e 13 e2 cd e0 fd c8', - 3072: '1b 15 56 cb 93 5f 17 33 37 70 5f bb 5d 50 1f c1', - 4080: 'ec d0 e9 66 02 be 7f 8d 50 92 81 6c cc f2 c2 e9', - 4096: '02 78 81 fa b4 99 3a 1c 26 20 24 a9 4f ff 3f 61' - } - ), - # Page 8 - ( - '641910833222772a', - { - 0: 'bb f6 09 de 94 13 17 2d 07 66 0c b6 80 71 69 26', - 16: '46 10 1a 6d ab 43 11 5d 6c 52 2b 4f e9 36 04 a9', - 240: 'cb e1 ff f2 1c 96 f3 ee f6 1e 8f e0 54 2c bd f0', - 256: '34 79 38 bf fa 40 09 c5 12 cf b4 03 4b 0d d1 a7', - 496: '78 67 a7 86 d0 0a 71 47 90 4d 76 dd f1 e5 20 e3', - 512: '8d 3e 9e 1c ae fc cc b3 fb f8 d1 8f 64 12 0b 32', - 752: '94 23 37 f8 fd 76 f0 fa e8 c5 2d 79 54 81 06 72', - 768: 'b8 54 8c 10 f5 16 67 f6 e6 0e 18 2f a1 9b 30 f7', - 1008: '02 11 c7 c6 19 0c 9e fd 12 37 c3 4c 8f 2e 06 c4', - 1024: 'bd a6 4f 65 27 6d 2a ac b8 f9 02 12 20 3a 80 8e', - 1520: 'bd 38 20 f7 32 ff b5 3e c1 93 e7 9d 33 e2 7c 73', - 1536: 'd0 16 86 16 86 19 07 d4 82 e3 6c da c8 cf 57 49', - 2032: '97 b0 f0 f2 24 b2 d2 31 71 14 80 8f b0 3a f7 a0', - 2048: 'e5 96 16 e4 69 78 79 39 a0 63 ce ea 9a f9 56 d1', - 3056: 'c4 7e 0d c1 66 09 19 c1 11 01 20 8f 9e 69 aa 1f', - 3072: '5a e4 f1 28 96 b8 37 9a 2a ad 89 b5 b5 53 d6 b0', - 4080: '6b 6b 09 8d 0c 29 3b c2 99 3d 80 bf 05 18 b6 d9', - 4096: '81 70 cc 3c cd 92 a6 98 62 1b 93 9d d3 8f e7 b9' - } - ), - ( - '8b37641910833222772a', - { - 0: 'ab 65 c2 6e dd b2 87 60 0d b2 fd a1 0d 1e 60 5c', - 16: 'bb 75 90 10 c2 96 58 f2 c7 2d 93 a2 d1 6d 29 30', - 240: 'b9 01 e8 03 6e d1 c3 83 cd 3c 4c 4d d0 a6 ab 05', - 256: '3d 25 ce 49 22 92 4c 55 f0 64 94 33 53 d7 8a 6c', - 496: '12 c1 aa 44 bb f8 7e 75 e6 11 f6 9b 2c 38 f4 9b', - 512: '28 f2 b3 43 4b 65 c0 98 77 47 00 44 c6 ea 17 0d', - 752: 'bd 9e f8 22 de 52 88 19 61 34 cf 8a f7 83 93 04', - 768: '67 55 9c 23 f0 52 15 84 70 a2 96 f7 25 73 5a 32', - 1008: '8b ab 26 fb c2 c1 2b 0f 13 e2 ab 18 5e ab f2 41', - 1024: '31 18 5a 6d 69 6f 0c fa 9b 42 80 8b 38 e1 32 a2', - 1520: '56 4d 3d ae 18 3c 52 34 c8 af 1e 51 06 1c 44 b5', - 1536: '3c 07 78 a7 b5 f7 2d 3c 23 a3 13 5c 7d 67 b9 f4', - 2032: 'f3 43 69 89 0f cf 16 fb 51 7d ca ae 44 63 b2 dd', - 2048: '02 f3 1c 81 e8 20 07 31 b8 99 b0 28 e7 91 bf a7', - 3056: '72 da 64 62 83 22 8c 14 30 08 53 70 17 95 61 6f', - 3072: '4e 0a 8c 6f 79 34 a7 88 e2 26 5e 81 d6 d0 c8 f4', - 4080: '43 8d d5 ea fe a0 11 1b 6f 36 b4 b9 38 da 2a 68', - 4096: '5f 6b fc 73 81 58 74 d9 71 00 f0 86 97 93 57 d8' - } - ), - # Page 9 - ( - 'ebb46227c6cc8b37641910833222772a', - { - 0: '72 0c 94 b6 3e df 44 e1 31 d9 50 ca 21 1a 5a 30', - 16: 'c3 66 fd ea cf 9c a8 04 36 be 7c 35 84 24 d2 0b', - 240: 'b3 39 4a 40 aa bf 75 cb a4 22 82 ef 25 a0 05 9f', - 256: '48 47 d8 1d a4 94 2d bc 24 9d ef c4 8c 92 2b 9f', - 496: '08 12 8c 46 9f 27 53 42 ad da 20 2b 2b 58 da 95', - 512: '97 0d ac ef 40 ad 98 72 3b ac 5d 69 55 b8 17 61', - 752: '3c b8 99 93 b0 7b 0c ed 93 de 13 d2 a1 10 13 ac', - 768: 'ef 2d 67 6f 15 45 c2 c1 3d c6 80 a0 2f 4a db fe', - 1008: 'b6 05 95 51 4f 24 bc 9f e5 22 a6 ca d7 39 36 44', - 1024: 'b5 15 a8 c5 01 17 54 f5 90 03 05 8b db 81 51 4e', - 1520: '3c 70 04 7e 8c bc 03 8e 3b 98 20 db 60 1d a4 95', - 1536: '11 75 da 6e e7 56 de 46 a5 3e 2b 07 56 60 b7 70', - 2032: '00 a5 42 bb a0 21 11 cc 2c 65 b3 8e bd ba 58 7e', - 2048: '58 65 fd bb 5b 48 06 41 04 e8 30 b3 80 f2 ae de', - 3056: '34 b2 1a d2 ad 44 e9 99 db 2d 7f 08 63 f0 d9 b6', - 3072: '84 a9 21 8f c3 6e 8a 5f 2c cf be ae 53 a2 7d 25', - 4080: 'a2 22 1a 11 b8 33 cc b4 98 a5 95 40 f0 54 5f 4a', - 4096: '5b be b4 78 7d 59 e5 37 3f db ea 6c 6f 75 c2 9b' - } - ), - ( - 'c109163908ebe51debb46227c6cc8b37641910833222772a', - { - 0: '54 b6 4e 6b 5a 20 b5 e2 ec 84 59 3d c7 98 9d a7', - 16: 'c1 35 ee e2 37 a8 54 65 ff 97 dc 03 92 4f 45 ce', - 240: 'cf cc 92 2f b4 a1 4a b4 5d 61 75 aa bb f2 d2 01', - 256: '83 7b 87 e2 a4 46 ad 0e f7 98 ac d0 2b 94 12 4f', - 496: '17 a6 db d6 64 92 6a 06 36 b3 f4 c3 7a 4f 46 94', - 512: '4a 5f 9f 26 ae ee d4 d4 a2 5f 63 2d 30 52 33 d9', - 752: '80 a3 d0 1e f0 0c 8e 9a 42 09 c1 7f 4e eb 35 8c', - 768: 'd1 5e 7d 5f fa aa bc 02 07 bf 20 0a 11 77 93 a2', - 1008: '34 96 82 bf 58 8e aa 52 d0 aa 15 60 34 6a ea fa', - 1024: 'f5 85 4c db 76 c8 89 e3 ad 63 35 4e 5f 72 75 e3', - 1520: '53 2c 7c ec cb 39 df 32 36 31 84 05 a4 b1 27 9c', - 1536: 'ba ef e6 d9 ce b6 51 84 22 60 e0 d1 e0 5e 3b 90', - 2032: 'e8 2d 8c 6d b5 4e 3c 63 3f 58 1c 95 2b a0 42 07', - 2048: '4b 16 e5 0a bd 38 1b d7 09 00 a9 cd 9a 62 cb 23', - 3056: '36 82 ee 33 bd 14 8b d9 f5 86 56 cd 8f 30 d9 fb', - 3072: '1e 5a 0b 84 75 04 5d 9b 20 b2 62 86 24 ed fd 9e', - 4080: '63 ed d6 84 fb 82 62 82 fe 52 8f 9c 0e 92 37 bc', - 4096: 'e4 dd 2e 98 d6 96 0f ae 0b 43 54 54 56 74 33 91' - } - ), - # Page 10 - ( - '1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a', - { - 0: 'dd 5b cb 00 18 e9 22 d4 94 75 9d 7c 39 5d 02 d3', - 16: 'c8 44 6f 8f 77 ab f7 37 68 53 53 eb 89 a1 c9 eb', - 240: 'af 3e 30 f9 c0 95 04 59 38 15 15 75 c3 fb 90 98', - 256: 'f8 cb 62 74 db 99 b8 0b 1d 20 12 a9 8e d4 8f 0e', - 496: '25 c3 00 5a 1c b8 5d e0 76 25 98 39 ab 71 98 ab', - 512: '9d cb c1 83 e8 cb 99 4b 72 7b 75 be 31 80 76 9c', - 752: 'a1 d3 07 8d fa 91 69 50 3e d9 d4 49 1d ee 4e b2', - 768: '85 14 a5 49 58 58 09 6f 59 6e 4b cd 66 b1 06 65', - 1008: '5f 40 d5 9e c1 b0 3b 33 73 8e fa 60 b2 25 5d 31', - 1024: '34 77 c7 f7 64 a4 1b ac ef f9 0b f1 4f 92 b7 cc', - 1520: 'ac 4e 95 36 8d 99 b9 eb 78 b8 da 8f 81 ff a7 95', - 1536: '8c 3c 13 f8 c2 38 8b b7 3f 38 57 6e 65 b7 c4 46', - 2032: '13 c4 b9 c1 df b6 65 79 ed dd 8a 28 0b 9f 73 16', - 2048: 'dd d2 78 20 55 01 26 69 8e fa ad c6 4b 64 f6 6e', - 3056: 'f0 8f 2e 66 d2 8e d1 43 f3 a2 37 cf 9d e7 35 59', - 3072: '9e a3 6c 52 55 31 b8 80 ba 12 43 34 f5 7b 0b 70', - 4080: 'd5 a3 9e 3d fc c5 02 80 ba c4 a6 b5 aa 0d ca 7d', - 4096: '37 0b 1c 1f e6 55 91 6d 97 fd 0d 47 ca 1d 72 b8' - } - ) - ] + # Test vectors from RFC 6229. Each test vector is a tuple with two items: + # the ARC4 key and a dictionary. The dictionary has keystream offsets as keys + # and the 16-byte keystream starting at the relevant offset as value. + rfc6229_data = [ + # Page 3 + ( + "0102030405", + { + 0: "b2 39 63 05 f0 3d c0 27 cc c3 52 4a 0a 11 18 a8", + 16: "69 82 94 4f 18 fc 82 d5 89 c4 03 a4 7a 0d 09 19", + 240: "28 cb 11 32 c9 6c e2 86 42 1d ca ad b8 b6 9e ae", + 256: "1c fc f6 2b 03 ed db 64 1d 77 df cf 7f 8d 8c 93", + 496: "42 b7 d0 cd d9 18 a8 a3 3d d5 17 81 c8 1f 40 41", + 512: "64 59 84 44 32 a7 da 92 3c fb 3e b4 98 06 61 f6", + 752: "ec 10 32 7b de 2b ee fd 18 f9 27 76 80 45 7e 22", + 768: "eb 62 63 8d 4f 0b a1 fe 9f ca 20 e0 5b f8 ff 2b", + 1008: "45 12 90 48 e6 a0 ed 0b 56 b4 90 33 8f 07 8d a5", + 1024: "30 ab bc c7 c2 0b 01 60 9f 23 ee 2d 5f 6b b7 df", + 1520: "32 94 f7 44 d8 f9 79 05 07 e7 0f 62 e5 bb ce ea", + 1536: "d8 72 9d b4 18 82 25 9b ee 4f 82 53 25 f5 a1 30", + 2032: "1e b1 4a 0c 13 b3 bf 47 fa 2a 0b a9 3a d4 5b 8b", + 2048: "cc 58 2f 8b a9 f2 65 e2 b1 be 91 12 e9 75 d2 d7", + 3056: "f2 e3 0f 9b d1 02 ec bf 75 aa ad e9 bc 35 c4 3c", + 3072: "ec 0e 11 c4 79 dc 32 9d c8 da 79 68 fe 96 56 81", + 4080: "06 83 26 a2 11 84 16 d2 1f 9d 04 b2 cd 1c a0 50", + 4096: "ff 25 b5 89 95 99 67 07 e5 1f bd f0 8b 34 d8 75", + }, + ), + # Page 4 + ( + "01020304050607", + { + 0: "29 3f 02 d4 7f 37 c9 b6 33 f2 af 52 85 fe b4 6b", + 16: "e6 20 f1 39 0d 19 bd 84 e2 e0 fd 75 20 31 af c1", + 240: "91 4f 02 53 1c 92 18 81 0d f6 0f 67 e3 38 15 4c", + 256: "d0 fd b5 83 07 3c e8 5a b8 39 17 74 0e c0 11 d5", + 496: "75 f8 14 11 e8 71 cf fa 70 b9 0c 74 c5 92 e4 54", + 512: "0b b8 72 02 93 8d ad 60 9e 87 a5 a1 b0 79 e5 e4", + 752: "c2 91 12 46 b6 12 e7 e7 b9 03 df ed a1 da d8 66", + 768: "32 82 8f 91 50 2b 62 91 36 8d e8 08 1d e3 6f c2", + 1008: "f3 b9 a7 e3 b2 97 bf 9a d8 04 51 2f 90 63 ef f1", + 1024: "8e cb 67 a9 ba 1f 55 a5 a0 67 e2 b0 26 a3 67 6f", + 1520: "d2 aa 90 2b d4 2d 0d 7c fd 34 0c d4 58 10 52 9f", + 1536: "78 b2 72 c9 6e 42 ea b4 c6 0b d9 14 e3 9d 06 e3", + 2032: "f4 33 2f d3 1a 07 93 96 ee 3c ee 3f 2a 4f f0 49", + 2048: "05 45 97 81 d4 1f da 7f 30 c1 be 7e 12 46 c6 23", + 3056: "ad fd 38 68 b8 e5 14 85 d5 e6 10 01 7e 3d d6 09", + 3072: "ad 26 58 1c 0c 5b e4 5f 4c ea 01 db 2f 38 05 d5", + 4080: "f3 17 2c ef fc 3b 3d 99 7c 85 cc d5 af 1a 95 0c", + 4096: "e7 4b 0b 97 31 22 7f d3 7c 0e c0 8a 47 dd d8 b8", + }, + ), + ( + "0102030405060708", + { + 0: "97 ab 8a 1b f0 af b9 61 32 f2 f6 72 58 da 15 a8", + 16: "82 63 ef db 45 c4 a1 86 84 ef 87 e6 b1 9e 5b 09", + 240: "96 36 eb c9 84 19 26 f4 f7 d1 f3 62 bd df 6e 18", + 256: "d0 a9 90 ff 2c 05 fe f5 b9 03 73 c9 ff 4b 87 0a", + 496: "73 23 9f 1d b7 f4 1d 80 b6 43 c0 c5 25 18 ec 63", + 512: "16 3b 31 99 23 a6 bd b4 52 7c 62 61 26 70 3c 0f", + 752: "49 d6 c8 af 0f 97 14 4a 87 df 21 d9 14 72 f9 66", + 768: "44 17 3a 10 3b 66 16 c5 d5 ad 1c ee 40 c8 63 d0", + 1008: "27 3c 9c 4b 27 f3 22 e4 e7 16 ef 53 a4 7d e7 a4", + 1024: "c6 d0 e7 b2 26 25 9f a9 02 34 90 b2 61 67 ad 1d", + 1520: "1f e8 98 67 13 f0 7c 3d 9a e1 c1 63 ff 8c f9 d3", + 1536: "83 69 e1 a9 65 61 0b e8 87 fb d0 c7 91 62 aa fb", + 2032: "0a 01 27 ab b4 44 84 b9 fb ef 5a bc ae 1b 57 9f", + 2048: "c2 cd ad c6 40 2e 8e e8 66 e1 f3 7b db 47 e4 2c", + 3056: "26 b5 1e a3 7d f8 e1 d6 f7 6f c3 b6 6a 74 29 b3", + 3072: "bc 76 83 20 5d 4f 44 3d c1 f2 9d da 33 15 c8 7b", + 4080: "d5 fa 5a 34 69 d2 9a aa f8 3d 23 58 9d b8 c8 5b", + 4096: "3f b4 6e 2c 8f 0f 06 8e dc e8 cd cd 7d fc 58 62", + }, + ), + # Page 5 + ( + "0102030405060708090a", + { + 0: "ed e3 b0 46 43 e5 86 cc 90 7d c2 18 51 70 99 02", + 16: "03 51 6b a7 8f 41 3b eb 22 3a a5 d4 d2 df 67 11", + 240: "3c fd 6c b5 8e e0 fd de 64 01 76 ad 00 00 04 4d", + 256: "48 53 2b 21 fb 60 79 c9 11 4c 0f fd 9c 04 a1 ad", + 496: "3e 8c ea 98 01 71 09 97 90 84 b1 ef 92 f9 9d 86", + 512: "e2 0f b4 9b db 33 7e e4 8b 8d 8d c0 f4 af ef fe", + 752: "5c 25 21 ea cd 79 66 f1 5e 05 65 44 be a0 d3 15", + 768: "e0 67 a7 03 19 31 a2 46 a6 c3 87 5d 2f 67 8a cb", + 1008: "a6 4f 70 af 88 ae 56 b6 f8 75 81 c0 e2 3e 6b 08", + 1024: "f4 49 03 1d e3 12 81 4e c6 f3 19 29 1f 4a 05 16", + 1520: "bd ae 85 92 4b 3c b1 d0 a2 e3 3a 30 c6 d7 95 99", + 1536: "8a 0f ed db ac 86 5a 09 bc d1 27 fb 56 2e d6 0a", + 2032: "b5 5a 0a 5b 51 a1 2a 8b e3 48 99 c3 e0 47 51 1a", + 2048: "d9 a0 9c ea 3c e7 5f e3 96 98 07 03 17 a7 13 39", + 3056: "55 22 25 ed 11 77 f4 45 84 ac 8c fa 6c 4e b5 fc", + 3072: "7e 82 cb ab fc 95 38 1b 08 09 98 44 21 29 c2 f8", + 4080: "1f 13 5e d1 4c e6 0a 91 36 9d 23 22 be f2 5e 3c", + 4096: "08 b6 be 45 12 4a 43 e2 eb 77 95 3f 84 dc 85 53", + }, + ), + ( + "0102030405060708090a0b0c0d0e0f10", + { + 0: "9a c7 cc 9a 60 9d 1e f7 b2 93 28 99 cd e4 1b 97", + 16: "52 48 c4 95 90 14 12 6a 6e 8a 84 f1 1d 1a 9e 1c", + 240: "06 59 02 e4 b6 20 f6 cc 36 c8 58 9f 66 43 2f 2b", + 256: "d3 9d 56 6b c6 bc e3 01 07 68 15 15 49 f3 87 3f", + 496: "b6 d1 e6 c4 a5 e4 77 1c ad 79 53 8d f2 95 fb 11", + 512: "c6 8c 1d 5c 55 9a 97 41 23 df 1d bc 52 a4 3b 89", + 752: "c5 ec f8 8d e8 97 fd 57 fe d3 01 70 1b 82 a2 59", + 768: "ec cb e1 3d e1 fc c9 1c 11 a0 b2 6c 0b c8 fa 4d", + 1008: "e7 a7 25 74 f8 78 2a e2 6a ab cf 9e bc d6 60 65", + 1024: "bd f0 32 4e 60 83 dc c6 d3 ce dd 3c a8 c5 3c 16", + 1520: "b4 01 10 c4 19 0b 56 22 a9 61 16 b0 01 7e d2 97", + 1536: "ff a0 b5 14 64 7e c0 4f 63 06 b8 92 ae 66 11 81", + 2032: "d0 3d 1b c0 3c d3 3d 70 df f9 fa 5d 71 96 3e bd", + 2048: "8a 44 12 64 11 ea a7 8b d5 1e 8d 87 a8 87 9b f5", + 3056: "fa be b7 60 28 ad e2 d0 e4 87 22 e4 6c 46 15 a3", + 3072: "c0 5d 88 ab d5 03 57 f9 35 a6 3c 59 ee 53 76 23", + 4080: "ff 38 26 5c 16 42 c1 ab e8 d3 c2 fe 5e 57 2b f8", + 4096: "a3 6a 4c 30 1a e8 ac 13 61 0c cb c1 22 56 ca cc", + }, + ), + # Page 6 + ( + "0102030405060708090a0b0c0d0e0f101112131415161718", + { + 0: "05 95 e5 7f e5 f0 bb 3c 70 6e da c8 a4 b2 db 11", + 16: "df de 31 34 4a 1a f7 69 c7 4f 07 0a ee 9e 23 26", + 240: "b0 6b 9b 1e 19 5d 13 d8 f4 a7 99 5c 45 53 ac 05", + 256: "6b d2 37 8e c3 41 c9 a4 2f 37 ba 79 f8 8a 32 ff", + 496: "e7 0b ce 1d f7 64 5a db 5d 2c 41 30 21 5c 35 22", + 512: "9a 57 30 c7 fc b4 c9 af 51 ff da 89 c7 f1 ad 22", + 752: "04 85 05 5f d4 f6 f0 d9 63 ef 5a b9 a5 47 69 82", + 768: "59 1f c6 6b cd a1 0e 45 2b 03 d4 55 1f 6b 62 ac", + 1008: "27 53 cc 83 98 8a fa 3e 16 88 a1 d3 b4 2c 9a 02", + 1024: "93 61 0d 52 3d 1d 3f 00 62 b3 c2 a3 bb c7 c7 f0", + 1520: "96 c2 48 61 0a ad ed fe af 89 78 c0 3d e8 20 5a", + 1536: "0e 31 7b 3d 1c 73 b9 e9 a4 68 8f 29 6d 13 3a 19", + 2032: "bd f0 e6 c3 cc a5 b5 b9 d5 33 b6 9c 56 ad a1 20", + 2048: "88 a2 18 b6 e2 ec e1 e6 24 6d 44 c7 59 d1 9b 10", + 3056: "68 66 39 7e 95 c1 40 53 4f 94 26 34 21 00 6e 40", + 3072: "32 cb 0a 1e 95 42 c6 b3 b8 b3 98 ab c3 b0 f1 d5", + 4080: "29 a0 b8 ae d5 4a 13 23 24 c6 2e 42 3f 54 b4 c8", + 4096: "3c b0 f3 b5 02 0a 98 b8 2a f9 fe 15 44 84 a1 68", + }, + ), + ( + "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + { + 0: "ea a6 bd 25 88 0b f9 3d 3f 5d 1e 4c a2 61 1d 91", + 16: "cf a4 5c 9f 7e 71 4b 54 bd fa 80 02 7c b1 43 80", + 240: "11 4a e3 44 de d7 1b 35 f2 e6 0f eb ad 72 7f d8", + 256: "02 e1 e7 05 6b 0f 62 39 00 49 64 22 94 3e 97 b6", + 496: "91 cb 93 c7 87 96 4e 10 d9 52 7d 99 9c 6f 93 6b", + 512: "49 b1 8b 42 f8 e8 36 7c be b5 ef 10 4b a1 c7 cd", + 752: "87 08 4b 3b a7 00 ba de 95 56 10 67 27 45 b3 74", + 768: "e7 a7 b9 e9 ec 54 0d 5f f4 3b db 12 79 2d 1b 35", + 1008: "c7 99 b5 96 73 8f 6b 01 8c 76 c7 4b 17 59 bd 90", + 1024: "7f ec 5b fd 9f 9b 89 ce 65 48 30 90 92 d7 e9 58", + 1520: "40 f2 50 b2 6d 1f 09 6a 4a fd 4c 34 0a 58 88 15", + 1536: "3e 34 13 5c 79 db 01 02 00 76 76 51 cf 26 30 73", + 2032: "f6 56 ab cc f8 8d d8 27 02 7b 2c e9 17 d4 64 ec", + 2048: "18 b6 25 03 bf bc 07 7f ba bb 98 f2 0d 98 ab 34", + 3056: "8a ed 95 ee 5b 0d cb fb ef 4e b2 1d 3a 3f 52 f9", + 3072: "62 5a 1a b0 0e e3 9a 53 27 34 6b dd b0 1a 9c 18", + 4080: "a1 3a 7c 79 c7 e1 19 b5 ab 02 96 ab 28 c3 00 b9", + 4096: "f3 e4 c0 a2 e0 2d 1d 01 f7 f0 a7 46 18 af 2b 48", + }, + ), + # Page 7 + ( + "833222772a", + { + 0: "80 ad 97 bd c9 73 df 8a 2e 87 9e 92 a4 97 ef da", + 16: "20 f0 60 c2 f2 e5 12 65 01 d3 d4 fe a1 0d 5f c0", + 240: "fa a1 48 e9 90 46 18 1f ec 6b 20 85 f3 b2 0e d9", + 256: "f0 da f5 ba b3 d5 96 83 98 57 84 6f 73 fb fe 5a", + 496: "1c 7e 2f c4 63 92 32 fe 29 75 84 b2 96 99 6b c8", + 512: "3d b9 b2 49 40 6c c8 ed ff ac 55 cc d3 22 ba 12", + 752: "e4 f9 f7 e0 06 61 54 bb d1 25 b7 45 56 9b c8 97", + 768: "75 d5 ef 26 2b 44 c4 1a 9c f6 3a e1 45 68 e1 b9", + 1008: "6d a4 53 db f8 1e 82 33 4a 3d 88 66 cb 50 a1 e3", + 1024: "78 28 d0 74 11 9c ab 5c 22 b2 94 d7 a9 bf a0 bb", + 1520: "ad b8 9c ea 9a 15 fb e6 17 29 5b d0 4b 8c a0 5c", + 1536: "62 51 d8 7f d4 aa ae 9a 7e 4a d5 c2 17 d3 f3 00", + 2032: "e7 11 9b d6 dd 9b 22 af e8 f8 95 85 43 28 81 e2", + 2048: "78 5b 60 fd 7e c4 e9 fc b6 54 5f 35 0d 66 0f ab", + 3056: "af ec c0 37 fd b7 b0 83 8e b3 d7 0b cd 26 83 82", + 3072: "db c1 a7 b4 9d 57 35 8c c9 fa 6d 61 d7 3b 7c f0", + 4080: "63 49 d1 26 a3 7a fc ba 89 79 4f 98 04 91 4f dc", + 4096: "bf 42 c3 01 8c 2f 7c 66 bf de 52 49 75 76 81 15", + }, + ), + ( + "1910833222772a", + { + 0: "bc 92 22 db d3 27 4d 8f c6 6d 14 cc bd a6 69 0b", + 16: "7a e6 27 41 0c 9a 2b e6 93 df 5b b7 48 5a 63 e3", + 240: "3f 09 31 aa 03 de fb 30 0f 06 01 03 82 6f 2a 64", + 256: "be aa 9e c8 d5 9b b6 81 29 f3 02 7c 96 36 11 81", + 496: "74 e0 4d b4 6d 28 64 8d 7d ee 8a 00 64 b0 6c fe", + 512: "9b 5e 81 c6 2f e0 23 c5 5b e4 2f 87 bb f9 32 b8", + 752: "ce 17 8f c1 82 6e fe cb c1 82 f5 79 99 a4 61 40", + 768: "8b df 55 cd 55 06 1c 06 db a6 be 11 de 4a 57 8a", + 1008: "62 6f 5f 4d ce 65 25 01 f3 08 7d 39 c9 2c c3 49", + 1024: "42 da ac 6a 8f 9a b9 a7 fd 13 7c 60 37 82 56 82", + 1520: "cc 03 fd b7 91 92 a2 07 31 2f 53 f5 d4 dc 33 d9", + 1536: "f7 0f 14 12 2a 1c 98 a3 15 5d 28 b8 a0 a8 a4 1d", + 2032: "2a 3a 30 7a b2 70 8a 9c 00 fe 0b 42 f9 c2 d6 a1", + 2048: "86 26 17 62 7d 22 61 ea b0 b1 24 65 97 ca 0a e9", + 3056: "55 f8 77 ce 4f 2e 1d db bf 8e 13 e2 cd e0 fd c8", + 3072: "1b 15 56 cb 93 5f 17 33 37 70 5f bb 5d 50 1f c1", + 4080: "ec d0 e9 66 02 be 7f 8d 50 92 81 6c cc f2 c2 e9", + 4096: "02 78 81 fa b4 99 3a 1c 26 20 24 a9 4f ff 3f 61", + }, + ), + # Page 8 + ( + "641910833222772a", + { + 0: "bb f6 09 de 94 13 17 2d 07 66 0c b6 80 71 69 26", + 16: "46 10 1a 6d ab 43 11 5d 6c 52 2b 4f e9 36 04 a9", + 240: "cb e1 ff f2 1c 96 f3 ee f6 1e 8f e0 54 2c bd f0", + 256: "34 79 38 bf fa 40 09 c5 12 cf b4 03 4b 0d d1 a7", + 496: "78 67 a7 86 d0 0a 71 47 90 4d 76 dd f1 e5 20 e3", + 512: "8d 3e 9e 1c ae fc cc b3 fb f8 d1 8f 64 12 0b 32", + 752: "94 23 37 f8 fd 76 f0 fa e8 c5 2d 79 54 81 06 72", + 768: "b8 54 8c 10 f5 16 67 f6 e6 0e 18 2f a1 9b 30 f7", + 1008: "02 11 c7 c6 19 0c 9e fd 12 37 c3 4c 8f 2e 06 c4", + 1024: "bd a6 4f 65 27 6d 2a ac b8 f9 02 12 20 3a 80 8e", + 1520: "bd 38 20 f7 32 ff b5 3e c1 93 e7 9d 33 e2 7c 73", + 1536: "d0 16 86 16 86 19 07 d4 82 e3 6c da c8 cf 57 49", + 2032: "97 b0 f0 f2 24 b2 d2 31 71 14 80 8f b0 3a f7 a0", + 2048: "e5 96 16 e4 69 78 79 39 a0 63 ce ea 9a f9 56 d1", + 3056: "c4 7e 0d c1 66 09 19 c1 11 01 20 8f 9e 69 aa 1f", + 3072: "5a e4 f1 28 96 b8 37 9a 2a ad 89 b5 b5 53 d6 b0", + 4080: "6b 6b 09 8d 0c 29 3b c2 99 3d 80 bf 05 18 b6 d9", + 4096: "81 70 cc 3c cd 92 a6 98 62 1b 93 9d d3 8f e7 b9", + }, + ), + ( + "8b37641910833222772a", + { + 0: "ab 65 c2 6e dd b2 87 60 0d b2 fd a1 0d 1e 60 5c", + 16: "bb 75 90 10 c2 96 58 f2 c7 2d 93 a2 d1 6d 29 30", + 240: "b9 01 e8 03 6e d1 c3 83 cd 3c 4c 4d d0 a6 ab 05", + 256: "3d 25 ce 49 22 92 4c 55 f0 64 94 33 53 d7 8a 6c", + 496: "12 c1 aa 44 bb f8 7e 75 e6 11 f6 9b 2c 38 f4 9b", + 512: "28 f2 b3 43 4b 65 c0 98 77 47 00 44 c6 ea 17 0d", + 752: "bd 9e f8 22 de 52 88 19 61 34 cf 8a f7 83 93 04", + 768: "67 55 9c 23 f0 52 15 84 70 a2 96 f7 25 73 5a 32", + 1008: "8b ab 26 fb c2 c1 2b 0f 13 e2 ab 18 5e ab f2 41", + 1024: "31 18 5a 6d 69 6f 0c fa 9b 42 80 8b 38 e1 32 a2", + 1520: "56 4d 3d ae 18 3c 52 34 c8 af 1e 51 06 1c 44 b5", + 1536: "3c 07 78 a7 b5 f7 2d 3c 23 a3 13 5c 7d 67 b9 f4", + 2032: "f3 43 69 89 0f cf 16 fb 51 7d ca ae 44 63 b2 dd", + 2048: "02 f3 1c 81 e8 20 07 31 b8 99 b0 28 e7 91 bf a7", + 3056: "72 da 64 62 83 22 8c 14 30 08 53 70 17 95 61 6f", + 3072: "4e 0a 8c 6f 79 34 a7 88 e2 26 5e 81 d6 d0 c8 f4", + 4080: "43 8d d5 ea fe a0 11 1b 6f 36 b4 b9 38 da 2a 68", + 4096: "5f 6b fc 73 81 58 74 d9 71 00 f0 86 97 93 57 d8", + }, + ), + # Page 9 + ( + "ebb46227c6cc8b37641910833222772a", + { + 0: "72 0c 94 b6 3e df 44 e1 31 d9 50 ca 21 1a 5a 30", + 16: "c3 66 fd ea cf 9c a8 04 36 be 7c 35 84 24 d2 0b", + 240: "b3 39 4a 40 aa bf 75 cb a4 22 82 ef 25 a0 05 9f", + 256: "48 47 d8 1d a4 94 2d bc 24 9d ef c4 8c 92 2b 9f", + 496: "08 12 8c 46 9f 27 53 42 ad da 20 2b 2b 58 da 95", + 512: "97 0d ac ef 40 ad 98 72 3b ac 5d 69 55 b8 17 61", + 752: "3c b8 99 93 b0 7b 0c ed 93 de 13 d2 a1 10 13 ac", + 768: "ef 2d 67 6f 15 45 c2 c1 3d c6 80 a0 2f 4a db fe", + 1008: "b6 05 95 51 4f 24 bc 9f e5 22 a6 ca d7 39 36 44", + 1024: "b5 15 a8 c5 01 17 54 f5 90 03 05 8b db 81 51 4e", + 1520: "3c 70 04 7e 8c bc 03 8e 3b 98 20 db 60 1d a4 95", + 1536: "11 75 da 6e e7 56 de 46 a5 3e 2b 07 56 60 b7 70", + 2032: "00 a5 42 bb a0 21 11 cc 2c 65 b3 8e bd ba 58 7e", + 2048: "58 65 fd bb 5b 48 06 41 04 e8 30 b3 80 f2 ae de", + 3056: "34 b2 1a d2 ad 44 e9 99 db 2d 7f 08 63 f0 d9 b6", + 3072: "84 a9 21 8f c3 6e 8a 5f 2c cf be ae 53 a2 7d 25", + 4080: "a2 22 1a 11 b8 33 cc b4 98 a5 95 40 f0 54 5f 4a", + 4096: "5b be b4 78 7d 59 e5 37 3f db ea 6c 6f 75 c2 9b", + }, + ), + ( + "c109163908ebe51debb46227c6cc8b37641910833222772a", + { + 0: "54 b6 4e 6b 5a 20 b5 e2 ec 84 59 3d c7 98 9d a7", + 16: "c1 35 ee e2 37 a8 54 65 ff 97 dc 03 92 4f 45 ce", + 240: "cf cc 92 2f b4 a1 4a b4 5d 61 75 aa bb f2 d2 01", + 256: "83 7b 87 e2 a4 46 ad 0e f7 98 ac d0 2b 94 12 4f", + 496: "17 a6 db d6 64 92 6a 06 36 b3 f4 c3 7a 4f 46 94", + 512: "4a 5f 9f 26 ae ee d4 d4 a2 5f 63 2d 30 52 33 d9", + 752: "80 a3 d0 1e f0 0c 8e 9a 42 09 c1 7f 4e eb 35 8c", + 768: "d1 5e 7d 5f fa aa bc 02 07 bf 20 0a 11 77 93 a2", + 1008: "34 96 82 bf 58 8e aa 52 d0 aa 15 60 34 6a ea fa", + 1024: "f5 85 4c db 76 c8 89 e3 ad 63 35 4e 5f 72 75 e3", + 1520: "53 2c 7c ec cb 39 df 32 36 31 84 05 a4 b1 27 9c", + 1536: "ba ef e6 d9 ce b6 51 84 22 60 e0 d1 e0 5e 3b 90", + 2032: "e8 2d 8c 6d b5 4e 3c 63 3f 58 1c 95 2b a0 42 07", + 2048: "4b 16 e5 0a bd 38 1b d7 09 00 a9 cd 9a 62 cb 23", + 3056: "36 82 ee 33 bd 14 8b d9 f5 86 56 cd 8f 30 d9 fb", + 3072: "1e 5a 0b 84 75 04 5d 9b 20 b2 62 86 24 ed fd 9e", + 4080: "63 ed d6 84 fb 82 62 82 fe 52 8f 9c 0e 92 37 bc", + 4096: "e4 dd 2e 98 d6 96 0f ae 0b 43 54 54 56 74 33 91", + }, + ), + # Page 10 + ( + "1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a", + { + 0: "dd 5b cb 00 18 e9 22 d4 94 75 9d 7c 39 5d 02 d3", + 16: "c8 44 6f 8f 77 ab f7 37 68 53 53 eb 89 a1 c9 eb", + 240: "af 3e 30 f9 c0 95 04 59 38 15 15 75 c3 fb 90 98", + 256: "f8 cb 62 74 db 99 b8 0b 1d 20 12 a9 8e d4 8f 0e", + 496: "25 c3 00 5a 1c b8 5d e0 76 25 98 39 ab 71 98 ab", + 512: "9d cb c1 83 e8 cb 99 4b 72 7b 75 be 31 80 76 9c", + 752: "a1 d3 07 8d fa 91 69 50 3e d9 d4 49 1d ee 4e b2", + 768: "85 14 a5 49 58 58 09 6f 59 6e 4b cd 66 b1 06 65", + 1008: "5f 40 d5 9e c1 b0 3b 33 73 8e fa 60 b2 25 5d 31", + 1024: "34 77 c7 f7 64 a4 1b ac ef f9 0b f1 4f 92 b7 cc", + 1520: "ac 4e 95 36 8d 99 b9 eb 78 b8 da 8f 81 ff a7 95", + 1536: "8c 3c 13 f8 c2 38 8b b7 3f 38 57 6e 65 b7 c4 46", + 2032: "13 c4 b9 c1 df b6 65 79 ed dd 8a 28 0b 9f 73 16", + 2048: "dd d2 78 20 55 01 26 69 8e fa ad c6 4b 64 f6 6e", + 3056: "f0 8f 2e 66 d2 8e d1 43 f3 a2 37 cf 9d e7 35 59", + 3072: "9e a3 6c 52 55 31 b8 80 ba 12 43 34 f5 7b 0b 70", + 4080: "d5 a3 9e 3d fc c5 02 80 ba c4 a6 b5 aa 0d ca 7d", + 4096: "37 0b 1c 1f e6 55 91 6d 97 fd 0d 47 ca 1d 72 b8", + }, + ), + ] - def test_keystream(self): - for tv in self.rfc6229_data: - key = unhexlify(b((tv[0]))) - cipher = ARC4.new(key) - count = 0 - for offset in range(0, 4096+1, 16): - ct = cipher.encrypt(b('\x00')*16) - expected = tv[1].get(offset) - if expected: - expected = unhexlify(b(expected.replace(" ", ''))) - self.assertEqual(ct, expected) - count += 1 - self.assertEqual(count, len(tv[1])) + def test_keystream(self): + for tv in self.rfc6229_data: + key = unhexlify(b((tv[0]))) + cipher = ARC4.new(key) + count = 0 + for offset in range(0, 4096 + 1, 16): + ct = cipher.encrypt(b("\x00") * 16) + expected = tv[1].get(offset) + if expected: + expected = unhexlify(b(expected.replace(" ", ""))) + self.assertEqual(ct, expected) + count += 1 + self.assertEqual(count, len(tv[1])) class Drop_Tests(unittest.TestCase): - key = b('\xAA')*16 - data = b('\x00')*5000 + key = b("\xaa") * 16 + data = b("\x00") * 5000 - def setUp(self): - self.cipher = ARC4.new(self.key) + def setUp(self): + self.cipher = ARC4.new(self.key) - def test_drop256_encrypt(self): - cipher_drop = ARC4.new(self.key, 256) - ct_drop = cipher_drop.encrypt(self.data[:16]) - ct = self.cipher.encrypt(self.data)[256:256+16] - self.assertEqual(ct_drop, ct) + def test_drop256_encrypt(self): + cipher_drop = ARC4.new(self.key, 256) + ct_drop = cipher_drop.encrypt(self.data[:16]) + ct = self.cipher.encrypt(self.data)[256 : 256 + 16] + self.assertEqual(ct_drop, ct) - def test_drop256_decrypt(self): - cipher_drop = ARC4.new(self.key, 256) - pt_drop = cipher_drop.decrypt(self.data[:16]) - pt = self.cipher.decrypt(self.data)[256:256+16] - self.assertEqual(pt_drop, pt) + def test_drop256_decrypt(self): + cipher_drop = ARC4.new(self.key, 256) + pt_drop = cipher_drop.decrypt(self.data[:16]) + pt = self.cipher.decrypt(self.data)[256 : 256 + 16] + self.assertEqual(pt_drop, pt) class KeyLength(unittest.TestCase): - - def runTest(self): - self.assertRaises(ValueError, ARC4.new, b'') - self.assertRaises(ValueError, ARC4.new, b'\x00' * 257) + def runTest(self): + self.assertRaises(ValueError, ARC4.new, b"") + self.assertRaises(ValueError, ARC4.new, b"\x00" * 257) def get_tests(config={}): - from .common import make_stream_tests - tests = make_stream_tests(ARC4, "ARC4", test_data) - tests += list_test_cases(RFC6229_Tests) - tests += list_test_cases(Drop_Tests) - tests.append(KeyLength()) - return tests + from .common import make_stream_tests + + tests = make_stream_tests(ARC4, "ARC4", test_data) + tests += list_test_cases(RFC6229_Tests) + tests += list_test_cases(Drop_Tests) + tests.append(KeyLength()) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_Blowfish.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_Blowfish.py index ca5c6033..93efc56b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_Blowfish.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_Blowfish.py @@ -32,129 +32,164 @@ # This is a list of (plaintext, ciphertext, key) tuples. test_data = [ - # Test vectors from http://www.schneier.com/code/vectors.txt - ('0000000000000000', '4ef997456198dd78', '0000000000000000'), - ('ffffffffffffffff', '51866fd5b85ecb8a', 'ffffffffffffffff'), - ('1000000000000001', '7d856f9a613063f2', '3000000000000000'), - ('1111111111111111', '2466dd878b963c9d', '1111111111111111'), - ('1111111111111111', '61f9c3802281b096', '0123456789abcdef'), - ('0123456789abcdef', '7d0cc630afda1ec7', '1111111111111111'), - ('0000000000000000', '4ef997456198dd78', '0000000000000000'), - ('0123456789abcdef', '0aceab0fc6a0a28d', 'fedcba9876543210'), - ('01a1d6d039776742', '59c68245eb05282b', '7ca110454a1a6e57'), - ('5cd54ca83def57da', 'b1b8cc0b250f09a0', '0131d9619dc1376e'), - ('0248d43806f67172', '1730e5778bea1da4', '07a1133e4a0b2686'), - ('51454b582ddf440a', 'a25e7856cf2651eb', '3849674c2602319e'), - ('42fd443059577fa2', '353882b109ce8f1a', '04b915ba43feb5b6'), - ('059b5e0851cf143a', '48f4d0884c379918', '0113b970fd34f2ce'), - ('0756d8e0774761d2', '432193b78951fc98', '0170f175468fb5e6'), - ('762514b829bf486a', '13f04154d69d1ae5', '43297fad38e373fe'), - ('3bdd119049372802', '2eedda93ffd39c79', '07a7137045da2a16'), - ('26955f6835af609a', 'd887e0393c2da6e3', '04689104c2fd3b2f'), - ('164d5e404f275232', '5f99d04f5b163969', '37d06bb516cb7546'), - ('6b056e18759f5cca', '4a057a3b24d3977b', '1f08260d1ac2465e'), - ('004bd6ef09176062', '452031c1e4fada8e', '584023641aba6176'), - ('480d39006ee762f2', '7555ae39f59b87bd', '025816164629b007'), - ('437540c8698f3cfa', '53c55f9cb49fc019', '49793ebc79b3258f'), - ('072d43a077075292', '7a8e7bfa937e89a3', '4fb05e1515ab73a7'), - ('02fe55778117f12a', 'cf9c5d7a4986adb5', '49e95d6d4ca229bf'), - ('1d9d5c5018f728c2', 'd1abb290658bc778', '018310dc409b26d6'), - ('305532286d6f295a', '55cb3774d13ef201', '1c587f1c13924fef'), - ('0123456789abcdef', 'fa34ec4847b268b2', '0101010101010101'), - ('0123456789abcdef', 'a790795108ea3cae', '1f1f1f1f0e0e0e0e'), - ('0123456789abcdef', 'c39e072d9fac631d', 'e0fee0fef1fef1fe'), - ('ffffffffffffffff', '014933e0cdaff6e4', '0000000000000000'), - ('0000000000000000', 'f21e9a77b71c49bc', 'ffffffffffffffff'), - ('0000000000000000', '245946885754369a', '0123456789abcdef'), - ('ffffffffffffffff', '6b5c5a9c5d9e0a5a', 'fedcba9876543210'), - #('fedcba9876543210', 'f9ad597c49db005e', 'f0'), - #('fedcba9876543210', 'e91d21c1d961a6d6', 'f0e1'), - #('fedcba9876543210', 'e9c2b70a1bc65cf3', 'f0e1d2'), - ('fedcba9876543210', 'be1e639408640f05', 'f0e1d2c3'), - ('fedcba9876543210', 'b39e44481bdb1e6e', 'f0e1d2c3b4'), - ('fedcba9876543210', '9457aa83b1928c0d', 'f0e1d2c3b4a5'), - ('fedcba9876543210', '8bb77032f960629d', 'f0e1d2c3b4a596'), - ('fedcba9876543210', 'e87a244e2cc85e82', 'f0e1d2c3b4a59687'), - ('fedcba9876543210', '15750e7a4f4ec577', 'f0e1d2c3b4a5968778'), - ('fedcba9876543210', '122ba70b3ab64ae0', 'f0e1d2c3b4a596877869'), - ('fedcba9876543210', '3a833c9affc537f6', 'f0e1d2c3b4a5968778695a'), - ('fedcba9876543210', '9409da87a90f6bf2', 'f0e1d2c3b4a5968778695a4b'), - ('fedcba9876543210', '884f80625060b8b4', 'f0e1d2c3b4a5968778695a4b3c'), - ('fedcba9876543210', '1f85031c19e11968', 'f0e1d2c3b4a5968778695a4b3c2d'), - ('fedcba9876543210', '79d9373a714ca34f', 'f0e1d2c3b4a5968778695a4b3c2d1e'), - ('fedcba9876543210', '93142887ee3be15c', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f'), - ('fedcba9876543210', '03429e838ce2d14b', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f00'), - ('fedcba9876543210', 'a4299e27469ff67b', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f0011'), - ('fedcba9876543210', 'afd5aed1c1bc96a8', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f001122'), - ('fedcba9876543210', '10851c0e3858da9f', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233'), - ('fedcba9876543210', 'e6f51ed79b9db21f', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344'), - ('fedcba9876543210', '64a6e14afd36b46f', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455'), - ('fedcba9876543210', '80c7d7d45a5479ad', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566'), - ('fedcba9876543210', '05044b62fa52d080', - 'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677'), + # Test vectors from http://www.schneier.com/code/vectors.txt + ("0000000000000000", "4ef997456198dd78", "0000000000000000"), + ("ffffffffffffffff", "51866fd5b85ecb8a", "ffffffffffffffff"), + ("1000000000000001", "7d856f9a613063f2", "3000000000000000"), + ("1111111111111111", "2466dd878b963c9d", "1111111111111111"), + ("1111111111111111", "61f9c3802281b096", "0123456789abcdef"), + ("0123456789abcdef", "7d0cc630afda1ec7", "1111111111111111"), + ("0000000000000000", "4ef997456198dd78", "0000000000000000"), + ("0123456789abcdef", "0aceab0fc6a0a28d", "fedcba9876543210"), + ("01a1d6d039776742", "59c68245eb05282b", "7ca110454a1a6e57"), + ("5cd54ca83def57da", "b1b8cc0b250f09a0", "0131d9619dc1376e"), + ("0248d43806f67172", "1730e5778bea1da4", "07a1133e4a0b2686"), + ("51454b582ddf440a", "a25e7856cf2651eb", "3849674c2602319e"), + ("42fd443059577fa2", "353882b109ce8f1a", "04b915ba43feb5b6"), + ("059b5e0851cf143a", "48f4d0884c379918", "0113b970fd34f2ce"), + ("0756d8e0774761d2", "432193b78951fc98", "0170f175468fb5e6"), + ("762514b829bf486a", "13f04154d69d1ae5", "43297fad38e373fe"), + ("3bdd119049372802", "2eedda93ffd39c79", "07a7137045da2a16"), + ("26955f6835af609a", "d887e0393c2da6e3", "04689104c2fd3b2f"), + ("164d5e404f275232", "5f99d04f5b163969", "37d06bb516cb7546"), + ("6b056e18759f5cca", "4a057a3b24d3977b", "1f08260d1ac2465e"), + ("004bd6ef09176062", "452031c1e4fada8e", "584023641aba6176"), + ("480d39006ee762f2", "7555ae39f59b87bd", "025816164629b007"), + ("437540c8698f3cfa", "53c55f9cb49fc019", "49793ebc79b3258f"), + ("072d43a077075292", "7a8e7bfa937e89a3", "4fb05e1515ab73a7"), + ("02fe55778117f12a", "cf9c5d7a4986adb5", "49e95d6d4ca229bf"), + ("1d9d5c5018f728c2", "d1abb290658bc778", "018310dc409b26d6"), + ("305532286d6f295a", "55cb3774d13ef201", "1c587f1c13924fef"), + ("0123456789abcdef", "fa34ec4847b268b2", "0101010101010101"), + ("0123456789abcdef", "a790795108ea3cae", "1f1f1f1f0e0e0e0e"), + ("0123456789abcdef", "c39e072d9fac631d", "e0fee0fef1fef1fe"), + ("ffffffffffffffff", "014933e0cdaff6e4", "0000000000000000"), + ("0000000000000000", "f21e9a77b71c49bc", "ffffffffffffffff"), + ("0000000000000000", "245946885754369a", "0123456789abcdef"), + ("ffffffffffffffff", "6b5c5a9c5d9e0a5a", "fedcba9876543210"), + # ('fedcba9876543210', 'f9ad597c49db005e', 'f0'), + # ('fedcba9876543210', 'e91d21c1d961a6d6', 'f0e1'), + # ('fedcba9876543210', 'e9c2b70a1bc65cf3', 'f0e1d2'), + ("fedcba9876543210", "be1e639408640f05", "f0e1d2c3"), + ("fedcba9876543210", "b39e44481bdb1e6e", "f0e1d2c3b4"), + ("fedcba9876543210", "9457aa83b1928c0d", "f0e1d2c3b4a5"), + ("fedcba9876543210", "8bb77032f960629d", "f0e1d2c3b4a596"), + ("fedcba9876543210", "e87a244e2cc85e82", "f0e1d2c3b4a59687"), + ("fedcba9876543210", "15750e7a4f4ec577", "f0e1d2c3b4a5968778"), + ("fedcba9876543210", "122ba70b3ab64ae0", "f0e1d2c3b4a596877869"), + ("fedcba9876543210", "3a833c9affc537f6", "f0e1d2c3b4a5968778695a"), + ("fedcba9876543210", "9409da87a90f6bf2", "f0e1d2c3b4a5968778695a4b"), + ("fedcba9876543210", "884f80625060b8b4", "f0e1d2c3b4a5968778695a4b3c"), + ("fedcba9876543210", "1f85031c19e11968", "f0e1d2c3b4a5968778695a4b3c2d"), + ("fedcba9876543210", "79d9373a714ca34f", "f0e1d2c3b4a5968778695a4b3c2d1e"), + ( + "fedcba9876543210", + "93142887ee3be15c", + "f0e1d2c3b4a5968778695a4b3c2d1e0f", + ), + ( + "fedcba9876543210", + "03429e838ce2d14b", + "f0e1d2c3b4a5968778695a4b3c2d1e0f00", + ), + ( + "fedcba9876543210", + "a4299e27469ff67b", + "f0e1d2c3b4a5968778695a4b3c2d1e0f0011", + ), + ( + "fedcba9876543210", + "afd5aed1c1bc96a8", + "f0e1d2c3b4a5968778695a4b3c2d1e0f001122", + ), + ( + "fedcba9876543210", + "10851c0e3858da9f", + "f0e1d2c3b4a5968778695a4b3c2d1e0f00112233", + ), + ( + "fedcba9876543210", + "e6f51ed79b9db21f", + "f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344", + ), + ( + "fedcba9876543210", + "64a6e14afd36b46f", + "f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455", + ), + ( + "fedcba9876543210", + "80c7d7d45a5479ad", + "f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566", + ), + ( + "fedcba9876543210", + "05044b62fa52d080", + "f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677", + ), ] class KeyLength(unittest.TestCase): - - def runTest(self): - self.assertRaises(ValueError, Blowfish.new, bchr(0) * 3, - Blowfish.MODE_ECB) - self.assertRaises(ValueError, Blowfish.new, bchr(0) * 57, - Blowfish.MODE_ECB) + def runTest(self): + self.assertRaises( + ValueError, + Blowfish.new, + bchr(0) * 3, + Blowfish.MODE_ECB, + ) + self.assertRaises( + ValueError, + Blowfish.new, + bchr(0) * 57, + Blowfish.MODE_ECB, + ) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter + + cipher = Blowfish.new(b"4" * 16, Blowfish.MODE_ECB) - def runTest(self): - # Encrypt/Decrypt data and test output parameter + pt = b"5" * 16 + ct = cipher.encrypt(pt) - cipher = Blowfish.new(b'4'*16, Blowfish.MODE_ECB) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from .common import make_block_tests - tests = make_block_tests(Blowfish, "Blowfish", test_data) - tests.append(KeyLength()) - tests += [TestOutput()] - return tests + from .common import make_block_tests + + tests = make_block_tests(Blowfish, "Blowfish", test_data) + tests.append(KeyLength()) + tests += [TestOutput()] + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CAST.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CAST.py index 8bc21fd3..a97a31ce 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CAST.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CAST.py @@ -32,70 +32,76 @@ # This is a list of (plaintext, ciphertext, key) tuples. test_data = [ - # Test vectors from RFC 2144, B.1 - ('0123456789abcdef', '238b4fe5847e44b2', - '0123456712345678234567893456789a', - '128-bit key'), - - ('0123456789abcdef', 'eb6a711a2c02271b', - '01234567123456782345', - '80-bit key'), - - ('0123456789abcdef', '7ac816d16e9b302e', - '0123456712', - '40-bit key'), + # Test vectors from RFC 2144, B.1 + ( + "0123456789abcdef", + "238b4fe5847e44b2", + "0123456712345678234567893456789a", + "128-bit key", + ), + ( + "0123456789abcdef", + "eb6a711a2c02271b", + "01234567123456782345", + "80-bit key", + ), + ( + "0123456789abcdef", + "7ac816d16e9b302e", + "0123456712", + "40-bit key", + ), ] class KeyLength(unittest.TestCase): - - def runTest(self): - self.assertRaises(ValueError, CAST.new, bchr(0) * 4, CAST.MODE_ECB) - self.assertRaises(ValueError, CAST.new, bchr(0) * 17, CAST.MODE_ECB) + def runTest(self): + self.assertRaises(ValueError, CAST.new, bchr(0) * 4, CAST.MODE_ECB) + self.assertRaises(ValueError, CAST.new, bchr(0) * 17, CAST.MODE_ECB) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter + + cipher = CAST.new(b"4" * 16, CAST.MODE_ECB) - def runTest(self): - # Encrypt/Decrypt data and test output parameter + pt = b"5" * 16 + ct = cipher.encrypt(pt) - cipher = CAST.new(b'4'*16, CAST.MODE_ECB) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from .common import make_block_tests + from .common import make_block_tests + + tests = make_block_tests(CAST, "CAST", test_data) + tests.append(KeyLength()) + tests.append(TestOutput()) + return tests - tests = make_block_tests(CAST, "CAST", test_data) - tests.append(KeyLength()) - tests.append(TestOutput()) - return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CBC.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CBC.py index f118eb6b..eca54125 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CBC.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CBC.py @@ -39,518 +39,568 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) -class BlockChainingTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - key_192 = get_tag_random("key_192", 24) - iv_128 = get_tag_random("iv_128", 16) - iv_64 = get_tag_random("iv_64", 8) - data_128 = get_tag_random("data_128", 16) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_loopback_64(self): - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - pt = get_tag_random("plaintext", 8 * 100) - ct = cipher.encrypt(pt) - - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_iv(self): - # If not passed, the iv is created randomly - cipher = AES.new(self.key_128, self.aes_mode) - iv1 = cipher.iv - cipher = AES.new(self.key_128, self.aes_mode) - iv2 = cipher.iv - self.assertNotEqual(iv1, iv2) - self.assertEqual(len(iv1), 16) - - # IV can be passed in uppercase or lowercase - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - ct = cipher.encrypt(self.data_128) - - cipher = AES.new(self.key_128, self.aes_mode, iv=self.iv_128) - self.assertEqual(ct, cipher.encrypt(self.data_128)) - - cipher = AES.new(self.key_128, self.aes_mode, IV=self.iv_128) - self.assertEqual(ct, cipher.encrypt(self.data_128)) - - def test_iv_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode, - iv = u'test1234567890-*') - - def test_only_one_iv(self): - # Only one IV/iv keyword allowed - self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode, - iv=self.iv_128, IV=self.iv_128) - - def test_iv_with_matching_length(self): - self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode, - b"") - self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode, - self.iv_128[:15]) - self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode, - self.iv_128 + b"0") - - def test_block_size_128(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_block_size_64(self): - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - self.assertEqual(cipher.block_size, DES3.block_size) - - def test_unaligned_data_128(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - for wrong_length in range(1,16): - self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length) - - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - for wrong_length in range(1,16): - self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length) - - def test_unaligned_data_64(self): - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - for wrong_length in range(1,8): - self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length) - - cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) - for wrong_length in range(1,8): - self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length) - - def test_IV_iv_attributes(self): - data = get_tag_random("data", 16 * 100) - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - getattr(cipher, func)(data) - self.assertEqual(cipher.iv, self.iv_128) - self.assertEqual(cipher.IV, self.iv_128) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode, - self.iv_128, 7) - self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode, - iv=self.iv_128, unknown=7) - # But some are only known by the base cipher (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, self.aes_mode, iv=self.iv_128, use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_bytearray(self): - data = b"1" * 128 - data_ba = bytearray(data) - - # Encrypt - key_ba = bytearray(self.key_128) - iv_ba = bytearray(self.iv_128) - - cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128) - ref1 = cipher1.encrypt(data) - - cipher2 = AES.new(key_ba, self.aes_mode, iv_ba) - key_ba[:3] = b'\xFF\xFF\xFF' - iv_ba[:3] = b'\xFF\xFF\xFF' - ref2 = cipher2.encrypt(data_ba) - - self.assertEqual(ref1, ref2) - self.assertEqual(cipher1.iv, cipher2.iv) - - # Decrypt - key_ba = bytearray(self.key_128) - iv_ba = bytearray(self.iv_128) - - cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128) - ref3 = cipher3.decrypt(data) - - cipher4 = AES.new(key_ba, self.aes_mode, iv_ba) - key_ba[:3] = b'\xFF\xFF\xFF' - iv_ba[:3] = b'\xFF\xFF\xFF' - ref4 = cipher4.decrypt(data_ba) - - self.assertEqual(ref3, ref4) - - def test_memoryview(self): - data = b"1" * 128 - data_mv = memoryview(bytearray(data)) - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - iv_mv = memoryview(bytearray(self.iv_128)) - - cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128) - ref1 = cipher1.encrypt(data) - - cipher2 = AES.new(key_mv, self.aes_mode, iv_mv) - key_mv[:3] = b'\xFF\xFF\xFF' - iv_mv[:3] = b'\xFF\xFF\xFF' - ref2 = cipher2.encrypt(data_mv) - - self.assertEqual(ref1, ref2) - self.assertEqual(cipher1.iv, cipher2.iv) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - iv_mv = memoryview(bytearray(self.iv_128)) - - cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128) - ref3 = cipher3.decrypt(data) - - cipher4 = AES.new(key_mv, self.aes_mode, iv_mv) - key_mv[:3] = b'\xFF\xFF\xFF' - iv_mv[:3] = b'\xFF\xFF\xFF' - ref4 = cipher4.decrypt(data_mv) - - self.assertEqual(ref3, ref4) - - def test_output_param(self): - pt = b'5' * 128 - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) - - output = bytearray(128) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - - def test_output_param_same_buffer(self): - - pt = b'5' * 128 - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) +class BlockChainingTests(unittest.TestCase): + key_128 = get_tag_random("key_128", 16) + key_192 = get_tag_random("key_192", 24) + iv_128 = get_tag_random("iv_128", 16) + iv_64 = get_tag_random("iv_64", 8) + data_128 = get_tag_random("data_128", 16) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_loopback_64(self): + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + pt = get_tag_random("plaintext", 8 * 100) + ct = cipher.encrypt(pt) + + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_iv(self): + # If not passed, the iv is created randomly + cipher = AES.new(self.key_128, self.aes_mode) + iv1 = cipher.iv + cipher = AES.new(self.key_128, self.aes_mode) + iv2 = cipher.iv + self.assertNotEqual(iv1, iv2) + self.assertEqual(len(iv1), 16) + + # IV can be passed in uppercase or lowercase + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + ct = cipher.encrypt(self.data_128) + + cipher = AES.new(self.key_128, self.aes_mode, iv=self.iv_128) + self.assertEqual(ct, cipher.encrypt(self.data_128)) + + cipher = AES.new(self.key_128, self.aes_mode, IV=self.iv_128) + self.assertEqual(ct, cipher.encrypt(self.data_128)) + + def test_iv_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + self.aes_mode, + iv="test1234567890-*", + ) + + def test_only_one_iv(self): + # Only one IV/iv keyword allowed + self.assertRaises( + TypeError, + AES.new, + self.key_128, + self.aes_mode, + iv=self.iv_128, + IV=self.iv_128, + ) + + def test_iv_with_matching_length(self): + self.assertRaises( + ValueError, + AES.new, + self.key_128, + self.aes_mode, + b"", + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + self.aes_mode, + self.iv_128[:15], + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + self.aes_mode, + self.iv_128 + b"0", + ) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_block_size_64(self): + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + self.assertEqual(cipher.block_size, DES3.block_size) + + def test_unaligned_data_128(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + for wrong_length in range(1, 16): + self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length) + + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + for wrong_length in range(1, 16): + self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length) + + def test_unaligned_data_64(self): + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + for wrong_length in range(1, 8): + self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length) + + cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64) + for wrong_length in range(1, 8): + self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length) + + def test_IV_iv_attributes(self): + data = get_tag_random("data", 16 * 100) + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + getattr(cipher, func)(data) + self.assertEqual(cipher.iv, self.iv_128) + self.assertEqual(cipher.IV, self.iv_128) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + self.aes_mode, + self.iv_128, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + self.aes_mode, + iv=self.iv_128, + unknown=7, + ) + # But some are only known by the base cipher (e.g. use_aesni consumed by the AES module) + AES.new(self.key_128, self.aes_mode, iv=self.iv_128, use_aesni=False) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, self.aes_mode, self.iv_128) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_bytearray(self): + data = b"1" * 128 + data_ba = bytearray(data) + + # Encrypt + key_ba = bytearray(self.key_128) + iv_ba = bytearray(self.iv_128) + + cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128) + ref1 = cipher1.encrypt(data) + + cipher2 = AES.new(key_ba, self.aes_mode, iv_ba) + key_ba[:3] = b"\xff\xff\xff" + iv_ba[:3] = b"\xff\xff\xff" + ref2 = cipher2.encrypt(data_ba) + + self.assertEqual(ref1, ref2) + self.assertEqual(cipher1.iv, cipher2.iv) + + # Decrypt + key_ba = bytearray(self.key_128) + iv_ba = bytearray(self.iv_128) + + cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128) + ref3 = cipher3.decrypt(data) + + cipher4 = AES.new(key_ba, self.aes_mode, iv_ba) + key_ba[:3] = b"\xff\xff\xff" + iv_ba[:3] = b"\xff\xff\xff" + ref4 = cipher4.decrypt(data_ba) + + self.assertEqual(ref3, ref4) + + def test_memoryview(self): + data = b"1" * 128 + data_mv = memoryview(bytearray(data)) + + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + iv_mv = memoryview(bytearray(self.iv_128)) + + cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128) + ref1 = cipher1.encrypt(data) + + cipher2 = AES.new(key_mv, self.aes_mode, iv_mv) + key_mv[:3] = b"\xff\xff\xff" + iv_mv[:3] = b"\xff\xff\xff" + ref2 = cipher2.encrypt(data_mv) + + self.assertEqual(ref1, ref2) + self.assertEqual(cipher1.iv, cipher2.iv) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + iv_mv = memoryview(bytearray(self.iv_128)) + + cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128) + ref3 = cipher3.decrypt(data) + + cipher4 = AES.new(key_mv, self.aes_mode, iv_mv) + key_mv[:3] = b"\xff\xff\xff" + iv_mv[:3] = b"\xff\xff\xff" + ref4 = cipher4.decrypt(data_mv) + + self.assertEqual(ref3, ref4) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + ct = cipher.encrypt(pt) + + output = bytearray(128) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt_ba = bytearray(pt) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - res = cipher.encrypt(pt_ba, output=pt_ba) - self.assertEqual(ct, pt_ba) - self.assertEqual(res, None) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - ct_ba = bytearray(ct) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - res = cipher.decrypt(ct_ba, output=ct_ba) - self.assertEqual(pt, ct_ba) - self.assertEqual(res, None) + def test_output_param_same_buffer(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + ct = cipher.encrypt(pt) + pt_ba = bytearray(pt) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + res = cipher.encrypt(pt_ba, output=pt_ba) + self.assertEqual(ct, pt_ba) + self.assertEqual(res, None) - def test_output_param_memoryview(self): + ct_ba = bytearray(ct) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + res = cipher.decrypt(ct_ba, output=ct_ba) + self.assertEqual(pt, ct_ba) + self.assertEqual(res, None) - pt = b'5' * 128 - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + ct = cipher.encrypt(pt) - output = memoryview(bytearray(128)) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + output = memoryview(bytearray(128)) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - def test_output_param_neg(self): - LEN_PT = 128 + def test_output_param_neg(self): + LEN_PT = 128 - pt = b'5' * LEN_PT - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) + pt = b"5" * LEN_PT + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + ct = cipher.encrypt(pt) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * LEN_PT) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * LEN_PT) - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(b"4" * 16, self.aes_mode, iv=self.iv_128) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) class CbcTests(BlockChainingTests): - aes_mode = AES.MODE_CBC - des3_mode = DES3.MODE_CBC + aes_mode = AES.MODE_CBC + des3_mode = DES3.MODE_CBC class NistBlockChainingVectors(unittest.TestCase): - - def _do_kat_aes_test(self, file_name): - - test_vectors = load_test_vectors(("Cipher", "AES"), - file_name, - "AES CBC KAT", - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - - cipher = AES.new(tv.key, self.aes_mode, tv.iv) - if direction == "[ENCRYPT]": - self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) - elif direction == "[DECRYPT]": - self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) - else: - assert False - - # See Section 6.4.2 in AESAVS - def _do_mct_aes_test(self, file_name): - - test_vectors = load_test_vectors(("Cipher", "AES"), - file_name, - "AES CBC Montecarlo", - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - cipher = AES.new(tv.key, self.aes_mode, tv.iv) - - if direction == '[ENCRYPT]': - cts = [ tv.iv ] - for count in range(1000): - cts.append(cipher.encrypt(tv.plaintext)) - tv.plaintext = cts[-2] - self.assertEqual(cts[-1], tv.ciphertext) - elif direction == '[DECRYPT]': - pts = [ tv.iv] - for count in range(1000): - pts.append(cipher.decrypt(tv.ciphertext)) - tv.ciphertext = pts[-2] - self.assertEqual(pts[-1], tv.plaintext) - else: - assert False - - def _do_tdes_test(self, file_name): - - test_vectors = load_test_vectors(("Cipher", "TDES"), - file_name, - "TDES CBC KAT", - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - if hasattr(tv, "keys"): - cipher = DES.new(tv.keys, self.des_mode, tv.iv) - else: - if tv.key1 != tv.key3: - key = tv.key1 + tv.key2 + tv.key3 # Option 3 - else: - key = tv.key1 + tv.key2 # Option 2 - cipher = DES3.new(key, self.des3_mode, tv.iv) - - if direction == "[ENCRYPT]": - self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) - elif direction == "[DECRYPT]": - self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) - else: - assert False + def _do_kat_aes_test(self, file_name): + test_vectors = load_test_vectors( + ("Cipher", "AES"), + file_name, + "AES CBC KAT", + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + + cipher = AES.new(tv.key, self.aes_mode, tv.iv) + if direction == "[ENCRYPT]": + self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) + elif direction == "[DECRYPT]": + self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) + else: + assert False + + # See Section 6.4.2 in AESAVS + def _do_mct_aes_test(self, file_name): + test_vectors = load_test_vectors( + ("Cipher", "AES"), + file_name, + "AES CBC Montecarlo", + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + cipher = AES.new(tv.key, self.aes_mode, tv.iv) + + if direction == "[ENCRYPT]": + cts = [tv.iv] + for count in range(1000): + cts.append(cipher.encrypt(tv.plaintext)) + tv.plaintext = cts[-2] + self.assertEqual(cts[-1], tv.ciphertext) + elif direction == "[DECRYPT]": + pts = [tv.iv] + for count in range(1000): + pts.append(cipher.decrypt(tv.ciphertext)) + tv.ciphertext = pts[-2] + self.assertEqual(pts[-1], tv.plaintext) + else: + assert False + + def _do_tdes_test(self, file_name): + test_vectors = load_test_vectors( + ("Cipher", "TDES"), + file_name, + "TDES CBC KAT", + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + if hasattr(tv, "keys"): + cipher = DES.new(tv.keys, self.des_mode, tv.iv) + else: + if tv.key1 != tv.key3: + key = tv.key1 + tv.key2 + tv.key3 # Option 3 + else: + key = tv.key1 + tv.key2 # Option 2 + cipher = DES3.new(key, self.des3_mode, tv.iv) + + if direction == "[ENCRYPT]": + self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) + elif direction == "[DECRYPT]": + self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) + else: + assert False class NistCbcVectors(NistBlockChainingVectors): - aes_mode = AES.MODE_CBC - des_mode = DES.MODE_CBC - des3_mode = DES3.MODE_CBC + aes_mode = AES.MODE_CBC + des_mode = DES.MODE_CBC + des3_mode = DES3.MODE_CBC # Create one test method per file nist_aes_kat_mmt_files = ( - # KAT - "CBCGFSbox128.rsp", - "CBCGFSbox192.rsp", - "CBCGFSbox256.rsp", - "CBCKeySbox128.rsp", - "CBCKeySbox192.rsp", - "CBCKeySbox256.rsp", - "CBCVarKey128.rsp", - "CBCVarKey192.rsp", - "CBCVarKey256.rsp", - "CBCVarTxt128.rsp", - "CBCVarTxt192.rsp", - "CBCVarTxt256.rsp", - # MMT - "CBCMMT128.rsp", - "CBCMMT192.rsp", - "CBCMMT256.rsp", - ) + # KAT + "CBCGFSbox128.rsp", + "CBCGFSbox192.rsp", + "CBCGFSbox256.rsp", + "CBCKeySbox128.rsp", + "CBCKeySbox192.rsp", + "CBCKeySbox256.rsp", + "CBCVarKey128.rsp", + "CBCVarKey192.rsp", + "CBCVarKey256.rsp", + "CBCVarTxt128.rsp", + "CBCVarTxt192.rsp", + "CBCVarTxt256.rsp", + # MMT + "CBCMMT128.rsp", + "CBCMMT192.rsp", + "CBCMMT256.rsp", +) nist_aes_mct_files = ( - "CBCMCT128.rsp", - "CBCMCT192.rsp", - "CBCMCT256.rsp", - ) + "CBCMCT128.rsp", + "CBCMCT192.rsp", + "CBCMCT256.rsp", +) for file_name in nist_aes_kat_mmt_files: - def new_func(self, file_name=file_name): - self._do_kat_aes_test(file_name) - setattr(NistCbcVectors, "test_AES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_kat_aes_test(file_name) + + setattr(NistCbcVectors, "test_AES_" + file_name, new_func) for file_name in nist_aes_mct_files: - def new_func(self, file_name=file_name): - self._do_mct_aes_test(file_name) - setattr(NistCbcVectors, "test_AES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_mct_aes_test(file_name) + + setattr(NistCbcVectors, "test_AES_" + file_name, new_func) del file_name, new_func nist_tdes_files = ( - "TCBCMMT2.rsp", # 2TDES - "TCBCMMT3.rsp", # 3TDES - "TCBCinvperm.rsp", # Single DES - "TCBCpermop.rsp", - "TCBCsubtab.rsp", - "TCBCvarkey.rsp", - "TCBCvartext.rsp", - ) + "TCBCMMT2.rsp", # 2TDES + "TCBCMMT3.rsp", # 3TDES + "TCBCinvperm.rsp", # Single DES + "TCBCpermop.rsp", + "TCBCsubtab.rsp", + "TCBCvarkey.rsp", + "TCBCvartext.rsp", +) for file_name in nist_tdes_files: - def new_func(self, file_name=file_name): - self._do_tdes_test(file_name) - setattr(NistCbcVectors, "test_TDES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_tdes_test(file_name) + + setattr(NistCbcVectors, "test_TDES_" + file_name, new_func) # END OF NIST CBC TEST VECTORS class SP800TestVectors(unittest.TestCase): - """Class exercising the CBC test vectors found in Section F.2 - of NIST SP 800-3A""" - - def test_aes_128(self): - key = '2b7e151628aed2a6abf7158809cf4f3c' - iv = '000102030405060708090a0b0c0d0e0f' - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '7649abac8119b246cee98e9b12e9197d' +\ - '5086cb9b507219ee95db113a917678b2' +\ - '73bed6b8e3c1743b7116e69e22229516' +\ - '3ff1caa1681fac09120eca307586e1a7' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_192(self): - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - iv = '000102030405060708090a0b0c0d0e0f' - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '4f021db243bc633d7178183a9fa071e8' +\ - 'b4d9ada9ad7dedf4e5e738763f69145a' +\ - '571b242012fb7ae07fa9baac3df102e0' +\ - '08b0e27988598881d920a9e64f5615cd' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_256(self): - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - iv = '000102030405060708090a0b0c0d0e0f' - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = 'f58c4c04d6e5f1ba779eabfb5f7bfbd6' +\ - '9cfc4e967edb808d679f777bc6702c7d' +\ - '39f23369a9d9bacfa530e26304231461' +\ - 'b2eb05e2c39be9fcda6c19078c6a9d1b' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CBC, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) + """Class exercising the CBC test vectors found in Section F.2 + of NIST SP 800-3A""" + + def test_aes_128(self): + key = "2b7e151628aed2a6abf7158809cf4f3c" + iv = "000102030405060708090a0b0c0d0e0f" + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "7649abac8119b246cee98e9b12e9197d" + + "5086cb9b507219ee95db113a917678b2" + + "73bed6b8e3c1743b7116e69e22229516" + + "3ff1caa1681fac09120eca307586e1a7" + ) + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_192(self): + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + iv = "000102030405060708090a0b0c0d0e0f" + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "4f021db243bc633d7178183a9fa071e8" + + "b4d9ada9ad7dedf4e5e738763f69145a" + + "571b242012fb7ae07fa9baac3df102e0" + + "08b0e27988598881d920a9e64f5615cd" + ) + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_256(self): + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + iv = "000102030405060708090a0b0c0d0e0f" + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "f58c4c04d6e5f1ba779eabfb5f7bfbd6" + + "9cfc4e967edb808d679f777bc6702c7d" + + "39f23369a9d9bacfa530e26304231461" + + "b2eb05e2c39be9fcda6c19078c6a9d1b" + ) + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CBC, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) def get_tests(config={}): - tests = [] - tests += list_test_cases(CbcTests) - if config.get('slow_tests'): - tests += list_test_cases(NistCbcVectors) - tests += list_test_cases(SP800TestVectors) - return tests + tests = [] + tests += list_test_cases(CbcTests) + if config.get("slow_tests"): + tests += list_test_cases(NistCbcVectors) + tests += list_test_cases(SP800TestVectors) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CCM.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CCM.py index c179f16e..91df8390 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CCM.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CCM.py @@ -43,928 +43,1162 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class CcmTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # If not passed, the nonce is created randomly - cipher = AES.new(self.key_128, AES.MODE_CCM) - nonce1 = cipher.nonce - cipher = AES.new(self.key_128, AES.MODE_CCM) - nonce2 = cipher.nonce - self.assertEqual(len(nonce1), 11) - self.assertNotEqual(nonce1, nonce2) - - cipher = AES.new(self.key_128, AES.MODE_CCM, self.nonce_96) - ct = cipher.encrypt(self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CCM, - nonce=u'test12345678') - - def test_nonce_length(self): - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM, - nonce=b"") - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM, - nonce=bchr(1) * 6) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM, - nonce=bchr(1) * 14) - for x in range(7, 13 + 1): - AES.new(self.key_128, AES.MODE_CCM, nonce=bchr(1) * x) - - def test_block_size(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 11 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_CCM).nonce - nonce2 = AES.new(self.key_128, AES.MODE_CCM).nonce - self.assertEqual(len(nonce1), 11) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CCM, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - # Invalid MAC length - for mac_len in range(3, 17 + 1, 2): - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, mac_len=mac_len) - - # Valid MAC length - for mac_len in range(4, 16 + 1, 2): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - mac_len=mac_len) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), mac_len) - - # Default MAC length - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_longer_assoc_data_than_declared(self): - # More than zero - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=0) - self.assertRaises(ValueError, cipher.update, b"1") - - # Too large - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=15) - self.assertRaises(ValueError, cipher.update, self.data) - - def test_shorter_assoc_data_than_expected(self): - DATA_LEN = len(self.data) - - # With plaintext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=DATA_LEN + 1) - cipher.update(self.data) - self.assertRaises(ValueError, cipher.encrypt, self.data) - - # With empty plaintext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=DATA_LEN + 1) - cipher.update(self.data) - self.assertRaises(ValueError, cipher.digest) - - # With ciphertext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=DATA_LEN + 1) - cipher.update(self.data) - self.assertRaises(ValueError, cipher.decrypt, self.data) - - # With empty ciphertext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=DATA_LEN + 1) - cipher.update(self.data) - self.assertRaises(ValueError, cipher.verify, mac) - - def test_shorter_and_longer_plaintext_than_declared(self): - DATA_LEN = len(self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=DATA_LEN + 1) - cipher.encrypt(self.data) - self.assertRaises(ValueError, cipher.digest) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=DATA_LEN - 1) - self.assertRaises(ValueError, cipher.encrypt, self.data) - - def test_shorter_ciphertext_than_declared(self): - DATA_LEN = len(self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=DATA_LEN + 1) - cipher.decrypt(ct) - self.assertRaises(ValueError, cipher.verify, mac) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=DATA_LEN - 1) - self.assertRaises(ValueError, cipher.decrypt, ct) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=127, assoc_len=127) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b"" - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=127, assoc_len=127) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b"" - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - data_ba = bytearray(self.data) - - cipher1 = AES.new(self.key_128, - AES.MODE_CCM, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) - tag = cipher1.digest() - - cipher2 = AES.new(key_ba, - AES.MODE_CCM, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_ba) - data_ba[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - del data_ba - - cipher4 = AES.new(key_ba, - AES.MODE_CCM, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - data_mv = memoryview(bytearray(self.data)) - - cipher1 = AES.new(self.key_128, - AES.MODE_CCM, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) - tag = cipher1.digest() - - cipher2 = AES.new(key_mv, - AES.MODE_CCM, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_mv) - data_mv[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - del data_mv - - cipher4 = AES.new(key_mv, - AES.MODE_CCM, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - tag = cipher.digest() - - output = bytearray(128) - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - res, tag_out = cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - self.assertEqual(tag, tag_out) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - res = cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - - def test_output_param_neg(self): - - pt = b'5' * 16 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) - - shorter_output = bytearray(15) - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) - - def test_message_too_long(self): - - nonce = b'N' * 13 - self.assertRaises(CCMMessageTooLongError, - AES.new, - self.key_128, - AES.MODE_CCM, - nonce=nonce, - assoc_len=20, - msg_len=0x10000) - - nonce = b'N' * 7 - self.assertRaises(CCMMessageTooLongError, - AES.new, - self.key_128, - AES.MODE_CCM, - nonce=nonce, - assoc_len=20, - msg_len=2**64) - - nonce = b'N' * 13 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=nonce) - self.assertRaises(CCMMessageTooLongError, - cipher.encrypt, - b'C' * 0x10000) - - nonce = b'N' * 13 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=nonce) - self.assertRaises(CCMMessageTooLongError, - cipher.decrypt, - b'C' * 0x10000) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # If not passed, the nonce is created randomly + cipher = AES.new(self.key_128, AES.MODE_CCM) + nonce1 = cipher.nonce + cipher = AES.new(self.key_128, AES.MODE_CCM) + nonce2 = cipher.nonce + self.assertEqual(len(nonce1), 11) + self.assertNotEqual(nonce1, nonce2) + + cipher = AES.new(self.key_128, AES.MODE_CCM, self.nonce_96) + ct = cipher.encrypt(self.data) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertEqual(ct, cipher.encrypt(self.data)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce="test12345678", + ) + + def test_nonce_length(self): + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=b"", + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=bchr(1) * 6, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=bchr(1) * 14, + ) + for x in range(7, 13 + 1): + AES.new(self.key_128, AES.MODE_CCM, nonce=bchr(1) * x) + + def test_block_size(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 11 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_CCM).nonce + nonce2 = AES.new(self.key_128, AES.MODE_CCM).nonce + self.assertEqual(len(nonce1), 11) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CCM, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + # Invalid MAC length + for mac_len in range(3, 17 + 1, 2): + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + mac_len=mac_len, + ) + + # Valid MAC length + for mac_len in range(4, 16 + 1, 2): + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + mac_len=mac_len, + ) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), mac_len) + + # Default MAC length + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_longer_assoc_data_than_declared(self): + # More than zero + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=0, + ) + self.assertRaises(ValueError, cipher.update, b"1") + + # Too large + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=15, + ) + self.assertRaises(ValueError, cipher.update, self.data) + + def test_shorter_assoc_data_than_expected(self): + DATA_LEN = len(self.data) + + # With plaintext + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=DATA_LEN + 1, + ) + cipher.update(self.data) + self.assertRaises(ValueError, cipher.encrypt, self.data) + + # With empty plaintext + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=DATA_LEN + 1, + ) + cipher.update(self.data) + self.assertRaises(ValueError, cipher.digest) + + # With ciphertext + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=DATA_LEN + 1, + ) + cipher.update(self.data) + self.assertRaises(ValueError, cipher.decrypt, self.data) + + # With empty ciphertext + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + mac = cipher.digest() + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=DATA_LEN + 1, + ) + cipher.update(self.data) + self.assertRaises(ValueError, cipher.verify, mac) + + def test_shorter_and_longer_plaintext_than_declared(self): + DATA_LEN = len(self.data) + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=DATA_LEN + 1, + ) + cipher.encrypt(self.data) + self.assertRaises(ValueError, cipher.digest) + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=DATA_LEN - 1, + ) + self.assertRaises(ValueError, cipher.encrypt, self.data) + + def test_shorter_ciphertext_than_declared(self): + DATA_LEN = len(self.data) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=DATA_LEN + 1, + ) + cipher.decrypt(ct) + self.assertRaises(ValueError, cipher.verify, mac) + + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=DATA_LEN - 1, + ) + self.assertRaises(ValueError, cipher.decrypt, ct) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=127, + assoc_len=127, + ) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b"" + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=127, + assoc_len=127, + ) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b"" + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + data_ba = bytearray(self.data) + + cipher1 = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + tag = cipher1.digest() + + cipher2 = AES.new( + key_ba, + AES.MODE_CCM, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + data_ba[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + del data_ba + + cipher4 = AES.new( + key_ba, + AES.MODE_CCM, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher4.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + data_mv = memoryview(bytearray(self.data)) + + cipher1 = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + tag = cipher1.digest() + + cipher2 = AES.new( + key_mv, + AES.MODE_CCM, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + data_mv[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + del data_mv + + cipher4 = AES.new( + key_mv, + AES.MODE_CCM, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher4.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + tag = cipher.digest() + + output = bytearray(128) + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + res, tag_out = cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + self.assertEqual(tag, tag_out) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + res = cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + pt = b"5" * 16 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) + + shorter_output = bytearray(15) + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + + def test_message_too_long(self): + nonce = b"N" * 13 + self.assertRaises( + CCMMessageTooLongError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=nonce, + assoc_len=20, + msg_len=0x10000, + ) + + nonce = b"N" * 7 + self.assertRaises( + CCMMessageTooLongError, + AES.new, + self.key_128, + AES.MODE_CCM, + nonce=nonce, + assoc_len=20, + msg_len=2**64, + ) + + nonce = b"N" * 13 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=nonce) + self.assertRaises( + CCMMessageTooLongError, + cipher.encrypt, + b"C" * 0x10000, + ) + + nonce = b"N" * 13 + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=nonce) + self.assertRaises( + CCMMessageTooLongError, + cipher.decrypt, + b"C" * 0x10000, + ) class CcmFSMTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 16) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - for assoc_len in (None, 0): - for msg_len in (None, len(self.data)): - # Verify path INIT->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - # Verify path INIT->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - for assoc_len in (None, len(self.data)): - for msg_len in (None, 0): - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.update(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.update(self.data) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - for assoc_len in (None, len(self.data)): - for msg_len in (None, len(self.data)): - # Verify path INIT->UPDATE->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.update(self.data) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - assoc_len=assoc_len, - msg_len=msg_len) - cipher.update(self.data) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - # Only possible if msg_len is declared in advance - for method_name in "encrypt", "decrypt": - for auth_data in (None, b"333", self.data, - self.data + b"3"): - if auth_data is None: - assoc_len = None - else: - assoc_len = len(auth_data) - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - msg_len=64, - assoc_len=assoc_len) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data) - method(self.data) - method(self.data) - method(self.data) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - ct, mac = cipher.encrypt_and_digest(self.data) - - # decrypt_and_verify - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data, pt) - - def test_invalid_multiple_encrypt_decrypt_without_msg_len(self): - # Once per method, with or without assoc. data - for method_name in "encrypt", "decrypt": - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data) - method = getattr(cipher, method_name) - method(self.data) - self.assertRaises(TypeError, method, self.data) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_CCM, - nonce=self.nonce_96, - msg_len=32) - if assoc_data_present: - cipher.update(self.data) - getattr(cipher, method1_name)(self.data) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.encrypt(self.data) - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 16) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + for assoc_len in (None, 0): + for msg_len in (None, len(self.data)): + # Verify path INIT->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + # Verify path INIT->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + for assoc_len in (None, len(self.data)): + for msg_len in (None, 0): + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.update(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.update(self.data) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + for assoc_len in (None, len(self.data)): + for msg_len in (None, len(self.data)): + # Verify path INIT->UPDATE->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.update(self.data) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + assoc_len=assoc_len, + msg_len=msg_len, + ) + cipher.update(self.data) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + # Only possible if msg_len is declared in advance + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b"333", + self.data, + self.data + b"3", + ): + if auth_data is None: + assoc_len = None + else: + assoc_len = len(auth_data) + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=64, + assoc_len=assoc_len, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data) + method(self.data) + method(self.data) + method(self.data) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + ct, mac = cipher.encrypt_and_digest(self.data) + + # decrypt_and_verify + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.update(self.data) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data, pt) + + def test_invalid_multiple_encrypt_decrypt_without_msg_len(self): + # Once per method, with or without assoc. data + for method_name in "encrypt", "decrypt": + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data) + method = getattr(cipher, method_name) + method(self.data) + self.assertRaises(TypeError, method, self.data) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_CCM, + nonce=self.nonce_96, + msg_len=32, + ) + if assoc_data_present: + cipher.update(self.data) + getattr(cipher, method1_name)(self.data) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.encrypt(self.data) + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) class TestVectors(unittest.TestCase): - """Class exercising the CCM test vectors found in Appendix C - of NIST SP 800-38C and in RFC 3610""" - - # List of test vectors, each made up of: - # - authenticated data - # - plaintext - # - ciphertext - # - MAC - # - AES key - # - nonce - test_vectors_hex = [ - # NIST SP 800 38C - ( '0001020304050607', - '20212223', - '7162015b', - '4dac255d', - '404142434445464748494a4b4c4d4e4f', - '10111213141516'), - ( '000102030405060708090a0b0c0d0e0f', - '202122232425262728292a2b2c2d2e2f', - 'd2a1f0e051ea5f62081a7792073d593d', - '1fc64fbfaccd', - '404142434445464748494a4b4c4d4e4f', - '1011121314151617'), - ( '000102030405060708090a0b0c0d0e0f10111213', - '202122232425262728292a2b2c2d2e2f3031323334353637', - 'e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5', - '484392fbc1b09951', - '404142434445464748494a4b4c4d4e4f', - '101112131415161718191a1b'), - ( (''.join(["%02X" % (x*16+y) for x in range(0,16) for y in range(0,16)]))*256, - '202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f', - '69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72', - 'b4ac6bec93e8598e7f0dadbcea5b', - '404142434445464748494a4b4c4d4e4f', - '101112131415161718191a1b1c'), - # RFC3610 - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e', - '588c979a61c663d2f066d0c2c0f989806d5f6b61dac384', - '17e8d12cfdf926e0', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000003020100a0a1a2a3a4a5'), - ( - '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b', - 'a091d56e10400916', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000004030201a0a1a2a3a4a5'), - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', - '51b1e5f44a197d1da46b0f8e2d282ae871e838bb64da859657', - '4adaa76fbd9fb0c5', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000005040302A0A1A2A3A4A5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e', - 'a28c6865939a9a79faaa5c4c2a9d4a91cdac8c', - '96c861b9c9e61ef1', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000006050403a0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e1f', - 'dcf1fb7b5d9e23fb9d4e131253658ad86ebdca3e', - '51e83f077d9c2d93', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000007060504a0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e1f20', - '6fc1b011f006568b5171a42d953d469b2570a4bd87', - '405a0443ac91cb94', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000008070605a0a1a2a3a4a5'), - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e', - '0135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c', - '048c56602c97acbb7490', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '00000009080706a0a1a2a3a4a5'), - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '7b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24', - 'c17b4433f434963f34b4', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000a090807a0a1a2a3a4a5'), - ( '0001020304050607', - '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', - '82531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197', - 'ea9c07e56b5eb17e5f4e', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000b0a0908a0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e', - '07342594157785152b074098330abb141b947b', - '566aa9406b4d999988dd', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000c0b0a09a0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e1f', - '676bb20380b0e301e8ab79590a396da78b834934', - 'f53aa2e9107a8b6c022c', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000d0c0b0aa0a1a2a3a4a5'), - ( '000102030405060708090a0b', - '0c0d0e0f101112131415161718191a1b1c1d1e1f20', - 'c0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43', - 'cd1aa31662e7ad65d6db', - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', - '0000000e0d0c0ba0a1a2a3a4a5'), - ( '0be1a88bace018b1', - '08e8cf97d820ea258460e96ad9cf5289054d895ceac47c', - '4cb97f86a2a4689a877947ab8091ef5386a6ffbdd080f8', - 'e78cf7cb0cddd7b3', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00412b4ea9cdbe3c9696766cfa'), - ( '63018f76dc8a1bcb', - '9020ea6f91bdd85afa0039ba4baff9bfb79c7028949cd0ec', - '4ccb1e7ca981befaa0726c55d378061298c85c92814abc33', - 'c52ee81d7d77c08a', - 'd7828d13b2b0bdc325a76236df93cc6b', - '0033568ef7b2633c9696766cfa'), - ( 'aa6cfa36cae86b40', - 'b916e0eacc1c00d7dcec68ec0b3bbb1a02de8a2d1aa346132e', - 'b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708', - 'a776796edb723506', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00103fe41336713c9696766cfa'), - ( 'd0d0735c531e1becf049c244', - '12daac5630efa5396f770ce1a66b21f7b2101c', - '14d253c3967b70609b7cbb7c49916028324526', - '9a6f49975bcadeaf', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00764c63b8058e3c9696766cfa'), - ( '77b60f011c03e1525899bcae', - 'e88b6a46c78d63e52eb8c546efb5de6f75e9cc0d', - '5545ff1a085ee2efbf52b2e04bee1e2336c73e3f', - '762c0c7744fe7e3c', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00f8b678094e3b3c9696766cfa'), - ( 'cd9044d2b71fdb8120ea60c0', - '6435acbafb11a82e2f071d7ca4a5ebd93a803ba87f', - '009769ecabdf48625594c59251e6035722675e04c8', - '47099e5ae0704551', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00d560912d3f703c9696766cfa'), - ( 'd85bc7e69f944fb8', - '8a19b950bcf71a018e5e6701c91787659809d67dbedd18', - 'bc218daa947427b6db386a99ac1aef23ade0b52939cb6a', - '637cf9bec2408897c6ba', - 'd7828d13b2b0bdc325a76236df93cc6b', - '0042fff8f1951c3c9696766cfa'), - ( '74a0ebc9069f5b37', - '1761433c37c5a35fc1f39f406302eb907c6163be38c98437', - '5810e6fd25874022e80361a478e3e9cf484ab04f447efff6', - 'f0a477cc2fc9bf548944', - 'd7828d13b2b0bdc325a76236df93cc6b', - '00920f40e56cdc3c9696766cfa'), - ( '44a3aa3aae6475ca', - 'a434a8e58500c6e41530538862d686ea9e81301b5ae4226bfa', - 'f2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f154', - '4d4151a4ed3a8b87b9ce', - 'd7828d13b2b0bdc325a76236df93cc6b', - '0027ca0c7120bc3c9696766cfa'), - ( 'ec46bb63b02520c33c49fd70', - 'b96b49e21d621741632875db7f6c9243d2d7c2', - '31d750a09da3ed7fddd49a2032aabf17ec8ebf', - '7d22c8088c666be5c197', - 'd7828d13b2b0bdc325a76236df93cc6b', - '005b8ccbcd9af83c9696766cfa'), - ( '47a65ac78b3d594227e85e71', - 'e2fcfbb880442c731bf95167c8ffd7895e337076', - 'e882f1dbd38ce3eda7c23f04dd65071eb41342ac', - 'df7e00dccec7ae52987d', - 'd7828d13b2b0bdc325a76236df93cc6b', - '003ebe94044b9a3c9696766cfa'), - ( '6e37a6ef546d955d34ab6059', - 'abf21c0b02feb88f856df4a37381bce3cc128517d4', - 'f32905b88a641b04b9c9ffb58cc390900f3da12ab1', - '6dce9e82efa16da62059', - 'd7828d13b2b0bdc325a76236df93cc6b', - '008d493b30ae8b3c9696766cfa'), - ] - - test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - # Encrypt - cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Class exercising the CCM test vectors found in Appendix C + of NIST SP 800-38C and in RFC 3610""" + + # List of test vectors, each made up of: + # - authenticated data + # - plaintext + # - ciphertext + # - MAC + # - AES key + # - nonce + test_vectors_hex = [ + # NIST SP 800 38C + ( + "0001020304050607", + "20212223", + "7162015b", + "4dac255d", + "404142434445464748494a4b4c4d4e4f", + "10111213141516", + ), + ( + "000102030405060708090a0b0c0d0e0f", + "202122232425262728292a2b2c2d2e2f", + "d2a1f0e051ea5f62081a7792073d593d", + "1fc64fbfaccd", + "404142434445464748494a4b4c4d4e4f", + "1011121314151617", + ), + ( + "000102030405060708090a0b0c0d0e0f10111213", + "202122232425262728292a2b2c2d2e2f3031323334353637", + "e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5", + "484392fbc1b09951", + "404142434445464748494a4b4c4d4e4f", + "101112131415161718191a1b", + ), + ( + ("".join(["%02X" % (x * 16 + y) for x in range(0, 16) for y in range(0, 16)])) * 256, + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72", + "b4ac6bec93e8598e7f0dadbcea5b", + "404142434445464748494a4b4c4d4e4f", + "101112131415161718191a1b1c", + ), + # RFC3610 + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e", + "588c979a61c663d2f066d0c2c0f989806d5f6b61dac384", + "17e8d12cfdf926e0", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000003020100a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b", + "a091d56e10400916", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000004030201a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "51b1e5f44a197d1da46b0f8e2d282ae871e838bb64da859657", + "4adaa76fbd9fb0c5", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000005040302A0A1A2A3A4A5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e", + "a28c6865939a9a79faaa5c4c2a9d4a91cdac8c", + "96c861b9c9e61ef1", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000006050403a0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e1f", + "dcf1fb7b5d9e23fb9d4e131253658ad86ebdca3e", + "51e83f077d9c2d93", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000007060504a0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "6fc1b011f006568b5171a42d953d469b2570a4bd87", + "405a0443ac91cb94", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000008070605a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e", + "0135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c", + "048c56602c97acbb7490", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "00000009080706a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "7b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24", + "c17b4433f434963f34b4", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000a090807a0a1a2a3a4a5", + ), + ( + "0001020304050607", + "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "82531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197", + "ea9c07e56b5eb17e5f4e", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000b0a0908a0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e", + "07342594157785152b074098330abb141b947b", + "566aa9406b4d999988dd", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000c0b0a09a0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e1f", + "676bb20380b0e301e8ab79590a396da78b834934", + "f53aa2e9107a8b6c022c", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000d0c0b0aa0a1a2a3a4a5", + ), + ( + "000102030405060708090a0b", + "0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "c0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43", + "cd1aa31662e7ad65d6db", + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", + "0000000e0d0c0ba0a1a2a3a4a5", + ), + ( + "0be1a88bace018b1", + "08e8cf97d820ea258460e96ad9cf5289054d895ceac47c", + "4cb97f86a2a4689a877947ab8091ef5386a6ffbdd080f8", + "e78cf7cb0cddd7b3", + "d7828d13b2b0bdc325a76236df93cc6b", + "00412b4ea9cdbe3c9696766cfa", + ), + ( + "63018f76dc8a1bcb", + "9020ea6f91bdd85afa0039ba4baff9bfb79c7028949cd0ec", + "4ccb1e7ca981befaa0726c55d378061298c85c92814abc33", + "c52ee81d7d77c08a", + "d7828d13b2b0bdc325a76236df93cc6b", + "0033568ef7b2633c9696766cfa", + ), + ( + "aa6cfa36cae86b40", + "b916e0eacc1c00d7dcec68ec0b3bbb1a02de8a2d1aa346132e", + "b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708", + "a776796edb723506", + "d7828d13b2b0bdc325a76236df93cc6b", + "00103fe41336713c9696766cfa", + ), + ( + "d0d0735c531e1becf049c244", + "12daac5630efa5396f770ce1a66b21f7b2101c", + "14d253c3967b70609b7cbb7c49916028324526", + "9a6f49975bcadeaf", + "d7828d13b2b0bdc325a76236df93cc6b", + "00764c63b8058e3c9696766cfa", + ), + ( + "77b60f011c03e1525899bcae", + "e88b6a46c78d63e52eb8c546efb5de6f75e9cc0d", + "5545ff1a085ee2efbf52b2e04bee1e2336c73e3f", + "762c0c7744fe7e3c", + "d7828d13b2b0bdc325a76236df93cc6b", + "00f8b678094e3b3c9696766cfa", + ), + ( + "cd9044d2b71fdb8120ea60c0", + "6435acbafb11a82e2f071d7ca4a5ebd93a803ba87f", + "009769ecabdf48625594c59251e6035722675e04c8", + "47099e5ae0704551", + "d7828d13b2b0bdc325a76236df93cc6b", + "00d560912d3f703c9696766cfa", + ), + ( + "d85bc7e69f944fb8", + "8a19b950bcf71a018e5e6701c91787659809d67dbedd18", + "bc218daa947427b6db386a99ac1aef23ade0b52939cb6a", + "637cf9bec2408897c6ba", + "d7828d13b2b0bdc325a76236df93cc6b", + "0042fff8f1951c3c9696766cfa", + ), + ( + "74a0ebc9069f5b37", + "1761433c37c5a35fc1f39f406302eb907c6163be38c98437", + "5810e6fd25874022e80361a478e3e9cf484ab04f447efff6", + "f0a477cc2fc9bf548944", + "d7828d13b2b0bdc325a76236df93cc6b", + "00920f40e56cdc3c9696766cfa", + ), + ( + "44a3aa3aae6475ca", + "a434a8e58500c6e41530538862d686ea9e81301b5ae4226bfa", + "f2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f154", + "4d4151a4ed3a8b87b9ce", + "d7828d13b2b0bdc325a76236df93cc6b", + "0027ca0c7120bc3c9696766cfa", + ), + ( + "ec46bb63b02520c33c49fd70", + "b96b49e21d621741632875db7f6c9243d2d7c2", + "31d750a09da3ed7fddd49a2032aabf17ec8ebf", + "7d22c8088c666be5c197", + "d7828d13b2b0bdc325a76236df93cc6b", + "005b8ccbcd9af83c9696766cfa", + ), + ( + "47a65ac78b3d594227e85e71", + "e2fcfbb880442c731bf95167c8ffd7895e337076", + "e882f1dbd38ce3eda7c23f04dd65071eb41342ac", + "df7e00dccec7ae52987d", + "d7828d13b2b0bdc325a76236df93cc6b", + "003ebe94044b9a3c9696766cfa", + ), + ( + "6e37a6ef546d955d34ab6059", + "abf21c0b02feb88f856df4a37381bce3cc128517d4", + "f32905b88a641b04b9c9ffb58cc390900f3da12ab1", + "6dce9e82efa16da62059", + "d7828d13b2b0bdc325a76236df93cc6b", + "008d493b30ae8b3c9696766cfa", + ), + ] + + test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, **extra_params): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._extra_params = extra_params - self._id = "None" - - def setUp(self): - - def filter_tag(group): - return group['tagSize'] // 8 - - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aes_ccm_test.json", - "Wycheproof AES CCM", - group_tag={'tag_size': filter_tag}) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt CCM Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - except ValueError as e: - if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e): - assert not tv.valid - return - if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e): - assert not tv.valid - return - raise e - - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt CCM Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - except ValueError as e: - if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e): - assert not tv.valid - return - if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e): - assert not tv.valid - return - raise e - - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def test_corrupt_decrypt(self, tv): - self._id = "Wycheproof Corrupt Decrypt CCM Test #" + str(tv.id) - if len(tv.iv) not in range(7, 13 + 1, 2) or len(tv.ct) == 0: - return - cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - cipher.update(tv.aad) - ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) - self.test_corrupt_decrypt(tv) + def __init__(self, wycheproof_warnings, **extra_params): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._extra_params = extra_params + self._id = "None" + + def setUp(self): + def filter_tag(group): + return group["tagSize"] // 8 + + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aes_ccm_test.json", + "Wycheproof AES CCM", + group_tag={"tag_size": filter_tag}, + ) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt CCM Test #" + str(tv.id) + + try: + cipher = AES.new( + tv.key, + AES.MODE_CCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + except ValueError as e: + if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e): + assert not tv.valid + return + if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e): + assert not tv.valid + return + raise e + + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt CCM Test #" + str(tv.id) + + try: + cipher = AES.new( + tv.key, + AES.MODE_CCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + except ValueError as e: + if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e): + assert not tv.valid + return + if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e): + assert not tv.valid + return + raise e + + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def test_corrupt_decrypt(self, tv): + self._id = "Wycheproof Corrupt Decrypt CCM Test #" + str(tv.id) + if len(tv.iv) not in range(7, 13 + 1, 2) or len(tv.ct) == 0: + return + cipher = AES.new( + tv.key, + AES.MODE_CCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + cipher.update(tv.aad) + ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) + self.test_corrupt_decrypt(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(CcmTests) + tests += list_test_cases(CcmFSMTests) + tests += [TestVectors()] + tests += [TestVectorsWycheproof(wycheproof_warnings)] + + return tests - tests = [] - tests += list_test_cases(CcmTests) - tests += list_test_cases(CcmFSMTests) - tests += [TestVectors()] - tests += [TestVectorsWycheproof(wycheproof_warnings)] - return tests +if __name__ == "__main__": + def suite(): + unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CFB.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CFB.py index 673bf8ed..b3872f6c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CFB.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CFB.py @@ -41,371 +41,421 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class CfbTests(BlockChainingTests): - - aes_mode = AES.MODE_CFB - des3_mode = DES3.MODE_CFB - - # Redefine test_unaligned_data_128/64 - - def test_unaligned_data_128(self): - plaintexts = [ b"7777777" ] * 100 - - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - def test_unaligned_data_64(self): - plaintexts = [ b"7777777" ] * 100 - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - # Extra - - def test_segment_size_128(self): - for bits in range(8, 129, 8): - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, - segment_size=bits) - - for bits in 0, 7, 9, 127, 129: - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CFB, - self.iv_128, - segment_size=bits) - - def test_segment_size_64(self): - for bits in range(8, 65, 8): - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, - segment_size=bits) - - for bits in 0, 7, 9, 63, 65: - self.assertRaises(ValueError, DES3.new, self.key_192, AES.MODE_CFB, - self.iv_64, - segment_size=bits) + aes_mode = AES.MODE_CFB + des3_mode = DES3.MODE_CFB + + # Redefine test_unaligned_data_128/64 + + def test_unaligned_data_128(self): + plaintexts = [b"7777777"] * 100 + + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + def test_unaligned_data_64(self): + plaintexts = [b"7777777"] * 100 + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + # Extra + + def test_segment_size_128(self): + for bits in range(8, 129, 8): + cipher = AES.new( + self.key_128, + AES.MODE_CFB, + self.iv_128, + segment_size=bits, + ) + + for bits in 0, 7, 9, 127, 129: + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CFB, + self.iv_128, + segment_size=bits, + ) + + def test_segment_size_64(self): + for bits in range(8, 65, 8): + cipher = DES3.new( + self.key_192, + DES3.MODE_CFB, + self.iv_64, + segment_size=bits, + ) + + for bits in 0, 7, 9, 63, 65: + self.assertRaises( + ValueError, + DES3.new, + self.key_192, + AES.MODE_CFB, + self.iv_64, + segment_size=bits, + ) class NistCfbVectors(unittest.TestCase): - - def _do_kat_aes_test(self, file_name, segment_size): - - test_vectors = load_test_vectors(("Cipher", "AES"), - file_name, - "AES CFB%d KAT" % segment_size, - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv, - segment_size=segment_size) - if direction == "[ENCRYPT]": - self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) - elif direction == "[DECRYPT]": - self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) - else: - assert False - - # See Section 6.4.5 in AESAVS - def _do_mct_aes_test(self, file_name, segment_size): - - test_vectors = load_test_vectors(("Cipher", "AES"), - file_name, - "AES CFB%d Montecarlo" % segment_size, - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - assert(segment_size in (8, 128)) - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv, - segment_size=segment_size) - - def get_input(input_text, output_seq, j): - # CFB128 - if segment_size == 128: - if j >= 2: - return output_seq[-2] - return [input_text, tv.iv][j] - # CFB8 - if j == 0: - return input_text - elif j <= 16: - return tv.iv[j - 1:j] - return output_seq[j - 17] - - if direction == '[ENCRYPT]': - cts = [] - for j in range(1000): - plaintext = get_input(tv.plaintext, cts, j) - cts.append(cipher.encrypt(plaintext)) - self.assertEqual(cts[-1], tv.ciphertext) - elif direction == '[DECRYPT]': - pts = [] - for j in range(1000): - ciphertext = get_input(tv.ciphertext, pts, j) - pts.append(cipher.decrypt(ciphertext)) - self.assertEqual(pts[-1], tv.plaintext) - else: - assert False - - def _do_tdes_test(self, file_name, segment_size): - - test_vectors = load_test_vectors(("Cipher", "TDES"), - file_name, - "TDES CFB%d KAT" % segment_size, - { "count" : lambda x: int(x) } ) - if test_vectors is None: - return - - direction = None - for tv in test_vectors: - - # The test vector file contains some directive lines - if is_string(tv): - direction = tv - continue - - self.description = tv.desc - if hasattr(tv, "keys"): - cipher = DES.new(tv.keys, DES.MODE_CFB, tv.iv, - segment_size=segment_size) - else: - if tv.key1 != tv.key3: - key = tv.key1 + tv.key2 + tv.key3 # Option 3 - else: - key = tv.key1 + tv.key2 # Option 2 - cipher = DES3.new(key, DES3.MODE_CFB, tv.iv, - segment_size=segment_size) - if direction == "[ENCRYPT]": - self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) - elif direction == "[DECRYPT]": - self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) - else: - assert False + def _do_kat_aes_test(self, file_name, segment_size): + test_vectors = load_test_vectors( + ("Cipher", "AES"), + file_name, + "AES CFB%d KAT" % segment_size, + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + cipher = AES.new( + tv.key, + AES.MODE_CFB, + tv.iv, + segment_size=segment_size, + ) + if direction == "[ENCRYPT]": + self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) + elif direction == "[DECRYPT]": + self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) + else: + assert False + + # See Section 6.4.5 in AESAVS + def _do_mct_aes_test(self, file_name, segment_size): + test_vectors = load_test_vectors( + ("Cipher", "AES"), + file_name, + "AES CFB%d Montecarlo" % segment_size, + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + assert segment_size in (8, 128) + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + cipher = AES.new( + tv.key, + AES.MODE_CFB, + tv.iv, + segment_size=segment_size, + ) + + def get_input(input_text, output_seq, j): + # CFB128 + if segment_size == 128: + if j >= 2: + return output_seq[-2] + return [input_text, tv.iv][j] + # CFB8 + if j == 0: + return input_text + elif j <= 16: + return tv.iv[j - 1 : j] + return output_seq[j - 17] + + if direction == "[ENCRYPT]": + cts = [] + for j in range(1000): + plaintext = get_input(tv.plaintext, cts, j) + cts.append(cipher.encrypt(plaintext)) + self.assertEqual(cts[-1], tv.ciphertext) + elif direction == "[DECRYPT]": + pts = [] + for j in range(1000): + ciphertext = get_input(tv.ciphertext, pts, j) + pts.append(cipher.decrypt(ciphertext)) + self.assertEqual(pts[-1], tv.plaintext) + else: + assert False + + def _do_tdes_test(self, file_name, segment_size): + test_vectors = load_test_vectors( + ("Cipher", "TDES"), + file_name, + "TDES CFB%d KAT" % segment_size, + {"count": lambda x: int(x)}, + ) + if test_vectors is None: + return + + direction = None + for tv in test_vectors: + # The test vector file contains some directive lines + if is_string(tv): + direction = tv + continue + + self.description = tv.desc + if hasattr(tv, "keys"): + cipher = DES.new( + tv.keys, + DES.MODE_CFB, + tv.iv, + segment_size=segment_size, + ) + else: + if tv.key1 != tv.key3: + key = tv.key1 + tv.key2 + tv.key3 # Option 3 + else: + key = tv.key1 + tv.key2 # Option 2 + cipher = DES3.new( + key, + DES3.MODE_CFB, + tv.iv, + segment_size=segment_size, + ) + if direction == "[ENCRYPT]": + self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext) + elif direction == "[DECRYPT]": + self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext) + else: + assert False # Create one test method per file nist_aes_kat_mmt_files = ( - # KAT - "CFB?GFSbox128.rsp", - "CFB?GFSbox192.rsp", - "CFB?GFSbox256.rsp", - "CFB?KeySbox128.rsp", - "CFB?KeySbox192.rsp", - "CFB?KeySbox256.rsp", - "CFB?VarKey128.rsp", - "CFB?VarKey192.rsp", - "CFB?VarKey256.rsp", - "CFB?VarTxt128.rsp", - "CFB?VarTxt192.rsp", - "CFB?VarTxt256.rsp", - # MMT - "CFB?MMT128.rsp", - "CFB?MMT192.rsp", - "CFB?MMT256.rsp", - ) + # KAT + "CFB?GFSbox128.rsp", + "CFB?GFSbox192.rsp", + "CFB?GFSbox256.rsp", + "CFB?KeySbox128.rsp", + "CFB?KeySbox192.rsp", + "CFB?KeySbox256.rsp", + "CFB?VarKey128.rsp", + "CFB?VarKey192.rsp", + "CFB?VarKey256.rsp", + "CFB?VarTxt128.rsp", + "CFB?VarTxt192.rsp", + "CFB?VarTxt256.rsp", + # MMT + "CFB?MMT128.rsp", + "CFB?MMT192.rsp", + "CFB?MMT256.rsp", +) nist_aes_mct_files = ( - "CFB?MCT128.rsp", - "CFB?MCT192.rsp", - "CFB?MCT256.rsp", - ) + "CFB?MCT128.rsp", + "CFB?MCT192.rsp", + "CFB?MCT256.rsp", +) for file_gen_name in nist_aes_kat_mmt_files: - for bits in "8", "128": - file_name = file_gen_name.replace("?", bits) - def new_func(self, file_name=file_name, bits=bits): - self._do_kat_aes_test(file_name, int(bits)) - setattr(NistCfbVectors, "test_AES_" + file_name, new_func) + for bits in "8", "128": + file_name = file_gen_name.replace("?", bits) + + def new_func(self, file_name=file_name, bits=bits): + self._do_kat_aes_test(file_name, int(bits)) + + setattr(NistCfbVectors, "test_AES_" + file_name, new_func) for file_gen_name in nist_aes_mct_files: - for bits in "8", "128": - file_name = file_gen_name.replace("?", bits) - def new_func(self, file_name=file_name, bits=bits): - self._do_mct_aes_test(file_name, int(bits)) - setattr(NistCfbVectors, "test_AES_" + file_name, new_func) + for bits in "8", "128": + file_name = file_gen_name.replace("?", bits) + + def new_func(self, file_name=file_name, bits=bits): + self._do_mct_aes_test(file_name, int(bits)) + + setattr(NistCfbVectors, "test_AES_" + file_name, new_func) del file_name, new_func nist_tdes_files = ( - "TCFB?MMT2.rsp", # 2TDES - "TCFB?MMT3.rsp", # 3TDES - "TCFB?invperm.rsp", # Single DES - "TCFB?permop.rsp", - "TCFB?subtab.rsp", - "TCFB?varkey.rsp", - "TCFB?vartext.rsp", - ) + "TCFB?MMT2.rsp", # 2TDES + "TCFB?MMT3.rsp", # 3TDES + "TCFB?invperm.rsp", # Single DES + "TCFB?permop.rsp", + "TCFB?subtab.rsp", + "TCFB?varkey.rsp", + "TCFB?vartext.rsp", +) for file_gen_name in nist_tdes_files: - for bits in "8", "64": - file_name = file_gen_name.replace("?", bits) - def new_func(self, file_name=file_name, bits=bits): - self._do_tdes_test(file_name, int(bits)) - setattr(NistCfbVectors, "test_TDES_" + file_name, new_func) + for bits in "8", "64": + file_name = file_gen_name.replace("?", bits) + + def new_func(self, file_name=file_name, bits=bits): + self._do_tdes_test(file_name, int(bits)) + + setattr(NistCfbVectors, "test_TDES_" + file_name, new_func) # END OF NIST CBC TEST VECTORS class SP800TestVectors(unittest.TestCase): - """Class exercising the CFB test vectors found in Section F.3 - of NIST SP 800-3A""" - - def test_aes_128_cfb8(self): - plaintext = '6bc1bee22e409f96e93d7e117393172aae2d' - ciphertext = '3b79424c9c0dd436bace9e0ed4586a4f32b9' - key = '2b7e151628aed2a6abf7158809cf4f3c' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_192_cfb8(self): - plaintext = '6bc1bee22e409f96e93d7e117393172aae2d' - ciphertext = 'cda2521ef0a905ca44cd057cbf0d47a0678a' - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_256_cfb8(self): - plaintext = '6bc1bee22e409f96e93d7e117393172aae2d' - ciphertext = 'dc1f1a8520a64db55fcc8ac554844e889700' - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_128_cfb128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '3b3fd92eb72dad20333449f8e83cfb4a' +\ - 'c8a64537a0b3a93fcde3cdad9f1ce58b' +\ - '26751f67a3cbb140b1808cf187a4f4df' +\ - 'c04b05357c5d1c0eeac4c66f9ff7f2e6' - key = '2b7e151628aed2a6abf7158809cf4f3c' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_192_cfb128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = 'cdc80d6fddf18cab34c25909c99a4174' +\ - '67ce7f7f81173621961a2b70171d3d7a' +\ - '2e1e8a1dd59b88b1c8e60fed1efac4c9' +\ - 'c05f9f9ca9834fa042ae8fba584b09ff' - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_256_cfb128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - - ciphertext = 'dc7e84bfda79164b7ecd8486985d3860' +\ - '39ffed143b28b1c832113c6331e5407b' +\ - 'df10132415e54b92a13ed0a8267ae2f9' +\ - '75a385741ab9cef82031623d55b1e471' - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) + """Class exercising the CFB test vectors found in Section F.3 + of NIST SP 800-3A""" + + def test_aes_128_cfb8(self): + plaintext = "6bc1bee22e409f96e93d7e117393172aae2d" + ciphertext = "3b79424c9c0dd436bace9e0ed4586a4f32b9" + key = "2b7e151628aed2a6abf7158809cf4f3c" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_192_cfb8(self): + plaintext = "6bc1bee22e409f96e93d7e117393172aae2d" + ciphertext = "cda2521ef0a905ca44cd057cbf0d47a0678a" + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_256_cfb8(self): + plaintext = "6bc1bee22e409f96e93d7e117393172aae2d" + ciphertext = "dc1f1a8520a64db55fcc8ac554844e889700" + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_128_cfb128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "3b3fd92eb72dad20333449f8e83cfb4a" + + "c8a64537a0b3a93fcde3cdad9f1ce58b" + + "26751f67a3cbb140b1808cf187a4f4df" + + "c04b05357c5d1c0eeac4c66f9ff7f2e6" + ) + key = "2b7e151628aed2a6abf7158809cf4f3c" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_192_cfb128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "cdc80d6fddf18cab34c25909c99a4174" + + "67ce7f7f81173621961a2b70171d3d7a" + + "2e1e8a1dd59b88b1c8e60fed1efac4c9" + + "c05f9f9ca9834fa042ae8fba584b09ff" + ) + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_256_cfb128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + + ciphertext = ( + "dc7e84bfda79164b7ecd8486985d3860" + + "39ffed143b28b1c832113c6331e5407b" + + "df10132415e54b92a13ed0a8267ae2f9" + + "75a385741ab9cef82031623d55b1e471" + ) + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) def get_tests(config={}): - tests = [] - tests += list_test_cases(CfbTests) - if config.get('slow_tests'): - tests += list_test_cases(NistCfbVectors) - tests += list_test_cases(SP800TestVectors) - return tests + tests = [] + tests += list_test_cases(CfbTests) + if config.get("slow_tests"): + tests += list_test_cases(NistCfbVectors) + tests += list_test_cases(SP800TestVectors) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CTR.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CTR.py index ef5be5d0..466a17d4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CTR.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_CTR.py @@ -37,436 +37,552 @@ from Cryptodome.Hash import SHAKE128, SHA256 from Cryptodome.Util import Counter -def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) - -class CtrTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - key_192 = get_tag_random("key_192", 24) - nonce_32 = get_tag_random("nonce_32", 4) - nonce_64 = get_tag_random("nonce_64", 8) - ctr_64 = Counter.new(32, prefix=nonce_32) - ctr_128 = Counter.new(64, prefix=nonce_64) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_loopback_64(self): - cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) - pt = get_tag_random("plaintext", 8 * 100) - ct = cipher.encrypt(pt) - - cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_invalid_counter_parameter(self): - # Counter object is required for ciphers with short block size - self.assertRaises(TypeError, DES3.new, self.key_192, AES.MODE_CTR) - # Positional arguments are not allowed (Counter must be passed as - # keyword) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, self.ctr_128) - - def test_nonce_attribute(self): - # Nonce attribute is the prefix passed to Counter (DES3) - cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) - self.assertEqual(cipher.nonce, self.nonce_32) - - # Nonce attribute is the prefix passed to Counter (AES) - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - self.assertEqual(cipher.nonce, self.nonce_64) - - # Nonce attribute is not defined if suffix is used in Counter - counter = Counter.new(64, prefix=self.nonce_32, suffix=self.nonce_32) - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - self.assertFalse(hasattr(cipher, "nonce")) - - def test_nonce_parameter(self): - # Nonce parameter becomes nonce attribute - cipher1 = AES.new(self.key_128, AES.MODE_CTR, nonce=self.nonce_64) - self.assertEqual(cipher1.nonce, self.nonce_64) - - counter = Counter.new(64, prefix=self.nonce_64, initial_value=0) - cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - pt = get_tag_random("plaintext", 65536) - self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) - - # Nonce is implicitly created (for AES) when no parameters are passed - nonce1 = AES.new(self.key_128, AES.MODE_CTR).nonce - nonce2 = AES.new(self.key_128, AES.MODE_CTR).nonce - self.assertNotEqual(nonce1, nonce2) - self.assertEqual(len(nonce1), 8) - - # Nonce can be zero-length - cipher = AES.new(self.key_128, AES.MODE_CTR, nonce=b"") - self.assertEqual(b"", cipher.nonce) - cipher.encrypt(b'0'*300) - - # Nonce and Counter are mutually exclusive - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, - counter=self.ctr_128, nonce=self.nonce_64) - - def test_initial_value_parameter(self): - # Test with nonce parameter - cipher1 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, initial_value=0xFFFF) - counter = Counter.new(64, prefix=self.nonce_64, initial_value=0xFFFF) - cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - pt = get_tag_random("plaintext", 65536) - self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) - - # Test without nonce parameter - cipher1 = AES.new(self.key_128, AES.MODE_CTR, - initial_value=0xFFFF) - counter = Counter.new(64, prefix=cipher1.nonce, initial_value=0xFFFF) - cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - pt = get_tag_random("plaintext", 65536) - self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) - - # Initial_value and Counter are mutually exclusive - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, - counter=self.ctr_128, initial_value=0) - - def test_initial_value_bytes_parameter(self): - # Same result as when passing an integer - cipher1 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, - initial_value=b"\x00"*6+b"\xFF\xFF") - cipher2 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, initial_value=0xFFFF) - pt = get_tag_random("plaintext", 65536) - self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) - - # Fail if the iv is too large - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - initial_value=b"5"*17) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, initial_value=b"5"*9) - - # Fail if the iv is too short - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - initial_value=b"5"*15) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, initial_value=b"5"*7) - - def test_iv_with_matching_length(self): - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - counter=Counter.new(120)) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR, - counter=Counter.new(136)) - - def test_block_size_128(self): - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_block_size_64(self): - cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) - self.assertEqual(cipher.block_size, DES3.block_size) - - def test_unaligned_data_128(self): - plaintexts = [ b"7777777" ] * 100 - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - def test_unaligned_data_64(self): - plaintexts = [ b"7777777" ] * 100 - cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, - 7, counter=self.ctr_128) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, - counter=self.ctr_128, unknown=7) - # But some are only known by the base cipher (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128, use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_wrap_around(self): - # Counter is only 8 bits, so we can only encrypt/decrypt 256 blocks (=4096 bytes) - counter = Counter.new(8, prefix=bchr(9) * 15) - max_bytes = 4096 - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - cipher.encrypt(b'9' * max_bytes) - self.assertRaises(OverflowError, cipher.encrypt, b'9') - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - self.assertRaises(OverflowError, cipher.encrypt, b'9' * (max_bytes + 1)) - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - cipher.decrypt(b'9' * max_bytes) - self.assertRaises(OverflowError, cipher.decrypt, b'9') - - cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) - self.assertRaises(OverflowError, cipher.decrypt, b'9' * (max_bytes + 1)) - - def test_bytearray(self): - data = b"1" * 16 - iv = b"\x00" * 6 + b"\xFF\xFF" - - # Encrypt - cipher1 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, - initial_value=iv) - ref1 = cipher1.encrypt(data) - - cipher2 = AES.new(self.key_128, AES.MODE_CTR, - nonce=bytearray(self.nonce_64), - initial_value=bytearray(iv)) - ref2 = cipher2.encrypt(bytearray(data)) - - self.assertEqual(ref1, ref2) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - cipher3 = AES.new(self.key_128, AES.MODE_CTR, - nonce=self.nonce_64, - initial_value=iv) - ref3 = cipher3.decrypt(data) - - cipher4 = AES.new(self.key_128, AES.MODE_CTR, - nonce=bytearray(self.nonce_64), - initial_value=bytearray(iv)) - ref4 = cipher4.decrypt(bytearray(data)) - - self.assertEqual(ref3, ref4) - - def test_very_long_data(self): - cipher = AES.new(b'A' * 32, AES.MODE_CTR, nonce=b'') - ct = cipher.encrypt(b'B' * 1000000) - digest = SHA256.new(ct).hexdigest() - self.assertEqual(digest, "96204fc470476561a3a8f3b6fe6d24be85c87510b638142d1d0fb90989f8a6a6") - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - ct = cipher.encrypt(pt) - - output = bytearray(128) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - def test_output_param_neg(self): - LEN_PT = 128 - - pt = b'5' * LEN_PT - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - ct = cipher.encrypt(pt) - - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT) +def get_tag_random(tag, length): + return SHAKE128.new(data=tobytes(tag)).read(length) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT) - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) +class CtrTests(unittest.TestCase): + key_128 = get_tag_random("key_128", 16) + key_192 = get_tag_random("key_192", 24) + nonce_32 = get_tag_random("nonce_32", 4) + nonce_64 = get_tag_random("nonce_64", 8) + ctr_64 = Counter.new(32, prefix=nonce_32) + ctr_128 = Counter.new(64, prefix=nonce_64) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_loopback_64(self): + cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) + pt = get_tag_random("plaintext", 8 * 100) + ct = cipher.encrypt(pt) + + cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_invalid_counter_parameter(self): + # Counter object is required for ciphers with short block size + self.assertRaises(TypeError, DES3.new, self.key_192, AES.MODE_CTR) + # Positional arguments are not allowed (Counter must be passed as + # keyword) + self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, self.ctr_128) + + def test_nonce_attribute(self): + # Nonce attribute is the prefix passed to Counter (DES3) + cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) + self.assertEqual(cipher.nonce, self.nonce_32) + + # Nonce attribute is the prefix passed to Counter (AES) + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + self.assertEqual(cipher.nonce, self.nonce_64) + + # Nonce attribute is not defined if suffix is used in Counter + counter = Counter.new(64, prefix=self.nonce_32, suffix=self.nonce_32) + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + self.assertFalse(hasattr(cipher, "nonce")) + + def test_nonce_parameter(self): + # Nonce parameter becomes nonce attribute + cipher1 = AES.new(self.key_128, AES.MODE_CTR, nonce=self.nonce_64) + self.assertEqual(cipher1.nonce, self.nonce_64) + + counter = Counter.new(64, prefix=self.nonce_64, initial_value=0) + cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + pt = get_tag_random("plaintext", 65536) + self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) + + # Nonce is implicitly created (for AES) when no parameters are passed + nonce1 = AES.new(self.key_128, AES.MODE_CTR).nonce + nonce2 = AES.new(self.key_128, AES.MODE_CTR).nonce + self.assertNotEqual(nonce1, nonce2) + self.assertEqual(len(nonce1), 8) + + # Nonce can be zero-length + cipher = AES.new(self.key_128, AES.MODE_CTR, nonce=b"") + self.assertEqual(b"", cipher.nonce) + cipher.encrypt(b"0" * 300) + + # Nonce and Counter are mutually exclusive + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=self.ctr_128, + nonce=self.nonce_64, + ) + + def test_initial_value_parameter(self): + # Test with nonce parameter + cipher1 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=0xFFFF, + ) + counter = Counter.new(64, prefix=self.nonce_64, initial_value=0xFFFF) + cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + pt = get_tag_random("plaintext", 65536) + self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) + + # Test without nonce parameter + cipher1 = AES.new( + self.key_128, + AES.MODE_CTR, + initial_value=0xFFFF, + ) + counter = Counter.new(64, prefix=cipher1.nonce, initial_value=0xFFFF) + cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + pt = get_tag_random("plaintext", 65536) + self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) + + # Initial_value and Counter are mutually exclusive + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=self.ctr_128, + initial_value=0, + ) + + def test_initial_value_bytes_parameter(self): + # Same result as when passing an integer + cipher1 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=b"\x00" * 6 + b"\xff\xff", + ) + cipher2 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=0xFFFF, + ) + pt = get_tag_random("plaintext", 65536) + self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt)) + + # Fail if the iv is too large + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + initial_value=b"5" * 17, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=b"5" * 9, + ) + + # Fail if the iv is too short + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + initial_value=b"5" * 15, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=b"5" * 7, + ) + + def test_iv_with_matching_length(self): + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=Counter.new(120), + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=Counter.new(136), + ) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_block_size_64(self): + cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64) + self.assertEqual(cipher.block_size, DES3.block_size) + + def test_unaligned_data_128(self): + plaintexts = [b"7777777"] * 100 + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + def test_unaligned_data_64(self): + plaintexts = [b"7777777"] * 100 + cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CTR, + 7, + counter=self.ctr_128, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_CTR, + counter=self.ctr_128, + unknown=7, + ) + # But some are only known by the base cipher (e.g. use_aesni consumed by the AES module) + AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128, use_aesni=False) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_wrap_around(self): + # Counter is only 8 bits, so we can only encrypt/decrypt 256 blocks (=4096 bytes) + counter = Counter.new(8, prefix=bchr(9) * 15) + max_bytes = 4096 + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + cipher.encrypt(b"9" * max_bytes) + self.assertRaises(OverflowError, cipher.encrypt, b"9") + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + self.assertRaises(OverflowError, cipher.encrypt, b"9" * (max_bytes + 1)) + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + cipher.decrypt(b"9" * max_bytes) + self.assertRaises(OverflowError, cipher.decrypt, b"9") + + cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter) + self.assertRaises(OverflowError, cipher.decrypt, b"9" * (max_bytes + 1)) + + def test_bytearray(self): + data = b"1" * 16 + iv = b"\x00" * 6 + b"\xff\xff" + + # Encrypt + cipher1 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=iv, + ) + ref1 = cipher1.encrypt(data) + + cipher2 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=bytearray(self.nonce_64), + initial_value=bytearray(iv), + ) + ref2 = cipher2.encrypt(bytearray(data)) + + self.assertEqual(ref1, ref2) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + cipher3 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=self.nonce_64, + initial_value=iv, + ) + ref3 = cipher3.decrypt(data) + + cipher4 = AES.new( + self.key_128, + AES.MODE_CTR, + nonce=bytearray(self.nonce_64), + initial_value=bytearray(iv), + ) + ref4 = cipher4.decrypt(bytearray(data)) + + self.assertEqual(ref3, ref4) + + def test_very_long_data(self): + cipher = AES.new(b"A" * 32, AES.MODE_CTR, nonce=b"") + ct = cipher.encrypt(b"B" * 1000000) + digest = SHA256.new(ct).hexdigest() + self.assertEqual(digest, "96204fc470476561a3a8f3b6fe6d24be85c87510b638142d1d0fb90989f8a6a6") + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + ct = cipher.encrypt(pt) + + output = bytearray(128) + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + ct = cipher.encrypt(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + LEN_PT = 128 + + pt = b"5" * LEN_PT + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + ct = cipher.encrypt(pt) + + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * LEN_PT) + + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * LEN_PT) + + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(b"4" * 16, AES.MODE_CTR, nonce=self.nonce_64) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) class SP800TestVectors(unittest.TestCase): - """Class exercising the CTR test vectors found in Section F.5 - of NIST SP 800-38A""" - - def test_aes_128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '874d6191b620e3261bef6864990db6ce' +\ - '9806f66b7970fdff8617187bb9fffdff' +\ - '5ae4df3edbd5d35e5b4f09020db03eab' +\ - '1e031dda2fbe03d1792170a0f3009cee' - key = '2b7e151628aed2a6abf7158809cf4f3c' - counter = Counter.new(nbits=16, - prefix=unhexlify('f0f1f2f3f4f5f6f7f8f9fafbfcfd'), - initial_value=0xfeff) - - key = unhexlify(key) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_192(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '1abc932417521ca24f2b0459fe7e6e0b' +\ - '090339ec0aa6faefd5ccc2c6f4ce8e94' +\ - '1e36b26bd1ebc670d1bd1d665620abf7' +\ - '4f78a7f6d29809585a97daec58c6b050' - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - counter = Counter.new(nbits=16, - prefix=unhexlify('f0f1f2f3f4f5f6f7f8f9fafbfcfd'), - initial_value=0xfeff) - - key = unhexlify(key) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - def test_aes_256(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '601ec313775789a5b7a7f504bbf3d228' +\ - 'f443e3ca4d62b59aca84e990cacaf5c5' +\ - '2b0930daa23de94ce87017ba2d84988d' +\ - 'dfc9c58db67aada613c2dd08457941a6' - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - counter = Counter.new(nbits=16, - prefix=unhexlify('f0f1f2f3f4f5f6f7f8f9fafbfcfd'), - initial_value=0xfeff) - key = unhexlify(key) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) + """Class exercising the CTR test vectors found in Section F.5 + of NIST SP 800-38A""" + + def test_aes_128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "874d6191b620e3261bef6864990db6ce" + + "9806f66b7970fdff8617187bb9fffdff" + + "5ae4df3edbd5d35e5b4f09020db03eab" + + "1e031dda2fbe03d1792170a0f3009cee" + ) + key = "2b7e151628aed2a6abf7158809cf4f3c" + counter = Counter.new( + nbits=16, + prefix=unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfd"), + initial_value=0xFEFF, + ) + + key = unhexlify(key) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_192(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "1abc932417521ca24f2b0459fe7e6e0b" + + "090339ec0aa6faefd5ccc2c6f4ce8e94" + + "1e36b26bd1ebc670d1bd1d665620abf7" + + "4f78a7f6d29809585a97daec58c6b050" + ) + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + counter = Counter.new( + nbits=16, + prefix=unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfd"), + initial_value=0xFEFF, + ) + + key = unhexlify(key) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + def test_aes_256(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "601ec313775789a5b7a7f504bbf3d228" + + "f443e3ca4d62b59aca84e990cacaf5c5" + + "2b0930daa23de94ce87017ba2d84988d" + + "dfc9c58db67aada613c2dd08457941a6" + ) + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + counter = Counter.new( + nbits=16, + prefix=unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfd"), + initial_value=0xFEFF, + ) + key = unhexlify(key) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) class RFC3686TestVectors(unittest.TestCase): - - # Each item is a test vector with: - # - plaintext - # - ciphertext - # - key (AES 128, 192 or 256 bits) - # - counter prefix (4 byte nonce + 8 byte nonce) - data = ( - ('53696e676c6520626c6f636b206d7367', - 'e4095d4fb7a7b3792d6175a3261311b8', - 'ae6852f8121067cc4bf7a5765577f39e', - '000000300000000000000000'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '5104a106168a72d9790d41ee8edad388eb2e1efc46da57c8fce630df9141be28', - '7e24067817fae0d743d6ce1f32539163', - '006cb6dbc0543b59da48d90b'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223', - 'c1cf48a89f2ffdd9cf4652e9efdb72d74540a42bde6d7836d59a5ceaaef3105325b2072f', - '7691be035e5020a8ac6e618529f9a0dc', - '00e0017b27777f3f4a1786f0'), - ('53696e676c6520626c6f636b206d7367', - '4b55384fe259c9c84e7935a003cbe928', - '16af5b145fc9f579c175f93e3bfb0eed863d06ccfdb78515', - '0000004836733c147d6d93cb'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '453243fc609b23327edfaafa7131cd9f8490701c5ad4a79cfc1fe0ff42f4fb00', - '7c5cb2401b3dc33c19e7340819e0f69c678c3db8e6f6a91a', - '0096b03b020c6eadc2cb500d'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223', - '96893fc55e5c722f540b7dd1ddf7e758d288bc95c69165884536c811662f2188abee0935', - '02bf391ee8ecb159b959617b0965279bf59b60a786d3e0fe', - '0007bdfd5cbd60278dcc0912'), - ('53696e676c6520626c6f636b206d7367', - '145ad01dbf824ec7560863dc71e3e0c0', - '776beff2851db06f4c8a0542c8696f6c6a81af1eec96b4d37fc1d689e6c1c104', - '00000060db5672c97aa8f0b2'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - 'f05e231b3894612c49ee000b804eb2a9b8306b508f839d6a5530831d9344af1c', - 'f6d66d6bd52d59bb0796365879eff886c66dd51a5b6a99744b50590c87a23884', - '00faac24c1585ef15a43d875'), - ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223', - 'eb6c52821d0bbbf7ce7594462aca4faab407df866569fd07f48cc0b583d6071f1ec0e6b8', - 'ff7a617ce69148e4f1726e2f43581de2aa62d9f805532edff1eed687fb54153d', - '001cc5b751a51d70a1c11148') - ) - - bindata = [] - for tv in data: - bindata.append([unhexlify(x) for x in tv]) - - def runTest(self): - for pt, ct, key, prefix in self.bindata: - counter = Counter.new(32, prefix=prefix) - cipher = AES.new(key, AES.MODE_CTR, counter=counter) - result = cipher.encrypt(pt) - self.assertEqual(hexlify(ct), hexlify(result)) + # Each item is a test vector with: + # - plaintext + # - ciphertext + # - key (AES 128, 192 or 256 bits) + # - counter prefix (4 byte nonce + 8 byte nonce) + data = ( + ( + "53696e676c6520626c6f636b206d7367", + "e4095d4fb7a7b3792d6175a3261311b8", + "ae6852f8121067cc4bf7a5765577f39e", + "000000300000000000000000", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "5104a106168a72d9790d41ee8edad388eb2e1efc46da57c8fce630df9141be28", + "7e24067817fae0d743d6ce1f32539163", + "006cb6dbc0543b59da48d90b", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", + "c1cf48a89f2ffdd9cf4652e9efdb72d74540a42bde6d7836d59a5ceaaef3105325b2072f", + "7691be035e5020a8ac6e618529f9a0dc", + "00e0017b27777f3f4a1786f0", + ), + ( + "53696e676c6520626c6f636b206d7367", + "4b55384fe259c9c84e7935a003cbe928", + "16af5b145fc9f579c175f93e3bfb0eed863d06ccfdb78515", + "0000004836733c147d6d93cb", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "453243fc609b23327edfaafa7131cd9f8490701c5ad4a79cfc1fe0ff42f4fb00", + "7c5cb2401b3dc33c19e7340819e0f69c678c3db8e6f6a91a", + "0096b03b020c6eadc2cb500d", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", + "96893fc55e5c722f540b7dd1ddf7e758d288bc95c69165884536c811662f2188abee0935", + "02bf391ee8ecb159b959617b0965279bf59b60a786d3e0fe", + "0007bdfd5cbd60278dcc0912", + ), + ( + "53696e676c6520626c6f636b206d7367", + "145ad01dbf824ec7560863dc71e3e0c0", + "776beff2851db06f4c8a0542c8696f6c6a81af1eec96b4d37fc1d689e6c1c104", + "00000060db5672c97aa8f0b2", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "f05e231b3894612c49ee000b804eb2a9b8306b508f839d6a5530831d9344af1c", + "f6d66d6bd52d59bb0796365879eff886c66dd51a5b6a99744b50590c87a23884", + "00faac24c1585ef15a43d875", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", + "eb6c52821d0bbbf7ce7594462aca4faab407df866569fd07f48cc0b583d6071f1ec0e6b8", + "ff7a617ce69148e4f1726e2f43581de2aa62d9f805532edff1eed687fb54153d", + "001cc5b751a51d70a1c11148", + ), + ) + + bindata = [] + for tv in data: + bindata.append([unhexlify(x) for x in tv]) + + def runTest(self): + for pt, ct, key, prefix in self.bindata: + counter = Counter.new(32, prefix=prefix) + cipher = AES.new(key, AES.MODE_CTR, counter=counter) + result = cipher.encrypt(pt) + self.assertEqual(hexlify(ct), hexlify(result)) def get_tests(config={}): - tests = [] - tests += list_test_cases(CtrTests) - tests += list_test_cases(SP800TestVectors) - tests += [ RFC3686TestVectors() ] - return tests + tests = [] + tests += list_test_cases(CtrTests) + tests += list_test_cases(SP800TestVectors) + tests += [RFC3686TestVectors()] + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ChaCha20.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ChaCha20.py index 92c6f3cf..979e73a4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ChaCha20.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ChaCha20.py @@ -28,264 +28,262 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -import os -import re import unittest -from binascii import hexlify, unhexlify +from binascii import unhexlify -from Cryptodome.Util.py3compat import b, tobytes, bchr -from Cryptodome.Util.strxor import strxor_c +from Cryptodome.Util.py3compat import b, bchr from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Cipher import ChaCha20 class ChaCha20Test(unittest.TestCase): - - def test_new_positive(self): - cipher = ChaCha20.new(key=b("0")*32, nonce=b"0"*8) - self.assertEqual(cipher.nonce, b"0" * 8) - cipher = ChaCha20.new(key=b("0")*32, nonce=b"0"*12) - self.assertEqual(cipher.nonce, b"0" * 12) - - def test_new_negative(self): - new = ChaCha20.new - self.assertRaises(TypeError, new) - self.assertRaises(TypeError, new, nonce=b("0")) - self.assertRaises(ValueError, new, nonce=b("0")*8, key=b("0")) - self.assertRaises(ValueError, new, nonce=b("0"), key=b("0")*32) - - def test_default_nonce(self): - cipher1 = ChaCha20.new(key=bchr(1) * 32) - cipher2 = ChaCha20.new(key=bchr(1) * 32) - self.assertEqual(len(cipher1.nonce), 8) - self.assertNotEqual(cipher1.nonce, cipher2.nonce) - - def test_nonce(self): - key = b'A' * 32 - - nonce1 = b'P' * 8 - cipher1 = ChaCha20.new(key=key, nonce=nonce1) - self.assertEqual(nonce1, cipher1.nonce) - - nonce2 = b'Q' * 12 - cipher2 = ChaCha20.new(key=key, nonce=nonce2) - self.assertEqual(nonce2, cipher2.nonce) - - def test_eiter_encrypt_or_decrypt(self): - """Verify that a cipher cannot be used for both decrypting and encrypting""" - - c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) - c1.encrypt(b("8")) - self.assertRaises(TypeError, c1.decrypt, b("9")) - - c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) - c2.decrypt(b("8")) - self.assertRaises(TypeError, c2.encrypt, b("9")) - - def test_round_trip(self): - pt = b("A") * 1024 - c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) - c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) - ct = c1.encrypt(pt) - self.assertEqual(c2.decrypt(ct), pt) - - self.assertEqual(c1.encrypt(b("")), b("")) - self.assertEqual(c2.decrypt(b("")), b("")) - - def test_streaming(self): - """Verify that an arbitrary number of bytes can be encrypted/decrypted""" - from Cryptodome.Hash import SHA1 - - segments = (1, 3, 5, 7, 11, 17, 23) - total = sum(segments) - - pt = b("") - while len(pt) < total: - pt += SHA1.new(pt).digest() - - cipher1 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) - ct = cipher1.encrypt(pt) - - cipher2 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) - cipher3 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) - idx = 0 - for segment in segments: - self.assertEqual(cipher2.decrypt(ct[idx:idx+segment]), pt[idx:idx+segment]) - self.assertEqual(cipher3.encrypt(pt[idx:idx+segment]), ct[idx:idx+segment]) - idx += segment - - def test_seek(self): - cipher1 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8) - - offset = 64 * 900 + 7 - pt = b("1") * 64 - - cipher1.encrypt(b("0") * offset) - ct1 = cipher1.encrypt(pt) - - cipher2 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8) - cipher2.seek(offset) - ct2 = cipher2.encrypt(pt) - - self.assertEqual(ct1, ct2) - - def test_seek_tv(self): - # Test Vector #4, A.1 from - # http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 - key = bchr(0) + bchr(255) + bchr(0) * 30 - nonce = bchr(0) * 8 - cipher = ChaCha20.new(key=key, nonce=nonce) - cipher.seek(64 * 2) - expected_key_stream = unhexlify(b( - "72d54dfbf12ec44b362692df94137f32" - "8fea8da73990265ec1bbbea1ae9af0ca" - "13b25aa26cb4a648cb9b9d1be65b2c09" - "24a66c54d545ec1b7374f4872e99f096" - )) - ct = cipher.encrypt(bchr(0) * len(expected_key_stream)) - self.assertEqual(expected_key_stream, ct) - - def test_rfc7539(self): - # from https://tools.ietf.org/html/rfc7539 Annex A.1 - # Each item is: key, nonce, block #, plaintext, ciphertext - tvs = [ - # Test Vector #1 - ( - "00"*32, - "00"*12, - 0, - "00"*16*4, - "76b8e0ada0f13d90405d6ae55386bd28" - "bdd219b8a08ded1aa836efcc8b770dc7" - "da41597c5157488d7724e03fb8d84a37" - "6a43b8f41518a11cc387b669b2ee6586" - ), - # Test Vector #2 - ( - "00"*31 + "01", - "00"*11 + "02", - 1, - "416e79207375626d697373696f6e2074" - "6f20746865204945544620696e74656e" - "6465642062792074686520436f6e7472" - "696275746f7220666f72207075626c69" - "636174696f6e20617320616c6c206f72" - "2070617274206f6620616e2049455446" - "20496e7465726e65742d447261667420" - "6f722052464320616e6420616e792073" - "746174656d656e74206d616465207769" - "7468696e2074686520636f6e74657874" - "206f6620616e20494554462061637469" - "7669747920697320636f6e7369646572" - "656420616e20224945544620436f6e74" - "7269627574696f6e222e205375636820" - "73746174656d656e747320696e636c75" - "6465206f72616c2073746174656d656e" - "747320696e2049455446207365737369" - "6f6e732c2061732077656c6c20617320" - "7772697474656e20616e6420656c6563" - "74726f6e696320636f6d6d756e696361" - "74696f6e73206d61646520617420616e" - "792074696d65206f7220706c6163652c" - "20776869636820617265206164647265" - "7373656420746f", - "a3fbf07df3fa2fde4f376ca23e827370" - "41605d9f4f4f57bd8cff2c1d4b7955ec" - "2a97948bd3722915c8f3d337f7d37005" - "0e9e96d647b7c39f56e031ca5eb6250d" - "4042e02785ececfa4b4bb5e8ead0440e" - "20b6e8db09d881a7c6132f420e527950" - "42bdfa7773d8a9051447b3291ce1411c" - "680465552aa6c405b7764d5e87bea85a" - "d00f8449ed8f72d0d662ab052691ca66" - "424bc86d2df80ea41f43abf937d3259d" - "c4b2d0dfb48a6c9139ddd7f76966e928" - "e635553ba76c5c879d7b35d49eb2e62b" - "0871cdac638939e25e8a1e0ef9d5280f" - "a8ca328b351c3c765989cbcf3daa8b6c" - "cc3aaf9f3979c92b3720fc88dc95ed84" - "a1be059c6499b9fda236e7e818b04b0b" - "c39c1e876b193bfe5569753f88128cc0" - "8aaa9b63d1a16f80ef2554d7189c411f" - "5869ca52c5b83fa36ff216b9c1d30062" - "bebcfd2dc5bce0911934fda79a86f6e6" - "98ced759c3ff9b6477338f3da4f9cd85" - "14ea9982ccafb341b2384dd902f3d1ab" - "7ac61dd29c6f21ba5b862f3730e37cfd" - "c4fd806c22f221" - ), - # Test Vector #3 - ( - "1c9240a5eb55d38af333888604f6b5f0" - "473917c1402b80099dca5cbc207075c0", - "00"*11 + "02", - 42, - "2754776173206272696c6c69672c2061" - "6e642074686520736c6974687920746f" - "7665730a446964206779726520616e64" - "2067696d626c6520696e207468652077" - "6162653a0a416c6c206d696d73792077" - "6572652074686520626f726f676f7665" - "732c0a416e6420746865206d6f6d6520" - "7261746873206f757467726162652e", - "62e6347f95ed87a45ffae7426f27a1df" - "5fb69110044c0d73118effa95b01e5cf" - "166d3df2d721caf9b21e5fb14c616871" - "fd84c54f9d65b283196c7fe4f60553eb" - "f39c6402c42234e32a356b3e764312a6" - "1a5532055716ead6962568f87d3f3f77" - "04c6a8d1bcd1bf4d50d6154b6da731b1" - "87b58dfd728afa36757a797ac188d1" - ) - ] - - for tv in tvs: - key = unhexlify(tv[0]) - nonce = unhexlify(tv[1]) - offset = tv[2] * 64 - pt = unhexlify(tv[3]) - ct_expect = unhexlify(tv[4]) - - cipher = ChaCha20.new(key=key, nonce=nonce) - if offset != 0: - cipher.seek(offset) - ct = cipher.encrypt(pt) - assert(ct == ct_expect) + def test_new_positive(self): + cipher = ChaCha20.new(key=b("0") * 32, nonce=b"0" * 8) + self.assertEqual(cipher.nonce, b"0" * 8) + cipher = ChaCha20.new(key=b("0") * 32, nonce=b"0" * 12) + self.assertEqual(cipher.nonce, b"0" * 12) + + def test_new_negative(self): + new = ChaCha20.new + self.assertRaises(TypeError, new) + self.assertRaises(TypeError, new, nonce=b("0")) + self.assertRaises(ValueError, new, nonce=b("0") * 8, key=b("0")) + self.assertRaises(ValueError, new, nonce=b("0"), key=b("0") * 32) + + def test_default_nonce(self): + cipher1 = ChaCha20.new(key=bchr(1) * 32) + cipher2 = ChaCha20.new(key=bchr(1) * 32) + self.assertEqual(len(cipher1.nonce), 8) + self.assertNotEqual(cipher1.nonce, cipher2.nonce) + + def test_nonce(self): + key = b"A" * 32 + + nonce1 = b"P" * 8 + cipher1 = ChaCha20.new(key=key, nonce=nonce1) + self.assertEqual(nonce1, cipher1.nonce) + + nonce2 = b"Q" * 12 + cipher2 = ChaCha20.new(key=key, nonce=nonce2) + self.assertEqual(nonce2, cipher2.nonce) + + def test_eiter_encrypt_or_decrypt(self): + """Verify that a cipher cannot be used for both decrypting and encrypting""" + + c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) + c1.encrypt(b("8")) + self.assertRaises(TypeError, c1.decrypt, b("9")) + + c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) + c2.decrypt(b("8")) + self.assertRaises(TypeError, c2.encrypt, b("9")) + + def test_round_trip(self): + pt = b("A") * 1024 + c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) + c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8) + ct = c1.encrypt(pt) + self.assertEqual(c2.decrypt(ct), pt) + + self.assertEqual(c1.encrypt(b("")), b("")) + self.assertEqual(c2.decrypt(b("")), b("")) + + def test_streaming(self): + """Verify that an arbitrary number of bytes can be encrypted/decrypted""" + from Cryptodome.Hash import SHA1 + + segments = (1, 3, 5, 7, 11, 17, 23) + total = sum(segments) + + pt = b("") + while len(pt) < total: + pt += SHA1.new(pt).digest() + + cipher1 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) + ct = cipher1.encrypt(pt) + + cipher2 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) + cipher3 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8) + idx = 0 + for segment in segments: + self.assertEqual(cipher2.decrypt(ct[idx : idx + segment]), pt[idx : idx + segment]) + self.assertEqual(cipher3.encrypt(pt[idx : idx + segment]), ct[idx : idx + segment]) + idx += segment + + def test_seek(self): + cipher1 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8) + + offset = 64 * 900 + 7 + pt = b("1") * 64 + + cipher1.encrypt(b("0") * offset) + ct1 = cipher1.encrypt(pt) + + cipher2 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8) + cipher2.seek(offset) + ct2 = cipher2.encrypt(pt) + + self.assertEqual(ct1, ct2) + + def test_seek_tv(self): + # Test Vector #4, A.1 from + # http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + key = bchr(0) + bchr(255) + bchr(0) * 30 + nonce = bchr(0) * 8 + cipher = ChaCha20.new(key=key, nonce=nonce) + cipher.seek(64 * 2) + expected_key_stream = unhexlify( + b( + "72d54dfbf12ec44b362692df94137f32" + "8fea8da73990265ec1bbbea1ae9af0ca" + "13b25aa26cb4a648cb9b9d1be65b2c09" + "24a66c54d545ec1b7374f4872e99f096", + ), + ) + ct = cipher.encrypt(bchr(0) * len(expected_key_stream)) + self.assertEqual(expected_key_stream, ct) + + def test_rfc7539(self): + # from https://tools.ietf.org/html/rfc7539 Annex A.1 + # Each item is: key, nonce, block #, plaintext, ciphertext + tvs = [ + # Test Vector #1 + ( + "00" * 32, + "00" * 12, + 0, + "00" * 16 * 4, + "76b8e0ada0f13d90405d6ae55386bd28" + "bdd219b8a08ded1aa836efcc8b770dc7" + "da41597c5157488d7724e03fb8d84a37" + "6a43b8f41518a11cc387b669b2ee6586", + ), + # Test Vector #2 + ( + "00" * 31 + "01", + "00" * 11 + "02", + 1, + "416e79207375626d697373696f6e2074" + "6f20746865204945544620696e74656e" + "6465642062792074686520436f6e7472" + "696275746f7220666f72207075626c69" + "636174696f6e20617320616c6c206f72" + "2070617274206f6620616e2049455446" + "20496e7465726e65742d447261667420" + "6f722052464320616e6420616e792073" + "746174656d656e74206d616465207769" + "7468696e2074686520636f6e74657874" + "206f6620616e20494554462061637469" + "7669747920697320636f6e7369646572" + "656420616e20224945544620436f6e74" + "7269627574696f6e222e205375636820" + "73746174656d656e747320696e636c75" + "6465206f72616c2073746174656d656e" + "747320696e2049455446207365737369" + "6f6e732c2061732077656c6c20617320" + "7772697474656e20616e6420656c6563" + "74726f6e696320636f6d6d756e696361" + "74696f6e73206d61646520617420616e" + "792074696d65206f7220706c6163652c" + "20776869636820617265206164647265" + "7373656420746f", + "a3fbf07df3fa2fde4f376ca23e827370" + "41605d9f4f4f57bd8cff2c1d4b7955ec" + "2a97948bd3722915c8f3d337f7d37005" + "0e9e96d647b7c39f56e031ca5eb6250d" + "4042e02785ececfa4b4bb5e8ead0440e" + "20b6e8db09d881a7c6132f420e527950" + "42bdfa7773d8a9051447b3291ce1411c" + "680465552aa6c405b7764d5e87bea85a" + "d00f8449ed8f72d0d662ab052691ca66" + "424bc86d2df80ea41f43abf937d3259d" + "c4b2d0dfb48a6c9139ddd7f76966e928" + "e635553ba76c5c879d7b35d49eb2e62b" + "0871cdac638939e25e8a1e0ef9d5280f" + "a8ca328b351c3c765989cbcf3daa8b6c" + "cc3aaf9f3979c92b3720fc88dc95ed84" + "a1be059c6499b9fda236e7e818b04b0b" + "c39c1e876b193bfe5569753f88128cc0" + "8aaa9b63d1a16f80ef2554d7189c411f" + "5869ca52c5b83fa36ff216b9c1d30062" + "bebcfd2dc5bce0911934fda79a86f6e6" + "98ced759c3ff9b6477338f3da4f9cd85" + "14ea9982ccafb341b2384dd902f3d1ab" + "7ac61dd29c6f21ba5b862f3730e37cfd" + "c4fd806c22f221", + ), + # Test Vector #3 + ( + "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "00" * 11 + "02", + 42, + "2754776173206272696c6c69672c2061" + "6e642074686520736c6974687920746f" + "7665730a446964206779726520616e64" + "2067696d626c6520696e207468652077" + "6162653a0a416c6c206d696d73792077" + "6572652074686520626f726f676f7665" + "732c0a416e6420746865206d6f6d6520" + "7261746873206f757467726162652e", + "62e6347f95ed87a45ffae7426f27a1df" + "5fb69110044c0d73118effa95b01e5cf" + "166d3df2d721caf9b21e5fb14c616871" + "fd84c54f9d65b283196c7fe4f60553eb" + "f39c6402c42234e32a356b3e764312a6" + "1a5532055716ead6962568f87d3f3f77" + "04c6a8d1bcd1bf4d50d6154b6da731b1" + "87b58dfd728afa36757a797ac188d1", + ), + ] + + for tv in tvs: + key = unhexlify(tv[0]) + nonce = unhexlify(tv[1]) + offset = tv[2] * 64 + pt = unhexlify(tv[3]) + ct_expect = unhexlify(tv[4]) + + cipher = ChaCha20.new(key=key, nonce=nonce) + if offset != 0: + cipher.seek(offset) + ct = cipher.encrypt(pt) + assert ct == ct_expect class XChaCha20Test(unittest.TestCase): + # From https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - # From https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - - def test_hchacha20(self): - # Section 2.2.1 + def test_hchacha20(self): + # Section 2.2.1 - from Cryptodome.Cipher.ChaCha20 import _HChaCha20 + from Cryptodome.Cipher.ChaCha20 import _HChaCha20 - key = b"00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f" - key = unhexlify(key.replace(b":", b"")) + key = ( + b"00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f" + ) + key = unhexlify(key.replace(b":", b"")) - nonce = b"00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27" - nonce = unhexlify(nonce.replace(b":", b"")) + nonce = b"00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27" + nonce = unhexlify(nonce.replace(b":", b"")) - subkey = _HChaCha20(key, nonce) + subkey = _HChaCha20(key, nonce) - expected = b"82413b42 27b27bfe d30e4250 8a877d73 a0f9e4d5 8a74a853 c12ec413 26d3ecdc" - expected = unhexlify(expected.replace(b" ", b"")) + expected = b"82413b42 27b27bfe d30e4250 8a877d73 a0f9e4d5 8a74a853 c12ec413 26d3ecdc" + expected = unhexlify(expected.replace(b" ", b"")) - self.assertEqual(subkey, expected) + self.assertEqual(subkey, expected) - def test_nonce(self): - key = b'A' * 32 - nonce = b'P' * 24 - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertEqual(nonce, cipher.nonce) + def test_nonce(self): + key = b"A" * 32 + nonce = b"P" * 24 + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertEqual(nonce, cipher.nonce) - def test_encrypt(self): - # Section A.3.2 + def test_encrypt(self): + # Section A.3.2 - pt = b""" + pt = b""" 5468652064686f6c65202870726f6e6f756e6365642022646f6c652229206973 20616c736f206b6e6f776e2061732074686520417369617469632077696c6420 646f672c2072656420646f672c20616e642077686973746c696e6720646f672e @@ -296,12 +294,12 @@ def test_encrypt(self): 736966696564207769746820776f6c7665732c20636f796f7465732c206a6163 6b616c732c20616e6420666f78657320696e20746865207461786f6e6f6d6963 2066616d696c792043616e696461652e""" - pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b"")) + pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b"")) - key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") - iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555658") + key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") + iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555658") - ct = b""" + ct = b""" 7d0a2e6b7f7c65a236542630294e063b7ab9b555a5d5149aa21e4ae1e4fbce87 ecc8e08a8b5e350abe622b2ffa617b202cfad72032a3037e76ffdcdc4376ee05 3a190d7e46ca1de04144850381b9cb29f051915386b8a710b8ac4d027b8b050f @@ -312,218 +310,220 @@ def test_encrypt(self): c0b63615cdad0480680f16515a7ace9d39236464328a37743ffc28f4ddb324f4 d0f5bbdc270c65b1749a6efff1fbaa09536175ccd29fb9e6057b307320d31683 8a9c71f70b5b5907a66f7ea49aadc409""" - ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b"")) + ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b"")) - cipher = ChaCha20.new(key=key, nonce=iv) - cipher.seek(64) # Counter = 1 - ct_test = cipher.encrypt(pt) - self.assertEqual(ct, ct_test) + cipher = ChaCha20.new(key=key, nonce=iv) + cipher.seek(64) # Counter = 1 + ct_test = cipher.encrypt(pt) + self.assertEqual(ct, ct_test) class ByteArrayTest(unittest.TestCase): - """Verify we can encrypt or decrypt bytearrays""" + """Verify we can encrypt or decrypt bytearrays""" - def runTest(self): + def runTest(self): + data = b"0123" + key = b"9" * 32 + nonce = b"t" * 8 - data = b"0123" - key = b"9" * 32 - nonce = b"t" * 8 + # Encryption + data_ba = bytearray(data) + key_ba = bytearray(key) + nonce_ba = bytearray(nonce) - # Encryption - data_ba = bytearray(data) - key_ba = bytearray(key) - nonce_ba = bytearray(nonce) + cipher1 = ChaCha20.new(key=key, nonce=nonce) + ct = cipher1.encrypt(data) - cipher1 = ChaCha20.new(key=key, nonce=nonce) - ct = cipher1.encrypt(data) + cipher2 = ChaCha20.new(key=key_ba, nonce=nonce_ba) + key_ba[:1] = b"\xff" + nonce_ba[:1] = b"\xff" + ct_test = cipher2.encrypt(data_ba) - cipher2 = ChaCha20.new(key=key_ba, nonce=nonce_ba) - key_ba[:1] = b'\xFF' - nonce_ba[:1] = b'\xFF' - ct_test = cipher2.encrypt(data_ba) + self.assertEqual(ct, ct_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) - self.assertEqual(ct, ct_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) + # Decryption + key_ba = bytearray(key) + nonce_ba = bytearray(nonce) + ct_ba = bytearray(ct) - # Decryption - key_ba = bytearray(key) - nonce_ba = bytearray(nonce) - ct_ba = bytearray(ct) + cipher3 = ChaCha20.new(key=key_ba, nonce=nonce_ba) + key_ba[:1] = b"\xff" + nonce_ba[:1] = b"\xff" + pt_test = cipher3.decrypt(ct_ba) - cipher3 = ChaCha20.new(key=key_ba, nonce=nonce_ba) - key_ba[:1] = b'\xFF' - nonce_ba[:1] = b'\xFF' - pt_test = cipher3.decrypt(ct_ba) - - self.assertEqual(data, pt_test) + self.assertEqual(data, pt_test) class MemoryviewTest(unittest.TestCase): - """Verify we can encrypt or decrypt bytearrays""" - - def runTest(self): + """Verify we can encrypt or decrypt bytearrays""" - data = b"0123" - key = b"9" * 32 - nonce = b"t" * 8 + def runTest(self): + data = b"0123" + key = b"9" * 32 + nonce = b"t" * 8 - # Encryption - data_mv = memoryview(bytearray(data)) - key_mv = memoryview(bytearray(key)) - nonce_mv = memoryview(bytearray(nonce)) + # Encryption + data_mv = memoryview(bytearray(data)) + key_mv = memoryview(bytearray(key)) + nonce_mv = memoryview(bytearray(nonce)) - cipher1 = ChaCha20.new(key=key, nonce=nonce) - ct = cipher1.encrypt(data) + cipher1 = ChaCha20.new(key=key, nonce=nonce) + ct = cipher1.encrypt(data) - cipher2 = ChaCha20.new(key=key_mv, nonce=nonce_mv) - key_mv[:1] = b'\xFF' - nonce_mv[:1] = b'\xFF' - ct_test = cipher2.encrypt(data_mv) + cipher2 = ChaCha20.new(key=key_mv, nonce=nonce_mv) + key_mv[:1] = b"\xff" + nonce_mv[:1] = b"\xff" + ct_test = cipher2.encrypt(data_mv) - self.assertEqual(ct, ct_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) + self.assertEqual(ct, ct_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) - # Decryption - key_mv = memoryview(bytearray(key)) - nonce_mv = memoryview(bytearray(nonce)) - ct_mv = memoryview(bytearray(ct)) + # Decryption + key_mv = memoryview(bytearray(key)) + nonce_mv = memoryview(bytearray(nonce)) + ct_mv = memoryview(bytearray(ct)) - cipher3 = ChaCha20.new(key=key_mv, nonce=nonce_mv) - key_mv[:1] = b'\xFF' - nonce_mv[:1] = b'\xFF' - pt_test = cipher3.decrypt(ct_mv) + cipher3 = ChaCha20.new(key=key_mv, nonce=nonce_mv) + key_mv[:1] = b"\xff" + nonce_mv[:1] = b"\xff" + pt_test = cipher3.decrypt(ct_mv) - self.assertEqual(data, pt_test) + self.assertEqual(data, pt_test) class ChaCha20_AGL_NIR(unittest.TestCase): - - # From http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 - # and http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 - tv = [ - ( "00" * 32, - "00" * 8, - "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc" - "8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11c" - "c387b669b2ee6586" - "9f07e7be5551387a98ba977c732d080d" - "cb0f29a048e3656912c6533e32ee7aed" - "29b721769ce64e43d57133b074d839d5" - "31ed1f28510afb45ace10a1f4b794d6f" - ), - ( "00" * 31 + "01", - "00" * 8, - "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952" - "ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea81" - "7e9ad275ae546963" - "3aeb5224ecf849929b9d828db1ced4dd" - "832025e8018b8160b82284f3c949aa5a" - "8eca00bbb4a73bdad192b5c42f73f2fd" - "4e273644c8b36125a64addeb006c13a0" - ), - ( "00" * 32, - "00" * 7 + "01", - "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df1" - "37821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e" - "445f41e3" - ), - ( "00" * 32, - "01" + "00" * 7, - "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd1" - "38e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d" - "6bbdb0041b2f586b" - ), - ( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b" - "1c1d1e1f", - "0001020304050607", - "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56" - "f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f1" - "5916155c2be8241a38008b9a26bc35941e2444177c8ade6689de9526" - "4986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e" - "09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a4750" - "32b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c5" - "07b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f7" - "6dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2" - "ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab7" - "8fab78c9" - ), - ( "00" * 32, - "00" * 7 + "02", - "c2c64d378cd536374ae204b9ef933fcd" - "1a8b2288b3dfa49672ab765b54ee27c7" - "8a970e0e955c14f3a88e741b97c286f7" - "5f8fc299e8148362fa198a39531bed6d" - ), - ] - - def runTest(self): - for (key, nonce, stream) in self.tv: - c = ChaCha20.new(key=unhexlify(b(key)), nonce=unhexlify(b(nonce))) - ct = unhexlify(b(stream)) - pt = b("\x00") * len(ct) - self.assertEqual(c.encrypt(pt), ct) + # From http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 + # and http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + tv = [ + ( + "00" * 32, + "00" * 8, + "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc" + "8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11c" + "c387b669b2ee6586" + "9f07e7be5551387a98ba977c732d080d" + "cb0f29a048e3656912c6533e32ee7aed" + "29b721769ce64e43d57133b074d839d5" + "31ed1f28510afb45ace10a1f4b794d6f", + ), + ( + "00" * 31 + "01", + "00" * 8, + "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952" + "ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea81" + "7e9ad275ae546963" + "3aeb5224ecf849929b9d828db1ced4dd" + "832025e8018b8160b82284f3c949aa5a" + "8eca00bbb4a73bdad192b5c42f73f2fd" + "4e273644c8b36125a64addeb006c13a0", + ), + ( + "00" * 32, + "00" * 7 + "01", + "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df1" + "37821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e" + "445f41e3", + ), + ( + "00" * 32, + "01" + "00" * 7, + "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd1" + "38e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d" + "6bbdb0041b2f586b", + ), + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "0001020304050607", + "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56" + "f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f1" + "5916155c2be8241a38008b9a26bc35941e2444177c8ade6689de9526" + "4986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e" + "09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a4750" + "32b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c5" + "07b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f7" + "6dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2" + "ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab7" + "8fab78c9", + ), + ( + "00" * 32, + "00" * 7 + "02", + "c2c64d378cd536374ae204b9ef933fcd" + "1a8b2288b3dfa49672ab765b54ee27c7" + "8a970e0e955c14f3a88e741b97c286f7" + "5f8fc299e8148362fa198a39531bed6d", + ), + ] + + def runTest(self): + for key, nonce, stream in self.tv: + c = ChaCha20.new(key=unhexlify(b(key)), nonce=unhexlify(b(nonce))) + ct = unhexlify(b(stream)) + pt = b("\x00") * len(ct) + self.assertEqual(c.encrypt(pt), ct) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter - - key = b'4' * 32 - nonce = b'5' * 8 - cipher = ChaCha20.new(key=key, nonce=nonce) + key = b"4" * 32 + nonce = b"5" * 8 + cipher = ChaCha20.new(key=key, nonce=nonce) - pt = b'5' * 300 - ct = cipher.encrypt(pt) + pt = b"5" * 300 + ct = cipher.encrypt(pt) - output = bytearray(len(pt)) - cipher = ChaCha20.new(key=key, nonce=nonce) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) + output = bytearray(len(pt)) + cipher = ChaCha20.new(key=key, nonce=nonce) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - cipher = ChaCha20.new(key=key, nonce=nonce) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + cipher = ChaCha20.new(key=key, nonce=nonce) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = memoryview(bytearray(len(pt))) - cipher = ChaCha20.new(key=key, nonce=nonce) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + output = memoryview(bytearray(len(pt))) + cipher = ChaCha20.new(key=key, nonce=nonce) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - cipher = ChaCha20.new(key=key, nonce=nonce) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher = ChaCha20.new(key=key, nonce=nonce) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*len(pt)) + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * len(pt)) - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*len(pt)) + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * len(pt)) - shorter_output = bytearray(len(pt) - 1) + shorter_output = bytearray(len(pt) - 1) - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + cipher = ChaCha20.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - tests = [] - tests += list_test_cases(ChaCha20Test) - tests += list_test_cases(XChaCha20Test) - tests.append(ChaCha20_AGL_NIR()) - tests.append(ByteArrayTest()) - tests.append(MemoryviewTest()) - tests.append(TestOutput()) + tests = [] + tests += list_test_cases(ChaCha20Test) + tests += list_test_cases(XChaCha20Test) + tests.append(ChaCha20_AGL_NIR()) + tests.append(ByteArrayTest()) + tests.append(MemoryviewTest()) + tests.append(TestOutput()) + + return tests - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ChaCha20_Poly1305.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ChaCha20_Poly1305.py index 495028ab..c9c145c0 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ChaCha20_Poly1305.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_ChaCha20_Poly1305.py @@ -41,736 +41,868 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class ChaCha20Poly1305Tests(unittest.TestCase): - - key_256 = get_tag_random("key_256", 32) - nonce_96 = get_tag_random("nonce_96", 12) - data_128 = get_tag_random("data_128", 16) - - def test_loopback(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # Nonce can only be 8 or 12 bytes - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=b'H' * 8) - self.assertEqual(len(cipher.nonce), 8) - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=b'H' * 12) - self.assertEqual(len(cipher.nonce), 12) - - # If not passed, the nonce is created randomly - cipher = ChaCha20_Poly1305.new(key=self.key_256) - nonce1 = cipher.nonce - cipher = ChaCha20_Poly1305.new(key=self.key_256) - nonce2 = cipher.nonce - self.assertEqual(len(nonce1), 12) - self.assertNotEqual(nonce1, nonce2) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data_128)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, - ChaCha20_Poly1305.new, - key=self.key_256, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce can only be 8 or 12 bytes long - self.assertRaises(ValueError, - ChaCha20_Poly1305.new, - key=self.key_256, - nonce=b'0' * 7) - self.assertRaises(ValueError, - ChaCha20_Poly1305.new, - key=self.key_256, - nonce=b'') - - def test_block_size(self): - # Not based on block ciphers - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertFalse(hasattr(cipher, 'block_size')) - - def test_nonce_attribute(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 12 bytes long nonce is randomly generated - nonce1 = ChaCha20_Poly1305.new(key=self.key_256).nonce - nonce2 = ChaCha20_Poly1305.new(key=self.key_256).nonce - self.assertEqual(len(nonce1), 12) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, - ChaCha20_Poly1305.new, - key=self.key_256, - param=9) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data_128) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data_128) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b"" - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b"" - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_256) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data_128) - data_ba = bytearray(self.data_128) - - cipher1 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) - tag = cipher1.digest() - - cipher2 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - key_ba[:3] = b'\xFF\xFF\xFF' - nonce_ba[:3] = b'\xFF\xFF\xFF' - cipher2.update(header_ba) - header_ba[:3] = b'\xFF\xFF\xFF' - ct_test = cipher2.encrypt(data_ba) - data_ba[:3] = b'\x99\x99\x99' - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_256) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data_128) - ct_ba = bytearray(ct) - tag_ba = bytearray(tag) - del data_ba - - cipher3 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - key_ba[:3] = b'\xFF\xFF\xFF' - nonce_ba[:3] = b'\xFF\xFF\xFF' - cipher3.update(header_ba) - header_ba[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt(ct_ba) - ct_ba[:3] = b'\xFF\xFF\xFF' - cipher3.verify(tag_ba) - - self.assertEqual(pt_test, self.data_128) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_256)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data_128)) - data_mv = memoryview(bytearray(self.data_128)) - - cipher1 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) - tag = cipher1.digest() - - cipher2 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - key_mv[:3] = b'\xFF\xFF\xFF' - nonce_mv[:3] = b'\xFF\xFF\xFF' - cipher2.update(header_mv) - header_mv[:3] = b'\xFF\xFF\xFF' - ct_test = cipher2.encrypt(data_mv) - data_mv[:3] = b'\x99\x99\x99' - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_256)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data_128)) - ct_mv = memoryview(bytearray(ct)) - tag_mv = memoryview(bytearray(tag)) - del data_mv - - cipher3 = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - key_mv[:3] = b'\xFF\xFF\xFF' - nonce_mv[:3] = b'\xFF\xFF\xFF' - cipher3.update(header_mv) - header_mv[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt(ct_mv) - ct_mv[:3] = b'\x99\x99\x99' - cipher3.verify(tag_mv) - - self.assertEqual(pt_test, self.data_128) + key_256 = get_tag_random("key_256", 32) + nonce_96 = get_tag_random("nonce_96", 12) + data_128 = get_tag_random("data_128", 16) + + def test_loopback(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # Nonce can only be 8 or 12 bytes + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=b"H" * 8, + ) + self.assertEqual(len(cipher.nonce), 8) + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=b"H" * 12, + ) + self.assertEqual(len(cipher.nonce), 12) + + # If not passed, the nonce is created randomly + cipher = ChaCha20_Poly1305.new(key=self.key_256) + nonce1 = cipher.nonce + cipher = ChaCha20_Poly1305.new(key=self.key_256) + nonce2 = cipher.nonce + self.assertEqual(len(nonce1), 12) + self.assertNotEqual(nonce1, nonce2) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data_128) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertEqual(ct, cipher.encrypt(self.data_128)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + ChaCha20_Poly1305.new, + key=self.key_256, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce can only be 8 or 12 bytes long + self.assertRaises( + ValueError, + ChaCha20_Poly1305.new, + key=self.key_256, + nonce=b"0" * 7, + ) + self.assertRaises( + ValueError, + ChaCha20_Poly1305.new, + key=self.key_256, + nonce=b"", + ) + + def test_block_size(self): + # Not based on block ciphers + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertFalse(hasattr(cipher, "block_size")) + + def test_nonce_attribute(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 12 bytes long nonce is randomly generated + nonce1 = ChaCha20_Poly1305.new(key=self.key_256).nonce + nonce2 = ChaCha20_Poly1305.new(key=self.key_256).nonce + self.assertEqual(len(nonce1), 12) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + ChaCha20_Poly1305.new, + key=self.key_256, + param=9, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + _, mac = cipher.encrypt_and_digest(self.data_128) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + ct, mac = cipher.encrypt_and_digest(self.data_128) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.hexverify(mac_hex) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b"" + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b"" + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_256) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data_128) + data_ba = bytearray(self.data_128) + + cipher1 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher1.update(self.data_128) + ct = cipher1.encrypt(self.data_128) + tag = cipher1.digest() + + cipher2 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + data_ba[:3] = b"\x99\x99\x99" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_256) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data_128) + ct_ba = bytearray(ct) + tag_ba = bytearray(tag) + del data_ba + + cipher3 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher3.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt(ct_ba) + ct_ba[:3] = b"\xff\xff\xff" + cipher3.verify(tag_ba) + + self.assertEqual(pt_test, self.data_128) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_256)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data_128)) + data_mv = memoryview(bytearray(self.data_128)) + + cipher1 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher1.update(self.data_128) + ct = cipher1.encrypt(self.data_128) + tag = cipher1.digest() + + cipher2 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + data_mv[:3] = b"\x99\x99\x99" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_256)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data_128)) + ct_mv = memoryview(bytearray(ct)) + tag_mv = memoryview(bytearray(tag)) + del data_mv + + cipher3 = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher3.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt(ct_mv) + ct_mv[:3] = b"\x99\x99\x99" + cipher3.verify(tag_mv) + + self.assertEqual(pt_test, self.data_128) class XChaCha20Poly1305Tests(unittest.TestCase): - - def test_nonce(self): - # Nonce can only be 24 bytes - cipher = ChaCha20_Poly1305.new(key=b'Y' * 32, - nonce=b'H' * 24) - self.assertEqual(len(cipher.nonce), 24) - self.assertEqual(cipher.nonce, b'H' * 24) - - def test_encrypt(self): - # From https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - # Section A.3.1 - - pt = b""" + def test_nonce(self): + # Nonce can only be 24 bytes + cipher = ChaCha20_Poly1305.new( + key=b"Y" * 32, + nonce=b"H" * 24, + ) + self.assertEqual(len(cipher.nonce), 24) + self.assertEqual(cipher.nonce, b"H" * 24) + + def test_encrypt(self): + # From https://tools.ietf.org/html/draft-arciszewski-xchacha-03 + # Section A.3.1 + + pt = b""" 4c616469657320616e642047656e746c656d656e206f662074686520636c6173 73206f66202739393a204966204920636f756c64206f6666657220796f75206f 6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73 637265656e20776f756c642062652069742e""" - pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b"")) + pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b"")) - aad = unhexlify(b"50515253c0c1c2c3c4c5c6c7") - key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") - iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555657") + aad = unhexlify(b"50515253c0c1c2c3c4c5c6c7") + key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") + iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555657") - ct = b""" + ct = b""" bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb 731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b452 2f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff9 21f9664c97637da9768812f615c68b13b52e""" - ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b"")) + ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b"")) - tag = unhexlify(b"c0875924c1c7987947deafd8780acf49") + tag = unhexlify(b"c0875924c1c7987947deafd8780acf49") - cipher = ChaCha20_Poly1305.new(key=key, nonce=iv) - cipher.update(aad) - ct_test, tag_test = cipher.encrypt_and_digest(pt) + cipher = ChaCha20_Poly1305.new(key=key, nonce=iv) + cipher.update(aad) + ct_test, tag_test = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) - cipher = ChaCha20_Poly1305.new(key=key, nonce=iv) - cipher.update(aad) - cipher.decrypt_and_verify(ct, tag) + cipher = ChaCha20_Poly1305.new(key=key, nonce=iv) + cipher.update(aad) + cipher.decrypt_and_verify(ct, tag) class ChaCha20Poly1305FSMTests(unittest.TestCase): - - key_256 = get_tag_random("key_256", 32) - nonce_96 = get_tag_random("nonce_96", 12) - data_128 = get_tag_random("data_128", 16) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->DIGEST - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - # Verify path INIT->DECRYPT->VERIFY - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - # Verify path INIT->UPDATE->ENCRYPT->DIGEST - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->VERIFY - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - mac = cipher.digest() - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - for method_name in "encrypt", "decrypt": - for auth_data in (None, b"333", self.data_128, - self.data_128 + b"3"): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data_128) - method(self.data_128) - method(self.data_128) - method(self.data_128) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - ct, mac = cipher.encrypt_and_digest(self.data_128) - - # decrypt_and_verify - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.update(self.data_128) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data_128, pt) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data_128) - getattr(cipher, method1_name)(self.data_128) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data_128) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.encrypt(self.data_128) - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data_128) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = ChaCha20_Poly1305.new(key=self.key_256, - nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) + key_256 = get_tag_random("key_256", 32) + nonce_96 = get_tag_random("nonce_96", 12) + data_128 = get_tag_random("data_128", 16) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->DIGEST + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + # Verify path INIT->DECRYPT->VERIFY + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + # Verify path INIT->UPDATE->ENCRYPT->DIGEST + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->VERIFY + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + mac = cipher.digest() + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b"333", + self.data_128, + self.data_128 + b"3", + ): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data_128) + method(self.data_128) + method(self.data_128) + method(self.data_128) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + ct, mac = cipher.encrypt_and_digest(self.data_128) + + # decrypt_and_verify + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data_128, pt) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data_128) + getattr(cipher, method1_name)(self.data_128) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data_128, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.encrypt(self.data_128) + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.encrypt_and_digest(self.data_128) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = ChaCha20_Poly1305.new( + key=self.key_256, + nonce=self.nonce_96, + ) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) def compact(x): - return unhexlify(x.replace(" ", "").replace(":", "")) + return unhexlify(x.replace(" ", "").replace(":", "")) class TestVectorsRFC(unittest.TestCase): - """Test cases from RFC7539""" - - # AAD, PT, CT, MAC, KEY, NONCE - test_vectors_hex = [ - ( '50 51 52 53 c0 c1 c2 c3 c4 c5 c6 c7', - '4c 61 64 69 65 73 20 61 6e 64 20 47 65 6e 74 6c' - '65 6d 65 6e 20 6f 66 20 74 68 65 20 63 6c 61 73' - '73 20 6f 66 20 27 39 39 3a 20 49 66 20 49 20 63' - '6f 75 6c 64 20 6f 66 66 65 72 20 79 6f 75 20 6f' - '6e 6c 79 20 6f 6e 65 20 74 69 70 20 66 6f 72 20' - '74 68 65 20 66 75 74 75 72 65 2c 20 73 75 6e 73' - '63 72 65 65 6e 20 77 6f 75 6c 64 20 62 65 20 69' - '74 2e', - 'd3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2' - 'a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6' - '3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b' - '1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36' - '92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58' - 'fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc' - '3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b' - '61 16', - '1a:e1:0b:59:4f:09:e2:6a:7e:90:2e:cb:d0:60:06:91', - '80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f' - '90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f', - '07 00 00 00' + '40 41 42 43 44 45 46 47', - ), - ( 'f3 33 88 86 00 00 00 00 00 00 4e 91', - '49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 73 20' - '61 72 65 20 64 72 61 66 74 20 64 6f 63 75 6d 65' - '6e 74 73 20 76 61 6c 69 64 20 66 6f 72 20 61 20' - '6d 61 78 69 6d 75 6d 20 6f 66 20 73 69 78 20 6d' - '6f 6e 74 68 73 20 61 6e 64 20 6d 61 79 20 62 65' - '20 75 70 64 61 74 65 64 2c 20 72 65 70 6c 61 63' - '65 64 2c 20 6f 72 20 6f 62 73 6f 6c 65 74 65 64' - '20 62 79 20 6f 74 68 65 72 20 64 6f 63 75 6d 65' - '6e 74 73 20 61 74 20 61 6e 79 20 74 69 6d 65 2e' - '20 49 74 20 69 73 20 69 6e 61 70 70 72 6f 70 72' - '69 61 74 65 20 74 6f 20 75 73 65 20 49 6e 74 65' - '72 6e 65 74 2d 44 72 61 66 74 73 20 61 73 20 72' - '65 66 65 72 65 6e 63 65 20 6d 61 74 65 72 69 61' - '6c 20 6f 72 20 74 6f 20 63 69 74 65 20 74 68 65' - '6d 20 6f 74 68 65 72 20 74 68 61 6e 20 61 73 20' - '2f e2 80 9c 77 6f 72 6b 20 69 6e 20 70 72 6f 67' - '72 65 73 73 2e 2f e2 80 9d', - '64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd' - '5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2' - '4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0' - 'bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf' - '33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81' - '14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55' - '97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38' - '36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4' - 'b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9' - '90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e' - 'af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a' - '0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a' - '0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e' - 'ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10' - '49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30' - '30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29' - 'a6 ad 5c b4 02 2b 02 70 9b', - 'ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38', - '1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0' - '47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0', - '00 00 00 00 01 02 03 04 05 06 07 08', - ) - ] - - test_vectors = [[unhexlify(x.replace(" ", "").replace(":", "")) for x in tv] for tv in test_vectors_hex] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - # Encrypt - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.update(assoc_data) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.update(assoc_data) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Test cases from RFC7539""" + + # AAD, PT, CT, MAC, KEY, NONCE + test_vectors_hex = [ + ( + "50 51 52 53 c0 c1 c2 c3 c4 c5 c6 c7", + "4c 61 64 69 65 73 20 61 6e 64 20 47 65 6e 74 6c" + "65 6d 65 6e 20 6f 66 20 74 68 65 20 63 6c 61 73" + "73 20 6f 66 20 27 39 39 3a 20 49 66 20 49 20 63" + "6f 75 6c 64 20 6f 66 66 65 72 20 79 6f 75 20 6f" + "6e 6c 79 20 6f 6e 65 20 74 69 70 20 66 6f 72 20" + "74 68 65 20 66 75 74 75 72 65 2c 20 73 75 6e 73" + "63 72 65 65 6e 20 77 6f 75 6c 64 20 62 65 20 69" + "74 2e", + "d3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2" + "a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6" + "3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b" + "1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36" + "92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58" + "fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc" + "3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b" + "61 16", + "1a:e1:0b:59:4f:09:e2:6a:7e:90:2e:cb:d0:60:06:91", + "80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f", + "07 00 00 00" + "40 41 42 43 44 45 46 47", + ), + ( + "f3 33 88 86 00 00 00 00 00 00 4e 91", + "49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 73 20" + "61 72 65 20 64 72 61 66 74 20 64 6f 63 75 6d 65" + "6e 74 73 20 76 61 6c 69 64 20 66 6f 72 20 61 20" + "6d 61 78 69 6d 75 6d 20 6f 66 20 73 69 78 20 6d" + "6f 6e 74 68 73 20 61 6e 64 20 6d 61 79 20 62 65" + "20 75 70 64 61 74 65 64 2c 20 72 65 70 6c 61 63" + "65 64 2c 20 6f 72 20 6f 62 73 6f 6c 65 74 65 64" + "20 62 79 20 6f 74 68 65 72 20 64 6f 63 75 6d 65" + "6e 74 73 20 61 74 20 61 6e 79 20 74 69 6d 65 2e" + "20 49 74 20 69 73 20 69 6e 61 70 70 72 6f 70 72" + "69 61 74 65 20 74 6f 20 75 73 65 20 49 6e 74 65" + "72 6e 65 74 2d 44 72 61 66 74 73 20 61 73 20 72" + "65 66 65 72 65 6e 63 65 20 6d 61 74 65 72 69 61" + "6c 20 6f 72 20 74 6f 20 63 69 74 65 20 74 68 65" + "6d 20 6f 74 68 65 72 20 74 68 61 6e 20 61 73 20" + "2f e2 80 9c 77 6f 72 6b 20 69 6e 20 70 72 6f 67" + "72 65 73 73 2e 2f e2 80 9d", + "64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd" + "5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2" + "4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0" + "bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf" + "33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81" + "14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55" + "97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38" + "36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4" + "b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9" + "90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e" + "af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a" + "0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a" + "0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e" + "ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10" + "49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30" + "30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29" + "a6 ad 5c b4 02 2b 02 70 9b", + "ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38", + "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f047 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", + "00 00 00 00 01 02 03 04 05 06 07 08", + ), + ] + + test_vectors = [[unhexlify(x.replace(" ", "").replace(":", "")) for x in tv] for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + cipher.update(assoc_data) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + cipher.update(assoc_data) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def load_tests(self, filename): - - def filter_tag(group): - return group['tagSize'] // 8 - - def filter_algo(root): - return root['algorithm'] - - result = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - filename, - "Wycheproof ChaCha20-Poly1305", - root_tag={'algo': filter_algo}, - group_tag={'tag_size': filter_tag}) - return result - - def setUp(self): - self.tv = [] - self.tv.extend(self.load_tests("chacha20_poly1305_test.json")) - self.tv.extend(self.load_tests("xchacha20_poly1305_test.json")) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt %s Test #%s" % (tv.algo, tv.id) - - try: - cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) - except ValueError as e: - assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e) - return - - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id) - - try: - cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) - except ValueError as e: - assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e) - return - - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def test_corrupt_decrypt(self, tv): - self._id = "Wycheproof Corrupt Decrypt ChaCha20-Poly1305 Test #" + str(tv.id) - if len(tv.iv) == 0 or len(tv.ct) < 1: - return - cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) - cipher.update(tv.aad) - ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) - self.test_corrupt_decrypt(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def load_tests(self, filename): + def filter_tag(group): + return group["tagSize"] // 8 + + def filter_algo(root): + return root["algorithm"] + + result = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + filename, + "Wycheproof ChaCha20-Poly1305", + root_tag={"algo": filter_algo}, + group_tag={"tag_size": filter_tag}, + ) + return result + + def setUp(self): + self.tv = [] + self.tv.extend(self.load_tests("chacha20_poly1305_test.json")) + self.tv.extend(self.load_tests("xchacha20_poly1305_test.json")) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt %s Test #%s" % (tv.algo, tv.id) + + try: + cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) + except ValueError as e: + assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e) + return + + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id) + + try: + cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) + except ValueError as e: + assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e) + return + + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def test_corrupt_decrypt(self, tv): + self._id = "Wycheproof Corrupt Decrypt ChaCha20-Poly1305 Test #" + str(tv.id) + if len(tv.iv) == 0 or len(tv.ct) < 1: + return + cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv) + cipher.update(tv.aad) + ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) + self.test_corrupt_decrypt(tv) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter + key = b"4" * 32 + nonce = b"5" * 12 + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - key = b'4' * 32 - nonce = b'5' * 12 - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + pt = b"5" * 16 + ct = cipher.encrypt(pt) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + output = bytearray(16) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - output = bytearray(16) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(16)) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(16)) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + shorter_output = bytearray(7) - shorter_output = bytearray(7) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - - cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') - - tests = [] - tests += list_test_cases(ChaCha20Poly1305Tests) - tests += list_test_cases(XChaCha20Poly1305Tests) - tests += list_test_cases(ChaCha20Poly1305FSMTests) - tests += [TestVectorsRFC()] - tests += [TestVectorsWycheproof(wycheproof_warnings)] - tests += [TestOutput()] - return tests - - -if __name__ == '__main__': - def suite(): - unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(ChaCha20Poly1305Tests) + tests += list_test_cases(XChaCha20Poly1305Tests) + tests += list_test_cases(ChaCha20Poly1305FSMTests) + tests += [TestVectorsRFC()] + tests += [TestVectorsWycheproof(wycheproof_warnings)] + tests += [TestOutput()] + return tests + + +if __name__ == "__main__": + + def suite(): + unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_DES.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_DES.py index df1313af..bb419c65 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_DES.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_DES.py @@ -29,346 +29,832 @@ from Cryptodome.Cipher import DES # This is a list of (plaintext, ciphertext, key, description) tuples. -SP800_17_B1_KEY = '01' * 8 -SP800_17_B2_PT = '00' * 8 +SP800_17_B1_KEY = "01" * 8 +SP800_17_B2_PT = "00" * 8 test_data = [ - # Test vectors from Appendix A of NIST SP 800-17 - # "Modes of Operation Validation System (MOVS): Requirements and Procedures" - # http://csrc.nist.gov/publications/nistpubs/800-17/800-17.pdf - - # Appendix A - "Sample Round Outputs for the DES" - ('0000000000000000', '82dcbafbdeab6602', '10316e028c8f3b4a', - "NIST SP800-17 A"), - - # Table B.1 - Variable Plaintext Known Answer Test - ('8000000000000000', '95f8a5e5dd31d900', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #0'), - ('4000000000000000', 'dd7f121ca5015619', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #1'), - ('2000000000000000', '2e8653104f3834ea', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #2'), - ('1000000000000000', '4bd388ff6cd81d4f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #3'), - ('0800000000000000', '20b9e767b2fb1456', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #4'), - ('0400000000000000', '55579380d77138ef', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #5'), - ('0200000000000000', '6cc5defaaf04512f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #6'), - ('0100000000000000', '0d9f279ba5d87260', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #7'), - ('0080000000000000', 'd9031b0271bd5a0a', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #8'), - ('0040000000000000', '424250b37c3dd951', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #9'), - ('0020000000000000', 'b8061b7ecd9a21e5', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #10'), - ('0010000000000000', 'f15d0f286b65bd28', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #11'), - ('0008000000000000', 'add0cc8d6e5deba1', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #12'), - ('0004000000000000', 'e6d5f82752ad63d1', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #13'), - ('0002000000000000', 'ecbfe3bd3f591a5e', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #14'), - ('0001000000000000', 'f356834379d165cd', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #15'), - ('0000800000000000', '2b9f982f20037fa9', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #16'), - ('0000400000000000', '889de068a16f0be6', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #17'), - ('0000200000000000', 'e19e275d846a1298', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #18'), - ('0000100000000000', '329a8ed523d71aec', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #19'), - ('0000080000000000', 'e7fce22557d23c97', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #20'), - ('0000040000000000', '12a9f5817ff2d65d', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #21'), - ('0000020000000000', 'a484c3ad38dc9c19', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #22'), - ('0000010000000000', 'fbe00a8a1ef8ad72', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #23'), - ('0000008000000000', '750d079407521363', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #24'), - ('0000004000000000', '64feed9c724c2faf', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #25'), - ('0000002000000000', 'f02b263b328e2b60', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #26'), - ('0000001000000000', '9d64555a9a10b852', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #27'), - ('0000000800000000', 'd106ff0bed5255d7', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #28'), - ('0000000400000000', 'e1652c6b138c64a5', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #29'), - ('0000000200000000', 'e428581186ec8f46', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #30'), - ('0000000100000000', 'aeb5f5ede22d1a36', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #31'), - ('0000000080000000', 'e943d7568aec0c5c', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #32'), - ('0000000040000000', 'df98c8276f54b04b', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #33'), - ('0000000020000000', 'b160e4680f6c696f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #34'), - ('0000000010000000', 'fa0752b07d9c4ab8', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #35'), - ('0000000008000000', 'ca3a2b036dbc8502', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #36'), - ('0000000004000000', '5e0905517bb59bcf', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #37'), - ('0000000002000000', '814eeb3b91d90726', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #38'), - ('0000000001000000', '4d49db1532919c9f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #39'), - ('0000000000800000', '25eb5fc3f8cf0621', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #40'), - ('0000000000400000', 'ab6a20c0620d1c6f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #41'), - ('0000000000200000', '79e90dbc98f92cca', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #42'), - ('0000000000100000', '866ecedd8072bb0e', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #43'), - ('0000000000080000', '8b54536f2f3e64a8', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #44'), - ('0000000000040000', 'ea51d3975595b86b', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #45'), - ('0000000000020000', 'caffc6ac4542de31', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #46'), - ('0000000000010000', '8dd45a2ddf90796c', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #47'), - ('0000000000008000', '1029d55e880ec2d0', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #48'), - ('0000000000004000', '5d86cb23639dbea9', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #49'), - ('0000000000002000', '1d1ca853ae7c0c5f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #50'), - ('0000000000001000', 'ce332329248f3228', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #51'), - ('0000000000000800', '8405d1abe24fb942', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #52'), - ('0000000000000400', 'e643d78090ca4207', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #53'), - ('0000000000000200', '48221b9937748a23', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #54'), - ('0000000000000100', 'dd7c0bbd61fafd54', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #55'), - ('0000000000000080', '2fbc291a570db5c4', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #56'), - ('0000000000000040', 'e07c30d7e4e26e12', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #57'), - ('0000000000000020', '0953e2258e8e90a1', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #58'), - ('0000000000000010', '5b711bc4ceebf2ee', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #59'), - ('0000000000000008', 'cc083f1e6d9e85f6', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #60'), - ('0000000000000004', 'd2fd8867d50d2dfe', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #61'), - ('0000000000000002', '06e7ea22ce92708f', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #62'), - ('0000000000000001', '166b40b44aba4bd6', SP800_17_B1_KEY, - 'NIST SP800-17 B.1 #63'), - - # Table B.2 - Variable Key Known Answer Test - (SP800_17_B2_PT, '95a8d72813daa94d', '8001010101010101', - 'NIST SP800-17 B.2 #0'), - (SP800_17_B2_PT, '0eec1487dd8c26d5', '4001010101010101', - 'NIST SP800-17 B.2 #1'), - (SP800_17_B2_PT, '7ad16ffb79c45926', '2001010101010101', - 'NIST SP800-17 B.2 #2'), - (SP800_17_B2_PT, 'd3746294ca6a6cf3', '1001010101010101', - 'NIST SP800-17 B.2 #3'), - (SP800_17_B2_PT, '809f5f873c1fd761', '0801010101010101', - 'NIST SP800-17 B.2 #4'), - (SP800_17_B2_PT, 'c02faffec989d1fc', '0401010101010101', - 'NIST SP800-17 B.2 #5'), - (SP800_17_B2_PT, '4615aa1d33e72f10', '0201010101010101', - 'NIST SP800-17 B.2 #6'), - (SP800_17_B2_PT, '2055123350c00858', '0180010101010101', - 'NIST SP800-17 B.2 #7'), - (SP800_17_B2_PT, 'df3b99d6577397c8', '0140010101010101', - 'NIST SP800-17 B.2 #8'), - (SP800_17_B2_PT, '31fe17369b5288c9', '0120010101010101', - 'NIST SP800-17 B.2 #9'), - (SP800_17_B2_PT, 'dfdd3cc64dae1642', '0110010101010101', - 'NIST SP800-17 B.2 #10'), - (SP800_17_B2_PT, '178c83ce2b399d94', '0108010101010101', - 'NIST SP800-17 B.2 #11'), - (SP800_17_B2_PT, '50f636324a9b7f80', '0104010101010101', - 'NIST SP800-17 B.2 #12'), - (SP800_17_B2_PT, 'a8468ee3bc18f06d', '0102010101010101', - 'NIST SP800-17 B.2 #13'), - (SP800_17_B2_PT, 'a2dc9e92fd3cde92', '0101800101010101', - 'NIST SP800-17 B.2 #14'), - (SP800_17_B2_PT, 'cac09f797d031287', '0101400101010101', - 'NIST SP800-17 B.2 #15'), - (SP800_17_B2_PT, '90ba680b22aeb525', '0101200101010101', - 'NIST SP800-17 B.2 #16'), - (SP800_17_B2_PT, 'ce7a24f350e280b6', '0101100101010101', - 'NIST SP800-17 B.2 #17'), - (SP800_17_B2_PT, '882bff0aa01a0b87', '0101080101010101', - 'NIST SP800-17 B.2 #18'), - (SP800_17_B2_PT, '25610288924511c2', '0101040101010101', - 'NIST SP800-17 B.2 #19'), - (SP800_17_B2_PT, 'c71516c29c75d170', '0101020101010101', - 'NIST SP800-17 B.2 #20'), - (SP800_17_B2_PT, '5199c29a52c9f059', '0101018001010101', - 'NIST SP800-17 B.2 #21'), - (SP800_17_B2_PT, 'c22f0a294a71f29f', '0101014001010101', - 'NIST SP800-17 B.2 #22'), - (SP800_17_B2_PT, 'ee371483714c02ea', '0101012001010101', - 'NIST SP800-17 B.2 #23'), - (SP800_17_B2_PT, 'a81fbd448f9e522f', '0101011001010101', - 'NIST SP800-17 B.2 #24'), - (SP800_17_B2_PT, '4f644c92e192dfed', '0101010801010101', - 'NIST SP800-17 B.2 #25'), - (SP800_17_B2_PT, '1afa9a66a6df92ae', '0101010401010101', - 'NIST SP800-17 B.2 #26'), - (SP800_17_B2_PT, 'b3c1cc715cb879d8', '0101010201010101', - 'NIST SP800-17 B.2 #27'), - (SP800_17_B2_PT, '19d032e64ab0bd8b', '0101010180010101', - 'NIST SP800-17 B.2 #28'), - (SP800_17_B2_PT, '3cfaa7a7dc8720dc', '0101010140010101', - 'NIST SP800-17 B.2 #29'), - (SP800_17_B2_PT, 'b7265f7f447ac6f3', '0101010120010101', - 'NIST SP800-17 B.2 #30'), - (SP800_17_B2_PT, '9db73b3c0d163f54', '0101010110010101', - 'NIST SP800-17 B.2 #31'), - (SP800_17_B2_PT, '8181b65babf4a975', '0101010108010101', - 'NIST SP800-17 B.2 #32'), - (SP800_17_B2_PT, '93c9b64042eaa240', '0101010104010101', - 'NIST SP800-17 B.2 #33'), - (SP800_17_B2_PT, '5570530829705592', '0101010102010101', - 'NIST SP800-17 B.2 #34'), - (SP800_17_B2_PT, '8638809e878787a0', '0101010101800101', - 'NIST SP800-17 B.2 #35'), - (SP800_17_B2_PT, '41b9a79af79ac208', '0101010101400101', - 'NIST SP800-17 B.2 #36'), - (SP800_17_B2_PT, '7a9be42f2009a892', '0101010101200101', - 'NIST SP800-17 B.2 #37'), - (SP800_17_B2_PT, '29038d56ba6d2745', '0101010101100101', - 'NIST SP800-17 B.2 #38'), - (SP800_17_B2_PT, '5495c6abf1e5df51', '0101010101080101', - 'NIST SP800-17 B.2 #39'), - (SP800_17_B2_PT, 'ae13dbd561488933', '0101010101040101', - 'NIST SP800-17 B.2 #40'), - (SP800_17_B2_PT, '024d1ffa8904e389', '0101010101020101', - 'NIST SP800-17 B.2 #41'), - (SP800_17_B2_PT, 'd1399712f99bf02e', '0101010101018001', - 'NIST SP800-17 B.2 #42'), - (SP800_17_B2_PT, '14c1d7c1cffec79e', '0101010101014001', - 'NIST SP800-17 B.2 #43'), - (SP800_17_B2_PT, '1de5279dae3bed6f', '0101010101012001', - 'NIST SP800-17 B.2 #44'), - (SP800_17_B2_PT, 'e941a33f85501303', '0101010101011001', - 'NIST SP800-17 B.2 #45'), - (SP800_17_B2_PT, 'da99dbbc9a03f379', '0101010101010801', - 'NIST SP800-17 B.2 #46'), - (SP800_17_B2_PT, 'b7fc92f91d8e92e9', '0101010101010401', - 'NIST SP800-17 B.2 #47'), - (SP800_17_B2_PT, 'ae8e5caa3ca04e85', '0101010101010201', - 'NIST SP800-17 B.2 #48'), - (SP800_17_B2_PT, '9cc62df43b6eed74', '0101010101010180', - 'NIST SP800-17 B.2 #49'), - (SP800_17_B2_PT, 'd863dbb5c59a91a0', '0101010101010140', - 'NIST SP800-17 B.2 #50'), - (SP800_17_B2_PT, 'a1ab2190545b91d7', '0101010101010120', - 'NIST SP800-17 B.2 #51'), - (SP800_17_B2_PT, '0875041e64c570f7', '0101010101010110', - 'NIST SP800-17 B.2 #52'), - (SP800_17_B2_PT, '5a594528bebef1cc', '0101010101010108', - 'NIST SP800-17 B.2 #53'), - (SP800_17_B2_PT, 'fcdb3291de21f0c0', '0101010101010104', - 'NIST SP800-17 B.2 #54'), - (SP800_17_B2_PT, '869efd7f9f265a09', '0101010101010102', - 'NIST SP800-17 B.2 #55'), + # Test vectors from Appendix A of NIST SP 800-17 + # "Modes of Operation Validation System (MOVS): Requirements and Procedures" + # http://csrc.nist.gov/publications/nistpubs/800-17/800-17.pdf + # Appendix A - "Sample Round Outputs for the DES" + ( + "0000000000000000", + "82dcbafbdeab6602", + "10316e028c8f3b4a", + "NIST SP800-17 A", + ), + # Table B.1 - Variable Plaintext Known Answer Test + ( + "8000000000000000", + "95f8a5e5dd31d900", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #0", + ), + ( + "4000000000000000", + "dd7f121ca5015619", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #1", + ), + ( + "2000000000000000", + "2e8653104f3834ea", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #2", + ), + ( + "1000000000000000", + "4bd388ff6cd81d4f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #3", + ), + ( + "0800000000000000", + "20b9e767b2fb1456", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #4", + ), + ( + "0400000000000000", + "55579380d77138ef", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #5", + ), + ( + "0200000000000000", + "6cc5defaaf04512f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #6", + ), + ( + "0100000000000000", + "0d9f279ba5d87260", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #7", + ), + ( + "0080000000000000", + "d9031b0271bd5a0a", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #8", + ), + ( + "0040000000000000", + "424250b37c3dd951", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #9", + ), + ( + "0020000000000000", + "b8061b7ecd9a21e5", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #10", + ), + ( + "0010000000000000", + "f15d0f286b65bd28", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #11", + ), + ( + "0008000000000000", + "add0cc8d6e5deba1", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #12", + ), + ( + "0004000000000000", + "e6d5f82752ad63d1", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #13", + ), + ( + "0002000000000000", + "ecbfe3bd3f591a5e", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #14", + ), + ( + "0001000000000000", + "f356834379d165cd", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #15", + ), + ( + "0000800000000000", + "2b9f982f20037fa9", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #16", + ), + ( + "0000400000000000", + "889de068a16f0be6", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #17", + ), + ( + "0000200000000000", + "e19e275d846a1298", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #18", + ), + ( + "0000100000000000", + "329a8ed523d71aec", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #19", + ), + ( + "0000080000000000", + "e7fce22557d23c97", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #20", + ), + ( + "0000040000000000", + "12a9f5817ff2d65d", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #21", + ), + ( + "0000020000000000", + "a484c3ad38dc9c19", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #22", + ), + ( + "0000010000000000", + "fbe00a8a1ef8ad72", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #23", + ), + ( + "0000008000000000", + "750d079407521363", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #24", + ), + ( + "0000004000000000", + "64feed9c724c2faf", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #25", + ), + ( + "0000002000000000", + "f02b263b328e2b60", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #26", + ), + ( + "0000001000000000", + "9d64555a9a10b852", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #27", + ), + ( + "0000000800000000", + "d106ff0bed5255d7", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #28", + ), + ( + "0000000400000000", + "e1652c6b138c64a5", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #29", + ), + ( + "0000000200000000", + "e428581186ec8f46", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #30", + ), + ( + "0000000100000000", + "aeb5f5ede22d1a36", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #31", + ), + ( + "0000000080000000", + "e943d7568aec0c5c", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #32", + ), + ( + "0000000040000000", + "df98c8276f54b04b", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #33", + ), + ( + "0000000020000000", + "b160e4680f6c696f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #34", + ), + ( + "0000000010000000", + "fa0752b07d9c4ab8", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #35", + ), + ( + "0000000008000000", + "ca3a2b036dbc8502", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #36", + ), + ( + "0000000004000000", + "5e0905517bb59bcf", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #37", + ), + ( + "0000000002000000", + "814eeb3b91d90726", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #38", + ), + ( + "0000000001000000", + "4d49db1532919c9f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #39", + ), + ( + "0000000000800000", + "25eb5fc3f8cf0621", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #40", + ), + ( + "0000000000400000", + "ab6a20c0620d1c6f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #41", + ), + ( + "0000000000200000", + "79e90dbc98f92cca", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #42", + ), + ( + "0000000000100000", + "866ecedd8072bb0e", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #43", + ), + ( + "0000000000080000", + "8b54536f2f3e64a8", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #44", + ), + ( + "0000000000040000", + "ea51d3975595b86b", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #45", + ), + ( + "0000000000020000", + "caffc6ac4542de31", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #46", + ), + ( + "0000000000010000", + "8dd45a2ddf90796c", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #47", + ), + ( + "0000000000008000", + "1029d55e880ec2d0", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #48", + ), + ( + "0000000000004000", + "5d86cb23639dbea9", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #49", + ), + ( + "0000000000002000", + "1d1ca853ae7c0c5f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #50", + ), + ( + "0000000000001000", + "ce332329248f3228", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #51", + ), + ( + "0000000000000800", + "8405d1abe24fb942", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #52", + ), + ( + "0000000000000400", + "e643d78090ca4207", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #53", + ), + ( + "0000000000000200", + "48221b9937748a23", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #54", + ), + ( + "0000000000000100", + "dd7c0bbd61fafd54", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #55", + ), + ( + "0000000000000080", + "2fbc291a570db5c4", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #56", + ), + ( + "0000000000000040", + "e07c30d7e4e26e12", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #57", + ), + ( + "0000000000000020", + "0953e2258e8e90a1", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #58", + ), + ( + "0000000000000010", + "5b711bc4ceebf2ee", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #59", + ), + ( + "0000000000000008", + "cc083f1e6d9e85f6", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #60", + ), + ( + "0000000000000004", + "d2fd8867d50d2dfe", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #61", + ), + ( + "0000000000000002", + "06e7ea22ce92708f", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #62", + ), + ( + "0000000000000001", + "166b40b44aba4bd6", + SP800_17_B1_KEY, + "NIST SP800-17 B.1 #63", + ), + # Table B.2 - Variable Key Known Answer Test + ( + SP800_17_B2_PT, + "95a8d72813daa94d", + "8001010101010101", + "NIST SP800-17 B.2 #0", + ), + ( + SP800_17_B2_PT, + "0eec1487dd8c26d5", + "4001010101010101", + "NIST SP800-17 B.2 #1", + ), + ( + SP800_17_B2_PT, + "7ad16ffb79c45926", + "2001010101010101", + "NIST SP800-17 B.2 #2", + ), + ( + SP800_17_B2_PT, + "d3746294ca6a6cf3", + "1001010101010101", + "NIST SP800-17 B.2 #3", + ), + ( + SP800_17_B2_PT, + "809f5f873c1fd761", + "0801010101010101", + "NIST SP800-17 B.2 #4", + ), + ( + SP800_17_B2_PT, + "c02faffec989d1fc", + "0401010101010101", + "NIST SP800-17 B.2 #5", + ), + ( + SP800_17_B2_PT, + "4615aa1d33e72f10", + "0201010101010101", + "NIST SP800-17 B.2 #6", + ), + ( + SP800_17_B2_PT, + "2055123350c00858", + "0180010101010101", + "NIST SP800-17 B.2 #7", + ), + ( + SP800_17_B2_PT, + "df3b99d6577397c8", + "0140010101010101", + "NIST SP800-17 B.2 #8", + ), + ( + SP800_17_B2_PT, + "31fe17369b5288c9", + "0120010101010101", + "NIST SP800-17 B.2 #9", + ), + ( + SP800_17_B2_PT, + "dfdd3cc64dae1642", + "0110010101010101", + "NIST SP800-17 B.2 #10", + ), + ( + SP800_17_B2_PT, + "178c83ce2b399d94", + "0108010101010101", + "NIST SP800-17 B.2 #11", + ), + ( + SP800_17_B2_PT, + "50f636324a9b7f80", + "0104010101010101", + "NIST SP800-17 B.2 #12", + ), + ( + SP800_17_B2_PT, + "a8468ee3bc18f06d", + "0102010101010101", + "NIST SP800-17 B.2 #13", + ), + ( + SP800_17_B2_PT, + "a2dc9e92fd3cde92", + "0101800101010101", + "NIST SP800-17 B.2 #14", + ), + ( + SP800_17_B2_PT, + "cac09f797d031287", + "0101400101010101", + "NIST SP800-17 B.2 #15", + ), + ( + SP800_17_B2_PT, + "90ba680b22aeb525", + "0101200101010101", + "NIST SP800-17 B.2 #16", + ), + ( + SP800_17_B2_PT, + "ce7a24f350e280b6", + "0101100101010101", + "NIST SP800-17 B.2 #17", + ), + ( + SP800_17_B2_PT, + "882bff0aa01a0b87", + "0101080101010101", + "NIST SP800-17 B.2 #18", + ), + ( + SP800_17_B2_PT, + "25610288924511c2", + "0101040101010101", + "NIST SP800-17 B.2 #19", + ), + ( + SP800_17_B2_PT, + "c71516c29c75d170", + "0101020101010101", + "NIST SP800-17 B.2 #20", + ), + ( + SP800_17_B2_PT, + "5199c29a52c9f059", + "0101018001010101", + "NIST SP800-17 B.2 #21", + ), + ( + SP800_17_B2_PT, + "c22f0a294a71f29f", + "0101014001010101", + "NIST SP800-17 B.2 #22", + ), + ( + SP800_17_B2_PT, + "ee371483714c02ea", + "0101012001010101", + "NIST SP800-17 B.2 #23", + ), + ( + SP800_17_B2_PT, + "a81fbd448f9e522f", + "0101011001010101", + "NIST SP800-17 B.2 #24", + ), + ( + SP800_17_B2_PT, + "4f644c92e192dfed", + "0101010801010101", + "NIST SP800-17 B.2 #25", + ), + ( + SP800_17_B2_PT, + "1afa9a66a6df92ae", + "0101010401010101", + "NIST SP800-17 B.2 #26", + ), + ( + SP800_17_B2_PT, + "b3c1cc715cb879d8", + "0101010201010101", + "NIST SP800-17 B.2 #27", + ), + ( + SP800_17_B2_PT, + "19d032e64ab0bd8b", + "0101010180010101", + "NIST SP800-17 B.2 #28", + ), + ( + SP800_17_B2_PT, + "3cfaa7a7dc8720dc", + "0101010140010101", + "NIST SP800-17 B.2 #29", + ), + ( + SP800_17_B2_PT, + "b7265f7f447ac6f3", + "0101010120010101", + "NIST SP800-17 B.2 #30", + ), + ( + SP800_17_B2_PT, + "9db73b3c0d163f54", + "0101010110010101", + "NIST SP800-17 B.2 #31", + ), + ( + SP800_17_B2_PT, + "8181b65babf4a975", + "0101010108010101", + "NIST SP800-17 B.2 #32", + ), + ( + SP800_17_B2_PT, + "93c9b64042eaa240", + "0101010104010101", + "NIST SP800-17 B.2 #33", + ), + ( + SP800_17_B2_PT, + "5570530829705592", + "0101010102010101", + "NIST SP800-17 B.2 #34", + ), + ( + SP800_17_B2_PT, + "8638809e878787a0", + "0101010101800101", + "NIST SP800-17 B.2 #35", + ), + ( + SP800_17_B2_PT, + "41b9a79af79ac208", + "0101010101400101", + "NIST SP800-17 B.2 #36", + ), + ( + SP800_17_B2_PT, + "7a9be42f2009a892", + "0101010101200101", + "NIST SP800-17 B.2 #37", + ), + ( + SP800_17_B2_PT, + "29038d56ba6d2745", + "0101010101100101", + "NIST SP800-17 B.2 #38", + ), + ( + SP800_17_B2_PT, + "5495c6abf1e5df51", + "0101010101080101", + "NIST SP800-17 B.2 #39", + ), + ( + SP800_17_B2_PT, + "ae13dbd561488933", + "0101010101040101", + "NIST SP800-17 B.2 #40", + ), + ( + SP800_17_B2_PT, + "024d1ffa8904e389", + "0101010101020101", + "NIST SP800-17 B.2 #41", + ), + ( + SP800_17_B2_PT, + "d1399712f99bf02e", + "0101010101018001", + "NIST SP800-17 B.2 #42", + ), + ( + SP800_17_B2_PT, + "14c1d7c1cffec79e", + "0101010101014001", + "NIST SP800-17 B.2 #43", + ), + ( + SP800_17_B2_PT, + "1de5279dae3bed6f", + "0101010101012001", + "NIST SP800-17 B.2 #44", + ), + ( + SP800_17_B2_PT, + "e941a33f85501303", + "0101010101011001", + "NIST SP800-17 B.2 #45", + ), + ( + SP800_17_B2_PT, + "da99dbbc9a03f379", + "0101010101010801", + "NIST SP800-17 B.2 #46", + ), + ( + SP800_17_B2_PT, + "b7fc92f91d8e92e9", + "0101010101010401", + "NIST SP800-17 B.2 #47", + ), + ( + SP800_17_B2_PT, + "ae8e5caa3ca04e85", + "0101010101010201", + "NIST SP800-17 B.2 #48", + ), + ( + SP800_17_B2_PT, + "9cc62df43b6eed74", + "0101010101010180", + "NIST SP800-17 B.2 #49", + ), + ( + SP800_17_B2_PT, + "d863dbb5c59a91a0", + "0101010101010140", + "NIST SP800-17 B.2 #50", + ), + ( + SP800_17_B2_PT, + "a1ab2190545b91d7", + "0101010101010120", + "NIST SP800-17 B.2 #51", + ), + ( + SP800_17_B2_PT, + "0875041e64c570f7", + "0101010101010110", + "NIST SP800-17 B.2 #52", + ), + ( + SP800_17_B2_PT, + "5a594528bebef1cc", + "0101010101010108", + "NIST SP800-17 B.2 #53", + ), + ( + SP800_17_B2_PT, + "fcdb3291de21f0c0", + "0101010101010104", + "NIST SP800-17 B.2 #54", + ), + ( + SP800_17_B2_PT, + "869efd7f9f265a09", + "0101010101010102", + "NIST SP800-17 B.2 #55", + ), ] + class RonRivestTest(unittest.TestCase): - """ Ronald L. Rivest's DES test, see - http://people.csail.mit.edu/rivest/Destest.txt - ABSTRACT - -------- + """Ronald L. Rivest's DES test, see + http://people.csail.mit.edu/rivest/Destest.txt + ABSTRACT + -------- + + We present a simple way to test the correctness of a DES implementation: + Use the recurrence relation: - We present a simple way to test the correctness of a DES implementation: - Use the recurrence relation: + X0 = 9474B8E8C73BCA7D (hexadecimal) - X0 = 9474B8E8C73BCA7D (hexadecimal) + X(i+1) = IF (i is even) THEN E(Xi,Xi) ELSE D(Xi,Xi) - X(i+1) = IF (i is even) THEN E(Xi,Xi) ELSE D(Xi,Xi) + to compute a sequence of 64-bit values: X0, X1, X2, ..., X16. Here + E(X,K) denotes the DES encryption of X using key K, and D(X,K) denotes + the DES decryption of X using key K. If you obtain - to compute a sequence of 64-bit values: X0, X1, X2, ..., X16. Here - E(X,K) denotes the DES encryption of X using key K, and D(X,K) denotes - the DES decryption of X using key K. If you obtain + X16 = 1B1A2DDB4C642438 - X16 = 1B1A2DDB4C642438 + your implementation does not have any of the 36,568 possible single-fault + errors described herein. + """ - your implementation does not have any of the 36,568 possible single-fault - errors described herein. - """ - def runTest(self): - from binascii import b2a_hex + def runTest(self): + from binascii import b2a_hex - X = [] - X[0:] = [b'\x94\x74\xB8\xE8\xC7\x3B\xCA\x7D'] + X = [] + X[0:] = [b"\x94\x74\xb8\xe8\xc7\x3b\xca\x7d"] - for i in range(16): - c = DES.new(X[i],DES.MODE_ECB) - if not (i&1): # (num&1) returns 1 for odd numbers - X[i+1:] = [c.encrypt(X[i])] # even - else: - X[i+1:] = [c.decrypt(X[i])] # odd + for i in range(16): + c = DES.new(X[i], DES.MODE_ECB) + if not (i & 1): # (num&1) returns 1 for odd numbers + X[i + 1 :] = [c.encrypt(X[i])] # even + else: + X[i + 1 :] = [c.decrypt(X[i])] # odd - self.assertEqual(b2a_hex(X[16]), - b2a_hex(b'\x1B\x1A\x2D\xDB\x4C\x64\x24\x38')) + self.assertEqual( + b2a_hex(X[16]), + b2a_hex(b"\x1b\x1a\x2d\xdb\x4c\x64\x24\x38"), + ) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter + + cipher = DES.new(b"4" * 8, DES.MODE_ECB) - def runTest(self): - # Encrypt/Decrypt data and test output parameter + pt = b"5" * 8 + ct = cipher.encrypt(pt) - cipher = DES.new(b'4'*8, DES.MODE_ECB) + output = bytearray(8) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - pt = b'5' * 8 - ct = cipher.encrypt(pt) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = bytearray(8) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(8)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(8)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*8) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*8) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 8) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 8) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from .common import make_block_tests - tests = make_block_tests(DES, "DES", test_data) - tests += [RonRivestTest()] - tests += [TestOutput()] - return tests + from .common import make_block_tests + + tests = make_block_tests(DES, "DES", test_data) + tests += [RonRivestTest()] + tests += [TestOutput()] + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_DES3.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_DES3.py index 8f8479ba..5e4920d6 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_DES3.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_DES3.py @@ -36,19 +36,24 @@ # This is a list of (plaintext, ciphertext, key, description) tuples. test_data = [ - # Test vector from Appendix B of NIST SP 800-67 - # "Recommendation for the Triple Data Encryption Algorithm (TDEA) Block - # Cipher" - # http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf - ('54686520717566636b2062726f776e20666f78206a756d70', - 'a826fd8ce53b855fcce21c8112256fe668d5c05dd9b6b900', - '0123456789abcdef23456789abcdef01456789abcdef0123', - 'NIST SP800-67 B.1'), - - # This test is designed to test the DES3 API, not the correctness of the - # output. - ('21e81b7ade88a259', '5c577d4d9b20c0f8', - '9b397ebf81b1181e282f4bb8adbadc6b', 'Two-key 3DES'), + # Test vector from Appendix B of NIST SP 800-67 + # "Recommendation for the Triple Data Encryption Algorithm (TDEA) Block + # Cipher" + # http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf + ( + "54686520717566636b2062726f776e20666f78206a756d70", + "a826fd8ce53b855fcce21c8112256fe668d5c05dd9b6b900", + "0123456789abcdef23456789abcdef01456789abcdef0123", + "NIST SP800-67 B.1", + ), + # This test is designed to test the DES3 API, not the correctness of the + # output. + ( + "21e81b7ade88a259", + "5c577d4d9b20c0f8", + "9b397ebf81b1181e282f4bb8adbadc6b", + "Two-key 3DES", + ), ] # NIST CAVP test vectors @@ -56,140 +61,169 @@ nist_tdes_mmt_files = ("TECBMMT2.rsp", "TECBMMT3.rsp") for tdes_file in nist_tdes_mmt_files: - - test_vectors = load_test_vectors( - ("Cipher", "TDES"), - tdes_file, - "TDES ECB (%s)" % tdes_file, - {"count": lambda x: int(x)}) or [] - - for index, tv in enumerate(test_vectors): - - # The test vector file contains some directive lines - if isinstance(tv, str): - continue - - key = tv.key1 + tv.key2 + tv.key3 - test_data_item = (tostr(hexlify(tv.plaintext)), - tostr(hexlify(tv.ciphertext)), - tostr(hexlify(key)), - "%s (%s)" % (tdes_file, index)) - test_data.append(test_data_item) + test_vectors = ( + load_test_vectors( + ("Cipher", "TDES"), + tdes_file, + "TDES ECB (%s)" % tdes_file, + {"count": lambda x: int(x)}, + ) + or [] + ) + + for index, tv in enumerate(test_vectors): + # The test vector file contains some directive lines + if isinstance(tv, str): + continue + + key = tv.key1 + tv.key2 + tv.key3 + test_data_item = ( + tostr(hexlify(tv.plaintext)), + tostr(hexlify(tv.ciphertext)), + tostr(hexlify(key)), + "%s (%s)" % (tdes_file, index), + ) + test_data.append(test_data_item) class CheckParity(unittest.TestCase): - - def test_parity_option2(self): - before_2k = unhexlify("CABF326FA56734324FFCCABCDEFACABF") - after_2k = DES3.adjust_key_parity(before_2k) - self.assertEqual(after_2k, - unhexlify("CBBF326EA46734324FFDCBBCDFFBCBBF")) - - def test_parity_option3(self): - before_3k = unhexlify("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC") - after_3k = DES3.adjust_key_parity(before_3k) - self.assertEqual(after_3k, - unhexlify("ABABABABABABABABBABABABABABABABACDCDCDCDCDCDCDCD")) - - def test_degradation(self): - sub_key1 = bchr(1) * 8 - sub_key2 = bchr(255) * 8 - - # K1 == K2 - self.assertRaises(ValueError, DES3.adjust_key_parity, - sub_key1 * 2 + sub_key2) - - # K2 == K3 - self.assertRaises(ValueError, DES3.adjust_key_parity, - sub_key1 + sub_key2 * 2) - - # K1 == K2 == K3 - self.assertRaises(ValueError, DES3.adjust_key_parity, - sub_key1 * 3) - - # K1 == K2 (with different parity) - self.assertRaises(ValueError, DES3.adjust_key_parity, - sub_key1 + strxor_c(sub_key1, 1) + sub_key2) + def test_parity_option2(self): + before_2k = unhexlify("CABF326FA56734324FFCCABCDEFACABF") + after_2k = DES3.adjust_key_parity(before_2k) + self.assertEqual( + after_2k, + unhexlify("CBBF326EA46734324FFDCBBCDFFBCBBF"), + ) + + def test_parity_option3(self): + before_3k = unhexlify("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC") + after_3k = DES3.adjust_key_parity(before_3k) + self.assertEqual( + after_3k, + unhexlify("ABABABABABABABABBABABABABABABABACDCDCDCDCDCDCDCD"), + ) + + def test_degradation(self): + sub_key1 = bchr(1) * 8 + sub_key2 = bchr(255) * 8 + + # K1 == K2 + self.assertRaises( + ValueError, + DES3.adjust_key_parity, + sub_key1 * 2 + sub_key2, + ) + + # K2 == K3 + self.assertRaises( + ValueError, + DES3.adjust_key_parity, + sub_key1 + sub_key2 * 2, + ) + + # K1 == K2 == K3 + self.assertRaises( + ValueError, + DES3.adjust_key_parity, + sub_key1 * 3, + ) + + # K1 == K2 (with different parity) + self.assertRaises( + ValueError, + DES3.adjust_key_parity, + sub_key1 + strxor_c(sub_key1, 1) + sub_key2, + ) class DegenerateToDESTest(unittest.TestCase): - - def runTest(self): - sub_key1 = bchr(1) * 8 - sub_key2 = bchr(255) * 8 - - # K1 == K2 - self.assertRaises(ValueError, DES3.new, - sub_key1 * 2 + sub_key2, - DES3.MODE_ECB) - - # K2 == K3 - self.assertRaises(ValueError, DES3.new, - sub_key1 + sub_key2 * 2, - DES3.MODE_ECB) - - # K1 == K2 == K3 - self.assertRaises(ValueError, DES3.new, - sub_key1 * 3, - DES3.MODE_ECB) - - # K2 == K3 (parity is ignored) - self.assertRaises(ValueError, DES3.new, - sub_key1 + sub_key2 + strxor_c(sub_key2, 0x1), - DES3.MODE_ECB) + def runTest(self): + sub_key1 = bchr(1) * 8 + sub_key2 = bchr(255) * 8 + + # K1 == K2 + self.assertRaises( + ValueError, + DES3.new, + sub_key1 * 2 + sub_key2, + DES3.MODE_ECB, + ) + + # K2 == K3 + self.assertRaises( + ValueError, + DES3.new, + sub_key1 + sub_key2 * 2, + DES3.MODE_ECB, + ) + + # K1 == K2 == K3 + self.assertRaises( + ValueError, + DES3.new, + sub_key1 * 3, + DES3.MODE_ECB, + ) + + # K2 == K3 (parity is ignored) + self.assertRaises( + ValueError, + DES3.new, + sub_key1 + sub_key2 + strxor_c(sub_key2, 0x1), + DES3.MODE_ECB, + ) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter - - cipher = DES3.new(b'4'*8 + b'G'*8 + b'T'*8, DES3.MODE_ECB) + cipher = DES3.new(b"4" * 8 + b"G" * 8 + b"T" * 8, DES3.MODE_ECB) - pt = b'5' * 16 - ct = cipher.encrypt(pt) + pt = b"5" * 16 + ct = cipher.encrypt(pt) - output = bytearray(16) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) + output = bytearray(16) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - output = memoryview(bytearray(16)) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + output = memoryview(bytearray(16)) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * 16) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * 16) - shorter_output = bytearray(7) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + shorter_output = bytearray(7) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - from .common import make_block_tests + from .common import make_block_tests - tests = [] - tests = make_block_tests(DES3, "DES3", test_data) - tests.append(DegenerateToDESTest()) - tests += list_test_cases(CheckParity) - tests += [TestOutput()] - return tests + tests = [] + tests = make_block_tests(DES3, "DES3", test_data) + tests.append(DegenerateToDESTest()) + tests += list_test_cases(CheckParity) + tests += [TestOutput()] + return tests -if __name__ == '__main__': - import unittest +if __name__ == "__main__": + import unittest - def suite(): - unittest.TestSuite(get_tests()) + def suite(): + unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_EAX.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_EAX.py index 4127a888..a83f0b68 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_EAX.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_EAX.py @@ -41,733 +41,836 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class EaxTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - key_192 = get_tag_random("key_192", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data_128 = get_tag_random("data_128", 16) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_loopback_64(self): - cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 8 * 100) - ct = cipher.encrypt(pt) - - cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # If not passed, the nonce is created randomly - cipher = AES.new(self.key_128, AES.MODE_EAX) - nonce1 = cipher.nonce - cipher = AES.new(self.key_128, AES.MODE_EAX) - nonce2 = cipher.nonce - self.assertEqual(len(nonce1), 16) - self.assertNotEqual(nonce1, nonce2) - - cipher = AES.new(self.key_128, AES.MODE_EAX, self.nonce_96) - ct = cipher.encrypt(self.data_128) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data_128)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_EAX, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce can be of any length (but not empty) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_EAX, - nonce=b"") - - for x in range(1, 128): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=bchr(1) * x) - cipher.encrypt(bchr(1)) - - def test_block_size_128(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_block_size_64(self): - cipher = DES3.new(self.key_192, AES.MODE_EAX, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, DES3.block_size) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 16 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_EAX).nonce - nonce2 = AES.new(self.key_128, AES.MODE_EAX).nonce - self.assertEqual(len(nonce1), 16) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_EAX, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_EAX, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96, - use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - # Invalid MAC length - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_EAX, - nonce=self.nonce_96, mac_len=2-1) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_EAX, - nonce=self.nonce_96, mac_len=16+1) - - # Valid MAC length - for mac_len in range(2, 16 + 1): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96, - mac_len=mac_len) - _, mac = cipher.encrypt_and_digest(self.data_128) - self.assertEqual(len(mac), mac_len) - - # Default MAC length - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data_128) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data_128) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b"" - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b"" - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data_128) - data_ba = bytearray(self.data_128) - - cipher1 = AES.new(self.key_128, - AES.MODE_EAX, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) - tag = cipher1.digest() - - cipher2 = AES.new(key_ba, - AES.MODE_EAX, - nonce=nonce_ba) - key_ba[:3] = b'\xFF\xFF\xFF' - nonce_ba[:3] = b'\xFF\xFF\xFF' - cipher2.update(header_ba) - header_ba[:3] = b'\xFF\xFF\xFF' - ct_test = cipher2.encrypt(data_ba) - data_ba[:3] = b'\x99\x99\x99' - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data_128) - ct_ba = bytearray(ct) - tag_ba = bytearray(tag) - del data_ba - - cipher3 = AES.new(key_ba, - AES.MODE_EAX, - nonce=nonce_ba) - key_ba[:3] = b'\xFF\xFF\xFF' - nonce_ba[:3] = b'\xFF\xFF\xFF' - cipher3.update(header_ba) - header_ba[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt(ct_ba) - ct_ba[:3] = b'\xFF\xFF\xFF' - cipher3.verify(tag_ba) - - self.assertEqual(pt_test, self.data_128) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data_128)) - data_mv = memoryview(bytearray(self.data_128)) - - cipher1 = AES.new(self.key_128, - AES.MODE_EAX, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) - tag = cipher1.digest() - - cipher2 = AES.new(key_mv, - AES.MODE_EAX, - nonce=nonce_mv) - key_mv[:3] = b'\xFF\xFF\xFF' - nonce_mv[:3] = b'\xFF\xFF\xFF' - cipher2.update(header_mv) - header_mv[:3] = b'\xFF\xFF\xFF' - ct_test = cipher2.encrypt(data_mv) - data_mv[:3] = b'\x99\x99\x99' - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data_128)) - ct_mv = memoryview(bytearray(ct)) - tag_mv = memoryview(bytearray(tag)) - del data_mv - - cipher3 = AES.new(key_mv, - AES.MODE_EAX, - nonce=nonce_mv) - key_mv[:3] = b'\xFF\xFF\xFF' - nonce_mv[:3] = b'\xFF\xFF\xFF' - cipher3.update(header_mv) - header_mv[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt(ct_mv) - ct_mv[:3] = b'\x99\x99\x99' - cipher3.verify(tag_mv) - - self.assertEqual(pt_test, self.data_128) - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - tag = cipher.digest() - - output = bytearray(128) - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - res, tag_out = cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - self.assertEqual(tag, tag_out) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - res = cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - - def test_output_param_neg(self): - LEN_PT = 16 - - pt = b'5' * LEN_PT - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT) - - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + key_128 = get_tag_random("key_128", 16) + key_192 = get_tag_random("key_192", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data_128 = get_tag_random("data_128", 16) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_loopback_64(self): + cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 8 * 100) + ct = cipher.encrypt(pt) + + cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # If not passed, the nonce is created randomly + cipher = AES.new(self.key_128, AES.MODE_EAX) + nonce1 = cipher.nonce + cipher = AES.new(self.key_128, AES.MODE_EAX) + nonce2 = cipher.nonce + self.assertEqual(len(nonce1), 16) + self.assertNotEqual(nonce1, nonce2) + + cipher = AES.new(self.key_128, AES.MODE_EAX, self.nonce_96) + ct = cipher.encrypt(self.data_128) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertEqual(ct, cipher.encrypt(self.data_128)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce can be of any length (but not empty) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce=b"", + ) + + for x in range(1, 128): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=bchr(1) * x) + cipher.encrypt(bchr(1)) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_block_size_64(self): + cipher = DES3.new(self.key_192, AES.MODE_EAX, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, DES3.block_size) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 16 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_EAX).nonce + nonce2 = AES.new(self.key_128, AES.MODE_EAX).nonce + self.assertEqual(len(nonce1), 16) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_EAX, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + # Invalid MAC length + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + mac_len=2 - 1, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + mac_len=16 + 1, + ) + + # Valid MAC length + for mac_len in range(2, 16 + 1): + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + mac_len=mac_len, + ) + _, mac = cipher.encrypt_and_digest(self.data_128) + self.assertEqual(len(mac), mac_len) + + # Default MAC length + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data_128) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data_128) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b"" + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b"" + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data_128) + data_ba = bytearray(self.data_128) + + cipher1 = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher1.update(self.data_128) + ct = cipher1.encrypt(self.data_128) + tag = cipher1.digest() + + cipher2 = AES.new( + key_ba, + AES.MODE_EAX, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + data_ba[:3] = b"\x99\x99\x99" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data_128) + ct_ba = bytearray(ct) + tag_ba = bytearray(tag) + del data_ba + + cipher3 = AES.new( + key_ba, + AES.MODE_EAX, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher3.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt(ct_ba) + ct_ba[:3] = b"\xff\xff\xff" + cipher3.verify(tag_ba) + + self.assertEqual(pt_test, self.data_128) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data_128)) + data_mv = memoryview(bytearray(self.data_128)) + + cipher1 = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher1.update(self.data_128) + ct = cipher1.encrypt(self.data_128) + tag = cipher1.digest() + + cipher2 = AES.new( + key_mv, + AES.MODE_EAX, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + data_mv[:3] = b"\x99\x99\x99" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data_128)) + ct_mv = memoryview(bytearray(ct)) + tag_mv = memoryview(bytearray(tag)) + del data_mv + + cipher3 = AES.new( + key_mv, + AES.MODE_EAX, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher3.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt(ct_mv) + ct_mv[:3] = b"\x99\x99\x99" + cipher3.verify(tag_mv) + + self.assertEqual(pt_test, self.data_128) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + tag = cipher.digest() + + output = bytearray(128) + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + res, tag_out = cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + self.assertEqual(tag, tag_out) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + res = cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + LEN_PT = 16 + + pt = b"5" * LEN_PT + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * LEN_PT) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * LEN_PT) + + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) class EaxFSMTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data_128 = get_tag_random("data_128", 16) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - # Verify path INIT->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.update(self.data_128) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.update(self.data_128) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - # Verify path INIT->UPDATE->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.update(self.data_128) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - cipher.update(self.data_128) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - for method_name in "encrypt", "decrypt": - for auth_data in (None, b"333", self.data_128, - self.data_128 + b"3"): - if auth_data is None: - assoc_len = None - else: - assoc_len = len(auth_data) - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data_128) - method(self.data_128) - method(self.data_128) - method(self.data_128) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(self.data_128) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(self.data_128) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(self.data_128) - ct, mac = cipher.encrypt_and_digest(self.data_128) - - # decrypt_and_verify - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.update(self.data_128) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data_128, pt) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_EAX, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data_128) - getattr(cipher, method1_name)(self.data_128) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data_128) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.encrypt(self.data_128) - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data_128) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data_128 = get_tag_random("data_128", 16) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + # Verify path INIT->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + # Verify path INIT->UPDATE->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + cipher.update(self.data_128) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b"333", + self.data_128, + self.data_128 + b"3", + ): + if auth_data is None: + assoc_len = None + else: + assoc_len = len(auth_data) + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data_128) + method(self.data_128) + method(self.data_128) + method(self.data_128) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(self.data_128) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(self.data_128) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(self.data_128) + ct, mac = cipher.encrypt_and_digest(self.data_128) + + # decrypt_and_verify + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.update(self.data_128) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data_128, pt) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_EAX, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data_128) + getattr(cipher, method1_name)(self.data_128) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data_128, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.encrypt(self.data_128) + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data_128) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + ct = cipher.encrypt(self.data_128) + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) + + cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data_128, + ) class TestVectorsPaper(unittest.TestCase): - """Class exercising the EAX test vectors found in - http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf""" - - test_vectors_hex = [ - ( '6bfb914fd07eae6b', - '', - '', - 'e037830e8389f27b025a2d6527e79d01', - '233952dee4d5ed5f9b9c6d6ff80ff478', - '62EC67F9C3A4A407FCB2A8C49031A8B3' - ), - ( - 'fa3bfd4806eb53fa', - 'f7fb', - '19dd', - '5c4c9331049d0bdab0277408f67967e5', - '91945d3f4dcbee0bf45ef52255f095a4', - 'BECAF043B0A23D843194BA972C66DEBD' - ), - ( '234a3463c1264ac6', - '1a47cb4933', - 'd851d5bae0', - '3a59f238a23e39199dc9266626c40f80', - '01f74ad64077f2e704c0f60ada3dd523', - '70C3DB4F0D26368400A10ED05D2BFF5E' - ), - ( - '33cce2eabff5a79d', - '481c9e39b1', - '632a9d131a', - 'd4c168a4225d8e1ff755939974a7bede', - 'd07cf6cbb7f313bdde66b727afd3c5e8', - '8408DFFF3C1A2B1292DC199E46B7D617' - ), - ( - 'aeb96eaebe2970e9', - '40d0c07da5e4', - '071dfe16c675', - 'cb0677e536f73afe6a14b74ee49844dd', - '35b6d0580005bbc12b0587124557d2c2', - 'FDB6B06676EEDC5C61D74276E1F8E816' - ), - ( - 'd4482d1ca78dce0f', - '4de3b35c3fc039245bd1fb7d', - '835bb4f15d743e350e728414', - 'abb8644fd6ccb86947c5e10590210a4f', - 'bd8e6e11475e60b268784c38c62feb22', - '6EAC5C93072D8E8513F750935E46DA1B' - ), - ( - '65d2017990d62528', - '8b0a79306c9ce7ed99dae4f87f8dd61636', - '02083e3979da014812f59f11d52630da30', - '137327d10649b0aa6e1c181db617d7f2', - '7c77d6e813bed5ac98baa417477a2e7d', - '1A8C98DCD73D38393B2BF1569DEEFC19' - ), - ( - '54b9f04e6a09189a', - '1bda122bce8a8dbaf1877d962b8592dd2d56', - '2ec47b2c4954a489afc7ba4897edcdae8cc3', - '3b60450599bd02c96382902aef7f832a', - '5fff20cafab119ca2fc73549e20f5b0d', - 'DDE59B97D722156D4D9AFF2BC7559826' - ), - ( - '899a175897561d7e', - '6cf36720872b8513f6eab1a8a44438d5ef11', - '0de18fd0fdd91e7af19f1d8ee8733938b1e8', - 'e7f6d2231618102fdb7fe55ff1991700', - 'a4a4782bcffd3ec5e7ef6d8c34a56123', - 'B781FCF2F75FA5A8DE97A9CA48E522EC' - ), - ( - '126735fcc320d25a', - 'ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7', - 'cb8920f87a6c75cff39627b56e3ed197c552d295a7', - 'cfc46afc253b4652b1af3795b124ab6e', - '8395fcf1e95bebd697bd010bc766aac3', - '22E7ADD93CFC6393C57EC0B3C17D6B44' - ), - ] - - test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - # Encrypt - cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Class exercising the EAX test vectors found in + http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf""" + + test_vectors_hex = [ + ( + "6bfb914fd07eae6b", + "", + "", + "e037830e8389f27b025a2d6527e79d01", + "233952dee4d5ed5f9b9c6d6ff80ff478", + "62EC67F9C3A4A407FCB2A8C49031A8B3", + ), + ( + "fa3bfd4806eb53fa", + "f7fb", + "19dd", + "5c4c9331049d0bdab0277408f67967e5", + "91945d3f4dcbee0bf45ef52255f095a4", + "BECAF043B0A23D843194BA972C66DEBD", + ), + ( + "234a3463c1264ac6", + "1a47cb4933", + "d851d5bae0", + "3a59f238a23e39199dc9266626c40f80", + "01f74ad64077f2e704c0f60ada3dd523", + "70C3DB4F0D26368400A10ED05D2BFF5E", + ), + ( + "33cce2eabff5a79d", + "481c9e39b1", + "632a9d131a", + "d4c168a4225d8e1ff755939974a7bede", + "d07cf6cbb7f313bdde66b727afd3c5e8", + "8408DFFF3C1A2B1292DC199E46B7D617", + ), + ( + "aeb96eaebe2970e9", + "40d0c07da5e4", + "071dfe16c675", + "cb0677e536f73afe6a14b74ee49844dd", + "35b6d0580005bbc12b0587124557d2c2", + "FDB6B06676EEDC5C61D74276E1F8E816", + ), + ( + "d4482d1ca78dce0f", + "4de3b35c3fc039245bd1fb7d", + "835bb4f15d743e350e728414", + "abb8644fd6ccb86947c5e10590210a4f", + "bd8e6e11475e60b268784c38c62feb22", + "6EAC5C93072D8E8513F750935E46DA1B", + ), + ( + "65d2017990d62528", + "8b0a79306c9ce7ed99dae4f87f8dd61636", + "02083e3979da014812f59f11d52630da30", + "137327d10649b0aa6e1c181db617d7f2", + "7c77d6e813bed5ac98baa417477a2e7d", + "1A8C98DCD73D38393B2BF1569DEEFC19", + ), + ( + "54b9f04e6a09189a", + "1bda122bce8a8dbaf1877d962b8592dd2d56", + "2ec47b2c4954a489afc7ba4897edcdae8cc3", + "3b60450599bd02c96382902aef7f832a", + "5fff20cafab119ca2fc73549e20f5b0d", + "DDE59B97D722156D4D9AFF2BC7559826", + ), + ( + "899a175897561d7e", + "6cf36720872b8513f6eab1a8a44438d5ef11", + "0de18fd0fdd91e7af19f1d8ee8733938b1e8", + "e7f6d2231618102fdb7fe55ff1991700", + "a4a4782bcffd3ec5e7ef6d8c34a56123", + "B781FCF2F75FA5A8DE97A9CA48E522EC", + ), + ( + "126735fcc320d25a", + "ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7", + "cb8920f87a6c75cff39627b56e3ed197c552d295a7", + "cfc46afc253b4652b1af3795b124ab6e", + "8395fcf1e95bebd697bd010bc766aac3", + "22E7ADD93CFC6393C57EC0B3C17D6B44", + ), + ] + + test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def setUp(self): - - def filter_tag(group): - return group['tagSize'] // 8 - - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aes_eax_test.json", - "Wycheproof EAX", - group_tag={'tag_size': filter_tag}) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt EAX Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) - except ValueError as e: - assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e) - return - - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt EAX Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) - except ValueError as e: - assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e) - return - - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def test_corrupt_decrypt(self, tv): - self._id = "Wycheproof Corrupt Decrypt EAX Test #" + str(tv.id) - if len(tv.iv) == 0 or len(tv.ct) < 1: - return - cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) - cipher.update(tv.aad) - ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) - self.test_corrupt_decrypt(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def setUp(self): + def filter_tag(group): + return group["tagSize"] // 8 + + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aes_eax_test.json", + "Wycheproof EAX", + group_tag={"tag_size": filter_tag}, + ) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt EAX Test #" + str(tv.id) + + try: + cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) + except ValueError as e: + assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e) + return + + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt EAX Test #" + str(tv.id) + + try: + cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) + except ValueError as e: + assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e) + return + + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def test_corrupt_decrypt(self, tv): + self._id = "Wycheproof Corrupt Decrypt EAX Test #" + str(tv.id) + if len(tv.iv) == 0 or len(tv.ct) < 1: + return + cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size) + cipher.update(tv.aad) + ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) + self.test_corrupt_decrypt(tv) class TestOtherCiphers(unittest.TestCase): + @classmethod + def create_test(cls, name, factory, key_size): + def test_template(self, factory=factory, key_size=key_size): + cipher = factory.new( + get_tag_random("cipher", key_size), + factory.MODE_EAX, + nonce=b"nonce", + ) + ct, mac = cipher.encrypt_and_digest(b"plaintext") - @classmethod - def create_test(cls, name, factory, key_size): - - def test_template(self, factory=factory, key_size=key_size): - cipher = factory.new(get_tag_random("cipher", key_size), - factory.MODE_EAX, - nonce=b"nonce") - ct, mac = cipher.encrypt_and_digest(b"plaintext") - - cipher = factory.new(get_tag_random("cipher", key_size), - factory.MODE_EAX, - nonce=b"nonce") - pt2 = cipher.decrypt_and_verify(ct, mac) + cipher = factory.new( + get_tag_random("cipher", key_size), + factory.MODE_EAX, + nonce=b"nonce", + ) + pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(b"plaintext", pt2) + self.assertEqual(b"plaintext", pt2) - setattr(cls, "test_" + name, test_template) + setattr(cls, "test_" + name, test_template) -from Cryptodome.Cipher import DES, DES3, ARC2, CAST, Blowfish +from Cryptodome.Cipher import DES, ARC2, CAST, Blowfish TestOtherCiphers.create_test("DES_" + str(DES.key_size), DES, DES.key_size) for ks in DES3.key_size: - TestOtherCiphers.create_test("DES3_" + str(ks), DES3, ks) + TestOtherCiphers.create_test("DES3_" + str(ks), DES3, ks) for ks in ARC2.key_size: - TestOtherCiphers.create_test("ARC2_" + str(ks), ARC2, ks) + TestOtherCiphers.create_test("ARC2_" + str(ks), ARC2, ks) for ks in CAST.key_size: - TestOtherCiphers.create_test("CAST_" + str(ks), CAST, ks) + TestOtherCiphers.create_test("CAST_" + str(ks), CAST, ks) for ks in Blowfish.key_size: - TestOtherCiphers.create_test("Blowfish_" + str(ks), Blowfish, ks) + TestOtherCiphers.create_test("Blowfish_" + str(ks), Blowfish, ks) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") - tests = [] - tests += list_test_cases(EaxTests) - tests += list_test_cases(EaxFSMTests) - tests += [ TestVectorsPaper() ] - tests += [ TestVectorsWycheproof(wycheproof_warnings) ] - tests += list_test_cases(TestOtherCiphers) - return tests + tests = [] + tests += list_test_cases(EaxTests) + tests += list_test_cases(EaxFSMTests) + tests += [TestVectorsPaper()] + tests += [TestVectorsWycheproof(wycheproof_warnings)] + tests += list_test_cases(TestOtherCiphers) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_GCM.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_GCM.py index ac8e7412..8f19663c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_GCM.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_GCM.py @@ -44,908 +44,1043 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class GcmTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # Nonce is optional (a random one will be created) - AES.new(self.key_128, AES.MODE_GCM) - - cipher = AES.new(self.key_128, AES.MODE_GCM, self.nonce_96) - ct = cipher.encrypt(self.data) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_GCM, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce can be of any length (but not empty) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_GCM, - nonce=b"") - - for x in range(1, 128): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=bchr(1) * x) - cipher.encrypt(bchr(1)) - - def test_block_size_128(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 15 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_GCM).nonce - nonce2 = AES.new(self.key_128, AES.MODE_GCM).nonce - self.assertEqual(len(nonce1), 16) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_GCM, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_GCM, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96, - use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - result = getattr(cipher, func)(b"") - self.assertEqual(result, b"") - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - # Invalid MAC length - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_GCM, - nonce=self.nonce_96, mac_len=3) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_GCM, - nonce=self.nonce_96, mac_len=16+1) - - # Valid MAC length - for mac_len in range(5, 16 + 1): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96, - mac_len=mac_len) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), mac_len) - - # Default MAC length - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b"" - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b"" - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - data_ba = bytearray(self.data) - - cipher1 = AES.new(self.key_128, - AES.MODE_GCM, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) - tag = cipher1.digest() - - cipher2 = AES.new(key_ba, - AES.MODE_GCM, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_ba) - data_ba[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - del data_ba - - cipher4 = AES.new(key_ba, - AES.MODE_GCM, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - data_mv = memoryview(bytearray(self.data)) - - cipher1 = AES.new(self.key_128, - AES.MODE_GCM, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) - tag = cipher1.digest() - - cipher2 = AES.new(key_mv, - AES.MODE_GCM, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_mv) - data_mv[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - del data_mv - - cipher4 = AES.new(key_mv, - AES.MODE_GCM, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - tag = cipher.digest() - - output = bytearray(128) - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - res, tag_out = cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - self.assertEqual(tag, tag_out) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - res = cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - - def test_output_param_neg(self): - LEN_PT = 128 - - pt = b'5' * LEN_PT - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT) - - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # Nonce is optional (a random one will be created) + AES.new(self.key_128, AES.MODE_GCM) + + cipher = AES.new(self.key_128, AES.MODE_GCM, self.nonce_96) + ct = cipher.encrypt(self.data) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertEqual(ct, cipher.encrypt(self.data)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce can be of any length (but not empty) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce=b"", + ) + + for x in range(1, 128): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=bchr(1) * x) + cipher.encrypt(bchr(1)) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 15 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_GCM).nonce + nonce2 = AES.new(self.key_128, AES.MODE_GCM).nonce + self.assertEqual(len(nonce1), 16) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_GCM, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + result = getattr(cipher, func)(b"") + self.assertEqual(result, b"") + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + # Invalid MAC length + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + mac_len=3, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + mac_len=16 + 1, + ) + + # Valid MAC length + for mac_len in range(5, 16 + 1): + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + mac_len=mac_len, + ) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), mac_len) + + # Default MAC length + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b"" + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b"" + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + data_ba = bytearray(self.data) + + cipher1 = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + tag = cipher1.digest() + + cipher2 = AES.new( + key_ba, + AES.MODE_GCM, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + data_ba[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + del data_ba + + cipher4 = AES.new( + key_ba, + AES.MODE_GCM, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher4.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + data_mv = memoryview(bytearray(self.data)) + + cipher1 = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + tag = cipher1.digest() + + cipher2 = AES.new( + key_mv, + AES.MODE_GCM, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + data_mv[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + del data_mv + + cipher4 = AES.new( + key_mv, + AES.MODE_GCM, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher4.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + tag = cipher.digest() + + output = bytearray(128) + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + res, tag_out = cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + self.assertEqual(tag, tag_out) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + res = cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + LEN_PT = 128 + + pt = b"5" * LEN_PT + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct = cipher.encrypt(pt) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * LEN_PT) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * LEN_PT) + + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) class GcmFSMTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - # Verify path INIT->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.update(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - # Verify path INIT->UPDATE->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.update(self.data) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.decrypt(ct) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - for method_name in "encrypt", "decrypt": - for auth_data in (None, b"333", self.data, - self.data + b"3"): - if auth_data is None: - assoc_len = None - else: - assoc_len = len(auth_data) - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data) - method(self.data) - method(self.data) - method(self.data) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(self.data) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(self.data) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(self.data) - ct, mac = cipher.encrypt_and_digest(self.data) - - # decrypt_and_verify - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.update(self.data) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data, pt) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_GCM, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data) - getattr(cipher, method1_name)(self.data) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.encrypt(self.data) - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + # Verify path INIT->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.update(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + # Verify path INIT->UPDATE->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.update(self.data) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.decrypt(ct) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b"333", + self.data, + self.data + b"3", + ): + if auth_data is None: + assoc_len = None + else: + assoc_len = len(auth_data) + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data) + method(self.data) + method(self.data) + method(self.data) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(self.data) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(self.data) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(self.data) + ct, mac = cipher.encrypt_and_digest(self.data) + + # decrypt_and_verify + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.update(self.data) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data, pt) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_GCM, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data) + getattr(cipher, method1_name)(self.data) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.encrypt(self.data) + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + ct = cipher.encrypt(self.data) + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.decrypt(ct) + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) class TestVectors(unittest.TestCase): - """Class exercising the GCM test vectors found in - http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf""" - - # List of test vectors, each made up of: - # - authenticated data - # - plaintext - # - ciphertext - # - MAC - # - AES key - # - nonce - test_vectors_hex = [ - ( - '', - '', - '', - '58e2fccefa7e3061367f1d57a4e7455a', - '00000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - '00000000000000000000000000000000', - '0388dace60b6a392f328c2b971b2fe78', - 'ab6e47d42cec13bdf53a67b21257bddf', - '00000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', - '42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' + - '21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985', - '4d5c2af327cd64a62cf35abd2ba6fab4', - 'feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' + - '21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091', - '5bc94fbc3221a5db94fae95ae7121a47', - 'feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423' + - '73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598', - '3612d2e79e3b0785561be14aaca2fccb', - 'feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbad' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7' + - '01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5', - '619cc5aefffe0bfa462af43c1699d050', - 'feffe9928665731c6d6a8f9467308308', - '9313225df88406e555909c5aff5269aa' + - '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' + - '16aedbf5a0de6a57a637b39b' - ), - ( - '', - '', - '', - 'cd33b28ac773f74ba00ed1f312572435', - '000000000000000000000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - '00000000000000000000000000000000', - '98e7247c07f0fe411c267e4384b0f600', - '2ff58d80033927ab8ef4d4587514f0fb', - '000000000000000000000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', - '3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' + - '7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256', - '9924a7c8587336bfb118024db8674a14', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' + - '7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710', - '2519498e80f1478f37ba55bd6d27618c', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057' + - 'fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7', - '65dcc57fcf623a24094fcca40d3533f8', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c', - 'cafebabefacedbad' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - 'd27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45' + - '81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b', - 'dcf566ff291c25bbb8568fc3d376a6d9', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c', - '9313225df88406e555909c5aff5269aa' + - '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' + - '16aedbf5a0de6a57a637b39b' - ), - ( - '', - '', - '', - '530f8afbc74536b9a963b4f1c4cb738b', - '0000000000000000000000000000000000000000000000000000000000000000', - '000000000000000000000000' - ), - ( - '', - '00000000000000000000000000000000', - 'cea7403d4d606b6e074ec5d3baf39d18', - 'd0d1c8a799996bf0265b98b5d48ab919', - '0000000000000000000000000000000000000000000000000000000000000000', - '000000000000000000000000' - ), - ( '', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', - '522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' + - '8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad', - 'b094dac5d93471bdec1a502270e3cc6c', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' + - '8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662', - '76fc6ece0f4e1768cddf8853bb2d551b', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbaddecaf888' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - 'c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0' + - 'feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f', - '3a337dbf46a792c45e454913fe2ea8f2', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', - 'cafebabefacedbad' - ), - ( - 'feedfacedeadbeeffeedfacedeadbeefabaddad2', - 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + - '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', - '5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4' + - '0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f', - 'a44a8266ee1c8eb0c8b5d4cf5ae9f19a', - 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', - '9313225df88406e555909c5aff5269aa' + - '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' + - '16aedbf5a0de6a57a637b39b' - ) - ] - - test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - - # Encrypt - cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac)) - cipher.update(assoc_data) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Class exercising the GCM test vectors found in + http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf""" + + # List of test vectors, each made up of: + # - authenticated data + # - plaintext + # - ciphertext + # - MAC + # - AES key + # - nonce + test_vectors_hex = [ + ( + "", + "", + "", + "58e2fccefa7e3061367f1d57a4e7455a", + "00000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "00000000000000000000000000000000", + "0388dace60b6a392f328c2b971b2fe78", + "ab6e47d42cec13bdf53a67b21257bddf", + "00000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985", + "4d5c2af327cd64a62cf35abd2ba6fab4", + "feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091", + "5bc94fbc3221a5db94fae95ae7121a47", + "feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423" + + "73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598", + "3612d2e79e3b0785561be14aaca2fccb", + "feffe9928665731c6d6a8f9467308308", + "cafebabefacedbad", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7" + + "01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5", + "619cc5aefffe0bfa462af43c1699d050", + "feffe9928665731c6d6a8f9467308308", + "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b", + ), + ( + "", + "", + "", + "cd33b28ac773f74ba00ed1f312572435", + "000000000000000000000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "00000000000000000000000000000000", + "98e7247c07f0fe411c267e4384b0f600", + "2ff58d80033927ab8ef4d4587514f0fb", + "000000000000000000000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c" + + "7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256", + "9924a7c8587336bfb118024db8674a14", + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c" + + "7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710", + "2519498e80f1478f37ba55bd6d27618c", + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057" + + "fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7", + "65dcc57fcf623a24094fcca40d3533f8", + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbad", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45" + + "81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b", + "dcf566ff291c25bbb8568fc3d376a6d9", + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b", + ), + ( + "", + "", + "", + "530f8afbc74536b9a963b4f1c4cb738b", + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "00000000000000000000000000000000", + "cea7403d4d606b6e074ec5d3baf39d18", + "d0d1c8a799996bf0265b98b5d48ab919", + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + ), + ( + "", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa" + + "8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad", + "b094dac5d93471bdec1a502270e3cc6c", + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa" + + "8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662", + "76fc6ece0f4e1768cddf8853bb2d551b", + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0" + + "feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f", + "3a337dbf46a792c45e454913fe2ea8f2", + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbad", + ), + ( + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4" + + "0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f", + "a44a8266ee1c8eb0c8b5d4cf5ae9f19a", + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b", + ), + ] + + test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac)) + cipher.update(assoc_data) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsGueronKrasnov(unittest.TestCase): - """Class exercising the GCM test vectors found in - 'The fragility of AES-GCM authentication algorithm', Gueron, Krasnov - https://eprint.iacr.org/2013/157.pdf""" - - def test_1(self): - key = unhexlify("3da6c536d6295579c0959a7043efb503") - iv = unhexlify("2b926197d34e091ef722db94") - aad = unhexlify("00000000000000000000000000000000" + - "000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f") - digest = unhexlify("69dd586555ce3fcc89663801a71d957b") - - cipher = AES.new(key, AES.MODE_GCM, iv).update(aad) - self.assertEqual(digest, cipher.digest()) - - def test_2(self): - key = unhexlify("843ffcf5d2b72694d19ed01d01249412") - iv = unhexlify("dbcca32ebf9b804617c3aa9e") - aad = unhexlify("00000000000000000000000000000000" + - "101112131415161718191a1b1c1d1e1f") - pt = unhexlify("000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f" + - "404142434445464748494a4b4c4d4e4f") - ct = unhexlify("6268c6fa2a80b2d137467f092f657ac0" + - "4d89be2beaa623d61b5a868c8f03ff95" + - "d3dcee23ad2f1ab3a6c80eaf4b140eb0" + - "5de3457f0fbc111a6b43d0763aa422a3" + - "013cf1dc37fe417d1fbfc449b75d4cc5") - digest = unhexlify("3b629ccfbc1119b7319e1dce2cd6fd6d") - - cipher = AES.new(key, AES.MODE_GCM, iv).update(aad) - ct2, digest2 = cipher.encrypt_and_digest(pt) - - self.assertEqual(ct, ct2) - self.assertEqual(digest, digest2) + """Class exercising the GCM test vectors found in + 'The fragility of AES-GCM authentication algorithm', Gueron, Krasnov + https://eprint.iacr.org/2013/157.pdf""" + + def test_1(self): + key = unhexlify("3da6c536d6295579c0959a7043efb503") + iv = unhexlify("2b926197d34e091ef722db94") + aad = unhexlify( + "00000000000000000000000000000000" + + "000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f", + ) + digest = unhexlify("69dd586555ce3fcc89663801a71d957b") + + cipher = AES.new(key, AES.MODE_GCM, iv).update(aad) + self.assertEqual(digest, cipher.digest()) + + def test_2(self): + key = unhexlify("843ffcf5d2b72694d19ed01d01249412") + iv = unhexlify("dbcca32ebf9b804617c3aa9e") + aad = unhexlify( + "00000000000000000000000000000000" + "101112131415161718191a1b1c1d1e1f", + ) + pt = unhexlify( + "000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f", + ) + ct = unhexlify( + "6268c6fa2a80b2d137467f092f657ac0" + + "4d89be2beaa623d61b5a868c8f03ff95" + + "d3dcee23ad2f1ab3a6c80eaf4b140eb0" + + "5de3457f0fbc111a6b43d0763aa422a3" + + "013cf1dc37fe417d1fbfc449b75d4cc5", + ) + digest = unhexlify("3b629ccfbc1119b7319e1dce2cd6fd6d") + + cipher = AES.new(key, AES.MODE_GCM, iv).update(aad) + ct2, digest2 = cipher.encrypt_and_digest(pt) + + self.assertEqual(ct, ct2) + self.assertEqual(digest, digest2) class NISTTestVectorsGCM(unittest.TestCase): - - def __init__(self, a): - self.use_clmul = True - unittest.TestCase.__init__(self, a) + def __init__(self, a): + self.use_clmul = True + unittest.TestCase.__init__(self, a) class NISTTestVectorsGCM_no_clmul(unittest.TestCase): + def __init__(self, a): + self.use_clmul = False + unittest.TestCase.__init__(self, a) + + +test_vectors_nist = ( + load_test_vectors( + ("Cipher", "AES"), + "gcmDecrypt128.rsp", + "GCM decrypt", + {"count": lambda x: int(x)}, + ) + or [] +) + +test_vectors_nist += ( + load_test_vectors( + ("Cipher", "AES"), + "gcmEncryptExtIV128.rsp", + "GCM encrypt", + {"count": lambda x: int(x)}, + ) + or [] +) - def __init__(self, a): - self.use_clmul = False - unittest.TestCase.__init__(self, a) - - -test_vectors_nist = load_test_vectors( - ("Cipher", "AES"), - "gcmDecrypt128.rsp", - "GCM decrypt", - {"count": lambda x: int(x)}) or [] +for idx, tv in enumerate(test_vectors_nist): + # The test vector file contains some directive lines + if isinstance(tv, str): + continue + + def single_test(self, tv=tv): + self.description = tv.desc + cipher = AES.new( + tv.key, + AES.MODE_GCM, + nonce=tv.iv, + mac_len=len(tv.tag), + use_clmul=self.use_clmul, + ) + cipher.update(tv.aad) + if "FAIL" in tv.others: + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + tv.ct, + tv.tag, + ) + else: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + self.assertEqual(pt, tv.pt) + + setattr(NISTTestVectorsGCM, "test_%d" % idx, single_test) + setattr(NISTTestVectorsGCM_no_clmul, "test_%d" % idx, single_test) -test_vectors_nist += load_test_vectors( - ("Cipher", "AES"), - "gcmEncryptExtIV128.rsp", - "GCM encrypt", - {"count": lambda x: int(x)}) or [] -for idx, tv in enumerate(test_vectors_nist): +class TestVectorsWycheproof(unittest.TestCase): + def __init__(self, wycheproof_warnings, **extra_params): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._extra_params = extra_params + self._id = "None" + + def setUp(self): + def filter_tag(group): + return group["tagSize"] // 8 + + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aes_gcm_test.json", + "Wycheproof GCM", + group_tag={"tag_size": filter_tag}, + ) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt GCM Test #" + str(tv.id) + + try: + cipher = AES.new( + tv.key, + AES.MODE_GCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + except ValueError as e: + if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e): + return + raise e + + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt GCM Test #" + str(tv.id) + + try: + cipher = AES.new( + tv.key, + AES.MODE_GCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + except ValueError as e: + if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e): + return + raise e + + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def test_corrupt_decrypt(self, tv): + self._id = "Wycheproof Corrupt Decrypt GCM Test #" + str(tv.id) + if len(tv.iv) == 0 or len(tv.ct) < 1: + return + cipher = AES.new( + tv.key, + AES.MODE_GCM, + tv.iv, + mac_len=tv.tag_size, + **self._extra_params, + ) + cipher.update(tv.aad) + ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) + self.test_corrupt_decrypt(tv) - # The test vector file contains some directive lines - if isinstance(tv, str): - continue - def single_test(self, tv=tv): +class TestVariableLength(unittest.TestCase): + def __init__(self, **extra_params): + unittest.TestCase.__init__(self) + self._extra_params = extra_params - self.description = tv.desc - cipher = AES.new(tv.key, AES.MODE_GCM, nonce=tv.iv, - mac_len=len(tv.tag), use_clmul=self.use_clmul) - cipher.update(tv.aad) - if "FAIL" in tv.others: - self.assertRaises(ValueError, cipher.decrypt_and_verify, - tv.ct, tv.tag) - else: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - self.assertEqual(pt, tv.pt) + def runTest(self): + key = b"0" * 16 + h = SHA256.new() - setattr(NISTTestVectorsGCM, "test_%d" % idx, single_test) - setattr(NISTTestVectorsGCM_no_clmul, "test_%d" % idx, single_test) + for length in range(160): + nonce = "{0:04d}".format(length).encode("utf-8") + data = bchr(length) * length + cipher = AES.new(key, AES.MODE_GCM, nonce=nonce, **self._extra_params) + ct, tag = cipher.encrypt_and_digest(data) + h.update(ct) + h.update(tag) + self.assertEqual(h.hexdigest(), "7b7eb1ffbe67a2e53a912067c0ec8e62ebc7ce4d83490ea7426941349811bdf4") -class TestVectorsWycheproof(unittest.TestCase): - def __init__(self, wycheproof_warnings, **extra_params): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._extra_params = extra_params - self._id = "None" - - def setUp(self): - - def filter_tag(group): - return group['tagSize'] // 8 - - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aes_gcm_test.json", - "Wycheproof GCM", - group_tag={'tag_size': filter_tag}) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt GCM Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - except ValueError as e: - if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e): - return - raise e - - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt GCM Test #" + str(tv.id) - - try: - cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - except ValueError as e: - if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e): - return - raise e - - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def test_corrupt_decrypt(self, tv): - self._id = "Wycheproof Corrupt Decrypt GCM Test #" + str(tv.id) - if len(tv.iv) == 0 or len(tv.ct) < 1: - return - cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size, - **self._extra_params) - cipher.update(tv.aad) - ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01") - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) - self.test_corrupt_decrypt(tv) +def get_tests(config={}): + from Cryptodome.Util import _cpu_features + wycheproof_warnings = config.get("wycheproof_warnings") -class TestVariableLength(unittest.TestCase): + tests = [] + tests += list_test_cases(GcmTests) + tests += list_test_cases(GcmFSMTests) + tests += [TestVectors()] + tests += [TestVectorsWycheproof(wycheproof_warnings)] + tests += list_test_cases(TestVectorsGueronKrasnov) + tests += [TestVariableLength()] + if config.get("slow_tests"): + tests += list_test_cases(NISTTestVectorsGCM) - def __init__(self, **extra_params): - unittest.TestCase.__init__(self) - self._extra_params = extra_params + if _cpu_features.have_clmul(): + tests += [TestVectorsWycheproof(wycheproof_warnings, use_clmul=False)] + tests += [TestVariableLength(use_clmul=False)] + if config.get("slow_tests"): + tests += list_test_cases(NISTTestVectorsGCM_no_clmul) + else: + print("Skipping test of PCLMULDQD in AES GCM") - def runTest(self): - key = b'0' * 16 - h = SHA256.new() + return tests - for length in range(160): - nonce = '{0:04d}'.format(length).encode('utf-8') - data = bchr(length) * length - cipher = AES.new(key, AES.MODE_GCM, nonce=nonce, **self._extra_params) - ct, tag = cipher.encrypt_and_digest(data) - h.update(ct) - h.update(tag) - self.assertEqual(h.hexdigest(), "7b7eb1ffbe67a2e53a912067c0ec8e62ebc7ce4d83490ea7426941349811bdf4") +if __name__ == "__main__": + def suite(): + unittest.TestSuite(get_tests()) -def get_tests(config={}): - from Cryptodome.Util import _cpu_features - - wycheproof_warnings = config.get('wycheproof_warnings') - - tests = [] - tests += list_test_cases(GcmTests) - tests += list_test_cases(GcmFSMTests) - tests += [TestVectors()] - tests += [TestVectorsWycheproof(wycheproof_warnings)] - tests += list_test_cases(TestVectorsGueronKrasnov) - tests += [TestVariableLength()] - if config.get('slow_tests'): - tests += list_test_cases(NISTTestVectorsGCM) - - if _cpu_features.have_clmul(): - tests += [TestVectorsWycheproof(wycheproof_warnings, use_clmul=False)] - tests += [TestVariableLength(use_clmul=False)] - if config.get('slow_tests'): - tests += list_test_cases(NISTTestVectorsGCM_no_clmul) - else: - print("Skipping test of PCLMULDQD in AES GCM") - - return tests - - -if __name__ == '__main__': - def suite(): - unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_KW.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_KW.py index 4b530cf8..d7eb814d 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_KW.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_KW.py @@ -7,169 +7,183 @@ class KW_Tests(unittest.TestCase): - - # From RFC3394 - tvs = [ - ("000102030405060708090A0B0C0D0E0F", - "00112233445566778899AABBCCDDEEFF", - "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5"), - ("000102030405060708090A0B0C0D0E0F1011121314151617", - "00112233445566778899AABBCCDDEEFF", - "96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D"), - ("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "00112233445566778899AABBCCDDEEFF", - "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7"), - ("000102030405060708090A0B0C0D0E0F1011121314151617", - "00112233445566778899AABBCCDDEEFF0001020304050607", - "031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2"), - ("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "00112233445566778899AABBCCDDEEFF0001020304050607", - "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1"), - ("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F", - "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21"), - ] - - def test_rfc3394(self): - for tv in self.tvs: - kek, pt, ct = [bytes.fromhex(x) for x in tv] - - cipher = AES.new(kek, AES.MODE_KW) - ct2 = cipher.seal(pt) - - self.assertEqual(ct, ct2) - - cipher = AES.new(kek, AES.MODE_KW) - pt2 = cipher.unseal(ct) - self.assertEqual(pt, pt2) - - def test_neg1(self): - - cipher = AES.new(b'-' * 16, AES.MODE_KW) - - with self.assertRaises(ValueError): - cipher.seal(b'') - - with self.assertRaises(ValueError): - cipher.seal(b'8' * 17) - - def test_neg2(self): - - cipher = AES.new(b'-' * 16, AES.MODE_KW) - ct = bytearray(cipher.seal(b'7' * 16)) - - cipher = AES.new(b'-' * 16, AES.MODE_KW) - cipher.unseal(ct) - - cipher = AES.new(b'-' * 16, AES.MODE_KW) - ct[0] ^= 0xFF - with self.assertRaises(ValueError): - cipher.unseal(ct) + # From RFC3394 + tvs = [ + ( + "000102030405060708090A0B0C0D0E0F", + "00112233445566778899AABBCCDDEEFF", + "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5", + ), + ( + "000102030405060708090A0B0C0D0E0F1011121314151617", + "00112233445566778899AABBCCDDEEFF", + "96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D", + ), + ( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "00112233445566778899AABBCCDDEEFF", + "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7", + ), + ( + "000102030405060708090A0B0C0D0E0F1011121314151617", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2", + ), + ( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1", + ), + ( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F", + "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21", + ), + ] + + def test_rfc3394(self): + for tv in self.tvs: + kek, pt, ct = [bytes.fromhex(x) for x in tv] + + cipher = AES.new(kek, AES.MODE_KW) + ct2 = cipher.seal(pt) + + self.assertEqual(ct, ct2) + + cipher = AES.new(kek, AES.MODE_KW) + pt2 = cipher.unseal(ct) + self.assertEqual(pt, pt2) + + def test_neg1(self): + cipher = AES.new(b"-" * 16, AES.MODE_KW) + + with self.assertRaises(ValueError): + cipher.seal(b"") + + with self.assertRaises(ValueError): + cipher.seal(b"8" * 17) + + def test_neg2(self): + cipher = AES.new(b"-" * 16, AES.MODE_KW) + ct = bytearray(cipher.seal(b"7" * 16)) + + cipher = AES.new(b"-" * 16, AES.MODE_KW) + cipher.unseal(ct) + + cipher = AES.new(b"-" * 16, AES.MODE_KW) + ct[0] ^= 0xFF + with self.assertRaises(ValueError): + cipher.unseal(ct) class KW_Wycheproof(unittest.TestCase): - - def setUp(self): - self.vectors = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "kw_test.json", - "Wycheproof tests for KW") - - def test_wycheproof(self): - - if not self.vectors: - self.skipTest("No test vectors available") - - for vector in self.vectors: - with self.subTest(testId=vector.id): - cipher = AES.new(vector.key, AES.MODE_KW) - - try: - cipher.seal(vector.msg) - except ValueError: - if vector.valid: - raise - continue - - cipher = AES.new(vector.key, AES.MODE_KW) - try: - pt = cipher.unseal(vector.ct) - except ValueError: - if vector.valid: - raise - continue - - self.assertEqual(pt, vector.msg) + def setUp(self): + self.vectors = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "kw_test.json", + "Wycheproof tests for KW", + ) + + def test_wycheproof(self): + if not self.vectors: + self.skipTest("No test vectors available") + + for vector in self.vectors: + with self.subTest(testId=vector.id): + cipher = AES.new(vector.key, AES.MODE_KW) + + try: + cipher.seal(vector.msg) + except ValueError: + if vector.valid: + raise + continue + + cipher = AES.new(vector.key, AES.MODE_KW) + try: + pt = cipher.unseal(vector.ct) + except ValueError: + if vector.valid: + raise + continue + + self.assertEqual(pt, vector.msg) class KWP_Tests(unittest.TestCase): + tvs = [ + ( + "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8", + "c37b7e6492584340bed12207808941155068f738", + "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a", + ), + ( + "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8", + "466f7250617369", + "afbeb0f07dfbf5419200f2ccb50bb24f", + ), + ] - tvs = [ - ("5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8", - "c37b7e6492584340bed12207808941155068f738", - "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a"), - ("5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8", - "466f7250617369", - "afbeb0f07dfbf5419200f2ccb50bb24f"), - ] + def test_rfc5649(self): + for tv in self.tvs: + kek, pt, ct = [bytes.fromhex(x) for x in tv] - def test_rfc5649(self): - for tv in self.tvs: - kek, pt, ct = [bytes.fromhex(x) for x in tv] + cipher = AES.new(kek, AES.MODE_KWP) + ct2 = cipher.seal(pt) - cipher = AES.new(kek, AES.MODE_KWP) - ct2 = cipher.seal(pt) + self.assertEqual(ct, ct2) - self.assertEqual(ct, ct2) - - cipher = AES.new(kek, AES.MODE_KWP) - pt2 = cipher.unseal(ct) - self.assertEqual(pt, pt2) + cipher = AES.new(kek, AES.MODE_KWP) + pt2 = cipher.unseal(ct) + self.assertEqual(pt, pt2) class KWP_Wycheproof(unittest.TestCase): + def setUp(self): + self.vectors = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "kwp_test.json", + "Wycheproof tests for KWP", + ) + + def test_wycheproof(self): + if not self.vectors: + self.skipTest("No test vectors available") + + for vector in self.vectors: + with self.subTest(testId=vector.id): + cipher = AES.new(vector.key, AES.MODE_KWP) + + try: + cipher.seal(vector.msg) + except ValueError: + if vector.valid and not vector.warning: + raise + continue + + cipher = AES.new(vector.key, AES.MODE_KWP) + try: + pt = cipher.unseal(vector.ct) + except ValueError: + if vector.valid and not vector.warning: + raise + continue + + self.assertEqual(pt, vector.msg) - def setUp(self): - self.vectors = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "kwp_test.json", - "Wycheproof tests for KWP") - - def test_wycheproof(self): - - if not self.vectors: - self.skipTest("No test vectors available") - for vector in self.vectors: - with self.subTest(testId=vector.id): - cipher = AES.new(vector.key, AES.MODE_KWP) - - try: - cipher.seal(vector.msg) - except ValueError: - if vector.valid and not vector.warning: - raise - continue +def get_tests(config={}): + tests = [] + tests += list_test_cases(KW_Tests) + tests += list_test_cases(KWP_Tests) + tests += list_test_cases(KW_Wycheproof) + tests += list_test_cases(KWP_Wycheproof) + return tests - cipher = AES.new(vector.key, AES.MODE_KWP) - try: - pt = cipher.unseal(vector.ct) - except ValueError: - if vector.valid and not vector.warning: - raise - continue - self.assertEqual(pt, vector.msg) +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -def get_tests(config={}): - tests = [] - tests += list_test_cases(KW_Tests) - tests += list_test_cases(KWP_Tests) - tests += list_test_cases(KW_Wycheproof) - tests += list_test_cases(KWP_Wycheproof) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OCB.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OCB.py index 1f2ffbc5..ec3799a5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OCB.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OCB.py @@ -41,805 +41,922 @@ def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class OcbTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct, mac = cipher.encrypt_and_digest(pt) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # Nonce is optional - AES.new(self.key_128, AES.MODE_OCB) - - cipher = AES.new(self.key_128, AES.MODE_OCB, self.nonce_96) - ct = cipher.encrypt(self.data) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertEqual(ct, cipher.encrypt(self.data)) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_OCB, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce cannot be empty - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, - nonce=b("")) - - # nonce can be up to 15 bytes long - for length in range(1, 16): - AES.new(self.key_128, AES.MODE_OCB, nonce=self.data[:length]) - - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, - nonce=self.data) - - def test_block_size_128(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - # By default, a 15 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce - nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce - self.assertEqual(len(nonce1), 15) - self.assertNotEqual(nonce1, nonce2) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, a 15 bytes long nonce is randomly generated - nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce - nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce - self.assertEqual(len(nonce1), 15) - self.assertNotEqual(nonce1, nonce2) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_OCB, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_OCB, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96, - use_aesni=False) - - def test_null_encryption_decryption(self): - for func in "encrypt", "decrypt": - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - result = getattr(cipher, func)(b("")) - self.assertEqual(result, b("")) - - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.encrypt(b("xyz")) - self.assertRaises(TypeError, cipher.decrypt, b("xyz")) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.decrypt(b("xyz")) - self.assertRaises(TypeError, cipher.encrypt, b("xyz")) - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*') - - def test_mac_len(self): - # Invalid MAC length - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, - nonce=self.nonce_96, mac_len=7) - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, - nonce=self.nonce_96, mac_len=16+1) - - # Valid MAC length - for mac_len in range(8, 16 + 1): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96, - mac_len=mac_len) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), mac_len) - - # Default MAC length - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_message_chunks(self): - # Validate that both associated data and plaintext/ciphertext - # can be broken up in chunks of arbitrary length - - auth_data = get_tag_random("authenticated data", 127) - plaintext = get_tag_random("plaintext", 127) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(auth_data) - ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) - - def break_up(data, chunk_length): - return [data[i:i+chunk_length] for i in range(0, len(data), - chunk_length)] - - # Encryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - pt2 = b("") - for chunk in break_up(ciphertext, chunk_length): - pt2 += cipher.decrypt(chunk) - pt2 += cipher.decrypt() - self.assertEqual(plaintext, pt2) - cipher.verify(ref_mac) - - # Decryption - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - - for chunk in break_up(auth_data, chunk_length): - cipher.update(chunk) - ct2 = b("") - for chunk in break_up(plaintext, chunk_length): - ct2 += cipher.encrypt(chunk) - ct2 += cipher.encrypt() - self.assertEqual(ciphertext, ct2) - self.assertEqual(cipher.digest(), ref_mac) - - def test_bytearray(self): - - # Encrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - data_ba = bytearray(self.data) - - cipher1 = AES.new(self.key_128, - AES.MODE_OCB, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) + cipher1.encrypt() - tag = cipher1.digest() - - cipher2 = AES.new(key_ba, - AES.MODE_OCB, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_ba) + cipher2.encrypt() - data_ba[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_ba = bytearray(self.key_128) - nonce_ba = bytearray(self.nonce_96) - header_ba = bytearray(self.data) - del data_ba - - cipher4 = AES.new(key_ba, - AES.MODE_OCB, - nonce=nonce_ba) - key_ba[:3] = b"\xFF\xFF\xFF" - nonce_ba[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_ba) - header_ba[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) - - self.assertEqual(self.data, pt_test) - - def test_memoryview(self): - - # Encrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - data_mv = memoryview(bytearray(self.data)) - - cipher1 = AES.new(self.key_128, - AES.MODE_OCB, - nonce=self.nonce_96) - cipher1.update(self.data) - ct = cipher1.encrypt(self.data) + cipher1.encrypt() - tag = cipher1.digest() - - cipher2 = AES.new(key_mv, - AES.MODE_OCB, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher2.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - ct_test = cipher2.encrypt(data_mv) + cipher2.encrypt() - data_mv[:3] = b"\xFF\xFF\xFF" - tag_test = cipher2.digest() - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key_mv = memoryview(bytearray(self.key_128)) - nonce_mv = memoryview(bytearray(self.nonce_96)) - header_mv = memoryview(bytearray(self.data)) - del data_mv - - cipher4 = AES.new(key_mv, - AES.MODE_OCB, - nonce=nonce_mv) - key_mv[:3] = b"\xFF\xFF\xFF" - nonce_mv[:3] = b"\xFF\xFF\xFF" - cipher4.update(header_mv) - header_mv[:3] = b"\xFF\xFF\xFF" - pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) - - self.assertEqual(self.data, pt_test) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct, mac = cipher.encrypt_and_digest(pt) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # Nonce is optional + AES.new(self.key_128, AES.MODE_OCB) + + cipher = AES.new(self.key_128, AES.MODE_OCB, self.nonce_96) + ct = cipher.encrypt(self.data) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertEqual(ct, cipher.encrypt(self.data)) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce cannot be empty + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=b(""), + ) + + # nonce can be up to 15 bytes long + for length in range(1, 16): + AES.new(self.key_128, AES.MODE_OCB, nonce=self.data[:length]) + + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=self.data, + ) + + def test_block_size_128(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + # By default, a 15 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce + nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce + self.assertEqual(len(nonce1), 15) + self.assertNotEqual(nonce1, nonce2) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, a 15 bytes long nonce is randomly generated + nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce + nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce + self.assertEqual(len(nonce1), 15) + self.assertNotEqual(nonce1, nonce2) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_OCB, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_null_encryption_decryption(self): + for func in "encrypt", "decrypt": + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + result = getattr(cipher, func)(b("")) + self.assertEqual(result, b("")) + + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.encrypt(b("xyz")) + self.assertRaises(TypeError, cipher.decrypt, b("xyz")) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.decrypt(b("xyz")) + self.assertRaises(TypeError, cipher.encrypt, b("xyz")) + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt, "test1234567890-*") + + def test_mac_len(self): + # Invalid MAC length + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + mac_len=7, + ) + self.assertRaises( + ValueError, + AES.new, + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + mac_len=16 + 1, + ) + + # Valid MAC length + for mac_len in range(8, 16 + 1): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + mac_len=mac_len, + ) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), mac_len) + + # Default MAC length + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_message_chunks(self): + # Validate that both associated data and plaintext/ciphertext + # can be broken up in chunks of arbitrary length + + auth_data = get_tag_random("authenticated data", 127) + plaintext = get_tag_random("plaintext", 127) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(auth_data) + ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext) + + def break_up(data, chunk_length): + return [ + data[i : i + chunk_length] + for i in range( + 0, + len(data), + chunk_length, + ) + ] + + # Encryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + pt2 = b("") + for chunk in break_up(ciphertext, chunk_length): + pt2 += cipher.decrypt(chunk) + pt2 += cipher.decrypt() + self.assertEqual(plaintext, pt2) + cipher.verify(ref_mac) + + # Decryption + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + + for chunk in break_up(auth_data, chunk_length): + cipher.update(chunk) + ct2 = b("") + for chunk in break_up(plaintext, chunk_length): + ct2 += cipher.encrypt(chunk) + ct2 += cipher.encrypt() + self.assertEqual(ciphertext, ct2) + self.assertEqual(cipher.digest(), ref_mac) + + def test_bytearray(self): + # Encrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + data_ba = bytearray(self.data) + + cipher1 = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + cipher1.encrypt() + tag = cipher1.digest() + + cipher2 = AES.new( + key_ba, + AES.MODE_OCB, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher2.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_ba) + cipher2.encrypt() + data_ba[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_ba = bytearray(self.key_128) + nonce_ba = bytearray(self.nonce_96) + header_ba = bytearray(self.data) + del data_ba + + cipher4 = AES.new( + key_ba, + AES.MODE_OCB, + nonce=nonce_ba, + ) + key_ba[:3] = b"\xff\xff\xff" + nonce_ba[:3] = b"\xff\xff\xff" + cipher4.update(header_ba) + header_ba[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test)) + + self.assertEqual(self.data, pt_test) + + def test_memoryview(self): + # Encrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + data_mv = memoryview(bytearray(self.data)) + + cipher1 = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct = cipher1.encrypt(self.data) + cipher1.encrypt() + tag = cipher1.digest() + + cipher2 = AES.new( + key_mv, + AES.MODE_OCB, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher2.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + ct_test = cipher2.encrypt(data_mv) + cipher2.encrypt() + data_mv[:3] = b"\xff\xff\xff" + tag_test = cipher2.digest() + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key_mv = memoryview(bytearray(self.key_128)) + nonce_mv = memoryview(bytearray(self.nonce_96)) + header_mv = memoryview(bytearray(self.data)) + del data_mv + + cipher4 = AES.new( + key_mv, + AES.MODE_OCB, + nonce=nonce_mv, + ) + key_mv[:3] = b"\xff\xff\xff" + nonce_mv[:3] = b"\xff\xff\xff" + cipher4.update(header_mv) + header_mv[:3] = b"\xff\xff\xff" + pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test)) + + self.assertEqual(self.data, pt_test) class OcbFSMTests(unittest.TestCase): - - key_128 = get_tag_random("key_128", 16) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_valid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->ENCRYPT(NONE)->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - ct += cipher.encrypt() - mac = cipher.digest() - - # Verify path INIT->DECRYPT->DECRYPT(NONCE)->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.decrypt() - cipher.verify(mac) - - def test_invalid_init_encrypt_decrypt_digest_verify(self): - # No authenticated data, fixed plaintext - # Verify path INIT->ENCRYPT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - self.assertRaises(TypeError, cipher.digest) - - # Verify path INIT->DECRYPT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.decrypt(ct) - self.assertRaises(TypeError, cipher.verify) - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - # Verify path INIT->UPDATE->ENCRYPT->ENCRYPT(NONE)->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - ct = cipher.encrypt(self.data) - ct += cipher.encrypt() - mac = cipher.digest() - - # Verify path INIT->UPDATE->DECRYPT->DECRYPT(NONE)->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.decrypt(ct) - cipher.decrypt() - cipher.verify(mac) - - # Verify path INIT->UPDATE->ENCRYPT->ENCRYPT_AND_DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - ct1 = cipher.encrypt(self.data[:2]) - ct2, mac = cipher.encrypt_and_digest(self.data[2:]) - - # Verify path INIT->UPDATE->DECRYPT->DECRYPT_AND_VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.decrypt(ct1) - cipher.decrypt_and_verify(ct2, mac) - - def test_invalid_encrypt_after_final(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.encrypt(self.data) - cipher.encrypt() - self.assertRaises(TypeError, cipher.encrypt, self.data) - - def test_invalid_decrypt_after_final(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.decrypt(self.data) - cipher.decrypt() - self.assertRaises(TypeError, cipher.decrypt, self.data) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_encrypt_or_decrypt(self): - for method_name in "encrypt", "decrypt": - for auth_data in (None, b("333"), self.data, - self.data + b("3")): - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - if auth_data is not None: - cipher.update(auth_data) - method = getattr(cipher, method_name) - method(self.data) - method(self.data) - method(self.data) - method(self.data) - method() - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(self.data) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(self.data) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(self.data) - ct, mac = cipher.encrypt_and_digest(self.data) - - # decrypt_and_verify - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.update(self.data) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data, pt) - - def test_invalid_mixing_encrypt_decrypt(self): - # Once per method, with or without assoc. data - for method1_name, method2_name in (("encrypt", "decrypt"), - ("decrypt", "encrypt")): - for assoc_data_present in (True, False): - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - if assoc_data_present: - cipher.update(self.data) - getattr(cipher, method1_name)(self.data) - self.assertRaises(TypeError, getattr(cipher, method2_name), - self.data) - - def test_invalid_encrypt_or_update_after_digest(self): - for method_name in "encrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.encrypt(self.data) - cipher.encrypt() - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - - def test_invalid_decrypt_or_update_after_verify(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - ct = cipher.encrypt(self.data) - ct += cipher.encrypt() - mac = cipher.digest() - - for method_name in "decrypt", "update": - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.decrypt(ct) - cipher.decrypt() - cipher.verify(mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data) + key_128 = get_tag_random("key_128", 16) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_valid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->ENCRYPT(NONE)->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data) + ct += cipher.encrypt() + mac = cipher.digest() + + # Verify path INIT->DECRYPT->DECRYPT(NONCE)->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + cipher.decrypt() + cipher.verify(mac) + + def test_invalid_init_encrypt_decrypt_digest_verify(self): + # No authenticated data, fixed plaintext + # Verify path INIT->ENCRYPT->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + ct = cipher.encrypt(self.data) + self.assertRaises(TypeError, cipher.digest) + + # Verify path INIT->DECRYPT->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.decrypt(ct) + self.assertRaises(TypeError, cipher.verify) + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.verify(mac) + + def test_valid_full_path(self): + # Fixed authenticated data, fixed plaintext + # Verify path INIT->UPDATE->ENCRYPT->ENCRYPT(NONE)->DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + ct = cipher.encrypt(self.data) + ct += cipher.encrypt() + mac = cipher.digest() + + # Verify path INIT->UPDATE->DECRYPT->DECRYPT(NONE)->VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.decrypt(ct) + cipher.decrypt() + cipher.verify(mac) + + # Verify path INIT->UPDATE->ENCRYPT->ENCRYPT_AND_DIGEST + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + ct1 = cipher.encrypt(self.data[:2]) + ct2, mac = cipher.encrypt_and_digest(self.data[2:]) + + # Verify path INIT->UPDATE->DECRYPT->DECRYPT_AND_VERIFY + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.decrypt(ct1) + cipher.decrypt_and_verify(ct2, mac) + + def test_invalid_encrypt_after_final(self): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.encrypt(self.data) + cipher.encrypt() + self.assertRaises(TypeError, cipher.encrypt, self.data) + + def test_invalid_decrypt_after_final(self): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.decrypt(self.data) + cipher.decrypt() + self.assertRaises(TypeError, cipher.decrypt, self.data) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_encrypt_or_decrypt(self): + for method_name in "encrypt", "decrypt": + for auth_data in ( + None, + b("333"), + self.data, + self.data + b("3"), + ): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + if auth_data is not None: + cipher.update(auth_data) + method = getattr(cipher, method_name) + method(self.data) + method(self.data) + method(self.data) + method(self.data) + method() + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(self.data) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(self.data) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(self.data) + ct, mac = cipher.encrypt_and_digest(self.data) + + # decrypt_and_verify + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.update(self.data) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data, pt) + + def test_invalid_mixing_encrypt_decrypt(self): + # Once per method, with or without assoc. data + for method1_name, method2_name in ( + ("encrypt", "decrypt"), + ("decrypt", "encrypt"), + ): + for assoc_data_present in (True, False): + cipher = AES.new( + self.key_128, + AES.MODE_OCB, + nonce=self.nonce_96, + ) + if assoc_data_present: + cipher.update(self.data) + getattr(cipher, method1_name)(self.data) + self.assertRaises( + TypeError, + getattr(cipher, method2_name), + self.data, + ) + + def test_invalid_encrypt_or_update_after_digest(self): + for method_name in "encrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.encrypt(self.data) + cipher.encrypt() + cipher.digest() + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + + def test_invalid_decrypt_or_update_after_verify(self): + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + ct = cipher.encrypt(self.data) + ct += cipher.encrypt() + mac = cipher.digest() + + for method_name in "decrypt", "update": + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.decrypt(ct) + cipher.decrypt() + cipher.verify(mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) + + cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, mac) + self.assertRaises( + TypeError, + getattr(cipher, method_name), + self.data, + ) def algo_rfc7253(keylen, taglen, noncelen): - """Implement the algorithm at page 18 of RFC 7253""" + """Implement the algorithm at page 18 of RFC 7253""" - key = bchr(0) * (keylen // 8 - 1) + bchr(taglen) - C = b"" + key = bchr(0) * (keylen // 8 - 1) + bchr(taglen) + C = b"" - for i in range(128): - S = bchr(0) * i + for i in range(128): + S = bchr(0) * i - N = long_to_bytes(3 * i + 1, noncelen // 8) - cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) - cipher.update(S) - C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() + N = long_to_bytes(3 * i + 1, noncelen // 8) + cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) + cipher.update(S) + C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() - N = long_to_bytes(3 * i + 2, noncelen // 8) - cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) - C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() + N = long_to_bytes(3 * i + 2, noncelen // 8) + cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) + C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest() - N = long_to_bytes(3 * i + 3, noncelen // 8) - cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) - cipher.update(S) - C += cipher.encrypt() + cipher.digest() + N = long_to_bytes(3 * i + 3, noncelen // 8) + cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) + cipher.update(S) + C += cipher.encrypt() + cipher.digest() - N = long_to_bytes(385, noncelen // 8) - cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) - cipher.update(C) - return cipher.encrypt() + cipher.digest() + N = long_to_bytes(385, noncelen // 8) + cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) + cipher.update(C) + return cipher.encrypt() + cipher.digest() class OcbRfc7253Test(unittest.TestCase): - - # Tuple with - # - nonce - # - authenticated data - # - plaintext - # - ciphertext and 16 byte MAC tag - tv1_key = "000102030405060708090A0B0C0D0E0F" - tv1 = ( - ( - "BBAA99887766554433221100", - "", - "", - "785407BFFFC8AD9EDCC5520AC9111EE6" - ), - ( - "BBAA99887766554433221101", - "0001020304050607", - "0001020304050607", - "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009" - ), - ( - "BBAA99887766554433221102", - "0001020304050607", - "", - "81017F8203F081277152FADE694A0A00" - ), - ( - "BBAA99887766554433221103", - "", - "0001020304050607", - "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9" - ), - ( - "BBAA99887766554433221104", - "000102030405060708090A0B0C0D0E0F", - "000102030405060708090A0B0C0D0E0F", - "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5" - "701C1CCEC8FC3358" - ), - ( - "BBAA99887766554433221105", - "000102030405060708090A0B0C0D0E0F", - "", - "8CF761B6902EF764462AD86498CA6B97" - ), - ( - "BBAA99887766554433221106", - "", - "000102030405060708090A0B0C0D0E0F", - "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436B" - "DF06D8FA1ECA343D" - ), - ( - "BBAA99887766554433221107", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "1CA2207308C87C010756104D8840CE1952F09673A448A122" - "C92C62241051F57356D7F3C90BB0E07F" - ), - ( - "BBAA99887766554433221108", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "", - "6DC225A071FC1B9F7C69F93B0F1E10DE" - ), - ( - "BBAA99887766554433221109", - "", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3C" - "E725F32494B9F914D85C0B1EB38357FF" - ), - ( - "BBAA9988776655443322110A", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F", - "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DE" - "AFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240" - ), - ( - "BBAA9988776655443322110B", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F", - "", - "FE80690BEE8A485D11F32965BC9D2A32" - ), - ( - "BBAA9988776655443322110C", - "", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F", - "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF4" - "6040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF" - ), - ( - "BBAA9988776655443322110D", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "D5CA91748410C1751FF8A2F618255B68A0A12E093FF45460" - "6E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483" - "A7035490C5769E60" - ), - ( - "BBAA9988776655443322110E", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "", - "C5CD9D1850C141E358649994EE701B68" - ), - ( - "BBAA9988776655443322110F", - "", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15" - "A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95" - "A98CA5F3000B1479" - ) - ) - - # Tuple with - # - key - # - nonce - # - authenticated data - # - plaintext - # - ciphertext and 12 byte MAC tag - tv2 = ( - "0F0E0D0C0B0A09080706050403020100", - "BBAA9988776655443322110D", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627", - "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1" - "A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD" - "AC4F02AA" - ) - - # Tuple with - # - key length - # - MAC tag length - # - Expected output - tv3 = ( - (128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"), - (192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"), - (256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"), - (128, 96, "77A3D8E73589158D25D01209"), - (192, 96, "05D56EAD2752C86BE6932C5E"), - (256, 96, "5458359AC23B0CBA9E6330DD"), - (128, 64, "192C9B7BD90BA06A"), - (192, 64, "0066BC6E0EF34E24"), - (256, 64, "7D4EA5D445501CBE"), - ) - - def test1(self): - key = unhexlify(b(self.tv1_key)) - for tv in self.tv1: - nonce, aad, pt, ct = [unhexlify(b(x)) for x in tv] - ct, mac_tag = ct[:-16], ct[-16:] - - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) - cipher.update(aad) - ct2 = cipher.encrypt(pt) + cipher.encrypt() - self.assertEqual(ct, ct2) - self.assertEqual(mac_tag, cipher.digest()) - - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) - cipher.update(aad) - pt2 = cipher.decrypt(ct) + cipher.decrypt() - self.assertEqual(pt, pt2) - cipher.verify(mac_tag) - - def test2(self): - - key, nonce, aad, pt, ct = [unhexlify(b(x)) for x in self.tv2] - ct, mac_tag = ct[:-12], ct[-12:] - - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12) - cipher.update(aad) - ct2 = cipher.encrypt(pt) + cipher.encrypt() - self.assertEqual(ct, ct2) - self.assertEqual(mac_tag, cipher.digest()) - - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12) - cipher.update(aad) - pt2 = cipher.decrypt(ct) + cipher.decrypt() - self.assertEqual(pt, pt2) - cipher.verify(mac_tag) - - def test3(self): - for keylen, taglen, result in self.tv3: - result2 = algo_rfc7253(keylen, taglen, 96) - self.assertEqual(unhexlify(b(result)), result2) + # Tuple with + # - nonce + # - authenticated data + # - plaintext + # - ciphertext and 16 byte MAC tag + tv1_key = "000102030405060708090A0B0C0D0E0F" + tv1 = ( + ( + "BBAA99887766554433221100", + "", + "", + "785407BFFFC8AD9EDCC5520AC9111EE6", + ), + ( + "BBAA99887766554433221101", + "0001020304050607", + "0001020304050607", + "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009", + ), + ( + "BBAA99887766554433221102", + "0001020304050607", + "", + "81017F8203F081277152FADE694A0A00", + ), + ( + "BBAA99887766554433221103", + "", + "0001020304050607", + "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9", + ), + ( + "BBAA99887766554433221104", + "000102030405060708090A0B0C0D0E0F", + "000102030405060708090A0B0C0D0E0F", + "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358", + ), + ( + "BBAA99887766554433221105", + "000102030405060708090A0B0C0D0E0F", + "", + "8CF761B6902EF764462AD86498CA6B97", + ), + ( + "BBAA99887766554433221106", + "", + "000102030405060708090A0B0C0D0E0F", + "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D", + ), + ( + "BBAA99887766554433221107", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F", + ), + ( + "BBAA99887766554433221108", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "", + "6DC225A071FC1B9F7C69F93B0F1E10DE", + ), + ( + "BBAA99887766554433221109", + "", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF", + ), + ( + "BBAA9988776655443322110A", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DE" + "AFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240", + ), + ( + "BBAA9988776655443322110B", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "", + "FE80690BEE8A485D11F32965BC9D2A32", + ), + ( + "BBAA9988776655443322110C", + "", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF4" + "6040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF", + ), + ( + "BBAA9988776655443322110D", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "D5CA91748410C1751FF8A2F618255B68A0A12E093FF45460" + "6E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483" + "A7035490C5769E60", + ), + ( + "BBAA9988776655443322110E", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "", + "C5CD9D1850C141E358649994EE701B68", + ), + ( + "BBAA9988776655443322110F", + "", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15" + "A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95" + "A98CA5F3000B1479", + ), + ) + + # Tuple with + # - key + # - nonce + # - authenticated data + # - plaintext + # - ciphertext and 12 byte MAC tag + tv2 = ( + "0F0E0D0C0B0A09080706050403020100", + "BBAA9988776655443322110D", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1" + "A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD" + "AC4F02AA", + ) + + # Tuple with + # - key length + # - MAC tag length + # - Expected output + tv3 = ( + (128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"), + (192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"), + (256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"), + (128, 96, "77A3D8E73589158D25D01209"), + (192, 96, "05D56EAD2752C86BE6932C5E"), + (256, 96, "5458359AC23B0CBA9E6330DD"), + (128, 64, "192C9B7BD90BA06A"), + (192, 64, "0066BC6E0EF34E24"), + (256, 64, "7D4EA5D445501CBE"), + ) + + def test1(self): + key = unhexlify(b(self.tv1_key)) + for tv in self.tv1: + nonce, aad, pt, ct = [unhexlify(b(x)) for x in tv] + ct, mac_tag = ct[:-16], ct[-16:] + + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) + cipher.update(aad) + ct2 = cipher.encrypt(pt) + cipher.encrypt() + self.assertEqual(ct, ct2) + self.assertEqual(mac_tag, cipher.digest()) + + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) + cipher.update(aad) + pt2 = cipher.decrypt(ct) + cipher.decrypt() + self.assertEqual(pt, pt2) + cipher.verify(mac_tag) + + def test2(self): + key, nonce, aad, pt, ct = [unhexlify(b(x)) for x in self.tv2] + ct, mac_tag = ct[:-12], ct[-12:] + + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12) + cipher.update(aad) + ct2 = cipher.encrypt(pt) + cipher.encrypt() + self.assertEqual(ct, ct2) + self.assertEqual(mac_tag, cipher.digest()) + + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12) + cipher.update(aad) + pt2 = cipher.decrypt(ct) + cipher.decrypt() + self.assertEqual(pt, pt2) + cipher.verify(mac_tag) + + def test3(self): + for keylen, taglen, result in self.tv3: + result2 = algo_rfc7253(keylen, taglen, 96) + self.assertEqual(unhexlify(b(result)), result2) class OcbDkgTest(unittest.TestCase): - """Test vectors from https://gitlab.com/dkg/ocb-test-vectors""" - - def test_1_2(self): - tvs = [] - for fi in (1, 2): - for nb in (104, 112, 120): - tv_file = load_test_vectors(("Cipher", "AES"), - "test-vector-%d-nonce%d.txt" % (fi, nb), - "DKG tests, %d, %d bits" % (fi, nb), - {}) - if tv_file is None: - break - key = tv_file[0].k - for tv in tv_file[1:]: - tv.k = key - tvs.append(tv) - - for tv in tvs: - k, n, a, p, c = tv.k, tv.n, tv.a, tv.p, tv.c - mac_len = len(c) - len(p) - cipher = AES.new(k, AES.MODE_OCB, nonce=n, mac_len=mac_len) - cipher.update(a) - c_out, tag_out = cipher.encrypt_and_digest(p) - self.assertEqual(c, c_out + tag_out) - - def test_3(self): - - def check(keylen, taglen, noncelen, exp): - result = algo_rfc7253(keylen, taglen, noncelen) - self.assertEqual(result, unhexlify(exp)) - - # test-vector-3-nonce104.txt - check(128, 128, 104, "C47F5F0341E15326D4D1C46F47F05062") - check(192, 128, 104, "95B9167A38EB80495DFC561A8486E109") - check(256, 128, 104, "AFE1CDDB97028FD92F8FB3C8CFBA7D83") - check(128, 96, 104, "F471B4983BA80946DF217A54") - check(192, 96, 104, "5AE828BC51C24D85FA5CC7B2") - check(256, 96, 104, "8C8335982E2B734616CAD14C") - check(128, 64, 104, "B553F74B85FD1E5B") - check(192, 64, 104, "3B49D20E513531F9") - check(256, 64, 104, "ED6DA5B1216BF8BB") - - # test-vector-3-nonce112.txt - check(128, 128, 112, "CA8AFCA031BAC3F480A583BD6C50A547") - check(192, 128, 112, "D170C1DF356308079DA9A3F619147148") - check(256, 128, 112, "57F94381F2F9231EFB04AECD323757C3") - check(128, 96, 112, "3A618B2531ED39F260C750DC") - check(192, 96, 112, "9071EB89FEDBADDA88FD286E") - check(256, 96, 112, "FDF0EFB97F21A39AC4BAB5AC") - check(128, 64, 112, "FAB2FF3A8DD82A13") - check(192, 64, 112, "AC01D912BD0737D3") - check(256, 64, 112, "9D1FD0B500EA4ECF") - - # test-vector-3-nonce120.txt - check(128, 128, 120, "9E043A7140A25FB91F43BCC9DD7E0F46") - check(192, 128, 120, "680000E53908323A7F396B955B8EC641") - check(256, 128, 120, "8304B97FAACDA56E676602E1878A7E6F") - check(128, 96, 120, "81F978AC9867E825D339847D") - check(192, 96, 120, "EFCF2D60B24926ADA48CF5B1") - check(256, 96, 120, "84961DC56E917B165E58C174") - check(128, 64, 120, "227AEE6C9D905A61") - check(192, 64, 120, "541DE691B9E1A2F9") - check(256, 64, 120, "B0E761381C7129FC") - - def test_2_bugfix(self): - nonce = unhexlify("EEDDCCBBAA9988776655443322110D") - key = unhexlify("0F0E0D0C0B0A09080706050403020100") - A = unhexlify("000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627") - P = unhexlify("000102030405060708090A0B0C0D0E0F1011121314151617" - "18191A1B1C1D1E1F2021222324252627") - C = unhexlify("07E903BFC49552411ABC865F5ECE60F6FAD1F5A9F14D3070" - "FA2F1308A563207FFE14C1EEA44B22059C7484319D8A2C53" - "C236A7B3") - mac_len = len(C) - len(P) - - # Prior to version 3.17, a nonce of maximum length (15 bytes) - # was actually used as a 14 byte nonce. The last byte was erroneously - # ignored. - buggy_result = unhexlify("BA015C4E5AE54D76C890AE81BD40DC57" - "03EDC30E8AC2A58BC5D8FA4D61C5BAE6" - "C39BEAC435B2FD56A2A5085C1B135D77" - "0C8264B7") - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce[:-1], mac_len=mac_len) - cipher.update(A) - C_out2, tag_out2 = cipher.encrypt_and_digest(P) - self.assertEqual(buggy_result, C_out2 + tag_out2) + """Test vectors from https://gitlab.com/dkg/ocb-test-vectors""" + + def test_1_2(self): + tvs = [] + for fi in (1, 2): + for nb in (104, 112, 120): + tv_file = load_test_vectors( + ("Cipher", "AES"), + "test-vector-%d-nonce%d.txt" % (fi, nb), + "DKG tests, %d, %d bits" % (fi, nb), + {}, + ) + if tv_file is None: + break + key = tv_file[0].k + for tv in tv_file[1:]: + tv.k = key + tvs.append(tv) + + for tv in tvs: + k, n, a, p, c = tv.k, tv.n, tv.a, tv.p, tv.c + mac_len = len(c) - len(p) + cipher = AES.new(k, AES.MODE_OCB, nonce=n, mac_len=mac_len) + cipher.update(a) + c_out, tag_out = cipher.encrypt_and_digest(p) + self.assertEqual(c, c_out + tag_out) + + def test_3(self): + def check(keylen, taglen, noncelen, exp): + result = algo_rfc7253(keylen, taglen, noncelen) + self.assertEqual(result, unhexlify(exp)) + + # test-vector-3-nonce104.txt + check(128, 128, 104, "C47F5F0341E15326D4D1C46F47F05062") + check(192, 128, 104, "95B9167A38EB80495DFC561A8486E109") + check(256, 128, 104, "AFE1CDDB97028FD92F8FB3C8CFBA7D83") + check(128, 96, 104, "F471B4983BA80946DF217A54") + check(192, 96, 104, "5AE828BC51C24D85FA5CC7B2") + check(256, 96, 104, "8C8335982E2B734616CAD14C") + check(128, 64, 104, "B553F74B85FD1E5B") + check(192, 64, 104, "3B49D20E513531F9") + check(256, 64, 104, "ED6DA5B1216BF8BB") + + # test-vector-3-nonce112.txt + check(128, 128, 112, "CA8AFCA031BAC3F480A583BD6C50A547") + check(192, 128, 112, "D170C1DF356308079DA9A3F619147148") + check(256, 128, 112, "57F94381F2F9231EFB04AECD323757C3") + check(128, 96, 112, "3A618B2531ED39F260C750DC") + check(192, 96, 112, "9071EB89FEDBADDA88FD286E") + check(256, 96, 112, "FDF0EFB97F21A39AC4BAB5AC") + check(128, 64, 112, "FAB2FF3A8DD82A13") + check(192, 64, 112, "AC01D912BD0737D3") + check(256, 64, 112, "9D1FD0B500EA4ECF") + + # test-vector-3-nonce120.txt + check(128, 128, 120, "9E043A7140A25FB91F43BCC9DD7E0F46") + check(192, 128, 120, "680000E53908323A7F396B955B8EC641") + check(256, 128, 120, "8304B97FAACDA56E676602E1878A7E6F") + check(128, 96, 120, "81F978AC9867E825D339847D") + check(192, 96, 120, "EFCF2D60B24926ADA48CF5B1") + check(256, 96, 120, "84961DC56E917B165E58C174") + check(128, 64, 120, "227AEE6C9D905A61") + check(192, 64, 120, "541DE691B9E1A2F9") + check(256, 64, 120, "B0E761381C7129FC") + + def test_2_bugfix(self): + nonce = unhexlify("EEDDCCBBAA9988776655443322110D") + key = unhexlify("0F0E0D0C0B0A09080706050403020100") + A = unhexlify( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + ) + P = unhexlify( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + ) + C = unhexlify( + "07E903BFC49552411ABC865F5ECE60F6FAD1F5A9F14D3070" + "FA2F1308A563207FFE14C1EEA44B22059C7484319D8A2C53" + "C236A7B3", + ) + mac_len = len(C) - len(P) + + # Prior to version 3.17, a nonce of maximum length (15 bytes) + # was actually used as a 14 byte nonce. The last byte was erroneously + # ignored. + buggy_result = unhexlify( + "BA015C4E5AE54D76C890AE81BD40DC57" + "03EDC30E8AC2A58BC5D8FA4D61C5BAE6" + "C39BEAC435B2FD56A2A5085C1B135D77" + "0C8264B7", + ) + cipher = AES.new(key, AES.MODE_OCB, nonce=nonce[:-1], mac_len=mac_len) + cipher.update(A) + C_out2, tag_out2 = cipher.encrypt_and_digest(P) + self.assertEqual(buggy_result, C_out2 + tag_out2) def get_tests(config={}): - tests = [] - tests += list_test_cases(OcbTests) - tests += list_test_cases(OcbFSMTests) - tests += list_test_cases(OcbRfc7253Test) - tests += list_test_cases(OcbDkgTest) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(OcbTests) + tests += list_test_cases(OcbFSMTests) + tests += list_test_cases(OcbRfc7253Test) + tests += list_test_cases(OcbDkgTest) + return tests + + +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OFB.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OFB.py index 9a8ef0a1..d4bd00a8 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OFB.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OFB.py @@ -35,204 +35,224 @@ from Cryptodome.Util.py3compat import tobytes from Cryptodome.Cipher import AES, DES3, DES from Cryptodome.Hash import SHAKE128 -from Cryptodome.SelfTest.loader import load_test_vectors_wycheproof + def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) + from Cryptodome.SelfTest.Cipher.test_CBC import BlockChainingTests -class OfbTests(BlockChainingTests): - aes_mode = AES.MODE_OFB - des3_mode = DES3.MODE_OFB +class OfbTests(BlockChainingTests): + aes_mode = AES.MODE_OFB + des3_mode = DES3.MODE_OFB - # Redefine test_unaligned_data_128/64 + # Redefine test_unaligned_data_128/64 - def test_unaligned_data_128(self): - plaintexts = [ b"7777777" ] * 100 + def test_unaligned_data_128(self): + plaintexts = [b"7777777"] * 100 - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - def test_unaligned_data_64(self): - plaintexts = [ b"7777777" ] * 100 - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + def test_unaligned_data_64(self): + plaintexts = [b"7777777"] * 100 + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) from Cryptodome.SelfTest.Cipher.test_CBC import NistBlockChainingVectors + class NistOfbVectors(NistBlockChainingVectors): - aes_mode = AES.MODE_OFB - des_mode = DES.MODE_OFB - des3_mode = DES3.MODE_OFB + aes_mode = AES.MODE_OFB + des_mode = DES.MODE_OFB + des3_mode = DES3.MODE_OFB # Create one test method per file nist_aes_kat_mmt_files = ( - # KAT - "OFBGFSbox128.rsp", - "OFBGFSbox192.rsp", - "OFBGFSbox256.rsp", - "OFBKeySbox128.rsp", - "OFBKeySbox192.rsp", - "OFBKeySbox256.rsp", - "OFBVarKey128.rsp", - "OFBVarKey192.rsp", - "OFBVarKey256.rsp", - "OFBVarTxt128.rsp", - "OFBVarTxt192.rsp", - "OFBVarTxt256.rsp", - # MMT - "OFBMMT128.rsp", - "OFBMMT192.rsp", - "OFBMMT256.rsp", - ) + # KAT + "OFBGFSbox128.rsp", + "OFBGFSbox192.rsp", + "OFBGFSbox256.rsp", + "OFBKeySbox128.rsp", + "OFBKeySbox192.rsp", + "OFBKeySbox256.rsp", + "OFBVarKey128.rsp", + "OFBVarKey192.rsp", + "OFBVarKey256.rsp", + "OFBVarTxt128.rsp", + "OFBVarTxt192.rsp", + "OFBVarTxt256.rsp", + # MMT + "OFBMMT128.rsp", + "OFBMMT192.rsp", + "OFBMMT256.rsp", +) nist_aes_mct_files = ( - "OFBMCT128.rsp", - "OFBMCT192.rsp", - "OFBMCT256.rsp", - ) + "OFBMCT128.rsp", + "OFBMCT192.rsp", + "OFBMCT256.rsp", +) for file_name in nist_aes_kat_mmt_files: - def new_func(self, file_name=file_name): - self._do_kat_aes_test(file_name) - setattr(NistOfbVectors, "test_AES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_kat_aes_test(file_name) + + setattr(NistOfbVectors, "test_AES_" + file_name, new_func) for file_name in nist_aes_mct_files: - def new_func(self, file_name=file_name): - self._do_mct_aes_test(file_name) - setattr(NistOfbVectors, "test_AES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_mct_aes_test(file_name) + + setattr(NistOfbVectors, "test_AES_" + file_name, new_func) del file_name, new_func nist_tdes_files = ( - "TOFBMMT2.rsp", # 2TDES - "TOFBMMT3.rsp", # 3TDES - "TOFBinvperm.rsp", # Single DES - "TOFBpermop.rsp", - "TOFBsubtab.rsp", - "TOFBvarkey.rsp", - "TOFBvartext.rsp", - ) + "TOFBMMT2.rsp", # 2TDES + "TOFBMMT3.rsp", # 3TDES + "TOFBinvperm.rsp", # Single DES + "TOFBpermop.rsp", + "TOFBsubtab.rsp", + "TOFBvarkey.rsp", + "TOFBvartext.rsp", +) for file_name in nist_tdes_files: - def new_func(self, file_name=file_name): - self._do_tdes_test(file_name) - setattr(NistOfbVectors, "test_TDES_" + file_name, new_func) + + def new_func(self, file_name=file_name): + self._do_tdes_test(file_name) + + setattr(NistOfbVectors, "test_TDES_" + file_name, new_func) # END OF NIST OFB TEST VECTORS class SP800TestVectors(unittest.TestCase): - """Class exercising the OFB test vectors found in Section F.4 - of NIST SP 800-3A""" - - def test_aes_128(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = '3b3fd92eb72dad20333449f8e83cfb4a' +\ - '7789508d16918f03f53c52dac54ed825' +\ - '9740051e9c5fecf64344f7a82260edcc' +\ - '304c6528f659c77866a510d9c1d6ae5e' - key = '2b7e151628aed2a6abf7158809cf4f3c' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) - - def test_aes_192(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = 'cdc80d6fddf18cab34c25909c99a4174' +\ - 'fcc28b8d4c63837c09e81700c1100401' +\ - '8d9a9aeac0f6596f559c6d4daf59a5f2' +\ - '6d9f200857ca6c3e9cac524bd9acc92a' - key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) - - def test_aes_256(self): - plaintext = '6bc1bee22e409f96e93d7e117393172a' +\ - 'ae2d8a571e03ac9c9eb76fac45af8e51' +\ - '30c81c46a35ce411e5fbc1191a0a52ef' +\ - 'f69f2445df4f9b17ad2b417be66c3710' - ciphertext = 'dc7e84bfda79164b7ecd8486985d3860' +\ - '4febdc6740d20b3ac88f6ad82a4fb08d' +\ - '71ab47a086e86eedf39d1c5bba97c408' +\ - '0126141d67f37be8538f5a8be740e484' - key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' - iv = '000102030405060708090a0b0c0d0e0f' - - key = unhexlify(key) - iv = unhexlify(iv) - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext), ciphertext) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext), plaintext) - - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) - cipher = AES.new(key, AES.MODE_OFB, iv) - self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) + """Class exercising the OFB test vectors found in Section F.4 + of NIST SP 800-3A""" + + def test_aes_128(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "3b3fd92eb72dad20333449f8e83cfb4a" + + "7789508d16918f03f53c52dac54ed825" + + "9740051e9c5fecf64344f7a82260edcc" + + "304c6528f659c77866a510d9c1d6ae5e" + ) + key = "2b7e151628aed2a6abf7158809cf4f3c" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) + + def test_aes_192(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "cdc80d6fddf18cab34c25909c99a4174" + + "fcc28b8d4c63837c09e81700c1100401" + + "8d9a9aeac0f6596f559c6d4daf59a5f2" + + "6d9f200857ca6c3e9cac524bd9acc92a" + ) + key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) + + def test_aes_256(self): + plaintext = ( + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710" + ) + ciphertext = ( + "dc7e84bfda79164b7ecd8486985d3860" + + "4febdc6740d20b3ac88f6ad82a4fb08d" + + "71ab47a086e86eedf39d1c5bba97c408" + + "0126141d67f37be8538f5a8be740e484" + ) + key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + iv = "000102030405060708090a0b0c0d0e0f" + + key = unhexlify(key) + iv = unhexlify(iv) + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext), ciphertext) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext), plaintext) + + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8]) + cipher = AES.new(key, AES.MODE_OFB, iv) + self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8]) def get_tests(config={}): - tests = [] - tests += list_test_cases(OfbTests) - if config.get('slow_tests'): - tests += list_test_cases(NistOfbVectors) - tests += list_test_cases(SP800TestVectors) - return tests + tests = [] + tests += list_test_cases(OfbTests) + if config.get("slow_tests"): + tests += list_test_cases(NistOfbVectors) + tests += list_test_cases(SP800TestVectors) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OpenPGP.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OpenPGP.py index 4090a1a0..bad208e4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OpenPGP.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_OpenPGP.py @@ -33,186 +33,186 @@ from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Util.py3compat import tobytes -from Cryptodome.Cipher import AES, DES3, DES +from Cryptodome.Cipher import AES, DES3 from Cryptodome.Hash import SHAKE128 + def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) from Cryptodome.SelfTest.Cipher.test_CBC import BlockChainingTests -class OpenPGPTests(BlockChainingTests): - aes_mode = AES.MODE_OPENPGP - des3_mode = DES3.MODE_OPENPGP +class OpenPGPTests(BlockChainingTests): + aes_mode = AES.MODE_OPENPGP + des3_mode = DES3.MODE_OPENPGP - # Redefine test_unaligned_data_128/64 + # Redefine test_unaligned_data_128/64 - key_128 = get_tag_random("key_128", 16) - key_192 = get_tag_random("key_192", 24) - iv_128 = get_tag_random("iv_128", 16) - iv_64 = get_tag_random("iv_64", 8) - data_128 = get_tag_random("data_128", 16) + key_128 = get_tag_random("key_128", 16) + key_192 = get_tag_random("key_192", 24) + iv_128 = get_tag_random("iv_128", 16) + iv_64 = get_tag_random("iv_64", 8) + data_128 = get_tag_random("data_128", 16) - def test_loopback_128(self): - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - pt = get_tag_random("plaintext", 16 * 100) - ct = cipher.encrypt(pt) + def test_loopback_128(self): + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + pt = get_tag_random("plaintext", 16 * 100) + ct = cipher.encrypt(pt) - eiv, ct = ct[:18], ct[18:] + eiv, ct = ct[:18], ct[18:] - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) - def test_loopback_64(self): - cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) - pt = get_tag_random("plaintext", 8 * 100) - ct = cipher.encrypt(pt) + def test_loopback_64(self): + cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) + pt = get_tag_random("plaintext", 8 * 100) + ct = cipher.encrypt(pt) - eiv, ct = ct[:10], ct[10:] + eiv, ct = ct[:10], ct[10:] - cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, eiv) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) + cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, eiv) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) - def test_IV_iv_attributes(self): - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - eiv = cipher.encrypt(b"") - self.assertEqual(cipher.iv, self.iv_128) + def test_IV_iv_attributes(self): + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + eiv = cipher.encrypt(b"") + self.assertEqual(cipher.iv, self.iv_128) - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) - self.assertEqual(cipher.iv, self.iv_128) + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) + self.assertEqual(cipher.iv, self.iv_128) - def test_null_encryption_decryption(self): - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - eiv = cipher.encrypt(b"") + def test_null_encryption_decryption(self): + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + eiv = cipher.encrypt(b"") - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) - self.assertEqual(cipher.decrypt(b""), b"") + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) + self.assertEqual(cipher.decrypt(b""), b"") - def test_either_encrypt_or_decrypt(self): - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - eiv = cipher.encrypt(b"") - self.assertRaises(TypeError, cipher.decrypt, b"") + def test_either_encrypt_or_decrypt(self): + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + eiv = cipher.encrypt(b"") + self.assertRaises(TypeError, cipher.decrypt, b"") - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) - cipher.decrypt(b"") - self.assertRaises(TypeError, cipher.encrypt, b"") + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv) + cipher.decrypt(b"") + self.assertRaises(TypeError, cipher.encrypt, b"") - def test_unaligned_data_128(self): - plaintexts = [ b"7777777" ] * 100 + def test_unaligned_data_128(self): + plaintexts = [b"7777777"] * 100 - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - def test_unaligned_data_64(self): - plaintexts = [ b"7777777" ] * 100 + def test_unaligned_data_64(self): + plaintexts = [b"7777777"] * 100 - cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) - ciphertexts = [ cipher.encrypt(x) for x in plaintexts ] - cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) - self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) + cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) + ciphertexts = [cipher.encrypt(x) for x in plaintexts] + cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64) + self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts))) - def test_output_param(self): - pass + def test_output_param(self): + pass - def test_output_param_same_buffer(self): - pass + def test_output_param_same_buffer(self): + pass - def test_output_param_memoryview(self): - pass + def test_output_param_memoryview(self): + pass - def test_output_param_neg(self): - pass + def test_output_param_neg(self): + pass class TestVectors(unittest.TestCase): - - def test_aes(self): - # The following test vectors have been generated with gpg v1.4.0. - # The command line used was: - # - # gpg -c -z 0 --cipher-algo AES --passphrase secret_passphrase \ - # --disable-mdc --s2k-mode 0 --output ct pt - # - # As result, the content of the file 'pt' is encrypted with a key derived - # from 'secret_passphrase' and written to file 'ct'. - # Test vectors must be extracted from 'ct', which is a collection of - # TLVs (see RFC4880 for all details): - # - the encrypted data (with the encrypted IV as prefix) is the payload - # of the TLV with tag 9 (Symmetrical Encrypted Data Packet). - # This is the ciphertext in the test vector. - # - inside the encrypted part, there is a further layer of TLVs. One must - # look for tag 11 (Literal Data Packet); in its payload, after a short - # but time dependent header, there is the content of file 'pt'. - # In the test vector, the plaintext is the complete set of TLVs that gets - # encrypted. It is not just the content of 'pt'. - # - the key is the leftmost 16 bytes of the SHA1 digest of the password. - # The test vector contains such shortened digest. - # - # Note that encryption uses a clear IV, and decryption an encrypted IV - - plaintext = 'ac18620270744fb4f647426c61636b4361745768697465436174' - ciphertext = 'dc6b9e1f095de609765c59983db5956ae4f63aea7405389d2ebb' - key = '5baa61e4c9b93f3f0682250b6cf8331b' - iv = '3d7d3e62282add7eb203eeba5c800733' - encrypted_iv='fd934601ef49cb58b6d9aebca6056bdb96ef' - - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - key = unhexlify(key) - iv = unhexlify(iv) - encrypted_iv = unhexlify(encrypted_iv) - - cipher = AES.new(key, AES.MODE_OPENPGP, iv) - ct = cipher.encrypt(plaintext) - self.assertEqual(ct[:18], encrypted_iv) - self.assertEqual(ct[18:], ciphertext) - - cipher = AES.new(key, AES.MODE_OPENPGP, encrypted_iv) - pt = cipher.decrypt(ciphertext) - self.assertEqual(pt, plaintext) - - def test_des3(self): - # The following test vectors have been generated with gpg v1.4.0. - # The command line used was: - # gpg -c -z 0 --cipher-algo 3DES --passphrase secret_passphrase \ - # --disable-mdc --s2k-mode 0 --output ct pt - # For an explanation, see test_AES.py . - - plaintext = 'ac1762037074324fb53ba3596f73656d69746556616c6c6579' - ciphertext = '9979238528357b90e2e0be549cb0b2d5999b9a4a447e5c5c7d' - key = '7ade65b460f5ea9be35f9e14aa883a2048e3824aa616c0b2' - iv='cd47e2afb8b7e4b0' - encrypted_iv='6a7eef0b58050e8b904a' - - plaintext = unhexlify(plaintext) - ciphertext = unhexlify(ciphertext) - key = unhexlify(key) - iv = unhexlify(iv) - encrypted_iv = unhexlify(encrypted_iv) - - cipher = DES3.new(key, DES3.MODE_OPENPGP, iv) - ct = cipher.encrypt(plaintext) - self.assertEqual(ct[:10], encrypted_iv) - self.assertEqual(ct[10:], ciphertext) - - cipher = DES3.new(key, DES3.MODE_OPENPGP, encrypted_iv) - pt = cipher.decrypt(ciphertext) - self.assertEqual(pt, plaintext) + def test_aes(self): + # The following test vectors have been generated with gpg v1.4.0. + # The command line used was: + # + # gpg -c -z 0 --cipher-algo AES --passphrase secret_passphrase \ + # --disable-mdc --s2k-mode 0 --output ct pt + # + # As result, the content of the file 'pt' is encrypted with a key derived + # from 'secret_passphrase' and written to file 'ct'. + # Test vectors must be extracted from 'ct', which is a collection of + # TLVs (see RFC4880 for all details): + # - the encrypted data (with the encrypted IV as prefix) is the payload + # of the TLV with tag 9 (Symmetrical Encrypted Data Packet). + # This is the ciphertext in the test vector. + # - inside the encrypted part, there is a further layer of TLVs. One must + # look for tag 11 (Literal Data Packet); in its payload, after a short + # but time dependent header, there is the content of file 'pt'. + # In the test vector, the plaintext is the complete set of TLVs that gets + # encrypted. It is not just the content of 'pt'. + # - the key is the leftmost 16 bytes of the SHA1 digest of the password. + # The test vector contains such shortened digest. + # + # Note that encryption uses a clear IV, and decryption an encrypted IV + + plaintext = "ac18620270744fb4f647426c61636b4361745768697465436174" + ciphertext = "dc6b9e1f095de609765c59983db5956ae4f63aea7405389d2ebb" + key = "5baa61e4c9b93f3f0682250b6cf8331b" + iv = "3d7d3e62282add7eb203eeba5c800733" + encrypted_iv = "fd934601ef49cb58b6d9aebca6056bdb96ef" + + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + key = unhexlify(key) + iv = unhexlify(iv) + encrypted_iv = unhexlify(encrypted_iv) + + cipher = AES.new(key, AES.MODE_OPENPGP, iv) + ct = cipher.encrypt(plaintext) + self.assertEqual(ct[:18], encrypted_iv) + self.assertEqual(ct[18:], ciphertext) + + cipher = AES.new(key, AES.MODE_OPENPGP, encrypted_iv) + pt = cipher.decrypt(ciphertext) + self.assertEqual(pt, plaintext) + + def test_des3(self): + # The following test vectors have been generated with gpg v1.4.0. + # The command line used was: + # gpg -c -z 0 --cipher-algo 3DES --passphrase secret_passphrase \ + # --disable-mdc --s2k-mode 0 --output ct pt + # For an explanation, see test_AES.py . + + plaintext = "ac1762037074324fb53ba3596f73656d69746556616c6c6579" + ciphertext = "9979238528357b90e2e0be549cb0b2d5999b9a4a447e5c5c7d" + key = "7ade65b460f5ea9be35f9e14aa883a2048e3824aa616c0b2" + iv = "cd47e2afb8b7e4b0" + encrypted_iv = "6a7eef0b58050e8b904a" + + plaintext = unhexlify(plaintext) + ciphertext = unhexlify(ciphertext) + key = unhexlify(key) + iv = unhexlify(iv) + encrypted_iv = unhexlify(encrypted_iv) + + cipher = DES3.new(key, DES3.MODE_OPENPGP, iv) + ct = cipher.encrypt(plaintext) + self.assertEqual(ct[:10], encrypted_iv) + self.assertEqual(ct[10:], ciphertext) + + cipher = DES3.new(key, DES3.MODE_OPENPGP, encrypted_iv) + pt = cipher.decrypt(ciphertext) + self.assertEqual(pt, plaintext) def get_tests(config={}): - tests = [] - tests += list_test_cases(OpenPGPTests) - tests += list_test_cases(TestVectors) - return tests + tests = [] + tests += list_test_cases(OpenPGPTests) + tests += list_test_cases(TestVectors) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_SIV.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_SIV.py index d4bb5a9a..464c6401 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_SIV.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_SIV.py @@ -28,7 +28,6 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -import json import unittest from binascii import unhexlify @@ -39,514 +38,568 @@ from Cryptodome.Cipher import AES from Cryptodome.Hash import SHAKE128 -from Cryptodome.Util.strxor import strxor - def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class SivTests(unittest.TestCase): - - key_256 = get_tag_random("key_256", 32) - key_384 = get_tag_random("key_384", 48) - key_512 = get_tag_random("key_512", 64) - nonce_96 = get_tag_random("nonce_128", 12) - data = get_tag_random("data", 128) - - def test_loopback_128(self): - for key in self.key_256, self.key_384, self.key_512: - cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96) - pt = get_tag_random("plaintext", 16 * 100) - ct, mac = cipher.encrypt_and_digest(pt) - - cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) - - def test_nonce(self): - # Deterministic encryption - AES.new(self.key_256, AES.MODE_SIV) - - cipher = AES.new(self.key_256, AES.MODE_SIV, self.nonce_96) - ct1, tag1 = cipher.encrypt_and_digest(self.data) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct2, tag2 = cipher.encrypt_and_digest(self.data) - self.assertEqual(ct1 + tag1, ct2 + tag2) - - def test_nonce_must_be_bytes(self): - self.assertRaises(TypeError, AES.new, self.key_256, AES.MODE_SIV, - nonce=u'test12345678') - - def test_nonce_length(self): - # nonce can be of any length (but not empty) - self.assertRaises(ValueError, AES.new, self.key_256, AES.MODE_SIV, - nonce=b"") - - for x in range(1, 128): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=bchr(1) * x) - cipher.encrypt_and_digest(b'\x01') - - def test_block_size_128(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertEqual(cipher.block_size, AES.block_size) - - def test_nonce_attribute(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertEqual(cipher.nonce, self.nonce_96) - - # By default, no nonce is randomly generated - self.assertFalse(hasattr(AES.new(self.key_256, AES.MODE_SIV), "nonce")) - - def test_unknown_parameters(self): - self.assertRaises(TypeError, AES.new, self.key_256, AES.MODE_SIV, - self.nonce_96, 7) - self.assertRaises(TypeError, AES.new, self.key_256, AES.MODE_SIV, - nonce=self.nonce_96, unknown=7) - - # But some are only known by the base cipher - # (e.g. use_aesni consumed by the AES module) - AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96, - use_aesni=False) - - def test_encrypt_excludes_decrypt(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - self.assertRaises(TypeError, cipher.decrypt, self.data) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data) - self.assertRaises(TypeError, cipher.decrypt_and_verify, - self.data, self.data) - - def test_data_must_be_bytes(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*') - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt_and_verify, - u'test1234567890-*', b"xxxx") - - def test_mac_len(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - _, mac = cipher.encrypt_and_digest(self.data) - self.assertEqual(len(mac), 16) - - def test_invalid_mac(self): - from Cryptodome.Util.strxor import strxor_c - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data) - - invalid_mac = strxor_c(mac, 0x01) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, - invalid_mac) - - def test_hex_mac(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - mac_hex = cipher.hexdigest() - self.assertEqual(cipher.digest(), unhexlify(mac_hex)) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.hexverify(mac_hex) - - def test_bytearray(self): - - # Encrypt - key = bytearray(self.key_256) - nonce = bytearray(self.nonce_96) - data = bytearray(self.data) - header = bytearray(self.data) - - cipher1 = AES.new(self.key_256, - AES.MODE_SIV, - nonce=self.nonce_96) - cipher1.update(self.data) - ct, tag = cipher1.encrypt_and_digest(self.data) - - cipher2 = AES.new(key, - AES.MODE_SIV, - nonce=nonce) - key[:3] = b'\xFF\xFF\xFF' - nonce[:3] = b'\xFF\xFF\xFF' - cipher2.update(header) - header[:3] = b'\xFF\xFF\xFF' - ct_test, tag_test = cipher2.encrypt_and_digest(data) - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key = bytearray(self.key_256) - nonce = bytearray(self.nonce_96) - header = bytearray(self.data) - ct_ba = bytearray(ct) - tag_ba = bytearray(tag) - - cipher3 = AES.new(key, - AES.MODE_SIV, - nonce=nonce) - key[:3] = b'\xFF\xFF\xFF' - nonce[:3] = b'\xFF\xFF\xFF' - cipher3.update(header) - header[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba) - - self.assertEqual(self.data, pt_test) - - def test_memoryview(self): - - # Encrypt - key = memoryview(bytearray(self.key_256)) - nonce = memoryview(bytearray(self.nonce_96)) - data = memoryview(bytearray(self.data)) - header = memoryview(bytearray(self.data)) - - cipher1 = AES.new(self.key_256, - AES.MODE_SIV, - nonce=self.nonce_96) - cipher1.update(self.data) - ct, tag = cipher1.encrypt_and_digest(self.data) - - cipher2 = AES.new(key, - AES.MODE_SIV, - nonce=nonce) - key[:3] = b'\xFF\xFF\xFF' - nonce[:3] = b'\xFF\xFF\xFF' - cipher2.update(header) - header[:3] = b'\xFF\xFF\xFF' - ct_test, tag_test= cipher2.encrypt_and_digest(data) - - self.assertEqual(ct, ct_test) - self.assertEqual(tag, tag_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) - - # Decrypt - key = memoryview(bytearray(self.key_256)) - nonce = memoryview(bytearray(self.nonce_96)) - header = memoryview(bytearray(self.data)) - ct_ba = memoryview(bytearray(ct)) - tag_ba = memoryview(bytearray(tag)) - - cipher3 = AES.new(key, - AES.MODE_SIV, - nonce=nonce) - key[:3] = b'\xFF\xFF\xFF' - nonce[:3] = b'\xFF\xFF\xFF' - cipher3.update(header) - header[:3] = b'\xFF\xFF\xFF' - pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba) - - self.assertEqual(self.data, pt_test) - - def test_output_param(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(pt) - - output = bytearray(128) - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - res, tag_out = cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) - self.assertEqual(tag, tag_out) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - res = cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) - - def test_output_param_memoryview(self): - - pt = b'5' * 128 - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(pt) - - output = memoryview(bytearray(128)) - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.encrypt_and_digest(pt, output=output) - self.assertEqual(ct, output) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, tag, output=output) - self.assertEqual(pt, output) - - def test_output_param_neg(self): - LEN_PT = 128 - - pt = b'5' * LEN_PT - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(pt) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt_and_digest, pt, output=b'0' * LEN_PT) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag, output=b'0' * LEN_PT) - - shorter_output = bytearray(LEN_PT - 1) - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.encrypt_and_digest, pt, output=shorter_output) - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, tag, output=shorter_output) + key_256 = get_tag_random("key_256", 32) + key_384 = get_tag_random("key_384", 48) + key_512 = get_tag_random("key_512", 64) + nonce_96 = get_tag_random("nonce_128", 12) + data = get_tag_random("data", 128) + + def test_loopback_128(self): + for key in self.key_256, self.key_384, self.key_512: + cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96) + pt = get_tag_random("plaintext", 16 * 100) + ct, mac = cipher.encrypt_and_digest(pt) + + cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) + + def test_nonce(self): + # Deterministic encryption + AES.new(self.key_256, AES.MODE_SIV) + + cipher = AES.new(self.key_256, AES.MODE_SIV, self.nonce_96) + ct1, tag1 = cipher.encrypt_and_digest(self.data) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct2, tag2 = cipher.encrypt_and_digest(self.data) + self.assertEqual(ct1 + tag1, ct2 + tag2) + + def test_nonce_must_be_bytes(self): + self.assertRaises( + TypeError, + AES.new, + self.key_256, + AES.MODE_SIV, + nonce="test12345678", + ) + + def test_nonce_length(self): + # nonce can be of any length (but not empty) + self.assertRaises( + ValueError, + AES.new, + self.key_256, + AES.MODE_SIV, + nonce=b"", + ) + + for x in range(1, 128): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=bchr(1) * x) + cipher.encrypt_and_digest(b"\x01") + + def test_block_size_128(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertEqual(cipher.block_size, AES.block_size) + + def test_nonce_attribute(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertEqual(cipher.nonce, self.nonce_96) + + # By default, no nonce is randomly generated + self.assertFalse(hasattr(AES.new(self.key_256, AES.MODE_SIV), "nonce")) + + def test_unknown_parameters(self): + self.assertRaises( + TypeError, + AES.new, + self.key_256, + AES.MODE_SIV, + self.nonce_96, + 7, + ) + self.assertRaises( + TypeError, + AES.new, + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + unknown=7, + ) + + # But some are only known by the base cipher + # (e.g. use_aesni consumed by the AES module) + AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + use_aesni=False, + ) + + def test_encrypt_excludes_decrypt(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + self.assertRaises(TypeError, cipher.decrypt, self.data) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.encrypt_and_digest(self.data) + self.assertRaises( + TypeError, + cipher.decrypt_and_verify, + self.data, + self.data, + ) + + def test_data_must_be_bytes(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt, "test1234567890-*") + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises( + TypeError, + cipher.decrypt_and_verify, + "test1234567890-*", + b"xxxx", + ) + + def test_mac_len(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + _, mac = cipher.encrypt_and_digest(self.data) + self.assertEqual(len(mac), 16) + + def test_invalid_mac(self): + from Cryptodome.Util.strxor import strxor_c + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, mac = cipher.encrypt_and_digest(self.data) + + invalid_mac = strxor_c(mac, 0x01) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises( + ValueError, + cipher.decrypt_and_verify, + ct, + invalid_mac, + ) + + def test_hex_mac(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + mac_hex = cipher.hexdigest() + self.assertEqual(cipher.digest(), unhexlify(mac_hex)) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.hexverify(mac_hex) + + def test_bytearray(self): + # Encrypt + key = bytearray(self.key_256) + nonce = bytearray(self.nonce_96) + data = bytearray(self.data) + header = bytearray(self.data) + + cipher1 = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct, tag = cipher1.encrypt_and_digest(self.data) + + cipher2 = AES.new( + key, + AES.MODE_SIV, + nonce=nonce, + ) + key[:3] = b"\xff\xff\xff" + nonce[:3] = b"\xff\xff\xff" + cipher2.update(header) + header[:3] = b"\xff\xff\xff" + ct_test, tag_test = cipher2.encrypt_and_digest(data) + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key = bytearray(self.key_256) + nonce = bytearray(self.nonce_96) + header = bytearray(self.data) + ct_ba = bytearray(ct) + tag_ba = bytearray(tag) + + cipher3 = AES.new( + key, + AES.MODE_SIV, + nonce=nonce, + ) + key[:3] = b"\xff\xff\xff" + nonce[:3] = b"\xff\xff\xff" + cipher3.update(header) + header[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba) + + self.assertEqual(self.data, pt_test) + + def test_memoryview(self): + # Encrypt + key = memoryview(bytearray(self.key_256)) + nonce = memoryview(bytearray(self.nonce_96)) + data = memoryview(bytearray(self.data)) + header = memoryview(bytearray(self.data)) + + cipher1 = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + cipher1.update(self.data) + ct, tag = cipher1.encrypt_and_digest(self.data) + + cipher2 = AES.new( + key, + AES.MODE_SIV, + nonce=nonce, + ) + key[:3] = b"\xff\xff\xff" + nonce[:3] = b"\xff\xff\xff" + cipher2.update(header) + header[:3] = b"\xff\xff\xff" + ct_test, tag_test = cipher2.encrypt_and_digest(data) + + self.assertEqual(ct, ct_test) + self.assertEqual(tag, tag_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) + + # Decrypt + key = memoryview(bytearray(self.key_256)) + nonce = memoryview(bytearray(self.nonce_96)) + header = memoryview(bytearray(self.data)) + ct_ba = memoryview(bytearray(ct)) + tag_ba = memoryview(bytearray(tag)) + + cipher3 = AES.new( + key, + AES.MODE_SIV, + nonce=nonce, + ) + key[:3] = b"\xff\xff\xff" + nonce[:3] = b"\xff\xff\xff" + cipher3.update(header) + header[:3] = b"\xff\xff\xff" + pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba) + + self.assertEqual(self.data, pt_test) + + def test_output_param(self): + pt = b"5" * 128 + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(pt) + + output = bytearray(128) + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + res, tag_out = cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) + self.assertEqual(tag, tag_out) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + res = cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) + + def test_output_param_memoryview(self): + pt = b"5" * 128 + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(pt) + + output = memoryview(bytearray(128)) + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.encrypt_and_digest(pt, output=output) + self.assertEqual(ct, output) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, tag, output=output) + self.assertEqual(pt, output) + + def test_output_param_neg(self): + LEN_PT = 128 + + pt = b"5" * LEN_PT + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(pt) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.encrypt_and_digest, pt, output=b"0" * LEN_PT) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag, output=b"0" * LEN_PT) + + shorter_output = bytearray(LEN_PT - 1) + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.encrypt_and_digest, pt, output=shorter_output) + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, tag, output=shorter_output) class SivFSMTests(unittest.TestCase): - - key_256 = get_tag_random("key_256", 32) - nonce_96 = get_tag_random("nonce_96", 12) - data = get_tag_random("data", 128) - - def test_invalid_init_encrypt(self): - # Path INIT->ENCRYPT fails - cipher = AES.new(self.key_256, AES.MODE_SIV, - nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.encrypt, b"xxx") - - def test_invalid_init_decrypt(self): - # Path INIT->DECRYPT fails - cipher = AES.new(self.key_256, AES.MODE_SIV, - nonce=self.nonce_96) - self.assertRaises(TypeError, cipher.decrypt, b"xxx") - - def test_valid_init_update_digest_verify(self): - # No plaintext, fixed authenticated data - # Verify path INIT->UPDATE->DIGEST - cipher = AES.new(self.key_256, AES.MODE_SIV, - nonce=self.nonce_96) - cipher.update(self.data) - mac = cipher.digest() - - # Verify path INIT->UPDATE->VERIFY - cipher = AES.new(self.key_256, AES.MODE_SIV, - nonce=self.nonce_96) - cipher.update(self.data) - cipher.verify(mac) - - def test_valid_init_digest(self): - # Verify path INIT->DIGEST - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.digest() - - def test_valid_init_verify(self): - # Verify path INIT->VERIFY - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - mac = cipher.digest() - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.verify(mac) - - def test_valid_multiple_digest_or_verify(self): - # Multiple calls to digest - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.update(self.data) - first_mac = cipher.digest() - for x in range(4): - self.assertEqual(first_mac, cipher.digest()) - - # Multiple calls to verify - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.update(self.data) - for x in range(5): - cipher.verify(first_mac) - - def test_valid_encrypt_and_digest_decrypt_and_verify(self): - # encrypt_and_digest - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.update(self.data) - ct, mac = cipher.encrypt_and_digest(self.data) - - # decrypt_and_verify - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.update(self.data) - pt = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(self.data, pt) - - def test_invalid_multiple_encrypt_and_digest(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(self.data) - self.assertRaises(TypeError, cipher.encrypt_and_digest, b'') - - def test_invalid_multiple_decrypt_and_verify(self): - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(self.data) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, tag) - self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag) + key_256 = get_tag_random("key_256", 32) + nonce_96 = get_tag_random("nonce_96", 12) + data = get_tag_random("data", 128) + + def test_invalid_init_encrypt(self): + # Path INIT->ENCRYPT fails + cipher = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + self.assertRaises(TypeError, cipher.encrypt, b"xxx") + + def test_invalid_init_decrypt(self): + # Path INIT->DECRYPT fails + cipher = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + self.assertRaises(TypeError, cipher.decrypt, b"xxx") + + def test_valid_init_update_digest_verify(self): + # No plaintext, fixed authenticated data + # Verify path INIT->UPDATE->DIGEST + cipher = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + cipher.update(self.data) + mac = cipher.digest() + + # Verify path INIT->UPDATE->VERIFY + cipher = AES.new( + self.key_256, + AES.MODE_SIV, + nonce=self.nonce_96, + ) + cipher.update(self.data) + cipher.verify(mac) + + def test_valid_init_digest(self): + # Verify path INIT->DIGEST + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.digest() + + def test_valid_init_verify(self): + # Verify path INIT->VERIFY + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + mac = cipher.digest() + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.verify(mac) + + def test_valid_multiple_digest_or_verify(self): + # Multiple calls to digest + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.update(self.data) + first_mac = cipher.digest() + for x in range(4): + self.assertEqual(first_mac, cipher.digest()) + + # Multiple calls to verify + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.update(self.data) + for x in range(5): + cipher.verify(first_mac) + + def test_valid_encrypt_and_digest_decrypt_and_verify(self): + # encrypt_and_digest + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.update(self.data) + ct, mac = cipher.encrypt_and_digest(self.data) + + # decrypt_and_verify + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.update(self.data) + pt = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(self.data, pt) + + def test_invalid_multiple_encrypt_and_digest(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(self.data) + self.assertRaises(TypeError, cipher.encrypt_and_digest, b"") + + def test_invalid_multiple_decrypt_and_verify(self): + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + ct, tag = cipher.encrypt_and_digest(self.data) + + cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) + cipher.decrypt_and_verify(ct, tag) + self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag) def transform(tv): - new_tv = [[unhexlify(x) for x in tv[0].split("-")]] - new_tv += [ unhexlify(x) for x in tv[1:5]] - if tv[5]: - nonce = unhexlify(tv[5]) - else: - nonce = None - new_tv += [ nonce ] - return new_tv + new_tv = [[unhexlify(x) for x in tv[0].split("-")]] + new_tv += [unhexlify(x) for x in tv[1:5]] + if tv[5]: + nonce = unhexlify(tv[5]) + else: + nonce = None + new_tv += [nonce] + return new_tv class TestVectors(unittest.TestCase): - """Class exercising the SIV test vectors found in RFC5297""" - - # This is a list of tuples with 5 items: - # - # 1. Header + '|' + plaintext - # 2. Header + '|' + ciphertext + '|' + MAC - # 3. AES-128 key - # 4. Description - # 5. Dictionary of parameters to be passed to AES.new(). - # It must include the nonce. - # - # A "Header" is a dash ('-') separated sequece of components. - # - test_vectors_hex = [ - ( - '101112131415161718191a1b1c1d1e1f2021222324252627', - '112233445566778899aabbccddee', - '40c02b9690c4dc04daef7f6afe5c', - '85632d07c6e8f37f950acd320a2ecc93', - 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff', - None - ), - ( - '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988' + - '7766554433221100-102030405060708090a0', - '7468697320697320736f6d6520706c61696e7465787420746f20656e63727970' + - '74207573696e67205349562d414553', - 'cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829' + - 'ea64ad544a272e9c485b62a3fd5c0d', - '7bdb6e3b432667eb06f4d14bff2fbd0f', - '7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f', - '09f911029d74e35bd84156c5635688c0' - ), - ] - - test_vectors = [ transform(tv) for tv in test_vectors_hex ] - - def runTest(self): - for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: - - # Encrypt - cipher = AES.new(key, AES.MODE_SIV, nonce=nonce) - for x in assoc_data: - cipher.update(x) - ct2, mac2 = cipher.encrypt_and_digest(pt) - self.assertEqual(ct, ct2) - self.assertEqual(mac, mac2) - - # Decrypt - cipher = AES.new(key, AES.MODE_SIV, nonce=nonce) - for x in assoc_data: - cipher.update(x) - pt2 = cipher.decrypt_and_verify(ct, mac) - self.assertEqual(pt, pt2) + """Class exercising the SIV test vectors found in RFC5297""" + + # This is a list of tuples with 5 items: + # + # 1. Header + '|' + plaintext + # 2. Header + '|' + ciphertext + '|' + MAC + # 3. AES-128 key + # 4. Description + # 5. Dictionary of parameters to be passed to AES.new(). + # It must include the nonce. + # + # A "Header" is a dash ('-') separated sequece of components. + # + test_vectors_hex = [ + ( + "101112131415161718191a1b1c1d1e1f2021222324252627", + "112233445566778899aabbccddee", + "40c02b9690c4dc04daef7f6afe5c", + "85632d07c6e8f37f950acd320a2ecc93", + "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + None, + ), + ( + "00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988" + + "7766554433221100-102030405060708090a0", + "7468697320697320736f6d6520706c61696e7465787420746f20656e63727970" + + "74207573696e67205349562d414553", + "cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829" + + "ea64ad544a272e9c485b62a3fd5c0d", + "7bdb6e3b432667eb06f4d14bff2fbd0f", + "7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f", + "09f911029d74e35bd84156c5635688c0", + ), + ] + + test_vectors = [transform(tv) for tv in test_vectors_hex] + + def runTest(self): + for assoc_data, pt, ct, mac, key, nonce in self.test_vectors: + # Encrypt + cipher = AES.new(key, AES.MODE_SIV, nonce=nonce) + for x in assoc_data: + cipher.update(x) + ct2, mac2 = cipher.encrypt_and_digest(pt) + self.assertEqual(ct, ct2) + self.assertEqual(mac, mac2) + + # Decrypt + cipher = AES.new(key, AES.MODE_SIV, nonce=nonce) + for x in assoc_data: + cipher.update(x) + pt2 = cipher.decrypt_and_verify(ct, mac) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self): - unittest.TestCase.__init__(self) - self._id = "None" - - def setUp(self): - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aes_siv_cmac_test.json", - "Wycheproof AES SIV") - - def shortDescription(self): - return self._id - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt AES-SIV Test #" + str(tv.id) - - cipher = AES.new(tv.key, AES.MODE_SIV) - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(tag + ct, tv.ct) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt AES_SIV Test #" + str(tv.id) - - cipher = AES.new(tv.key, AES.MODE_SIV) - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct[16:], tv.ct[:16]) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) + def __init__(self): + unittest.TestCase.__init__(self) + self._id = "None" + + def setUp(self): + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aes_siv_cmac_test.json", + "Wycheproof AES SIV", + ) + + def shortDescription(self): + return self._id + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt AES-SIV Test #" + str(tv.id) + + cipher = AES.new(tv.key, AES.MODE_SIV) + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(tag + ct, tv.ct) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt AES_SIV Test #" + str(tv.id) + + cipher = AES.new(tv.key, AES.MODE_SIV) + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct[16:], tv.ct[:16]) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) class TestVectorsWycheproof2(unittest.TestCase): - - def __init__(self): - unittest.TestCase.__init__(self) - self._id = "None" - - def setUp(self): - self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - "aead_aes_siv_cmac_test.json", - "Wycheproof AEAD SIV") - - def shortDescription(self): - return self._id - - def test_encrypt(self, tv): - self._id = "Wycheproof Encrypt AEAD-AES-SIV Test #" + str(tv.id) - - cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv) - cipher.update(tv.aad) - ct, tag = cipher.encrypt_and_digest(tv.msg) - if tv.valid: - self.assertEqual(ct, tv.ct) - self.assertEqual(tag, tv.tag) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt AEAD-AES-SIV Test #" + str(tv.id) - - cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv) - cipher.update(tv.aad) - try: - pt = cipher.decrypt_and_verify(tv.ct, tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - - def runTest(self): - - for tv in self.tv: - self.test_encrypt(tv) - self.test_decrypt(tv) + def __init__(self): + unittest.TestCase.__init__(self) + self._id = "None" + + def setUp(self): + self.tv = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + "aead_aes_siv_cmac_test.json", + "Wycheproof AEAD SIV", + ) + + def shortDescription(self): + return self._id + + def test_encrypt(self, tv): + self._id = "Wycheproof Encrypt AEAD-AES-SIV Test #" + str(tv.id) + + cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv) + cipher.update(tv.aad) + ct, tag = cipher.encrypt_and_digest(tv.msg) + if tv.valid: + self.assertEqual(ct, tv.ct) + self.assertEqual(tag, tv.tag) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt AEAD-AES-SIV Test #" + str(tv.id) + + cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv) + cipher.update(tv.aad) + try: + pt = cipher.decrypt_and_verify(tv.ct, tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + + def runTest(self): + for tv in self.tv: + self.test_encrypt(tv) + self.test_decrypt(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") - tests = [] - tests += list_test_cases(SivTests) - tests += list_test_cases(SivFSMTests) - tests += [ TestVectors() ] - tests += [ TestVectorsWycheproof() ] - tests += [ TestVectorsWycheproof2() ] - return tests + tests = [] + tests += list_test_cases(SivTests) + tests += list_test_cases(SivFSMTests) + tests += [TestVectors()] + tests += [TestVectorsWycheproof()] + tests += [TestVectorsWycheproof2()] + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_Salsa20.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_Salsa20.py index a4449062..a46c518b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_Salsa20.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_Salsa20.py @@ -37,331 +37,331 @@ # This is a list of (plaintext, ciphertext, key[, description[, params]]) # tuples. test_data = [ - # Test vectors are taken from - # http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors - ( '00' * 512, - '4dfa5e481da23ea09a31022050859936da52fcee218005164f267cb65f5cfd7f' - + '2b4f97e0ff16924a52df269515110a07f9e460bc65ef95da58f740b7d1dbb0aa' - + 'd64cec189c7eb8c6bbf3d7376c80a481d43e628701f6a27afb9fe23919f24114' - + '8db44f70d7063efcc3dd55a0893a613c3c6fe1c127bd6f59910589293bb6ef9e' - + 'e24819066dee1a64f49b0bbad5988635272b169af861f85df881939f29ada6fd' - + '0241410e8d332ae4798d929434a2630de451ec4e0169694cbaa7ebb121ea6a2b' - + 'da9c1581f429e0a00f7d67e23b730676783b262e8eb43a25f55fb90b3e753aef' - + '8c6713ec66c51881111593ccb3e8cb8f8de124080501eeeb389c4bcb6977cf95' - + '7d5789631eb4554400e1e025935dfa7b3e9039d61bdc58a8697d36815bf1985c' - + 'efdf7ae112e5bb81e37ecf0616ce7147fc08a93a367e08631f23c03b00a8da2f' - + 'aa5024e5c8d30aca43fc2d5082067b21b234bc741d68fb292c6012c3764ccee3' - + '1e364a5403e00cfee338a21a01e7d3cefd5a770ca0ab48c435ea6116435f7ad8' - + '30b217b49f978a68e207ed9f462af7fb195b2115fe8f24f152e4ddc32202d6f2' - + 'b52fafbcfbc202d8a259a611e901d3f62d065eb13f09bbc45cd45119b843efaa' - + 'b375703739daced4dd4059fd71c3c47fc2f9939670fad4a46066adcc6a564578' - + '3308b90ffb72be04a6b147cbe38cc0c3b9267c296a92a7c69873f9f263be9703', - '80000000000000000000000000000000', - '128 bits key, set 1, vector 0', - dict (iv='00'*8)), - - ( '00' * 512, - 'e3be8fdd8beca2e3ea8ef9475b29a6e7003951e1097a5c38d23b7a5fad9f6844' - + 'b22c97559e2723c7cbbd3fe4fc8d9a0744652a83e72a9c461876af4d7ef1a117' - + '8da2b74eef1b6283e7e20166abcae538e9716e4669e2816b6b20c5c356802001' - + 'cc1403a9a117d12a2669f456366d6ebb0f1246f1265150f793cdb4b253e348ae' - + '203d89bc025e802a7e0e00621d70aa36b7e07cb1e7d5b38d5e222b8b0e4b8407' - + '0142b1e29504767d76824850320b5368129fdd74e861b498e3be8d16f2d7d169' - + '57be81f47b17d9ae7c4ff15429a73e10acf250ed3a90a93c711308a74c6216a9' - + 'ed84cd126da7f28e8abf8bb63517e1ca98e712f4fb2e1a6aed9fdc73291faa17' - + '958211c4ba2ebd5838c635edb81f513a91a294e194f1c039aeec657dce40aa7e' - + '7c0af57cacefa40c9f14b71a4b3456a63e162ec7d8d10b8ffb1810d71001b618' - + '2f9f73da53b85405c11f7b2d890fa8ae0c7f2e926d8a98c7ec4e91b65120e988' - + '349631a700c6facec3471cb0413656e75e309456584084d7e12c5b43a41c43ed' - + '9a048abd9b880da65f6a665a20fe7b77cd292fe62cae644b7f7df69f32bdb331' - + '903e6505ce44fdc293920c6a9ec7057e23df7dad298f82ddf4efb7fdc7bfc622' - + '696afcfd0cddcc83c7e77f11a649d79acdc3354e9635ff137e929933a0bd6f53' - + '77efa105a3a4266b7c0d089d08f1e855cc32b15b93784a36e56a76cc64bc8477', - '8000000000000000000000000000000000000000000000000000000000000000', - '256 bits key, set 1, vector 0', - dict (iv='00'*8)), - - ( '00' * 512, - '169060ccb42bea7bee4d8012a02f3635eb7bca12859fa159cd559094b3507db8' - + '01735d1a1300102a9c9415546829cbd2021ba217b39b81d89c55b13d0c603359' - + '3f84159a3c84f4b4f4a0edcd9d38ff261a737909e0b66d68b5cac496f3a5be99' - + 'cb12c321ab711afaab36cc0947955e1a9bb952ed54425e7711279fbc81bb83f5' - + '6e55cea44e6daddb05858a153ea6213b3350c12aa1a83ef2726f09485fa71790' - + 'f9b9f922c7dda1113b1f9d56658ed3402803f511bc1f122601d5e7f0ff036e23' - + '23ef24bb24195b9fd574823cd8a40c29d86bd35c191e2038779ff696c712b6d8' - + '2e7014dbe1ac5d527af076c088c4a8d44317958189f6ef54933a7e0816b5b916' - + 'd8f12ed8afe9422b85e5cc9b8adec9d6cfabe8dbc1082bccc02f5a7266aa074c' - + 'a284e583a35837798cc0e69d4ce937653b8cdd65ce414b89138615ccb165ad19' - + '3c6b9c3d05eef4be921a10ea811fe61d11c6867600188e065daff90b509ec56b' - + 'd41e7e8968c478c78d590c2d2ee24ea009c8f49bc3d81672cfc47895a9e21c9a' - + '471ebf8e294bee5d2de436ac8d052bf31111b345f1da23c3a4d13b9fc5f0900a' - + 'a298f98f538973b8fad40d4d159777de2cfe2a3dead1645ddb49794827dba040' - + 'f70a0ff4ecd155e0f033604693a51e2363880e2ecf98699e7174af7c2c6b0fc6' - + '59ae329599a3949272a37b9b2183a0910922a3f325ae124dcbdd735364055ceb', - '09090909090909090909090909090909', - '128 bits key, set 2, vector 9', - dict (iv='00'*8)), - - ( '00' * 512, - '7041e747ceb22ed7812985465f50333124f971da1c5d6efe5ca201b886f31046' - + 'e757e5c3ec914f60ed1f6bce2819b6810953f12b8ba1199bf82d746a8b8a88f1' - + '142002978ec4c35b95dc2c82990f9e847a0ab45f2ca72625f5190c820f29f3aa' - + 'f5f0b5572b06b70a144f2a240c3b3098d4831fa1ce1459f8d1df226a6a79b0ab' - + '41e91799ef31b5ff3d756c19126b19025858ee70fbd69f2be955cb011c005e31' - + '32b271b378f39b0cb594e95c99ce6ff17735a541891845bbf0450afcb4a850b9' - + '4ee90afb713ae7e01295c74381180a3816d7020d5a396c0d97aaa783eaabb6ec' - + '44d5111157f2212d1b1b8fca7893e8b520cd482418c272ab119b569a2b9598eb' - + '355624d12e79adab81153b58cd22eaf1b2a32395dedc4a1c66f4d274070b9800' - + 'ea95766f0245a8295f8aadb36ddbbdfa936417c8dbc6235d19494036964d3e70' - + 'b125b0f800c3d53881d9d11e7970f827c2f9556935cd29e927b0aceb8cae5fd4' - + '0fd88a8854010a33db94c96c98735858f1c5df6844f864feaca8f41539313e7f' - + '3c0610214912cd5e6362197646207e2d64cd5b26c9dfe0822629dcbeb16662e8' - + '9ff5bf5cf2e499138a5e27bd5027329d0e68ddf53103e9e409523662e27f61f6' - + '5cf38c1232023e6a6ef66c315bcb2a4328642faabb7ca1e889e039e7c444b34b' - + 'b3443f596ac730f3df3dfcdb343c307c80f76e43e8898c5e8f43dc3bb280add0', - '0909090909090909090909090909090909090909090909090909090909090909', - '256 bits key, set 2, vector 9', - dict (iv='00'*8)), - - ( '00' * 1024, - '71daee5142d0728b41b6597933ebf467e43279e30978677078941602629cbf68' - + 'b73d6bd2c95f118d2b3e6ec955dabb6dc61c4143bc9a9b32b99dbe6866166dc0' - + '8631b7d6553050303d7252c264d3a90d26c853634813e09ad7545a6ce7e84a5d' - + 'fc75ec43431207d5319970b0faadb0e1510625bb54372c8515e28e2accf0a993' - + '0ad15f431874923d2a59e20d9f2a5367dba6051564f150287debb1db536ff9b0' - + '9ad981f25e5010d85d76ee0c305f755b25e6f09341e0812f95c94f42eead346e' - + '81f39c58c5faa2c88953dc0cac90469db2063cb5cdb22c9eae22afbf0506fca4' - + '1dc710b846fbdfe3c46883dd118f3a5e8b11b6afd9e71680d8666557301a2daa' - + 'fb9496c559784d35a035360885f9b17bd7191977deea932b981ebdb29057ae3c' - + '92cfeff5e6c5d0cb62f209ce342d4e35c69646ccd14e53350e488bb310a32f8b' - + '0248e70acc5b473df537ced3f81a014d4083932bedd62ed0e447b6766cd2604b' - + '706e9b346c4468beb46a34ecf1610ebd38331d52bf33346afec15eefb2a7699e' - + '8759db5a1f636a48a039688e39de34d995df9f27ed9edc8dd795e39e53d9d925' - + 'b278010565ff665269042f05096d94da3433d957ec13d2fd82a0066283d0d1ee' - + 'b81bf0ef133b7fd90248b8ffb499b2414cd4fa003093ff0864575a43749bf596' - + '02f26c717fa96b1d057697db08ebc3fa664a016a67dcef8807577cc3a09385d3' - + 'f4dc79b34364bb3b166ce65fe1dd28e3950fe6fa81063f7b16ce1c0e6daac1f8' - + '188455b77752045e863c9b256ad92bc6e2d08314c5bba191c274f42dfbb3d652' - + 'bb771956555e880f84cd8b827a4c5a52f3a099fa0259bd4aac3efd541f191170' - + '4412d6e85fbcc628b335875b9fef24807f6e1bc66c3186159e1e7f5a13913e02' - + 'd241ce2efdbcaa275039fb14eac5923d17ffbc7f1abd3b45e92127575bfbabf9' - + '3a257ebef0aa1437b326e41b585af572f7239c33b32981a1577a4f629b027e1e' - + 'b49d58cc497e944d79cef44357c2bf25442ab779651e991147bf79d6fd3a8868' - + '0cd3b1748e07fd10d78aceef6db8a5e563570d40127f754146c34a440f2a991a' - + '23fa39d365141f255041f2135c5cba4373452c114da1801bacca38610e3a6524' - + '2b822d32de4ab5a7d3cf9b61b37493c863bd12e2cae10530cddcda2cb7a5436b' - + 'ef8988d4d24e8cdc31b2d2a3586340bc5141f8f6632d0dd543bfed81eb471ba1' - + 'f3dc2225a15ffddcc03eb48f44e27e2aa390598adf83f15c6608a5f18d4dfcf0' - + 'f547d467a4d70b281c83a595d7660d0b62de78b9cca023cca89d7b1f83484638' - + '0e228c25f049184a612ef5bb3d37454e6cfa5b10dceda619d898a699b3c8981a' - + '173407844bb89b4287bf57dd6600c79e352c681d74b03fa7ea0d7bf6ad69f8a6' - + '8ecb001963bd2dd8a2baa0083ec09751cd9742402ad716be16d5c052304cfca1', - '0F62B5085BAE0154A7FA4DA0F34699EC', - '128 bits key, Set 6, vector# 3', - dict (iv='288FF65DC42B92F9')), - - ( '00' * 1024, - '5e5e71f90199340304abb22a37b6625bf883fb89ce3b21f54a10b81066ef87da' - + '30b77699aa7379da595c77dd59542da208e5954f89e40eb7aa80a84a6176663f' - + 'd910cde567cf1ff60f7040548d8f376bfd1f44c4774aac37410ede7d5c3463fc' - + '4508a603201d8495ad257894e5eb1914b53e8da5e4bf2bc83ac87ce55cc67df7' - + '093d9853d2a83a9c8be969175df7c807a17156df768445dd0874a9271c6537f5' - + 'ce0466473582375f067fa4fcdaf65dbc0139cd75e8c21a482f28c0fb8c3d9f94' - + '22606cc8e88fe28fe73ec3cb10ff0e8cc5f2a49e540f007265c65b7130bfdb98' - + '795b1df9522da46e48b30e55d9f0d787955ece720205b29c85f3ad9be33b4459' - + '7d21b54d06c9a60b04b8e640c64e566e51566730e86cf128ab14174f91bd8981' - + 'a6fb00fe587bbd6c38b5a1dfdb04ea7e61536fd229f957aa9b070ca931358e85' - + '11b92c53c523cb54828fb1513c5636fa9a0645b4a3c922c0db94986d92f314ff' - + '7852c03b231e4dceea5dd8cced621869cff818daf3c270ff3c8be2e5c74be767' - + 'a4e1fdf3327a934fe31e46df5a74ae2021cee021d958c4f615263d99a5ddae7f' - + 'eab45e6eccbafefe4761c57750847b7e75ee2e2f14333c0779ce4678f47b1e1b' - + '760a03a5f17d6e91d4b42313b3f1077ee270e432fe04917ed1fc8babebf7c941' - + '42b80dfb44a28a2a3e59093027606f6860bfb8c2e5897078cfccda7314c70035' - + 'f137de6f05daa035891d5f6f76e1df0fce1112a2ff0ac2bd3534b5d1bf4c7165' - + 'fb40a1b6eacb7f295711c4907ae457514a7010f3a342b4427593d61ba993bc59' - + '8bd09c56b9ee53aac5dd861fa4b4bb53888952a4aa9d8ca8671582de716270e1' - + '97375b3ee49e51fa2bf4ef32015dd9a764d966aa2ae541592d0aa650849e99ca' - + '5c6c39beebf516457cc32fe4c105bff314a12f1ec94bdf4d626f5d9b1cbbde42' - + 'e5733f0885765ba29e2e82c829d312f5fc7e180679ac84826c08d0a644b326d0' - + '44da0fdcc75fa53cfe4ced0437fa4df5a7ecbca8b4cb7c4a9ecf9a60d00a56eb' - + '81da52adc21f508dbb60a9503a3cc94a896616d86020d5b0e5c637329b6d396a' - + '41a21ba2c4a9493cf33fa2d4f10f77d5b12fdad7e478ccfe79b74851fc96a7ca' - + '6320c5efd561a222c0ab0fb44bbda0e42149611d2262bb7d1719150fa798718a' - + '0eec63ee297cad459869c8b0f06c4e2b56cbac03cd2605b2a924efedf85ec8f1' - + '9b0b6c90e7cbd933223ffeb1b3a3f9677657905829294c4c70acdb8b0891b47d' - + '0875d0cd6c0f4efe2917fc44b581ef0d1e4280197065d07da34ab33283364552' - + 'efad0bd9257b059acdd0a6f246812feb69e7e76065f27dbc2eee94da9cc41835' - + 'bf826e36e5cebe5d4d6a37a6a666246290ce51a0c082718ab0ec855668db1add' - + 'a658e5f257e0db39384d02e6145c4c00eaa079098f6d820d872de711b6ed08cf', - '0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C', - '256 bits key, Set 6, vector# 3', - dict (iv='288FF65DC42B92F9')), - + # Test vectors are taken from + # http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors + ( + "00" * 512, + "4dfa5e481da23ea09a31022050859936da52fcee218005164f267cb65f5cfd7f" + + "2b4f97e0ff16924a52df269515110a07f9e460bc65ef95da58f740b7d1dbb0aa" + + "d64cec189c7eb8c6bbf3d7376c80a481d43e628701f6a27afb9fe23919f24114" + + "8db44f70d7063efcc3dd55a0893a613c3c6fe1c127bd6f59910589293bb6ef9e" + + "e24819066dee1a64f49b0bbad5988635272b169af861f85df881939f29ada6fd" + + "0241410e8d332ae4798d929434a2630de451ec4e0169694cbaa7ebb121ea6a2b" + + "da9c1581f429e0a00f7d67e23b730676783b262e8eb43a25f55fb90b3e753aef" + + "8c6713ec66c51881111593ccb3e8cb8f8de124080501eeeb389c4bcb6977cf95" + + "7d5789631eb4554400e1e025935dfa7b3e9039d61bdc58a8697d36815bf1985c" + + "efdf7ae112e5bb81e37ecf0616ce7147fc08a93a367e08631f23c03b00a8da2f" + + "aa5024e5c8d30aca43fc2d5082067b21b234bc741d68fb292c6012c3764ccee3" + + "1e364a5403e00cfee338a21a01e7d3cefd5a770ca0ab48c435ea6116435f7ad8" + + "30b217b49f978a68e207ed9f462af7fb195b2115fe8f24f152e4ddc32202d6f2" + + "b52fafbcfbc202d8a259a611e901d3f62d065eb13f09bbc45cd45119b843efaa" + + "b375703739daced4dd4059fd71c3c47fc2f9939670fad4a46066adcc6a564578" + + "3308b90ffb72be04a6b147cbe38cc0c3b9267c296a92a7c69873f9f263be9703", + "80000000000000000000000000000000", + "128 bits key, set 1, vector 0", + dict(iv="00" * 8), + ), + ( + "00" * 512, + "e3be8fdd8beca2e3ea8ef9475b29a6e7003951e1097a5c38d23b7a5fad9f6844" + + "b22c97559e2723c7cbbd3fe4fc8d9a0744652a83e72a9c461876af4d7ef1a117" + + "8da2b74eef1b6283e7e20166abcae538e9716e4669e2816b6b20c5c356802001" + + "cc1403a9a117d12a2669f456366d6ebb0f1246f1265150f793cdb4b253e348ae" + + "203d89bc025e802a7e0e00621d70aa36b7e07cb1e7d5b38d5e222b8b0e4b8407" + + "0142b1e29504767d76824850320b5368129fdd74e861b498e3be8d16f2d7d169" + + "57be81f47b17d9ae7c4ff15429a73e10acf250ed3a90a93c711308a74c6216a9" + + "ed84cd126da7f28e8abf8bb63517e1ca98e712f4fb2e1a6aed9fdc73291faa17" + + "958211c4ba2ebd5838c635edb81f513a91a294e194f1c039aeec657dce40aa7e" + + "7c0af57cacefa40c9f14b71a4b3456a63e162ec7d8d10b8ffb1810d71001b618" + + "2f9f73da53b85405c11f7b2d890fa8ae0c7f2e926d8a98c7ec4e91b65120e988" + + "349631a700c6facec3471cb0413656e75e309456584084d7e12c5b43a41c43ed" + + "9a048abd9b880da65f6a665a20fe7b77cd292fe62cae644b7f7df69f32bdb331" + + "903e6505ce44fdc293920c6a9ec7057e23df7dad298f82ddf4efb7fdc7bfc622" + + "696afcfd0cddcc83c7e77f11a649d79acdc3354e9635ff137e929933a0bd6f53" + + "77efa105a3a4266b7c0d089d08f1e855cc32b15b93784a36e56a76cc64bc8477", + "8000000000000000000000000000000000000000000000000000000000000000", + "256 bits key, set 1, vector 0", + dict(iv="00" * 8), + ), + ( + "00" * 512, + "169060ccb42bea7bee4d8012a02f3635eb7bca12859fa159cd559094b3507db8" + + "01735d1a1300102a9c9415546829cbd2021ba217b39b81d89c55b13d0c603359" + + "3f84159a3c84f4b4f4a0edcd9d38ff261a737909e0b66d68b5cac496f3a5be99" + + "cb12c321ab711afaab36cc0947955e1a9bb952ed54425e7711279fbc81bb83f5" + + "6e55cea44e6daddb05858a153ea6213b3350c12aa1a83ef2726f09485fa71790" + + "f9b9f922c7dda1113b1f9d56658ed3402803f511bc1f122601d5e7f0ff036e23" + + "23ef24bb24195b9fd574823cd8a40c29d86bd35c191e2038779ff696c712b6d8" + + "2e7014dbe1ac5d527af076c088c4a8d44317958189f6ef54933a7e0816b5b916" + + "d8f12ed8afe9422b85e5cc9b8adec9d6cfabe8dbc1082bccc02f5a7266aa074c" + + "a284e583a35837798cc0e69d4ce937653b8cdd65ce414b89138615ccb165ad19" + + "3c6b9c3d05eef4be921a10ea811fe61d11c6867600188e065daff90b509ec56b" + + "d41e7e8968c478c78d590c2d2ee24ea009c8f49bc3d81672cfc47895a9e21c9a" + + "471ebf8e294bee5d2de436ac8d052bf31111b345f1da23c3a4d13b9fc5f0900a" + + "a298f98f538973b8fad40d4d159777de2cfe2a3dead1645ddb49794827dba040" + + "f70a0ff4ecd155e0f033604693a51e2363880e2ecf98699e7174af7c2c6b0fc6" + + "59ae329599a3949272a37b9b2183a0910922a3f325ae124dcbdd735364055ceb", + "09090909090909090909090909090909", + "128 bits key, set 2, vector 9", + dict(iv="00" * 8), + ), + ( + "00" * 512, + "7041e747ceb22ed7812985465f50333124f971da1c5d6efe5ca201b886f31046" + + "e757e5c3ec914f60ed1f6bce2819b6810953f12b8ba1199bf82d746a8b8a88f1" + + "142002978ec4c35b95dc2c82990f9e847a0ab45f2ca72625f5190c820f29f3aa" + + "f5f0b5572b06b70a144f2a240c3b3098d4831fa1ce1459f8d1df226a6a79b0ab" + + "41e91799ef31b5ff3d756c19126b19025858ee70fbd69f2be955cb011c005e31" + + "32b271b378f39b0cb594e95c99ce6ff17735a541891845bbf0450afcb4a850b9" + + "4ee90afb713ae7e01295c74381180a3816d7020d5a396c0d97aaa783eaabb6ec" + + "44d5111157f2212d1b1b8fca7893e8b520cd482418c272ab119b569a2b9598eb" + + "355624d12e79adab81153b58cd22eaf1b2a32395dedc4a1c66f4d274070b9800" + + "ea95766f0245a8295f8aadb36ddbbdfa936417c8dbc6235d19494036964d3e70" + + "b125b0f800c3d53881d9d11e7970f827c2f9556935cd29e927b0aceb8cae5fd4" + + "0fd88a8854010a33db94c96c98735858f1c5df6844f864feaca8f41539313e7f" + + "3c0610214912cd5e6362197646207e2d64cd5b26c9dfe0822629dcbeb16662e8" + + "9ff5bf5cf2e499138a5e27bd5027329d0e68ddf53103e9e409523662e27f61f6" + + "5cf38c1232023e6a6ef66c315bcb2a4328642faabb7ca1e889e039e7c444b34b" + + "b3443f596ac730f3df3dfcdb343c307c80f76e43e8898c5e8f43dc3bb280add0", + "0909090909090909090909090909090909090909090909090909090909090909", + "256 bits key, set 2, vector 9", + dict(iv="00" * 8), + ), + ( + "00" * 1024, + "71daee5142d0728b41b6597933ebf467e43279e30978677078941602629cbf68" + + "b73d6bd2c95f118d2b3e6ec955dabb6dc61c4143bc9a9b32b99dbe6866166dc0" + + "8631b7d6553050303d7252c264d3a90d26c853634813e09ad7545a6ce7e84a5d" + + "fc75ec43431207d5319970b0faadb0e1510625bb54372c8515e28e2accf0a993" + + "0ad15f431874923d2a59e20d9f2a5367dba6051564f150287debb1db536ff9b0" + + "9ad981f25e5010d85d76ee0c305f755b25e6f09341e0812f95c94f42eead346e" + + "81f39c58c5faa2c88953dc0cac90469db2063cb5cdb22c9eae22afbf0506fca4" + + "1dc710b846fbdfe3c46883dd118f3a5e8b11b6afd9e71680d8666557301a2daa" + + "fb9496c559784d35a035360885f9b17bd7191977deea932b981ebdb29057ae3c" + + "92cfeff5e6c5d0cb62f209ce342d4e35c69646ccd14e53350e488bb310a32f8b" + + "0248e70acc5b473df537ced3f81a014d4083932bedd62ed0e447b6766cd2604b" + + "706e9b346c4468beb46a34ecf1610ebd38331d52bf33346afec15eefb2a7699e" + + "8759db5a1f636a48a039688e39de34d995df9f27ed9edc8dd795e39e53d9d925" + + "b278010565ff665269042f05096d94da3433d957ec13d2fd82a0066283d0d1ee" + + "b81bf0ef133b7fd90248b8ffb499b2414cd4fa003093ff0864575a43749bf596" + + "02f26c717fa96b1d057697db08ebc3fa664a016a67dcef8807577cc3a09385d3" + + "f4dc79b34364bb3b166ce65fe1dd28e3950fe6fa81063f7b16ce1c0e6daac1f8" + + "188455b77752045e863c9b256ad92bc6e2d08314c5bba191c274f42dfbb3d652" + + "bb771956555e880f84cd8b827a4c5a52f3a099fa0259bd4aac3efd541f191170" + + "4412d6e85fbcc628b335875b9fef24807f6e1bc66c3186159e1e7f5a13913e02" + + "d241ce2efdbcaa275039fb14eac5923d17ffbc7f1abd3b45e92127575bfbabf9" + + "3a257ebef0aa1437b326e41b585af572f7239c33b32981a1577a4f629b027e1e" + + "b49d58cc497e944d79cef44357c2bf25442ab779651e991147bf79d6fd3a8868" + + "0cd3b1748e07fd10d78aceef6db8a5e563570d40127f754146c34a440f2a991a" + + "23fa39d365141f255041f2135c5cba4373452c114da1801bacca38610e3a6524" + + "2b822d32de4ab5a7d3cf9b61b37493c863bd12e2cae10530cddcda2cb7a5436b" + + "ef8988d4d24e8cdc31b2d2a3586340bc5141f8f6632d0dd543bfed81eb471ba1" + + "f3dc2225a15ffddcc03eb48f44e27e2aa390598adf83f15c6608a5f18d4dfcf0" + + "f547d467a4d70b281c83a595d7660d0b62de78b9cca023cca89d7b1f83484638" + + "0e228c25f049184a612ef5bb3d37454e6cfa5b10dceda619d898a699b3c8981a" + + "173407844bb89b4287bf57dd6600c79e352c681d74b03fa7ea0d7bf6ad69f8a6" + + "8ecb001963bd2dd8a2baa0083ec09751cd9742402ad716be16d5c052304cfca1", + "0F62B5085BAE0154A7FA4DA0F34699EC", + "128 bits key, Set 6, vector# 3", + dict(iv="288FF65DC42B92F9"), + ), + ( + "00" * 1024, + "5e5e71f90199340304abb22a37b6625bf883fb89ce3b21f54a10b81066ef87da" + + "30b77699aa7379da595c77dd59542da208e5954f89e40eb7aa80a84a6176663f" + + "d910cde567cf1ff60f7040548d8f376bfd1f44c4774aac37410ede7d5c3463fc" + + "4508a603201d8495ad257894e5eb1914b53e8da5e4bf2bc83ac87ce55cc67df7" + + "093d9853d2a83a9c8be969175df7c807a17156df768445dd0874a9271c6537f5" + + "ce0466473582375f067fa4fcdaf65dbc0139cd75e8c21a482f28c0fb8c3d9f94" + + "22606cc8e88fe28fe73ec3cb10ff0e8cc5f2a49e540f007265c65b7130bfdb98" + + "795b1df9522da46e48b30e55d9f0d787955ece720205b29c85f3ad9be33b4459" + + "7d21b54d06c9a60b04b8e640c64e566e51566730e86cf128ab14174f91bd8981" + + "a6fb00fe587bbd6c38b5a1dfdb04ea7e61536fd229f957aa9b070ca931358e85" + + "11b92c53c523cb54828fb1513c5636fa9a0645b4a3c922c0db94986d92f314ff" + + "7852c03b231e4dceea5dd8cced621869cff818daf3c270ff3c8be2e5c74be767" + + "a4e1fdf3327a934fe31e46df5a74ae2021cee021d958c4f615263d99a5ddae7f" + + "eab45e6eccbafefe4761c57750847b7e75ee2e2f14333c0779ce4678f47b1e1b" + + "760a03a5f17d6e91d4b42313b3f1077ee270e432fe04917ed1fc8babebf7c941" + + "42b80dfb44a28a2a3e59093027606f6860bfb8c2e5897078cfccda7314c70035" + + "f137de6f05daa035891d5f6f76e1df0fce1112a2ff0ac2bd3534b5d1bf4c7165" + + "fb40a1b6eacb7f295711c4907ae457514a7010f3a342b4427593d61ba993bc59" + + "8bd09c56b9ee53aac5dd861fa4b4bb53888952a4aa9d8ca8671582de716270e1" + + "97375b3ee49e51fa2bf4ef32015dd9a764d966aa2ae541592d0aa650849e99ca" + + "5c6c39beebf516457cc32fe4c105bff314a12f1ec94bdf4d626f5d9b1cbbde42" + + "e5733f0885765ba29e2e82c829d312f5fc7e180679ac84826c08d0a644b326d0" + + "44da0fdcc75fa53cfe4ced0437fa4df5a7ecbca8b4cb7c4a9ecf9a60d00a56eb" + + "81da52adc21f508dbb60a9503a3cc94a896616d86020d5b0e5c637329b6d396a" + + "41a21ba2c4a9493cf33fa2d4f10f77d5b12fdad7e478ccfe79b74851fc96a7ca" + + "6320c5efd561a222c0ab0fb44bbda0e42149611d2262bb7d1719150fa798718a" + + "0eec63ee297cad459869c8b0f06c4e2b56cbac03cd2605b2a924efedf85ec8f1" + + "9b0b6c90e7cbd933223ffeb1b3a3f9677657905829294c4c70acdb8b0891b47d" + + "0875d0cd6c0f4efe2917fc44b581ef0d1e4280197065d07da34ab33283364552" + + "efad0bd9257b059acdd0a6f246812feb69e7e76065f27dbc2eee94da9cc41835" + + "bf826e36e5cebe5d4d6a37a6a666246290ce51a0c082718ab0ec855668db1add" + + "a658e5f257e0db39384d02e6145c4c00eaa079098f6d820d872de711b6ed08cf", + "0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C", + "256 bits key, Set 6, vector# 3", + dict(iv="288FF65DC42B92F9"), + ), ] class KeyLength(unittest.TestCase): - - def runTest(self): - - nonce = bchr(0) * 8 - for key_length in (15, 30, 33): - key = bchr(1) * key_length - self.assertRaises(ValueError, Salsa20.new, key, nonce) + def runTest(self): + nonce = bchr(0) * 8 + for key_length in (15, 30, 33): + key = bchr(1) * key_length + self.assertRaises(ValueError, Salsa20.new, key, nonce) class NonceTests(unittest.TestCase): + def test_invalid_nonce_length(self): + key = bchr(1) * 16 + self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 7) + self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 9) - def test_invalid_nonce_length(self): - key = bchr(1) * 16 - self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 7) - self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 9) - - def test_default_nonce(self): - - cipher1 = Salsa20.new(bchr(1) * 16) - cipher2 = Salsa20.new(bchr(1) * 16) - self.assertEqual(len(cipher1.nonce), 8) - self.assertNotEqual(cipher1.nonce, cipher2.nonce) + def test_default_nonce(self): + cipher1 = Salsa20.new(bchr(1) * 16) + cipher2 = Salsa20.new(bchr(1) * 16) + self.assertEqual(len(cipher1.nonce), 8) + self.assertNotEqual(cipher1.nonce, cipher2.nonce) class ByteArrayTest(unittest.TestCase): - """Verify we can encrypt or decrypt bytearrays""" + """Verify we can encrypt or decrypt bytearrays""" - def runTest(self): + def runTest(self): + data = b"0123" + key = b"9" * 32 + nonce = b"t" * 8 - data = b"0123" - key = b"9" * 32 - nonce = b"t" * 8 + # Encryption + data_ba = bytearray(data) + key_ba = bytearray(key) + nonce_ba = bytearray(nonce) - # Encryption - data_ba = bytearray(data) - key_ba = bytearray(key) - nonce_ba = bytearray(nonce) + cipher1 = Salsa20.new(key=key, nonce=nonce) + ct = cipher1.encrypt(data) - cipher1 = Salsa20.new(key=key, nonce=nonce) - ct = cipher1.encrypt(data) + cipher2 = Salsa20.new(key=key_ba, nonce=nonce_ba) + key_ba[:1] = b"\xff" + nonce_ba[:1] = b"\xff" + ct_test = cipher2.encrypt(data_ba) - cipher2 = Salsa20.new(key=key_ba, nonce=nonce_ba) - key_ba[:1] = b'\xFF' - nonce_ba[:1] = b'\xFF' - ct_test = cipher2.encrypt(data_ba) + self.assertEqual(ct, ct_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) - self.assertEqual(ct, ct_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) + # Decryption + key_ba = bytearray(key) + nonce_ba = bytearray(nonce) + ct_ba = bytearray(ct) - # Decryption - key_ba = bytearray(key) - nonce_ba = bytearray(nonce) - ct_ba = bytearray(ct) + cipher3 = Salsa20.new(key=key_ba, nonce=nonce_ba) + key_ba[:1] = b"\xff" + nonce_ba[:1] = b"\xff" + pt_test = cipher3.decrypt(ct_ba) - cipher3 = Salsa20.new(key=key_ba, nonce=nonce_ba) - key_ba[:1] = b'\xFF' - nonce_ba[:1] = b'\xFF' - pt_test = cipher3.decrypt(ct_ba) - - self.assertEqual(data, pt_test) + self.assertEqual(data, pt_test) class MemoryviewTest(unittest.TestCase): - """Verify we can encrypt or decrypt bytearrays""" - - def runTest(self): + """Verify we can encrypt or decrypt bytearrays""" - data = b"0123" - key = b"9" * 32 - nonce = b"t" * 8 + def runTest(self): + data = b"0123" + key = b"9" * 32 + nonce = b"t" * 8 - # Encryption - data_mv = memoryview(bytearray(data)) - key_mv = memoryview(bytearray(key)) - nonce_mv = memoryview(bytearray(nonce)) + # Encryption + data_mv = memoryview(bytearray(data)) + key_mv = memoryview(bytearray(key)) + nonce_mv = memoryview(bytearray(nonce)) - cipher1 = Salsa20.new(key=key, nonce=nonce) - ct = cipher1.encrypt(data) + cipher1 = Salsa20.new(key=key, nonce=nonce) + ct = cipher1.encrypt(data) - cipher2 = Salsa20.new(key=key_mv, nonce=nonce_mv) - key_mv[:1] = b'\xFF' - nonce_mv[:1] = b'\xFF' - ct_test = cipher2.encrypt(data_mv) + cipher2 = Salsa20.new(key=key_mv, nonce=nonce_mv) + key_mv[:1] = b"\xff" + nonce_mv[:1] = b"\xff" + ct_test = cipher2.encrypt(data_mv) - self.assertEqual(ct, ct_test) - self.assertEqual(cipher1.nonce, cipher2.nonce) + self.assertEqual(ct, ct_test) + self.assertEqual(cipher1.nonce, cipher2.nonce) - # Decryption - key_mv = memoryview(bytearray(key)) - nonce_mv = memoryview(bytearray(nonce)) - ct_mv = memoryview(bytearray(ct)) + # Decryption + key_mv = memoryview(bytearray(key)) + nonce_mv = memoryview(bytearray(nonce)) + ct_mv = memoryview(bytearray(ct)) - cipher3 = Salsa20.new(key=key_mv, nonce=nonce_mv) - key_mv[:1] = b'\xFF' - nonce_mv[:1] = b'\xFF' - pt_test = cipher3.decrypt(ct_mv) + cipher3 = Salsa20.new(key=key_mv, nonce=nonce_mv) + key_mv[:1] = b"\xff" + nonce_mv[:1] = b"\xff" + pt_test = cipher3.decrypt(ct_mv) - self.assertEqual(data, pt_test) + self.assertEqual(data, pt_test) class TestOutput(unittest.TestCase): + def runTest(self): + # Encrypt/Decrypt data and test output parameter - def runTest(self): - # Encrypt/Decrypt data and test output parameter + key = b"4" * 32 + nonce = b"5" * 8 + cipher = Salsa20.new(key=key, nonce=nonce) - key = b'4' * 32 - nonce = b'5' * 8 - cipher = Salsa20.new(key=key, nonce=nonce) + pt = b"5" * 300 + ct = cipher.encrypt(pt) - pt = b'5' * 300 - ct = cipher.encrypt(pt) + output = bytearray(len(pt)) + cipher = Salsa20.new(key=key, nonce=nonce) + res = cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) + self.assertEqual(res, None) - output = bytearray(len(pt)) - cipher = Salsa20.new(key=key, nonce=nonce) - res = cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) - self.assertEqual(res, None) + cipher = Salsa20.new(key=key, nonce=nonce) + res = cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) + self.assertEqual(res, None) - cipher = Salsa20.new(key=key, nonce=nonce) - res = cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) - self.assertEqual(res, None) + output = memoryview(bytearray(len(pt))) + cipher = Salsa20.new(key=key, nonce=nonce) + cipher.encrypt(pt, output=output) + self.assertEqual(ct, output) - output = memoryview(bytearray(len(pt))) - cipher = Salsa20.new(key=key, nonce=nonce) - cipher.encrypt(pt, output=output) - self.assertEqual(ct, output) + cipher = Salsa20.new(key=key, nonce=nonce) + cipher.decrypt(ct, output=output) + self.assertEqual(pt, output) - cipher = Salsa20.new(key=key, nonce=nonce) - cipher.decrypt(ct, output=output) - self.assertEqual(pt, output) + cipher = Salsa20.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.encrypt, pt, output=b"0" * len(pt)) - cipher = Salsa20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*len(pt)) + cipher = Salsa20.new(key=key, nonce=nonce) + self.assertRaises(TypeError, cipher.decrypt, ct, output=b"0" * len(ct)) - cipher = Salsa20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*len(ct)) + shorter_output = bytearray(len(pt) - 1) - shorter_output = bytearray(len(pt) - 1) + cipher = Salsa20.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - cipher = Salsa20.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - - cipher = Salsa20.new(key=key, nonce=nonce) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) + cipher = Salsa20.new(key=key, nonce=nonce) + self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) def get_tests(config={}): - tests = make_stream_tests(Salsa20, "Salsa20", test_data) - tests.append(KeyLength()) - tests += list_test_cases(NonceTests) - tests.append(ByteArrayTest()) - tests.append(MemoryviewTest()) - tests.append(TestOutput()) + tests = make_stream_tests(Salsa20, "Salsa20", test_data) + tests.append(KeyLength()) + tests += list_test_cases(NonceTests) + tests.append(ByteArrayTest()) + tests.append(MemoryviewTest()) + tests.append(TestOutput()) + + return tests - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_pkcs1_15.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_pkcs1_15.py index 12c09dd6..e72d7baf 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_pkcs1_15.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_pkcs1_15.py @@ -34,41 +34,39 @@ def rws(t): - """Remove white spaces, tabs, and new lines from a string""" - for c in ['\n', '\t', ' ']: - t = t.replace(c, '') - return t + """Remove white spaces, tabs, and new lines from a string""" + for c in ["\n", "\t", " "]: + t = t.replace(c, "") + return t def t2b(t): - """Convert a text string with bytes in hex form to a byte string""" - clean = b(rws(t)) - if len(clean) % 2 == 1: - raise ValueError("Even number of characters expected") - return a2b_hex(clean) + """Convert a text string with bytes in hex form to a byte string""" + clean = b(rws(t)) + if len(clean) % 2 == 1: + raise ValueError("Even number of characters expected") + return a2b_hex(clean) class PKCS1_15_Tests(unittest.TestCase): - - def setUp(self): - self.rng = Random.new().read - self.key1024 = RSA.generate(1024, self.rng) - - # List of tuples with test data for PKCS#1 v1.5. - # Each tuple is made up by: - # Item #0: dictionary with RSA key component, or key to import - # Item #1: plaintext - # Item #2: ciphertext - # Item #3: random data - - _testData = ( - - # - # Generated with openssl 0.9.8o - # - ( - # Private key - '''-----BEGIN RSA PRIVATE KEY----- + def setUp(self): + self.rng = Random.new().read + self.key1024 = RSA.generate(1024, self.rng) + + # List of tuples with test data for PKCS#1 v1.5. + # Each tuple is made up by: + # Item #0: dictionary with RSA key component, or key to import + # Item #1: plaintext + # Item #2: ciphertext + # Item #3: random data + + _testData = ( + # + # Generated with openssl 0.9.8o + # + ( + # Private key + """-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDAiAnvIAOvqVwJTaYzsKnefZftgtXGE2hPJppGsWl78yz9jeXY W/FxX/gTPURArNhdnhP6n3p2ZaDIBrO2zizbgIXs0IsljTTcr4vnI8fMXzyNUOjA zP3nzMqZDZK6757XQAobOssMkBFqRWwilT/3DsBhRpl3iMUhF+wvpTSHewIDAQAB @@ -82,202 +80,205 @@ def setUp(self): 1JYNMtRen5unSAbIOxRcKkWz92F0LKpm9ZW/S9vFHO+mBcClMGoKJHiuQxLBsLbT NtEZfSJZAeS2sUtn3/0CQDb2M2zNBTF8LlM0nxmh0k9VGm5TVIyBEMcipmvOgqIs HKukWBcq9f/UOmS0oEhai/6g+Uf7VHJdWaeO5LzuvwU= ------END RSA PRIVATE KEY-----''', - # Plaintext - '''THIS IS PLAINTEXT\x0A''', - # Ciphertext - '''3f dc fd 3c cd 5c 9b 12 af 65 32 e3 f7 d0 da 36 +-----END RSA PRIVATE KEY-----""", + # Plaintext + """THIS IS PLAINTEXT\x0a""", + # Ciphertext + """3f dc fd 3c cd 5c 9b 12 af 65 32 e3 f7 d0 da 36 8f 8f d9 e3 13 1c 7f c8 b3 f9 c1 08 e4 eb 79 9c 91 89 1f 96 3b 94 77 61 99 a4 b1 ee 5d e6 17 c9 5d 0a b5 63 52 0a eb 00 45 38 2a fb b0 71 3d 11 f7 a1 9e a7 69 b3 af 61 c0 bb 04 5b 5d 4b 27 44 1f 5b 97 89 ba 6a 08 95 ee 4f a2 eb 56 64 e5 0f da 7c f9 9a 61 61 06 62 ed a0 bc 5f aa 6c 31 78 - 70 28 1a bb 98 3c e3 6a 60 3c d1 0b 0f 5a f4 75''', - # Random data - '''eb d7 7d 86 a4 35 23 a3 54 7e 02 0b 42 1d + 70 28 1a bb 98 3c e3 6a 60 3c d1 0b 0f 5a f4 75""", + # Random data + """eb d7 7d 86 a4 35 23 a3 54 7e 02 0b 42 1d 61 6c af 67 b8 4e 17 56 80 66 36 04 64 34 26 8a 47 dd 44 b3 1a b2 17 60 f4 91 2e e2 b5 95 64 cc f9 da c8 70 94 54 86 4c ef 5b 08 7d 18 c4 ab 8d 04 06 33 8f ca 15 5f 52 60 8a a1 0c f5 08 b5 4c bb 99 b8 94 25 04 9c e6 01 75 e6 f9 63 7a 65 61 - 13 8a a7 47 77 81 ae 0d b8 2c 4d 50 a5''' - ), - ) - - def testEncrypt1(self): - for test in self._testData: - # Build the key - key = RSA.importKey(test[0]) - # RNG that takes its random numbers from a pool given - # at initialization - class randGen: - def __init__(self, data): - self.data = data - self.idx = 0 - def __call__(self, N): - r = self.data[self.idx:self.idx+N] - self.idx += N - return r - # The real test - cipher = PKCS.new(key, randfunc=randGen(t2b(test[3]))) - ct = cipher.encrypt(b(test[1])) - self.assertEqual(ct, t2b(test[2])) - - def testEncrypt2(self): - # Verify that encryption fail if plaintext is too long - pt = '\x00'*(128-11+1) - cipher = PKCS.new(self.key1024) - self.assertRaises(ValueError, cipher.encrypt, pt) - - def testVerify1(self): - for test in self._testData: - key = RSA.importKey(test[0]) - expected_pt = b(test[1]) - ct = t2b(test[2]) - cipher = PKCS.new(key) - - # The real test - pt = cipher.decrypt(ct, None) - self.assertEqual(pt, expected_pt) - - pt = cipher.decrypt(ct, b'\xFF' * len(expected_pt)) - self.assertEqual(pt, expected_pt) - - def testVerify2(self): - # Verify that decryption fails if ciphertext is not as long as - # RSA modulus - cipher = PKCS.new(self.key1024) - self.assertRaises(ValueError, cipher.decrypt, '\x00'*127, "---") - self.assertRaises(ValueError, cipher.decrypt, '\x00'*129, "---") - - # Verify that decryption fails if there are less then 8 non-zero padding - # bytes - pt = b('\x00\x02' + '\xFF'*7 + '\x00' + '\x45'*118) - pt_int = bytes_to_long(pt) - ct_int = self.key1024._encrypt(pt_int) - ct = long_to_bytes(ct_int, 128) - self.assertEqual(b"---", cipher.decrypt(ct, b"---")) - - def testEncryptVerify1(self): - # Encrypt/Verify messages of length [0..RSAlen-11] - # and therefore padding [8..117] - for pt_len in range(0, 128 - 11 + 1): - pt = self.rng(pt_len) - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(pt) - pt2 = cipher.decrypt(ct, b'\xAA' * pt_len) - self.assertEqual(pt, pt2) - - def test_encrypt_verify_exp_pt_len(self): - - cipher = PKCS.new(self.key1024) - pt = b'5' * 16 - ct = cipher.encrypt(pt) - sentinel = b'\xAA' * 16 - - pt_A = cipher.decrypt(ct, sentinel, 16) - self.assertEqual(pt, pt_A) - - pt_B = cipher.decrypt(ct, sentinel, 15) - self.assertEqual(sentinel, pt_B) - - pt_C = cipher.decrypt(ct, sentinel, 17) - self.assertEqual(sentinel, pt_C) - - def testByteArray(self): - pt = b"XER" - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(bytearray(pt)) - pt2 = cipher.decrypt(bytearray(ct), '\xFF' * len(pt)) - self.assertEqual(pt, pt2) - - def testMemoryview(self): - pt = b"XER" - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(memoryview(bytearray(pt))) - pt2 = cipher.decrypt(memoryview(bytearray(ct)), b'\xFF' * len(pt)) - self.assertEqual(pt, pt2) - - def test_return_type(self): - pt = b"XYZ" - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(pt) - self.assertTrue(isinstance(ct, bytes)) - pt2 = cipher.decrypt(ct, b'\xAA' * 3) - self.assertTrue(isinstance(pt2, bytes)) + 13 8a a7 47 77 81 ae 0d b8 2c 4d 50 a5""", + ), + ) + + def testEncrypt1(self): + for test in self._testData: + # Build the key + key = RSA.importKey(test[0]) + + # RNG that takes its random numbers from a pool given + # at initialization + class randGen: + def __init__(self, data): + self.data = data + self.idx = 0 + + def __call__(self, N): + r = self.data[self.idx : self.idx + N] + self.idx += N + return r + + # The real test + cipher = PKCS.new(key, randfunc=randGen(t2b(test[3]))) + ct = cipher.encrypt(b(test[1])) + self.assertEqual(ct, t2b(test[2])) + + def testEncrypt2(self): + # Verify that encryption fail if plaintext is too long + pt = "\x00" * (128 - 11 + 1) + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.encrypt, pt) + + def testVerify1(self): + for test in self._testData: + key = RSA.importKey(test[0]) + expected_pt = b(test[1]) + ct = t2b(test[2]) + cipher = PKCS.new(key) + + # The real test + pt = cipher.decrypt(ct, None) + self.assertEqual(pt, expected_pt) + + pt = cipher.decrypt(ct, b"\xff" * len(expected_pt)) + self.assertEqual(pt, expected_pt) + + def testVerify2(self): + # Verify that decryption fails if ciphertext is not as long as + # RSA modulus + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.decrypt, "\x00" * 127, "---") + self.assertRaises(ValueError, cipher.decrypt, "\x00" * 129, "---") + + # Verify that decryption fails if there are less then 8 non-zero padding + # bytes + pt = b("\x00\x02" + "\xff" * 7 + "\x00" + "\x45" * 118) + pt_int = bytes_to_long(pt) + ct_int = self.key1024._encrypt(pt_int) + ct = long_to_bytes(ct_int, 128) + self.assertEqual(b"---", cipher.decrypt(ct, b"---")) + + def testEncryptVerify1(self): + # Encrypt/Verify messages of length [0..RSAlen-11] + # and therefore padding [8..117] + for pt_len in range(0, 128 - 11 + 1): + pt = self.rng(pt_len) + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(pt) + pt2 = cipher.decrypt(ct, b"\xaa" * pt_len) + self.assertEqual(pt, pt2) + + def test_encrypt_verify_exp_pt_len(self): + cipher = PKCS.new(self.key1024) + pt = b"5" * 16 + ct = cipher.encrypt(pt) + sentinel = b"\xaa" * 16 + + pt_A = cipher.decrypt(ct, sentinel, 16) + self.assertEqual(pt, pt_A) + + pt_B = cipher.decrypt(ct, sentinel, 15) + self.assertEqual(sentinel, pt_B) + + pt_C = cipher.decrypt(ct, sentinel, 17) + self.assertEqual(sentinel, pt_C) + + def testByteArray(self): + pt = b"XER" + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(bytearray(pt)) + pt2 = cipher.decrypt(bytearray(ct), "\xff" * len(pt)) + self.assertEqual(pt, pt2) + + def testMemoryview(self): + pt = b"XER" + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(memoryview(bytearray(pt))) + pt2 = cipher.decrypt(memoryview(bytearray(ct)), b"\xff" * len(pt)) + self.assertEqual(pt, pt2) + + def test_return_type(self): + pt = b"XYZ" + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(pt) + self.assertTrue(isinstance(ct, bytes)) + pt2 = cipher.decrypt(ct, b"\xaa" * 3) + self.assertTrue(isinstance(pt2, bytes)) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, skip_slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._skip_slow_tests = skip_slow_tests - self._id = "None" - - def load_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['privateKeyPem']) - - result = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - filename, - "Wycheproof PKCS#1v1.5 (%s)" % filename, - group_tag={'rsa_key': filter_rsa} - ) - return result - - def setUp(self): - self.tv = [] - self.tv.extend(self.load_tests("rsa_pkcs1_2048_test.json")) - if not self._skip_slow_tests: - self.tv.extend(self.load_tests("rsa_pkcs1_3072_test.json")) - self.tv.extend(self.load_tests("rsa_pkcs1_4096_test.json")) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt PKCS#1v1.5 Test #%s" % tv.id - sentinel = b'\xAA' * max(3, len(tv.msg)) - cipher = PKCS.new(tv.rsa_key) - try: - pt = cipher.decrypt(tv.ct, sentinel=sentinel) - except ValueError: - assert not tv.valid - else: - if pt == sentinel: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def runTest(self): - - for tv in self.tv: - self.test_decrypt(tv) + def __init__(self, wycheproof_warnings, skip_slow_tests): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._skip_slow_tests = skip_slow_tests + self._id = "None" + + def load_tests(self, filename): + def filter_rsa(group): + return RSA.import_key(group["privateKeyPem"]) + + result = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + filename, + "Wycheproof PKCS#1v1.5 (%s)" % filename, + group_tag={"rsa_key": filter_rsa}, + ) + return result + + def setUp(self): + self.tv = [] + self.tv.extend(self.load_tests("rsa_pkcs1_2048_test.json")) + if not self._skip_slow_tests: + self.tv.extend(self.load_tests("rsa_pkcs1_3072_test.json")) + self.tv.extend(self.load_tests("rsa_pkcs1_4096_test.json")) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt PKCS#1v1.5 Test #%s" % tv.id + sentinel = b"\xaa" * max(3, len(tv.msg)) + cipher = PKCS.new(tv.rsa_key) + try: + pt = cipher.decrypt(tv.ct, sentinel=sentinel) + except ValueError: + assert not tv.valid + else: + if pt == sentinel: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_decrypt(tv) def get_tests(config={}): - skip_slow_tests = not config.get('slow_tests') - wycheproof_warnings = config.get('wycheproof_warnings') + skip_slow_tests = not config.get("slow_tests") + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(PKCS1_15_Tests) + tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)] + return tests + - tests = [] - tests += list_test_cases(PKCS1_15_Tests) - tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)] - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_pkcs1_oaep.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_pkcs1_oaep.py index aa00c9cf..7052fe3f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_pkcs1_oaep.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Cipher/test_pkcs1_oaep.py @@ -35,133 +35,127 @@ def rws(t): - """Remove white spaces, tabs, and new lines from a string""" - for c in ['\n', '\t', ' ']: - t = t.replace(c, '') - return t + """Remove white spaces, tabs, and new lines from a string""" + for c in ["\n", "\t", " "]: + t = t.replace(c, "") + return t def t2b(t): - """Convert a text string with bytes in hex form to a byte string""" - clean = rws(t) - if len(clean) % 2 == 1: - raise ValueError("Even number of characters expected") - return a2b_hex(clean) + """Convert a text string with bytes in hex form to a byte string""" + clean = rws(t) + if len(clean) % 2 == 1: + raise ValueError("Even number of characters expected") + return a2b_hex(clean) class PKCS1_OAEP_Tests(unittest.TestCase): - - def setUp(self): - self.rng = Random.new().read - self.key1024 = RSA.generate(1024, self.rng) - - # List of tuples with test data for PKCS#1 OAEP - # Each tuple is made up by: - # Item #0: dictionary with RSA key component - # Item #1: plaintext - # Item #2: ciphertext - # Item #3: random data (=seed) - # Item #4: hash object - - _testData = ( - - # - # From in oaep-int.txt to be found in - # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - # - ( - # Private key - { - 'n':'''bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 + def setUp(self): + self.rng = Random.new().read + self.key1024 = RSA.generate(1024, self.rng) + + # List of tuples with test data for PKCS#1 OAEP + # Each tuple is made up by: + # Item #0: dictionary with RSA key component + # Item #1: plaintext + # Item #2: ciphertext + # Item #3: random data (=seed) + # Item #4: hash object + + _testData = ( + # + # From in oaep-int.txt to be found in + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + "n": """bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48 76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84 ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f - e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb''', - # Public key - 'e':'11', - # In the test vector, only p and q were given... - # d is computed offline as e^{-1} mod (p-1)(q-1) - 'd':'''a5dafc5341faf289c4b988db30c1cdf83f31251e0 + e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb""", + # Public key + "e": "11", + # In the test vector, only p and q were given... + # d is computed offline as e^{-1} mod (p-1)(q-1) + "d": """a5dafc5341faf289c4b988db30c1cdf83f31251e0 668b42784813801579641b29410b3c7998d6bc465745e5c3 92669d6870da2c082a939e37fdcb82ec93edac97ff3ad595 0accfbc111c76f1a9529444e56aaf68c56c092cd38dc3bef 5d20a939926ed4f74a13eddfbe1a1cecc4894af9428c2b7b - 8883fe4463a4bc85b1cb3c1''' - } - , - # Plaintext - '''d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49''', - # Ciphertext - '''12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 + 8883fe4463a4bc85b1cb3c1""", + }, + # Plaintext + """d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49""", + # Ciphertext + """12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7 63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6 53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb 6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0 24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48 da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d - 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55''', - # Random - '''aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2 - f0 6c b5 8f''', - # Hash - SHA1, - ), - - # - # From in oaep-vect.txt to be found in Example 1.1 - # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - # - ( - # Private key - { - 'n':'''a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 + 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55""", + # Random + """aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2 + f0 6c b5 8f""", + # Hash + SHA1, + ), + # + # From in oaep-vect.txt to be found in Example 1.1 + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + "n": """a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85 12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72 f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97 c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14 8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24 - 76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb''', - 'e':'''01 00 01''', - 'd':'''53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c + 76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb""", + "e": """01 00 01""", + "d": """53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c 55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd 8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b 15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55 fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73 2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de - f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 ''' - } - , - # Plaintext - '''66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 - 97 d5 0d ba 79 b9 87 00 4a fe fe 34''', - # Ciphertext - '''35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f + f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 """, + }, + # Plaintext + """66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 + 97 d5 0d ba 79 b9 87 00 4a fe fe 34""", + # Ciphertext + """35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f 7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb 21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01 03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22 d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26 d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c - 40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a''', - # Random - '''18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1 - dd a0 a5 ef''', - SHA1 - ), - - # - # From in oaep-vect.txt to be found in Example 2.1 - # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - # - ( - # Private key - { - 'n':'''01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5 + 40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a""", + # Random + """18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1 + dd a0 a5 ef""", + SHA1, + ), + # + # From in oaep-vect.txt to be found in Example 2.1 + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + "n": """01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5 e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e 49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba 7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d @@ -169,22 +163,22 @@ def setUp(self): de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05 5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66 32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f - 45''', - 'e':'''01 00 01''', - 'd':'''08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa + 45""", + "e": """01 00 01""", + "d": """08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa 4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93 c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47 39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0 8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59 41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25 - 25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39''' - }, - # Plaintext - '''8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6 - 52 b5 8c f1 d9 2f ec 57 0b ee e7''', - # Ciphertext - '''01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99 + 25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39""", + }, + # Plaintext + """8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6 + 52 b5 8c f1 d9 2f ec 57 0b ee e7""", + # Ciphertext + """01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99 2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a 5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34 @@ -192,21 +186,20 @@ def setUp(self): 56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72 - 0e''', - # Random - '''8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94 - e7 1b 17 82''', - SHA1 - ), - - # - # From in oaep-vect.txt to be found in Example 10.1 - # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - # - ( - # Private key - { - 'n':'''ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d + 0e""", + # Random + """8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94 + e7 1b 17 82""", + SHA1, + ), + # + # From in oaep-vect.txt to be found in Example 10.1 + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + "n": """ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8 df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4 02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5 @@ -221,9 +214,9 @@ def setUp(self): a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76 57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88 d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc - 36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb''', - 'e':'''01 00 01''', - 'd':'''05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85 + 36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb""", + "e": """01 00 01""", + "d": """05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85 25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59 6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0 d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d @@ -238,13 +231,13 @@ def setUp(self): 0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87 6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01 84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e - 97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79''' - }, - # Plaintext - '''8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70 - b0 89 53 b0 6b 4e b2 05 bc 16 94 ee''', - # Ciphertext - '''53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15 + 97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79""", + }, + # Plaintext + """8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70 + b0 89 53 b0 6b 4e b2 05 bc 16 94 ee""", + # Ciphertext + """53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15 52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19 ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14 @@ -259,248 +252,250 @@ def setUp(self): ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55 ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64 73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54 - bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc''', - # Random - '''47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0 - aa 63 bd 33''', - SHA1 - ), - ) - - def testEncrypt1(self): - # Verify encryption using all test vectors - for test in self._testData: - # Build the key - comps = [int(rws(test[0][x]), 16) for x in ('n', 'e')] - key = RSA.construct(comps) - - # RNG that takes its random numbers from a pool given - # at initialization - class randGen: - - def __init__(self, data): - self.data = data - self.idx = 0 - - def __call__(self, N): - r = self.data[self.idx:N] - self.idx += N - return r - - # The real test - cipher = PKCS.new(key, test[4], randfunc=randGen(t2b(test[3]))) - ct = cipher.encrypt(t2b(test[1])) - self.assertEqual(ct, t2b(test[2])) - - def testEncrypt2(self): - # Verify that encryption fails if plaintext is too long - pt = '\x00'*(128-2*20-2+1) - cipher = PKCS.new(self.key1024) - self.assertRaises(ValueError, cipher.encrypt, pt) - - def testDecrypt1(self): - # Verify decryption using all test vectors - for test in self._testData: - # Build the key - comps = [int(rws(test[0][x]),16) for x in ('n', 'e', 'd')] - key = RSA.construct(comps) - # The real test - cipher = PKCS.new(key, test[4]) - pt = cipher.decrypt(t2b(test[2])) - self.assertEqual(pt, t2b(test[1])) - - def testDecrypt2(self): - # Simplest possible negative tests - for ct_size in (127, 128, 129): - cipher = PKCS.new(self.key1024) - self.assertRaises(ValueError, cipher.decrypt, bchr(0x00)*ct_size) - - def testEncryptDecrypt1(self): - # Encrypt/Decrypt messages of length [0..128-2*20-2] - for pt_len in range(0, 128-2*20-2): - pt = self.rng(pt_len) - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(pt) - pt2 = cipher.decrypt(ct) - self.assertEqual(pt, pt2) - - def testEncryptDecrypt2(self): - # Helper function to monitor what's requested from RNG - global asked - - def localRng(N): - global asked - asked += N - return self.rng(N) - - # Verify that OAEP is friendly to all hashes - for hashmod in (MD2, MD5, SHA1, SHA256, RIPEMD160): - # Verify that encrypt() asks for as many random bytes - # as the hash output size - asked = 0 - pt = self.rng(40) - cipher = PKCS.new(self.key1024, hashmod, randfunc=localRng) - ct = cipher.encrypt(pt) - self.assertEqual(cipher.decrypt(ct), pt) - self.assertEqual(asked, hashmod.digest_size) - - def testEncryptDecrypt3(self): - # Verify that OAEP supports labels - pt = self.rng(35) - xlabel = self.rng(22) - cipher = PKCS.new(self.key1024, label=xlabel) - ct = cipher.encrypt(pt) - self.assertEqual(cipher.decrypt(ct), pt) - - def testEncryptDecrypt4(self): - # Verify that encrypt() uses the custom MGF - global mgfcalls - # Helper function to monitor what's requested from MGF - - def newMGF(seed, maskLen): - global mgfcalls - mgfcalls += 1 - return b'\x00' * maskLen - - mgfcalls = 0 - pt = self.rng(32) - cipher = PKCS.new(self.key1024, mgfunc=newMGF) - ct = cipher.encrypt(pt) - self.assertEqual(mgfcalls, 2) - self.assertEqual(cipher.decrypt(ct), pt) - - def testByteArray(self): - pt = b("XER") - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(bytearray(pt)) - pt2 = cipher.decrypt(bytearray(ct)) - self.assertEqual(pt, pt2) - - def testMemoryview(self): - pt = b("XER") - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(memoryview(bytearray(pt))) - pt2 = cipher.decrypt(memoryview(bytearray(ct))) - self.assertEqual(pt, pt2) + bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc""", + # Random + """47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0 + aa 63 bd 33""", + SHA1, + ), + ) + + def testEncrypt1(self): + # Verify encryption using all test vectors + for test in self._testData: + # Build the key + comps = [int(rws(test[0][x]), 16) for x in ("n", "e")] + key = RSA.construct(comps) + + # RNG that takes its random numbers from a pool given + # at initialization + class randGen: + def __init__(self, data): + self.data = data + self.idx = 0 + + def __call__(self, N): + r = self.data[self.idx : N] + self.idx += N + return r + + # The real test + cipher = PKCS.new(key, test[4], randfunc=randGen(t2b(test[3]))) + ct = cipher.encrypt(t2b(test[1])) + self.assertEqual(ct, t2b(test[2])) + + def testEncrypt2(self): + # Verify that encryption fails if plaintext is too long + pt = "\x00" * (128 - 2 * 20 - 2 + 1) + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.encrypt, pt) + + def testDecrypt1(self): + # Verify decryption using all test vectors + for test in self._testData: + # Build the key + comps = [int(rws(test[0][x]), 16) for x in ("n", "e", "d")] + key = RSA.construct(comps) + # The real test + cipher = PKCS.new(key, test[4]) + pt = cipher.decrypt(t2b(test[2])) + self.assertEqual(pt, t2b(test[1])) + + def testDecrypt2(self): + # Simplest possible negative tests + for ct_size in (127, 128, 129): + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.decrypt, bchr(0x00) * ct_size) + + def testEncryptDecrypt1(self): + # Encrypt/Decrypt messages of length [0..128-2*20-2] + for pt_len in range(0, 128 - 2 * 20 - 2): + pt = self.rng(pt_len) + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(pt) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt, pt2) + + def testEncryptDecrypt2(self): + # Helper function to monitor what's requested from RNG + global asked + + def localRng(N): + global asked + asked += N + return self.rng(N) + + # Verify that OAEP is friendly to all hashes + for hashmod in (MD2, MD5, SHA1, SHA256, RIPEMD160): + # Verify that encrypt() asks for as many random bytes + # as the hash output size + asked = 0 + pt = self.rng(40) + cipher = PKCS.new(self.key1024, hashmod, randfunc=localRng) + ct = cipher.encrypt(pt) + self.assertEqual(cipher.decrypt(ct), pt) + self.assertEqual(asked, hashmod.digest_size) + + def testEncryptDecrypt3(self): + # Verify that OAEP supports labels + pt = self.rng(35) + xlabel = self.rng(22) + cipher = PKCS.new(self.key1024, label=xlabel) + ct = cipher.encrypt(pt) + self.assertEqual(cipher.decrypt(ct), pt) + + def testEncryptDecrypt4(self): + # Verify that encrypt() uses the custom MGF + global mgfcalls + # Helper function to monitor what's requested from MGF + + def newMGF(seed, maskLen): + global mgfcalls + mgfcalls += 1 + return b"\x00" * maskLen + + mgfcalls = 0 + pt = self.rng(32) + cipher = PKCS.new(self.key1024, mgfunc=newMGF) + ct = cipher.encrypt(pt) + self.assertEqual(mgfcalls, 2) + self.assertEqual(cipher.decrypt(ct), pt) + + def testByteArray(self): + pt = b("XER") + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(bytearray(pt)) + pt2 = cipher.decrypt(bytearray(ct)) + self.assertEqual(pt, pt2) + + def testMemoryview(self): + pt = b("XER") + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(memoryview(bytearray(pt))) + pt2 = cipher.decrypt(memoryview(bytearray(ct))) + self.assertEqual(pt, pt2) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, skip_slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._skip_slow_tests = skip_slow_tests - self._id = "None" - - def load_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['privateKeyPem']) - - def filter_sha(group): - if group['sha'] == "SHA-1": - return SHA1 - elif group['sha'] == "SHA-224": - return SHA224 - elif group['sha'] == "SHA-256": - return SHA256 - elif group['sha'] == "SHA-384": - return SHA384 - elif group['sha'] == "SHA-512": - return SHA512 - else: - raise ValueError("Unknown sha " + group['sha']) - - def filter_mgf(group): - if group['mgfSha'] == "SHA-1": - return lambda x, y: MGF1(x, y, SHA1) - elif group['mgfSha'] == "SHA-224": - return lambda x, y: MGF1(x, y, SHA224) - elif group['mgfSha'] == "SHA-256": - return lambda x, y: MGF1(x, y, SHA256) - elif group['mgfSha'] == "SHA-384": - return lambda x, y: MGF1(x, y, SHA384) - elif group['mgfSha'] == "SHA-512": - return lambda x, y: MGF1(x, y, SHA512) - else: - raise ValueError("Unknown mgf/sha " + group['mgfSha']) - - def filter_algo(group): - return "%s with MGF1/%s" % (group['sha'], group['mgfSha']) - - result = load_test_vectors_wycheproof(("Cipher", "wycheproof"), - filename, - "Wycheproof PKCS#1 OAEP (%s)" % filename, - group_tag={'rsa_key': filter_rsa, - 'hash_mod': filter_sha, - 'mgf': filter_mgf, - 'algo': filter_algo} - ) - return result - - def setUp(self): - self.tv = [] - self.tv.extend(self.load_tests("rsa_oaep_2048_sha1_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha224_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha256_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha384_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha512_test.json")) - if not self._skip_slow_tests: - self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha256_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha512_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha256_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha1_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json")) - self.tv.extend(self.load_tests("rsa_oaep_misc_test.json")) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_decrypt(self, tv): - self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id) - - cipher = PKCS.new(tv.rsa_key, hashAlgo=tv.hash_mod, mgfunc=tv.mgf, label=tv.label) - try: - pt = cipher.decrypt(tv.ct) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.assertEqual(pt, tv.msg) - self.warn(tv) - - def runTest(self): - - for tv in self.tv: - self.test_decrypt(tv) + def __init__(self, wycheproof_warnings, skip_slow_tests): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._skip_slow_tests = skip_slow_tests + self._id = "None" + + def load_tests(self, filename): + def filter_rsa(group): + return RSA.import_key(group["privateKeyPem"]) + + def filter_sha(group): + if group["sha"] == "SHA-1": + return SHA1 + elif group["sha"] == "SHA-224": + return SHA224 + elif group["sha"] == "SHA-256": + return SHA256 + elif group["sha"] == "SHA-384": + return SHA384 + elif group["sha"] == "SHA-512": + return SHA512 + else: + raise ValueError("Unknown sha " + group["sha"]) + + def filter_mgf(group): + if group["mgfSha"] == "SHA-1": + return lambda x, y: MGF1(x, y, SHA1) + elif group["mgfSha"] == "SHA-224": + return lambda x, y: MGF1(x, y, SHA224) + elif group["mgfSha"] == "SHA-256": + return lambda x, y: MGF1(x, y, SHA256) + elif group["mgfSha"] == "SHA-384": + return lambda x, y: MGF1(x, y, SHA384) + elif group["mgfSha"] == "SHA-512": + return lambda x, y: MGF1(x, y, SHA512) + else: + raise ValueError("Unknown mgf/sha " + group["mgfSha"]) + + def filter_algo(group): + return "%s with MGF1/%s" % (group["sha"], group["mgfSha"]) + + result = load_test_vectors_wycheproof( + ("Cipher", "wycheproof"), + filename, + "Wycheproof PKCS#1 OAEP (%s)" % filename, + group_tag={ + "rsa_key": filter_rsa, + "hash_mod": filter_sha, + "mgf": filter_mgf, + "algo": filter_algo, + }, + ) + return result + + def setUp(self): + self.tv = [] + self.tv.extend(self.load_tests("rsa_oaep_2048_sha1_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha224_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha256_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha384_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha512_test.json")) + if not self._skip_slow_tests: + self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha256_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha512_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha256_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha1_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json")) + self.tv.extend(self.load_tests("rsa_oaep_misc_test.json")) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_decrypt(self, tv): + self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id) + + cipher = PKCS.new(tv.rsa_key, hashAlgo=tv.hash_mod, mgfunc=tv.mgf, label=tv.label) + try: + pt = cipher.decrypt(tv.ct) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.assertEqual(pt, tv.msg) + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_decrypt(tv) def get_tests(config={}): - skip_slow_tests = not config.get('slow_tests') - wycheproof_warnings = config.get('wycheproof_warnings') + skip_slow_tests = not config.get("slow_tests") + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(PKCS1_OAEP_Tests) + tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)] + return tests + - tests = [] - tests += list_test_cases(PKCS1_OAEP_Tests) - tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)] - return tests +if __name__ == "__main__": + def suite(): + unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/__init__.py index 5f5b9992..a6e40944 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/__init__.py @@ -26,37 +26,88 @@ __revision__ = "$Id$" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Hash import test_HMAC; tests += test_HMAC.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_CMAC; tests += test_CMAC.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_MD2; tests += test_MD2.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_MD4; tests += test_MD4.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_MD5; tests += test_MD5.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_RIPEMD160; tests += test_RIPEMD160.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA1; tests += test_SHA1.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA224; tests += test_SHA224.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA256; tests += test_SHA256.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA384; tests += test_SHA384.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA512; tests += test_SHA512.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA3_224; tests += test_SHA3_224.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA3_256; tests += test_SHA3_256.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA3_384; tests += test_SHA3_384.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHA3_512; tests += test_SHA3_512.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_keccak; tests += test_keccak.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_SHAKE; tests += test_SHAKE.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_BLAKE2; tests += test_BLAKE2.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_Poly1305; tests += test_Poly1305.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_cSHAKE; tests += test_cSHAKE.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_KMAC; tests += test_KMAC.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_TupleHash; tests += test_TupleHash.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_KangarooTwelve; tests += test_KangarooTwelve.get_tests(config=config) - from Cryptodome.SelfTest.Hash import test_TurboSHAKE; tests += test_TurboSHAKE.get_tests(config=config) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + from Cryptodome.SelfTest.Hash import test_HMAC + + tests += test_HMAC.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_CMAC + + tests += test_CMAC.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_MD2 + + tests += test_MD2.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_MD4 + + tests += test_MD4.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_MD5 + + tests += test_MD5.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_RIPEMD160 + + tests += test_RIPEMD160.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA1 + + tests += test_SHA1.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA224 + + tests += test_SHA224.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA256 + + tests += test_SHA256.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA384 + + tests += test_SHA384.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA512 + + tests += test_SHA512.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA3_224 + + tests += test_SHA3_224.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA3_256 + + tests += test_SHA3_256.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA3_384 + + tests += test_SHA3_384.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHA3_512 + + tests += test_SHA3_512.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_keccak + + tests += test_keccak.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_SHAKE + + tests += test_SHAKE.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_BLAKE2 + + tests += test_BLAKE2.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_Poly1305 + + tests += test_Poly1305.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_cSHAKE + + tests += test_cSHAKE.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_KMAC + + tests += test_KMAC.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_TupleHash + + tests += test_TupleHash.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_KangarooTwelve + + tests += test_KangarooTwelve.get_tests(config=config) + from Cryptodome.SelfTest.Hash import test_TurboSHAKE + + tests += test_TurboSHAKE.get_tests(config=config) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/common.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/common.py index 4ed92346..602c0a27 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/common.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/common.py @@ -28,263 +28,262 @@ import sys import unittest import binascii -import Cryptodome.Hash from binascii import hexlify, unhexlify from Cryptodome.Util.py3compat import b, tobytes from Cryptodome.Util.strxor import strxor_c + def t2b(hex_string): - shorter = re.sub(br'\s+', b'', tobytes(hex_string)) - return unhexlify(shorter) + shorter = re.sub(rb"\s+", b"", tobytes(hex_string)) + return unhexlify(shorter) class HashDigestSizeSelfTest(unittest.TestCase): + def __init__(self, hashmod, description, expected, extra_params): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + self.expected = expected + self.description = description + self.extra_params = extra_params - def __init__(self, hashmod, description, expected, extra_params): - unittest.TestCase.__init__(self) - self.hashmod = hashmod - self.expected = expected - self.description = description - self.extra_params = extra_params - - def shortDescription(self): - return self.description + def shortDescription(self): + return self.description - def runTest(self): - if "truncate" not in self.extra_params: - self.assertTrue(hasattr(self.hashmod, "digest_size")) - self.assertEqual(self.hashmod.digest_size, self.expected) - h = self.hashmod.new(**self.extra_params) - self.assertTrue(hasattr(h, "digest_size")) - self.assertEqual(h.digest_size, self.expected) + def runTest(self): + if "truncate" not in self.extra_params: + self.assertTrue(hasattr(self.hashmod, "digest_size")) + self.assertEqual(self.hashmod.digest_size, self.expected) + h = self.hashmod.new(**self.extra_params) + self.assertTrue(hasattr(h, "digest_size")) + self.assertEqual(h.digest_size, self.expected) class HashSelfTest(unittest.TestCase): - - def __init__(self, hashmod, description, expected, input, extra_params): - unittest.TestCase.__init__(self) - self.hashmod = hashmod - self.expected = expected.lower() - self.input = input - self.description = description - self.extra_params = extra_params - - def shortDescription(self): - return self.description - - def runTest(self): - h = self.hashmod.new(**self.extra_params) - h.update(self.input) - - out1 = binascii.b2a_hex(h.digest()) - out2 = h.hexdigest() - - h = self.hashmod.new(self.input, **self.extra_params) - - out3 = h.hexdigest() - out4 = binascii.b2a_hex(h.digest()) - - # PY3K: hexdigest() should return str(), and digest() bytes - self.assertEqual(self.expected, out1) # h = .new(); h.update(data); h.digest() - if sys.version_info[0] == 2: - self.assertEqual(self.expected, out2) # h = .new(); h.update(data); h.hexdigest() - self.assertEqual(self.expected, out3) # h = .new(data); h.hexdigest() - else: - self.assertEqual(self.expected.decode(), out2) # h = .new(); h.update(data); h.hexdigest() - self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest() - self.assertEqual(self.expected, out4) # h = .new(data); h.digest() - - # Verify that the .new() method produces a fresh hash object, except - # for MD5 and SHA1, which are hashlib objects. (But test any .new() - # method that does exist.) - if self.hashmod.__name__ not in ('Cryptodome.Hash.MD5', 'Cryptodome.Hash.SHA1') or hasattr(h, 'new'): - h2 = h.new() - h2.update(self.input) - out5 = binascii.b2a_hex(h2.digest()) - self.assertEqual(self.expected, out5) + def __init__(self, hashmod, description, expected, input, extra_params): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + self.expected = expected.lower() + self.input = input + self.description = description + self.extra_params = extra_params + + def shortDescription(self): + return self.description + + def runTest(self): + h = self.hashmod.new(**self.extra_params) + h.update(self.input) + + out1 = binascii.b2a_hex(h.digest()) + out2 = h.hexdigest() + + h = self.hashmod.new(self.input, **self.extra_params) + + out3 = h.hexdigest() + out4 = binascii.b2a_hex(h.digest()) + + # PY3K: hexdigest() should return str(), and digest() bytes + self.assertEqual(self.expected, out1) # h = .new(); h.update(data); h.digest() + if sys.version_info[0] == 2: + self.assertEqual(self.expected, out2) # h = .new(); h.update(data); h.hexdigest() + self.assertEqual(self.expected, out3) # h = .new(data); h.hexdigest() + else: + self.assertEqual(self.expected.decode(), out2) # h = .new(); h.update(data); h.hexdigest() + self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest() + self.assertEqual(self.expected, out4) # h = .new(data); h.digest() + + # Verify that the .new() method produces a fresh hash object, except + # for MD5 and SHA1, which are hashlib objects. (But test any .new() + # method that does exist.) + if self.hashmod.__name__ not in ("Cryptodome.Hash.MD5", "Cryptodome.Hash.SHA1") or hasattr(h, "new"): + h2 = h.new() + h2.update(self.input) + out5 = binascii.b2a_hex(h2.digest()) + self.assertEqual(self.expected, out5) class HashTestOID(unittest.TestCase): - def __init__(self, hashmod, oid, extra_params): - unittest.TestCase.__init__(self) - self.hashmod = hashmod - self.oid = oid - self.extra_params = extra_params + def __init__(self, hashmod, oid, extra_params): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + self.oid = oid + self.extra_params = extra_params - def runTest(self): - h = self.hashmod.new(**self.extra_params) - self.assertEqual(h.oid, self.oid) + def runTest(self): + h = self.hashmod.new(**self.extra_params) + self.assertEqual(h.oid, self.oid) class ByteArrayTest(unittest.TestCase): + def __init__(self, module, extra_params): + unittest.TestCase.__init__(self) + self.module = module + self.extra_params = extra_params - def __init__(self, module, extra_params): - unittest.TestCase.__init__(self) - self.module = module - self.extra_params = extra_params - - def runTest(self): - data = b("\x00\x01\x02") + def runTest(self): + data = b("\x00\x01\x02") - # Data can be a bytearray (during initialization) - ba = bytearray(data) + # Data can be a bytearray (during initialization) + ba = bytearray(data) - h1 = self.module.new(data, **self.extra_params) - h2 = self.module.new(ba, **self.extra_params) - ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = self.module.new(data, **self.extra_params) + h2 = self.module.new(ba, **self.extra_params) + ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a bytearray (during operation) - ba = bytearray(data) + # Data can be a bytearray (during operation) + ba = bytearray(data) - h1 = self.module.new(**self.extra_params) - h2 = self.module.new(**self.extra_params) + h1 = self.module.new(**self.extra_params) + h2 = self.module.new(**self.extra_params) - h1.update(data) - h2.update(ba) + h1.update(data) + h2.update(ba) - ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) class MemoryViewTest(unittest.TestCase): + def __init__(self, module, extra_params): + unittest.TestCase.__init__(self) + self.module = module + self.extra_params = extra_params - def __init__(self, module, extra_params): - unittest.TestCase.__init__(self) - self.module = module - self.extra_params = extra_params - - def runTest(self): - - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) + def runTest(self): + data = b"\x00\x01\x02" - def get_mv_rw(data): - return memoryview(bytearray(data)) + def get_mv_ro(data): + return memoryview(data) - for get_mv in get_mv_ro, get_mv_rw: + def get_mv_rw(data): + return memoryview(bytearray(data)) - # Data can be a memoryview (during initialization) - mv = get_mv(data) + for get_mv in get_mv_ro, get_mv_rw: + # Data can be a memoryview (during initialization) + mv = get_mv(data) - h1 = self.module.new(data, **self.extra_params) - h2 = self.module.new(mv, **self.extra_params) - if not mv.readonly: - mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = self.module.new(data, **self.extra_params) + h2 = self.module.new(mv, **self.extra_params) + if not mv.readonly: + mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a memoryview (during operation) - mv = get_mv(data) + # Data can be a memoryview (during operation) + mv = get_mv(data) - h1 = self.module.new(**self.extra_params) - h2 = self.module.new(**self.extra_params) - h1.update(data) - h2.update(mv) - if not mv.readonly: - mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = self.module.new(**self.extra_params) + h2 = self.module.new(**self.extra_params) + h1.update(data) + h2.update(mv) + if not mv.readonly: + mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) class MACSelfTest(unittest.TestCase): - - def __init__(self, module, description, result, data, key, params): - unittest.TestCase.__init__(self) - self.module = module - self.result = t2b(result) - self.data = t2b(data) - self.key = t2b(key) - self.params = params - self.description = description - - def shortDescription(self): - return self.description - - def runTest(self): - - result_hex = hexlify(self.result) - - # Verify result - h = self.module.new(self.key, **self.params) - h.update(self.data) - self.assertEqual(self.result, h.digest()) - self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest()) - - # Verify that correct MAC does not raise any exception - h.verify(self.result) - h.hexverify(result_hex) - - # Verify that incorrect MAC does raise ValueError exception - wrong_mac = strxor_c(self.result, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - # Verify again, with data passed to new() - h = self.module.new(self.key, self.data, **self.params) - self.assertEqual(self.result, h.digest()) - self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest()) - - # Test .copy() - try: - h = self.module.new(self.key, self.data, **self.params) - h2 = h.copy() - h3 = h.copy() - - # Verify that changing the copy does not change the original - h2.update(b"bla") - self.assertEqual(h3.digest(), self.result) - - # Verify that both can reach the same state - h.update(b"bla") - self.assertEqual(h.digest(), h2.digest()) - except NotImplementedError: - pass - - # PY3K: Check that hexdigest() returns str and digest() returns bytes - self.assertTrue(isinstance(h.digest(), type(b""))) - self.assertTrue(isinstance(h.hexdigest(), type(""))) - - # PY3K: Check that .hexverify() accepts bytes or str - h.hexverify(h.hexdigest()) - h.hexverify(h.hexdigest().encode('ascii')) - - -def make_hash_tests(module, module_name, test_data, digest_size, oid=None, - extra_params={}): - tests = [] - for i in range(len(test_data)): - row = test_data[i] - (expected, input) = map(tobytes,row[0:2]) - if len(row) < 3: - description = repr(input) - else: - description = row[2] - name = "%s #%d: %s" % (module_name, i+1, description) - tests.append(HashSelfTest(module, name, expected, input, extra_params)) - - name = "%s #%d: digest_size" % (module_name, len(test_data) + 1) - tests.append(HashDigestSizeSelfTest(module, name, digest_size, extra_params)) - - if oid is not None: - tests.append(HashTestOID(module, oid, extra_params)) - - tests.append(ByteArrayTest(module, extra_params)) - - tests.append(MemoryViewTest(module, extra_params)) - - return tests + def __init__(self, module, description, result, data, key, params): + unittest.TestCase.__init__(self) + self.module = module + self.result = t2b(result) + self.data = t2b(data) + self.key = t2b(key) + self.params = params + self.description = description + + def shortDescription(self): + return self.description + + def runTest(self): + result_hex = hexlify(self.result) + + # Verify result + h = self.module.new(self.key, **self.params) + h.update(self.data) + self.assertEqual(self.result, h.digest()) + self.assertEqual(hexlify(self.result).decode("ascii"), h.hexdigest()) + + # Verify that correct MAC does not raise any exception + h.verify(self.result) + h.hexverify(result_hex) + + # Verify that incorrect MAC does raise ValueError exception + wrong_mac = strxor_c(self.result, 255) + self.assertRaises(ValueError, h.verify, wrong_mac) + self.assertRaises(ValueError, h.hexverify, "4556") + + # Verify again, with data passed to new() + h = self.module.new(self.key, self.data, **self.params) + self.assertEqual(self.result, h.digest()) + self.assertEqual(hexlify(self.result).decode("ascii"), h.hexdigest()) + + # Test .copy() + try: + h = self.module.new(self.key, self.data, **self.params) + h2 = h.copy() + h3 = h.copy() + + # Verify that changing the copy does not change the original + h2.update(b"bla") + self.assertEqual(h3.digest(), self.result) + + # Verify that both can reach the same state + h.update(b"bla") + self.assertEqual(h.digest(), h2.digest()) + except NotImplementedError: + pass + + # PY3K: Check that hexdigest() returns str and digest() returns bytes + self.assertTrue(isinstance(h.digest(), type(b""))) + self.assertTrue(isinstance(h.hexdigest(), type(""))) + + # PY3K: Check that .hexverify() accepts bytes or str + h.hexverify(h.hexdigest()) + h.hexverify(h.hexdigest().encode("ascii")) + + +def make_hash_tests( + module, + module_name, + test_data, + digest_size, + oid=None, + extra_params={}, +): + tests = [] + for i in range(len(test_data)): + row = test_data[i] + (expected, input) = map(tobytes, row[0:2]) + if len(row) < 3: + description = repr(input) + else: + description = row[2] + name = "%s #%d: %s" % (module_name, i + 1, description) + tests.append(HashSelfTest(module, name, expected, input, extra_params)) + + name = "%s #%d: digest_size" % (module_name, len(test_data) + 1) + tests.append(HashDigestSizeSelfTest(module, name, digest_size, extra_params)) + + if oid is not None: + tests.append(HashTestOID(module, oid, extra_params)) + + tests.append(ByteArrayTest(module, extra_params)) + + tests.append(MemoryViewTest(module, extra_params)) + + return tests def make_mac_tests(module, module_name, test_data): - tests = [] - for i, row in enumerate(test_data): - if len(row) == 4: - (key, data, results, description, params) = list(row) + [ {} ] - else: - (key, data, results, description, params) = row - name = "%s #%d: %s" % (module_name, i+1, description) - tests.append(MACSelfTest(module, name, results, data, key, params)) - return tests + tests = [] + for i, row in enumerate(test_data): + if len(row) == 4: + (key, data, results, description, params) = list(row) + [{}] + else: + (key, data, results, description, params) = row + name = "%s #%d: %s" % (module_name, i + 1, description) + tests.append(MACSelfTest(module, name, results, data, key, params)) + return tests + # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_BLAKE2.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_BLAKE2.py index e5ed63b7..e4067eb1 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_BLAKE2.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_BLAKE2.py @@ -42,441 +42,454 @@ class Blake2Test(unittest.TestCase): + def test_new_positive(self): + h = self.BLAKE2.new(digest_bits=self.max_bits) + for new_func in self.BLAKE2.new, h.new: + for dbits in range(8, self.max_bits + 1, 8): + hobj = new_func(digest_bits=dbits) + self.assertEqual(hobj.digest_size, dbits // 8) + + for dbytes in range(1, self.max_bytes + 1): + hobj = new_func(digest_bytes=dbytes) + self.assertEqual(hobj.digest_size, dbytes) + + digest1 = new_func(data=b"\x90", digest_bytes=self.max_bytes).digest() + digest2 = new_func(digest_bytes=self.max_bytes).update(b"\x90").digest() + self.assertEqual(digest1, digest2) + + new_func(data=b"A", key=b"5", digest_bytes=self.max_bytes) + + hobj = h.new() + self.assertEqual(hobj.digest_size, self.max_bytes) + + def test_new_negative(self): + h = self.BLAKE2.new(digest_bits=self.max_bits) + for new_func in self.BLAKE2.new, h.new: + self.assertRaises( + TypeError, + new_func, + digest_bytes=self.max_bytes, + digest_bits=self.max_bits, + ) + self.assertRaises(ValueError, new_func, digest_bytes=0) + self.assertRaises( + ValueError, + new_func, + digest_bytes=self.max_bytes + 1, + ) + self.assertRaises(ValueError, new_func, digest_bits=7) + self.assertRaises(ValueError, new_func, digest_bits=15) + self.assertRaises( + ValueError, + new_func, + digest_bits=self.max_bits + 1, + ) + self.assertRaises( + TypeError, + new_func, + digest_bytes=self.max_bytes, + key="string", + ) + self.assertRaises( + TypeError, + new_func, + digest_bytes=self.max_bytes, + data="string", + ) + + def test_default_digest_size(self): + digest = self.BLAKE2.new(data=b"abc").digest() + self.assertEqual(len(digest), self.max_bytes) + + def test_update(self): + pieces = [b"\x0a" * 200, b"\x14" * 300] + h = self.BLAKE2.new(digest_bytes=self.max_bytes) + h.update(pieces[0]).update(pieces[1]) + digest = h.digest() + h = self.BLAKE2.new(digest_bytes=self.max_bytes) + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.digest(), digest) + + def test_update_negative(self): + h = self.BLAKE2.new(digest_bytes=self.max_bytes) + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = self.BLAKE2.new(digest_bytes=self.max_bytes) + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b"digest"))) + + def test_update_after_digest(self): + msg = b"rrrrttt" + + # Normally, update() cannot be done after digest() + h = self.BLAKE2.new(digest_bits=256, data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = self.BLAKE2.new(digest_bits=256, data=msg).digest() + + # With the proper flag, it is allowed + h = self.BLAKE2.new(digest_bits=256, data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) + + def test_hex_digest(self): + mac = self.BLAKE2.new(digest_bits=self.max_bits) + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_verify(self): + h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") + mac = h.digest() + h.verify(mac) + wrong_mac = strxor_c(mac, 255) + self.assertRaises(ValueError, h.verify, wrong_mac) + + def test_hexverify(self): + h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") + mac = h.hexdigest() + h.hexverify(mac) + self.assertRaises(ValueError, h.hexverify, "4556") + + def test_oid(self): + prefix = "1.3.6.1.4.1.1722.12.2." + self.oid_variant + "." + + for digest_bits in self.digest_bits_oid: + h = self.BLAKE2.new(digest_bits=digest_bits) + self.assertEqual(h.oid, prefix + str(digest_bits // 8)) + + h = self.BLAKE2.new(digest_bits=digest_bits, key=b"secret") + self.assertRaises(AttributeError, lambda: h.oid) + + for digest_bits in (8, self.max_bits): + if digest_bits in self.digest_bits_oid: + continue + self.assertRaises(AttributeError, lambda: h.oid) + + def test_bytearray(self): + key = b"0" * 16 + data = b"\x00\x01\x02" + + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(key) + data_ba = bytearray(data) + + h1 = self.BLAKE2.new(data=data, key=key) + h2 = self.BLAKE2.new(data=data_ba, key=key_ba) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + # Data can be a bytearray (during operation) + data_ba = bytearray(data) + + h1 = self.BLAKE2.new() + h2 = self.BLAKE2.new() + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + def test_memoryview(self): + key = b"0" * 16 + data = b"\x00\x01\x02" + + def get_mv_ro(data): + return memoryview(data) + + def get_mv_rw(data): + return memoryview(bytearray(data)) + + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(key) + data_mv = get_mv(data) + + h1 = self.BLAKE2.new(data=data, key=key) + h2 = self.BLAKE2.new(data=data_mv, key=key_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + key_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + # Data can be a memoryview (during operation) + data_mv = get_mv(data) - def test_new_positive(self): - - h = self.BLAKE2.new(digest_bits=self.max_bits) - for new_func in self.BLAKE2.new, h.new: - - for dbits in range(8, self.max_bits + 1, 8): - hobj = new_func(digest_bits=dbits) - self.assertEqual(hobj.digest_size, dbits // 8) - - for dbytes in range(1, self.max_bytes + 1): - hobj = new_func(digest_bytes=dbytes) - self.assertEqual(hobj.digest_size, dbytes) - - digest1 = new_func(data=b"\x90", digest_bytes=self.max_bytes).digest() - digest2 = new_func(digest_bytes=self.max_bytes).update(b"\x90").digest() - self.assertEqual(digest1, digest2) - - new_func(data=b"A", key=b"5", digest_bytes=self.max_bytes) - - hobj = h.new() - self.assertEqual(hobj.digest_size, self.max_bytes) - - def test_new_negative(self): - - h = self.BLAKE2.new(digest_bits=self.max_bits) - for new_func in self.BLAKE2.new, h.new: - self.assertRaises(TypeError, new_func, - digest_bytes=self.max_bytes, - digest_bits=self.max_bits) - self.assertRaises(ValueError, new_func, digest_bytes=0) - self.assertRaises(ValueError, new_func, - digest_bytes=self.max_bytes + 1) - self.assertRaises(ValueError, new_func, digest_bits=7) - self.assertRaises(ValueError, new_func, digest_bits=15) - self.assertRaises(ValueError, new_func, - digest_bits=self.max_bits + 1) - self.assertRaises(TypeError, new_func, - digest_bytes=self.max_bytes, - key=u"string") - self.assertRaises(TypeError, new_func, - digest_bytes=self.max_bytes, - data=u"string") - - def test_default_digest_size(self): - digest = self.BLAKE2.new(data=b'abc').digest() - self.assertEqual(len(digest), self.max_bytes) - - def test_update(self): - pieces = [b"\x0A" * 200, b"\x14" * 300] - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - h.update(pieces[0]).update(pieces[1]) - digest = h.digest() - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.digest(), digest) - - def test_update_negative(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg = b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = self.BLAKE2.new(digest_bits=256, data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = self.BLAKE2.new(digest_bits=256, data=msg).digest() - - # With the proper flag, it is allowed - h = self.BLAKE2.new(digest_bits=256, data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) - - def test_hex_digest(self): - mac = self.BLAKE2.new(digest_bits=self.max_bits) - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_verify(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") - mac = h.digest() - h.verify(mac) - wrong_mac = strxor_c(mac, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - - def test_hexverify(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") - mac = h.hexdigest() - h.hexverify(mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - def test_oid(self): - - prefix = "1.3.6.1.4.1.1722.12.2." + self.oid_variant + "." - - for digest_bits in self.digest_bits_oid: - h = self.BLAKE2.new(digest_bits=digest_bits) - self.assertEqual(h.oid, prefix + str(digest_bits // 8)) - - h = self.BLAKE2.new(digest_bits=digest_bits, key=b"secret") - self.assertRaises(AttributeError, lambda: h.oid) - - for digest_bits in (8, self.max_bits): - if digest_bits in self.digest_bits_oid: - continue - self.assertRaises(AttributeError, lambda: h.oid) - - def test_bytearray(self): - - key = b'0' * 16 - data = b"\x00\x01\x02" - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) - - h1 = self.BLAKE2.new(data=data, key=key) - h2 = self.BLAKE2.new(data=data_ba, key=key_ba) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' + h1 = self.BLAKE2.new() + h2 = self.BLAKE2.new() + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = self.BLAKE2.new() - h2 = self.BLAKE2.new() - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - key = b'0' * 16 - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) - - h1 = self.BLAKE2.new(data=data, key=key) - h2 = self.BLAKE2.new(data=data_mv, key=key_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - key_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = self.BLAKE2.new() - h2 = self.BLAKE2.new() - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) + self.assertEqual(h1.digest(), h2.digest()) class Blake2bTest(Blake2Test): - #: Module - BLAKE2 = BLAKE2b - #: Max output size (in bits) - max_bits = 512 - #: Max output size (in bytes) - max_bytes = 64 - #: Bit size of the digests for which an ASN OID exists - digest_bits_oid = (160, 256, 384, 512) - # http://tools.ietf.org/html/draft-saarinen-blake2-02 - oid_variant = "1" + #: Module + BLAKE2 = BLAKE2b + #: Max output size (in bits) + max_bits = 512 + #: Max output size (in bytes) + max_bytes = 64 + #: Bit size of the digests for which an ASN OID exists + digest_bits_oid = (160, 256, 384, 512) + # http://tools.ietf.org/html/draft-saarinen-blake2-02 + oid_variant = "1" class Blake2sTest(Blake2Test): - #: Module - BLAKE2 = BLAKE2s - #: Max output size (in bits) - max_bits = 256 - #: Max output size (in bytes) - max_bytes = 32 - #: Bit size of the digests for which an ASN OID exists - digest_bits_oid = (128, 160, 224, 256) - # http://tools.ietf.org/html/draft-saarinen-blake2-02 - oid_variant = "2" + #: Module + BLAKE2 = BLAKE2s + #: Max output size (in bits) + max_bits = 256 + #: Max output size (in bytes) + max_bytes = 32 + #: Bit size of the digests for which an ASN OID exists + digest_bits_oid = (128, 160, 224, 256) + # http://tools.ietf.org/html/draft-saarinen-blake2-02 + oid_variant = "2" class Blake2OfficialTestVector(unittest.TestCase): - - def _load_tests(self, test_vector_file): - expected = "in" - test_vectors = [] - with open(test_vector_file, "rt") as test_vector_fd: - for line_number, line in enumerate(test_vector_fd): - - if line.strip() == "" or line.startswith("#"): - continue - - res = re.match("%s:\t([0-9A-Fa-f]*)" % expected, line) - if not res: - raise ValueError("Incorrect test vector format (line %d)" - % line_number) - - if res.group(1): - bin_value = unhexlify(tobytes(res.group(1))) - else: - bin_value = b"" - if expected == "in": - input_data = bin_value - expected = "key" - elif expected == "key": - key = bin_value - expected = "hash" - else: - result = bin_value - expected = "in" - test_vectors.append((input_data, key, result)) - return test_vectors - - def setUp(self): - - dir_comps = ("Hash", self.name) - file_name = self.name.lower() + "-test.txt" - self.description = "%s tests" % self.name - - try: - import pycryptodome_test_vectors # type: ignore - except ImportError: - warnings.warn("Warning: skipping extended tests for %s" % self.name, - UserWarning) - self.test_vectors = [] - return - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - self.test_vectors = self._load_tests(full_file_name) - - def runTest(self): - for (input_data, key, result) in self.test_vectors: - mac = self.BLAKE2.new(key=key, digest_bytes=self.max_bytes) - mac.update(input_data) - self.assertEqual(mac.digest(), result) + def _load_tests(self, test_vector_file): + expected = "in" + test_vectors = [] + with open(test_vector_file, "rt") as test_vector_fd: + for line_number, line in enumerate(test_vector_fd): + if line.strip() == "" or line.startswith("#"): + continue + + res = re.match("%s:\t([0-9A-Fa-f]*)" % expected, line) + if not res: + raise ValueError( + "Incorrect test vector format (line %d)" % line_number, + ) + + if res.group(1): + bin_value = unhexlify(tobytes(res.group(1))) + else: + bin_value = b"" + if expected == "in": + input_data = bin_value + expected = "key" + elif expected == "key": + key = bin_value + expected = "hash" + else: + result = bin_value + expected = "in" + test_vectors.append((input_data, key, result)) + return test_vectors + + def setUp(self): + dir_comps = ("Hash", self.name) + file_name = self.name.lower() + "-test.txt" + self.description = "%s tests" % self.name + + try: + import pycryptodome_test_vectors # type: ignore + except ImportError: + warnings.warn( + "Warning: skipping extended tests for %s" % self.name, + UserWarning, + ) + self.test_vectors = [] + return + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + self.test_vectors = self._load_tests(full_file_name) + + def runTest(self): + for input_data, key, result in self.test_vectors: + mac = self.BLAKE2.new(key=key, digest_bytes=self.max_bytes) + mac.update(input_data) + self.assertEqual(mac.digest(), result) class Blake2bOfficialTestVector(Blake2OfficialTestVector): - #: Module - BLAKE2 = BLAKE2b - #: Hash name - name = "BLAKE2b" - #: Max digest size - max_bytes = 64 + #: Module + BLAKE2 = BLAKE2b + #: Hash name + name = "BLAKE2b" + #: Max digest size + max_bytes = 64 class Blake2sOfficialTestVector(Blake2OfficialTestVector): - #: Module - BLAKE2 = BLAKE2s - #: Hash name - name = "BLAKE2s" - #: Max digest size - max_bytes = 32 + #: Module + BLAKE2 = BLAKE2s + #: Hash name + name = "BLAKE2s" + #: Max digest size + max_bytes = 32 class Blake2TestVector1(unittest.TestCase): - - def _load_tests(self, test_vector_file): - test_vectors = [] - with open(test_vector_file, "rt") as test_vector_fd: - for line_number, line in enumerate(test_vector_fd): - if line.strip() == "" or line.startswith("#"): - continue - res = re.match("digest: ([0-9A-Fa-f]*)", line) - if not res: - raise ValueError("Incorrect test vector format (line %d)" - % line_number) - - test_vectors.append(unhexlify(tobytes(res.group(1)))) - return test_vectors - - def setUp(self): - dir_comps = ("Hash", self.name) - file_name = "tv1.txt" - self.description = "%s tests" % self.name - - try: - import pycryptodome_test_vectors - except ImportError: - warnings.warn("Warning: skipping extended tests for %s" % self.name, - UserWarning) - self.test_vectors = [] - return - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - self.test_vectors = self._load_tests(full_file_name) - - def runTest(self): - - for tv in self.test_vectors: - digest_bytes = len(tv) - next_data = b"" - for _ in range(100): - h = self.BLAKE2.new(digest_bytes=digest_bytes) - h.update(next_data) - next_data = h.digest() + next_data - self.assertEqual(h.digest(), tv) + def _load_tests(self, test_vector_file): + test_vectors = [] + with open(test_vector_file, "rt") as test_vector_fd: + for line_number, line in enumerate(test_vector_fd): + if line.strip() == "" or line.startswith("#"): + continue + res = re.match("digest: ([0-9A-Fa-f]*)", line) + if not res: + raise ValueError( + "Incorrect test vector format (line %d)" % line_number, + ) + + test_vectors.append(unhexlify(tobytes(res.group(1)))) + return test_vectors + + def setUp(self): + dir_comps = ("Hash", self.name) + file_name = "tv1.txt" + self.description = "%s tests" % self.name + + try: + import pycryptodome_test_vectors + except ImportError: + warnings.warn( + "Warning: skipping extended tests for %s" % self.name, + UserWarning, + ) + self.test_vectors = [] + return + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + self.test_vectors = self._load_tests(full_file_name) + + def runTest(self): + for tv in self.test_vectors: + digest_bytes = len(tv) + next_data = b"" + for _ in range(100): + h = self.BLAKE2.new(digest_bytes=digest_bytes) + h.update(next_data) + next_data = h.digest() + next_data + self.assertEqual(h.digest(), tv) class Blake2bTestVector1(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2b - #: Hash name - name = "BLAKE2b" + #: Module + BLAKE2 = BLAKE2b + #: Hash name + name = "BLAKE2b" class Blake2sTestVector1(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2s - #: Hash name - name = "BLAKE2s" + #: Module + BLAKE2 = BLAKE2s + #: Hash name + name = "BLAKE2s" class Blake2TestVector2(unittest.TestCase): - - def _load_tests(self, test_vector_file): - test_vectors = [] - with open(test_vector_file, "rt") as test_vector_fd: - for line_number, line in enumerate(test_vector_fd): - if line.strip() == "" or line.startswith("#"): - continue - res = re.match(r"digest\(([0-9]+)\): ([0-9A-Fa-f]*)", line) - if not res: - raise ValueError("Incorrect test vector format (line %d)" - % line_number) - key_size = int(res.group(1)) - result = unhexlify(tobytes(res.group(2))) - test_vectors.append((key_size, result)) - return test_vectors - - def setUp(self): - dir_comps = ("Hash", self.name) - file_name = "tv2.txt" - self.description = "%s tests" % self.name - - try: - import pycryptodome_test_vectors # type: ignore - except ImportError: - warnings.warn("Warning: skipping extended tests for %s" % self.name, - UserWarning) - self.test_vectors = [] - return - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - self.test_vectors = self._load_tests(full_file_name) - - def runTest(self): - - for key_size, result in self.test_vectors: - next_data = b"" - for _ in range(100): - h = self.BLAKE2.new(digest_bytes=self.max_bytes, - key=b"A" * key_size) - h.update(next_data) - next_data = h.digest() + next_data - self.assertEqual(h.digest(), result) + def _load_tests(self, test_vector_file): + test_vectors = [] + with open(test_vector_file, "rt") as test_vector_fd: + for line_number, line in enumerate(test_vector_fd): + if line.strip() == "" or line.startswith("#"): + continue + res = re.match(r"digest\(([0-9]+)\): ([0-9A-Fa-f]*)", line) + if not res: + raise ValueError( + "Incorrect test vector format (line %d)" % line_number, + ) + key_size = int(res.group(1)) + result = unhexlify(tobytes(res.group(2))) + test_vectors.append((key_size, result)) + return test_vectors + + def setUp(self): + dir_comps = ("Hash", self.name) + file_name = "tv2.txt" + self.description = "%s tests" % self.name + + try: + import pycryptodome_test_vectors # type: ignore + except ImportError: + warnings.warn( + "Warning: skipping extended tests for %s" % self.name, + UserWarning, + ) + self.test_vectors = [] + return + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + self.test_vectors = self._load_tests(full_file_name) + + def runTest(self): + for key_size, result in self.test_vectors: + next_data = b"" + for _ in range(100): + h = self.BLAKE2.new( + digest_bytes=self.max_bytes, + key=b"A" * key_size, + ) + h.update(next_data) + next_data = h.digest() + next_data + self.assertEqual(h.digest(), result) class Blake2bTestVector2(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2b - #: Hash name - name = "BLAKE2b" - #: Max digest size in bytes - max_bytes = 64 + #: Module + BLAKE2 = BLAKE2b + #: Hash name + name = "BLAKE2b" + #: Max digest size in bytes + max_bytes = 64 class Blake2sTestVector2(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2s - #: Hash name - name = "BLAKE2s" - #: Max digest size in bytes - max_bytes = 32 + #: Module + BLAKE2 = BLAKE2s + #: Hash name + name = "BLAKE2s" + #: Max digest size in bytes + max_bytes = 32 def get_tests(config={}): - tests = [] + tests = [] + + tests += list_test_cases(Blake2bTest) + tests.append(Blake2bOfficialTestVector()) + tests.append(Blake2bTestVector1()) + tests.append(Blake2bTestVector2()) + + tests += list_test_cases(Blake2sTest) + tests.append(Blake2sOfficialTestVector()) + tests.append(Blake2sTestVector1()) + tests.append(Blake2sTestVector2()) - tests += list_test_cases(Blake2bTest) - tests.append(Blake2bOfficialTestVector()) - tests.append(Blake2bTestVector1()) - tests.append(Blake2bTestVector2()) + return tests - tests += list_test_cases(Blake2sTest) - tests.append(Blake2sOfficialTestVector()) - tests.append(Blake2sTestVector1()) - tests.append(Blake2sTestVector2()) - return tests +if __name__ == "__main__": + import unittest + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - import unittest - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_CMAC.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_CMAC.py index f88f1cd8..98208bd4 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_CMAC.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_CMAC.py @@ -33,9 +33,7 @@ """Self-test suite for Cryptodome.Hash.CMAC""" -import json import unittest -from binascii import unhexlify from Cryptodome.Util.py3compat import tobytes @@ -43,406 +41,359 @@ from Cryptodome.Cipher import AES, DES3 from Cryptodome.Hash import SHAKE128 -from Cryptodome.Util.strxor import strxor from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.SelfTest.loader import load_test_vectors_wycheproof # This is a list of (key, data, result, description, module) tuples. test_data = [ - - ## Test vectors from RFC 4493 ## - ## The are also in NIST SP 800 38B D.2 ## - ( '2b7e151628aed2a6abf7158809cf4f3c', - '', - 'bb1d6929e95937287fa37d129b756746', - 'RFC 4493 #1', - AES - ), - - ( '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172a', - '070a16b46b4d4144f79bdd9dd04a287c', - 'RFC 4493 #2', - AES - ), - - ( '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411', - 'dfa66747de9ae63030ca32611497c827', - 'RFC 4493 #3', - AES - ), - - ( '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+ - 'f69f2445df4f9b17ad2b417be66c3710', - '51f0bebf7e3b9d92fc49741779363cfe', - 'RFC 4493 #4', - AES - ), - - ## The rest of Appendix D of NIST SP 800 38B - ## was not totally correct. - ## Values in Examples 14, 15, 18, and 19 were wrong. - ## The updated test values are published in: - ## http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '', - 'd17ddf46adaacde531cac483de7a9367', - 'NIST SP 800 38B D.2 Example 5', - AES - ), - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172a', - '9e99a7bf31e710900662f65e617c5184', - 'NIST SP 800 38B D.2 Example 6', - AES - ), - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411', - '8a1de5be2eb31aad089a82e6ee908b0e', - 'NIST SP 800 38B D.2 Example 7', - AES - ), - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+ - 'f69f2445df4f9b17ad2b417be66c3710', - 'a1d5df0eed790f794d77589659f39a11', - 'NIST SP 800 38B D.2 Example 8', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '', - '028962f61b7bf89efc6b551f4667d983', - 'NIST SP 800 38B D.3 Example 9', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '6bc1bee22e409f96e93d7e117393172a', - '28a7023f452e8f82bd4bf28d8c37c35c', - 'NIST SP 800 38B D.3 Example 10', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411', - 'aaf3d8f1de5640c232f5b169b9c911e6', - 'NIST SP 800 38B D.3 Example 11', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+ - 'f69f2445df4f9b17ad2b417be66c3710', - 'e1992190549f6ed5696a2c056c315410', - 'NIST SP 800 38B D.3 Example 12', - AES - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '', - 'b7a688e122ffaf95', - 'NIST SP 800 38B D.4 Example 13', - DES3 - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '6bc1bee22e409f96', - '8e8f293136283797', - 'NIST SP 800 38B D.4 Example 14', - DES3 - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a57', - '743ddbe0ce2dc2ed', - 'NIST SP 800 38B D.4 Example 15', - DES3 - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a571e03ac9c'+ - '9eb76fac45af8e51', - '33e6b1092400eae5', - 'NIST SP 800 38B D.4 Example 16', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '', - 'bd2ebf9a3ba00361', - 'NIST SP 800 38B D.7 Example 17', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '6bc1bee22e409f96', - '4ff2ab813c53ce83', - 'NIST SP 800 38B D.7 Example 18', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a57', - '62dd1b471902bd4e', - 'NIST SP 800 38B D.7 Example 19', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a571e03ac9c'+ - '9eb76fac45af8e51', - '31b1e431dabc4eb8', - 'NIST SP 800 38B D.7 Example 20', - DES3 - ), - + ## Test vectors from RFC 4493 ## + ## The are also in NIST SP 800 38B D.2 ## + ( + "2b7e151628aed2a6abf7158809cf4f3c", + "", + "bb1d6929e95937287fa37d129b756746", + "RFC 4493 #1", + AES, + ), + ( + "2b7e151628aed2a6abf7158809cf4f3c", + "6bc1bee22e409f96e93d7e117393172a", + "070a16b46b4d4144f79bdd9dd04a287c", + "RFC 4493 #2", + AES, + ), + ( + "2b7e151628aed2a6abf7158809cf4f3c", + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", + "dfa66747de9ae63030ca32611497c827", + "RFC 4493 #3", + AES, + ), + ( + "2b7e151628aed2a6abf7158809cf4f3c", + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "51f0bebf7e3b9d92fc49741779363cfe", + "RFC 4493 #4", + AES, + ), + ## The rest of Appendix D of NIST SP 800 38B + ## was not totally correct. + ## Values in Examples 14, 15, 18, and 19 were wrong. + ## The updated test values are published in: + ## http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf + ( + "8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b", + "", + "d17ddf46adaacde531cac483de7a9367", + "NIST SP 800 38B D.2 Example 5", + AES, + ), + ( + "8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b", + "6bc1bee22e409f96e93d7e117393172a", + "9e99a7bf31e710900662f65e617c5184", + "NIST SP 800 38B D.2 Example 6", + AES, + ), + ( + "8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b", + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", + "8a1de5be2eb31aad089a82e6ee908b0e", + "NIST SP 800 38B D.2 Example 7", + AES, + ), + ( + "8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b", + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "a1d5df0eed790f794d77589659f39a11", + "NIST SP 800 38B D.2 Example 8", + AES, + ), + ( + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + "", + "028962f61b7bf89efc6b551f4667d983", + "NIST SP 800 38B D.3 Example 9", + AES, + ), + ( + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + "6bc1bee22e409f96e93d7e117393172a", + "28a7023f452e8f82bd4bf28d8c37c35c", + "NIST SP 800 38B D.3 Example 10", + AES, + ), + ( + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", + "aaf3d8f1de5640c232f5b169b9c911e6", + "NIST SP 800 38B D.3 Example 11", + AES, + ), + ( + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + "6bc1bee22e409f96e93d7e117393172a" + + "ae2d8a571e03ac9c9eb76fac45af8e51" + + "30c81c46a35ce411e5fbc1191a0a52ef" + + "f69f2445df4f9b17ad2b417be66c3710", + "e1992190549f6ed5696a2c056c315410", + "NIST SP 800 38B D.3 Example 12", + AES, + ), + ( + "8aa83bf8cbda1062" + "0bc1bf19fbb6cd58" + "bc313d4a371ca8b5", + "", + "b7a688e122ffaf95", + "NIST SP 800 38B D.4 Example 13", + DES3, + ), + ( + "8aa83bf8cbda1062" + "0bc1bf19fbb6cd58" + "bc313d4a371ca8b5", + "6bc1bee22e409f96", + "8e8f293136283797", + "NIST SP 800 38B D.4 Example 14", + DES3, + ), + ( + "8aa83bf8cbda1062" + "0bc1bf19fbb6cd58" + "bc313d4a371ca8b5", + "6bc1bee22e409f96" + "e93d7e117393172a" + "ae2d8a57", + "743ddbe0ce2dc2ed", + "NIST SP 800 38B D.4 Example 15", + DES3, + ), + ( + "8aa83bf8cbda1062" + "0bc1bf19fbb6cd58" + "bc313d4a371ca8b5", + "6bc1bee22e409f96" + "e93d7e117393172a" + "ae2d8a571e03ac9c" + "9eb76fac45af8e51", + "33e6b1092400eae5", + "NIST SP 800 38B D.4 Example 16", + DES3, + ), + ( + "4cf15134a2850dd5" + "8a3d10ba80570d38", + "", + "bd2ebf9a3ba00361", + "NIST SP 800 38B D.7 Example 17", + DES3, + ), + ( + "4cf15134a2850dd5" + "8a3d10ba80570d38", + "6bc1bee22e409f96", + "4ff2ab813c53ce83", + "NIST SP 800 38B D.7 Example 18", + DES3, + ), + ( + "4cf15134a2850dd5" + "8a3d10ba80570d38", + "6bc1bee22e409f96" + "e93d7e117393172a" + "ae2d8a57", + "62dd1b471902bd4e", + "NIST SP 800 38B D.7 Example 19", + DES3, + ), + ( + "4cf15134a2850dd5" + "8a3d10ba80570d38", + "6bc1bee22e409f96" + "e93d7e117393172a" + "ae2d8a571e03ac9c" + "9eb76fac45af8e51", + "31b1e431dabc4eb8", + "NIST SP 800 38B D.7 Example 20", + DES3, + ), ] def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) + return SHAKE128.new(data=tobytes(tag)).read(length) class TestCMAC(unittest.TestCase): - - def test_internal_caching(self): - """Verify that internal caching is implemented correctly""" - - data_to_mac = get_tag_random("data_to_mac", 128) - key = get_tag_random("key", 16) - ref_mac = CMAC.new(key, msg=data_to_mac, ciphermod=AES).digest() - - # Break up in chunks of different length - # The result must always be the same - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - chunks = [data_to_mac[i:i+chunk_length] for i in - range(0, len(data_to_mac), chunk_length)] - - mac = CMAC.new(key, ciphermod=AES) - for chunk in chunks: - mac.update(chunk) - self.assertEqual(ref_mac, mac.digest()) - - def test_update_after_digest(self): - msg = b"rrrrttt" - key = b"4" * 16 - - # Normally, update() cannot be done after digest() - h = CMAC.new(key, msg[:4], ciphermod=AES) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = CMAC.new(key, msg, ciphermod=AES).digest() - - # With the proper flag, it is allowed - h2 = CMAC.new(key, msg[:4], ciphermod=AES, update_after_digest=True) - self.assertEqual(h2.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h2.update(msg[4:]) - self.assertEqual(h2.digest(), dig2) + def test_internal_caching(self): + """Verify that internal caching is implemented correctly""" + + data_to_mac = get_tag_random("data_to_mac", 128) + key = get_tag_random("key", 16) + ref_mac = CMAC.new(key, msg=data_to_mac, ciphermod=AES).digest() + + # Break up in chunks of different length + # The result must always be the same + for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: + chunks = [data_to_mac[i : i + chunk_length] for i in range(0, len(data_to_mac), chunk_length)] + + mac = CMAC.new(key, ciphermod=AES) + for chunk in chunks: + mac.update(chunk) + self.assertEqual(ref_mac, mac.digest()) + + def test_update_after_digest(self): + msg = b"rrrrttt" + key = b"4" * 16 + + # Normally, update() cannot be done after digest() + h = CMAC.new(key, msg[:4], ciphermod=AES) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = CMAC.new(key, msg, ciphermod=AES).digest() + + # With the proper flag, it is allowed + h2 = CMAC.new(key, msg[:4], ciphermod=AES, update_after_digest=True) + self.assertEqual(h2.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h2.update(msg[4:]) + self.assertEqual(h2.digest(), dig2) class ByteArrayTests(unittest.TestCase): + def runTest(self): + key = b"0" * 16 + data = b"\x00\x01\x02" - def runTest(self): + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(key) + data_ba = bytearray(data) - key = b"0" * 16 - data = b"\x00\x01\x02" + h1 = CMAC.new(key, data, ciphermod=AES) + h2 = CMAC.new(key_ba, data_ba, ciphermod=AES) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) + # Data can be a bytearray (during operation) + key_ba = bytearray(key) + data_ba = bytearray(data) - h1 = CMAC.new(key, data, ciphermod=AES) - h2 = CMAC.new(key_ba, data_ba, ciphermod=AES) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = CMAC.new(key, ciphermod=AES) + h2 = CMAC.new(key, ciphermod=AES) + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a bytearray (during operation) - key_ba = bytearray(key) - data_ba = bytearray(data) - h1 = CMAC.new(key, ciphermod=AES) - h2 = CMAC.new(key, ciphermod=AES) - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) +class MemoryViewTests(unittest.TestCase): + def runTest(self): + key = b"0" * 16 + data = b"\x00\x01\x02" + def get_mv_ro(data): + return memoryview(data) -class MemoryViewTests(unittest.TestCase): + def get_mv_rw(data): + return memoryview(bytearray(data)) - def runTest(self): + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(key) + data_mv = get_mv(data) - key = b"0" * 16 - data = b"\x00\x01\x02" + h1 = CMAC.new(key, data, ciphermod=AES) + h2 = CMAC.new(key_mv, data_mv, ciphermod=AES) + if not data_mv.readonly: + key_mv[:1] = b"\xff" + data_mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - def get_mv_ro(data): - return memoryview(data) + # Data can be a memoryview (during operation) + data_mv = get_mv(data) - def get_mv_rw(data): - return memoryview(bytearray(data)) + h1 = CMAC.new(key, ciphermod=AES) + h2 = CMAC.new(key, ciphermod=AES) + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - for get_mv in (get_mv_ro, get_mv_rw): - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) +class TestVectorsWycheproof(unittest.TestCase): + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def setUp(self): + def filter_tag(group): + return group["tagSize"] // 8 + + self.tv = load_test_vectors_wycheproof( + ("Hash", "wycheproof"), + "aes_cmac_test.json", + "Wycheproof CMAC", + group_tag={"tag_size": filter_tag}, + ) + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_create_mac(self, tv): + self._id = "Wycheproof MAC creation Test #" + str(tv.id) + + try: + tag = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size).digest() + except ValueError as e: + if len(tv.key) not in (16, 24, 32) and "key length" in str(e): + return + raise e + if tv.valid: + self.assertEqual(tag, tv.tag) + self.warn(tv) + + def test_verify_mac(self, tv): + self._id = "Wycheproof MAC verification Test #" + str(tv.id) + + try: + mac = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size) + except ValueError as e: + if len(tv.key) not in (16, 24, 32) and "key length" in str(e): + return + raise e + try: + mac.verify(tv.tag) + except ValueError: + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_create_mac(tv) + self.test_verify_mac(tv) - h1 = CMAC.new(key, data, ciphermod=AES) - h2 = CMAC.new(key_mv, data_mv, ciphermod=AES) - if not data_mv.readonly: - key_mv[:1] = b'\xFF' - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - # Data can be a memoryview (during operation) - data_mv = get_mv(data) +def get_tests(config={}): + global test_data + from .common import make_mac_tests - h1 = CMAC.new(key, ciphermod=AES) - h2 = CMAC.new(key, ciphermod=AES) - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + wycheproof_warnings = config.get("wycheproof_warnings") + # Add new() parameters to the back of each test vector + params_test_data = [] + for row in test_data: + t = list(row) + t[4] = dict(ciphermod=t[4]) + params_test_data.append(t) -class TestVectorsWycheproof(unittest.TestCase): + tests = make_mac_tests(CMAC, "CMAC", params_test_data) + tests.append(ByteArrayTests()) + tests.append(list_test_cases(TestCMAC)) + tests.append(MemoryViewTests()) + tests += [TestVectorsWycheproof(wycheproof_warnings)] + return tests - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def setUp(self): - - def filter_tag(group): - return group['tagSize'] // 8 - - self.tv = load_test_vectors_wycheproof(("Hash", "wycheproof"), - "aes_cmac_test.json", - "Wycheproof CMAC", - group_tag={'tag_size': filter_tag}) - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_create_mac(self, tv): - self._id = "Wycheproof MAC creation Test #" + str(tv.id) - - try: - tag = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size).digest() - except ValueError as e: - if len(tv.key) not in (16, 24, 32) and "key length" in str(e): - return - raise e - if tv.valid: - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_verify_mac(self, tv): - self._id = "Wycheproof MAC verification Test #" + str(tv.id) - - try: - mac = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size) - except ValueError as e: - if len(tv.key) not in (16, 24, 32) and "key length" in str(e): - return - raise e - try: - mac.verify(tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - - for tv in self.tv: - self.test_create_mac(tv) - self.test_verify_mac(tv) +if __name__ == "__main__": + import unittest -def get_tests(config={}): - global test_data - import types - from .common import make_mac_tests - - wycheproof_warnings = config.get('wycheproof_warnings') - - # Add new() parameters to the back of each test vector - params_test_data = [] - for row in test_data: - t = list(row) - t[4] = dict(ciphermod=t[4]) - params_test_data.append(t) - - tests = make_mac_tests(CMAC, "CMAC", params_test_data) - tests.append(ByteArrayTests()) - tests.append(list_test_cases(TestCMAC)) - tests.append(MemoryViewTests()) - tests += [ TestVectorsWycheproof(wycheproof_warnings) ] - return tests - - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_HMAC.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_HMAC.py index ecec1a8f..612527ee 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_HMAC.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_HMAC.py @@ -28,521 +28,584 @@ from binascii import hexlify from Cryptodome.Util.py3compat import tostr, tobytes -from Cryptodome.Hash import (HMAC, MD5, SHA1, SHA256, - SHA224, SHA384, SHA512, - RIPEMD160, - SHA3_224, SHA3_256, SHA3_384, SHA3_512) - - -hash_modules = dict(MD5=MD5, SHA1=SHA1, SHA256=SHA256, - SHA224=SHA224, SHA384=SHA384, SHA512=SHA512, - RIPEMD160=RIPEMD160, - SHA3_224=SHA3_224, SHA3_256=SHA3_256, - SHA3_384=SHA3_384, SHA3_512=SHA3_512) +from Cryptodome.Hash import ( + HMAC, + MD5, + SHA1, + SHA256, + SHA224, + SHA384, + SHA512, + RIPEMD160, + SHA3_224, + SHA3_256, + SHA3_384, + SHA3_512, +) + + +hash_modules = dict( + MD5=MD5, + SHA1=SHA1, + SHA256=SHA256, + SHA224=SHA224, + SHA384=SHA384, + SHA512=SHA512, + RIPEMD160=RIPEMD160, + SHA3_224=SHA3_224, + SHA3_256=SHA3_256, + SHA3_384=SHA3_384, + SHA3_512=SHA3_512, +) default_hash = None + def xl(text): - return tostr(hexlify(tobytes(text))) + return tostr(hexlify(tobytes(text))) + # This is a list of (key, data, results, description) tuples. test_data = [ - ## Test vectors from RFC 2202 ## - # Test that the default hashmod is MD5 - ('0b' * 16, - '4869205468657265', - dict(default_hash='9294727a3638bb1c13f48ef8158bfc9d'), - 'default-is-MD5'), - - # Test case 1 (MD5) - ('0b' * 16, - '4869205468657265', - dict(MD5='9294727a3638bb1c13f48ef8158bfc9d'), - 'RFC 2202 #1-MD5 (HMAC-MD5)'), - - # Test case 1 (SHA1) - ('0b' * 20, - '4869205468657265', - dict(SHA1='b617318655057264e28bc0b6fb378c8ef146be00'), - 'RFC 2202 #1-SHA1 (HMAC-SHA1)'), - - # Test case 2 - ('4a656665', - '7768617420646f2079612077616e7420666f72206e6f7468696e673f', - dict(MD5='750c783e6ab0b503eaa86e310a5db738', - SHA1='effcdf6ae5eb2fa2d27416d5f184df9c259a7c79'), - 'RFC 2202 #2 (HMAC-MD5/SHA1)'), - - # Test case 3 (MD5) - ('aa' * 16, - 'dd' * 50, - dict(MD5='56be34521d144c88dbb8c733f0e8b3f6'), - 'RFC 2202 #3-MD5 (HMAC-MD5)'), - - # Test case 3 (SHA1) - ('aa' * 20, - 'dd' * 50, - dict(SHA1='125d7342b9ac11cd91a39af48aa17b4f63f175d3'), - 'RFC 2202 #3-SHA1 (HMAC-SHA1)'), - - # Test case 4 - ('0102030405060708090a0b0c0d0e0f10111213141516171819', - 'cd' * 50, - dict(MD5='697eaf0aca3a3aea3a75164746ffaa79', - SHA1='4c9007f4026250c6bc8414f9bf50c86c2d7235da'), - 'RFC 2202 #4 (HMAC-MD5/SHA1)'), - - # Test case 5 (MD5) - ('0c' * 16, - '546573742057697468205472756e636174696f6e', - dict(MD5='56461ef2342edc00f9bab995690efd4c'), - 'RFC 2202 #5-MD5 (HMAC-MD5)'), - - # Test case 5 (SHA1) - # NB: We do not implement hash truncation, so we only test the full hash here. - ('0c' * 20, - '546573742057697468205472756e636174696f6e', - dict(SHA1='4c1a03424b55e07fe7f27be1d58bb9324a9a5a04'), - 'RFC 2202 #5-SHA1 (HMAC-SHA1)'), - - # Test case 6 - ('aa' * 80, - '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' - + '65204b6579202d2048617368204b6579204669727374', - dict(MD5='6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd', - SHA1='aa4ae5e15272d00e95705637ce8a3b55ed402112'), - 'RFC 2202 #6 (HMAC-MD5/SHA1)'), - - # Test case 7 - ('aa' * 80, - '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' - + '65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d' - + '53697a652044617461', - dict(MD5='6f630fad67cda0ee1fb1f562db3aa53e', - SHA1='e8e99d0f45237d786d6bbaa7965c7808bbff1a91'), - 'RFC 2202 #7 (HMAC-MD5/SHA1)'), - - ## Test vectors from RFC 4231 ## - # 4.2. Test Case 1 - ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', - '4869205468657265', - dict(SHA256=''' + ## Test vectors from RFC 2202 ## + # Test that the default hashmod is MD5 + ( + "0b" * 16, + "4869205468657265", + dict(default_hash="9294727a3638bb1c13f48ef8158bfc9d"), + "default-is-MD5", + ), + # Test case 1 (MD5) + ( + "0b" * 16, + "4869205468657265", + dict(MD5="9294727a3638bb1c13f48ef8158bfc9d"), + "RFC 2202 #1-MD5 (HMAC-MD5)", + ), + # Test case 1 (SHA1) + ( + "0b" * 20, + "4869205468657265", + dict(SHA1="b617318655057264e28bc0b6fb378c8ef146be00"), + "RFC 2202 #1-SHA1 (HMAC-SHA1)", + ), + # Test case 2 + ( + "4a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + dict( + MD5="750c783e6ab0b503eaa86e310a5db738", + SHA1="effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", + ), + "RFC 2202 #2 (HMAC-MD5/SHA1)", + ), + # Test case 3 (MD5) + ( + "aa" * 16, + "dd" * 50, + dict(MD5="56be34521d144c88dbb8c733f0e8b3f6"), + "RFC 2202 #3-MD5 (HMAC-MD5)", + ), + # Test case 3 (SHA1) + ( + "aa" * 20, + "dd" * 50, + dict(SHA1="125d7342b9ac11cd91a39af48aa17b4f63f175d3"), + "RFC 2202 #3-SHA1 (HMAC-SHA1)", + ), + # Test case 4 + ( + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "cd" * 50, + dict( + MD5="697eaf0aca3a3aea3a75164746ffaa79", + SHA1="4c9007f4026250c6bc8414f9bf50c86c2d7235da", + ), + "RFC 2202 #4 (HMAC-MD5/SHA1)", + ), + # Test case 5 (MD5) + ( + "0c" * 16, + "546573742057697468205472756e636174696f6e", + dict(MD5="56461ef2342edc00f9bab995690efd4c"), + "RFC 2202 #5-MD5 (HMAC-MD5)", + ), + # Test case 5 (SHA1) + # NB: We do not implement hash truncation, so we only test the full hash here. + ( + "0c" * 20, + "546573742057697468205472756e636174696f6e", + dict(SHA1="4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"), + "RFC 2202 #5-SHA1 (HMAC-SHA1)", + ), + # Test case 6 + ( + "aa" * 80, + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + + "65204b6579202d2048617368204b6579204669727374", + dict( + MD5="6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd", + SHA1="aa4ae5e15272d00e95705637ce8a3b55ed402112", + ), + "RFC 2202 #6 (HMAC-MD5/SHA1)", + ), + # Test case 7 + ( + "aa" * 80, + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + + "65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d" + + "53697a652044617461", + dict( + MD5="6f630fad67cda0ee1fb1f562db3aa53e", + SHA1="e8e99d0f45237d786d6bbaa7965c7808bbff1a91", + ), + "RFC 2202 #7 (HMAC-MD5/SHA1)", + ), + ## Test vectors from RFC 4231 ## + # 4.2. Test Case 1 + ( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4869205468657265", + dict( + SHA256=""" b0344c61d8db38535ca8afceaf0bf12b 881dc200c9833da726e9376c2e32cff7 - '''), - 'RFC 4231 #1 (HMAC-SHA256)'), - - # 4.3. Test Case 2 - Test with a key shorter than the length of the HMAC - # output. - ('4a656665', - '7768617420646f2079612077616e7420666f72206e6f7468696e673f', - dict(SHA256=''' + """, + ), + "RFC 4231 #1 (HMAC-SHA256)", + ), + # 4.3. Test Case 2 - Test with a key shorter than the length of the HMAC + # output. + ( + "4a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + dict( + SHA256=""" 5bdcc146bf60754e6a042426089575c7 5a003f089d2739839dec58b964ec3843 - '''), - 'RFC 4231 #2 (HMAC-SHA256)'), - - # 4.4. Test Case 3 - Test with a combined length of key and data that is - # larger than 64 bytes (= block-size of SHA-224 and SHA-256). - ('aa' * 20, - 'dd' * 50, - dict(SHA256=''' + """, + ), + "RFC 4231 #2 (HMAC-SHA256)", + ), + # 4.4. Test Case 3 - Test with a combined length of key and data that is + # larger than 64 bytes (= block-size of SHA-224 and SHA-256). + ( + "aa" * 20, + "dd" * 50, + dict( + SHA256=""" 773ea91e36800e46854db8ebd09181a7 2959098b3ef8c122d9635514ced565fe - '''), - 'RFC 4231 #3 (HMAC-SHA256)'), - - # 4.5. Test Case 4 - Test with a combined length of key and data that is - # larger than 64 bytes (= block-size of SHA-224 and SHA-256). - ('0102030405060708090a0b0c0d0e0f10111213141516171819', - 'cd' * 50, - dict(SHA256=''' + """, + ), + "RFC 4231 #3 (HMAC-SHA256)", + ), + # 4.5. Test Case 4 - Test with a combined length of key and data that is + # larger than 64 bytes (= block-size of SHA-224 and SHA-256). + ( + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "cd" * 50, + dict( + SHA256=""" 82558a389a443c0ea4cc819899f2083a 85f0faa3e578f8077a2e3ff46729665b - '''), - 'RFC 4231 #4 (HMAC-SHA256)'), - - # 4.6. Test Case 5 - Test with a truncation of output to 128 bits. - # - # Not included because we do not implement hash truncation. - # - - # 4.7. Test Case 6 - Test with a key larger than 128 bytes (= block-size of - # SHA-384 and SHA-512). - ('aa' * 131, - '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' - + '65204b6579202d2048617368204b6579204669727374', - dict(SHA256=''' + """, + ), + "RFC 4231 #4 (HMAC-SHA256)", + ), + # 4.6. Test Case 5 - Test with a truncation of output to 128 bits. + # + # Not included because we do not implement hash truncation. + # + # 4.7. Test Case 6 - Test with a key larger than 128 bytes (= block-size of + # SHA-384 and SHA-512). + ( + "aa" * 131, + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + + "65204b6579202d2048617368204b6579204669727374", + dict( + SHA256=""" 60e431591ee0b67f0d8a26aacbf5b77f 8e0bc6213728c5140546040f0ee37f54 - '''), - 'RFC 4231 #6 (HMAC-SHA256)'), - - # 4.8. Test Case 7 - Test with a key and data that is larger than 128 bytes - # (= block-size of SHA-384 and SHA-512). - ('aa' * 131, - '5468697320697320612074657374207573696e672061206c6172676572207468' - + '616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074' - + '68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565' - + '647320746f20626520686173686564206265666f7265206265696e6720757365' - + '642062792074686520484d414320616c676f726974686d2e', - dict(SHA256=''' + """, + ), + "RFC 4231 #6 (HMAC-SHA256)", + ), + # 4.8. Test Case 7 - Test with a key and data that is larger than 128 bytes + # (= block-size of SHA-384 and SHA-512). + ( + "aa" * 131, + "5468697320697320612074657374207573696e672061206c6172676572207468" + + "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + + "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + + "647320746f20626520686173686564206265666f7265206265696e6720757365" + + "642062792074686520484d414320616c676f726974686d2e", + dict( + SHA256=""" 9b09ffa71b942fcb27635fbcd5b0e944 bfdc63644f0713938a7f51535c3a35e2 - '''), - 'RFC 4231 #7 (HMAC-SHA256)'), - - # Test case 8 (SHA224) - ('4a656665', - '7768617420646f2079612077616e74' - + '20666f72206e6f7468696e673f', - dict(SHA224='a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44'), - 'RFC 4634 8.4 SHA224 (HMAC-SHA224)'), - - # Test case 9 (SHA384) - ('4a656665', - '7768617420646f2079612077616e74' - + '20666f72206e6f7468696e673f', - dict(SHA384='af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649'), - 'RFC 4634 8.4 SHA384 (HMAC-SHA384)'), - - # Test case 10 (SHA512) - ('4a656665', - '7768617420646f2079612077616e74' - + '20666f72206e6f7468696e673f', - dict(SHA512='164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'), - 'RFC 4634 8.4 SHA512 (HMAC-SHA512)'), - - # Test case 11 (RIPEMD) - ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', - xl("Hi There"), - dict(RIPEMD160='24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668'), - 'RFC 2286 #1 (HMAC-RIPEMD)'), - - # Test case 12 (RIPEMD) - (xl("Jefe"), - xl("what do ya want for nothing?"), - dict(RIPEMD160='dda6c0213a485a9e24f4742064a7f033b43c4069'), - 'RFC 2286 #2 (HMAC-RIPEMD)'), - - # Test case 13 (RIPEMD) - ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'dd' * 50, - dict(RIPEMD160='b0b105360de759960ab4f35298e116e295d8e7c1'), - 'RFC 2286 #3 (HMAC-RIPEMD)'), - - # Test case 14 (RIPEMD) - ('0102030405060708090a0b0c0d0e0f10111213141516171819', - 'cd' * 50, - dict(RIPEMD160='d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4'), - 'RFC 2286 #4 (HMAC-RIPEMD)'), - - # Test case 15 (RIPEMD) - ('0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c', - xl("Test With Truncation"), - dict(RIPEMD160='7619693978f91d90539ae786500ff3d8e0518e39'), - 'RFC 2286 #5 (HMAC-RIPEMD)'), - - # Test case 16 (RIPEMD) - ('aa' * 80, - xl("Test Using Larger Than Block-Size Key - Hash Key First"), - dict(RIPEMD160='6466ca07ac5eac29e1bd523e5ada7605b791fd8b'), - 'RFC 2286 #6 (HMAC-RIPEMD)'), - - # Test case 17 (RIPEMD) - ('aa' * 80, - xl("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"), - dict(RIPEMD160='69ea60798d71616cce5fd0871e23754cd75d5a0a'), - 'RFC 2286 #7 (HMAC-RIPEMD)'), - - # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-224.pdf - ( - '000102030405060708090a0b0c0d0e0f' - '101112131415161718191a1b', - xl('Sample message for keylenblocklen'), - dict(SHA3_224='078695eecc227c636ad31d063a15dd05a7e819a66ec6d8de1e193e59'), - 'NIST CSRC Sample #3 (SHA3-224)' - ), - - # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-256.pdf - ( - '000102030405060708090a0b0c0d0e0f'\ - '101112131415161718191a1b1c1d1e1f', - xl('Sample message for keylenblocklen'), - dict(SHA3_256='9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258'), - 'NIST CSRC Sample #3 (SHA3-256)' - ), - - # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-384.pdf - ( - '000102030405060708090a0b0c0d0e0f'\ - '101112131415161718191a1b1c1d1e1f' - '202122232425262728292a2b2c2d2e2f', - xl('Sample message for keylenblocklen'), - dict(SHA3_384='e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac'), - 'NIST CSRC Sample #3 (SHA3-384)' - ), - - # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-512.pdf - ( - '000102030405060708090a0b0c0d0e0f'\ - '101112131415161718191a1b1c1d1e1f'\ - '202122232425262728292a2b2c2d2e2f'\ - '303132333435363738393a3b3c3d3e3f', - xl('Sample message for keylenblocklen'), - dict(SHA3_512='5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d46b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915'), - 'NIST CSRC Sample #3 (SHA3-512)' - ), - + """, + ), + "RFC 4231 #7 (HMAC-SHA256)", + ), + # Test case 8 (SHA224) + ( + "4a656665", + "7768617420646f2079612077616e74" + "20666f72206e6f7468696e673f", + dict(SHA224="a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44"), + "RFC 4634 8.4 SHA224 (HMAC-SHA224)", + ), + # Test case 9 (SHA384) + ( + "4a656665", + "7768617420646f2079612077616e74" + "20666f72206e6f7468696e673f", + dict( + SHA384="af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649" + ), + "RFC 4634 8.4 SHA384 (HMAC-SHA384)", + ), + # Test case 10 (SHA512) + ( + "4a656665", + "7768617420646f2079612077616e74" + "20666f72206e6f7468696e673f", + dict( + SHA512="164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737" + ), + "RFC 4634 8.4 SHA512 (HMAC-SHA512)", + ), + # Test case 11 (RIPEMD) + ( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + xl("Hi There"), + dict(RIPEMD160="24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668"), + "RFC 2286 #1 (HMAC-RIPEMD)", + ), + # Test case 12 (RIPEMD) + ( + xl("Jefe"), + xl("what do ya want for nothing?"), + dict(RIPEMD160="dda6c0213a485a9e24f4742064a7f033b43c4069"), + "RFC 2286 #2 (HMAC-RIPEMD)", + ), + # Test case 13 (RIPEMD) + ( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "dd" * 50, + dict(RIPEMD160="b0b105360de759960ab4f35298e116e295d8e7c1"), + "RFC 2286 #3 (HMAC-RIPEMD)", + ), + # Test case 14 (RIPEMD) + ( + "0102030405060708090a0b0c0d0e0f10111213141516171819", + "cd" * 50, + dict(RIPEMD160="d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4"), + "RFC 2286 #4 (HMAC-RIPEMD)", + ), + # Test case 15 (RIPEMD) + ( + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + xl("Test With Truncation"), + dict(RIPEMD160="7619693978f91d90539ae786500ff3d8e0518e39"), + "RFC 2286 #5 (HMAC-RIPEMD)", + ), + # Test case 16 (RIPEMD) + ( + "aa" * 80, + xl("Test Using Larger Than Block-Size Key - Hash Key First"), + dict(RIPEMD160="6466ca07ac5eac29e1bd523e5ada7605b791fd8b"), + "RFC 2286 #6 (HMAC-RIPEMD)", + ), + # Test case 17 (RIPEMD) + ( + "aa" * 80, + xl("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"), + dict(RIPEMD160="69ea60798d71616cce5fd0871e23754cd75d5a0a"), + "RFC 2286 #7 (HMAC-RIPEMD)", + ), + # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-224.pdf + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b", + xl("Sample message for keylenblocklen"), + dict(SHA3_224="078695eecc227c636ad31d063a15dd05a7e819a66ec6d8de1e193e59"), + "NIST CSRC Sample #3 (SHA3-224)", + ), + # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-256.pdf + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + xl("Sample message for keylenblocklen"), + dict(SHA3_256="9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258"), + "NIST CSRC Sample #3 (SHA3-256)", + ), + # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-384.pdf + ( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + xl("Sample message for keylenblocklen"), + dict( + SHA3_384="e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac" + ), + "NIST CSRC Sample #3 (SHA3-384)", + ), + # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-512.pdf + ( + "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f", + xl("Sample message for keylenblocklen"), + dict( + SHA3_512="5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d46b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915" + ), + "NIST CSRC Sample #3 (SHA3-512)", + ), ] class HMAC_Module_and_Instance_Test(unittest.TestCase): - """Test the HMAC construction and verify that it does not - matter if you initialize it with a hash module or - with an hash instance. + """Test the HMAC construction and verify that it does not + matter if you initialize it with a hash module or + with an hash instance. - See https://bugs.launchpad.net/pycrypto/+bug/1209399 - """ + See https://bugs.launchpad.net/pycrypto/+bug/1209399 + """ - def __init__(self, hashmods): - """Initialize the test with a dictionary of hash modules - indexed by their names""" + def __init__(self, hashmods): + """Initialize the test with a dictionary of hash modules + indexed by their names""" - unittest.TestCase.__init__(self) - self.hashmods = hashmods - self.description = "" + unittest.TestCase.__init__(self) + self.hashmods = hashmods + self.description = "" - def shortDescription(self): - return self.description + def shortDescription(self): + return self.description - def runTest(self): - key = b"\x90\x91\x92\x93" * 4 - payload = b"\x00" * 100 + def runTest(self): + key = b"\x90\x91\x92\x93" * 4 + payload = b"\x00" * 100 - for hashname, hashmod in self.hashmods.items(): - if hashmod is None: - continue - self.description = "Test HMAC in combination with " + hashname - one = HMAC.new(key, payload, hashmod).digest() - two = HMAC.new(key, payload, hashmod.new()).digest() - self.assertEqual(one, two) + for hashname, hashmod in self.hashmods.items(): + if hashmod is None: + continue + self.description = "Test HMAC in combination with " + hashname + one = HMAC.new(key, payload, hashmod).digest() + two = HMAC.new(key, payload, hashmod.new()).digest() + self.assertEqual(one, two) class HMAC_None(unittest.TestCase): - - def runTest(self): - - key = b"\x04" * 20 - one = HMAC.new(key, b"", SHA1).digest() - two = HMAC.new(key, None, SHA1).digest() - self.assertEqual(one, two) + def runTest(self): + key = b"\x04" * 20 + one = HMAC.new(key, b"", SHA1).digest() + two = HMAC.new(key, None, SHA1).digest() + self.assertEqual(one, two) class ByteArrayTests(unittest.TestCase): + def runTest(self): + key = b"0" * 16 + data = b"\x00\x01\x02" - def runTest(self): - - key = b"0" * 16 - data = b"\x00\x01\x02" - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(key) + data_ba = bytearray(data) - h1 = HMAC.new(key, data) - h2 = HMAC.new(key_ba, data_ba) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = HMAC.new(key, data) + h2 = HMAC.new(key_ba, data_ba) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a bytearray (during operation) - key_ba = bytearray(key) - data_ba = bytearray(data) + # Data can be a bytearray (during operation) + key_ba = bytearray(key) + data_ba = bytearray(data) - h1 = HMAC.new(key) - h2 = HMAC.new(key) - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = HMAC.new(key) + h2 = HMAC.new(key) + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) class MemoryViewTests(unittest.TestCase): + def runTest(self): + key = b"0" * 16 + data = b"\x00\x01\x02" - def runTest(self): - - key = b"0" * 16 - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) + def get_mv_ro(data): + return memoryview(data) - for get_mv in (get_mv_ro, get_mv_rw): + def get_mv_rw(data): + return memoryview(bytearray(data)) - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(key) + data_mv = get_mv(data) - h1 = HMAC.new(key, data) - h2 = HMAC.new(key_mv, data_mv) - if not data_mv.readonly: - key_mv[:1] = b'\xFF' - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = HMAC.new(key, data) + h2 = HMAC.new(key_mv, data_mv) + if not data_mv.readonly: + key_mv[:1] = b"\xff" + data_mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) - # Data can be a memoryview (during operation) - data_mv = get_mv(data) + # Data can be a memoryview (during operation) + data_mv = get_mv(data) - h1 = HMAC.new(key) - h2 = HMAC.new(key) - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) + h1 = HMAC.new(key) + h2 = HMAC.new(key) + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + self.assertEqual(h1.digest(), h2.digest()) def get_tests(config={}): - global test_data - import types - from .common import make_mac_tests - - # A test vector contains multiple results, each one for a - # different hash algorithm. - # Here we expand each test vector into multiple ones, - # and add the relevant parameters that will be passed to new() - exp_test_data = [] - for row in test_data: - for modname in row[2].keys(): - t = list(row) - t[2] = row[2][modname] - t.append(dict(digestmod=globals()[modname])) - exp_test_data.append(t) - tests = make_mac_tests(HMAC, "HMAC", exp_test_data) - tests.append(HMAC_Module_and_Instance_Test(hash_modules)) - tests.append(HMAC_None()) - - tests.append(ByteArrayTests()) - tests.append(MemoryViewTests()) - - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + global test_data + from .common import make_mac_tests + + # A test vector contains multiple results, each one for a + # different hash algorithm. + # Here we expand each test vector into multiple ones, + # and add the relevant parameters that will be passed to new() + exp_test_data = [] + for row in test_data: + for modname in row[2].keys(): + t = list(row) + t[2] = row[2][modname] + t.append(dict(digestmod=globals()[modname])) + exp_test_data.append(t) + tests = make_mac_tests(HMAC, "HMAC", exp_test_data) + tests.append(HMAC_Module_and_Instance_Test(hash_modules)) + tests.append(HMAC_None()) + + tests.append(ByteArrayTests()) + tests.append(MemoryViewTests()) + + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_KMAC.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_KMAC.py index 0543a4c0..7f2b4e50 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_KMAC.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_KMAC.py @@ -9,338 +9,333 @@ class KMACTest(unittest.TestCase): + def new(self, *args, **kwargs): + return self.KMAC.new(key=b"X" * (self.minimum_key_bits // 8), *args, **kwargs) + + def test_new_positive(self): + key = b"X" * 32 + + h = self.new() + for new_func in self.KMAC.new, h.new: + for dbytes in range(self.minimum_bytes, 128 + 1): + hobj = new_func(key=key, mac_len=dbytes) + self.assertEqual(hobj.digest_size, dbytes) + + digest1 = new_func(key=key, data=b"\x90").digest() + digest2 = new_func(key=key).update(b"\x90").digest() + self.assertEqual(digest1, digest2) + + new_func(data=b"A", key=key, custom=b"g") + + hobj = h.new(key=key) + self.assertEqual(hobj.digest_size, self.default_bytes) + + def test_new_negative(self): + h = self.new() + for new_func in self.KMAC.new, h.new: + self.assertRaises( + ValueError, + new_func, + key=b"X" * 32, + mac_len=0, + ) + self.assertRaises( + ValueError, + new_func, + key=b"X" * 32, + mac_len=self.minimum_bytes - 1, + ) + self.assertRaises( + TypeError, + new_func, + key="string", + ) + self.assertRaises( + TypeError, + new_func, + data="string", + ) + + def test_default_digest_size(self): + digest = self.new(data=b"abc").digest() + self.assertEqual(len(digest), self.default_bytes) + + def test_update(self): + pieces = [b"\x0a" * 200, b"\x14" * 300] + h = self.new() + h.update(pieces[0]).update(pieces[1]) + digest = h.digest() + h = self.new() + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.digest(), digest) + + def test_update_negative(self): + h = self.new() + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = self.new() + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b"digest"))) + + def test_update_after_digest(self): + msg = b"rrrrttt" + + # Normally, update() cannot be done after digest() + h = self.new(mac_len=32, data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, dig1) + + def test_hex_digest(self): + mac = self.new() + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_verify(self): + h = self.new() + mac = h.digest() + h.verify(mac) + wrong_mac = strxor_c(mac, 255) + self.assertRaises(ValueError, h.verify, wrong_mac) + + def test_hexverify(self): + h = self.new() + mac = h.hexdigest() + h.hexverify(mac) + self.assertRaises(ValueError, h.hexverify, "4556") + + def test_oid(self): + oid = "2.16.840.1.101.3.4.2." + self.oid_variant + h = self.new() + self.assertEqual(h.oid, oid) + + def test_bytearray(self): + key = b"0" * 32 + data = b"\x00\x01\x02" + + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(key) + data_ba = bytearray(data) + + h1 = self.KMAC.new(data=data, key=key) + h2 = self.KMAC.new(data=data_ba, key=key_ba) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + # Data can be a bytearray (during operation) + data_ba = bytearray(data) + + h1 = self.new() + h2 = self.new() + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + def test_memoryview(self): + key = b"0" * 32 + data = b"\x00\x01\x02" + + def get_mv_ro(data): + return memoryview(data) + + def get_mv_rw(data): + return memoryview(bytearray(data)) + + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(key) + data_mv = get_mv(data) + + h1 = self.KMAC.new(data=data, key=key) + h2 = self.KMAC.new(data=data_mv, key=key_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + key_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) - def new(self, *args, **kwargs): - return self.KMAC.new(key=b'X' * (self.minimum_key_bits // 8), *args, **kwargs) - - def test_new_positive(self): - - key = b'X' * 32 - - h = self.new() - for new_func in self.KMAC.new, h.new: + # Data can be a memoryview (during operation) + data_mv = get_mv(data) - for dbytes in range(self.minimum_bytes, 128 + 1): - hobj = new_func(key=key, mac_len=dbytes) - self.assertEqual(hobj.digest_size, dbytes) - - digest1 = new_func(key=key, data=b"\x90").digest() - digest2 = new_func(key=key).update(b"\x90").digest() - self.assertEqual(digest1, digest2) - - new_func(data=b"A", key=key, custom=b"g") - - hobj = h.new(key=key) - self.assertEqual(hobj.digest_size, self.default_bytes) - - def test_new_negative(self): - - h = self.new() - for new_func in self.KMAC.new, h.new: - self.assertRaises(ValueError, new_func, key=b'X'*32, - mac_len=0) - self.assertRaises(ValueError, new_func, key=b'X'*32, - mac_len=self.minimum_bytes - 1) - self.assertRaises(TypeError, new_func, - key=u"string") - self.assertRaises(TypeError, new_func, - data=u"string") - - def test_default_digest_size(self): - digest = self.new(data=b'abc').digest() - self.assertEqual(len(digest), self.default_bytes) - - def test_update(self): - pieces = [b"\x0A" * 200, b"\x14" * 300] - h = self.new() - h.update(pieces[0]).update(pieces[1]) - digest = h.digest() - h = self.new() - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.digest(), digest) - - def test_update_negative(self): - h = self.new() - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = self.new() - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg = b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = self.new(mac_len=32, data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, dig1) - - def test_hex_digest(self): - mac = self.new() - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_verify(self): - h = self.new() - mac = h.digest() - h.verify(mac) - wrong_mac = strxor_c(mac, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - - def test_hexverify(self): - h = self.new() - mac = h.hexdigest() - h.hexverify(mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - def test_oid(self): - - oid = "2.16.840.1.101.3.4.2." + self.oid_variant - h = self.new() - self.assertEqual(h.oid, oid) - - def test_bytearray(self): - - key = b'0' * 32 - data = b"\x00\x01\x02" - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) - - h1 = self.KMAC.new(data=data, key=key) - h2 = self.KMAC.new(data=data_ba, key=key_ba) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = self.new() - h2 = self.new() - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - key = b'0' * 32 - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) - - h1 = self.KMAC.new(data=data, key=key) - h2 = self.KMAC.new(data=data_mv, key=key_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - key_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = self.new() - h2 = self.new() - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) + h1 = self.new() + h2 = self.new() + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) class KMAC128Test(KMACTest): + KMAC = KMAC128 - KMAC = KMAC128 - - minimum_key_bits = 128 + minimum_key_bits = 128 - minimum_bytes = 8 - default_bytes = 64 + minimum_bytes = 8 + default_bytes = 64 - oid_variant = "19" + oid_variant = "19" class KMAC256Test(KMACTest): + KMAC = KMAC256 - KMAC = KMAC256 + minimum_key_bits = 256 - minimum_key_bits = 256 + minimum_bytes = 8 + default_bytes = 64 - minimum_bytes = 8 - default_bytes = 64 - - oid_variant = "20" + oid_variant = "20" class NISTExampleTestVectors(unittest.TestCase): - - # https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf - test_data = [ - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03", - "", - "E5 78 0B 0D 3E A6 F7 D3 A4 29 C5 70 6A A4 3A 00" - "FA DB D7 D4 96 28 83 9E 31 87 24 3F 45 6E E1 4E", - "Sample #1 NIST", - KMAC128 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03", - "My Tagged Application", - "3B 1F BA 96 3C D8 B0 B5 9E 8C 1A 6D 71 88 8B 71" - "43 65 1A F8 BA 0A 70 70 C0 97 9E 28 11 32 4A A5", - "Sample #2 NIST", - KMAC128 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" - "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" - "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" - "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" - "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" - "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" - "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" - "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" - "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" - "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" - "C0 C1 C2 C3 C4 C5 C6 C7", - "My Tagged Application", - "1F 5B 4E 6C CA 02 20 9E 0D CB 5C A6 35 B8 9A 15" - "E2 71 EC C7 60 07 1D FD 80 5F AA 38 F9 72 92 30", - "Sample #3 NIST", - KMAC128 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03", - "My Tagged Application", - "20 C5 70 C3 13 46 F7 03 C9 AC 36 C6 1C 03 CB 64" - "C3 97 0D 0C FC 78 7E 9B 79 59 9D 27 3A 68 D2 F7" - "F6 9D 4C C3 DE 9D 10 4A 35 16 89 F2 7C F6 F5 95" - "1F 01 03 F3 3F 4F 24 87 10 24 D9 C2 77 73 A8 DD", - "Sample #4 NIST", - KMAC256 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" - "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" - "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" - "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" - "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" - "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" - "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" - "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" - "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" - "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" - "C0 C1 C2 C3 C4 C5 C6 C7", - "", - "75 35 8C F3 9E 41 49 4E 94 97 07 92 7C EE 0A F2" - "0A 3F F5 53 90 4C 86 B0 8F 21 CC 41 4B CF D6 91" - "58 9D 27 CF 5E 15 36 9C BB FF 8B 9A 4C 2E B1 78" - "00 85 5D 02 35 FF 63 5D A8 25 33 EC 6B 75 9B 69", - "Sample #5 NIST", - KMAC256 - ), - ( - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", - "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" - "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" - "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" - "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" - "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" - "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" - "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" - "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" - "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" - "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" - "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" - "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" - "C0 C1 C2 C3 C4 C5 C6 C7", - "My Tagged Application", - "B5 86 18 F7 1F 92 E1 D5 6C 1B 8C 55 DD D7 CD 18" - "8B 97 B4 CA 4D 99 83 1E B2 69 9A 83 7D A2 E4 D9" - "70 FB AC FD E5 00 33 AE A5 85 F1 A2 70 85 10 C3" - "2D 07 88 08 01 BD 18 28 98 FE 47 68 76 FC 89 65", - "Sample #6 NIST", - KMAC256 - ), - ] - - def setUp(self): - td = [] - for key, data, custom, mac, text, module in self.test_data: - ni = ( - unhexlify(key.replace(" ", "")), - unhexlify(data.replace(" ", "")), - custom.encode(), - unhexlify(mac.replace(" ", "")), - text, - module - ) - td.append(ni) - self.test_data = td - - def runTest(self): - - for key, data, custom, mac, text, module in self.test_data: - h = module.new(data=data, key=key, custom=custom, mac_len=len(mac)) - mac_tag = h.digest() - self.assertEqual(mac_tag, mac, msg=text) + # https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf + test_data = [ + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03", + "", + "E5 78 0B 0D 3E A6 F7 D3 A4 29 C5 70 6A A4 3A 00FA DB D7 D4 96 28 83 9E 31 87 24 3F 45 6E E1 4E", + "Sample #1 NIST", + KMAC128, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03", + "My Tagged Application", + "3B 1F BA 96 3C D8 B0 B5 9E 8C 1A 6D 71 88 8B 7143 65 1A F8 BA 0A 70 70 C0 97 9E 28 11 32 4A A5", + "Sample #2 NIST", + KMAC128, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" + "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" + "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" + "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" + "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" + "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" + "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" + "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" + "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" + "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" + "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" + "C0 C1 C2 C3 C4 C5 C6 C7", + "My Tagged Application", + "1F 5B 4E 6C CA 02 20 9E 0D CB 5C A6 35 B8 9A 15E2 71 EC C7 60 07 1D FD 80 5F AA 38 F9 72 92 30", + "Sample #3 NIST", + KMAC128, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03", + "My Tagged Application", + "20 C5 70 C3 13 46 F7 03 C9 AC 36 C6 1C 03 CB 64" + "C3 97 0D 0C FC 78 7E 9B 79 59 9D 27 3A 68 D2 F7" + "F6 9D 4C C3 DE 9D 10 4A 35 16 89 F2 7C F6 F5 95" + "1F 01 03 F3 3F 4F 24 87 10 24 D9 C2 77 73 A8 DD", + "Sample #4 NIST", + KMAC256, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" + "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" + "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" + "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" + "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" + "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" + "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" + "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" + "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" + "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" + "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" + "C0 C1 C2 C3 C4 C5 C6 C7", + "", + "75 35 8C F3 9E 41 49 4E 94 97 07 92 7C EE 0A F2" + "0A 3F F5 53 90 4C 86 B0 8F 21 CC 41 4B CF D6 91" + "58 9D 27 CF 5E 15 36 9C BB FF 8B 9A 4C 2E B1 78" + "00 85 5D 02 35 FF 63 5D A8 25 33 EC 6B 75 9B 69", + "Sample #5 NIST", + KMAC256, + ), + ( + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F", + "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" + "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" + "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F" + "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F" + "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F" + "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F" + "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F" + "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F" + "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" + "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" + "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" + "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" + "C0 C1 C2 C3 C4 C5 C6 C7", + "My Tagged Application", + "B5 86 18 F7 1F 92 E1 D5 6C 1B 8C 55 DD D7 CD 18" + "8B 97 B4 CA 4D 99 83 1E B2 69 9A 83 7D A2 E4 D9" + "70 FB AC FD E5 00 33 AE A5 85 F1 A2 70 85 10 C3" + "2D 07 88 08 01 BD 18 28 98 FE 47 68 76 FC 89 65", + "Sample #6 NIST", + KMAC256, + ), + ] + + def setUp(self): + td = [] + for key, data, custom, mac, text, module in self.test_data: + ni = ( + unhexlify(key.replace(" ", "")), + unhexlify(data.replace(" ", "")), + custom.encode(), + unhexlify(mac.replace(" ", "")), + text, + module, + ) + td.append(ni) + self.test_data = td + + def runTest(self): + for key, data, custom, mac, text, module in self.test_data: + h = module.new(data=data, key=key, custom=custom, mac_len=len(mac)) + mac_tag = h.digest() + self.assertEqual(mac_tag, mac, msg=text) def get_tests(config={}): - tests = [] + tests = [] + + tests += list_test_cases(KMAC128Test) + tests += list_test_cases(KMAC256Test) + tests.append(NISTExampleTestVectors()) + + return tests - tests += list_test_cases(KMAC128Test) - tests += list_test_cases(KMAC256Test) - tests.append(NISTExampleTestVectors()) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_KangarooTwelve.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_KangarooTwelve.py index c9ad363e..59203e48 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_KangarooTwelve.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_KangarooTwelve.py @@ -36,332 +36,331 @@ class KangarooTwelveTest(unittest.TestCase): - - def test_length_encode(self): - self.assertEqual(K12._length_encode(0), b'\x00') - self.assertEqual(K12._length_encode(12), b'\x0C\x01') - self.assertEqual(K12._length_encode(65538), b'\x01\x00\x02\x03') - - def test_new_positive(self): - - xof1 = K12.new() - xof2 = K12.new(data=b("90")) - xof3 = K12.new().update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - xof1 = K12.new() - ref = xof1.read(10) - xof2 = K12.new(custom=b("")) - xof3 = K12.new(custom=b("foo")) - - self.assertEqual(ref, xof2.read(10)) - self.assertNotEqual(ref, xof3.read(10)) - - xof1 = K12.new(custom=b("foo")) - xof2 = K12.new(custom=b("foo"), data=b("90")) - xof3 = K12.new(custom=b("foo")).update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = K12.new() - h.update(pieces[0]).update(pieces[1]) - digest = h.read(10) - h = K12.new() - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.read(10), digest) - - def test_update_negative(self): - h = K12.new() - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = K12.new() - digest = h.read(90) - - # read returns a byte string of the right length - self.assertTrue(isinstance(digest, type(b("digest")))) - self.assertEqual(len(digest), 90) - - def test_update_after_read(self): - mac = K12.new() - mac.update(b("rrrr")) - mac.read(90) - self.assertRaises(TypeError, mac.update, b("ttt")) + def test_length_encode(self): + self.assertEqual(K12._length_encode(0), b"\x00") + self.assertEqual(K12._length_encode(12), b"\x0c\x01") + self.assertEqual(K12._length_encode(65538), b"\x01\x00\x02\x03") + + def test_new_positive(self): + xof1 = K12.new() + xof2 = K12.new(data=b("90")) + xof3 = K12.new().update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + xof1 = K12.new() + ref = xof1.read(10) + xof2 = K12.new(custom=b("")) + xof3 = K12.new(custom=b("foo")) + + self.assertEqual(ref, xof2.read(10)) + self.assertNotEqual(ref, xof3.read(10)) + + xof1 = K12.new(custom=b("foo")) + xof2 = K12.new(custom=b("foo"), data=b("90")) + xof3 = K12.new(custom=b("foo")).update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] + h = K12.new() + h.update(pieces[0]).update(pieces[1]) + digest = h.read(10) + h = K12.new() + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.read(10), digest) + + def test_update_negative(self): + h = K12.new() + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = K12.new() + digest = h.read(90) + + # read returns a byte string of the right length + self.assertTrue(isinstance(digest, type(b("digest")))) + self.assertEqual(len(digest), 90) + + def test_update_after_read(self): + mac = K12.new() + mac.update(b("rrrr")) + mac.read(90) + self.assertRaises(TypeError, mac.update, b("ttt")) def txt2bin(txt): - clean = txt.replace(" ", "").replace("\n", "").replace("\r", "") - return unhexlify(clean) + clean = txt.replace(" ", "").replace("\n", "").replace("\r", "") + return unhexlify(clean) def ptn(n): - res = bytearray(n) - pattern = b"".join([bchr(x) for x in range(0, 0xFB)]) - for base in range(0, n - 0xFB, 0xFB): - res[base:base + 0xFB] = pattern - remain = n % 0xFB - if remain: - base = (n // 0xFB) * 0xFB - res[base:] = pattern[:remain] - assert(len(res) == n) - return res + res = bytearray(n) + pattern = b"".join([bchr(x) for x in range(0, 0xFB)]) + for base in range(0, n - 0xFB, 0xFB): + res[base : base + 0xFB] = pattern + remain = n % 0xFB + if remain: + base = (n // 0xFB) * 0xFB + res[base:] = pattern[:remain] + assert len(res) == n + return res def chunked(source, size): - for i in range(0, len(source), size): - yield source[i:i+size] + for i in range(0, len(source), size): + yield source[i : i + size] class KangarooTwelveTV(unittest.TestCase): + # https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KangarooTwelve.txt - # https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KangarooTwelve.txt - - def test_zero_1(self): - tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51 + def test_zero_1(self): + tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51 3C 08 03 57 7A C7 16 7F 06 FE 2C E1 F0 EF 39 E5""" - btv = txt2bin(tv) - res = K12.new().read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new().read(32) + self.assertEqual(res, btv) - def test_zero_2(self): - tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51 + def test_zero_2(self): + tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51 3C 08 03 57 7A C7 16 7F 06 FE 2C E1 F0 EF 39 E5 42 69 C0 56 B8 C8 2E 48 27 60 38 B6 D2 92 96 6C C0 7A 3D 46 45 27 2E 31 FF 38 50 81 39 EB 0A 71""" - btv = txt2bin(tv) - res = K12.new().read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new().read(64) + self.assertEqual(res, btv) - def test_zero_3(self): - tv = """E8 DC 56 36 42 F7 22 8C 84 68 4C 89 84 05 D3 A8 + def test_zero_3(self): + tv = """E8 DC 56 36 42 F7 22 8C 84 68 4C 89 84 05 D3 A8 34 79 91 58 C0 79 B1 28 80 27 7A 1D 28 E2 FF 6D""" - btv = txt2bin(tv) - res = K12.new().read(10032) - self.assertEqual(res[-32:], btv) + btv = txt2bin(tv) + res = K12.new().read(10032) + self.assertEqual(res[-32:], btv) - def test_ptn_1(self): - tv = """2B DA 92 45 0E 8B 14 7F 8A 7C B6 29 E7 84 A0 58 + def test_ptn_1(self): + tv = """2B DA 92 45 0E 8B 14 7F 8A 7C B6 29 E7 84 A0 58 EF CA 7C F7 D8 21 8E 02 D3 45 DF AA 65 24 4A 1F""" - btv = txt2bin(tv) - res = K12.new(data=ptn(1)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=ptn(1)).read(32) + self.assertEqual(res, btv) - def test_ptn_17(self): - tv = """6B F7 5F A2 23 91 98 DB 47 72 E3 64 78 F8 E1 9B + def test_ptn_17(self): + tv = """6B F7 5F A2 23 91 98 DB 47 72 E3 64 78 F8 E1 9B 0F 37 12 05 F6 A9 A9 3A 27 3F 51 DF 37 12 28 88""" - btv = txt2bin(tv) - res = K12.new(data=ptn(17)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=ptn(17)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_2(self): - tv = """0C 31 5E BC DE DB F6 14 26 DE 7D CF 8F B7 25 D1 + def test_ptn_17_2(self): + tv = """0C 31 5E BC DE DB F6 14 26 DE 7D CF 8F B7 25 D1 E7 46 75 D7 F5 32 7A 50 67 F3 67 B1 08 EC B6 7C""" - btv = txt2bin(tv) - res = K12.new(data=ptn(17**2)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=ptn(17**2)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_3(self): - tv = """CB 55 2E 2E C7 7D 99 10 70 1D 57 8B 45 7D DF 77 + def test_ptn_17_3(self): + tv = """CB 55 2E 2E C7 7D 99 10 70 1D 57 8B 45 7D DF 77 2C 12 E3 22 E4 EE 7F E4 17 F9 2C 75 8F 0D 59 D0""" - btv = txt2bin(tv) - res = K12.new(data=ptn(17**3)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=ptn(17**3)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_4(self): - tv = """87 01 04 5E 22 20 53 45 FF 4D DA 05 55 5C BB 5C + def test_ptn_17_4(self): + tv = """87 01 04 5E 22 20 53 45 FF 4D DA 05 55 5C BB 5C 3A F1 A7 71 C2 B8 9B AE F3 7D B4 3D 99 98 B9 FE""" - btv = txt2bin(tv) - data = ptn(17**4) - - # All at once - res = K12.new(data=data).read(32) - self.assertEqual(res, btv) - - # Byte by byte - k12 = K12.new() - for x in data: - k12.update(bchr(x)) - res = k12.read(32) - self.assertEqual(res, btv) - - # Chunks of various prime sizes - for chunk_size in (13, 17, 19, 23, 31): - k12 = K12.new() - for x in chunked(data, chunk_size): - k12.update(x) - res = k12.read(32) - self.assertEqual(res, btv) - - def test_ptn_17_5(self): - tv = """84 4D 61 09 33 B1 B9 96 3C BD EB 5A E3 B6 B0 5C + btv = txt2bin(tv) + data = ptn(17**4) + + # All at once + res = K12.new(data=data).read(32) + self.assertEqual(res, btv) + + # Byte by byte + k12 = K12.new() + for x in data: + k12.update(bchr(x)) + res = k12.read(32) + self.assertEqual(res, btv) + + # Chunks of various prime sizes + for chunk_size in (13, 17, 19, 23, 31): + k12 = K12.new() + for x in chunked(data, chunk_size): + k12.update(x) + res = k12.read(32) + self.assertEqual(res, btv) + + def test_ptn_17_5(self): + tv = """84 4D 61 09 33 B1 B9 96 3C BD EB 5A E3 B6 B0 5C C7 CB D6 7C EE DF 88 3E B6 78 A0 A8 E0 37 16 82""" - btv = txt2bin(tv) - data = ptn(17**5) + btv = txt2bin(tv) + data = ptn(17**5) - # All at once - res = K12.new(data=data).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=data).read(32) + self.assertEqual(res, btv) - # Chunks - k12 = K12.new() - for chunk in chunked(data, 8192): - k12.update(chunk) - res = k12.read(32) - self.assertEqual(res, btv) + # Chunks + k12 = K12.new() + for chunk in chunked(data, 8192): + k12.update(chunk) + res = k12.read(32) + self.assertEqual(res, btv) - def test_ptn_17_6(self): - tv = """3C 39 07 82 A8 A4 E8 9F A6 36 7F 72 FE AA F1 32 + def test_ptn_17_6(self): + tv = """3C 39 07 82 A8 A4 E8 9F A6 36 7F 72 FE AA F1 32 55 C8 D9 58 78 48 1D 3C D8 CE 85 F5 8E 88 0A F8""" - btv = txt2bin(tv) - data = ptn(17**6) + btv = txt2bin(tv) + data = ptn(17**6) - # All at once - res = K12.new(data=data).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=data).read(32) + self.assertEqual(res, btv) - def test_ptn_c_1(self): - tv = """FA B6 58 DB 63 E9 4A 24 61 88 BF 7A F6 9A 13 30 + def test_ptn_c_1(self): + tv = """FA B6 58 DB 63 E9 4A 24 61 88 BF 7A F6 9A 13 30 45 F4 6E E9 84 C5 6E 3C 33 28 CA AF 1A A1 A5 83""" - btv = txt2bin(tv) - custom = ptn(1) + btv = txt2bin(tv) + custom = ptn(1) - # All at once - res = K12.new(custom=custom).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(custom=custom).read(32) + self.assertEqual(res, btv) - def test_ptn_c_41(self): - tv = """D8 48 C5 06 8C ED 73 6F 44 62 15 9B 98 67 FD 4C + def test_ptn_c_41(self): + tv = """D8 48 C5 06 8C ED 73 6F 44 62 15 9B 98 67 FD 4C 20 B8 08 AC C3 D5 BC 48 E0 B0 6B A0 A3 76 2E C4""" - btv = txt2bin(tv) - custom = ptn(41) + btv = txt2bin(tv) + custom = ptn(41) - # All at once - res = K12.new(data=b'\xFF', custom=custom).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=b"\xff", custom=custom).read(32) + self.assertEqual(res, btv) - def test_ptn_c_41_2(self): - tv = """C3 89 E5 00 9A E5 71 20 85 4C 2E 8C 64 67 0A C0 + def test_ptn_c_41_2(self): + tv = """C3 89 E5 00 9A E5 71 20 85 4C 2E 8C 64 67 0A C0 13 58 CF 4C 1B AF 89 44 7A 72 42 34 DC 7C ED 74""" - btv = txt2bin(tv) - custom = ptn(41**2) + btv = txt2bin(tv) + custom = ptn(41**2) - # All at once - res = K12.new(data=b'\xFF' * 3, custom=custom).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=b"\xff" * 3, custom=custom).read(32) + self.assertEqual(res, btv) - def test_ptn_c_41_3(self): - tv = """75 D2 F8 6A 2E 64 45 66 72 6B 4F BC FC 56 57 B9 + def test_ptn_c_41_3(self): + tv = """75 D2 F8 6A 2E 64 45 66 72 6B 4F BC FC 56 57 B9 DB CF 07 0C 7B 0D CA 06 45 0A B2 91 D7 44 3B CF""" - btv = txt2bin(tv) - custom = ptn(41**3) + btv = txt2bin(tv) + custom = ptn(41**3) - # All at once - res = K12.new(data=b'\xFF' * 7, custom=custom).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=b"\xff" * 7, custom=custom).read(32) + self.assertEqual(res, btv) - # https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/ + # https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/ - def test_ptn_8191(self): - tv = """1B 57 76 36 F7 23 64 3E 99 0C C7 D6 A6 59 83 74 + def test_ptn_8191(self): + tv = """1B 57 76 36 F7 23 64 3E 99 0C C7 D6 A6 59 83 74 36 FD 6A 10 36 26 60 0E B8 30 1C D1 DB E5 53 D6""" - btv = txt2bin(tv) + btv = txt2bin(tv) - # All at once - res = K12.new(data=ptn(8191)).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=ptn(8191)).read(32) + self.assertEqual(res, btv) - def test_ptn_8192(self): - tv = """48 F2 56 F6 77 2F 9E DF B6 A8 B6 61 EC 92 DC 93 + def test_ptn_8192(self): + tv = """48 F2 56 F6 77 2F 9E DF B6 A8 B6 61 EC 92 DC 93 B9 5E BD 05 A0 8A 17 B3 9A E3 49 08 70 C9 26 C3""" - btv = txt2bin(tv) + btv = txt2bin(tv) - # All at once - res = K12.new(data=ptn(8192)).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=ptn(8192)).read(32) + self.assertEqual(res, btv) - def test_ptn_8192_8189(self): - tv = """3E D1 2F 70 FB 05 DD B5 86 89 51 0A B3 E4 D2 3C + def test_ptn_8192_8189(self): + tv = """3E D1 2F 70 FB 05 DD B5 86 89 51 0A B3 E4 D2 3C 6C 60 33 84 9A A0 1E 1D 8C 22 0A 29 7F ED CD 0B""" - btv = txt2bin(tv) + btv = txt2bin(tv) - # All at once - res = K12.new(data=ptn(8192), custom=ptn(8189)).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=ptn(8192), custom=ptn(8189)).read(32) + self.assertEqual(res, btv) - def test_ptn_8192_8190(self): - tv = """6A 7C 1B 6A 5C D0 D8 C9 CA 94 3A 4A 21 6C C6 46 + def test_ptn_8192_8190(self): + tv = """6A 7C 1B 6A 5C D0 D8 C9 CA 94 3A 4A 21 6C C6 46 04 55 9A 2E A4 5F 78 57 0A 15 25 3D 67 BA 00 AE""" - btv = txt2bin(tv) + btv = txt2bin(tv) - # All at once - res = K12.new(data=ptn(8192), custom=ptn(8190)).read(32) - self.assertEqual(res, btv) + # All at once + res = K12.new(data=ptn(8192), custom=ptn(8190)).read(32) + self.assertEqual(res, btv) - ### + ### - def test_1(self): - tv = "fd608f91d81904a9916e78a18f65c157a78d63f93d8f6367db0524526a5ea2bb" + def test_1(self): + tv = "fd608f91d81904a9916e78a18f65c157a78d63f93d8f6367db0524526a5ea2bb" - btv = txt2bin(tv) - res = K12.new(data=b'', custom=ptn(100)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = K12.new(data=b"", custom=ptn(100)).read(32) + self.assertEqual(res, btv) - def test_2(self): - tv4 = "5a4ec9a649f81916d4ce1553492962f7868abf8dd1ceb2f0cb3682ea95cda6a6" - tv3 = "441688fe4fe4ae9425eb3105eb445eb2b3a6f67b66eff8e74ebfbc49371f6d4c" - tv2 = "17269a57759af0214c84a0fd9bc851f4d95f80554cfed4e7da8a6ee1ff080131" - tv1 = "33826990c09dc712ba7224f0d9be319e2720de95a4c1afbd2211507dae1c703a" - tv0 = "9f4d3aba908ddc096e4d3a71da954f917b9752f05052b9d26d916a6fbc75bf3e" + def test_2(self): + tv4 = "5a4ec9a649f81916d4ce1553492962f7868abf8dd1ceb2f0cb3682ea95cda6a6" + tv3 = "441688fe4fe4ae9425eb3105eb445eb2b3a6f67b66eff8e74ebfbc49371f6d4c" + tv2 = "17269a57759af0214c84a0fd9bc851f4d95f80554cfed4e7da8a6ee1ff080131" + tv1 = "33826990c09dc712ba7224f0d9be319e2720de95a4c1afbd2211507dae1c703a" + tv0 = "9f4d3aba908ddc096e4d3a71da954f917b9752f05052b9d26d916a6fbc75bf3e" - res = K12.new(data=b'A' * (8192 - 4), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv4)) + res = K12.new(data=b"A" * (8192 - 4), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv4)) - res = K12.new(data=b'A' * (8192 - 3), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv3)) + res = K12.new(data=b"A" * (8192 - 3), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv3)) - res = K12.new(data=b'A' * (8192 - 2), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv2)) + res = K12.new(data=b"A" * (8192 - 2), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv2)) - res = K12.new(data=b'A' * (8192 - 1), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv1)) + res = K12.new(data=b"A" * (8192 - 1), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv1)) - res = K12.new(data=b'A' * (8192 - 0), custom=b'B').read(32) - self.assertEqual(res, txt2bin(tv0)) + res = K12.new(data=b"A" * (8192 - 0), custom=b"B").read(32) + self.assertEqual(res, txt2bin(tv0)) def get_tests(config={}): - tests = [] - tests += list_test_cases(KangarooTwelveTest) - tests += list_test_cases(KangarooTwelveTV) - return tests + tests = [] + tests += list_test_cases(KangarooTwelveTest) + tests += list_test_cases(KangarooTwelveTV) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD2.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD2.py index beae38aa..0737ae8c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD2.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD2.py @@ -28,35 +28,46 @@ # This is a list of (expected_result, input[, description]) tuples. test_data = [ - # Test vectors from RFC 1319 - ('8350e5a3e24c153df2275c9f80692773', '', "'' (empty string)"), - ('32ec01ec4a6dac72c0ab96fb34c0b5d1', 'a'), - ('da853b0d3f88d99b30283a69e6ded6bb', 'abc'), - ('ab4f496bfb2a530b219ff33031fe06b0', 'message digest'), - - ('4e8ddff3650292ab5a4108c3aa47940b', 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - - ('da33def2a42df13975352846c30338cd', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), - - ('d5976f79d83d3a0dc9806c3c66f3efd8', - '1234567890123456789012345678901234567890123456' - + '7890123456789012345678901234567890', - "'1234567890' * 8"), + # Test vectors from RFC 1319 + ("8350e5a3e24c153df2275c9f80692773", "", "'' (empty string)"), + ("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a"), + ("da853b0d3f88d99b30283a69e6ded6bb", "abc"), + ("ab4f496bfb2a530b219ff33031fe06b0", "message digest"), + ( + "4e8ddff3650292ab5a4108c3aa47940b", + "abcdefghijklmnopqrstuvwxyz", + "a-z", + ), + ( + "da33def2a42df13975352846c30338cd", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "A-Z, a-z, 0-9", + ), + ( + "d5976f79d83d3a0dc9806c3c66f3efd8", + "1234567890123456789012345678901234567890123456" + "7890123456789012345678901234567890", + "'1234567890' * 8", + ), ] + def get_tests(config={}): - from Cryptodome.Hash import MD2 - from .common import make_hash_tests - return make_hash_tests(MD2, "MD2", test_data, - digest_size=16, - oid="1.2.840.113549.2.2") - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from Cryptodome.Hash import MD2 + from .common import make_hash_tests + + return make_hash_tests( + MD2, + "MD2", + test_data, + digest_size=16, + oid="1.2.840.113549.2.2", + ) + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD4.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD4.py index 41de9775..5d29626a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD4.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD4.py @@ -30,35 +30,46 @@ # This is a list of (expected_result, input[, description]) tuples. test_data = [ - # Test vectors from RFC 1320 - ('31d6cfe0d16ae931b73c59d7e0c089c0', '', "'' (empty string)"), - ('bde52cb31de33e46245e05fbdbd6fb24', 'a'), - ('a448017aaf21d8525fc10ae87aa6729d', 'abc'), - ('d9130a8164549fe818874806e1c7014b', 'message digest'), + # Test vectors from RFC 1320 + ("31d6cfe0d16ae931b73c59d7e0c089c0", "", "'' (empty string)"), + ("bde52cb31de33e46245e05fbdbd6fb24", "a"), + ("a448017aaf21d8525fc10ae87aa6729d", "abc"), + ("d9130a8164549fe818874806e1c7014b", "message digest"), + ( + "d79e1c308aa5bbcdeea8ed63df412da9", + "abcdefghijklmnopqrstuvwxyz", + "a-z", + ), + ( + "043f8582f241db351ce627e153e7f0e4", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "A-Z, a-z, 0-9", + ), + ( + "e33b4ddc9c38f2199c3e7b164fcc0536", + "1234567890123456789012345678901234567890123456" + "7890123456789012345678901234567890", + "'1234567890' * 8", + ), +] - ('d79e1c308aa5bbcdeea8ed63df412da9', 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - ('043f8582f241db351ce627e153e7f0e4', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), +def get_tests(config={}): + from Cryptodome.Hash import MD4 + from .common import make_hash_tests - ('e33b4ddc9c38f2199c3e7b164fcc0536', - '1234567890123456789012345678901234567890123456' - + '7890123456789012345678901234567890', - "'1234567890' * 8"), -] + return make_hash_tests( + MD4, + "MD4", + test_data, + digest_size=16, + oid="1.2.840.113549.2.4", + ) -def get_tests(config={}): - from Cryptodome.Hash import MD4 - from .common import make_hash_tests - return make_hash_tests(MD4, "MD4", test_data, - digest_size=16, - oid="1.2.840.113549.2.4") -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD5.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD5.py index 3f7a0057..7ba2db3f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD5.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_MD5.py @@ -26,69 +26,73 @@ from Cryptodome.Util.py3compat import * from Cryptodome.Hash import MD5 -from binascii import unhexlify import unittest -from Cryptodome.SelfTest.st_common import list_test_cases # This is a list of (expected_result, input[, description]) tuples. test_data = [ - # Test vectors from RFC 1321 - ('d41d8cd98f00b204e9800998ecf8427e', '', "'' (empty string)"), - ('0cc175b9c0f1b6a831c399e269772661', 'a'), - ('900150983cd24fb0d6963f7d28e17f72', 'abc'), - ('f96b697d7cb7938d525a2f31aaf161d0', 'message digest'), - - ('c3fcd3d76192e4007dfb496cca67e13b', 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - - ('d174ab98d277d9f5a5611c2c9f419d9f', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), - - ('57edf4a22be3c955ac49da2e2107b67a', - '1234567890123456789012345678901234567890123456' - + '7890123456789012345678901234567890', - "'1234567890' * 8"), - - # https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/md5/Md5-128.unverified.test-vectors - ('57EDF4A22BE3C955AC49DA2E2107B67A', '1234567890' * 8, 'Set 1, vector #7'), - ('7707D6AE4E027C70EEA2A935C2296F21', 'a'*1000000, 'Set 1, vector #8'), + # Test vectors from RFC 1321 + ("d41d8cd98f00b204e9800998ecf8427e", "", "'' (empty string)"), + ("0cc175b9c0f1b6a831c399e269772661", "a"), + ("900150983cd24fb0d6963f7d28e17f72", "abc"), + ("f96b697d7cb7938d525a2f31aaf161d0", "message digest"), + ( + "c3fcd3d76192e4007dfb496cca67e13b", + "abcdefghijklmnopqrstuvwxyz", + "a-z", + ), + ( + "d174ab98d277d9f5a5611c2c9f419d9f", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "A-Z, a-z, 0-9", + ), + ( + "57edf4a22be3c955ac49da2e2107b67a", + "1234567890123456789012345678901234567890123456" + "7890123456789012345678901234567890", + "'1234567890' * 8", + ), + # https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/md5/Md5-128.unverified.test-vectors + ("57EDF4A22BE3C955AC49DA2E2107B67A", "1234567890" * 8, "Set 1, vector #7"), + ("7707D6AE4E027C70EEA2A935C2296F21", "a" * 1000000, "Set 1, vector #8"), ] class Md5IterTest(unittest.TestCase): + def runTest(self): + message = b("\x00") * 16 + result1 = "4AE71336E44BF9BF79D2752E234818A5".lower() + result2 = "1A83F51285E4D89403D00C46EF8508FE".lower() - def runTest(self): - message = b("\x00") * 16 - result1 = "4AE71336E44BF9BF79D2752E234818A5".lower() - result2 = "1A83F51285E4D89403D00C46EF8508FE".lower() + h = MD5.new(message) + message = h.digest() + self.assertEqual(h.hexdigest(), result1) - h = MD5.new(message) - message = h.digest() - self.assertEqual(h.hexdigest(), result1) + for _ in range(99999): + h = MD5.new(message) + message = h.digest() - for _ in range(99999): - h = MD5.new(message) - message = h.digest() - - self.assertEqual(h.hexdigest(), result2) + self.assertEqual(h.hexdigest(), result2) def get_tests(config={}): - from .common import make_hash_tests + from .common import make_hash_tests + + tests = make_hash_tests( + MD5, + "MD5", + test_data, + digest_size=16, + oid="1.2.840.113549.2.5", + ) + if config.get("slow_tests"): + tests += [Md5IterTest()] + return tests - tests = make_hash_tests(MD5, "MD5", test_data, - digest_size=16, - oid="1.2.840.113549.2.5") - if config.get('slow_tests'): - tests += [ Md5IterTest() ] - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_Poly1305.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_Poly1305.py index 19cacb4d..80fb5468 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_Poly1305.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_Poly1305.py @@ -33,7 +33,6 @@ """Self-test suite for Cryptodome.Hash._Poly1305""" -import json import unittest from binascii import unhexlify, hexlify @@ -48,436 +47,430 @@ # This is a list of (r+s keypair, data, result, description, keywords) tuples. test_data_basic = [ - ( - "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b", - hexlify(b"Cryptographic Forum Research Group").decode(), - "a8061dc1305136c6c22b8baf0c0127a9", - "RFC7539" - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "0000000000000000000000000000000000000000000000000000000000000000", - "49ec78090e481ec6c26b33b91ccc0307", - "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 A", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "48656c6c6f20776f726c6421", - "a6f745008f81c916a20dcc74eef2b2f0", - "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 B", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "", - "6b657920666f7220506f6c7931333035", - "Generated with pure Python", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "FF", - "f7e4e0ef4c46d106219da3d1bdaeb3ff", - "Generated with pure Python", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "FF00", - "7471eceeb22988fc936da1d6e838b70e", - "Generated with pure Python", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "AA" * 17, - "32590bc07cb2afaccca3f67f122975fe", - "Generated with pure Python", - ), - ( - "00" * 32, - "00" * 64, - "00" * 16, - "RFC7539 A.3 #1", - ), - ( - "0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e", - hexlify( - b"Any submission t" - b"o the IETF inten" - b"ded by the Contr" - b"ibutor for publi" - b"cation as all or" - b" part of an IETF" - b" Internet-Draft " - b"or RFC and any s" - b"tatement made wi" - b"thin the context" - b" of an IETF acti" - b"vity is consider" - b"ed an \"IETF Cont" - b"ribution\". Such " - b"statements inclu" - b"de oral statemen" - b"ts in IETF sessi" - b"ons, as well as " - b"written and elec" - b"tronic communica" - b"tions made at an" - b"y time or place," - b" which are addre" - b"ssed to").decode(), - "36e5f6b5c5e06070f0efca96227a863e", - "RFC7539 A.3 #2", - ), - ( - "36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000", - hexlify( - b"Any submission t" - b"o the IETF inten" - b"ded by the Contr" - b"ibutor for publi" - b"cation as all or" - b" part of an IETF" - b" Internet-Draft " - b"or RFC and any s" - b"tatement made wi" - b"thin the context" - b" of an IETF acti" - b"vity is consider" - b"ed an \"IETF Cont" - b"ribution\". Such " - b"statements inclu" - b"de oral statemen" - b"ts in IETF sessi" - b"ons, as well as " - b"written and elec" - b"tronic communica" - b"tions made at an" - b"y time or place," - b" which are addre" - b"ssed to").decode(), - "f3477e7cd95417af89a6b8794c310cf0", - "RFC7539 A.3 #3", - ), - ( - "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", - "2754776173206272696c6c69672c2061" - "6e642074686520736c6974687920746f" - "7665730a446964206779726520616e64" - "2067696d626c6520696e207468652077" - "6162653a0a416c6c206d696d73792077" - "6572652074686520626f726f676f7665" - "732c0a416e6420746865206d6f6d6520" - "7261746873206f757467726162652e", - "4541669a7eaaee61e708dc7cbcc5eb62", - "RFC7539 A.3 #4", - ), - ( - "02" + "00" * 31, - "FF" * 16, - "03" + "00" * 15, - "RFC7539 A.3 #5", - ), - ( - "02" + "00" * 15 + "FF" * 16, - "02" + "00" * 15, - "03" + "00" * 15, - "RFC7539 A.3 #6", - ), - ( - "01" + "00" * 31, - "FF" * 16 + "F0" + "FF" * 15 + "11" + "00" * 15, - "05" + "00" * 15, - "RFC7539 A.3 #7", - ), - ( - "01" + "00" * 31, - "FF" * 16 + "FB" + "FE" * 15 + "01" * 16, - "00" * 16, - "RFC7539 A.3 #8", - ), - ( - "02" + "00" * 31, - "FD" + "FF" * 15, - "FA" + "FF" * 15, - "RFC7539 A.3 #9", - ), - ( - "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" - "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" - "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "14 00 00 00 00 00 00 00 55 00 00 00 00 00 00 00", - "RFC7539 A.3 #10", - ), - ( - "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" - "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "13" + "00" * 15, - "RFC7539 A.3 #11", - ), + ( + "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b", + hexlify(b"Cryptographic Forum Research Group").decode(), + "a8061dc1305136c6c22b8baf0c0127a9", + "RFC7539", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "0000000000000000000000000000000000000000000000000000000000000000", + "49ec78090e481ec6c26b33b91ccc0307", + "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 A", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "48656c6c6f20776f726c6421", + "a6f745008f81c916a20dcc74eef2b2f0", + "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 B", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "", + "6b657920666f7220506f6c7931333035", + "Generated with pure Python", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "FF", + "f7e4e0ef4c46d106219da3d1bdaeb3ff", + "Generated with pure Python", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "FF00", + "7471eceeb22988fc936da1d6e838b70e", + "Generated with pure Python", + ), + ( + "746869732069732033322d62797465206b657920666f7220506f6c7931333035", + "AA" * 17, + "32590bc07cb2afaccca3f67f122975fe", + "Generated with pure Python", + ), + ( + "00" * 32, + "00" * 64, + "00" * 16, + "RFC7539 A.3 #1", + ), + ( + "0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e", + hexlify( + b"Any submission t" + b"o the IETF inten" + b"ded by the Contr" + b"ibutor for publi" + b"cation as all or" + b" part of an IETF" + b" Internet-Draft " + b"or RFC and any s" + b"tatement made wi" + b"thin the context" + b" of an IETF acti" + b"vity is consider" + b'ed an "IETF Cont' + b'ribution". Such ' + b"statements inclu" + b"de oral statemen" + b"ts in IETF sessi" + b"ons, as well as " + b"written and elec" + b"tronic communica" + b"tions made at an" + b"y time or place," + b" which are addre" + b"ssed to", + ).decode(), + "36e5f6b5c5e06070f0efca96227a863e", + "RFC7539 A.3 #2", + ), + ( + "36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000", + hexlify( + b"Any submission t" + b"o the IETF inten" + b"ded by the Contr" + b"ibutor for publi" + b"cation as all or" + b" part of an IETF" + b" Internet-Draft " + b"or RFC and any s" + b"tatement made wi" + b"thin the context" + b" of an IETF acti" + b"vity is consider" + b'ed an "IETF Cont' + b'ribution". Such ' + b"statements inclu" + b"de oral statemen" + b"ts in IETF sessi" + b"ons, as well as " + b"written and elec" + b"tronic communica" + b"tions made at an" + b"y time or place," + b" which are addre" + b"ssed to", + ).decode(), + "f3477e7cd95417af89a6b8794c310cf0", + "RFC7539 A.3 #3", + ), + ( + "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "2754776173206272696c6c69672c2061" + "6e642074686520736c6974687920746f" + "7665730a446964206779726520616e64" + "2067696d626c6520696e207468652077" + "6162653a0a416c6c206d696d73792077" + "6572652074686520626f726f676f7665" + "732c0a416e6420746865206d6f6d6520" + "7261746873206f757467726162652e", + "4541669a7eaaee61e708dc7cbcc5eb62", + "RFC7539 A.3 #4", + ), + ( + "02" + "00" * 31, + "FF" * 16, + "03" + "00" * 15, + "RFC7539 A.3 #5", + ), + ( + "02" + "00" * 15 + "FF" * 16, + "02" + "00" * 15, + "03" + "00" * 15, + "RFC7539 A.3 #6", + ), + ( + "01" + "00" * 31, + "FF" * 16 + "F0" + "FF" * 15 + "11" + "00" * 15, + "05" + "00" * 15, + "RFC7539 A.3 #7", + ), + ( + "01" + "00" * 31, + "FF" * 16 + "FB" + "FE" * 15 + "01" * 16, + "00" * 16, + "RFC7539 A.3 #8", + ), + ( + "02" + "00" * 31, + "FD" + "FF" * 15, + "FA" + "FF" * 15, + "RFC7539 A.3 #9", + ), + ( + "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" + "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" + "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "14 00 00 00 00 00 00 00 55 00 00 00 00 00 00 00", + "RFC7539 A.3 #10", + ), + ( + "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" + "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "13" + "00" * 15, + "RFC7539 A.3 #11", + ), ] # This is a list of (key(k+r), data, result, description, keywords) tuples. test_data_aes = [ - ( - "ec074c835580741701425b623235add6851fc40c3467ac0be05cc20404f3f700", - "f3f6", - "f4c633c3044fc145f84f335cb81953de", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("fb447350c4e868c52ac3275cf9d4327e") } - ), - ( - "75deaa25c09f208e1dc4ce6b5cad3fbfa0f3080000f46400d0c7e9076c834403", - "", - "dd3fab2251f11ac759f0887129cc2ee7", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("61ee09218d29b0aaed7e154a2c5509cc") } - ), - ( - "6acb5f61a7176dd320c5c1eb2edcdc7448443d0bb0d21109c89a100b5ce2c208", - "663cea190ffb83d89593f3f476b6bc24" - "d7e679107ea26adb8caf6652d0656136", - "0ee1c16bb73f0f4fd19881753c01cdbe", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("ae212a55399729595dea458bc621ff0e") } - ), - ( - "e1a5668a4d5b66a5f68cc5424ed5982d12976a08c4426d0ce8a82407c4f48207", - "ab0812724a7f1e342742cbed374d94d1" - "36c6b8795d45b3819830f2c04491faf0" - "990c62e48b8018b2c3e4a0fa3134cb67" - "fa83e158c994d961c4cb21095c1bf9", - "5154ad0d2cb26e01274fc51148491f1b", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("9ae831e743978d3a23527c7128149e3a") } - ), + ( + "ec074c835580741701425b623235add6851fc40c3467ac0be05cc20404f3f700", + "f3f6", + "f4c633c3044fc145f84f335cb81953de", + "http://cr.yp.to/mac/poly1305-20050329.pdf", + {"cipher": AES, "nonce": unhexlify("fb447350c4e868c52ac3275cf9d4327e")}, + ), + ( + "75deaa25c09f208e1dc4ce6b5cad3fbfa0f3080000f46400d0c7e9076c834403", + "", + "dd3fab2251f11ac759f0887129cc2ee7", + "http://cr.yp.to/mac/poly1305-20050329.pdf", + {"cipher": AES, "nonce": unhexlify("61ee09218d29b0aaed7e154a2c5509cc")}, + ), + ( + "6acb5f61a7176dd320c5c1eb2edcdc7448443d0bb0d21109c89a100b5ce2c208", + "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136", + "0ee1c16bb73f0f4fd19881753c01cdbe", + "http://cr.yp.to/mac/poly1305-20050329.pdf", + {"cipher": AES, "nonce": unhexlify("ae212a55399729595dea458bc621ff0e")}, + ), + ( + "e1a5668a4d5b66a5f68cc5424ed5982d12976a08c4426d0ce8a82407c4f48207", + "ab0812724a7f1e342742cbed374d94d1" + "36c6b8795d45b3819830f2c04491faf0" + "990c62e48b8018b2c3e4a0fa3134cb67" + "fa83e158c994d961c4cb21095c1bf9", + "5154ad0d2cb26e01274fc51148491f1b", + "http://cr.yp.to/mac/poly1305-20050329.pdf", + {"cipher": AES, "nonce": unhexlify("9ae831e743978d3a23527c7128149e3a")}, + ), ] test_data_chacha20 = [ - ( - "00" * 32, - "FF" * 15, - "13cc5bbadc36b03a5163928f0bcb65aa", - "RFC7539 A.4 #1", - { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 12) } - ), - ( - "00" * 31 + "01", - "FF" * 15, - "0baf33c1d6df211bdd50a6767e98e00a", - "RFC7539 A.4 #2", - { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 11 + "02") } - ), - ( - "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0" - "47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", - "FF" * 15, - "e8b4c6db226cd8939e65e02eebf834ce", - "RFC7539 A.4 #3", - { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 11 + "02") } - ), - ( - "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0" - "47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", - "f3 33 88 86 00 00 00 00 00 00 4e 91 00 00 00 00" - "64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd" - "5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2" - "4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0" - "bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf" - "33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81" - "14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55" - "97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38" - "36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4" - "b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9" - "90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e" - "af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a" - "0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a" - "0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e" - "ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10" - "49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30" - "30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29" - "a6 ad 5c b4 02 2b 02 70 9b 00 00 00 00 00 00 00" - "0c 00 00 00 00 00 00 00 09 01 00 00 00 00 00 00", - "ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38", - "RFC7539 A.5", - { 'cipher':ChaCha20, 'nonce':unhexlify("000000000102030405060708") } - ), + ( + "00" * 32, + "FF" * 15, + "13cc5bbadc36b03a5163928f0bcb65aa", + "RFC7539 A.4 #1", + {"cipher": ChaCha20, "nonce": unhexlify("00" * 12)}, + ), + ( + "00" * 31 + "01", + "FF" * 15, + "0baf33c1d6df211bdd50a6767e98e00a", + "RFC7539 A.4 #2", + {"cipher": ChaCha20, "nonce": unhexlify("00" * 11 + "02")}, + ), + ( + "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f047 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", + "FF" * 15, + "e8b4c6db226cd8939e65e02eebf834ce", + "RFC7539 A.4 #3", + {"cipher": ChaCha20, "nonce": unhexlify("00" * 11 + "02")}, + ), + ( + "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f047 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0", + "f3 33 88 86 00 00 00 00 00 00 4e 91 00 00 00 00" + "64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd" + "5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2" + "4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0" + "bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf" + "33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81" + "14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55" + "97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38" + "36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4" + "b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9" + "90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e" + "af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a" + "0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a" + "0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e" + "ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10" + "49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30" + "30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29" + "a6 ad 5c b4 02 2b 02 70 9b 00 00 00 00 00 00 00" + "0c 00 00 00 00 00 00 00 09 01 00 00 00 00 00 00", + "ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38", + "RFC7539 A.5", + {"cipher": ChaCha20, "nonce": unhexlify("000000000102030405060708")}, + ), ] class Poly1305Test_AES(unittest.TestCase): - - key = b'\x11' * 32 - - def test_new_positive(self): - - data = b'r' * 100 - - h1 = Poly1305.new(key=self.key, cipher=AES) - self.assertEqual(h1.digest_size, 16) - self.assertEqual(len(h1.nonce), 16) - d1 = h1.update(data).digest() - self.assertEqual(len(d1), 16) - - h2 = Poly1305.new(key=self.key, nonce=h1.nonce, data=data, cipher=AES) - d2 = h2.digest() - self.assertEqual(h1.nonce, h2.nonce) - self.assertEqual(d1, d2) - - def test_new_negative(self): - from Cryptodome.Cipher import DES3 - - self.assertRaises(ValueError, Poly1305.new, key=self.key[:31], cipher=AES) - self.assertRaises(ValueError, Poly1305.new, key=self.key, cipher=DES3) - self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b'1' * 15, cipher=AES) - self.assertRaises(TypeError, Poly1305.new, key=u"2" * 32, cipher=AES) - self.assertRaises(TypeError, Poly1305.new, key=self.key, data=u"2" * 100, cipher=AES) - - def test_update(self): - pieces = [b"\x0A" * 200, b"\x14" * 300] - h1 = Poly1305.new(key=self.key, cipher=AES) - h1.update(pieces[0]).update(pieces[1]) - d1 = h1.digest() - - h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) - h2.update(pieces[0] + pieces[1]) - d2 = h2.digest() - self.assertEqual(d1, d2) - - def test_update_negative(self): - h = Poly1305.new(key=self.key, cipher=AES) - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = Poly1305.new(key=self.key, cipher=AES) - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg=b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = Poly1305.new(key=self.key, data=msg[:4], cipher=AES) - h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - - def test_hex_digest(self): - mac = Poly1305.new(key=self.key, cipher=AES) - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_verify(self): - h = Poly1305.new(key=self.key, cipher=AES) - mac = h.digest() - h.verify(mac) - wrong_mac = strxor_c(mac, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - - def test_hexverify(self): - h = Poly1305.new(key=self.key, cipher=AES) - mac = h.hexdigest() - h.hexverify(mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - def test_bytearray(self): - - data = b"\x00\x01\x02" - h0 = Poly1305.new(key=self.key, data=data, cipher=AES) - d_ref = h0.digest() - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(self.key) - data_ba = bytearray(data) - - h1 = Poly1305.new(key=self.key, data=data, cipher=AES, nonce=h0.nonce) - h2 = Poly1305.new(key=key_ba, data=data_ba, cipher=AES, nonce=h0.nonce) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xEE' - - self.assertEqual(h1.digest(), d_ref) - self.assertEqual(h2.digest(), d_ref) - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = Poly1305.new(key=self.key, cipher=AES) - h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(self.key) - data_mv = get_mv(data) - - h1 = Poly1305.new(key=self.key, data=data, cipher=AES) - h2 = Poly1305.new(key=key_mv, data=data_mv, cipher=AES, - nonce=h1.nonce) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - key_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = Poly1305.new(key=self.key, cipher=AES) - h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) + key = b"\x11" * 32 + + def test_new_positive(self): + data = b"r" * 100 + + h1 = Poly1305.new(key=self.key, cipher=AES) + self.assertEqual(h1.digest_size, 16) + self.assertEqual(len(h1.nonce), 16) + d1 = h1.update(data).digest() + self.assertEqual(len(d1), 16) + + h2 = Poly1305.new(key=self.key, nonce=h1.nonce, data=data, cipher=AES) + d2 = h2.digest() + self.assertEqual(h1.nonce, h2.nonce) + self.assertEqual(d1, d2) + + def test_new_negative(self): + from Cryptodome.Cipher import DES3 + + self.assertRaises(ValueError, Poly1305.new, key=self.key[:31], cipher=AES) + self.assertRaises(ValueError, Poly1305.new, key=self.key, cipher=DES3) + self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b"1" * 15, cipher=AES) + self.assertRaises(TypeError, Poly1305.new, key="2" * 32, cipher=AES) + self.assertRaises(TypeError, Poly1305.new, key=self.key, data="2" * 100, cipher=AES) + + def test_update(self): + pieces = [b"\x0a" * 200, b"\x14" * 300] + h1 = Poly1305.new(key=self.key, cipher=AES) + h1.update(pieces[0]).update(pieces[1]) + d1 = h1.digest() + + h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) + h2.update(pieces[0] + pieces[1]) + d2 = h2.digest() + self.assertEqual(d1, d2) + + def test_update_negative(self): + h = Poly1305.new(key=self.key, cipher=AES) + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = Poly1305.new(key=self.key, cipher=AES) + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b"digest"))) + + def test_update_after_digest(self): + msg = b"rrrrttt" + + # Normally, update() cannot be done after digest() + h = Poly1305.new(key=self.key, data=msg[:4], cipher=AES) + h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + + def test_hex_digest(self): + mac = Poly1305.new(key=self.key, cipher=AES) + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_verify(self): + h = Poly1305.new(key=self.key, cipher=AES) + mac = h.digest() + h.verify(mac) + wrong_mac = strxor_c(mac, 255) + self.assertRaises(ValueError, h.verify, wrong_mac) + + def test_hexverify(self): + h = Poly1305.new(key=self.key, cipher=AES) + mac = h.hexdigest() + h.hexverify(mac) + self.assertRaises(ValueError, h.hexverify, "4556") + + def test_bytearray(self): + data = b"\x00\x01\x02" + h0 = Poly1305.new(key=self.key, data=data, cipher=AES) + d_ref = h0.digest() + + # Data and key can be a bytearray (during initialization) + key_ba = bytearray(self.key) + data_ba = bytearray(data) + + h1 = Poly1305.new(key=self.key, data=data, cipher=AES, nonce=h0.nonce) + h2 = Poly1305.new(key=key_ba, data=data_ba, cipher=AES, nonce=h0.nonce) + key_ba[:1] = b"\xff" + data_ba[:1] = b"\xee" + + self.assertEqual(h1.digest(), d_ref) + self.assertEqual(h2.digest(), d_ref) + + # Data can be a bytearray (during operation) + data_ba = bytearray(data) + + h1 = Poly1305.new(key=self.key, cipher=AES) + h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + def test_memoryview(self): + data = b"\x00\x01\x02" + + def get_mv_ro(data): + return memoryview(data) + + def get_mv_rw(data): + return memoryview(bytearray(data)) + + for get_mv in (get_mv_ro, get_mv_rw): + # Data and key can be a memoryview (during initialization) + key_mv = get_mv(self.key) + data_mv = get_mv(data) + + h1 = Poly1305.new(key=self.key, data=data, cipher=AES) + h2 = Poly1305.new( + key=key_mv, + data=data_mv, + cipher=AES, + nonce=h1.nonce, + ) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + key_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + # Data can be a memoryview (during operation) + data_mv = get_mv(data) + + h1 = Poly1305.new(key=self.key, cipher=AES) + h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) class Poly1305Test_ChaCha20(unittest.TestCase): + key = b"\x11" * 32 - key = b'\x11' * 32 + def test_new_positive(self): + data = b"r" * 100 - def test_new_positive(self): - data = b'r' * 100 + h1 = Poly1305.new(key=self.key, cipher=ChaCha20) + self.assertEqual(h1.digest_size, 16) + self.assertEqual(len(h1.nonce), 12) - h1 = Poly1305.new(key=self.key, cipher=ChaCha20) - self.assertEqual(h1.digest_size, 16) - self.assertEqual(len(h1.nonce), 12) - - h2 = Poly1305.new(key=self.key, cipher=ChaCha20, nonce = b'8' * 8) - self.assertEqual(len(h2.nonce), 8) - self.assertEqual(h2.nonce, b'8' * 8) + h2 = Poly1305.new(key=self.key, cipher=ChaCha20, nonce=b"8" * 8) + self.assertEqual(len(h2.nonce), 8) + self.assertEqual(h2.nonce, b"8" * 8) - def test_new_negative(self): - - self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b'1' * 7, cipher=ChaCha20) + def test_new_negative(self): + self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b"1" * 7, cipher=ChaCha20) # @@ -485,58 +478,55 @@ def test_new_negative(self): # **kwargs), and we need to adapt Poly1305's, as it only uses keywords # class Poly1305_New(object): - - @staticmethod - def new(key, *data, **kwds): - _kwds = dict(kwds) - if len(data) == 1: - _kwds['data'] = data[0] - _kwds['key'] = key - return Poly1305.new(**_kwds) + @staticmethod + def new(key, *data, **kwds): + _kwds = dict(kwds) + if len(data) == 1: + _kwds["data"] = data[0] + _kwds["key"] = key + return Poly1305.new(**_kwds) class Poly1305_Basic(object): + @staticmethod + def new(key, *data, **kwds): + from Cryptodome.Hash.Poly1305 import Poly1305_MAC - @staticmethod - def new(key, *data, **kwds): - from Cryptodome.Hash.Poly1305 import Poly1305_MAC + if len(data) == 1: + msg = data[0] + else: + msg = None - if len(data) == 1: - msg = data[0] - else: - msg = None - - return Poly1305_MAC(key[:16], key[16:], msg) + return Poly1305_MAC(key[:16], key[16:], msg) class Poly1305AES_MC(unittest.TestCase): + def runTest(self): + tag = unhexlify(b"fb447350c4e868c52ac3275cf9d4327e") - def runTest(self): - tag = unhexlify(b"fb447350c4e868c52ac3275cf9d4327e") - - msg = b'' - for msg_len in range(5000 + 1): - key = tag + strxor_c(tag, 0xFF) - nonce = tag[::-1] - if msg_len > 0: - msg = msg + tobytes(tag[0]) - auth = Poly1305.new(key=key, nonce=nonce, cipher=AES, data=msg) - tag = auth.digest() + msg = b"" + for msg_len in range(5000 + 1): + key = tag + strxor_c(tag, 0xFF) + nonce = tag[::-1] + if msg_len > 0: + msg = msg + tobytes(tag[0]) + auth = Poly1305.new(key=key, nonce=nonce, cipher=AES, data=msg) + tag = auth.digest() - # Compare against output of original DJB's poly1305aes-20050218 - self.assertEqual("CDFA436DDD629C7DC20E1128530BAED2", auth.hexdigest().upper()) + # Compare against output of original DJB's poly1305aes-20050218 + self.assertEqual("CDFA436DDD629C7DC20E1128530BAED2", auth.hexdigest().upper()) def get_tests(config={}): - tests = make_mac_tests(Poly1305_Basic, "Poly1305", test_data_basic) - tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_aes) - tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_chacha20) - tests += [ Poly1305AES_MC() ] - tests += list_test_cases(Poly1305Test_AES) - tests += list_test_cases(Poly1305Test_ChaCha20) - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = make_mac_tests(Poly1305_Basic, "Poly1305", test_data_basic) + tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_aes) + tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_chacha20) + tests += [Poly1305AES_MC()] + tests += list_test_cases(Poly1305Test_AES) + tests += list_test_cases(Poly1305Test_ChaCha20) + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_RIPEMD160.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_RIPEMD160.py index c05a8779..0f7b31a8 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_RIPEMD160.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_RIPEMD160.py @@ -22,50 +22,63 @@ # SOFTWARE. # =================================================================== -#"""Self-test suite for Cryptodome.Hash.RIPEMD160""" +# """Self-test suite for Cryptodome.Hash.RIPEMD160""" from Cryptodome.Util.py3compat import * # This is a list of (expected_result, input[, description]) tuples. test_data = [ - # Test vectors downloaded 2008-09-12 from - # http://homes.esat.kuleuven.be/~bosselae/ripemd160.html - ('9c1185a5c5e9fc54612808977ee8f548b2258d31', '', "'' (empty string)"), - ('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe', 'a'), - ('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc', 'abc'), - ('5d0689ef49d2fae572b881b123a85ffa21595f36', 'message digest'), + # Test vectors downloaded 2008-09-12 from + # http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + ("9c1185a5c5e9fc54612808977ee8f548b2258d31", "", "'' (empty string)"), + ("0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"), + ("8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"), + ("5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"), + ( + "f71c27109c692c1b56bbdceb5b9d2865b3708dbc", + "abcdefghijklmnopqrstuvwxyz", + "a-z", + ), + ( + "12a053384a9c0c88e405a06c27dcf49ada62eb2b", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "abcdbcd...pnopq", + ), + ( + "b0e20b6e3116640286ed3a87a5713079b21f5189", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "A-Z, a-z, 0-9", + ), + ( + "9b752e45573d4b39f4dbd3323cab82bf63326bfb", + "1234567890" * 8, + "'1234567890' * 8", + ), + ( + "52783243c1697bdbe16d37f97f68f08325dc1528", + "a" * 10**6, + '"a" * 10**6', + ), +] - ('f71c27109c692c1b56bbdceb5b9d2865b3708dbc', - 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - ('12a053384a9c0c88e405a06c27dcf49ada62eb2b', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', - 'abcdbcd...pnopq'), +def get_tests(config={}): + from Cryptodome.Hash import RIPEMD160 + from .common import make_hash_tests - ('b0e20b6e3116640286ed3a87a5713079b21f5189', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), + return make_hash_tests( + RIPEMD160, + "RIPEMD160", + test_data, + digest_size=20, + oid="1.3.36.3.2.1", + ) - ('9b752e45573d4b39f4dbd3323cab82bf63326bfb', - '1234567890' * 8, - "'1234567890' * 8"), - ('52783243c1697bdbe16d37f97f68f08325dc1528', - 'a' * 10**6, - '"a" * 10**6'), -] - -def get_tests(config={}): - from Cryptodome.Hash import RIPEMD160 - from .common import make_hash_tests - return make_hash_tests(RIPEMD160, "RIPEMD160", test_data, - digest_size=20, - oid="1.3.36.3.2.1") +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA1.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA1.py index a879e68c..364f559e 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA1.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA1.py @@ -31,54 +31,67 @@ # Test vectors from various sources # This is a list of (expected_result, input[, description]) tuples. test_data_various = [ - # FIPS PUB 180-2, A.1 - "One-Block Message" - ('a9993e364706816aba3e25717850c26c9cd0d89d', 'abc'), + # FIPS PUB 180-2, A.1 - "One-Block Message" + ("a9993e364706816aba3e25717850c26c9cd0d89d", "abc"), + # FIPS PUB 180-2, A.2 - "Multi-Block Message" + ( + "84983e441c3bd26ebaae4aa1f95129e5e54670f1", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + ), + # FIPS PUB 180-2, A.3 - "Long Message" + # ('34aa973cd4c4daa4f61eeb2bdbad27316534016f', + # 'a' * 10**6, + # '"a" * 10**6'), + # RFC 3174: Section 7.3, "TEST4" (multiple of 512 bits) + ( + "dea356a2cddd90c7a7ecedc5ebb563934f460452", + "01234567" * 80, + '"01234567" * 80', + ), +] - # FIPS PUB 180-2, A.2 - "Multi-Block Message" - ('84983e441c3bd26ebaae4aa1f95129e5e54670f1', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), - # FIPS PUB 180-2, A.3 - "Long Message" -# ('34aa973cd4c4daa4f61eeb2bdbad27316534016f', -# 'a' * 10**6, -# '"a" * 10**6'), +def get_tests(config={}): + from Cryptodome.Hash import SHA1 + from .common import make_hash_tests - # RFC 3174: Section 7.3, "TEST4" (multiple of 512 bits) - ('dea356a2cddd90c7a7ecedc5ebb563934f460452', - '01234567' * 80, - '"01234567" * 80'), -] + tests = [] -def get_tests(config={}): - from Cryptodome.Hash import SHA1 - from .common import make_hash_tests + test_vectors = ( + load_test_vectors( + ("Hash", "SHA1"), + "SHA1ShortMsg.rsp", + "KAT SHA-1", + {"len": lambda x: int(x)}, + ) + or [] + ) - tests = [] + test_data = test_data_various[:] + for tv in test_vectors: + try: + if tv.startswith("["): + continue + except AttributeError: + pass + if tv.len == 0: + tv.msg = b"" + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - test_vectors = load_test_vectors(("Hash", "SHA1"), - "SHA1ShortMsg.rsp", - "KAT SHA-1", - { "len" : lambda x: int(x) } ) or [] + tests = make_hash_tests( + SHA1, + "SHA1", + test_data, + digest_size=20, + oid="1.3.14.3.2.26", + ) + return tests - test_data = test_data_various[:] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - tests = make_hash_tests(SHA1, "SHA1", test_data, - digest_size=20, - oid="1.3.14.3.2.26") - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA224.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA224.py index da32423a..a45feb1b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA224.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA224.py @@ -27,37 +27,45 @@ # Test vectors from various sources # This is a list of (expected_result, input[, description]) tuples. test_data = [ + # RFC 3874: Section 3.1, "Test Vector #1 + ("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", "abc"), + # RFC 3874: Section 3.2, "Test Vector #2 + ( + "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + ), + # RFC 3874: Section 3.3, "Test Vector #3 + ("20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67", "a" * 10**6, "'a' * 10**6"), + # Examples from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", ""), + ( + "49b08defa65e644cbf8a2dd9270bdededabc741997d1dadd42026d7b", + "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), + ( + "58911e7fccf2971a7d07f93162d8bd13568e71aa8fc86fc1fe9043d1", + "Frank jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), +] - # RFC 3874: Section 3.1, "Test Vector #1 - ('23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7', 'abc'), - - # RFC 3874: Section 3.2, "Test Vector #2 - ('75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), - - # RFC 3874: Section 3.3, "Test Vector #3 - ('20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67', 'a' * 10**6, "'a' * 10**6"), - # Examples from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f', ''), +def get_tests(config={}): + from Cryptodome.Hash import SHA224 + from .common import make_hash_tests - ('49b08defa65e644cbf8a2dd9270bdededabc741997d1dadd42026d7b', - 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), + return make_hash_tests( + SHA224, + "SHA224", + test_data, + digest_size=28, + oid="2.16.840.1.101.3.4.2.4", + ) - ('58911e7fccf2971a7d07f93162d8bd13568e71aa8fc86fc1fe9043d1', - 'Frank jagt im komplett verwahrlosten Taxi quer durch Bayern'), -] +if __name__ == "__main__": + import unittest -def get_tests(config={}): - from Cryptodome.Hash import SHA224 - from .common import make_hash_tests - return make_hash_tests(SHA224, "SHA224", test_data, - digest_size=28, - oid='2.16.840.1.101.3.4.2.4') - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA256.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA256.py index 23d1145c..66d11707 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA256.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA256.py @@ -27,68 +27,87 @@ import unittest from Cryptodome.Util.py3compat import * + class LargeSHA256Test(unittest.TestCase): - def runTest(self): - """SHA256: 512/520 MiB test""" - from Cryptodome.Hash import SHA256 - zeros = bchr(0x00) * (1024*1024) + def runTest(self): + """SHA256: 512/520 MiB test""" + from Cryptodome.Hash import SHA256 + + zeros = bchr(0x00) * (1024 * 1024) + + h = SHA256.new(zeros) + for i in range(511): + h.update(zeros) - h = SHA256.new(zeros) - for i in range(511): - h.update(zeros) + # This test vector is from PyCrypto's old testdata.py file. + self.assertEqual( + "9acca8e8c22201155389f65abbf6bc9723edc7384ead80503839f49dcc56d767", h.hexdigest() + ) # 512 MiB - # This test vector is from PyCrypto's old testdata.py file. - self.assertEqual('9acca8e8c22201155389f65abbf6bc9723edc7384ead80503839f49dcc56d767', h.hexdigest()) # 512 MiB + for i in range(8): + h.update(zeros) - for i in range(8): - h.update(zeros) + # This test vector is from PyCrypto's old testdata.py file. + self.assertEqual( + "abf51ad954b246009dfe5a50ecd582fd5b8f1b8b27f30393853c3ef721e7fa6e", h.hexdigest() + ) # 520 MiB - # This test vector is from PyCrypto's old testdata.py file. - self.assertEqual('abf51ad954b246009dfe5a50ecd582fd5b8f1b8b27f30393853c3ef721e7fa6e', h.hexdigest()) # 520 MiB def get_tests(config={}): - # Test vectors from FIPS PUB 180-2 - # This is a list of (expected_result, input[, description]) tuples. - test_data = [ - # FIPS PUB 180-2, B.1 - "One-Block Message" - ('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', - 'abc'), - - # FIPS PUB 180-2, B.2 - "Multi-Block Message" - ('248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), - - # FIPS PUB 180-2, B.3 - "Long Message" - ('cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0', - 'a' * 10**6, - '"a" * 10**6'), - - # Test for an old PyCryptodome bug. - ('f7fd017a3c721ce7ff03f3552c0813adcc48b7f33f07e5e2ba71e23ea393d103', - 'This message is precisely 55 bytes long, to test a bug.', - 'Length = 55 (mod 64)'), - - # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', ''), - - ('d32b568cd1b96d459e7291ebf4b25d007f275c9f13149beeb782fac0716613f8', - 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), - ] - - from Cryptodome.Hash import SHA256 - from .common import make_hash_tests - tests = make_hash_tests(SHA256, "SHA256", test_data, - digest_size=32, - oid="2.16.840.1.101.3.4.2.1") - - if config.get('slow_tests'): - tests += [LargeSHA256Test()] - - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + # Test vectors from FIPS PUB 180-2 + # This is a list of (expected_result, input[, description]) tuples. + test_data = [ + # FIPS PUB 180-2, B.1 - "One-Block Message" + ( + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + "abc", + ), + # FIPS PUB 180-2, B.2 - "Multi-Block Message" + ( + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + ), + # FIPS PUB 180-2, B.3 - "Long Message" + ( + "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0", + "a" * 10**6, + '"a" * 10**6', + ), + # Test for an old PyCryptodome bug. + ( + "f7fd017a3c721ce7ff03f3552c0813adcc48b7f33f07e5e2ba71e23ea393d103", + "This message is precisely 55 bytes long, to test a bug.", + "Length = 55 (mod 64)", + ), + # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""), + ( + "d32b568cd1b96d459e7291ebf4b25d007f275c9f13149beeb782fac0716613f8", + "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), + ] + + from Cryptodome.Hash import SHA256 + from .common import make_hash_tests + + tests = make_hash_tests( + SHA256, + "SHA256", + test_data, + digest_size=32, + oid="2.16.840.1.101.3.4.2.1", + ) + + if config.get("slow_tests"): + tests += [LargeSHA256Test()] + + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA384.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA384.py index 5233d133..3dbf2eee 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA384.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA384.py @@ -27,35 +27,49 @@ # Test vectors from various sources # This is a list of (expected_result, input[, description]) tuples. test_data = [ + # RFC 4634: Section Page 8.4, "Test 1" + ( + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7", + "abc", + ), + # RFC 4634: Section Page 8.4, "Test 2.2" + ( + "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039", + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + ), + # RFC 4634: Section Page 8.4, "Test 3" + ( + "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985", + "a" * 10**6, + "'a' * 10**6", + ), + # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ("38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", ""), + # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ( + "71e8383a4cea32d6fd6877495db2ee353542f46fa44bc23100bca48f3366b84e809f0708e81041f427c6d5219a286677", + "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), +] - # RFC 4634: Section Page 8.4, "Test 1" - ('cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7', 'abc'), - # RFC 4634: Section Page 8.4, "Test 2.2" - ('09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'), +def get_tests(config={}): + from Cryptodome.Hash import SHA384 + from .common import make_hash_tests - # RFC 4634: Section Page 8.4, "Test 3" - ('9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985', 'a' * 10**6, "'a' * 10**6"), + return make_hash_tests( + SHA384, + "SHA384", + test_data, + digest_size=48, + oid="2.16.840.1.101.3.4.2.2", + ) - # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b', ''), - # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('71e8383a4cea32d6fd6877495db2ee353542f46fa44bc23100bca48f3366b84e809f0708e81041f427c6d5219a286677', - 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), +if __name__ == "__main__": + import unittest -] - -def get_tests(config={}): - from Cryptodome.Hash import SHA384 - from .common import make_hash_tests - return make_hash_tests(SHA384, "SHA384", test_data, - digest_size=48, - oid='2.16.840.1.101.3.4.2.2') - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_224.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_224.py index 3141880c..d52c0ce7 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_224.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_224.py @@ -32,48 +32,58 @@ class APITest(unittest.TestCase): + def test_update_after_digest(self): + msg = b("rrrrttt") - def test_update_after_digest(self): - msg=b("rrrrttt") + # Normally, update() cannot be done after digest() + h = SHA3.new(data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = SHA3.new(data=msg).digest() - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) + # With the proper flag, it is allowed + h = SHA3.new(data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-224.txt", - "KAT SHA-3 224", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests += make_hash_tests(SHA3, "SHA3_224", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.7") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from .common import make_hash_tests + + tests = [] + + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHA3-224.txt", + "KAT SHA-3 224", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + if tv.len == 0: + tv.msg = b("") + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests += make_hash_tests( + SHA3, + "SHA3_224", + test_data, + digest_size=SHA3.digest_size, + oid="2.16.840.1.101.3.4.2.7", + ) + tests += list_test_cases(APITest) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_256.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_256.py index 9dee5514..30152df8 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_256.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_256.py @@ -32,49 +32,58 @@ class APITest(unittest.TestCase): + def test_update_after_digest(self): + msg = b("rrrrttt") - def test_update_after_digest(self): - msg=b("rrrrttt") + # Normally, update() cannot be done after digest() + h = SHA3.new(data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = SHA3.new(data=msg).digest() - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) + # With the proper flag, it is allowed + h = SHA3.new(data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-256.txt", - "KAT SHA-3 256", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - - tests += make_hash_tests(SHA3, "SHA3_256", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.8") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from .common import make_hash_tests + + tests = [] + + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHA3-256.txt", + "KAT SHA-3 256", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + if tv.len == 0: + tv.msg = b("") + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests += make_hash_tests( + SHA3, + "SHA3_256", + test_data, + digest_size=SHA3.digest_size, + oid="2.16.840.1.101.3.4.2.8", + ) + tests += list_test_cases(APITest) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_384.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_384.py index c5030b56..485576cc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_384.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_384.py @@ -32,48 +32,58 @@ class APITest(unittest.TestCase): + def test_update_after_digest(self): + msg = b("rrrrttt") - def test_update_after_digest(self): - msg=b("rrrrttt") + # Normally, update() cannot be done after digest() + h = SHA3.new(data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = SHA3.new(data=msg).digest() - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) + # With the proper flag, it is allowed + h = SHA3.new(data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-384.txt", - "KAT SHA-3 384", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests += make_hash_tests(SHA3, "SHA3_384", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.9") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from .common import make_hash_tests + + tests = [] + + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHA3-384.txt", + "KAT SHA-3 384", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + if tv.len == 0: + tv.msg = b("") + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests += make_hash_tests( + SHA3, + "SHA3_384", + test_data, + digest_size=SHA3.digest_size, + oid="2.16.840.1.101.3.4.2.9", + ) + tests += list_test_cases(APITest) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_512.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_512.py index b7a57f8f..35f54db6 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_512.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA3_512.py @@ -32,48 +32,58 @@ class APITest(unittest.TestCase): + def test_update_after_digest(self): + msg = b("rrrrttt") - def test_update_after_digest(self): - msg=b("rrrrttt") + # Normally, update() cannot be done after digest() + h = SHA3.new(data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = SHA3.new(data=msg).digest() - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) + # With the proper flag, it is allowed + h = SHA3.new(data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-512.txt", - "KAT SHA-3 512", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests += make_hash_tests(SHA3, "SHA3_512", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.10") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from .common import make_hash_tests + + tests = [] + + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHA3-512.txt", + "KAT SHA-3 512", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + if tv.len == 0: + tv.msg = b("") + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests += make_hash_tests( + SHA3, + "SHA3_512", + test_data, + digest_size=SHA3.digest_size, + oid="2.16.840.1.101.3.4.2.10", + ) + tests += list_test_cases(APITest) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA512.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA512.py index e6c74b36..861812a3 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA512.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHA512.py @@ -33,108 +33,144 @@ # Test vectors from various sources # This is a list of (expected_result, input[, description]) tuples. test_data_512_other = [ - - # RFC 4634: Section Page 8.4, "Test 1" - ('ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', 'abc'), - - # RFC 4634: Section Page 8.4, "Test 2.1" - ('8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'), - - # RFC 4634: Section Page 8.4, "Test 3" - ('e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b', 'a' * 10**6, "'a' * 10**6"), - - # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', ''), - - ('af9ed2de700433b803240a552b41b5a472a6ef3fe1431a722b2063c75e9f07451f67a28e37d09cde769424c96aea6f8971389db9e1993d6c565c3c71b855723c', 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), + # RFC 4634: Section Page 8.4, "Test 1" + ( + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + "abc", + ), + # RFC 4634: Section Page 8.4, "Test 2.1" + ( + "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909", + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + ), + # RFC 4634: Section Page 8.4, "Test 3" + ( + "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b", + "a" * 10**6, + "'a' * 10**6", + ), + # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ( + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + "", + ), + ( + "af9ed2de700433b803240a552b41b5a472a6ef3fe1431a722b2063c75e9f07451f67a28e37d09cde769424c96aea6f8971389db9e1993d6c565c3c71b855723c", + "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern", + ), ] def get_tests_SHA512(): - - test_vectors = load_test_vectors(("Hash", "SHA2"), - "SHA512ShortMsg.rsp", - "KAT SHA-512", - {"len": lambda x: int(x)}) or [] - - test_data = test_data_512_other[:] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA512, "SHA512", test_data, - digest_size=64, - oid="2.16.840.1.101.3.4.2.3") - return tests + test_vectors = ( + load_test_vectors( + ("Hash", "SHA2"), + "SHA512ShortMsg.rsp", + "KAT SHA-512", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = test_data_512_other[:] + for tv in test_vectors: + try: + if tv.startswith("["): + continue + except AttributeError: + pass + if tv.len == 0: + tv.msg = b"" + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests = make_hash_tests( + SHA512, + "SHA512", + test_data, + digest_size=64, + oid="2.16.840.1.101.3.4.2.3", + ) + return tests def get_tests_SHA512_224(): - - test_vectors = load_test_vectors(("Hash", "SHA2"), - "SHA512_224ShortMsg.rsp", - "KAT SHA-512/224", - {"len": lambda x: int(x)}) or [] - - test_data = [] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA512, "SHA512/224", test_data, - digest_size=28, - oid="2.16.840.1.101.3.4.2.5", - extra_params={ "truncate" : "224" }) - return tests + test_vectors = ( + load_test_vectors( + ("Hash", "SHA2"), + "SHA512_224ShortMsg.rsp", + "KAT SHA-512/224", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + try: + if tv.startswith("["): + continue + except AttributeError: + pass + if tv.len == 0: + tv.msg = b"" + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests = make_hash_tests( + SHA512, + "SHA512/224", + test_data, + digest_size=28, + oid="2.16.840.1.101.3.4.2.5", + extra_params={"truncate": "224"}, + ) + return tests def get_tests_SHA512_256(): - - test_vectors = load_test_vectors(("Hash", "SHA2"), - "SHA512_256ShortMsg.rsp", - "KAT SHA-512/256", - {"len": lambda x: int(x)}) or [] - - test_data = [] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA512, "SHA512/256", test_data, - digest_size=32, - oid="2.16.840.1.101.3.4.2.6", - extra_params={ "truncate" : "256" }) - return tests + test_vectors = ( + load_test_vectors( + ("Hash", "SHA2"), + "SHA512_256ShortMsg.rsp", + "KAT SHA-512/256", + {"len": lambda x: int(x)}, + ) + or [] + ) + + test_data = [] + for tv in test_vectors: + try: + if tv.startswith("["): + continue + except AttributeError: + pass + if tv.len == 0: + tv.msg = b"" + test_data.append((hexlify(tv.md), tv.msg, tv.desc)) + + tests = make_hash_tests( + SHA512, + "SHA512/256", + test_data, + digest_size=32, + oid="2.16.840.1.101.3.4.2.6", + extra_params={"truncate": "256"}, + ) + return tests def get_tests(config={}): + tests = [] + tests += get_tests_SHA512() + tests += get_tests_SHA512_224() + tests += get_tests_SHA512_256() + return tests + - tests = [] - tests += get_tests_SHA512() - tests += get_tests_SHA512_224() - tests += get_tests_SHA512_256() - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHAKE.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHAKE.py index 07965f62..d2284528 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHAKE.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_SHAKE.py @@ -31,121 +31,130 @@ """Self-test suite for Cryptodome.Hash.SHAKE128 and SHAKE256""" import unittest -from binascii import hexlify, unhexlify from Cryptodome.SelfTest.loader import load_test_vectors from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Hash import SHAKE128, SHAKE256 -from Cryptodome.Util.py3compat import b, bchr, bord, tobytes +from Cryptodome.Util.py3compat import b, bchr, tobytes -class SHAKETest(unittest.TestCase): - - def test_new_positive(self): - - xof1 = self.shake.new() - xof2 = self.shake.new(data=b("90")) - xof3 = self.shake.new().update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = self.shake.new() - h.update(pieces[0]).update(pieces[1]) - digest = h.read(10) - h = self.shake.new() - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.read(10), digest) - - def test_update_negative(self): - h = self.shake.new() - self.assertRaises(TypeError, h.update, u"string") - def test_digest(self): - h = self.shake.new() - digest = h.read(90) - - # read returns a byte string of the right length - self.assertTrue(isinstance(digest, type(b("digest")))) - self.assertEqual(len(digest), 90) - - def test_update_after_read(self): - mac = self.shake.new() - mac.update(b("rrrr")) - mac.read(90) - self.assertRaises(TypeError, mac.update, b("ttt")) - - def test_copy(self): - mac = self.shake.new() - mac.update(b("rrrr")) - mac2 = mac.copy() - x1 = mac.read(90) - x2 = mac2.read(90) - self.assertEqual(x1, x2) +class SHAKETest(unittest.TestCase): + def test_new_positive(self): + xof1 = self.shake.new() + xof2 = self.shake.new(data=b("90")) + xof3 = self.shake.new().update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] + h = self.shake.new() + h.update(pieces[0]).update(pieces[1]) + digest = h.read(10) + h = self.shake.new() + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.read(10), digest) + + def test_update_negative(self): + h = self.shake.new() + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = self.shake.new() + digest = h.read(90) + + # read returns a byte string of the right length + self.assertTrue(isinstance(digest, type(b("digest")))) + self.assertEqual(len(digest), 90) + + def test_update_after_read(self): + mac = self.shake.new() + mac.update(b("rrrr")) + mac.read(90) + self.assertRaises(TypeError, mac.update, b("ttt")) + + def test_copy(self): + mac = self.shake.new() + mac.update(b("rrrr")) + mac2 = mac.copy() + x1 = mac.read(90) + x2 = mac2.read(90) + self.assertEqual(x1, x2) class SHAKE128Test(SHAKETest): - shake = SHAKE128 + shake = SHAKE128 class SHAKE256Test(SHAKETest): - shake = SHAKE256 + shake = SHAKE256 class SHAKEVectors(unittest.TestCase): - pass + pass -test_vectors_128 = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHAKE128.txt", - "Short Messages KAT SHAKE128", - { "len" : lambda x: int(x) } ) or [] +test_vectors_128 = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHAKE128.txt", + "Short Messages KAT SHAKE128", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_128): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = SHAKE128.new(data=data) - digest = hobj.read(len(result)) - self.assertEqual(digest, result) + def new_test(self, data=data, result=tv.md): + hobj = SHAKE128.new(data=data) + digest = hobj.read(len(result)) + self.assertEqual(digest, result) - setattr(SHAKEVectors, "test_128_%d" % idx, new_test) + setattr(SHAKEVectors, "test_128_%d" % idx, new_test) -test_vectors_256 = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHAKE256.txt", - "Short Messages KAT SHAKE256", - { "len" : lambda x: int(x) } ) or [] +test_vectors_256 = ( + load_test_vectors( + ("Hash", "SHA3"), + "ShortMsgKAT_SHAKE256.txt", + "Short Messages KAT SHAKE256", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_256): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = SHAKE256.new(data=data) - digest = hobj.read(len(result)) - self.assertEqual(digest, result) + def new_test(self, data=data, result=tv.md): + hobj = SHAKE256.new(data=data) + digest = hobj.read(len(result)) + self.assertEqual(digest, result) - setattr(SHAKEVectors, "test_256_%d" % idx, new_test) + setattr(SHAKEVectors, "test_256_%d" % idx, new_test) def get_tests(config={}): - tests = [] - tests += list_test_cases(SHAKE128Test) - tests += list_test_cases(SHAKE256Test) - tests += list_test_cases(SHAKEVectors) - return tests + tests = [] + tests += list_test_cases(SHAKE128Test) + tests += list_test_cases(SHAKE256Test) + tests += list_test_cases(SHAKEVectors) + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_TupleHash.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_TupleHash.py index 2f93d7b3..bcd25524 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_TupleHash.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_TupleHash.py @@ -8,295 +8,293 @@ class TupleHashTest(unittest.TestCase): - - def new(self, *args, **kwargs): - return self.TupleHash.new(*args, **kwargs) - - def test_new_positive(self): - - h = self.new() - for new_func in self.TupleHash.new, h.new: - - for dbits in range(64, 1024 + 1, 8): - hobj = new_func(digest_bits=dbits) - self.assertEqual(hobj.digest_size * 8, dbits) - - for dbytes in range(8, 128 + 1): - hobj = new_func(digest_bytes=dbytes) - self.assertEqual(hobj.digest_size, dbytes) - - hobj = h.new() - self.assertEqual(hobj.digest_size, self.default_bytes) - - def test_new_negative(self): - - h = self.new() - for new_func in self.TupleHash.new, h.new: - self.assertRaises(TypeError, new_func, - digest_bytes=self.minimum_bytes, - digest_bits=self.minimum_bits) - self.assertRaises(ValueError, new_func, digest_bytes=0) - self.assertRaises(ValueError, new_func, - digest_bits=self.minimum_bits + 7) - self.assertRaises(ValueError, new_func, - digest_bits=self.minimum_bits - 8) - self.assertRaises(ValueError, new_func, - digest_bits=self.minimum_bytes - 1) - - def test_default_digest_size(self): - digest = self.new().digest() - self.assertEqual(len(digest), self.default_bytes) - - def test_update(self): - h = self.new() - h.update(b'') - h.digest() - - h = self.new() - h.update(b'') - h.update(b'STRING1') - h.update(b'STRING2') - mac1 = h.digest() - - h = self.new() - h.update(b'STRING1') - h.update(b'STRING2') - mac2 = h.digest() - self.assertNotEqual(mac1, mac2) - - h = self.new() - h.update(b'STRING1', b'STRING2') - self.assertEqual(mac2, h.digest()) - - h = self.new() - t = b'STRING1', b'STRING2' - h.update(*t) - self.assertEqual(mac2, h.digest()) - - def test_update_negative(self): - h = self.new() - self.assertRaises(TypeError, h.update, u"string") - self.assertRaises(TypeError, h.update, None) - self.assertRaises(TypeError, h.update, (b'STRING1', b'STRING2')) - - def test_digest(self): - h = self.new() - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg = b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = self.new() - h.update(msg) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, dig1) - - def test_hex_digest(self): - mac = self.new() - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_bytearray(self): - - data = b"\x00\x01\x02" - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = self.new() - h2 = self.new() - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = self.new() - h2 = self.new() - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) + def new(self, *args, **kwargs): + return self.TupleHash.new(*args, **kwargs) + + def test_new_positive(self): + h = self.new() + for new_func in self.TupleHash.new, h.new: + for dbits in range(64, 1024 + 1, 8): + hobj = new_func(digest_bits=dbits) + self.assertEqual(hobj.digest_size * 8, dbits) + + for dbytes in range(8, 128 + 1): + hobj = new_func(digest_bytes=dbytes) + self.assertEqual(hobj.digest_size, dbytes) + + hobj = h.new() + self.assertEqual(hobj.digest_size, self.default_bytes) + + def test_new_negative(self): + h = self.new() + for new_func in self.TupleHash.new, h.new: + self.assertRaises( + TypeError, + new_func, + digest_bytes=self.minimum_bytes, + digest_bits=self.minimum_bits, + ) + self.assertRaises(ValueError, new_func, digest_bytes=0) + self.assertRaises( + ValueError, + new_func, + digest_bits=self.minimum_bits + 7, + ) + self.assertRaises( + ValueError, + new_func, + digest_bits=self.minimum_bits - 8, + ) + self.assertRaises( + ValueError, + new_func, + digest_bits=self.minimum_bytes - 1, + ) + + def test_default_digest_size(self): + digest = self.new().digest() + self.assertEqual(len(digest), self.default_bytes) + + def test_update(self): + h = self.new() + h.update(b"") + h.digest() + + h = self.new() + h.update(b"") + h.update(b"STRING1") + h.update(b"STRING2") + mac1 = h.digest() + + h = self.new() + h.update(b"STRING1") + h.update(b"STRING2") + mac2 = h.digest() + self.assertNotEqual(mac1, mac2) + + h = self.new() + h.update(b"STRING1", b"STRING2") + self.assertEqual(mac2, h.digest()) + + h = self.new() + t = b"STRING1", b"STRING2" + h.update(*t) + self.assertEqual(mac2, h.digest()) + + def test_update_negative(self): + h = self.new() + self.assertRaises(TypeError, h.update, "string") + self.assertRaises(TypeError, h.update, None) + self.assertRaises(TypeError, h.update, (b"STRING1", b"STRING2")) + + def test_digest(self): + h = self.new() + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b"digest"))) + + def test_update_after_digest(self): + msg = b"rrrrttt" + + # Normally, update() cannot be done after digest() + h = self.new() + h.update(msg) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, dig1) + + def test_hex_digest(self): + mac = self.new() + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_bytearray(self): + data = b"\x00\x01\x02" + + # Data can be a bytearray (during operation) + data_ba = bytearray(data) + + h1 = self.new() + h2 = self.new() + h1.update(data) + h2.update(data_ba) + data_ba[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) + + def test_memoryview(self): + data = b"\x00\x01\x02" + + def get_mv_ro(data): + return memoryview(data) + + def get_mv_rw(data): + return memoryview(bytearray(data)) + + for get_mv in (get_mv_ro, get_mv_rw): + # Data can be a memoryview (during operation) + data_mv = get_mv(data) + + h1 = self.new() + h2 = self.new() + h1.update(data) + h2.update(data_mv) + if not data_mv.readonly: + data_mv[:1] = b"\xff" + + self.assertEqual(h1.digest(), h2.digest()) class TupleHash128Test(TupleHashTest): + TupleHash = TupleHash128 - TupleHash = TupleHash128 - - minimum_bytes = 8 - default_bytes = 64 + minimum_bytes = 8 + default_bytes = 64 - minimum_bits = 64 - default_bits = 512 + minimum_bits = 64 + default_bits = 512 class TupleHash256Test(TupleHashTest): + TupleHash = TupleHash256 - TupleHash = TupleHash256 + minimum_bytes = 8 + default_bytes = 64 - minimum_bytes = 8 - default_bytes = 64 - - minimum_bits = 64 - default_bits = 512 + minimum_bits = 64 + default_bits = 512 class NISTExampleTestVectors(unittest.TestCase): + # http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TupleHash_samples.pdf + test_data = [ + ( + ( + "00 01 02", + "10 11 12 13 14 15", + ), + "", + "C5 D8 78 6C 1A FB 9B 82 11 1A B3 4B 65 B2 C0 048F A6 4E 6D 48 E2 63 26 4C E1 70 7D 3F FC 8E D1", + "KMAC128 Sample #1 NIST", + TupleHash128, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + ), + "My Tuple App", + "75 CD B2 0F F4 DB 11 54 E8 41 D7 58 E2 41 60 C54B AE 86 EB 8C 13 E7 F5 F4 0E B3 55 88 E9 6D FB", + "KMAC128 Sample #2 NIST", + TupleHash128, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + "20 21 22 23 24 25 26 27 28", + ), + "My Tuple App", + "E6 0F 20 2C 89 A2 63 1E DA 8D 4C 58 8C A5 FD 07F3 9E 51 51 99 8D EC CF 97 3A DB 38 04 BB 6E 84", + "KMAC128 Sample #3 NIST", + TupleHash128, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + ), + "", + "CF B7 05 8C AC A5 E6 68 F8 1A 12 A2 0A 21 95 CE" + "97 A9 25 F1 DB A3 E7 44 9A 56 F8 22 01 EC 60 73" + "11 AC 26 96 B1 AB 5E A2 35 2D F1 42 3B DE 7B D4" + "BB 78 C9 AE D1 A8 53 C7 86 72 F9 EB 23 BB E1 94", + "KMAC256 Sample #4 NIST", + TupleHash256, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + ), + "My Tuple App", + "14 7C 21 91 D5 ED 7E FD 98 DB D9 6D 7A B5 A1 16" + "92 57 6F 5F E2 A5 06 5F 3E 33 DE 6B BA 9F 3A A1" + "C4 E9 A0 68 A2 89 C6 1C 95 AA B3 0A EE 1E 41 0B" + "0B 60 7D E3 62 0E 24 A4 E3 BF 98 52 A1 D4 36 7E", + "KMAC256 Sample #5 NIST", + TupleHash256, + ), + ( + ( + "00 01 02", + "10 11 12 13 14 15", + "20 21 22 23 24 25 26 27 28", + ), + "My Tuple App", + "45 00 0B E6 3F 9B 6B FD 89 F5 47 17 67 0F 69 A9" + "BC 76 35 91 A4 F0 5C 50 D6 88 91 A7 44 BC C6 E7" + "D6 D5 B5 E8 2C 01 8D A9 99 ED 35 B0 BB 49 C9 67" + "8E 52 6A BD 8E 85 C1 3E D2 54 02 1D B9 E7 90 CE", + "KMAC256 Sample #6 NIST", + TupleHash256, + ), + ] + + def setUp(self): + td = [] + for tv_in in self.test_data: + tv_out = [None] * len(tv_in) + + tv_out[0] = [] + for string in tv_in[0]: + tv_out[0].append(unhexlify(string.replace(" ", ""))) + + tv_out[1] = tobytes(tv_in[1]) # Custom + tv_out[2] = unhexlify(tv_in[2].replace(" ", "")) + tv_out[3] = tv_in[3] + tv_out[4] = tv_in[4] + td.append(tv_out) + self.test_data = td + + def runTest(self): + for data, custom, digest, text, module in self.test_data: + hd1 = module.new(custom=custom, digest_bytes=len(digest)) + hd2 = module.new(custom=custom, digest_bytes=len(digest)) + + # Call update() for each element + for string in data: + hd1.update(string) + + # One single update for all elements + hd2.update(*data) + + self.assertEqual(hd1.digest(), digest, msg=text) + self.assertEqual(hd2.digest(), digest, msg=text) - # http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TupleHash_samples.pdf - test_data = [ - ( - ( - "00 01 02", - "10 11 12 13 14 15", - ), - "", - "C5 D8 78 6C 1A FB 9B 82 11 1A B3 4B 65 B2 C0 04" - "8F A6 4E 6D 48 E2 63 26 4C E1 70 7D 3F FC 8E D1", - "KMAC128 Sample #1 NIST", - TupleHash128 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - ), - "My Tuple App", - "75 CD B2 0F F4 DB 11 54 E8 41 D7 58 E2 41 60 C5" - "4B AE 86 EB 8C 13 E7 F5 F4 0E B3 55 88 E9 6D FB", - "KMAC128 Sample #2 NIST", - TupleHash128 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - "20 21 22 23 24 25 26 27 28", - ), - "My Tuple App", - "E6 0F 20 2C 89 A2 63 1E DA 8D 4C 58 8C A5 FD 07" - "F3 9E 51 51 99 8D EC CF 97 3A DB 38 04 BB 6E 84", - "KMAC128 Sample #3 NIST", - TupleHash128 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - ), - "", - "CF B7 05 8C AC A5 E6 68 F8 1A 12 A2 0A 21 95 CE" - "97 A9 25 F1 DB A3 E7 44 9A 56 F8 22 01 EC 60 73" - "11 AC 26 96 B1 AB 5E A2 35 2D F1 42 3B DE 7B D4" - "BB 78 C9 AE D1 A8 53 C7 86 72 F9 EB 23 BB E1 94", - "KMAC256 Sample #4 NIST", - TupleHash256 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - ), - "My Tuple App", - "14 7C 21 91 D5 ED 7E FD 98 DB D9 6D 7A B5 A1 16" - "92 57 6F 5F E2 A5 06 5F 3E 33 DE 6B BA 9F 3A A1" - "C4 E9 A0 68 A2 89 C6 1C 95 AA B3 0A EE 1E 41 0B" - "0B 60 7D E3 62 0E 24 A4 E3 BF 98 52 A1 D4 36 7E", - "KMAC256 Sample #5 NIST", - TupleHash256 - ), - ( - ( - "00 01 02", - "10 11 12 13 14 15", - "20 21 22 23 24 25 26 27 28", - ), - "My Tuple App", - "45 00 0B E6 3F 9B 6B FD 89 F5 47 17 67 0F 69 A9" - "BC 76 35 91 A4 F0 5C 50 D6 88 91 A7 44 BC C6 E7" - "D6 D5 B5 E8 2C 01 8D A9 99 ED 35 B0 BB 49 C9 67" - "8E 52 6A BD 8E 85 C1 3E D2 54 02 1D B9 E7 90 CE", - "KMAC256 Sample #6 NIST", - TupleHash256 - ), - - - - ] - - def setUp(self): - td = [] - for tv_in in self.test_data: - tv_out = [None] * len(tv_in) - - tv_out[0] = [] - for string in tv_in[0]: - tv_out[0].append(unhexlify(string.replace(" ", ""))) - - tv_out[1] = tobytes(tv_in[1]) # Custom - tv_out[2] = unhexlify(tv_in[2].replace(" ", "")) - tv_out[3] = tv_in[3] - tv_out[4] = tv_in[4] - td.append(tv_out) - self.test_data = td - - def runTest(self): - - for data, custom, digest, text, module in self.test_data: - hd1 = module.new(custom=custom, digest_bytes=len(digest)) - hd2 = module.new(custom=custom, digest_bytes=len(digest)) - - # Call update() for each element - for string in data: - hd1.update(string) - - # One single update for all elements - hd2.update(*data) - - self.assertEqual(hd1.digest(), digest, msg=text) - self.assertEqual(hd2.digest(), digest, msg=text) def get_tests(config={}): - tests = [] + tests = [] + + tests += list_test_cases(TupleHash128Test) + tests += list_test_cases(TupleHash256Test) + tests.append(NISTExampleTestVectors()) + + return tests - tests += list_test_cases(TupleHash128Test) - tests += list_test_cases(TupleHash256Test) - tests.append(NISTExampleTestVectors()) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_TurboSHAKE.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_TurboSHAKE.py index 7c13d1e6..3b253211 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_TurboSHAKE.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_TurboSHAKE.py @@ -10,459 +10,457 @@ class TurboSHAKETest(unittest.TestCase): + def test_new_positive(self): + xof1 = self.TurboSHAKE.new() + xof1.update(b"90") - def test_new_positive(self): + xof2 = self.TurboSHAKE.new(domain=0x1F) + xof2.update(b"90") - xof1 = self.TurboSHAKE.new() - xof1.update(b'90') + xof3 = self.TurboSHAKE.new(data=b"90") - xof2 = self.TurboSHAKE.new(domain=0x1F) - xof2.update(b'90') + out1 = xof1.read(128) + out2 = xof2.read(128) + out3 = xof3.read(128) - xof3 = self.TurboSHAKE.new(data=b'90') + self.assertEqual(out1, out2) + self.assertEqual(out1, out3) - out1 = xof1.read(128) - out2 = xof2.read(128) - out3 = xof3.read(128) + def test_new_domain(self): + xof1 = self.TurboSHAKE.new(domain=0x1D) + xof2 = self.TurboSHAKE.new(domain=0x20) + self.assertNotEqual(xof1.read(128), xof2.read(128)) - self.assertEqual(out1, out2) - self.assertEqual(out1, out3) + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] - def test_new_domain(self): - xof1 = self.TurboSHAKE.new(domain=0x1D) - xof2 = self.TurboSHAKE.new(domain=0x20) - self.assertNotEqual(xof1.read(128), xof2.read(128)) + xof1 = self.TurboSHAKE.new() + xof1.update(pieces[0]).update(pieces[1]) + digest1 = xof1.read(10) - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] + xof2 = self.TurboSHAKE.new() + xof2.update(pieces[0] + pieces[1]) + digest2 = xof2.read(10) - xof1 = self.TurboSHAKE.new() - xof1.update(pieces[0]).update(pieces[1]) - digest1 = xof1.read(10) + self.assertEqual(digest1, digest2) - xof2 = self.TurboSHAKE.new() - xof2.update(pieces[0] + pieces[1]) - digest2 = xof2.read(10) + def test_update_negative(self): + xof1 = self.TurboSHAKE.new() + self.assertRaises(TypeError, xof1.update, "string") - self.assertEqual(digest1, digest2) + def test_read(self): + xof1 = self.TurboSHAKE.new() + digest = xof1.read(90) - def test_update_negative(self): - xof1 = self.TurboSHAKE.new() - self.assertRaises(TypeError, xof1.update, u"string") + # read returns a byte string of the right length + self.assertTrue(isinstance(digest, bytes)) + self.assertEqual(len(digest), 90) - def test_read(self): - xof1 = self.TurboSHAKE.new() - digest = xof1.read(90) + def test_update_after_read(self): + xof1 = self.TurboSHAKE.new() + xof1.update(b"rrrr") + xof1.read(90) + self.assertRaises(TypeError, xof1.update, b"ttt") - # read returns a byte string of the right length - self.assertTrue(isinstance(digest, bytes)) - self.assertEqual(len(digest), 90) + def test_new(self): + xof1 = self.TurboSHAKE.new(domain=0x07) + xof1.update(b"90") + digest1 = xof1.read(100) - def test_update_after_read(self): - xof1 = self.TurboSHAKE.new() - xof1.update(b"rrrr") - xof1.read(90) - self.assertRaises(TypeError, xof1.update, b"ttt") + xof2 = xof1.new() + xof2.update(b"90") + digest2 = xof2.read(100) - def test_new(self): - xof1 = self.TurboSHAKE.new(domain=0x07) - xof1.update(b'90') - digest1 = xof1.read(100) + self.assertEqual(digest1, digest2) - xof2 = xof1.new() - xof2.update(b'90') - digest2 = xof2.read(100) - - self.assertEqual(digest1, digest2) - - self.assertRaises(TypeError, xof1.new, domain=0x07) + self.assertRaises(TypeError, xof1.new, domain=0x07) class TurboSHAKE128Test(TurboSHAKETest): - TurboSHAKE = TurboSHAKE128 + TurboSHAKE = TurboSHAKE128 class TurboSHAKE256Test(TurboSHAKETest): - TurboSHAKE = TurboSHAKE256 + TurboSHAKE = TurboSHAKE256 def txt2bin(txt): - clean = txt.replace(" ", "").replace("\n", "").replace("\r", "") - return unhexlify(clean) + clean = txt.replace(" ", "").replace("\n", "").replace("\r", "") + return unhexlify(clean) def ptn(n): - res = bytearray(n) - pattern = b"".join([bchr(x) for x in range(0, 0xFB)]) - for base in range(0, n - 0xFB, 0xFB): - res[base:base + 0xFB] = pattern - remain = n % 0xFB - if remain: - base = (n // 0xFB) * 0xFB - res[base:] = pattern[:remain] - assert len(res) == n - return res + res = bytearray(n) + pattern = b"".join([bchr(x) for x in range(0, 0xFB)]) + for base in range(0, n - 0xFB, 0xFB): + res[base : base + 0xFB] = pattern + remain = n % 0xFB + if remain: + base = (n // 0xFB) * 0xFB + res[base:] = pattern[:remain] + assert len(res) == n + return res def chunked(source, size): - for i in range(0, len(source), size): - yield source[i:i+size] + for i in range(0, len(source), size): + yield source[i : i + size] class TurboSHAKE128TV(unittest.TestCase): - - def test_zero_1(self): - tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53 + def test_zero_1(self): + tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53 8C D9 45 A3 97 DD EC 54 1F 1C E4 1A F2 C1 B7 4C""" - btv = txt2bin(tv) - res = TurboSHAKE128.new().read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new().read(32) + self.assertEqual(res, btv) - def test_zero_2(self): - tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53 + def test_zero_2(self): + tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53 8C D9 45 A3 97 DD EC 54 1F 1C E4 1A F2 C1 B7 4C 3E 8C CA E2 A4 DA E5 6C 84 A0 4C 23 85 C0 3C 15 E8 19 3B DF 58 73 73 63 32 16 91 C0 54 62 C8 DF""" - btv = txt2bin(tv) - res = TurboSHAKE128.new().read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new().read(64) + self.assertEqual(res, btv) - def test_zero_3(self): - tv = """A3 B9 B0 38 59 00 CE 76 1F 22 AE D5 48 E7 54 DA + def test_zero_3(self): + tv = """A3 B9 B0 38 59 00 CE 76 1F 22 AE D5 48 E7 54 DA 10 A5 24 2D 62 E8 C6 58 E3 F3 A9 23 A7 55 56 07""" - btv = txt2bin(tv) - res = TurboSHAKE128.new().read(10032)[-32:] - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new().read(10032)[-32:] + self.assertEqual(res, btv) - def test_ptn_1(self): - tv = """55 CE DD 6F 60 AF 7B B2 9A 40 42 AE 83 2E F3 F5 + def test_ptn_1(self): + tv = """55 CE DD 6F 60 AF 7B B2 9A 40 42 AE 83 2E F3 F5 8D B7 29 9F 89 3E BB 92 47 24 7D 85 69 58 DA A9""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=ptn(1)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=ptn(1)).read(32) + self.assertEqual(res, btv) - def test_ptn_17(self): - tv = """9C 97 D0 36 A3 BA C8 19 DB 70 ED E0 CA 55 4E C6 + def test_ptn_17(self): + tv = """9C 97 D0 36 A3 BA C8 19 DB 70 ED E0 CA 55 4E C6 E4 C2 A1 A4 FF BF D9 EC 26 9C A6 A1 11 16 12 33""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=ptn(17)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=ptn(17)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_2(self): - tv = """96 C7 7C 27 9E 01 26 F7 FC 07 C9 B0 7F 5C DA E1 + def test_ptn_17_2(self): + tv = """96 C7 7C 27 9E 01 26 F7 FC 07 C9 B0 7F 5C DA E1 E0 BE 60 BD BE 10 62 00 40 E7 5D 72 23 A6 24 D2""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=ptn(17**2)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=ptn(17**2)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_3(self): - tv = """D4 97 6E B5 6B CF 11 85 20 58 2B 70 9F 73 E1 D6 + def test_ptn_17_3(self): + tv = """D4 97 6E B5 6B CF 11 85 20 58 2B 70 9F 73 E1 D6 85 3E 00 1F DA F8 0E 1B 13 E0 D0 59 9D 5F B3 72""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=ptn(17**3)).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=ptn(17**3)).read(32) + self.assertEqual(res, btv) - def test_ptn_17_4(self): - tv = """DA 67 C7 03 9E 98 BF 53 0C F7 A3 78 30 C6 66 4E + def test_ptn_17_4(self): + tv = """DA 67 C7 03 9E 98 BF 53 0C F7 A3 78 30 C6 66 4E 14 CB AB 7F 54 0F 58 40 3B 1B 82 95 13 18 EE 5C""" - btv = txt2bin(tv) - data = ptn(17**4) - - # All at once - res = TurboSHAKE128.new(data=data).read(32) - self.assertEqual(res, btv) - - # Byte by byte - xof = TurboSHAKE128.new() - for x in data: - xof.update(bchr(x)) - res = xof.read(32) - self.assertEqual(res, btv) - - # Chunks of various prime sizes - for chunk_size in (13, 17, 19, 23, 31): - xof = TurboSHAKE128.new() - for x in chunked(data, chunk_size): - xof.update(x) - res = xof.read(32) - self.assertEqual(res, btv) - - def test_ptn_17_5(self): - tv = """B9 7A 90 6F BF 83 EF 7C 81 25 17 AB F3 B2 D0 AE + btv = txt2bin(tv) + data = ptn(17**4) + + # All at once + res = TurboSHAKE128.new(data=data).read(32) + self.assertEqual(res, btv) + + # Byte by byte + xof = TurboSHAKE128.new() + for x in data: + xof.update(bchr(x)) + res = xof.read(32) + self.assertEqual(res, btv) + + # Chunks of various prime sizes + for chunk_size in (13, 17, 19, 23, 31): + xof = TurboSHAKE128.new() + for x in chunked(data, chunk_size): + xof.update(x) + res = xof.read(32) + self.assertEqual(res, btv) + + def test_ptn_17_5(self): + tv = """B9 7A 90 6F BF 83 EF 7C 81 25 17 AB F3 B2 D0 AE A0 C4 F6 03 18 CE 11 CF 10 39 25 12 7F 59 EE CD""" - btv = txt2bin(tv) - data = ptn(17**5) + btv = txt2bin(tv) + data = ptn(17**5) - # All at once - res = TurboSHAKE128.new(data=data).read(32) - self.assertEqual(res, btv) + # All at once + res = TurboSHAKE128.new(data=data).read(32) + self.assertEqual(res, btv) - # Chunks - xof = TurboSHAKE128.new() - for chunk in chunked(data, 8192): - xof.update(chunk) - res = xof.read(32) - self.assertEqual(res, btv) + # Chunks + xof = TurboSHAKE128.new() + for chunk in chunked(data, 8192): + xof.update(chunk) + res = xof.read(32) + self.assertEqual(res, btv) - def test_ptn_17_6(self): - tv = """35 CD 49 4A DE DE D2 F2 52 39 AF 09 A7 B8 EF 0C + def test_ptn_17_6(self): + tv = """35 CD 49 4A DE DE D2 F2 52 39 AF 09 A7 B8 EF 0C 4D 1C A4 FE 2D 1A C3 70 FA 63 21 6F E7 B4 C2 B1""" - btv = txt2bin(tv) - data = ptn(17**6) + btv = txt2bin(tv) + data = ptn(17**6) - res = TurboSHAKE128.new(data=data).read(32) - self.assertEqual(res, btv) + res = TurboSHAKE128.new(data=data).read(32) + self.assertEqual(res, btv) - def test_ffffff_d01(self): - tv = """BF 32 3F 94 04 94 E8 8E E1 C5 40 FE 66 0B E8 A0 + def test_ffffff_d01(self): + tv = """BF 32 3F 94 04 94 E8 8E E1 C5 40 FE 66 0B E8 A0 C9 3F 43 D1 5E C0 06 99 84 62 FA 99 4E ED 5D AB""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b"\xff\xff\xff", domain=0x01).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff\xff\xff", domain=0x01).read(32) + self.assertEqual(res, btv) - def test_ff_d06(self): - tv = """8E C9 C6 64 65 ED 0D 4A 6C 35 D1 35 06 71 8D 68 + def test_ff_d06(self): + tv = """8E C9 C6 64 65 ED 0D 4A 6C 35 D1 35 06 71 8D 68 7A 25 CB 05 C7 4C CA 1E 42 50 1A BD 83 87 4A 67""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF', domain=0x06).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff", domain=0x06).read(32) + self.assertEqual(res, btv) - def test_ffffff_d07(self): - tv = """B6 58 57 60 01 CA D9 B1 E5 F3 99 A9 F7 77 23 BB + def test_ffffff_d07(self): + tv = """B6 58 57 60 01 CA D9 B1 E5 F3 99 A9 F7 77 23 BB A0 54 58 04 2D 68 20 6F 72 52 68 2D BA 36 63 ED""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF' * 3, domain=0x07).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff" * 3, domain=0x07).read(32) + self.assertEqual(res, btv) - def test_ffffffffffff_d0b(self): - tv = """8D EE AA 1A EC 47 CC EE 56 9F 65 9C 21 DF A8 E1 + def test_ffffffffffff_d0b(self): + tv = """8D EE AA 1A EC 47 CC EE 56 9F 65 9C 21 DF A8 E1 12 DB 3C EE 37 B1 81 78 B2 AC D8 05 B7 99 CC 37""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF' * 7, domain=0x0B).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff" * 7, domain=0x0B).read(32) + self.assertEqual(res, btv) - def test_ff_d30(self): - tv = """55 31 22 E2 13 5E 36 3C 32 92 BE D2 C6 42 1F A2 + def test_ff_d30(self): + tv = """55 31 22 E2 13 5E 36 3C 32 92 BE D2 C6 42 1F A2 32 BA B0 3D AA 07 C7 D6 63 66 03 28 65 06 32 5B""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF', domain=0x30).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff", domain=0x30).read(32) + self.assertEqual(res, btv) - def test_ffffff_d7f(self): - tv = """16 27 4C C6 56 D4 4C EF D4 22 39 5D 0F 90 53 BD + def test_ffffff_d7f(self): + tv = """16 27 4C C6 56 D4 4C EF D4 22 39 5D 0F 90 53 BD A6 D2 8E 12 2A BA 15 C7 65 E5 AD 0E 6E AF 26 F9""" - btv = txt2bin(tv) - res = TurboSHAKE128.new(data=b'\xFF' * 3, domain=0x7F).read(32) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE128.new(data=b"\xff" * 3, domain=0x7F).read(32) + self.assertEqual(res, btv) class TurboSHAKE256TV(unittest.TestCase): - - def test_zero_1(self): - tv = """36 7A 32 9D AF EA 87 1C 78 02 EC 67 F9 05 AE 13 + def test_zero_1(self): + tv = """36 7A 32 9D AF EA 87 1C 78 02 EC 67 F9 05 AE 13 C5 76 95 DC 2C 66 63 C6 10 35 F5 9A 18 F8 E7 DB 11 ED C0 E1 2E 91 EA 60 EB 6B 32 DF 06 DD 7F 00 2F BA FA BB 6E 13 EC 1C C2 0D 99 55 47 60 0D B0""" - btv = txt2bin(tv) - res = TurboSHAKE256.new().read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new().read(64) + self.assertEqual(res, btv) - def test_zero_2(self): - tv = """AB EF A1 16 30 C6 61 26 92 49 74 26 85 EC 08 2F + def test_zero_2(self): + tv = """AB EF A1 16 30 C6 61 26 92 49 74 26 85 EC 08 2F 20 72 65 DC CF 2F 43 53 4E 9C 61 BA 0C 9D 1D 75""" - btv = txt2bin(tv) - res = TurboSHAKE256.new().read(10032)[-32:] - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new().read(10032)[-32:] + self.assertEqual(res, btv) - def test_ptn_1(self): - tv = """3E 17 12 F9 28 F8 EA F1 05 46 32 B2 AA 0A 24 6E + def test_ptn_1(self): + tv = """3E 17 12 F9 28 F8 EA F1 05 46 32 B2 AA 0A 24 6E D8 B0 C3 78 72 8F 60 BC 97 04 10 15 5C 28 82 0E 90 CC 90 D8 A3 00 6A A2 37 2C 5C 5E A1 76 B0 68 2B F2 2B AE 74 67 AC 94 F7 4D 43 D3 9B 04 82 E2""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=ptn(1)).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=ptn(1)).read(64) + self.assertEqual(res, btv) - def test_ptn_17(self): - tv = """B3 BA B0 30 0E 6A 19 1F BE 61 37 93 98 35 92 35 + def test_ptn_17(self): + tv = """B3 BA B0 30 0E 6A 19 1F BE 61 37 93 98 35 92 35 78 79 4E A5 48 43 F5 01 10 90 FA 2F 37 80 A9 E5 CB 22 C5 9D 78 B4 0A 0F BF F9 E6 72 C0 FB E0 97 0B D2 C8 45 09 1C 60 44 D6 87 05 4D A5 D8 E9 C7""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=ptn(17)).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=ptn(17)).read(64) + self.assertEqual(res, btv) - def test_ptn_17_2(self): - tv = """66 B8 10 DB 8E 90 78 04 24 C0 84 73 72 FD C9 57 + def test_ptn_17_2(self): + tv = """66 B8 10 DB 8E 90 78 04 24 C0 84 73 72 FD C9 57 10 88 2F DE 31 C6 DF 75 BE B9 D4 CD 93 05 CF CA E3 5E 7B 83 E8 B7 E6 EB 4B 78 60 58 80 11 63 16 FE 2C 07 8A 09 B9 4A D7 B8 21 3C 0A 73 8B 65 C0""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=ptn(17**2)).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=ptn(17**2)).read(64) + self.assertEqual(res, btv) - def test_ptn_17_3(self): - tv = """C7 4E BC 91 9A 5B 3B 0D D1 22 81 85 BA 02 D2 9E + def test_ptn_17_3(self): + tv = """C7 4E BC 91 9A 5B 3B 0D D1 22 81 85 BA 02 D2 9E F4 42 D6 9D 3D 42 76 A9 3E FE 0B F9 A1 6A 7D C0 CD 4E AB AD AB 8C D7 A5 ED D9 66 95 F5 D3 60 AB E0 9E 2C 65 11 A3 EC 39 7D A3 B7 6B 9E 16 74 FB""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=ptn(17**3)).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=ptn(17**3)).read(64) + self.assertEqual(res, btv) - def test_ptn_17_4(self): - tv = """02 CC 3A 88 97 E6 F4 F6 CC B6 FD 46 63 1B 1F 52 + def test_ptn_17_4(self): + tv = """02 CC 3A 88 97 E6 F4 F6 CC B6 FD 46 63 1B 1F 52 07 B6 6C 6D E9 C7 B5 5B 2D 1A 23 13 4A 17 0A FD AC 23 4E AB A9 A7 7C FF 88 C1 F0 20 B7 37 24 61 8C 56 87 B3 62 C4 30 B2 48 CD 38 64 7F 84 8A 1D""" - btv = txt2bin(tv) - data = ptn(17**4) - - # All at once - res = TurboSHAKE256.new(data=data).read(64) - self.assertEqual(res, btv) - - # Byte by byte - xof = TurboSHAKE256.new() - for x in data: - xof.update(bchr(x)) - res = xof.read(64) - self.assertEqual(res, btv) - - # Chunks of various prime sizes - for chunk_size in (13, 17, 19, 23, 31): - xof = TurboSHAKE256.new() - for x in chunked(data, chunk_size): - xof.update(x) - res = xof.read(64) - self.assertEqual(res, btv) - - def test_ptn_17_5(self): - tv = """AD D5 3B 06 54 3E 58 4B 58 23 F6 26 99 6A EE 50 + btv = txt2bin(tv) + data = ptn(17**4) + + # All at once + res = TurboSHAKE256.new(data=data).read(64) + self.assertEqual(res, btv) + + # Byte by byte + xof = TurboSHAKE256.new() + for x in data: + xof.update(bchr(x)) + res = xof.read(64) + self.assertEqual(res, btv) + + # Chunks of various prime sizes + for chunk_size in (13, 17, 19, 23, 31): + xof = TurboSHAKE256.new() + for x in chunked(data, chunk_size): + xof.update(x) + res = xof.read(64) + self.assertEqual(res, btv) + + def test_ptn_17_5(self): + tv = """AD D5 3B 06 54 3E 58 4B 58 23 F6 26 99 6A EE 50 FE 45 ED 15 F2 02 43 A7 16 54 85 AC B4 AA 76 B4 FF DA 75 CE DF 6D 8C DC 95 C3 32 BD 56 F4 B9 86 B5 8B B1 7D 17 78 BF C1 B1 A9 75 45 CD F4 EC 9F""" - btv = txt2bin(tv) - data = ptn(17**5) + btv = txt2bin(tv) + data = ptn(17**5) - # All at once - res = TurboSHAKE256.new(data=data).read(64) - self.assertEqual(res, btv) + # All at once + res = TurboSHAKE256.new(data=data).read(64) + self.assertEqual(res, btv) - # Chunks - xof = TurboSHAKE256.new() - for chunk in chunked(data, 8192): - xof.update(chunk) - res = xof.read(64) - self.assertEqual(res, btv) + # Chunks + xof = TurboSHAKE256.new() + for chunk in chunked(data, 8192): + xof.update(chunk) + res = xof.read(64) + self.assertEqual(res, btv) - def test_ptn_17_6(self): - tv = """9E 11 BC 59 C2 4E 73 99 3C 14 84 EC 66 35 8E F7 + def test_ptn_17_6(self): + tv = """9E 11 BC 59 C2 4E 73 99 3C 14 84 EC 66 35 8E F7 1D B7 4A EF D8 4E 12 3F 78 00 BA 9C 48 53 E0 2C FE 70 1D 9E 6B B7 65 A3 04 F0 DC 34 A4 EE 3B A8 2C 41 0F 0D A7 0E 86 BF BD 90 EA 87 7C 2D 61 04""" - btv = txt2bin(tv) - data = ptn(17**6) + btv = txt2bin(tv) + data = ptn(17**6) - res = TurboSHAKE256.new(data=data).read(64) - self.assertEqual(res, btv) + res = TurboSHAKE256.new(data=data).read(64) + self.assertEqual(res, btv) - def test_ffffff_d01(self): - tv = """D2 1C 6F BB F5 87 FA 22 82 F2 9A EA 62 01 75 FB + def test_ffffff_d01(self): + tv = """D2 1C 6F BB F5 87 FA 22 82 F2 9A EA 62 01 75 FB 02 57 41 3A F7 8A 0B 1B 2A 87 41 9C E0 31 D9 33 AE 7A 4D 38 33 27 A8 A1 76 41 A3 4F 8A 1D 10 03 AD 7D A6 B7 2D BA 84 BB 62 FE F2 8F 62 F1 24 24""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b"\xff\xff\xff", domain=0x01).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff\xff\xff", domain=0x01).read(64) + self.assertEqual(res, btv) - def test_ff_d06(self): - tv = """73 8D 7B 4E 37 D1 8B 7F 22 AD 1B 53 13 E3 57 E3 + def test_ff_d06(self): + tv = """73 8D 7B 4E 37 D1 8B 7F 22 AD 1B 53 13 E3 57 E3 DD 7D 07 05 6A 26 A3 03 C4 33 FA 35 33 45 52 80 F4 F5 A7 D4 F7 00 EF B4 37 FE 6D 28 14 05 E0 7B E3 2A 0A 97 2E 22 E6 3A DC 1B 09 0D AE FE 00 4B""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF', domain=0x06).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff", domain=0x06).read(64) + self.assertEqual(res, btv) - def test_ffffff_d07(self): - tv = """18 B3 B5 B7 06 1C 2E 67 C1 75 3A 00 E6 AD 7E D7 + def test_ffffff_d07(self): + tv = """18 B3 B5 B7 06 1C 2E 67 C1 75 3A 00 E6 AD 7E D7 BA 1C 90 6C F9 3E FB 70 92 EA F2 7F BE EB B7 55 AE 6E 29 24 93 C1 10 E4 8D 26 00 28 49 2B 8E 09 B5 50 06 12 B8 F2 57 89 85 DE D5 35 7D 00 EC 67""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF' * 3, domain=0x07).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff" * 3, domain=0x07).read(64) + self.assertEqual(res, btv) - def test_ffffffffffff_d0b(self): - tv = """BB 36 76 49 51 EC 97 E9 D8 5F 7E E9 A6 7A 77 18 + def test_ffffffffffff_d0b(self): + tv = """BB 36 76 49 51 EC 97 E9 D8 5F 7E E9 A6 7A 77 18 FC 00 5C F4 25 56 BE 79 CE 12 C0 BD E5 0E 57 36 D6 63 2B 0D 0D FB 20 2D 1B BB 8F FE 3D D7 4C B0 08 34 FA 75 6C B0 34 71 BA B1 3A 1E 2C 16 B3 C0""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF' * 7, domain=0x0B).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff" * 7, domain=0x0B).read(64) + self.assertEqual(res, btv) - def test_ff_d30(self): - tv = """F3 FE 12 87 3D 34 BC BB 2E 60 87 79 D6 B7 0E 7F + def test_ff_d30(self): + tv = """F3 FE 12 87 3D 34 BC BB 2E 60 87 79 D6 B7 0E 7F 86 BE C7 E9 0B F1 13 CB D4 FD D0 C4 E2 F4 62 5E 14 8D D7 EE 1A 52 77 6C F7 7F 24 05 14 D9 CC FC 3B 5D DA B8 EE 25 5E 39 EE 38 90 72 96 2C 11 1A""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF', domain=0x30).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff", domain=0x30).read(64) + self.assertEqual(res, btv) - def test_ffffff_d7f(self): - tv = """AB E5 69 C1 F7 7E C3 40 F0 27 05 E7 D3 7C 9A B7 + def test_ffffff_d7f(self): + tv = """AB E5 69 C1 F7 7E C3 40 F0 27 05 E7 D3 7C 9A B7 E1 55 51 6E 4A 6A 15 00 21 D7 0B 6F AC 0B B4 0C 06 9F 9A 98 28 A0 D5 75 CD 99 F9 BA E4 35 AB 1A CF 7E D9 11 0B A9 7C E0 38 8D 07 4B AC 76 87 76""" - btv = txt2bin(tv) - res = TurboSHAKE256.new(data=b'\xFF' * 3, domain=0x7F).read(64) - self.assertEqual(res, btv) + btv = txt2bin(tv) + res = TurboSHAKE256.new(data=b"\xff" * 3, domain=0x7F).read(64) + self.assertEqual(res, btv) def get_tests(config={}): - tests = [] - tests += list_test_cases(TurboSHAKE128Test) - tests += list_test_cases(TurboSHAKE256Test) - tests += list_test_cases(TurboSHAKE128TV) - tests += list_test_cases(TurboSHAKE256TV) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(TurboSHAKE128Test) + tests += list_test_cases(TurboSHAKE256Test) + tests += list_test_cases(TurboSHAKE128TV) + tests += list_test_cases(TurboSHAKE256TV) + return tests + + +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_cSHAKE.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_cSHAKE.py index 67971608..393365ab 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_cSHAKE.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_cSHAKE.py @@ -36,143 +36,153 @@ class cSHAKETest(unittest.TestCase): - - def test_left_encode(self): - from Cryptodome.Hash.cSHAKE128 import _left_encode - self.assertEqual(_left_encode(0), b'\x01\x00') - self.assertEqual(_left_encode(1), b'\x01\x01') - self.assertEqual(_left_encode(256), b'\x02\x01\x00') - - def test_bytepad(self): - from Cryptodome.Hash.cSHAKE128 import _bytepad - self.assertEqual(_bytepad(b'', 4), b'\x01\x04\x00\x00') - self.assertEqual(_bytepad(b'A', 4), b'\x01\x04A\x00') - self.assertEqual(_bytepad(b'AA', 4), b'\x01\x04AA') - self.assertEqual(_bytepad(b'AAA', 4), b'\x01\x04AAA\x00\x00\x00') - self.assertEqual(_bytepad(b'AAAA', 4), b'\x01\x04AAAA\x00\x00') - self.assertEqual(_bytepad(b'AAAAA', 4), b'\x01\x04AAAAA\x00') - self.assertEqual(_bytepad(b'AAAAAA', 4), b'\x01\x04AAAAAA') - self.assertEqual(_bytepad(b'AAAAAAA', 4), b'\x01\x04AAAAAAA\x00\x00\x00') - - def test_new_positive(self): - - xof1 = self.cshake.new() - xof2 = self.cshake.new(data=b("90")) - xof3 = self.cshake.new().update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - xof1 = self.cshake.new() - ref = xof1.read(10) - xof2 = self.cshake.new(custom=b("")) - xof3 = self.cshake.new(custom=b("foo")) - - self.assertEqual(ref, xof2.read(10)) - self.assertNotEqual(ref, xof3.read(10)) - - xof1 = self.cshake.new(custom=b("foo")) - xof2 = self.cshake.new(custom=b("foo"), data=b("90")) - xof3 = self.cshake.new(custom=b("foo")).update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = self.cshake.new() - h.update(pieces[0]).update(pieces[1]) - digest = h.read(10) - h = self.cshake.new() - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.read(10), digest) - - def test_update_negative(self): - h = self.cshake.new() - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = self.cshake.new() - digest = h.read(90) - - # read returns a byte string of the right length - self.assertTrue(isinstance(digest, type(b("digest")))) - self.assertEqual(len(digest), 90) - - def test_update_after_read(self): - mac = self.cshake.new() - mac.update(b("rrrr")) - mac.read(90) - self.assertRaises(TypeError, mac.update, b("ttt")) - - def test_shake(self): - # When no customization string is passed, results must match SHAKE - for digest_len in range(64): - xof1 = self.cshake.new(b'TEST') - xof2 = self.shake.new(b'TEST') - self.assertEqual(xof1.read(digest_len), xof2.read(digest_len)) + def test_left_encode(self): + from Cryptodome.Hash.cSHAKE128 import _left_encode + + self.assertEqual(_left_encode(0), b"\x01\x00") + self.assertEqual(_left_encode(1), b"\x01\x01") + self.assertEqual(_left_encode(256), b"\x02\x01\x00") + + def test_bytepad(self): + from Cryptodome.Hash.cSHAKE128 import _bytepad + + self.assertEqual(_bytepad(b"", 4), b"\x01\x04\x00\x00") + self.assertEqual(_bytepad(b"A", 4), b"\x01\x04A\x00") + self.assertEqual(_bytepad(b"AA", 4), b"\x01\x04AA") + self.assertEqual(_bytepad(b"AAA", 4), b"\x01\x04AAA\x00\x00\x00") + self.assertEqual(_bytepad(b"AAAA", 4), b"\x01\x04AAAA\x00\x00") + self.assertEqual(_bytepad(b"AAAAA", 4), b"\x01\x04AAAAA\x00") + self.assertEqual(_bytepad(b"AAAAAA", 4), b"\x01\x04AAAAAA") + self.assertEqual(_bytepad(b"AAAAAAA", 4), b"\x01\x04AAAAAAA\x00\x00\x00") + + def test_new_positive(self): + xof1 = self.cshake.new() + xof2 = self.cshake.new(data=b("90")) + xof3 = self.cshake.new().update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + xof1 = self.cshake.new() + ref = xof1.read(10) + xof2 = self.cshake.new(custom=b("")) + xof3 = self.cshake.new(custom=b("foo")) + + self.assertEqual(ref, xof2.read(10)) + self.assertNotEqual(ref, xof3.read(10)) + + xof1 = self.cshake.new(custom=b("foo")) + xof2 = self.cshake.new(custom=b("foo"), data=b("90")) + xof3 = self.cshake.new(custom=b("foo")).update(b("90")) + + self.assertNotEqual(xof1.read(10), xof2.read(10)) + xof3.read(10) + self.assertEqual(xof2.read(10), xof3.read(10)) + + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] + h = self.cshake.new() + h.update(pieces[0]).update(pieces[1]) + digest = h.read(10) + h = self.cshake.new() + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.read(10), digest) + + def test_update_negative(self): + h = self.cshake.new() + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = self.cshake.new() + digest = h.read(90) + + # read returns a byte string of the right length + self.assertTrue(isinstance(digest, type(b("digest")))) + self.assertEqual(len(digest), 90) + + def test_update_after_read(self): + mac = self.cshake.new() + mac.update(b("rrrr")) + mac.read(90) + self.assertRaises(TypeError, mac.update, b("ttt")) + + def test_shake(self): + # When no customization string is passed, results must match SHAKE + for digest_len in range(64): + xof1 = self.cshake.new(b"TEST") + xof2 = self.shake.new(b"TEST") + self.assertEqual(xof1.read(digest_len), xof2.read(digest_len)) class cSHAKE128Test(cSHAKETest): - cshake = cSHAKE128 - shake = SHAKE128 + cshake = cSHAKE128 + shake = SHAKE128 class cSHAKE256Test(cSHAKETest): - cshake = cSHAKE256 - shake = SHAKE256 + cshake = cSHAKE256 + shake = SHAKE256 class cSHAKEVectors(unittest.TestCase): - pass + pass -vector_files = [("ShortMsgSamples_cSHAKE128.txt", "Short Message Samples cSHAKE128", "128_cshake", cSHAKE128), - ("ShortMsgSamples_cSHAKE256.txt", "Short Message Samples cSHAKE256", "256_cshake", cSHAKE256), - ("CustomMsgSamples_cSHAKE128.txt", "Custom Message Samples cSHAKE128", "custom_128_cshake", cSHAKE128), - ("CustomMsgSamples_cSHAKE256.txt", "Custom Message Samples cSHAKE256", "custom_256_cshake", cSHAKE256), - ] +vector_files = [ + ("ShortMsgSamples_cSHAKE128.txt", "Short Message Samples cSHAKE128", "128_cshake", cSHAKE128), + ("ShortMsgSamples_cSHAKE256.txt", "Short Message Samples cSHAKE256", "256_cshake", cSHAKE256), + ("CustomMsgSamples_cSHAKE128.txt", "Custom Message Samples cSHAKE128", "custom_128_cshake", cSHAKE128), + ("CustomMsgSamples_cSHAKE256.txt", "Custom Message Samples cSHAKE256", "custom_256_cshake", cSHAKE256), +] for file, descr, tag, test_class in vector_files: - - test_vectors = load_test_vectors(("Hash", "SHA3"), file, descr, - {"len": lambda x: int(x), - "nlen": lambda x: int(x), - "slen": lambda x: int(x)}) or [] - - for idx, tv in enumerate(test_vectors): - if getattr(tv, "len", 0) == 0: - data = b("") - else: - data = tobytes(tv.msg) - assert(tv.len == len(tv.msg)*8) - if getattr(tv, "nlen", 0) != 0: - raise ValueError("Unsupported cSHAKE test vector") - if getattr(tv, "slen", 0) == 0: - custom = b("") - else: - custom = tobytes(tv.s) - assert(tv.slen == len(tv.s)*8) - - def new_test(self, data=data, result=tv.md, custom=custom, test_class=test_class): - hobj = test_class.new(data=data, custom=custom) - digest = hobj.read(len(result)) - self.assertEqual(digest, result) - - setattr(cSHAKEVectors, "test_%s_%d" % (tag, idx), new_test) + test_vectors = ( + load_test_vectors( + ("Hash", "SHA3"), + file, + descr, + { + "len": lambda x: int(x), + "nlen": lambda x: int(x), + "slen": lambda x: int(x), + }, + ) + or [] + ) + + for idx, tv in enumerate(test_vectors): + if getattr(tv, "len", 0) == 0: + data = b("") + else: + data = tobytes(tv.msg) + assert tv.len == len(tv.msg) * 8 + if getattr(tv, "nlen", 0) != 0: + raise ValueError("Unsupported cSHAKE test vector") + if getattr(tv, "slen", 0) == 0: + custom = b("") + else: + custom = tobytes(tv.s) + assert tv.slen == len(tv.s) * 8 + + def new_test(self, data=data, result=tv.md, custom=custom, test_class=test_class): + hobj = test_class.new(data=data, custom=custom) + digest = hobj.read(len(result)) + self.assertEqual(digest, result) + + setattr(cSHAKEVectors, "test_%s_%d" % (tag, idx), new_test) def get_tests(config={}): - tests = [] - tests += list_test_cases(cSHAKE128Test) - tests += list_test_cases(cSHAKE256Test) - tests += list_test_cases(cSHAKEVectors) - return tests + tests = [] + tests += list_test_cases(cSHAKE128Test) + tests += list_test_cases(cSHAKE256Test) + tests += list_test_cases(cSHAKEVectors) + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_keccak.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_keccak.py index dcc0d137..00587e2c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_keccak.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Hash/test_keccak.py @@ -31,7 +31,7 @@ """Self-test suite for Cryptodome.Hash.keccak""" import unittest -from binascii import hexlify, unhexlify +from binascii import hexlify from Cryptodome.SelfTest.loader import load_test_vectors from Cryptodome.SelfTest.st_common import list_test_cases @@ -39,212 +39,253 @@ from Cryptodome.Hash import keccak from Cryptodome.Util.py3compat import b, tobytes, bchr -class KeccakTest(unittest.TestCase): - - def test_new_positive(self): - - for digest_bits in (224, 256, 384, 512): - hobj = keccak.new(digest_bits=digest_bits) - self.assertEqual(hobj.digest_size, digest_bits // 8) - - hobj2 = hobj.new() - self.assertEqual(hobj2.digest_size, digest_bits // 8) - - for digest_bytes in (28, 32, 48, 64): - hobj = keccak.new(digest_bytes=digest_bytes) - self.assertEqual(hobj.digest_size, digest_bytes) - - hobj2 = hobj.new() - self.assertEqual(hobj2.digest_size, digest_bytes) - - def test_new_positive2(self): - - digest1 = keccak.new(data=b("\x90"), digest_bytes=64).digest() - digest2 = keccak.new(digest_bytes=64).update(b("\x90")).digest() - self.assertEqual(digest1, digest2) - - def test_new_negative(self): - - # keccak.new needs digest size - self.assertRaises(TypeError, keccak.new) - - h = keccak.new(digest_bits=512) - - # Either bits or bytes can be specified - self.assertRaises(TypeError, keccak.new, - digest_bytes=64, - digest_bits=512) - - # Range - self.assertRaises(ValueError, keccak.new, digest_bytes=0) - self.assertRaises(ValueError, keccak.new, digest_bytes=1) - self.assertRaises(ValueError, keccak.new, digest_bytes=65) - self.assertRaises(ValueError, keccak.new, digest_bits=0) - self.assertRaises(ValueError, keccak.new, digest_bits=1) - self.assertRaises(ValueError, keccak.new, digest_bits=513) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = keccak.new(digest_bytes=64) - h.update(pieces[0]).update(pieces[1]) - digest = h.digest() - h = keccak.new(digest_bytes=64) - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.digest(), digest) - - def test_update_negative(self): - h = keccak.new(digest_bytes=64) - self.assertRaises(TypeError, h.update, u"string") - def test_digest(self): - h = keccak.new(digest_bytes=64) - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.assertTrue(isinstance(digest, type(b("digest")))) - - def test_hex_digest(self): - mac = keccak.new(digest_bits=512) - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.assertTrue(isinstance(hexdigest, type("digest"))) - - def test_update_after_digest(self): - msg=b("rrrrttt") - - # Normally, update() cannot be done after digest() - h = keccak.new(digest_bits=512, data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = keccak.new(digest_bits=512, data=msg).digest() - - # With the proper flag, it is allowed - h = keccak.new(digest_bits=512, data=msg[:4], update_after_digest=True) - self.assertEqual(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEqual(h.digest(), dig2) +class KeccakTest(unittest.TestCase): + def test_new_positive(self): + for digest_bits in (224, 256, 384, 512): + hobj = keccak.new(digest_bits=digest_bits) + self.assertEqual(hobj.digest_size, digest_bits // 8) + + hobj2 = hobj.new() + self.assertEqual(hobj2.digest_size, digest_bits // 8) + + for digest_bytes in (28, 32, 48, 64): + hobj = keccak.new(digest_bytes=digest_bytes) + self.assertEqual(hobj.digest_size, digest_bytes) + + hobj2 = hobj.new() + self.assertEqual(hobj2.digest_size, digest_bytes) + + def test_new_positive2(self): + digest1 = keccak.new(data=b("\x90"), digest_bytes=64).digest() + digest2 = keccak.new(digest_bytes=64).update(b("\x90")).digest() + self.assertEqual(digest1, digest2) + + def test_new_negative(self): + # keccak.new needs digest size + self.assertRaises(TypeError, keccak.new) + + h = keccak.new(digest_bits=512) + + # Either bits or bytes can be specified + self.assertRaises( + TypeError, + keccak.new, + digest_bytes=64, + digest_bits=512, + ) + + # Range + self.assertRaises(ValueError, keccak.new, digest_bytes=0) + self.assertRaises(ValueError, keccak.new, digest_bytes=1) + self.assertRaises(ValueError, keccak.new, digest_bytes=65) + self.assertRaises(ValueError, keccak.new, digest_bits=0) + self.assertRaises(ValueError, keccak.new, digest_bits=1) + self.assertRaises(ValueError, keccak.new, digest_bits=513) + + def test_update(self): + pieces = [bchr(10) * 200, bchr(20) * 300] + h = keccak.new(digest_bytes=64) + h.update(pieces[0]).update(pieces[1]) + digest = h.digest() + h = keccak.new(digest_bytes=64) + h.update(pieces[0] + pieces[1]) + self.assertEqual(h.digest(), digest) + + def test_update_negative(self): + h = keccak.new(digest_bytes=64) + self.assertRaises(TypeError, h.update, "string") + + def test_digest(self): + h = keccak.new(digest_bytes=64) + digest = h.digest() + + # hexdigest does not change the state + self.assertEqual(h.digest(), digest) + # digest returns a byte string + self.assertTrue(isinstance(digest, type(b("digest")))) + + def test_hex_digest(self): + mac = keccak.new(digest_bits=512) + digest = mac.digest() + hexdigest = mac.hexdigest() + + # hexdigest is equivalent to digest + self.assertEqual(hexlify(digest), tobytes(hexdigest)) + # hexdigest does not change the state + self.assertEqual(mac.hexdigest(), hexdigest) + # hexdigest returns a string + self.assertTrue(isinstance(hexdigest, type("digest"))) + + def test_update_after_digest(self): + msg = b("rrrrttt") + + # Normally, update() cannot be done after digest() + h = keccak.new(digest_bits=512, data=msg[:4]) + dig1 = h.digest() + self.assertRaises(TypeError, h.update, msg[4:]) + dig2 = keccak.new(digest_bits=512, data=msg).digest() + + # With the proper flag, it is allowed + h = keccak.new(digest_bits=512, data=msg[:4], update_after_digest=True) + self.assertEqual(h.digest(), dig1) + # ... and the subsequent digest applies to the entire message + # up to that point + h.update(msg[4:]) + self.assertEqual(h.digest(), dig2) class KeccakVectors(unittest.TestCase): - pass - - # TODO: add ExtremelyLong tests - - -test_vectors_224 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_224.txt", - "Short Messages KAT 224", - {"len": lambda x: int(x)}) or [] - -test_vectors_224 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_224.txt", - "Long Messages KAT 224", - {"len": lambda x: int(x)}) or [] + pass + + # TODO: add ExtremelyLong tests + + +test_vectors_224 = ( + load_test_vectors( + ("Hash", "keccak"), + "ShortMsgKAT_224.txt", + "Short Messages KAT 224", + {"len": lambda x: int(x)}, + ) + or [] +) + +test_vectors_224 += ( + load_test_vectors( + ("Hash", "keccak"), + "LongMsgKAT_224.txt", + "Long Messages KAT 224", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_224): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=224, data=data) - self.assertEqual(hobj.digest(), result) + def new_test(self, data=data, result=tv.md): + hobj = keccak.new(digest_bits=224, data=data) + self.assertEqual(hobj.digest(), result) - setattr(KeccakVectors, "test_224_%d" % idx, new_test) + setattr(KeccakVectors, "test_224_%d" % idx, new_test) # --- -test_vectors_256 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_256.txt", - "Short Messages KAT 256", - { "len" : lambda x: int(x) } ) or [] - -test_vectors_256 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_256.txt", - "Long Messages KAT 256", - { "len" : lambda x: int(x) } ) or [] +test_vectors_256 = ( + load_test_vectors( + ("Hash", "keccak"), + "ShortMsgKAT_256.txt", + "Short Messages KAT 256", + {"len": lambda x: int(x)}, + ) + or [] +) + +test_vectors_256 += ( + load_test_vectors( + ("Hash", "keccak"), + "LongMsgKAT_256.txt", + "Long Messages KAT 256", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_256): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=256, data=data) - self.assertEqual(hobj.digest(), result) + def new_test(self, data=data, result=tv.md): + hobj = keccak.new(digest_bits=256, data=data) + self.assertEqual(hobj.digest(), result) - setattr(KeccakVectors, "test_256_%d" % idx, new_test) + setattr(KeccakVectors, "test_256_%d" % idx, new_test) # --- -test_vectors_384 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_384.txt", - "Short Messages KAT 384", - {"len": lambda x: int(x)}) or [] - -test_vectors_384 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_384.txt", - "Long Messages KAT 384", - {"len": lambda x: int(x)}) or [] +test_vectors_384 = ( + load_test_vectors( + ("Hash", "keccak"), + "ShortMsgKAT_384.txt", + "Short Messages KAT 384", + {"len": lambda x: int(x)}, + ) + or [] +) + +test_vectors_384 += ( + load_test_vectors( + ("Hash", "keccak"), + "LongMsgKAT_384.txt", + "Long Messages KAT 384", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_384): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=384, data=data) - self.assertEqual(hobj.digest(), result) + def new_test(self, data=data, result=tv.md): + hobj = keccak.new(digest_bits=384, data=data) + self.assertEqual(hobj.digest(), result) - setattr(KeccakVectors, "test_384_%d" % idx, new_test) + setattr(KeccakVectors, "test_384_%d" % idx, new_test) # --- -test_vectors_512 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_512.txt", - "Short Messages KAT 512", - {"len": lambda x: int(x)}) or [] - -test_vectors_512 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_512.txt", - "Long Messages KAT 512", - {"len": lambda x: int(x)}) or [] +test_vectors_512 = ( + load_test_vectors( + ("Hash", "keccak"), + "ShortMsgKAT_512.txt", + "Short Messages KAT 512", + {"len": lambda x: int(x)}, + ) + or [] +) + +test_vectors_512 += ( + load_test_vectors( + ("Hash", "keccak"), + "LongMsgKAT_512.txt", + "Long Messages KAT 512", + {"len": lambda x: int(x)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_512): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) + if tv.len == 0: + data = b("") + else: + data = tobytes(tv.msg) - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=512, data=data) - self.assertEqual(hobj.digest(), result) + def new_test(self, data=data, result=tv.md): + hobj = keccak.new(digest_bits=512, data=data) + self.assertEqual(hobj.digest(), result) - setattr(KeccakVectors, "test_512_%d" % idx, new_test) + setattr(KeccakVectors, "test_512_%d" % idx, new_test) def get_tests(config={}): - tests = [] - tests += list_test_cases(KeccakTest) - tests += list_test_cases(KeccakVectors) - return tests + tests = [] + tests += list_test_cases(KeccakTest) + tests += list_test_cases(KeccakVectors) + return tests + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/__init__.py index f15f1413..0c2fa3f2 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/__init__.py @@ -33,15 +33,20 @@ """Self-test for I/O""" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.IO import test_PKCS8; tests += test_PKCS8.get_tests(config=config) - from Cryptodome.SelfTest.IO import test_PBES; tests += test_PBES.get_tests(config=config) - return tests + tests = [] + from Cryptodome.SelfTest.IO import test_PKCS8 + + tests += test_PKCS8.get_tests(config=config) + from Cryptodome.SelfTest.IO import test_PBES + + tests += test_PBES.get_tests(config=config) + return tests -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/test_PBES.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/test_PBES.py index 19762f3a..d18a139a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/test_PBES.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/test_PBES.py @@ -39,80 +39,112 @@ class TestPBES2(unittest.TestCase): - - def setUp(self): - self.ref = b"Test data" - self.passphrase = b"Passphrase" - - def test1(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test2(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA224AndAES128-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test3(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA256AndAES192-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test4(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA384AndAES256-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test5(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA512AndAES128-GCM') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test6(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA512-224AndAES192-GCM') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test7(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA3-256AndAES256-GCM') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test8(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'scryptAndAES128-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test9(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'scryptAndAES192-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test10(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'scryptAndAES256-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) + def setUp(self): + self.ref = b"Test data" + self.passphrase = b"Passphrase" + + def test1(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test2(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA224AndAES128-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test3(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA256AndAES192-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test4(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA384AndAES256-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test5(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA512AndAES128-GCM", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test6(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA512-224AndAES192-GCM", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test7(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "PBKDF2WithHMAC-SHA3-256AndAES256-GCM", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test8(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "scryptAndAES128-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test9(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "scryptAndAES192-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) + + def test10(self): + ct = PBES2.encrypt( + self.ref, + self.passphrase, + "scryptAndAES256-CBC", + ) + pt = PBES2.decrypt(ct, self.passphrase) + self.assertEqual(self.ref, pt) def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - listTests = [] - listTests += list_test_cases(TestPBES2) - return listTests + from Cryptodome.SelfTest.st_common import list_test_cases + + listTests = [] + listTests += list_test_cases(TestPBES2) + return listTests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/test_PKCS8.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/test_PKCS8.py index 718b69db..2b0d1f05 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/test_PKCS8.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/IO/test_PKCS8.py @@ -41,11 +41,11 @@ from Cryptodome.Util.asn1 import DerNull -oid_key = '1.2.840.113549.1.1.1' +oid_key = "1.2.840.113549.1.1.1" # Original RSA key (in DER format) # hexdump -v -e '32/1 "%02x" "\n"' key.der -clear_key=""" +clear_key = """ 308201ab020100025a00b94a7f7075ab9e79e8196f47be707781e80dd965cf16 0c951a870b71783b6aaabbd550c0e65e5a3dfe15b8620009f6d7e5efec42a3f0 6fe20faeebb0c356e79cdec6db4dd427e82d8ae4a5b90996227b8ba54ccfc4d2 @@ -66,7 +66,7 @@ # # openssl pkcs8 -topk8 -inform DER -nocrypt -in key.der -outform DER -out keyp8.der # hexdump -v -e '32/1 "%02x" "\n"' keyp8.der -wrapped_clear_key=""" +wrapped_clear_key = """ 308201c5020100300d06092a864886f70d0101010500048201af308201ab0201 00025a00b94a7f7075ab9e79e8196f47be707781e80dd965cf160c951a870b71 783b6aaabbd550c0e65e5a3dfe15b8620009f6d7e5efec42a3f06fe20faeebb0 @@ -102,12 +102,13 @@ # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -outform DER -out keyenc.der -v2 des3 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC', -2048, -"47EA7227D8B22E2F", # IV -"E3F7A838AB911A4D", # Salt -""" +wrapped_enc_keys.append( + ( + "PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC", + 2048, + "47EA7227D8B22E2F", # IV + "E3F7A838AB911A4D", # Salt + """ 30820216304006092a864886f70d01050d3033301b06092a864886f70d01050c 300e0408e3f7a838ab911a4d02020800301406082a864886f70d0307040847ea 7227d8b22e2f048201d0ea388b374d2d0e4ceb7a5139f850fdff274884a6e6c0 @@ -125,19 +126,21 @@ 9c10c9e6efbe78430a61f71c89948aa32cdc3cc7338cf994147819ce7ab23450 c8f7d9b94c3bb377d17a3fa204b601526317824b142ff6bc843fa7815ece89c0 839573f234dac8d80cc571a045353d61db904a4398d8ef3df5ac -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -outform DER -out keyenc.der # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'skip encryption', # pbeWithMD5AndDES-CBC, only decoding is supported --1, -"", -"", -""" +wrapped_enc_keys.append( + ( + "skip encryption", # pbeWithMD5AndDES-CBC, only decoding is supported + -1, + "", + "", + """ 308201f1301b06092a864886f70d010503300e0408f9b990c89af1d41b020208 00048201d0c6267fe8592903891933d559e71a7ca68b2e39150f19daca0f7921 52f97e249d72f670d5140e9150433310ed7c7ee51927693fd39884cb9551cea5 @@ -154,20 +157,22 @@ a50e96a2264490aeabdc07c6e78e5dbf4fe3388726d0e2a228346bf3c2907d68 2a6276b22ae883fb30fa611f4e4193e7a08480fcd7db48308bacbd72bf4807aa 11fd394859f97d22982f7fe890b2e2a0f7e7ffb693 -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v1 PBE-SHA1-RC2-64 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'skip encryption', # pbeWithSHA1AndRC2-CBC, only decoding is supported --1, -"", -"", -""" +wrapped_enc_keys.append( + ( + "skip encryption", # pbeWithSHA1AndRC2-CBC, only decoding is supported + -1, + "", + "", + """ 308201f1301b06092a864886f70d01050b300e04083ee943bdae185008020208 00048201d0e4614d9371d3ff10ceabc2f6a7a13a0f449f9a714144e46518ea55 e3e6f0cde24031d01ef1f37ec40081449ef01914faf45983dde0d2bc496712de @@ -183,20 +188,22 @@ b16e27ae528db28593af9adcfccbebb3b9e1f2af5cd5531b51968389caa6c091 e7de1f1b96f0d258e54e540d961a7c0ef51fda45d6da5fddd33e9bbfd3a5f8d7 d7ab2e971de495cddbc86d38444fee9f0ac097b00adaf7802dabe0cff5b43b45 -4f26b7b547016f89be52676866189911c53e2f2477""" -)) +4f26b7b547016f89be52676866189911c53e2f2477""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v1 PBE-MD5-RC2-64 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'skip encryption', # pbeWithMD5AndRC2-CBC, only decoding is supported --1, -"", -"", -""" +wrapped_enc_keys.append( + ( + "skip encryption", # pbeWithMD5AndRC2-CBC, only decoding is supported + -1, + "", + "", + """ 308201f1301b06092a864886f70d010506300e0408f5cd2fee56d9b4b8020208 00048201d086454942d6166a19d6b108465bd111e7080911f573d54b1369c676 df28600e84936bfec04f91023ff16499e2e07178c340904f12ffa6886ab66228 @@ -212,20 +219,22 @@ b77d1db287b3a6264c466805be5a4fe85cfbca180699859280f2dd8e2c2c10b5 7a7d2ac670c6039d41952fbb0e4f99b560ebe1d020e1b96d02403283819c00cc 529c51f0b0101555e4c58002ba3c6e3c12e3fde1aec94382792e96d9666a2b33 -3dc397b22ecab67ee38a552fec29a1d4ff8719c748""" -)) +3dc397b22ecab67ee38a552fec29a1d4ff8719c748""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v1 PBE-SHA1-DES # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'skip encryption', # pbeWithSHA1AndDES-CBC, only decoding is supported --1, -"", -"", -""" +wrapped_enc_keys.append( + ( + "skip encryption", # pbeWithSHA1AndDES-CBC, only decoding is supported + -1, + "", + "", + """ 308201f1301b06092a864886f70d01050a300e04089bacc9cf1e8f734e020208 00048201d03e502f3ceafe8fd19ab2939576bfdded26d719b2441db1459688f5 9673218b41ec1f739edf1e460bd927bc28470c87b2d4fc8ea02ba17b47a63c49 @@ -242,20 +251,22 @@ 3a606f4e4b9b46eb13b57f2624b651859d3d2d5192b45dbd5a2ead14ff20ca76 48f321309aa56d8c0c4a192b580821cc6c70c75e6f19d1c5414da898ec4dd39d b0eb93d6ba387a80702dfd2db610757ba340f63230 -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v2 aes128 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndAES128-CBC', -2048, -"4F66EE5D3BCD531FE6EBF4B4E73016B8", # IV -"479F25156176C53A", # Salt -""" +wrapped_enc_keys.append( + ( + "PBKDF2WithHMAC-SHA1AndAES128-CBC", + 2048, + "4F66EE5D3BCD531FE6EBF4B4E73016B8", # IV + "479F25156176C53A", # Salt + """ 3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c 300e0408479f25156176c53a02020800301d060960864801650304010204104f 66ee5d3bcd531fe6ebf4b4e73016b8048201d0e33cfa560423f589d097d21533 @@ -274,20 +285,22 @@ d740e082b4a3bbb8bafdd34a0b3c5f2f3c2aceccccdccd092b78994b845bfa61 706c3b9df5165ed1dbcbf1244fe41fc9bf993f52f7658e2f87e1baaeacb0f562 9d905c -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v2 aes192 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndAES192-CBC', -2048, -"5CFC2A4FF7B63201A4A8A5B021148186", # IV -"D718541C264944CE", # Salt -""" +wrapped_enc_keys.append( + ( + "PBKDF2WithHMAC-SHA1AndAES192-CBC", + 2048, + "5CFC2A4FF7B63201A4A8A5B021148186", # IV + "D718541C264944CE", # Salt + """ 3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c 300e0408d718541c264944ce02020800301d060960864801650304011604105c fc2a4ff7b63201a4a8a5b021148186048201d08e74aaa21b8bcfb15b9790fe95 @@ -306,20 +319,22 @@ 0970ed34acd6e3e89d063987893b2b9570ddb8cc032b05a723bba9444933ebf3 c624204be72f4190e0245197d0cb772bec933fd8442445f9a28bd042d5a3a1e9 9a8a07 -""" -)) +""", + ) +) # # openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der # -outform DER -out keyenc.der -v2 aes192 # hexdump -v -e '32/1 "%02x" "\n"' keyenc.der # -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndAES256-CBC', -2048, -"323351F94462AC563E053A056252C2C4", # IV -"02A6CD0D12E727B5", # Salt -""" +wrapped_enc_keys.append( + ( + "PBKDF2WithHMAC-SHA1AndAES256-CBC", + 2048, + "323351F94462AC563E053A056252C2C4", # IV + "02A6CD0D12E727B5", # Salt + """ 3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c 300e040802a6cd0d12e727b502020800301d060960864801650304012a041032 3351f94462ac563e053a056252c2c4048201d07f4ef1c7be21aae738a20c5632 @@ -338,8 +353,9 @@ e8abd059f8e8ffea637c9c7721f817aaf0bb23403e26a0ef0ff0e2037da67d41 af728481f53443551a9bff4cea023164e9622b5441a309e1f4bff98e5bf76677 8d7cd9 -""" -)) +""", + ) +) # hexdump -v -e '32/1 "%02x" "\n"' botan_scrypt.der botan_scrypt = """ @@ -365,95 +381,106 @@ 996363f37032e10ac85afebb7cc1cbfc0e5d4c60a4c2 """ + def txt2bin(inputs): - s = b('').join([b(x) for x in inputs if not (x in '\n\r\t ')]) - return unhexlify(s) + s = b("").join([b(x) for x in inputs if x not in "\n\r\t "]) + return unhexlify(s) + class Rng: - def __init__(self, output): - self.output=output - self.idx=0 - def __call__(self, n): - output = self.output[self.idx:self.idx+n] - self.idx += n - return output + def __init__(self, output): + self.output = output + self.idx = 0 -class PKCS8_Decrypt(unittest.TestCase): + def __call__(self, n): + output = self.output[self.idx : self.idx + n] + self.idx += n + return output - def setUp(self): - self.oid_key = oid_key - self.clear_key = txt2bin(clear_key) - self.wrapped_clear_key = txt2bin(wrapped_clear_key) - self.wrapped_enc_keys = [] - for t in wrapped_enc_keys: - self.wrapped_enc_keys.append(( - t[0], - t[1], - txt2bin(t[2]), - txt2bin(t[3]), - txt2bin(t[4]) - )) - - ### NO ENCRYTION - - def test1(self): - """Verify unwrapping w/o encryption""" - res1, res2, res3 = PKCS8.unwrap(self.wrapped_clear_key) - self.assertEqual(res1, self.oid_key) - self.assertEqual(res2, self.clear_key) - - def test2(self): - """Verify wrapping w/o encryption""" - wrapped = PKCS8.wrap(self.clear_key, self.oid_key) - res1, res2, res3 = PKCS8.unwrap(wrapped) - self.assertEqual(res1, self.oid_key) - self.assertEqual(res2, self.clear_key) - - ## ENCRYPTION - - def test3(self): - """Verify unwrapping with encryption""" - - for t in self.wrapped_enc_keys: - res1, res2, res3 = PKCS8.unwrap(t[4], b"TestTest") - self.assertEqual(res1, self.oid_key) - self.assertEqual(res2, self.clear_key) - - def test4(self): - """Verify wrapping with encryption""" - - for t in self.wrapped_enc_keys: - if t[0] == 'skip encryption': - continue - rng = Rng(t[2]+t[3]) - params = { 'iteration_count':t[1] } - wrapped = PKCS8.wrap( - self.clear_key, - self.oid_key, - b("TestTest"), - protection=t[0], - prot_params=params, - key_params=DerNull(), - randfunc=rng) - self.assertEqual(wrapped, t[4]) - - def test_import_botan_keys(self): - botan_scrypt_der = txt2bin(botan_scrypt) - key1 = PKCS8.unwrap(botan_scrypt_der, - b'your_password') - botan_pbkdf2_der = txt2bin(botan_pbkdf2) - key2 = PKCS8.unwrap(botan_pbkdf2_der, - b'your_password') - self.assertEqual(key1, key2) + +class PKCS8_Decrypt(unittest.TestCase): + def setUp(self): + self.oid_key = oid_key + self.clear_key = txt2bin(clear_key) + self.wrapped_clear_key = txt2bin(wrapped_clear_key) + self.wrapped_enc_keys = [] + for t in wrapped_enc_keys: + self.wrapped_enc_keys.append( + ( + t[0], + t[1], + txt2bin(t[2]), + txt2bin(t[3]), + txt2bin(t[4]), + ) + ) + + ### NO ENCRYTION + + def test1(self): + """Verify unwrapping w/o encryption""" + res1, res2, res3 = PKCS8.unwrap(self.wrapped_clear_key) + self.assertEqual(res1, self.oid_key) + self.assertEqual(res2, self.clear_key) + + def test2(self): + """Verify wrapping w/o encryption""" + wrapped = PKCS8.wrap(self.clear_key, self.oid_key) + res1, res2, res3 = PKCS8.unwrap(wrapped) + self.assertEqual(res1, self.oid_key) + self.assertEqual(res2, self.clear_key) + + ## ENCRYPTION + + def test3(self): + """Verify unwrapping with encryption""" + + for t in self.wrapped_enc_keys: + res1, res2, res3 = PKCS8.unwrap(t[4], b"TestTest") + self.assertEqual(res1, self.oid_key) + self.assertEqual(res2, self.clear_key) + + def test4(self): + """Verify wrapping with encryption""" + + for t in self.wrapped_enc_keys: + if t[0] == "skip encryption": + continue + rng = Rng(t[2] + t[3]) + params = {"iteration_count": t[1]} + wrapped = PKCS8.wrap( + self.clear_key, + self.oid_key, + b("TestTest"), + protection=t[0], + prot_params=params, + key_params=DerNull(), + randfunc=rng, + ) + self.assertEqual(wrapped, t[4]) + + def test_import_botan_keys(self): + botan_scrypt_der = txt2bin(botan_scrypt) + key1 = PKCS8.unwrap( + botan_scrypt_der, + b"your_password", + ) + botan_pbkdf2_der = txt2bin(botan_pbkdf2) + key2 = PKCS8.unwrap( + botan_pbkdf2_der, + b"your_password", + ) + self.assertEqual(key1, key2) def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - listTests = [] - listTests += list_test_cases(PKCS8_Decrypt) - return listTests + from Cryptodome.SelfTest.st_common import list_test_cases + + listTests = [] + listTests += list_test_cases(PKCS8_Decrypt) + return listTests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/__init__.py index 9f732ba3..64e52df0 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/__init__.py @@ -33,19 +33,23 @@ """Self-test for Math""" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Math import test_Numbers - from Cryptodome.SelfTest.Math import test_Primality - from Cryptodome.SelfTest.Math import test_modexp - from Cryptodome.SelfTest.Math import test_modmult - tests += test_Numbers.get_tests(config=config) - tests += test_Primality.get_tests(config=config) - tests += test_modexp.get_tests(config=config) - tests += test_modmult.get_tests(config=config) - return tests + tests = [] + from Cryptodome.SelfTest.Math import test_Numbers + from Cryptodome.SelfTest.Math import test_Primality + from Cryptodome.SelfTest.Math import test_modexp + from Cryptodome.SelfTest.Math import test_modmult + + tests += test_Numbers.get_tests(config=config) + tests += test_Primality.get_tests(config=config) + tests += test_modexp.get_tests(config=config) + tests += test_modmult.get_tests(config=config) + return tests + + +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_Numbers.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_Numbers.py index f974d5a0..d3871e34 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_Numbers.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_Numbers.py @@ -44,795 +44,1287 @@ class TestIntegerBase(unittest.TestCase): - - def setUp(self): - raise NotImplementedError("To be implemented") - - def Integers(self, *arg): - return map(self.Integer, arg) - - def test_init_and_equality(self): - Integer = self.Integer - - v1 = Integer(23) - v2 = Integer(v1) - v3 = Integer(-9) - self.assertRaises(ValueError, Integer, 1.0) - - v4 = Integer(10**10) - v5 = Integer(-10**10) - - v6 = Integer(0xFFFF) - v7 = Integer(0xFFFFFFFF) - v8 = Integer(0xFFFFFFFFFFFFFFFF) - - self.assertEqual(v1, v1) - self.assertEqual(v1, 23) - self.assertEqual(v1, v2) - self.assertEqual(v3, -9) - self.assertEqual(v4, 10 ** 10) - self.assertEqual(v5, -10 ** 10) - self.assertEqual(v6, 0xFFFF) - self.assertEqual(v7, 0xFFFFFFFF) - self.assertEqual(v8, 0xFFFFFFFFFFFFFFFF) - - self.assertFalse(v1 == v4) - - # Init and comparison between Integer's - v6 = Integer(v1) - self.assertEqual(v1, v6) - - self.assertFalse(Integer(0) == None) - - def test_conversion_to_int(self): - v1, v2 = self.Integers(-23, 2 ** 1000) - self.assertEqual(int(v1), -23) - self.assertEqual(int(v2), 2 ** 1000) - - def test_equality_with_ints(self): - v1, v2, v3 = self.Integers(23, -89, 2 ** 1000) - self.assertTrue(v1 == 23) - self.assertTrue(v2 == -89) - self.assertFalse(v1 == 24) - self.assertTrue(v3 == 2 ** 1000) - - def test_conversion_to_str(self): - v1, v2, v3, v4 = self.Integers(20, 0, -20, 2 ** 1000) - self.assertTrue(str(v1) == "20") - self.assertTrue(str(v2) == "0") - self.assertTrue(str(v3) == "-20") - self.assertTrue(str(v4) == "10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376") - - def test_repr(self): - v1, v2 = self.Integers(-1, 2**80) - self.assertEqual(repr(v1), "Integer(-1)") - self.assertEqual(repr(v2), "Integer(1208925819614629174706176)") - - def test_conversion_to_bytes(self): - Integer = self.Integer - - v0 = Integer(0) - self.assertEqual(b"\x00", v0.to_bytes()) - - v1 = Integer(0x17) - self.assertEqual(b"\x17", v1.to_bytes()) - - v2 = Integer(0xFFFE) - self.assertEqual(b"\xFF\xFE", v2.to_bytes()) - self.assertEqual(b"\x00\xFF\xFE", v2.to_bytes(3)) - self.assertRaises(ValueError, v2.to_bytes, 1) - - self.assertEqual(b"\xFE\xFF", v2.to_bytes(byteorder='little')) - self.assertEqual(b"\xFE\xFF\x00", v2.to_bytes(3, byteorder='little')) - - v3 = Integer(0xFF00AABBCCDDEE1122) - self.assertEqual(b"\xFF\x00\xAA\xBB\xCC\xDD\xEE\x11\x22", v3.to_bytes()) - self.assertEqual(b"\x22\x11\xEE\xDD\xCC\xBB\xAA\x00\xFF", - v3.to_bytes(byteorder='little')) - self.assertEqual(b"\x00\xFF\x00\xAA\xBB\xCC\xDD\xEE\x11\x22", - v3.to_bytes(10)) - self.assertEqual(b"\x22\x11\xEE\xDD\xCC\xBB\xAA\x00\xFF\x00", - v3.to_bytes(10, byteorder='little')) - self.assertRaises(ValueError, v3.to_bytes, 8) - - v4 = Integer(-90) - self.assertRaises(ValueError, v4.to_bytes) - self.assertRaises(ValueError, v4.to_bytes, byteorder='bittle') - - def test_conversion_from_bytes(self): - Integer = self.Integer - - v1 = Integer.from_bytes(b"\x00") - self.assertTrue(isinstance(v1, Integer)) - self.assertEqual(0, v1) - - v2 = Integer.from_bytes(b"\x00\x01") - self.assertEqual(1, v2) - - v3 = Integer.from_bytes(b"\xFF\xFF") - self.assertEqual(0xFFFF, v3) - - v4 = Integer.from_bytes(b"\x00\x01", 'big') - self.assertEqual(1, v4) - - v5 = Integer.from_bytes(b"\x00\x01", byteorder='big') - self.assertEqual(1, v5) - - v6 = Integer.from_bytes(b"\x00\x01", byteorder='little') - self.assertEqual(0x0100, v6) - - self.assertRaises(ValueError, Integer.from_bytes, b'\x09', 'bittle') - - def test_inequality(self): - # Test Integer!=Integer and Integer!=int - v1, v2, v3, v4 = self.Integers(89, 89, 90, -8) - self.assertTrue(v1 != v3) - self.assertTrue(v1 != 90) - self.assertFalse(v1 != v2) - self.assertFalse(v1 != 89) - self.assertTrue(v1 != v4) - self.assertTrue(v4 != v1) - self.assertTrue(self.Integer(0) != None) - - def test_less_than(self): - # Test IntegerInteger and Integer>int - v1, v2, v3, v4, v5 = self.Integers(13, 13, 14, -8, 2 ** 10) - self.assertTrue(v3 > v1) - self.assertTrue(v3 > 13) - self.assertFalse(v1 > v1) - self.assertFalse(v1 > v2) - self.assertFalse(v1 > 13) - self.assertTrue(v1 > v4) - self.assertFalse(v4 > v1) - self.assertTrue(v5 > v1) - self.assertFalse(v1 > v5) - - def test_more_than_or_equal(self): - # Test Integer>=Integer and Integer>=int - v1, v2, v3, v4 = self.Integers(13, 13, 14, -4) - self.assertTrue(v3 >= v1) - self.assertTrue(v3 >= 13) - self.assertTrue(v1 >= v2) - self.assertTrue(v1 >= v1) - self.assertTrue(v1 >= 13) - self.assertFalse(v4 >= v1) - - def test_bool(self): - v1, v2, v3, v4 = self.Integers(0, 10, -9, 2 ** 10) - self.assertFalse(v1) - self.assertFalse(bool(v1)) - self.assertTrue(v2) - self.assertTrue(bool(v2)) - self.assertTrue(v3) - self.assertTrue(v4) - - def test_is_negative(self): - v1, v2, v3, v4, v5 = self.Integers(-3 ** 100, -3, 0, 3, 3**100) - self.assertTrue(v1.is_negative()) - self.assertTrue(v2.is_negative()) - self.assertFalse(v4.is_negative()) - self.assertFalse(v5.is_negative()) - - def test_addition(self): - # Test Integer+Integer and Integer+int - v1, v2, v3 = self.Integers(7, 90, -7) - self.assertTrue(isinstance(v1 + v2, self.Integer)) - self.assertEqual(v1 + v2, 97) - self.assertEqual(v1 + 90, 97) - self.assertEqual(v1 + v3, 0) - self.assertEqual(v1 + (-7), 0) - self.assertEqual(v1 + 2 ** 10, 2 ** 10 + 7) - - def test_subtraction(self): - # Test Integer-Integer and Integer-int - v1, v2, v3 = self.Integers(7, 90, -7) - self.assertTrue(isinstance(v1 - v2, self.Integer)) - self.assertEqual(v2 - v1, 83) - self.assertEqual(v2 - 7, 83) - self.assertEqual(v2 - v3, 97) - self.assertEqual(v1 - (-7), 14) - self.assertEqual(v1 - 2 ** 10, 7 - 2 ** 10) - - def test_multiplication(self): - # Test Integer-Integer and Integer-int - v1, v2, v3, v4 = self.Integers(4, 5, -2, 2 ** 10) - self.assertTrue(isinstance(v1 * v2, self.Integer)) - self.assertEqual(v1 * v2, 20) - self.assertEqual(v1 * 5, 20) - self.assertEqual(v1 * -2, -8) - self.assertEqual(v1 * 2 ** 10, 4 * (2 ** 10)) - - def test_floor_div(self): - v1, v2, v3 = self.Integers(3, 8, 2 ** 80) - self.assertTrue(isinstance(v1 // v2, self.Integer)) - self.assertEqual(v2 // v1, 2) - self.assertEqual(v2 // 3, 2) - self.assertEqual(v2 // -3, -3) - self.assertEqual(v3 // 2 ** 79, 2) - self.assertRaises(ZeroDivisionError, lambda: v1 // 0) - - def test_remainder(self): - # Test Integer%Integer and Integer%int - v1, v2, v3 = self.Integers(23, 5, -4) - self.assertTrue(isinstance(v1 % v2, self.Integer)) - self.assertEqual(v1 % v2, 3) - self.assertEqual(v1 % 5, 3) - self.assertEqual(v3 % 5, 1) - self.assertEqual(v1 % 2 ** 10, 23) - self.assertRaises(ZeroDivisionError, lambda: v1 % 0) - self.assertRaises(ValueError, lambda: v1 % -6) - - def test_simple_exponentiation(self): - v1, v2, v3 = self.Integers(4, 3, -2) - self.assertTrue(isinstance(v1 ** v2, self.Integer)) - self.assertEqual(v1 ** v2, 64) - self.assertEqual(pow(v1, v2), 64) - self.assertEqual(v1 ** 3, 64) - self.assertEqual(pow(v1, 3), 64) - self.assertEqual(v3 ** 2, 4) - self.assertEqual(v3 ** 3, -8) - - self.assertRaises(ValueError, pow, v1, -3) - - def test_modular_exponentiation(self): - v1, v2, v3 = self.Integers(23, 5, 17) - - self.assertTrue(isinstance(pow(v1, v2, v3), self.Integer)) - self.assertEqual(pow(v1, v2, v3), 7) - self.assertEqual(pow(v1, 5, v3), 7) - self.assertEqual(pow(v1, v2, 17), 7) - self.assertEqual(pow(v1, 5, 17), 7) - self.assertEqual(pow(v1, 0, 17), 1) - self.assertEqual(pow(v1, 1, 2 ** 80), 23) - self.assertEqual(pow(v1, 2 ** 80, 89298), 17689) - - self.assertRaises(ZeroDivisionError, pow, v1, 5, 0) - self.assertRaises(ValueError, pow, v1, 5, -4) - self.assertRaises(ValueError, pow, v1, -3, 8) - - def test_inplace_exponentiation(self): - v1 = self.Integer(4) - v1.inplace_pow(2) - self.assertEqual(v1, 16) - - v1 = self.Integer(4) - v1.inplace_pow(2, 15) - self.assertEqual(v1, 1) - - def test_abs(self): - v1, v2, v3, v4, v5 = self.Integers(-2 ** 100, -2, 0, 2, 2 ** 100) - self.assertEqual(abs(v1), 2 ** 100) - self.assertEqual(abs(v2), 2) - self.assertEqual(abs(v3), 0) - self.assertEqual(abs(v4), 2) - self.assertEqual(abs(v5), 2 ** 100) - - def test_sqrt(self): - v1, v2, v3, v4 = self.Integers(-2, 0, 49, 10**100) - - self.assertRaises(ValueError, v1.sqrt) - self.assertEqual(v2.sqrt(), 0) - self.assertEqual(v3.sqrt(), 7) - self.assertEqual(v4.sqrt(), 10**50) - - def test_sqrt_module(self): - - # Invalid modulus (non positive) - self.assertRaises(ValueError, self.Integer(5).sqrt, 0) - self.assertRaises(ValueError, self.Integer(5).sqrt, -1) - - # Simple cases - assert self.Integer(0).sqrt(5) == 0 - assert self.Integer(1).sqrt(5) in (1, 4) - - # Test with all quadratic residues in several fields - for p in (11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53): - for i in range(0, p): - square = i**2 % p - res = self.Integer(square).sqrt(p) - assert res in (i, p - i) - - # 2 is a non-quadratic reside in Z_11 - self.assertRaises(ValueError, self.Integer(2).sqrt, 11) - - # 10 is not a prime - self.assertRaises(ValueError, self.Integer(4).sqrt, 10) - - # 5 is square residue of 4 and 7 - assert self.Integer(5 - 11).sqrt(11) in (4, 7) - assert self.Integer(5 + 11).sqrt(11) in (4, 7) - - def test_in_place_add(self): - v1, v2 = self.Integers(10, 20) - - v1 += v2 - self.assertEqual(v1, 30) - v1 += 10 - self.assertEqual(v1, 40) - v1 += -1 - self.assertEqual(v1, 39) - v1 += 2 ** 1000 - self.assertEqual(v1, 39 + 2 ** 1000) - - def test_in_place_sub(self): - v1, v2 = self.Integers(10, 20) - - v1 -= v2 - self.assertEqual(v1, -10) - v1 -= -100 - self.assertEqual(v1, 90) - v1 -= 90000 - self.assertEqual(v1, -89910) - v1 -= -100000 - self.assertEqual(v1, 10090) - - def test_in_place_mul(self): - v1, v2 = self.Integers(3, 5) - - v1 *= v2 - self.assertEqual(v1, 15) - v1 *= 2 - self.assertEqual(v1, 30) - v1 *= -2 - self.assertEqual(v1, -60) - v1 *= 2 ** 1000 - self.assertEqual(v1, -60 * (2 ** 1000)) - - def test_in_place_modulus(self): - v1, v2 = self.Integers(20, 7) - - v1 %= v2 - self.assertEqual(v1, 6) - v1 %= 2 ** 1000 - self.assertEqual(v1, 6) - v1 %= 2 - self.assertEqual(v1, 0) - def t(): - v3 = self.Integer(9) - v3 %= 0 - self.assertRaises(ZeroDivisionError, t) - - def test_and(self): - v1, v2, v3 = self.Integers(0xF4, 0x31, -0xF) - self.assertTrue(isinstance(v1 & v2, self.Integer)) - self.assertEqual(v1 & v2, 0x30) - self.assertEqual(v1 & 0x31, 0x30) - self.assertEqual(v1 & v3, 0xF0) - self.assertEqual(v1 & -0xF, 0xF0) - self.assertEqual(v3 & -0xF, -0xF) - self.assertEqual(v2 & (2 ** 1000 + 0x31), 0x31) - - def test_or(self): - v1, v2, v3 = self.Integers(0x40, 0x82, -0xF) - self.assertTrue(isinstance(v1 | v2, self.Integer)) - self.assertEqual(v1 | v2, 0xC2) - self.assertEqual(v1 | 0x82, 0xC2) - self.assertEqual(v2 | v3, -0xD) - self.assertEqual(v2 | 2 ** 1000, 2 ** 1000 + 0x82) - - def test_right_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - self.assertEqual(v1 >> 0, v1) - self.assertTrue(isinstance(v1 >> v2, self.Integer)) - self.assertEqual(v1 >> v2, 0x08) - self.assertEqual(v1 >> 1, 0x08) - self.assertRaises(ValueError, lambda: v1 >> -1) - self.assertEqual(v1 >> (2 ** 1000), 0) - - self.assertEqual(v3 >> 1, -0x08) - self.assertEqual(v3 >> (2 ** 1000), -1) - - def test_in_place_right_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - v1 >>= 0 - self.assertEqual(v1, 0x10) - v1 >>= 1 - self.assertEqual(v1, 0x08) - v1 >>= v2 - self.assertEqual(v1, 0x04) - v3 >>= 1 - self.assertEqual(v3, -0x08) - def l(): - v4 = self.Integer(0x90) - v4 >>= -1 - self.assertRaises(ValueError, l) - def m1(): - v4 = self.Integer(0x90) - v4 >>= 2 ** 1000 - return v4 - self.assertEqual(0, m1()) - def m2(): - v4 = self.Integer(-1) - v4 >>= 2 ** 1000 - return v4 - self.assertEqual(-1, m2()) - - def _test_left_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - self.assertEqual(v1 << 0, v1) - self.assertTrue(isinstance(v1 << v2, self.Integer)) - self.assertEqual(v1 << v2, 0x20) - self.assertEqual(v1 << 1, 0x20) - self.assertEqual(v3 << 1, -0x20) - self.assertRaises(ValueError, lambda: v1 << -1) - self.assertRaises(ValueError, lambda: v1 << (2 ** 1000)) - - def test_in_place_left_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - v1 <<= 0 - self.assertEqual(v1, 0x10) - v1 <<= 1 - self.assertEqual(v1, 0x20) - v1 <<= v2 - self.assertEqual(v1, 0x40) - v3 <<= 1 - self.assertEqual(v3, -0x20) - def l(): - v4 = self.Integer(0x90) - v4 <<= -1 - self.assertRaises(ValueError, l) - def m(): - v4 = self.Integer(0x90) - v4 <<= 2 ** 1000 - self.assertRaises(ValueError, m) - - - def test_get_bit(self): - v1, v2, v3 = self.Integers(0x102, -3, 1) - self.assertEqual(v1.get_bit(0), 0) - self.assertEqual(v1.get_bit(1), 1) - self.assertEqual(v1.get_bit(v3), 1) - self.assertEqual(v1.get_bit(8), 1) - self.assertEqual(v1.get_bit(9), 0) - - self.assertRaises(ValueError, v1.get_bit, -1) - self.assertEqual(v1.get_bit(2 ** 1000), 0) - - self.assertRaises(ValueError, v2.get_bit, -1) - self.assertRaises(ValueError, v2.get_bit, 0) - self.assertRaises(ValueError, v2.get_bit, 1) - self.assertRaises(ValueError, v2.get_bit, 2 * 1000) - - def test_odd_even(self): - v1, v2, v3, v4, v5 = self.Integers(0, 4, 17, -4, -17) - - self.assertTrue(v1.is_even()) - self.assertTrue(v2.is_even()) - self.assertFalse(v3.is_even()) - self.assertTrue(v4.is_even()) - self.assertFalse(v5.is_even()) - - self.assertFalse(v1.is_odd()) - self.assertFalse(v2.is_odd()) - self.assertTrue(v3.is_odd()) - self.assertFalse(v4.is_odd()) - self.assertTrue(v5.is_odd()) - - def test_size_in_bits(self): - v1, v2, v3, v4 = self.Integers(0, 1, 0x100, -90) - self.assertEqual(v1.size_in_bits(), 1) - self.assertEqual(v2.size_in_bits(), 1) - self.assertEqual(v3.size_in_bits(), 9) - self.assertRaises(ValueError, v4.size_in_bits) - - def test_size_in_bytes(self): - v1, v2, v3, v4, v5, v6 = self.Integers(0, 1, 0xFF, 0x1FF, 0x10000, -9) - self.assertEqual(v1.size_in_bytes(), 1) - self.assertEqual(v2.size_in_bytes(), 1) - self.assertEqual(v3.size_in_bytes(), 1) - self.assertEqual(v4.size_in_bytes(), 2) - self.assertEqual(v5.size_in_bytes(), 3) - self.assertRaises(ValueError, v6.size_in_bits) - - def test_perfect_square(self): - - self.assertFalse(self.Integer(-9).is_perfect_square()) - self.assertTrue(self.Integer(0).is_perfect_square()) - self.assertTrue(self.Integer(1).is_perfect_square()) - self.assertFalse(self.Integer(2).is_perfect_square()) - self.assertFalse(self.Integer(3).is_perfect_square()) - self.assertTrue(self.Integer(4).is_perfect_square()) - self.assertTrue(self.Integer(39*39).is_perfect_square()) - self.assertFalse(self.Integer(39*39+1).is_perfect_square()) - - for x in range(100, 1000): - self.assertFalse(self.Integer(x**2+1).is_perfect_square()) - self.assertTrue(self.Integer(x**2).is_perfect_square()) - - def test_fail_if_divisible_by(self): - v1, v2, v3 = self.Integers(12, -12, 4) - - # No failure expected - v1.fail_if_divisible_by(7) - v2.fail_if_divisible_by(7) - v2.fail_if_divisible_by(2 ** 80) - - # Failure expected - self.assertRaises(ValueError, v1.fail_if_divisible_by, 4) - self.assertRaises(ValueError, v1.fail_if_divisible_by, v3) - - def test_multiply_accumulate(self): - v1, v2, v3 = self.Integers(4, 3, 2) - v1.multiply_accumulate(v2, v3) - self.assertEqual(v1, 10) - v1.multiply_accumulate(v2, 2) - self.assertEqual(v1, 16) - v1.multiply_accumulate(3, v3) - self.assertEqual(v1, 22) - v1.multiply_accumulate(1, -2) - self.assertEqual(v1, 20) - v1.multiply_accumulate(-2, 1) - self.assertEqual(v1, 18) - v1.multiply_accumulate(1, 2 ** 1000) - self.assertEqual(v1, 18 + 2 ** 1000) - v1.multiply_accumulate(2 ** 1000, 1) - self.assertEqual(v1, 18 + 2 ** 1001) - - def test_set(self): - v1, v2 = self.Integers(3, 6) - v1.set(v2) - self.assertEqual(v1, 6) - v1.set(9) - self.assertEqual(v1, 9) - v1.set(-2) - self.assertEqual(v1, -2) - v1.set(2 ** 1000) - self.assertEqual(v1, 2 ** 1000) - - def test_inverse(self): - v1, v2, v3, v4, v5, v6 = self.Integers(2, 5, -3, 0, 723872, 3433) - - self.assertTrue(isinstance(v1.inverse(v2), self.Integer)) - self.assertEqual(v1.inverse(v2), 3) - self.assertEqual(v1.inverse(5), 3) - self.assertEqual(v3.inverse(5), 3) - self.assertEqual(v5.inverse(92929921), 58610507) - self.assertEqual(v6.inverse(9912), 5353) - - self.assertRaises(ValueError, v2.inverse, 10) - self.assertRaises(ValueError, v1.inverse, -3) - self.assertRaises(ValueError, v4.inverse, 10) - self.assertRaises(ZeroDivisionError, v2.inverse, 0) - - def test_inplace_inverse(self): - v1, v2 = self.Integers(2, 5) - - v1.inplace_inverse(v2) - self.assertEqual(v1, 3) - - def test_gcd(self): - v1, v2, v3, v4 = self.Integers(6, 10, 17, -2) - self.assertTrue(isinstance(v1.gcd(v2), self.Integer)) - self.assertEqual(v1.gcd(v2), 2) - self.assertEqual(v1.gcd(10), 2) - self.assertEqual(v1.gcd(v3), 1) - self.assertEqual(v1.gcd(-2), 2) - self.assertEqual(v4.gcd(6), 2) - - def test_lcm(self): - v1, v2, v3, v4, v5 = self.Integers(6, 10, 17, -2, 0) - self.assertTrue(isinstance(v1.lcm(v2), self.Integer)) - self.assertEqual(v1.lcm(v2), 30) - self.assertEqual(v1.lcm(10), 30) - self.assertEqual(v1.lcm(v3), 102) - self.assertEqual(v1.lcm(-2), 6) - self.assertEqual(v4.lcm(6), 6) - self.assertEqual(v1.lcm(0), 0) - self.assertEqual(v5.lcm(0), 0) - - def test_jacobi_symbol(self): - - data = ( - (1001, 1, 1), - (19, 45, 1), - (8, 21, -1), - (5, 21, 1), - (610, 987, -1), - (1001, 9907, -1), - (5, 3439601197, -1) - ) - - js = self.Integer.jacobi_symbol - - # Jacobi symbol is always 1 for k==1 or n==1 - for k in range(1, 30): - self.assertEqual(js(k, 1), 1) - for n in range(1, 30, 2): - self.assertEqual(js(1, n), 1) - - # Fail if n is not positive odd - self.assertRaises(ValueError, js, 6, -2) - self.assertRaises(ValueError, js, 6, -1) - self.assertRaises(ValueError, js, 6, 0) - self.assertRaises(ValueError, js, 0, 0) - self.assertRaises(ValueError, js, 6, 2) - self.assertRaises(ValueError, js, 6, 4) - self.assertRaises(ValueError, js, 6, 6) - self.assertRaises(ValueError, js, 6, 8) - - for tv in data: - self.assertEqual(js(tv[0], tv[1]), tv[2]) - self.assertEqual(js(self.Integer(tv[0]), tv[1]), tv[2]) - self.assertEqual(js(tv[0], self.Integer(tv[1])), tv[2]) - - def test_jacobi_symbol_wikipedia(self): - + def setUp(self): + raise NotImplementedError("To be implemented") + + def Integers(self, *arg): + return map(self.Integer, arg) + + def test_init_and_equality(self): + Integer = self.Integer + + v1 = Integer(23) + v2 = Integer(v1) + v3 = Integer(-9) + self.assertRaises(ValueError, Integer, 1.0) + + v4 = Integer(10**10) + v5 = Integer(-(10**10)) + + v6 = Integer(0xFFFF) + v7 = Integer(0xFFFFFFFF) + v8 = Integer(0xFFFFFFFFFFFFFFFF) + + self.assertEqual(v1, v1) + self.assertEqual(v1, 23) + self.assertEqual(v1, v2) + self.assertEqual(v3, -9) + self.assertEqual(v4, 10**10) + self.assertEqual(v5, -(10**10)) + self.assertEqual(v6, 0xFFFF) + self.assertEqual(v7, 0xFFFFFFFF) + self.assertEqual(v8, 0xFFFFFFFFFFFFFFFF) + + self.assertFalse(v1 == v4) + + # Init and comparison between Integer's + v6 = Integer(v1) + self.assertEqual(v1, v6) + + self.assertFalse(Integer(0) == None) + + def test_conversion_to_int(self): + v1, v2 = self.Integers(-23, 2**1000) + self.assertEqual(int(v1), -23) + self.assertEqual(int(v2), 2**1000) + + def test_equality_with_ints(self): + v1, v2, v3 = self.Integers(23, -89, 2**1000) + self.assertTrue(v1 == 23) + self.assertTrue(v2 == -89) + self.assertFalse(v1 == 24) + self.assertTrue(v3 == 2**1000) + + def test_conversion_to_str(self): + v1, v2, v3, v4 = self.Integers(20, 0, -20, 2**1000) + self.assertTrue(str(v1) == "20") + self.assertTrue(str(v2) == "0") + self.assertTrue(str(v3) == "-20") + self.assertTrue( + str(v4) + == "10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376" + ) + + def test_repr(self): + v1, v2 = self.Integers(-1, 2**80) + self.assertEqual(repr(v1), "Integer(-1)") + self.assertEqual(repr(v2), "Integer(1208925819614629174706176)") + + def test_conversion_to_bytes(self): + Integer = self.Integer + + v0 = Integer(0) + self.assertEqual(b"\x00", v0.to_bytes()) + + v1 = Integer(0x17) + self.assertEqual(b"\x17", v1.to_bytes()) + + v2 = Integer(0xFFFE) + self.assertEqual(b"\xff\xfe", v2.to_bytes()) + self.assertEqual(b"\x00\xff\xfe", v2.to_bytes(3)) + self.assertRaises(ValueError, v2.to_bytes, 1) + + self.assertEqual(b"\xfe\xff", v2.to_bytes(byteorder="little")) + self.assertEqual(b"\xfe\xff\x00", v2.to_bytes(3, byteorder="little")) + + v3 = Integer(0xFF00AABBCCDDEE1122) + self.assertEqual(b"\xff\x00\xaa\xbb\xcc\xdd\xee\x11\x22", v3.to_bytes()) + self.assertEqual( + b"\x22\x11\xee\xdd\xcc\xbb\xaa\x00\xff", + v3.to_bytes(byteorder="little"), + ) + self.assertEqual( + b"\x00\xff\x00\xaa\xbb\xcc\xdd\xee\x11\x22", + v3.to_bytes(10), + ) + self.assertEqual( + b"\x22\x11\xee\xdd\xcc\xbb\xaa\x00\xff\x00", + v3.to_bytes(10, byteorder="little"), + ) + self.assertRaises(ValueError, v3.to_bytes, 8) + + v4 = Integer(-90) + self.assertRaises(ValueError, v4.to_bytes) + self.assertRaises(ValueError, v4.to_bytes, byteorder="bittle") + + def test_conversion_from_bytes(self): + Integer = self.Integer + + v1 = Integer.from_bytes(b"\x00") + self.assertTrue(isinstance(v1, Integer)) + self.assertEqual(0, v1) + + v2 = Integer.from_bytes(b"\x00\x01") + self.assertEqual(1, v2) + + v3 = Integer.from_bytes(b"\xff\xff") + self.assertEqual(0xFFFF, v3) + + v4 = Integer.from_bytes(b"\x00\x01", "big") + self.assertEqual(1, v4) + + v5 = Integer.from_bytes(b"\x00\x01", byteorder="big") + self.assertEqual(1, v5) + + v6 = Integer.from_bytes(b"\x00\x01", byteorder="little") + self.assertEqual(0x0100, v6) + + self.assertRaises(ValueError, Integer.from_bytes, b"\x09", "bittle") + + def test_inequality(self): + # Test Integer!=Integer and Integer!=int + v1, v2, v3, v4 = self.Integers(89, 89, 90, -8) + self.assertTrue(v1 != v3) + self.assertTrue(v1 != 90) + self.assertFalse(v1 != v2) + self.assertFalse(v1 != 89) + self.assertTrue(v1 != v4) + self.assertTrue(v4 != v1) + self.assertTrue(self.Integer(0) != None) + + def test_less_than(self): + # Test IntegerInteger and Integer>int + v1, v2, v3, v4, v5 = self.Integers(13, 13, 14, -8, 2**10) + self.assertTrue(v3 > v1) + self.assertTrue(v3 > 13) + self.assertFalse(v1 > v1) + self.assertFalse(v1 > v2) + self.assertFalse(v1 > 13) + self.assertTrue(v1 > v4) + self.assertFalse(v4 > v1) + self.assertTrue(v5 > v1) + self.assertFalse(v1 > v5) + + def test_more_than_or_equal(self): + # Test Integer>=Integer and Integer>=int + v1, v2, v3, v4 = self.Integers(13, 13, 14, -4) + self.assertTrue(v3 >= v1) + self.assertTrue(v3 >= 13) + self.assertTrue(v1 >= v2) + self.assertTrue(v1 >= v1) + self.assertTrue(v1 >= 13) + self.assertFalse(v4 >= v1) + + def test_bool(self): + v1, v2, v3, v4 = self.Integers(0, 10, -9, 2**10) + self.assertFalse(v1) + self.assertFalse(bool(v1)) + self.assertTrue(v2) + self.assertTrue(bool(v2)) + self.assertTrue(v3) + self.assertTrue(v4) + + def test_is_negative(self): + v1, v2, v3, v4, v5 = self.Integers(-(3**100), -3, 0, 3, 3**100) + self.assertTrue(v1.is_negative()) + self.assertTrue(v2.is_negative()) + self.assertFalse(v4.is_negative()) + self.assertFalse(v5.is_negative()) + + def test_addition(self): + # Test Integer+Integer and Integer+int + v1, v2, v3 = self.Integers(7, 90, -7) + self.assertTrue(isinstance(v1 + v2, self.Integer)) + self.assertEqual(v1 + v2, 97) + self.assertEqual(v1 + 90, 97) + self.assertEqual(v1 + v3, 0) + self.assertEqual(v1 + (-7), 0) + self.assertEqual(v1 + 2**10, 2**10 + 7) + + def test_subtraction(self): + # Test Integer-Integer and Integer-int + v1, v2, v3 = self.Integers(7, 90, -7) + self.assertTrue(isinstance(v1 - v2, self.Integer)) + self.assertEqual(v2 - v1, 83) + self.assertEqual(v2 - 7, 83) + self.assertEqual(v2 - v3, 97) + self.assertEqual(v1 - (-7), 14) + self.assertEqual(v1 - 2**10, 7 - 2**10) + + def test_multiplication(self): + # Test Integer-Integer and Integer-int + v1, v2, v3, v4 = self.Integers(4, 5, -2, 2**10) + self.assertTrue(isinstance(v1 * v2, self.Integer)) + self.assertEqual(v1 * v2, 20) + self.assertEqual(v1 * 5, 20) + self.assertEqual(v1 * -2, -8) + self.assertEqual(v1 * 2**10, 4 * (2**10)) + + def test_floor_div(self): + v1, v2, v3 = self.Integers(3, 8, 2**80) + self.assertTrue(isinstance(v1 // v2, self.Integer)) + self.assertEqual(v2 // v1, 2) + self.assertEqual(v2 // 3, 2) + self.assertEqual(v2 // -3, -3) + self.assertEqual(v3 // 2**79, 2) + self.assertRaises(ZeroDivisionError, lambda: v1 // 0) + + def test_remainder(self): + # Test Integer%Integer and Integer%int + v1, v2, v3 = self.Integers(23, 5, -4) + self.assertTrue(isinstance(v1 % v2, self.Integer)) + self.assertEqual(v1 % v2, 3) + self.assertEqual(v1 % 5, 3) + self.assertEqual(v3 % 5, 1) + self.assertEqual(v1 % 2**10, 23) + self.assertRaises(ZeroDivisionError, lambda: v1 % 0) + self.assertRaises(ValueError, lambda: v1 % -6) + + def test_simple_exponentiation(self): + v1, v2, v3 = self.Integers(4, 3, -2) + self.assertTrue(isinstance(v1**v2, self.Integer)) + self.assertEqual(v1**v2, 64) + self.assertEqual(pow(v1, v2), 64) + self.assertEqual(v1**3, 64) + self.assertEqual(pow(v1, 3), 64) + self.assertEqual(v3**2, 4) + self.assertEqual(v3**3, -8) + + self.assertRaises(ValueError, pow, v1, -3) + + def test_modular_exponentiation(self): + v1, v2, v3 = self.Integers(23, 5, 17) + + self.assertTrue(isinstance(pow(v1, v2, v3), self.Integer)) + self.assertEqual(pow(v1, v2, v3), 7) + self.assertEqual(pow(v1, 5, v3), 7) + self.assertEqual(pow(v1, v2, 17), 7) + self.assertEqual(pow(v1, 5, 17), 7) + self.assertEqual(pow(v1, 0, 17), 1) + self.assertEqual(pow(v1, 1, 2**80), 23) + self.assertEqual(pow(v1, 2**80, 89298), 17689) + + self.assertRaises(ZeroDivisionError, pow, v1, 5, 0) + self.assertRaises(ValueError, pow, v1, 5, -4) + self.assertRaises(ValueError, pow, v1, -3, 8) + + def test_inplace_exponentiation(self): + v1 = self.Integer(4) + v1.inplace_pow(2) + self.assertEqual(v1, 16) + + v1 = self.Integer(4) + v1.inplace_pow(2, 15) + self.assertEqual(v1, 1) + + def test_abs(self): + v1, v2, v3, v4, v5 = self.Integers(-(2**100), -2, 0, 2, 2**100) + self.assertEqual(abs(v1), 2**100) + self.assertEqual(abs(v2), 2) + self.assertEqual(abs(v3), 0) + self.assertEqual(abs(v4), 2) + self.assertEqual(abs(v5), 2**100) + + def test_sqrt(self): + v1, v2, v3, v4 = self.Integers(-2, 0, 49, 10**100) + + self.assertRaises(ValueError, v1.sqrt) + self.assertEqual(v2.sqrt(), 0) + self.assertEqual(v3.sqrt(), 7) + self.assertEqual(v4.sqrt(), 10**50) + + def test_sqrt_module(self): + # Invalid modulus (non positive) + self.assertRaises(ValueError, self.Integer(5).sqrt, 0) + self.assertRaises(ValueError, self.Integer(5).sqrt, -1) + + # Simple cases + assert self.Integer(0).sqrt(5) == 0 + assert self.Integer(1).sqrt(5) in (1, 4) + + # Test with all quadratic residues in several fields + for p in (11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53): + for i in range(0, p): + square = i**2 % p + res = self.Integer(square).sqrt(p) + assert res in (i, p - i) + + # 2 is a non-quadratic reside in Z_11 + self.assertRaises(ValueError, self.Integer(2).sqrt, 11) + + # 10 is not a prime + self.assertRaises(ValueError, self.Integer(4).sqrt, 10) + + # 5 is square residue of 4 and 7 + assert self.Integer(5 - 11).sqrt(11) in (4, 7) + assert self.Integer(5 + 11).sqrt(11) in (4, 7) + + def test_in_place_add(self): + v1, v2 = self.Integers(10, 20) + + v1 += v2 + self.assertEqual(v1, 30) + v1 += 10 + self.assertEqual(v1, 40) + v1 += -1 + self.assertEqual(v1, 39) + v1 += 2**1000 + self.assertEqual(v1, 39 + 2**1000) + + def test_in_place_sub(self): + v1, v2 = self.Integers(10, 20) + + v1 -= v2 + self.assertEqual(v1, -10) + v1 -= -100 + self.assertEqual(v1, 90) + v1 -= 90000 + self.assertEqual(v1, -89910) + v1 -= -100000 + self.assertEqual(v1, 10090) + + def test_in_place_mul(self): + v1, v2 = self.Integers(3, 5) + + v1 *= v2 + self.assertEqual(v1, 15) + v1 *= 2 + self.assertEqual(v1, 30) + v1 *= -2 + self.assertEqual(v1, -60) + v1 *= 2**1000 + self.assertEqual(v1, -60 * (2**1000)) + + def test_in_place_modulus(self): + v1, v2 = self.Integers(20, 7) + + v1 %= v2 + self.assertEqual(v1, 6) + v1 %= 2**1000 + self.assertEqual(v1, 6) + v1 %= 2 + self.assertEqual(v1, 0) + + def t(): + v3 = self.Integer(9) + v3 %= 0 + + self.assertRaises(ZeroDivisionError, t) + + def test_and(self): + v1, v2, v3 = self.Integers(0xF4, 0x31, -0xF) + self.assertTrue(isinstance(v1 & v2, self.Integer)) + self.assertEqual(v1 & v2, 0x30) + self.assertEqual(v1 & 0x31, 0x30) + self.assertEqual(v1 & v3, 0xF0) + self.assertEqual(v1 & -0xF, 0xF0) + self.assertEqual(v3 & -0xF, -0xF) + self.assertEqual(v2 & (2**1000 + 0x31), 0x31) + + def test_or(self): + v1, v2, v3 = self.Integers(0x40, 0x82, -0xF) + self.assertTrue(isinstance(v1 | v2, self.Integer)) + self.assertEqual(v1 | v2, 0xC2) + self.assertEqual(v1 | 0x82, 0xC2) + self.assertEqual(v2 | v3, -0xD) + self.assertEqual(v2 | 2**1000, 2**1000 + 0x82) + + def test_right_shift(self): + v1, v2, v3 = self.Integers(0x10, 1, -0x10) + self.assertEqual(v1 >> 0, v1) + self.assertTrue(isinstance(v1 >> v2, self.Integer)) + self.assertEqual(v1 >> v2, 0x08) + self.assertEqual(v1 >> 1, 0x08) + self.assertRaises(ValueError, lambda: v1 >> -1) + self.assertEqual(v1 >> (2**1000), 0) + + self.assertEqual(v3 >> 1, -0x08) + self.assertEqual(v3 >> (2**1000), -1) + + def test_in_place_right_shift(self): + v1, v2, v3 = self.Integers(0x10, 1, -0x10) + v1 >>= 0 + self.assertEqual(v1, 0x10) + v1 >>= 1 + self.assertEqual(v1, 0x08) + v1 >>= v2 + self.assertEqual(v1, 0x04) + v3 >>= 1 + self.assertEqual(v3, -0x08) + + def l(): + v4 = self.Integer(0x90) + v4 >>= -1 + + self.assertRaises(ValueError, l) + + def m1(): + v4 = self.Integer(0x90) + v4 >>= 2**1000 + return v4 + + self.assertEqual(0, m1()) + + def m2(): + v4 = self.Integer(-1) + v4 >>= 2**1000 + return v4 + + self.assertEqual(-1, m2()) + + def _test_left_shift(self): + v1, v2, v3 = self.Integers(0x10, 1, -0x10) + self.assertEqual(v1 << 0, v1) + self.assertTrue(isinstance(v1 << v2, self.Integer)) + self.assertEqual(v1 << v2, 0x20) + self.assertEqual(v1 << 1, 0x20) + self.assertEqual(v3 << 1, -0x20) + self.assertRaises(ValueError, lambda: v1 << -1) + self.assertRaises(ValueError, lambda: v1 << (2**1000)) + + def test_in_place_left_shift(self): + v1, v2, v3 = self.Integers(0x10, 1, -0x10) + v1 <<= 0 + self.assertEqual(v1, 0x10) + v1 <<= 1 + self.assertEqual(v1, 0x20) + v1 <<= v2 + self.assertEqual(v1, 0x40) + v3 <<= 1 + self.assertEqual(v3, -0x20) + + def l(): + v4 = self.Integer(0x90) + v4 <<= -1 + + self.assertRaises(ValueError, l) + + def m(): + v4 = self.Integer(0x90) + v4 <<= 2**1000 + + self.assertRaises(ValueError, m) + + def test_get_bit(self): + v1, v2, v3 = self.Integers(0x102, -3, 1) + self.assertEqual(v1.get_bit(0), 0) + self.assertEqual(v1.get_bit(1), 1) + self.assertEqual(v1.get_bit(v3), 1) + self.assertEqual(v1.get_bit(8), 1) + self.assertEqual(v1.get_bit(9), 0) + + self.assertRaises(ValueError, v1.get_bit, -1) + self.assertEqual(v1.get_bit(2**1000), 0) + + self.assertRaises(ValueError, v2.get_bit, -1) + self.assertRaises(ValueError, v2.get_bit, 0) + self.assertRaises(ValueError, v2.get_bit, 1) + self.assertRaises(ValueError, v2.get_bit, 2 * 1000) + + def test_odd_even(self): + v1, v2, v3, v4, v5 = self.Integers(0, 4, 17, -4, -17) + + self.assertTrue(v1.is_even()) + self.assertTrue(v2.is_even()) + self.assertFalse(v3.is_even()) + self.assertTrue(v4.is_even()) + self.assertFalse(v5.is_even()) + + self.assertFalse(v1.is_odd()) + self.assertFalse(v2.is_odd()) + self.assertTrue(v3.is_odd()) + self.assertFalse(v4.is_odd()) + self.assertTrue(v5.is_odd()) + + def test_size_in_bits(self): + v1, v2, v3, v4 = self.Integers(0, 1, 0x100, -90) + self.assertEqual(v1.size_in_bits(), 1) + self.assertEqual(v2.size_in_bits(), 1) + self.assertEqual(v3.size_in_bits(), 9) + self.assertRaises(ValueError, v4.size_in_bits) + + def test_size_in_bytes(self): + v1, v2, v3, v4, v5, v6 = self.Integers(0, 1, 0xFF, 0x1FF, 0x10000, -9) + self.assertEqual(v1.size_in_bytes(), 1) + self.assertEqual(v2.size_in_bytes(), 1) + self.assertEqual(v3.size_in_bytes(), 1) + self.assertEqual(v4.size_in_bytes(), 2) + self.assertEqual(v5.size_in_bytes(), 3) + self.assertRaises(ValueError, v6.size_in_bits) + + def test_perfect_square(self): + self.assertFalse(self.Integer(-9).is_perfect_square()) + self.assertTrue(self.Integer(0).is_perfect_square()) + self.assertTrue(self.Integer(1).is_perfect_square()) + self.assertFalse(self.Integer(2).is_perfect_square()) + self.assertFalse(self.Integer(3).is_perfect_square()) + self.assertTrue(self.Integer(4).is_perfect_square()) + self.assertTrue(self.Integer(39 * 39).is_perfect_square()) + self.assertFalse(self.Integer(39 * 39 + 1).is_perfect_square()) + + for x in range(100, 1000): + self.assertFalse(self.Integer(x**2 + 1).is_perfect_square()) + self.assertTrue(self.Integer(x**2).is_perfect_square()) + + def test_fail_if_divisible_by(self): + v1, v2, v3 = self.Integers(12, -12, 4) + + # No failure expected + v1.fail_if_divisible_by(7) + v2.fail_if_divisible_by(7) + v2.fail_if_divisible_by(2**80) + + # Failure expected + self.assertRaises(ValueError, v1.fail_if_divisible_by, 4) + self.assertRaises(ValueError, v1.fail_if_divisible_by, v3) + + def test_multiply_accumulate(self): + v1, v2, v3 = self.Integers(4, 3, 2) + v1.multiply_accumulate(v2, v3) + self.assertEqual(v1, 10) + v1.multiply_accumulate(v2, 2) + self.assertEqual(v1, 16) + v1.multiply_accumulate(3, v3) + self.assertEqual(v1, 22) + v1.multiply_accumulate(1, -2) + self.assertEqual(v1, 20) + v1.multiply_accumulate(-2, 1) + self.assertEqual(v1, 18) + v1.multiply_accumulate(1, 2**1000) + self.assertEqual(v1, 18 + 2**1000) + v1.multiply_accumulate(2**1000, 1) + self.assertEqual(v1, 18 + 2**1001) + + def test_set(self): + v1, v2 = self.Integers(3, 6) + v1.set(v2) + self.assertEqual(v1, 6) + v1.set(9) + self.assertEqual(v1, 9) + v1.set(-2) + self.assertEqual(v1, -2) + v1.set(2**1000) + self.assertEqual(v1, 2**1000) + + def test_inverse(self): + v1, v2, v3, v4, v5, v6 = self.Integers(2, 5, -3, 0, 723872, 3433) + + self.assertTrue(isinstance(v1.inverse(v2), self.Integer)) + self.assertEqual(v1.inverse(v2), 3) + self.assertEqual(v1.inverse(5), 3) + self.assertEqual(v3.inverse(5), 3) + self.assertEqual(v5.inverse(92929921), 58610507) + self.assertEqual(v6.inverse(9912), 5353) + + self.assertRaises(ValueError, v2.inverse, 10) + self.assertRaises(ValueError, v1.inverse, -3) + self.assertRaises(ValueError, v4.inverse, 10) + self.assertRaises(ZeroDivisionError, v2.inverse, 0) + + def test_inplace_inverse(self): + v1, v2 = self.Integers(2, 5) + + v1.inplace_inverse(v2) + self.assertEqual(v1, 3) + + def test_gcd(self): + v1, v2, v3, v4 = self.Integers(6, 10, 17, -2) + self.assertTrue(isinstance(v1.gcd(v2), self.Integer)) + self.assertEqual(v1.gcd(v2), 2) + self.assertEqual(v1.gcd(10), 2) + self.assertEqual(v1.gcd(v3), 1) + self.assertEqual(v1.gcd(-2), 2) + self.assertEqual(v4.gcd(6), 2) + + def test_lcm(self): + v1, v2, v3, v4, v5 = self.Integers(6, 10, 17, -2, 0) + self.assertTrue(isinstance(v1.lcm(v2), self.Integer)) + self.assertEqual(v1.lcm(v2), 30) + self.assertEqual(v1.lcm(10), 30) + self.assertEqual(v1.lcm(v3), 102) + self.assertEqual(v1.lcm(-2), 6) + self.assertEqual(v4.lcm(6), 6) + self.assertEqual(v1.lcm(0), 0) + self.assertEqual(v5.lcm(0), 0) + + def test_jacobi_symbol(self): + data = ( + (1001, 1, 1), + (19, 45, 1), + (8, 21, -1), + (5, 21, 1), + (610, 987, -1), + (1001, 9907, -1), + (5, 3439601197, -1), + ) + + js = self.Integer.jacobi_symbol + + # Jacobi symbol is always 1 for k==1 or n==1 + for k in range(1, 30): + self.assertEqual(js(k, 1), 1) + for n in range(1, 30, 2): + self.assertEqual(js(1, n), 1) + + # Fail if n is not positive odd + self.assertRaises(ValueError, js, 6, -2) + self.assertRaises(ValueError, js, 6, -1) + self.assertRaises(ValueError, js, 6, 0) + self.assertRaises(ValueError, js, 0, 0) + self.assertRaises(ValueError, js, 6, 2) + self.assertRaises(ValueError, js, 6, 4) + self.assertRaises(ValueError, js, 6, 6) + self.assertRaises(ValueError, js, 6, 8) + + for tv in data: + self.assertEqual(js(tv[0], tv[1]), tv[2]) + self.assertEqual(js(self.Integer(tv[0]), tv[1]), tv[2]) + self.assertEqual(js(tv[0], self.Integer(tv[1])), tv[2]) + + def test_jacobi_symbol_wikipedia(self): # Test vectors from https://en.wikipedia.org/wiki/Jacobi_symbol - tv = [ - (3, [(1, 1), (2, -1), (3, 0), (4, 1), (5, -1), (6, 0), (7, 1), (8, -1), (9, 0), (10, 1), (11, -1), (12, 0), (13, 1), (14, -1), (15, 0), (16, 1), (17, -1), (18, 0), (19, 1), (20, -1), (21, 0), (22, 1), (23, -1), (24, 0), (25, 1), (26, -1), (27, 0), (28, 1), (29, -1), (30, 0)]), - (5, [(1, 1), (2, -1), (3, -1), (4, 1), (5, 0), (6, 1), (7, -1), (8, -1), (9, 1), (10, 0), (11, 1), (12, -1), (13, -1), (14, 1), (15, 0), (16, 1), (17, -1), (18, -1), (19, 1), (20, 0), (21, 1), (22, -1), (23, -1), (24, 1), (25, 0), (26, 1), (27, -1), (28, -1), (29, 1), (30, 0)]), - (7, [(1, 1), (2, 1), (3, -1), (4, 1), (5, -1), (6, -1), (7, 0), (8, 1), (9, 1), (10, -1), (11, 1), (12, -1), (13, -1), (14, 0), (15, 1), (16, 1), (17, -1), (18, 1), (19, -1), (20, -1), (21, 0), (22, 1), (23, 1), (24, -1), (25, 1), (26, -1), (27, -1), (28, 0), (29, 1), (30, 1)]), - (9, [(1, 1), (2, 1), (3, 0), (4, 1), (5, 1), (6, 0), (7, 1), (8, 1), (9, 0), (10, 1), (11, 1), (12, 0), (13, 1), (14, 1), (15, 0), (16, 1), (17, 1), (18, 0), (19, 1), (20, 1), (21, 0), (22, 1), (23, 1), (24, 0), (25, 1), (26, 1), (27, 0), (28, 1), (29, 1), (30, 0)]), - (11, [(1, 1), (2, -1), (3, 1), (4, 1), (5, 1), (6, -1), (7, -1), (8, -1), (9, 1), (10, -1), (11, 0), (12, 1), (13, -1), (14, 1), (15, 1), (16, 1), (17, -1), (18, -1), (19, -1), (20, 1), (21, -1), (22, 0), (23, 1), (24, -1), (25, 1), (26, 1), (27, 1), (28, -1), (29, -1), (30, -1)]), - (13, [(1, 1), (2, -1), (3, 1), (4, 1), (5, -1), (6, -1), (7, -1), (8, -1), (9, 1), (10, 1), (11, -1), (12, 1), (13, 0), (14, 1), (15, -1), (16, 1), (17, 1), (18, -1), (19, -1), (20, -1), (21, -1), (22, 1), (23, 1), (24, -1), (25, 1), (26, 0), (27, 1), (28, -1), (29, 1), (30, 1)]), - (15, [(1, 1), (2, 1), (3, 0), (4, 1), (5, 0), (6, 0), (7, -1), (8, 1), (9, 0), (10, 0), (11, -1), (12, 0), (13, -1), (14, -1), (15, 0), (16, 1), (17, 1), (18, 0), (19, 1), (20, 0), (21, 0), (22, -1), (23, 1), (24, 0), (25, 0), (26, -1), (27, 0), (28, -1), (29, -1), (30, 0)]), - (17, [(1, 1), (2, 1), (3, -1), (4, 1), (5, -1), (6, -1), (7, -1), (8, 1), (9, 1), (10, -1), (11, -1), (12, -1), (13, 1), (14, -1), (15, 1), (16, 1), (17, 0), (18, 1), (19, 1), (20, -1), (21, 1), (22, -1), (23, -1), (24, -1), (25, 1), (26, 1), (27, -1), (28, -1), (29, -1), (30, 1)]), - (19, [(1, 1), (2, -1), (3, -1), (4, 1), (5, 1), (6, 1), (7, 1), (8, -1), (9, 1), (10, -1), (11, 1), (12, -1), (13, -1), (14, -1), (15, -1), (16, 1), (17, 1), (18, -1), (19, 0), (20, 1), (21, -1), (22, -1), (23, 1), (24, 1), (25, 1), (26, 1), (27, -1), (28, 1), (29, -1), (30, 1)]), - (21, [(1, 1), (2, -1), (3, 0), (4, 1), (5, 1), (6, 0), (7, 0), (8, -1), (9, 0), (10, -1), (11, -1), (12, 0), (13, -1), (14, 0), (15, 0), (16, 1), (17, 1), (18, 0), (19, -1), (20, 1), (21, 0), (22, 1), (23, -1), (24, 0), (25, 1), (26, 1), (27, 0), (28, 0), (29, -1), (30, 0)]), - (23, [(1, 1), (2, 1), (3, 1), (4, 1), (5, -1), (6, 1), (7, -1), (8, 1), (9, 1), (10, -1), (11, -1), (12, 1), (13, 1), (14, -1), (15, -1), (16, 1), (17, -1), (18, 1), (19, -1), (20, -1), (21, -1), (22, -1), (23, 0), (24, 1), (25, 1), (26, 1), (27, 1), (28, -1), (29, 1), (30, -1)]), - (25, [(1, 1), (2, 1), (3, 1), (4, 1), (5, 0), (6, 1), (7, 1), (8, 1), (9, 1), (10, 0), (11, 1), (12, 1), (13, 1), (14, 1), (15, 0), (16, 1), (17, 1), (18, 1), (19, 1), (20, 0), (21, 1), (22, 1), (23, 1), (24, 1), (25, 0), (26, 1), (27, 1), (28, 1), (29, 1), (30, 0)]), - (27, [(1, 1), (2, -1), (3, 0), (4, 1), (5, -1), (6, 0), (7, 1), (8, -1), (9, 0), (10, 1), (11, -1), (12, 0), (13, 1), (14, -1), (15, 0), (16, 1), (17, -1), (18, 0), (19, 1), (20, -1), (21, 0), (22, 1), (23, -1), (24, 0), (25, 1), (26, -1), (27, 0), (28, 1), (29, -1), (30, 0)]), - (29, [(1, 1), (2, -1), (3, -1), (4, 1), (5, 1), (6, 1), (7, 1), (8, -1), (9, 1), (10, -1), (11, -1), (12, -1), (13, 1), (14, -1), (15, -1), (16, 1), (17, -1), (18, -1), (19, -1), (20, 1), (21, -1), (22, 1), (23, 1), (24, 1), (25, 1), (26, -1), (27, -1), (28, 1), (29, 0), (30, 1)]), - ] - - js = self.Integer.jacobi_symbol - - for n, kj in tv: - for k, j in kj: - self.assertEqual(js(k, n), j) - - def test_hex(self): - v1, = self.Integers(0x10) - self.assertEqual(hex(v1), "0x10") - - def test_mult_modulo_bytes(self): - modmult = self.Integer._mult_modulo_bytes - - res = modmult(4, 5, 19) - self.assertEqual(res, b'\x01') - - res = modmult(4 - 19, 5, 19) - self.assertEqual(res, b'\x01') - - res = modmult(4, 5 - 19, 19) - self.assertEqual(res, b'\x01') - - res = modmult(4 + 19, 5, 19) - self.assertEqual(res, b'\x01') - - res = modmult(4, 5 + 19, 19) - self.assertEqual(res, b'\x01') - - modulus = 2**512 - 1 # 64 bytes - t1 = 13**100 - t2 = 17**100 - expect = b"\xfa\xb2\x11\x87\xc3(y\x07\xf8\xf1n\xdepq\x0b\xca\xf3\xd3B,\xef\xf2\xfbf\xcc)\x8dZ*\x95\x98r\x96\xa8\xd5\xc3}\xe2q:\xa2'z\xf48\xde%\xef\t\x07\xbc\xc4[C\x8bUE2\x90\xef\x81\xaa:\x08" - self.assertEqual(expect, modmult(t1, t2, modulus)) - - self.assertRaises(ZeroDivisionError, modmult, 4, 5, 0) - self.assertRaises(ValueError, modmult, 4, 5, -1) - self.assertRaises(ValueError, modmult, 4, 5, 4) + tv = [ + ( + 3, + [ + (1, 1), + (2, -1), + (3, 0), + (4, 1), + (5, -1), + (6, 0), + (7, 1), + (8, -1), + (9, 0), + (10, 1), + (11, -1), + (12, 0), + (13, 1), + (14, -1), + (15, 0), + (16, 1), + (17, -1), + (18, 0), + (19, 1), + (20, -1), + (21, 0), + (22, 1), + (23, -1), + (24, 0), + (25, 1), + (26, -1), + (27, 0), + (28, 1), + (29, -1), + (30, 0), + ], + ), + ( + 5, + [ + (1, 1), + (2, -1), + (3, -1), + (4, 1), + (5, 0), + (6, 1), + (7, -1), + (8, -1), + (9, 1), + (10, 0), + (11, 1), + (12, -1), + (13, -1), + (14, 1), + (15, 0), + (16, 1), + (17, -1), + (18, -1), + (19, 1), + (20, 0), + (21, 1), + (22, -1), + (23, -1), + (24, 1), + (25, 0), + (26, 1), + (27, -1), + (28, -1), + (29, 1), + (30, 0), + ], + ), + ( + 7, + [ + (1, 1), + (2, 1), + (3, -1), + (4, 1), + (5, -1), + (6, -1), + (7, 0), + (8, 1), + (9, 1), + (10, -1), + (11, 1), + (12, -1), + (13, -1), + (14, 0), + (15, 1), + (16, 1), + (17, -1), + (18, 1), + (19, -1), + (20, -1), + (21, 0), + (22, 1), + (23, 1), + (24, -1), + (25, 1), + (26, -1), + (27, -1), + (28, 0), + (29, 1), + (30, 1), + ], + ), + ( + 9, + [ + (1, 1), + (2, 1), + (3, 0), + (4, 1), + (5, 1), + (6, 0), + (7, 1), + (8, 1), + (9, 0), + (10, 1), + (11, 1), + (12, 0), + (13, 1), + (14, 1), + (15, 0), + (16, 1), + (17, 1), + (18, 0), + (19, 1), + (20, 1), + (21, 0), + (22, 1), + (23, 1), + (24, 0), + (25, 1), + (26, 1), + (27, 0), + (28, 1), + (29, 1), + (30, 0), + ], + ), + ( + 11, + [ + (1, 1), + (2, -1), + (3, 1), + (4, 1), + (5, 1), + (6, -1), + (7, -1), + (8, -1), + (9, 1), + (10, -1), + (11, 0), + (12, 1), + (13, -1), + (14, 1), + (15, 1), + (16, 1), + (17, -1), + (18, -1), + (19, -1), + (20, 1), + (21, -1), + (22, 0), + (23, 1), + (24, -1), + (25, 1), + (26, 1), + (27, 1), + (28, -1), + (29, -1), + (30, -1), + ], + ), + ( + 13, + [ + (1, 1), + (2, -1), + (3, 1), + (4, 1), + (5, -1), + (6, -1), + (7, -1), + (8, -1), + (9, 1), + (10, 1), + (11, -1), + (12, 1), + (13, 0), + (14, 1), + (15, -1), + (16, 1), + (17, 1), + (18, -1), + (19, -1), + (20, -1), + (21, -1), + (22, 1), + (23, 1), + (24, -1), + (25, 1), + (26, 0), + (27, 1), + (28, -1), + (29, 1), + (30, 1), + ], + ), + ( + 15, + [ + (1, 1), + (2, 1), + (3, 0), + (4, 1), + (5, 0), + (6, 0), + (7, -1), + (8, 1), + (9, 0), + (10, 0), + (11, -1), + (12, 0), + (13, -1), + (14, -1), + (15, 0), + (16, 1), + (17, 1), + (18, 0), + (19, 1), + (20, 0), + (21, 0), + (22, -1), + (23, 1), + (24, 0), + (25, 0), + (26, -1), + (27, 0), + (28, -1), + (29, -1), + (30, 0), + ], + ), + ( + 17, + [ + (1, 1), + (2, 1), + (3, -1), + (4, 1), + (5, -1), + (6, -1), + (7, -1), + (8, 1), + (9, 1), + (10, -1), + (11, -1), + (12, -1), + (13, 1), + (14, -1), + (15, 1), + (16, 1), + (17, 0), + (18, 1), + (19, 1), + (20, -1), + (21, 1), + (22, -1), + (23, -1), + (24, -1), + (25, 1), + (26, 1), + (27, -1), + (28, -1), + (29, -1), + (30, 1), + ], + ), + ( + 19, + [ + (1, 1), + (2, -1), + (3, -1), + (4, 1), + (5, 1), + (6, 1), + (7, 1), + (8, -1), + (9, 1), + (10, -1), + (11, 1), + (12, -1), + (13, -1), + (14, -1), + (15, -1), + (16, 1), + (17, 1), + (18, -1), + (19, 0), + (20, 1), + (21, -1), + (22, -1), + (23, 1), + (24, 1), + (25, 1), + (26, 1), + (27, -1), + (28, 1), + (29, -1), + (30, 1), + ], + ), + ( + 21, + [ + (1, 1), + (2, -1), + (3, 0), + (4, 1), + (5, 1), + (6, 0), + (7, 0), + (8, -1), + (9, 0), + (10, -1), + (11, -1), + (12, 0), + (13, -1), + (14, 0), + (15, 0), + (16, 1), + (17, 1), + (18, 0), + (19, -1), + (20, 1), + (21, 0), + (22, 1), + (23, -1), + (24, 0), + (25, 1), + (26, 1), + (27, 0), + (28, 0), + (29, -1), + (30, 0), + ], + ), + ( + 23, + [ + (1, 1), + (2, 1), + (3, 1), + (4, 1), + (5, -1), + (6, 1), + (7, -1), + (8, 1), + (9, 1), + (10, -1), + (11, -1), + (12, 1), + (13, 1), + (14, -1), + (15, -1), + (16, 1), + (17, -1), + (18, 1), + (19, -1), + (20, -1), + (21, -1), + (22, -1), + (23, 0), + (24, 1), + (25, 1), + (26, 1), + (27, 1), + (28, -1), + (29, 1), + (30, -1), + ], + ), + ( + 25, + [ + (1, 1), + (2, 1), + (3, 1), + (4, 1), + (5, 0), + (6, 1), + (7, 1), + (8, 1), + (9, 1), + (10, 0), + (11, 1), + (12, 1), + (13, 1), + (14, 1), + (15, 0), + (16, 1), + (17, 1), + (18, 1), + (19, 1), + (20, 0), + (21, 1), + (22, 1), + (23, 1), + (24, 1), + (25, 0), + (26, 1), + (27, 1), + (28, 1), + (29, 1), + (30, 0), + ], + ), + ( + 27, + [ + (1, 1), + (2, -1), + (3, 0), + (4, 1), + (5, -1), + (6, 0), + (7, 1), + (8, -1), + (9, 0), + (10, 1), + (11, -1), + (12, 0), + (13, 1), + (14, -1), + (15, 0), + (16, 1), + (17, -1), + (18, 0), + (19, 1), + (20, -1), + (21, 0), + (22, 1), + (23, -1), + (24, 0), + (25, 1), + (26, -1), + (27, 0), + (28, 1), + (29, -1), + (30, 0), + ], + ), + ( + 29, + [ + (1, 1), + (2, -1), + (3, -1), + (4, 1), + (5, 1), + (6, 1), + (7, 1), + (8, -1), + (9, 1), + (10, -1), + (11, -1), + (12, -1), + (13, 1), + (14, -1), + (15, -1), + (16, 1), + (17, -1), + (18, -1), + (19, -1), + (20, 1), + (21, -1), + (22, 1), + (23, 1), + (24, 1), + (25, 1), + (26, -1), + (27, -1), + (28, 1), + (29, 0), + (30, 1), + ], + ), + ] + + js = self.Integer.jacobi_symbol + + for n, kj in tv: + for k, j in kj: + self.assertEqual(js(k, n), j) + + def test_hex(self): + (v1,) = self.Integers(0x10) + self.assertEqual(hex(v1), "0x10") + + def test_mult_modulo_bytes(self): + modmult = self.Integer._mult_modulo_bytes + + res = modmult(4, 5, 19) + self.assertEqual(res, b"\x01") + + res = modmult(4 - 19, 5, 19) + self.assertEqual(res, b"\x01") + + res = modmult(4, 5 - 19, 19) + self.assertEqual(res, b"\x01") + + res = modmult(4 + 19, 5, 19) + self.assertEqual(res, b"\x01") + + res = modmult(4, 5 + 19, 19) + self.assertEqual(res, b"\x01") + + modulus = 2**512 - 1 # 64 bytes + t1 = 13**100 + t2 = 17**100 + expect = b"\xfa\xb2\x11\x87\xc3(y\x07\xf8\xf1n\xdepq\x0b\xca\xf3\xd3B,\xef\xf2\xfbf\xcc)\x8dZ*\x95\x98r\x96\xa8\xd5\xc3}\xe2q:\xa2'z\xf48\xde%\xef\t\x07\xbc\xc4[C\x8bUE2\x90\xef\x81\xaa:\x08" + self.assertEqual(expect, modmult(t1, t2, modulus)) + + self.assertRaises(ZeroDivisionError, modmult, 4, 5, 0) + self.assertRaises(ValueError, modmult, 4, 5, -1) + self.assertRaises(ValueError, modmult, 4, 5, 4) class TestIntegerInt(TestIntegerBase): - - def setUp(self): - self.Integer = IntegerNative + def setUp(self): + self.Integer = IntegerNative class testIntegerRandom(unittest.TestCase): + def test_random_exact_bits(self): + for _ in range(1000): + a = IntegerNative.random(exact_bits=8) + self.assertFalse(a < 128) + self.assertFalse(a >= 256) + + for bits_value in range(1024, 1024 + 8): + a = IntegerNative.random(exact_bits=bits_value) + self.assertFalse(a < 2 ** (bits_value - 1)) + self.assertFalse(a >= 2**bits_value) + + def test_random_max_bits(self): + flag = False + for _ in range(1000): + a = IntegerNative.random(max_bits=8) + flag = flag or a < 128 + self.assertFalse(a >= 256) + self.assertTrue(flag) + + for bits_value in range(1024, 1024 + 8): + a = IntegerNative.random(max_bits=bits_value) + self.assertFalse(a >= 2**bits_value) + + def test_random_bits_custom_rng(self): + class CustomRNG(object): + def __init__(self): + self.counter = 0 + + def __call__(self, size): + self.counter += size + return bchr(0) * size + + custom_rng = CustomRNG() + a = IntegerNative.random(exact_bits=32, randfunc=custom_rng) + self.assertEqual(custom_rng.counter, 4) + + def test_random_range(self): + func = IntegerNative.random_range + + for x in range(200): + a = func(min_inclusive=1, max_inclusive=15) + self.assertTrue(1 <= a <= 15) + + for x in range(200): + a = func(min_inclusive=1, max_exclusive=15) + self.assertTrue(1 <= a < 15) + + self.assertRaises( + ValueError, + func, + min_inclusive=1, + max_inclusive=2, + max_exclusive=3, + ) + self.assertRaises(ValueError, func, max_inclusive=2, max_exclusive=3) - def test_random_exact_bits(self): - - for _ in range(1000): - a = IntegerNative.random(exact_bits=8) - self.assertFalse(a < 128) - self.assertFalse(a >= 256) - - for bits_value in range(1024, 1024 + 8): - a = IntegerNative.random(exact_bits=bits_value) - self.assertFalse(a < 2**(bits_value - 1)) - self.assertFalse(a >= 2**bits_value) - - def test_random_max_bits(self): - - flag = False - for _ in range(1000): - a = IntegerNative.random(max_bits=8) - flag = flag or a < 128 - self.assertFalse(a>=256) - self.assertTrue(flag) - - for bits_value in range(1024, 1024 + 8): - a = IntegerNative.random(max_bits=bits_value) - self.assertFalse(a >= 2**bits_value) - - def test_random_bits_custom_rng(self): - - class CustomRNG(object): - def __init__(self): - self.counter = 0 - - def __call__(self, size): - self.counter += size - return bchr(0) * size - - custom_rng = CustomRNG() - a = IntegerNative.random(exact_bits=32, randfunc=custom_rng) - self.assertEqual(custom_rng.counter, 4) - - def test_random_range(self): - - func = IntegerNative.random_range - - for x in range(200): - a = func(min_inclusive=1, max_inclusive=15) - self.assertTrue(1 <= a <= 15) - - for x in range(200): - a = func(min_inclusive=1, max_exclusive=15) - self.assertTrue(1 <= a < 15) - - self.assertRaises(ValueError, func, min_inclusive=1, max_inclusive=2, - max_exclusive=3) - self.assertRaises(ValueError, func, max_inclusive=2, max_exclusive=3) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestIntegerInt) + tests = [] + tests += list_test_cases(TestIntegerInt) + + try: + from Cryptodome.Math._IntegerGMP import IntegerGMP - try: - from Cryptodome.Math._IntegerGMP import IntegerGMP + class TestIntegerGMP(TestIntegerBase): + def setUp(self): + self.Integer = IntegerGMP - class TestIntegerGMP(TestIntegerBase): - def setUp(self): - self.Integer = IntegerGMP + tests += list_test_cases(TestIntegerGMP) + except (ImportError, OSError) as e: + if sys.platform == "win32": + sys.stdout.write("Skipping GMP tests on Windows\n") + else: + sys.stdout.write("Skipping GMP tests (%s)\n" % str(e)) - tests += list_test_cases(TestIntegerGMP) - except (ImportError, OSError) as e: - if sys.platform == "win32": - sys.stdout.write("Skipping GMP tests on Windows\n") - else: - sys.stdout.write("Skipping GMP tests (%s)\n" % str(e) ) + try: + from Cryptodome.Math._IntegerCustom import IntegerCustom - try: - from Cryptodome.Math._IntegerCustom import IntegerCustom + class TestIntegerCustomModexp(TestIntegerBase): + def setUp(self): + self.Integer = IntegerCustom - class TestIntegerCustomModexp(TestIntegerBase): - def setUp(self): - self.Integer = IntegerCustom + tests += list_test_cases(TestIntegerCustomModexp) + except (ImportError, OSError) as e: + sys.stdout.write("Skipping custom modexp tests (%s)\n" % str(e)) - tests += list_test_cases(TestIntegerCustomModexp) - except (ImportError, OSError) as e: - sys.stdout.write("Skipping custom modexp tests (%s)\n" % str(e) ) + tests += list_test_cases(testIntegerRandom) + return tests - tests += list_test_cases(testIntegerRandom) - return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_Primality.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_Primality.py index 475d1d4b..5b826506 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_Primality.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_Primality.py @@ -39,80 +39,117 @@ from Cryptodome.Util.py3compat import * -from Cryptodome.Math.Numbers import Integer from Cryptodome.Math.Primality import ( - PROBABLY_PRIME, COMPOSITE, - miller_rabin_test, lucas_test, - test_probable_prime, - generate_probable_prime, - generate_probable_safe_prime, - ) + PROBABLY_PRIME, + COMPOSITE, + miller_rabin_test, + lucas_test, + test_probable_prime, + generate_probable_prime, + generate_probable_safe_prime, +) class TestPrimality(unittest.TestCase): + primes = ( + 1, + 2, + 3, + 5, + 7, + 11, + 13, + 17, + 19, + 23, + 2**127 - 1, + 175637383534939453397801320455508570374088202376942372758907369518414308188137781042871856139027160010343454418881888953150175357127346872102307696660678617989191485418582475696230580407111841072614783095326672517315988762029036079794994990250662362650625650262324085116467511357592728695033227611029693067539, + ) + composites = ( + 0, + 4, + 6, + 8, + 9, + 10, + 12, + 14, + 15, + 16, + 18, + 20, + 21, + 7 * 23, + (2**19 - 1) * (2**67 - 1), + 9746347772161, + ) + + def test_miller_rabin(self): + for prime in self.primes: + self.assertEqual(miller_rabin_test(prime, 3), PROBABLY_PRIME) + for composite in self.composites: + self.assertEqual(miller_rabin_test(composite, 3), COMPOSITE) + self.assertRaises(ValueError, miller_rabin_test, -1, 3) + + def test_lucas(self): + for prime in self.primes: + res = lucas_test(prime) + self.assertEqual(res, PROBABLY_PRIME) + for composite in self.composites: + res = lucas_test(composite) + self.assertEqual(res, COMPOSITE) + self.assertRaises(ValueError, lucas_test, -1) + + def test_is_prime(self): + primes = ( + 170141183460469231731687303715884105727, + 19175002942688032928599, + 1363005552434666078217421284621279933627102780881053358473, + 2**521 - 1, + ) + for p in primes: + self.assertEqual(test_probable_prime(p), PROBABLY_PRIME) + + not_primes = ( + 4754868377601046732119933839981363081972014948522510826417784001, + 1334733877147062382486934807105197899496002201113849920496510541601, + 260849323075371835669784094383812120359260783810157225730623388382401, + ) + for np in not_primes: + self.assertEqual(test_probable_prime(np), COMPOSITE) + + from Cryptodome.Util.number import sieve_base + + for p in sieve_base[:100]: + res = test_probable_prime(p) + self.assertEqual(res, PROBABLY_PRIME) + + def test_generate_prime_bit_size(self): + p = generate_probable_prime(exact_bits=512) + self.assertEqual(p.size_in_bits(), 512) + + def test_generate_prime_filter(self): + def ending_with_one(number): + return number % 10 == 1 + + for x in range(20): + q = generate_probable_prime( + exact_bits=160, + prime_filter=ending_with_one, + ) + self.assertEqual(q % 10, 1) + + def test_generate_safe_prime(self): + p = generate_probable_safe_prime(exact_bits=161) + self.assertEqual(p.size_in_bits(), 161) - primes = (1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 2**127-1, 175637383534939453397801320455508570374088202376942372758907369518414308188137781042871856139027160010343454418881888953150175357127346872102307696660678617989191485418582475696230580407111841072614783095326672517315988762029036079794994990250662362650625650262324085116467511357592728695033227611029693067539) - composites = (0, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 7*23, (2**19-1)*(2**67-1), 9746347772161,) - - def test_miller_rabin(self): - for prime in self.primes: - self.assertEqual(miller_rabin_test(prime, 3), PROBABLY_PRIME) - for composite in self.composites: - self.assertEqual(miller_rabin_test(composite, 3), COMPOSITE) - self.assertRaises(ValueError, miller_rabin_test, -1, 3) - - def test_lucas(self): - for prime in self.primes: - res = lucas_test(prime) - self.assertEqual(res, PROBABLY_PRIME) - for composite in self.composites: - res = lucas_test(composite) - self.assertEqual(res, COMPOSITE) - self.assertRaises(ValueError, lucas_test, -1) - - def test_is_prime(self): - primes = (170141183460469231731687303715884105727, - 19175002942688032928599, - 1363005552434666078217421284621279933627102780881053358473, - 2 ** 521 - 1) - for p in primes: - self.assertEqual(test_probable_prime(p), PROBABLY_PRIME) - - not_primes = ( - 4754868377601046732119933839981363081972014948522510826417784001, - 1334733877147062382486934807105197899496002201113849920496510541601, - 260849323075371835669784094383812120359260783810157225730623388382401, - ) - for np in not_primes: - self.assertEqual(test_probable_prime(np), COMPOSITE) - - from Cryptodome.Util.number import sieve_base - for p in sieve_base[:100]: - res = test_probable_prime(p) - self.assertEqual(res, PROBABLY_PRIME) - - def test_generate_prime_bit_size(self): - p = generate_probable_prime(exact_bits=512) - self.assertEqual(p.size_in_bits(), 512) - - def test_generate_prime_filter(self): - def ending_with_one(number): - return number % 10 == 1 - - for x in range(20): - q = generate_probable_prime(exact_bits=160, - prime_filter=ending_with_one) - self.assertEqual(q % 10, 1) - - def test_generate_safe_prime(self): - p = generate_probable_safe_prime(exact_bits=161) - self.assertEqual(p.size_in_bits(), 161) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestPrimality) - return tests + tests = [] + tests += list_test_cases(TestPrimality) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_modexp.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_modexp.py index d63f43cf..e6952cb3 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_modexp.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_modexp.py @@ -41,11 +41,12 @@ from Cryptodome.Util.py3compat import * -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, - c_size_t, - c_ulonglong) +from Cryptodome.Util._raw_api import ( + create_string_buffer, + get_raw_buffer, + c_size_t, + c_ulonglong, +) from Cryptodome.Hash import SHAKE128 from Cryptodome.Math.Numbers import Integer @@ -55,147 +56,148 @@ def create_rng(tag): - rng = StrongRandom(SHAKE128.new(data=tag)) - return rng + rng = StrongRandom(SHAKE128.new(data=tag)) + return rng + class ExceptionModulus(ValueError): - pass + pass + def monty_pow(base, exp, modulus): - max_len = len(long_to_bytes(max(base, exp, modulus))) + max_len = len(long_to_bytes(max(base, exp, modulus))) - base_b, exp_b, modulus_b = [ long_to_bytes(x, max_len) for x in - (base, exp, modulus) ] + base_b, exp_b, modulus_b = [long_to_bytes(x, max_len) for x in (base, exp, modulus)] - out = create_string_buffer(max_len) - error = _raw_montgomery.monty_pow( - out, - base_b, - exp_b, - modulus_b, - c_size_t(max_len), - c_ulonglong(32) - ) + out = create_string_buffer(max_len) + error = _raw_montgomery.monty_pow( + out, + base_b, + exp_b, + modulus_b, + c_size_t(max_len), + c_ulonglong(32), + ) - if error == 17: - raise ExceptionModulus() - if error: - raise ValueError("monty_pow failed with error: %d" % error) + if error == 17: + raise ExceptionModulus() + if error: + raise ValueError("monty_pow failed with error: %d" % error) - result = bytes_to_long(get_raw_buffer(out)) - return result + result = bytes_to_long(get_raw_buffer(out)) + return result -exponent1 = 0x2ce0af628901460a419a08ef950d498b9fd6f271a1a52ac293b86fe5c60efe8e8ba93fa1ebe1eb3d614d2e7b328cb60a2591440e163441a190ecf101ceec245f600fffdcf3f5b3a17a7baeacb96a424db1d7ec985e8ec998bb479fecfffed6a75f9a90fc97062fd973303bce855ad7b8d8272a94025e8532be9aabd54a183f303538d2a7e621b4131d59e823a4625f39bd7d518d7784f7c3a8f19061da74974ff42fa1c063dec2db97d461e291a7d6e721708a5229de166c1246363372854e27f3f08ae274bc16bfd205b028a4d81386494433d516dfbb35f495acba5e4e1d1843cb3c3129b6642a85fc7244ce5845fac071c7f622e4ee12ac43fabeeaa0cd01 -modulus1 = 0xd66691b20071be4d66d4b71032b37fa007cfabf579fcb91e50bfc2753b3f0ce7be74e216aef7e26d4ae180bc20d7bd3ea88a6cbf6f87380e613c8979b5b043b200a8ff8856a3b12875e36e98a7569f3852d028e967551000b02c19e9fa52e83115b89309aabb1e1cf1e2cb6369d637d46775ce4523ea31f64ad2794cbc365dd8a35e007ed3b57695877fbf102dbeb8b3212491398e494314e93726926e1383f8abb5889bea954eb8c0ca1c62c8e9d83f41888095c5e645ed6d32515fe0c58c1368cad84694e18da43668c6f43e61d7c9bca633ddcda7aef5b79bc396d4a9f48e2a9abe0836cc455e435305357228e93d25aaed46b952defae0f57339bf26f5a9 +exponent1 = 0x2CE0AF628901460A419A08EF950D498B9FD6F271A1A52AC293B86FE5C60EFE8E8BA93FA1EBE1EB3D614D2E7B328CB60A2591440E163441A190ECF101CEEC245F600FFFDCF3F5B3A17A7BAEACB96A424DB1D7EC985E8EC998BB479FECFFFED6A75F9A90FC97062FD973303BCE855AD7B8D8272A94025E8532BE9AABD54A183F303538D2A7E621B4131D59E823A4625F39BD7D518D7784F7C3A8F19061DA74974FF42FA1C063DEC2DB97D461E291A7D6E721708A5229DE166C1246363372854E27F3F08AE274BC16BFD205B028A4D81386494433D516DFBB35F495ACBA5E4E1D1843CB3C3129B6642A85FC7244CE5845FAC071C7F622E4EE12AC43FABEEAA0CD01 +modulus1 = 0xD66691B20071BE4D66D4B71032B37FA007CFABF579FCB91E50BFC2753B3F0CE7BE74E216AEF7E26D4AE180BC20D7BD3EA88A6CBF6F87380E613C8979B5B043B200A8FF8856A3B12875E36E98A7569F3852D028E967551000B02C19E9FA52E83115B89309AABB1E1CF1E2CB6369D637D46775CE4523EA31F64AD2794CBC365DD8A35E007ED3B57695877FBF102DBEB8B3212491398E494314E93726926E1383F8ABB5889BEA954EB8C0CA1C62C8E9D83F41888095C5E645ED6D32515FE0C58C1368CAD84694E18DA43668C6F43E61D7C9BCA633DDCDA7AEF5B79BC396D4A9F48E2A9ABE0836CC455E435305357228E93D25AAED46B952DEFAE0F57339BF26F5A9 -class TestModExp(unittest.TestCase): - def test_small(self): - self.assertEqual(1, monty_pow(11,12,19)) - - def test_large_1(self): - base = 0xfffffffffffffffffffffffffffffffffffffffffffffffffff - expected = pow(base, exponent1, modulus1) - result = monty_pow(base, exponent1, modulus1) - self.assertEqual(result, expected) - - def test_zero_exp(self): - base = 0xfffffffffffffffffffffffffffffffffffffffffffffffffff - result = monty_pow(base, 0, modulus1) - self.assertEqual(result, 1) - - def test_zero_base(self): - result = monty_pow(0, exponent1, modulus1) - self.assertEqual(result, 0) - - def test_zero_modulus(self): - base = 0xfffffffffffffffffffffffffffffffffffffffffffffffff - self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, 0) - self.assertRaises(ExceptionModulus, monty_pow, 0, 0, 0) - - def test_larger_exponent(self): - base = modulus1 - 0xFFFFFFF - expected = pow(base, modulus1<<64, modulus1) - result = monty_pow(base, modulus1<<64, modulus1) - self.assertEqual(result, expected) - - def test_even_modulus(self): - base = modulus1 >> 4 - self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, modulus1-1) - - def test_several_lengths(self): - prng = SHAKE128.new().update(b('Test')) - for length in range(1, 100): - modulus2 = Integer.from_bytes(prng.read(length)) | 1 - base = Integer.from_bytes(prng.read(length)) % modulus2 - exponent2 = Integer.from_bytes(prng.read(length)) - - expected = pow(base, exponent2, modulus2) - result = monty_pow(base, exponent2, modulus2) - self.assertEqual(result, expected) - - def test_variable_exponent(self): - prng = create_rng(b('Test variable exponent')) - for i in range(20): - for j in range(7): - modulus = prng.getrandbits(8*30) | 1 - base = prng.getrandbits(8*30) % modulus - exponent = prng.getrandbits(i*8+j) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - exponent ^= (1 << (i*8+j)) - 1 - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - def test_stress_63(self): - prng = create_rng(b('Test 63')) - length = 63 - for _ in range(2000): - modulus = prng.getrandbits(8*length) | 1 - base = prng.getrandbits(8*length) % modulus - exponent = prng.getrandbits(8*length) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - def test_stress_64(self): - prng = create_rng(b('Test 64')) - length = 64 - for _ in range(2000): - modulus = prng.getrandbits(8*length) | 1 - base = prng.getrandbits(8*length) % modulus - exponent = prng.getrandbits(8*length) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - def test_stress_65(self): - prng = create_rng(b('Test 65')) - length = 65 - for _ in range(2000): - modulus = prng.getrandbits(8*length) | 1 - base = prng.getrandbits(8*length) % modulus - exponent = prng.getrandbits(8*length) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) +class TestModExp(unittest.TestCase): + def test_small(self): + self.assertEqual(1, monty_pow(11, 12, 19)) + + def test_large_1(self): + base = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + expected = pow(base, exponent1, modulus1) + result = monty_pow(base, exponent1, modulus1) + self.assertEqual(result, expected) + + def test_zero_exp(self): + base = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + result = monty_pow(base, 0, modulus1) + self.assertEqual(result, 1) + + def test_zero_base(self): + result = monty_pow(0, exponent1, modulus1) + self.assertEqual(result, 0) + + def test_zero_modulus(self): + base = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, 0) + self.assertRaises(ExceptionModulus, monty_pow, 0, 0, 0) + + def test_larger_exponent(self): + base = modulus1 - 0xFFFFFFF + expected = pow(base, modulus1 << 64, modulus1) + result = monty_pow(base, modulus1 << 64, modulus1) + self.assertEqual(result, expected) + + def test_even_modulus(self): + base = modulus1 >> 4 + self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, modulus1 - 1) + + def test_several_lengths(self): + prng = SHAKE128.new().update(b("Test")) + for length in range(1, 100): + modulus2 = Integer.from_bytes(prng.read(length)) | 1 + base = Integer.from_bytes(prng.read(length)) % modulus2 + exponent2 = Integer.from_bytes(prng.read(length)) + + expected = pow(base, exponent2, modulus2) + result = monty_pow(base, exponent2, modulus2) + self.assertEqual(result, expected) + + def test_variable_exponent(self): + prng = create_rng(b("Test variable exponent")) + for i in range(20): + for j in range(7): + modulus = prng.getrandbits(8 * 30) | 1 + base = prng.getrandbits(8 * 30) % modulus + exponent = prng.getrandbits(i * 8 + j) + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) + + exponent ^= (1 << (i * 8 + j)) - 1 + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) + + def test_stress_63(self): + prng = create_rng(b("Test 63")) + length = 63 + for _ in range(2000): + modulus = prng.getrandbits(8 * length) | 1 + base = prng.getrandbits(8 * length) % modulus + exponent = prng.getrandbits(8 * length) + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) + + def test_stress_64(self): + prng = create_rng(b("Test 64")) + length = 64 + for _ in range(2000): + modulus = prng.getrandbits(8 * length) | 1 + base = prng.getrandbits(8 * length) % modulus + exponent = prng.getrandbits(8 * length) + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) + + def test_stress_65(self): + prng = create_rng(b("Test 65")) + length = 65 + for _ in range(2000): + modulus = prng.getrandbits(8 * length) | 1 + base = prng.getrandbits(8 * length) % modulus + exponent = prng.getrandbits(8 * length) + + expected = pow(base, exponent, modulus) + result = monty_pow(base, exponent, modulus) + self.assertEqual(result, expected) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestModExp) - return tests + tests = [] + tests += list_test_cases(TestModExp) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_modmult.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_modmult.py index df794e4e..c30c491b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_modmult.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Math/test_modmult.py @@ -39,82 +39,84 @@ from Cryptodome.Util.number import long_to_bytes, bytes_to_long -from Cryptodome.Util._raw_api import (create_string_buffer, - get_raw_buffer, - c_size_t) +from Cryptodome.Util._raw_api import ( + create_string_buffer, + get_raw_buffer, + c_size_t, +) from Cryptodome.Math._IntegerCustom import _raw_montgomery class ExceptionModulus(ValueError): - pass + pass def monty_mult(term1, term2, modulus): + if term1 >= modulus: + term1 %= modulus + if term2 >= modulus: + term2 %= modulus - if term1 >= modulus: - term1 %= modulus - if term2 >= modulus: - term2 %= modulus + modulus_b = long_to_bytes(modulus) + numbers_len = len(modulus_b) + term1_b = long_to_bytes(term1, numbers_len) + term2_b = long_to_bytes(term2, numbers_len) - modulus_b = long_to_bytes(modulus) - numbers_len = len(modulus_b) - term1_b = long_to_bytes(term1, numbers_len) - term2_b = long_to_bytes(term2, numbers_len) + out = create_string_buffer(numbers_len) + error = _raw_montgomery.monty_multiply( + out, + term1_b, + term2_b, + modulus_b, + c_size_t(numbers_len), + ) - out = create_string_buffer(numbers_len) - error = _raw_montgomery.monty_multiply( - out, - term1_b, - term2_b, - modulus_b, - c_size_t(numbers_len) - ) + if error == 17: + raise ExceptionModulus() + if error: + raise ValueError("monty_multiply() failed with error: %d" % error) - if error == 17: - raise ExceptionModulus() - if error: - raise ValueError("monty_multiply() failed with error: %d" % error) + return get_raw_buffer(out) - return get_raw_buffer(out) - -modulus1 = 0xd66691b20071be4d66d4b71032b37fa007cfabf579fcb91e50bfc2753b3f0ce7be74e216aef7e26d4ae180bc20d7bd3ea88a6cbf6f87380e613c8979b5b043b200a8ff8856a3b12875e36e98a7569f3852d028e967551000b02c19e9fa52e83115b89309aabb1e1cf1e2cb6369d637d46775ce4523ea31f64ad2794cbc365dd8a35e007ed3b57695877fbf102dbeb8b3212491398e494314e93726926e1383f8abb5889bea954eb8c0ca1c62c8e9d83f41888095c5e645ed6d32515fe0c58c1368cad84694e18da43668c6f43e61d7c9bca633ddcda7aef5b79bc396d4a9f48e2a9abe0836cc455e435305357228e93d25aaed46b952defae0f57339bf26f5a9 +modulus1 = 0xD66691B20071BE4D66D4B71032B37FA007CFABF579FCB91E50BFC2753B3F0CE7BE74E216AEF7E26D4AE180BC20D7BD3EA88A6CBF6F87380E613C8979B5B043B200A8FF8856A3B12875E36E98A7569F3852D028E967551000B02C19E9FA52E83115B89309AABB1E1CF1E2CB6369D637D46775CE4523EA31F64AD2794CBC365DD8A35E007ED3B57695877FBF102DBEB8B3212491398E494314E93726926E1383F8ABB5889BEA954EB8C0CA1C62C8E9D83F41888095C5E645ED6D32515FE0C58C1368CAD84694E18DA43668C6F43E61D7C9BCA633DDCDA7AEF5B79BC396D4A9F48E2A9ABE0836CC455E435305357228E93D25AAED46B952DEFAE0F57339BF26F5A9 class TestModMultiply(unittest.TestCase): + def test_small(self): + self.assertEqual(b"\x01", monty_mult(5, 6, 29)) - def test_small(self): - self.assertEqual(b"\x01", monty_mult(5, 6, 29)) - - def test_large(self): - numbers_len = (modulus1.bit_length() + 7) // 8 + def test_large(self): + numbers_len = (modulus1.bit_length() + 7) // 8 - t1 = modulus1 // 2 - t2 = modulus1 - 90 - expect = b'\x00' * (numbers_len - 1) + b'\x2d' - self.assertEqual(expect, monty_mult(t1, t2, modulus1)) + t1 = modulus1 // 2 + t2 = modulus1 - 90 + expect = b"\x00" * (numbers_len - 1) + b"\x2d" + self.assertEqual(expect, monty_mult(t1, t2, modulus1)) - def test_zero_term(self): - numbers_len = (modulus1.bit_length() + 7) // 8 - expect = b'\x00' * numbers_len - self.assertEqual(expect, monty_mult(0x100, 0, modulus1)) - self.assertEqual(expect, monty_mult(0, 0x100, modulus1)) + def test_zero_term(self): + numbers_len = (modulus1.bit_length() + 7) // 8 + expect = b"\x00" * numbers_len + self.assertEqual(expect, monty_mult(0x100, 0, modulus1)) + self.assertEqual(expect, monty_mult(0, 0x100, modulus1)) - def test_larger_term(self): - t1 = 2**2047 - expect_int = 0x8edf4071f78e3d7ba622cdbbbef74612e301d69186776ae6bf87ff38c320d9aebaa64889c2f67de2324e6bccd2b10ad89e91fd21ba4bb523904d033eff5e70e62f01a84f41fa90a4f248ef249b82e1d2729253fdfc2a3b5b740198123df8bfbf7057d03e15244ad5f26eb9a099763b5c5972121ec076b0bf899f59bd95f7cc129abddccf24217bce52ca0f3a44c9ccc504765dbb89734205f3ae6a8cc560494a60ea84b27d8e00fa24bdd5b4f1d4232edb61e47d3d984c1fa50a3820a2e580fbc3fc8bc11e99df53b9efadf5a40ac75d384e400905aa6f1d88950cd53b1c54dc2222115ad84a27260fa4d978155c1434c551de1ee7361a17a2f79d4388f78a5d - res = bytes_to_long(monty_mult(t1, t1, modulus1)) - self.assertEqual(res, expect_int) + def test_larger_term(self): + t1 = 2**2047 + expect_int = 0x8EDF4071F78E3D7BA622CDBBBEF74612E301D69186776AE6BF87FF38C320D9AEBAA64889C2F67DE2324E6BCCD2B10AD89E91FD21BA4BB523904D033EFF5E70E62F01A84F41FA90A4F248EF249B82E1D2729253FDFC2A3B5B740198123DF8BFBF7057D03E15244AD5F26EB9A099763B5C5972121EC076B0BF899F59BD95F7CC129ABDDCCF24217BCE52CA0F3A44C9CCC504765DBB89734205F3AE6A8CC560494A60EA84B27D8E00FA24BDD5B4F1D4232EDB61E47D3D984C1FA50A3820A2E580FBC3FC8BC11E99DF53B9EFADF5A40AC75D384E400905AA6F1D88950CD53B1C54DC2222115AD84A27260FA4D978155C1434C551DE1EE7361A17A2F79D4388F78A5D + res = bytes_to_long(monty_mult(t1, t1, modulus1)) + self.assertEqual(res, expect_int) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestModMultiply) - return tests + tests = [] + tests += list_test_cases(TestModMultiply) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/__init__.py index e40f7725..b25c80a3 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/__init__.py @@ -24,22 +24,33 @@ """Self-test for Cryptodome.Protocol""" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Protocol import test_rfc1751; tests += test_rfc1751.get_tests(config=config) - from Cryptodome.SelfTest.Protocol import test_KDF; tests += test_KDF.get_tests(config=config) - from Cryptodome.SelfTest.Protocol import test_ecdh; tests += test_ecdh.get_tests(config=config) + tests = [] + from Cryptodome.SelfTest.Protocol import test_rfc1751 + + tests += test_rfc1751.get_tests(config=config) + from Cryptodome.SelfTest.Protocol import test_KDF + + tests += test_KDF.get_tests(config=config) + from Cryptodome.SelfTest.Protocol import test_ecdh + + tests += test_ecdh.get_tests(config=config) + + from Cryptodome.SelfTest.Protocol import test_SecretSharing + + tests += test_SecretSharing.get_tests(config=config) + + if sys.version_info >= (3, 9): + from Cryptodome.SelfTest.Protocol import test_HPKE + + tests += test_HPKE.get_tests(config=config) - from Cryptodome.SelfTest.Protocol import test_SecretSharing - tests += test_SecretSharing.get_tests(config=config) + return tests - if sys.version_info >= (3, 9): - from Cryptodome.SelfTest.Protocol import test_HPKE - tests += test_HPKE.get_tests(config=config) - return tests +if __name__ == "__main__": + import unittest -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_HPKE.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_HPKE.py index d6339670..7671f38c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_HPKE.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_HPKE.py @@ -14,478 +14,542 @@ class HPKE_Tests(unittest.TestCase): + key1 = ECC.generate(curve="p256") + key2 = ECC.generate(curve="p256") + + # name, size of enc + curves = { + "p256": 65, + "p384": 97, + "p521": 133, + "curve25519": 32, + "curve448": 56, + } + + def round_trip(self, curve, aead_id): + key1 = ECC.generate(curve=curve) + aead_id = aead_id + + encryptor = HPKE.new( + receiver_key=key1.public_key(), + aead_id=aead_id, + ) + self.assertEqual(len(encryptor.enc), self.curves[curve]) + + # First message + ct = encryptor.seal(b"ABC", auth_data=b"DEF") + + decryptor = HPKE.new( + receiver_key=key1, + aead_id=aead_id, + enc=encryptor.enc, + ) + + pt = decryptor.unseal(ct, auth_data=b"DEF") + self.assertEqual(b"ABC", pt) + + # Second message + ct2 = encryptor.seal(b"GHI") + pt2 = decryptor.unseal(ct2) + self.assertEqual(b"GHI", pt2) + + def test_round_trip(self): + for curve in self.curves.keys(): + for aead_id in HPKE.AEAD: + self.round_trip(curve, aead_id) + + def test_psk(self): + aead_id = HPKE.AEAD.AES128_GCM + HPKE.new( + receiver_key=self.key1.public_key(), + aead_id=aead_id, + psk=(b"a", b"c" * 32), + ) + + def test_info(self): + aead_id = HPKE.AEAD.AES128_GCM + HPKE.new( + receiver_key=self.key1.public_key(), + aead_id=aead_id, + info=b"baba", + ) + + def test_neg_unsupported_curve(self): + key3 = ECC.generate(curve="p224") + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=key3.public_key(), + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("Unsupported curve", str(cm.exception)) + + def test_neg_too_many_private_keys(self): + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1, + sender_key=self.key2, + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("Exactly 1 private key", str(cm.exception)) + + def test_neg_curve_mismatch(self): + key3 = ECC.generate(curve="p384") + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + sender_key=key3, + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("but recipient key", str(cm.exception)) + + def test_neg_psk(self): + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + psk=(b"", b"G" * 32), + aead_id=HPKE.AEAD.AES128_GCM, + ) + + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + psk=(b"JJJ", b""), + aead_id=HPKE.AEAD.AES128_GCM, + ) + + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + psk=(b"JJJ", b"Y" * 31), + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("at least 32", str(cm.exception)) + + def test_neg_wrong_enc(self): + wrong_enc = b"\xff" + b"8" * 64 + with self.assertRaises(DeserializeError): + HPKE.new( + receiver_key=self.key1, + aead_id=HPKE.AEAD.AES128_GCM, + enc=wrong_enc, + ) + + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1.public_key(), + enc=self.key1.public_key().export_key(format="raw"), + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("'enc' cannot be an input", str(cm.exception)) + + with self.assertRaises(ValueError) as cm: + HPKE.new( + receiver_key=self.key1, + aead_id=HPKE.AEAD.AES128_GCM, + ) + self.assertIn("'enc' required", str(cm.exception)) + + def test_neg_unseal_wrong_ct(self): + decryptor = HPKE.new( + receiver_key=self.key1, + aead_id=HPKE.AEAD.CHACHA20_POLY1305, + enc=self.key2.public_key().export_key(format="raw"), + ) + + with self.assertRaises(ValueError): + decryptor.unseal(b"XYZ" * 20) + + def test_neg_unseal_no_auth_data(self): + aead_id = HPKE.AEAD.CHACHA20_POLY1305 + + encryptor = HPKE.new( + receiver_key=self.key1.public_key(), + aead_id=aead_id, + ) + + ct = encryptor.seal(b"ABC", auth_data=b"DEF") + + decryptor = HPKE.new( + receiver_key=self.key1, + aead_id=aead_id, + enc=encryptor.enc, + ) + + with self.assertRaises(ValueError): + decryptor.unseal(ct) + + def test_x25519_mode_0(self): + # RFC x9180, A.1.1.1, seq 0 and 1 + + keyR_hex = "4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8" + keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + + pt_hex = "4265617574792069732074727574682c20747275746820626561757479" + pt = bytes.fromhex(pt_hex) + + ct0_hex = "f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83d07bea87e13c512a" + ct0 = bytes.fromhex(ct0_hex) - key1 = ECC.generate(curve='p256') - key2 = ECC.generate(curve='p256') - - # name, size of enc - curves = { - 'p256': 65, - 'p384': 97, - 'p521': 133, - 'curve25519': 32, - 'curve448': 56, - } - - def round_trip(self, curve, aead_id): - key1 = ECC.generate(curve=curve) - aead_id = aead_id - - encryptor = HPKE.new(receiver_key=key1.public_key(), - aead_id=aead_id) - self.assertEqual(len(encryptor.enc), self.curves[curve]) - - # First message - ct = encryptor.seal(b'ABC', auth_data=b'DEF') - - decryptor = HPKE.new(receiver_key=key1, - aead_id=aead_id, - enc=encryptor.enc) - - pt = decryptor.unseal(ct, auth_data=b'DEF') - self.assertEqual(b'ABC', pt) - - # Second message - ct2 = encryptor.seal(b'GHI') - pt2 = decryptor.unseal(ct2) - self.assertEqual(b'GHI', pt2) - - def test_round_trip(self): - for curve in self.curves.keys(): - for aead_id in HPKE.AEAD: - self.round_trip(curve, aead_id) - - def test_psk(self): - aead_id = HPKE.AEAD.AES128_GCM - HPKE.new(receiver_key=self.key1.public_key(), - aead_id=aead_id, - psk=(b'a', b'c' * 32)) - - def test_info(self): - aead_id = HPKE.AEAD.AES128_GCM - HPKE.new(receiver_key=self.key1.public_key(), - aead_id=aead_id, - info=b'baba') - - def test_neg_unsupported_curve(self): - key3 = ECC.generate(curve='p224') - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=key3.public_key(), - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("Unsupported curve", str(cm.exception)) - - def test_neg_too_many_private_keys(self): - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1, - sender_key=self.key2, - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("Exactly 1 private key", str(cm.exception)) - - def test_neg_curve_mismatch(self): - key3 = ECC.generate(curve='p384') - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - sender_key=key3, - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("but recipient key", str(cm.exception)) - - def test_neg_psk(self): - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - psk=(b'', b'G' * 32), - aead_id=HPKE.AEAD.AES128_GCM) - - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - psk=(b'JJJ', b''), - aead_id=HPKE.AEAD.AES128_GCM) - - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - psk=(b'JJJ', b'Y' * 31), - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("at least 32", str(cm.exception)) - - def test_neg_wrong_enc(self): - wrong_enc = b'\xFF' + b'8' * 64 - with self.assertRaises(DeserializeError): - HPKE.new(receiver_key=self.key1, - aead_id=HPKE.AEAD.AES128_GCM, - enc=wrong_enc) + enc_hex = "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431" + enc = bytes.fromhex(enc_hex) - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1.public_key(), - enc=self.key1.public_key().export_key(format='raw'), - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("'enc' cannot be an input", str(cm.exception)) - - with self.assertRaises(ValueError) as cm: - HPKE.new(receiver_key=self.key1, - aead_id=HPKE.AEAD.AES128_GCM) - self.assertIn("'enc' required", str(cm.exception)) + aad0_hex = "436f756e742d30" + aad0 = bytes.fromhex(aad0_hex) - def test_neg_unseal_wrong_ct(self): - decryptor = HPKE.new(receiver_key=self.key1, - aead_id=HPKE.AEAD.CHACHA20_POLY1305, - enc=self.key2.public_key().export_key(format='raw')) + aad1_hex = "436f756e742d31" + aad1 = bytes.fromhex(aad1_hex) - with self.assertRaises(ValueError): - decryptor.unseal(b'XYZ' * 20) + info_hex = "4f6465206f6e2061204772656369616e2055726e" + info = bytes.fromhex(info_hex) - def test_neg_unseal_no_auth_data(self): - aead_id = HPKE.AEAD.CHACHA20_POLY1305 + ct1_hex = "af2d7e9ac9ae7e270f46ba1f975be53c09f8d875bdc8535458c2494e8a6eab251c03d0c22a56b8ca42c2063b84" + ct1 = bytes.fromhex(ct1_hex) - encryptor = HPKE.new(receiver_key=self.key1.public_key(), - aead_id=aead_id) + aead_id = HPKE.AEAD.AES128_GCM - ct = encryptor.seal(b'ABC', auth_data=b'DEF') + decryptor = HPKE.new( + receiver_key=keyR, + aead_id=aead_id, + info=info, + enc=enc, + ) - decryptor = HPKE.new(receiver_key=self.key1, - aead_id=aead_id, - enc=encryptor.enc) + pt_X0 = decryptor.unseal(ct0, aad0) + self.assertEqual(pt_X0, pt) - with self.assertRaises(ValueError): - decryptor.unseal(ct) + pt_X1 = decryptor.unseal(ct1, aad1) + self.assertEqual(pt_X1, pt) - def test_x25519_mode_0(self): - # RFC x9180, A.1.1.1, seq 0 and 1 + def test_x25519_mode_1(self): + # RFC x9180, A.1.2.1, seq 0 and 1 - keyR_hex = "4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8" - keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + keyR_hex = "c5eb01eb457fe6c6f57577c5413b931550a162c71a03ac8d196babbd4e5ce0fd" + keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) - pt_hex = "4265617574792069732074727574682c20747275746820626561757479" - pt = bytes.fromhex(pt_hex) + psk_id_hex = "456e6e796e20447572696e206172616e204d6f726961" + psk_id = bytes.fromhex(psk_id_hex) - ct0_hex = "f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83d07bea87e13c512a" - ct0 = bytes.fromhex(ct0_hex) + psk_hex = "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82" + psk = bytes.fromhex(psk_hex) - enc_hex = "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431" - enc = bytes.fromhex(enc_hex) + pt_hex = "4265617574792069732074727574682c20747275746820626561757479" + pt = bytes.fromhex(pt_hex) - aad0_hex = "436f756e742d30" - aad0 = bytes.fromhex(aad0_hex) + ct0_hex = "e52c6fed7f758d0cf7145689f21bc1be6ec9ea097fef4e959440012f4feb73fb611b946199e681f4cfc34db8ea" + ct0 = bytes.fromhex(ct0_hex) - aad1_hex = "436f756e742d31" - aad1 = bytes.fromhex(aad1_hex) + enc_hex = "0ad0950d9fb9588e59690b74f1237ecdf1d775cd60be2eca57af5a4b0471c91b" + enc = bytes.fromhex(enc_hex) - info_hex = "4f6465206f6e2061204772656369616e2055726e" - info = bytes.fromhex(info_hex) + aad0_hex = "436f756e742d30" + aad0 = bytes.fromhex(aad0_hex) - ct1_hex = "af2d7e9ac9ae7e270f46ba1f975be53c09f8d875bdc8535458c2494e8a6eab251c03d0c22a56b8ca42c2063b84" - ct1 = bytes.fromhex(ct1_hex) + aad1_hex = "436f756e742d31" + aad1 = bytes.fromhex(aad1_hex) - aead_id = HPKE.AEAD.AES128_GCM + info_hex = "4f6465206f6e2061204772656369616e2055726e" + info = bytes.fromhex(info_hex) - decryptor = HPKE.new(receiver_key=keyR, - aead_id=aead_id, - info=info, - enc=enc) + ct1_hex = "49f3b19b28a9ea9f43e8c71204c00d4a490ee7f61387b6719db765e948123b45b61633ef059ba22cd62437c8ba" + ct1 = bytes.fromhex(ct1_hex) - pt_X0 = decryptor.unseal(ct0, aad0) - self.assertEqual(pt_X0, pt) + aead_id = HPKE.AEAD.AES128_GCM - pt_X1 = decryptor.unseal(ct1, aad1) - self.assertEqual(pt_X1, pt) + decryptor = HPKE.new( + receiver_key=keyR, + aead_id=aead_id, + info=info, + psk=(psk_id, psk), + enc=enc, + ) - def test_x25519_mode_1(self): - # RFC x9180, A.1.2.1, seq 0 and 1 + pt_X0 = decryptor.unseal(ct0, aad0) + self.assertEqual(pt_X0, pt) - keyR_hex = "c5eb01eb457fe6c6f57577c5413b931550a162c71a03ac8d196babbd4e5ce0fd" - keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + pt_X1 = decryptor.unseal(ct1, aad1) + self.assertEqual(pt_X1, pt) - psk_id_hex = "456e6e796e20447572696e206172616e204d6f726961" - psk_id = bytes.fromhex(psk_id_hex) + def test_x25519_mode_2(self): + # RFC x9180, A.1.3.1, seq 0 and 1 - psk_hex = "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82" - psk = bytes.fromhex(psk_hex) + keyR_hex = "fdea67cf831f1ca98d8e27b1f6abeb5b7745e9d35348b80fa407ff6958f9137e" + keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) - pt_hex = "4265617574792069732074727574682c20747275746820626561757479" - pt = bytes.fromhex(pt_hex) + keyS_hex = "dc4a146313cce60a278a5323d321f051c5707e9c45ba21a3479fecdf76fc69dd" + keyS = DH.import_x25519_private_key(bytes.fromhex(keyS_hex)) - ct0_hex = "e52c6fed7f758d0cf7145689f21bc1be6ec9ea097fef4e959440012f4feb73fb611b946199e681f4cfc34db8ea" - ct0 = bytes.fromhex(ct0_hex) + pt_hex = "4265617574792069732074727574682c20747275746820626561757479" + pt = bytes.fromhex(pt_hex) - enc_hex = "0ad0950d9fb9588e59690b74f1237ecdf1d775cd60be2eca57af5a4b0471c91b" - enc = bytes.fromhex(enc_hex) + ct0_hex = "5fd92cc9d46dbf8943e72a07e42f363ed5f721212cd90bcfd072bfd9f44e06b80fd17824947496e21b680c141b" + ct0 = bytes.fromhex(ct0_hex) - aad0_hex = "436f756e742d30" - aad0 = bytes.fromhex(aad0_hex) + enc_hex = "23fb952571a14a25e3d678140cd0e5eb47a0961bb18afcf85896e5453c312e76" + enc = bytes.fromhex(enc_hex) - aad1_hex = "436f756e742d31" - aad1 = bytes.fromhex(aad1_hex) + aad0_hex = "436f756e742d30" + aad0 = bytes.fromhex(aad0_hex) - info_hex = "4f6465206f6e2061204772656369616e2055726e" - info = bytes.fromhex(info_hex) + aad1_hex = "436f756e742d31" + aad1 = bytes.fromhex(aad1_hex) - ct1_hex = "49f3b19b28a9ea9f43e8c71204c00d4a490ee7f61387b6719db765e948123b45b61633ef059ba22cd62437c8ba" - ct1 = bytes.fromhex(ct1_hex) + info_hex = "4f6465206f6e2061204772656369616e2055726e" + info = bytes.fromhex(info_hex) - aead_id = HPKE.AEAD.AES128_GCM + ct1_hex = "d3736bb256c19bfa93d79e8f80b7971262cb7c887e35c26370cfed62254369a1b52e3d505b79dd699f002bc8ed" + ct1 = bytes.fromhex(ct1_hex) - decryptor = HPKE.new(receiver_key=keyR, - aead_id=aead_id, - info=info, - psk=(psk_id, psk), - enc=enc) + aead_id = HPKE.AEAD.AES128_GCM - pt_X0 = decryptor.unseal(ct0, aad0) - self.assertEqual(pt_X0, pt) + decryptor = HPKE.new( + receiver_key=keyR, + sender_key=keyS.public_key(), + aead_id=aead_id, + info=info, + enc=enc, + ) - pt_X1 = decryptor.unseal(ct1, aad1) - self.assertEqual(pt_X1, pt) + pt_X0 = decryptor.unseal(ct0, aad0) + self.assertEqual(pt_X0, pt) - def test_x25519_mode_2(self): - # RFC x9180, A.1.3.1, seq 0 and 1 + pt_X1 = decryptor.unseal(ct1, aad1) + self.assertEqual(pt_X1, pt) - keyR_hex = "fdea67cf831f1ca98d8e27b1f6abeb5b7745e9d35348b80fa407ff6958f9137e" - keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + def test_x25519_mode_3(self): + # RFC x9180, A.1.4.1, seq 0 and 1 - keyS_hex = "dc4a146313cce60a278a5323d321f051c5707e9c45ba21a3479fecdf76fc69dd" - keyS = DH.import_x25519_private_key(bytes.fromhex(keyS_hex)) + keyR_hex = "cb29a95649dc5656c2d054c1aa0d3df0493155e9d5da6d7e344ed8b6a64a9423" + keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) - pt_hex = "4265617574792069732074727574682c20747275746820626561757479" - pt = bytes.fromhex(pt_hex) + keyS_hex = "fc1c87d2f3832adb178b431fce2ac77c7ca2fd680f3406c77b5ecdf818b119f4" + keyS = DH.import_x25519_private_key(bytes.fromhex(keyS_hex)) - ct0_hex = "5fd92cc9d46dbf8943e72a07e42f363ed5f721212cd90bcfd072bfd9f44e06b80fd17824947496e21b680c141b" - ct0 = bytes.fromhex(ct0_hex) + psk_id_hex = "456e6e796e20447572696e206172616e204d6f726961" + psk_id = bytes.fromhex(psk_id_hex) - enc_hex = "23fb952571a14a25e3d678140cd0e5eb47a0961bb18afcf85896e5453c312e76" - enc = bytes.fromhex(enc_hex) + psk_hex = "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82" + psk = bytes.fromhex(psk_hex) - aad0_hex = "436f756e742d30" - aad0 = bytes.fromhex(aad0_hex) + pt_hex = "4265617574792069732074727574682c20747275746820626561757479" + pt = bytes.fromhex(pt_hex) - aad1_hex = "436f756e742d31" - aad1 = bytes.fromhex(aad1_hex) + ct0_hex = "a84c64df1e11d8fd11450039d4fe64ff0c8a99fca0bd72c2d4c3e0400bc14a40f27e45e141a24001697737533e" + ct0 = bytes.fromhex(ct0_hex) - info_hex = "4f6465206f6e2061204772656369616e2055726e" - info = bytes.fromhex(info_hex) + enc_hex = "820818d3c23993492cc5623ab437a48a0a7ca3e9639c140fe1e33811eb844b7c" + enc = bytes.fromhex(enc_hex) - ct1_hex = "d3736bb256c19bfa93d79e8f80b7971262cb7c887e35c26370cfed62254369a1b52e3d505b79dd699f002bc8ed" - ct1 = bytes.fromhex(ct1_hex) + aad0_hex = "436f756e742d30" + aad0 = bytes.fromhex(aad0_hex) - aead_id = HPKE.AEAD.AES128_GCM + aad1_hex = "436f756e742d31" + aad1 = bytes.fromhex(aad1_hex) - decryptor = HPKE.new(receiver_key=keyR, - sender_key=keyS.public_key(), - aead_id=aead_id, - info=info, - enc=enc) + info_hex = "4f6465206f6e2061204772656369616e2055726e" + info = bytes.fromhex(info_hex) - pt_X0 = decryptor.unseal(ct0, aad0) - self.assertEqual(pt_X0, pt) + ct1_hex = "4d19303b848f424fc3c3beca249b2c6de0a34083b8e909b6aa4c3688505c05ffe0c8f57a0a4c5ab9da127435d9" + ct1 = bytes.fromhex(ct1_hex) - pt_X1 = decryptor.unseal(ct1, aad1) - self.assertEqual(pt_X1, pt) + aead_id = HPKE.AEAD.AES128_GCM - def test_x25519_mode_3(self): - # RFC x9180, A.1.4.1, seq 0 and 1 + decryptor = HPKE.new( + receiver_key=keyR, + sender_key=keyS.public_key(), + aead_id=aead_id, + psk=(psk_id, psk), + info=info, + enc=enc, + ) - keyR_hex = "cb29a95649dc5656c2d054c1aa0d3df0493155e9d5da6d7e344ed8b6a64a9423" - keyR = DH.import_x25519_private_key(bytes.fromhex(keyR_hex)) + pt_X0 = decryptor.unseal(ct0, aad0) + self.assertEqual(pt_X0, pt) - keyS_hex = "fc1c87d2f3832adb178b431fce2ac77c7ca2fd680f3406c77b5ecdf818b119f4" - keyS = DH.import_x25519_private_key(bytes.fromhex(keyS_hex)) - - psk_id_hex = "456e6e796e20447572696e206172616e204d6f726961" - psk_id = bytes.fromhex(psk_id_hex) - - psk_hex = "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82" - psk = bytes.fromhex(psk_hex) - - pt_hex = "4265617574792069732074727574682c20747275746820626561757479" - pt = bytes.fromhex(pt_hex) - - ct0_hex = "a84c64df1e11d8fd11450039d4fe64ff0c8a99fca0bd72c2d4c3e0400bc14a40f27e45e141a24001697737533e" - ct0 = bytes.fromhex(ct0_hex) - - enc_hex = "820818d3c23993492cc5623ab437a48a0a7ca3e9639c140fe1e33811eb844b7c" - enc = bytes.fromhex(enc_hex) - - aad0_hex = "436f756e742d30" - aad0 = bytes.fromhex(aad0_hex) - - aad1_hex = "436f756e742d31" - aad1 = bytes.fromhex(aad1_hex) - - info_hex = "4f6465206f6e2061204772656369616e2055726e" - info = bytes.fromhex(info_hex) - - ct1_hex = "4d19303b848f424fc3c3beca249b2c6de0a34083b8e909b6aa4c3688505c05ffe0c8f57a0a4c5ab9da127435d9" - ct1 = bytes.fromhex(ct1_hex) - - aead_id = HPKE.AEAD.AES128_GCM - - decryptor = HPKE.new(receiver_key=keyR, - sender_key=keyS.public_key(), - aead_id=aead_id, - psk=(psk_id, psk), - info=info, - enc=enc) - - pt_X0 = decryptor.unseal(ct0, aad0) - self.assertEqual(pt_X0, pt) - - pt_X1 = decryptor.unseal(ct1, aad1) - self.assertEqual(pt_X1, pt) + pt_X1 = decryptor.unseal(ct1, aad1) + self.assertEqual(pt_X1, pt) class HPKE_TestVectors(unittest.TestCase): - - def setUp(self): - self.vectors = [] - try: - import pycryptodome_test_vectors # type: ignore - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(init_dir, "Protocol", "wycheproof", "HPKE-test-vectors.json") - with open(full_file_name, "r") as f: - self.vectors = json.load(f) - except (FileNotFoundError, ImportError): - print("\nWarning: skipping extended tests for HPKE (install pycryptodome-test-vectors)") - - def import_private_key(self, key_hex, kem_id): - key_bin = unhexlify(key_hex) - if kem_id == 0x0010: - return ECC.construct(curve='p256', d=int.from_bytes(key_bin, - byteorder="big")) - elif kem_id == 0x0011: - return ECC.construct(curve='p384', d=int.from_bytes(key_bin, - byteorder="big")) - elif kem_id == 0x0012: - return ECC.construct(curve='p521', d=int.from_bytes(key_bin, - byteorder="big")) - elif kem_id == 0x0020: - return DH.import_x25519_private_key(key_bin) - elif kem_id == 0x0021: - return DH.import_x448_private_key(key_bin) - - def test_hpke_encap(self): - """Test HPKE encapsulation using test vectors.""" - - if not self.vectors: - self.skipTest("No test vectors available") - - for idx, vector in enumerate(self.vectors): - - kem_id = vector["kem_id"] - kdf_id = vector["kdf_id"] - aead_id = vector["aead_id"] - - # No export-only pseudo-cipher - if aead_id == 0xffff: - continue - - # We support only one KDF per curve - supported_combi = { - (0x10, 0x1): SHA256, - (0x11, 0x2): SHA384, - (0x12, 0x3): SHA512, - (0x20, 0x1): SHA256, - (0x21, 0x3): SHA512, - } - hashmod = supported_combi.get((kem_id, kdf_id)) - if hashmod is None: - continue - - with self.subTest(idx=idx, kem_id=kem_id, aead_id=aead_id): - - receiver_pub = self.import_private_key(vector["skRm"], - kem_id).public_key() - - sender_priv = None - if "skSm" in vector: - sender_priv = self.import_private_key(vector["skSm"], - kem_id) - - encap_key = self.import_private_key(vector["skEm"], kem_id) - - shared_secret, enc = HPKE.HPKE_Cipher._encap(receiver_pub, - kem_id, - hashmod, - sender_priv, - encap_key) - self.assertEqual(enc.hex(), vector["enc"]) - self.assertEqual(shared_secret, - unhexlify(vector["shared_secret"])) - - print(".", end="", flush=True) - - def test_hpke_unseal(self): - """Test HPKE encryption and decryption using test vectors.""" - - if not self.vectors: - self.skipTest("No test vectors available") - - for idx, vector in enumerate(self.vectors): - - kem_id = vector["kem_id"] - kdf_id = vector["kdf_id"] - aead_id = vector["aead_id"] - - # No export-only pseudo-cipher - if aead_id == 0xffff: - continue - - # We support only one KDF per curve - supported_combi = ( - (0x10, 0x1), - (0x11, 0x2), - (0x12, 0x3), - (0x20, 0x1), - (0x21, 0x3), - ) - if (kem_id, kdf_id) not in supported_combi: - continue - - with self.subTest(idx=idx, kem_id=kem_id, aead_id=aead_id): - - receiver_priv = self.import_private_key(vector["skRm"], - kem_id) - - sender_pub = None - if "skSm" in vector: - sender_priv = self.import_private_key(vector["skSm"], - kem_id) - sender_pub = sender_priv.public_key() - - encap_key = unhexlify(vector["enc"]) - - psk = None - if "psk_id" in vector: - psk = unhexlify(vector["psk_id"]), unhexlify(vector["psk"]) - - receiver_hpke = HPKE.new(receiver_key=receiver_priv, - aead_id=HPKE.AEAD(aead_id), - enc=encap_key, - sender_key=sender_pub, - psk=psk, - info=unhexlify(vector["info"])) - - for encryption in vector['encryptions']: - - plaintext = unhexlify(encryption["pt"]) - ciphertext = unhexlify(encryption["ct"]) - aad = unhexlify(encryption["aad"]) - - # Decrypt (unseal) - decrypted = receiver_hpke.unseal(ciphertext, aad) - self.assertEqual(decrypted, plaintext, "Decryption failed") - - print(".", end="", flush=True) + def setUp(self): + self.vectors = [] + try: + import pycryptodome_test_vectors # type: ignore + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(init_dir, "Protocol", "wycheproof", "HPKE-test-vectors.json") + with open(full_file_name, "r") as f: + self.vectors = json.load(f) + except (FileNotFoundError, ImportError): + print("\nWarning: skipping extended tests for HPKE (install pycryptodome-test-vectors)") + + def import_private_key(self, key_hex, kem_id): + key_bin = unhexlify(key_hex) + if kem_id == 0x0010: + return ECC.construct( + curve="p256", + d=int.from_bytes( + key_bin, + byteorder="big", + ), + ) + elif kem_id == 0x0011: + return ECC.construct( + curve="p384", + d=int.from_bytes( + key_bin, + byteorder="big", + ), + ) + elif kem_id == 0x0012: + return ECC.construct( + curve="p521", + d=int.from_bytes( + key_bin, + byteorder="big", + ), + ) + elif kem_id == 0x0020: + return DH.import_x25519_private_key(key_bin) + elif kem_id == 0x0021: + return DH.import_x448_private_key(key_bin) + + def test_hpke_encap(self): + """Test HPKE encapsulation using test vectors.""" + + if not self.vectors: + self.skipTest("No test vectors available") + + for idx, vector in enumerate(self.vectors): + kem_id = vector["kem_id"] + kdf_id = vector["kdf_id"] + aead_id = vector["aead_id"] + + # No export-only pseudo-cipher + if aead_id == 0xFFFF: + continue + + # We support only one KDF per curve + supported_combi = { + (0x10, 0x1): SHA256, + (0x11, 0x2): SHA384, + (0x12, 0x3): SHA512, + (0x20, 0x1): SHA256, + (0x21, 0x3): SHA512, + } + hashmod = supported_combi.get((kem_id, kdf_id)) + if hashmod is None: + continue + + with self.subTest(idx=idx, kem_id=kem_id, aead_id=aead_id): + receiver_pub = self.import_private_key( + vector["skRm"], + kem_id, + ).public_key() + + sender_priv = None + if "skSm" in vector: + sender_priv = self.import_private_key( + vector["skSm"], + kem_id, + ) + + encap_key = self.import_private_key(vector["skEm"], kem_id) + + shared_secret, enc = HPKE.HPKE_Cipher._encap( + receiver_pub, + kem_id, + hashmod, + sender_priv, + encap_key, + ) + self.assertEqual(enc.hex(), vector["enc"]) + self.assertEqual( + shared_secret, + unhexlify(vector["shared_secret"]), + ) + + print(".", end="", flush=True) + + def test_hpke_unseal(self): + """Test HPKE encryption and decryption using test vectors.""" + + if not self.vectors: + self.skipTest("No test vectors available") + + for idx, vector in enumerate(self.vectors): + kem_id = vector["kem_id"] + kdf_id = vector["kdf_id"] + aead_id = vector["aead_id"] + + # No export-only pseudo-cipher + if aead_id == 0xFFFF: + continue + + # We support only one KDF per curve + supported_combi = ( + (0x10, 0x1), + (0x11, 0x2), + (0x12, 0x3), + (0x20, 0x1), + (0x21, 0x3), + ) + if (kem_id, kdf_id) not in supported_combi: + continue + + with self.subTest(idx=idx, kem_id=kem_id, aead_id=aead_id): + receiver_priv = self.import_private_key( + vector["skRm"], + kem_id, + ) + + sender_pub = None + if "skSm" in vector: + sender_priv = self.import_private_key( + vector["skSm"], + kem_id, + ) + sender_pub = sender_priv.public_key() + + encap_key = unhexlify(vector["enc"]) + + psk = None + if "psk_id" in vector: + psk = unhexlify(vector["psk_id"]), unhexlify(vector["psk"]) + + receiver_hpke = HPKE.new( + receiver_key=receiver_priv, + aead_id=HPKE.AEAD(aead_id), + enc=encap_key, + sender_key=sender_pub, + psk=psk, + info=unhexlify(vector["info"]), + ) + + for encryption in vector["encryptions"]: + plaintext = unhexlify(encryption["pt"]) + ciphertext = unhexlify(encryption["ct"]) + aad = unhexlify(encryption["aad"]) + + # Decrypt (unseal) + decrypted = receiver_hpke.unseal(ciphertext, aad) + self.assertEqual(decrypted, plaintext, "Decryption failed") + + print(".", end="", flush=True) def get_tests(config={}): + tests = [] + tests += list_test_cases(HPKE_Tests) + + if config.get("slow_tests"): + tests += list_test_cases(HPKE_TestVectors) - tests = [] - tests += list_test_cases(HPKE_Tests) + return tests - if config.get('slow_tests'): - tests += list_test_cases(HPKE_TestVectors) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_KDF.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_KDF.py index eafe3499..8d971657 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_KDF.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_KDF.py @@ -31,779 +31,1202 @@ from Cryptodome.Hash import SHA1, HMAC, SHA256, MD5, SHA224, SHA384, SHA512 from Cryptodome.Cipher import AES, DES3 -from Cryptodome.Protocol.KDF import (PBKDF1, PBKDF2, _S2V, HKDF, scrypt, - bcrypt, bcrypt_check, - SP800_108_Counter) +from Cryptodome.Protocol.KDF import ( + PBKDF1, + PBKDF2, + _S2V, + HKDF, + scrypt, + bcrypt, + bcrypt_check, + SP800_108_Counter, +) from Cryptodome.Protocol.KDF import _bcrypt_decode def t2b(t): - if t is None: - return None - t2 = t.replace(" ", "").replace("\n", "") - return unhexlify(b(t2)) + if t is None: + return None + t2 = t.replace(" ", "").replace("\n", "") + return unhexlify(b(t2)) class TestVector(object): - pass + pass class PBKDF1_Tests(unittest.TestCase): - - # List of tuples with test data. - # Each tuple is made up by: - # Item #0: a pass phrase - # Item #1: salt (8 bytes encoded in hex) - # Item #2: output key length - # Item #3: iterations to use - # Item #4: expected result (encoded in hex) - _testData = ( - # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf - ("password", "78578E5A5D63CB06", 16, 1000, "DC19847E05C64D2FAF10EBFB4A3D2A20"), - ) - - def test1(self): - v = self._testData[0] - res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1) - self.assertEqual(res, t2b(v[4])) + # List of tuples with test data. + # Each tuple is made up by: + # Item #0: a pass phrase + # Item #1: salt (8 bytes encoded in hex) + # Item #2: output key length + # Item #3: iterations to use + # Item #4: expected result (encoded in hex) + _testData = ( + # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf + ("password", "78578E5A5D63CB06", 16, 1000, "DC19847E05C64D2FAF10EBFB4A3D2A20"), + ) + + def test1(self): + v = self._testData[0] + res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1) + self.assertEqual(res, t2b(v[4])) class PBKDF2_Tests(unittest.TestCase): - - # List of tuples with test data. - # Each tuple is made up by: - # Item #0: a pass phrase - # Item #1: salt (encoded in hex) - # Item #2: output key length - # Item #3: iterations to use - # Item #4: hash module - # Item #5: expected result (encoded in hex) - _testData = ( - # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf - ("password","78578E5A5D63CB06",24,2048, SHA1, "BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"), - # From RFC 6050 - ("password","73616c74", 20, 1, SHA1, "0c60c80f961f0e71f3a9b524af6012062fe037a6"), - ("password","73616c74", 20, 2, SHA1, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"), - ("password","73616c74", 20, 4096, SHA1, "4b007901b765489abead49d926f721d065a429c1"), - ("passwordPASSWORDpassword","73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74", - 25, 4096, SHA1, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"), - ( 'pass\x00word',"7361006c74",16,4096, SHA1, "56fa6aa75548099dcc37d7f03425e0c3"), - # From draft-josefsson-scrypt-kdf-01, Chapter 10 - ( 'passwd', '73616c74', 64, 1, SHA256, "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783"), - ( 'Password', '4e61436c', 64, 80000, SHA256, "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d"), - ) - - def test1(self): - # Test only for HMAC-SHA1 as PRF - - def prf_SHA1(p,s): - return HMAC.new(p,s,SHA1).digest() - - def prf_SHA256(p,s): - return HMAC.new(p,s,SHA256).digest() - - for i in range(len(self._testData)): - v = self._testData[i] - password = v[0] - salt = t2b(v[1]) - out_len = v[2] - iters = v[3] - hash_mod = v[4] - expected = t2b(v[5]) - - if hash_mod is SHA1: - res = PBKDF2(password, salt, out_len, iters) - self.assertEqual(res, expected) - - res = PBKDF2(password, salt, out_len, iters, prf_SHA1) - self.assertEqual(res, expected) - else: - res = PBKDF2(password, salt, out_len, iters, prf_SHA256) - self.assertEqual(res, expected) - - def test2(self): - # Verify that prf and hmac_hash_module are mutual exclusive - def prf_SHA1(p,s): - return HMAC.new(p,s,SHA1).digest() - - self.assertRaises(ValueError, PBKDF2, b("xxx"), b("yyy"), 16, 100, - prf=prf_SHA1, hmac_hash_module=SHA1) - - def test3(self): - # Verify that hmac_hash_module works like prf - - password = b("xxx") - salt = b("yyy") - - for hashmod in (MD5, SHA1, SHA224, SHA256, SHA384, SHA512): - - pr1 = PBKDF2(password, salt, 16, 100, - prf=lambda p, s: HMAC.new(p,s,hashmod).digest()) - pr2 = PBKDF2(password, salt, 16, 100, hmac_hash_module=hashmod) - - self.assertEqual(pr1, pr2) - - def test4(self): - # Verify that PBKDF2 can take bytes or strings as password or salt - k1 = PBKDF2("xxx", b("yyy"), 16, 10) - k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) - self.assertEqual(k1, k2) - - k1 = PBKDF2(b("xxx"), "yyy", 16, 10) - k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) - self.assertEqual(k1, k2) + # List of tuples with test data. + # Each tuple is made up by: + # Item #0: a pass phrase + # Item #1: salt (encoded in hex) + # Item #2: output key length + # Item #3: iterations to use + # Item #4: hash module + # Item #5: expected result (encoded in hex) + _testData = ( + # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf + ("password", "78578E5A5D63CB06", 24, 2048, SHA1, "BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"), + # From RFC 6050 + ("password", "73616c74", 20, 1, SHA1, "0c60c80f961f0e71f3a9b524af6012062fe037a6"), + ("password", "73616c74", 20, 2, SHA1, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"), + ("password", "73616c74", 20, 4096, SHA1, "4b007901b765489abead49d926f721d065a429c1"), + ( + "passwordPASSWORDpassword", + "73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74", + 25, + 4096, + SHA1, + "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038", + ), + ("pass\x00word", "7361006c74", 16, 4096, SHA1, "56fa6aa75548099dcc37d7f03425e0c3"), + # From draft-josefsson-scrypt-kdf-01, Chapter 10 + ( + "passwd", + "73616c74", + 64, + 1, + SHA256, + "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783", + ), + ( + "Password", + "4e61436c", + 64, + 80000, + SHA256, + "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d", + ), + ) + + def test1(self): + # Test only for HMAC-SHA1 as PRF + + def prf_SHA1(p, s): + return HMAC.new(p, s, SHA1).digest() + + def prf_SHA256(p, s): + return HMAC.new(p, s, SHA256).digest() + + for i in range(len(self._testData)): + v = self._testData[i] + password = v[0] + salt = t2b(v[1]) + out_len = v[2] + iters = v[3] + hash_mod = v[4] + expected = t2b(v[5]) + + if hash_mod is SHA1: + res = PBKDF2(password, salt, out_len, iters) + self.assertEqual(res, expected) + + res = PBKDF2(password, salt, out_len, iters, prf_SHA1) + self.assertEqual(res, expected) + else: + res = PBKDF2(password, salt, out_len, iters, prf_SHA256) + self.assertEqual(res, expected) + + def test2(self): + # Verify that prf and hmac_hash_module are mutual exclusive + def prf_SHA1(p, s): + return HMAC.new(p, s, SHA1).digest() + + self.assertRaises( + ValueError, + PBKDF2, + b("xxx"), + b("yyy"), + 16, + 100, + prf=prf_SHA1, + hmac_hash_module=SHA1, + ) + + def test3(self): + # Verify that hmac_hash_module works like prf + + password = b("xxx") + salt = b("yyy") + + for hashmod in (MD5, SHA1, SHA224, SHA256, SHA384, SHA512): + pr1 = PBKDF2( + password, + salt, + 16, + 100, + prf=lambda p, s: HMAC.new(p, s, hashmod).digest(), + ) + pr2 = PBKDF2(password, salt, 16, 100, hmac_hash_module=hashmod) + + self.assertEqual(pr1, pr2) + + def test4(self): + # Verify that PBKDF2 can take bytes or strings as password or salt + k1 = PBKDF2("xxx", b("yyy"), 16, 10) + k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) + self.assertEqual(k1, k2) + + k1 = PBKDF2(b("xxx"), "yyy", 16, 10) + k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) + self.assertEqual(k1, k2) class S2V_Tests(unittest.TestCase): - - # Sequence of test vectors. - # Each test vector is made up by: - # Item #0: a tuple of strings - # Item #1: an AES key - # Item #2: the result - # Item #3: the cipher module S2V is based on - # Everything is hex encoded - _testData = [ - - # RFC5297, A.1 - ( - ( '101112131415161718191a1b1c1d1e1f2021222324252627', - '112233445566778899aabbccddee' ), - 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0', - '85632d07c6e8f37f950acd320a2ecc93', - AES - ), - - # RFC5297, A.2 - ( - ( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddcc'+ - 'bbaa99887766554433221100', - '102030405060708090a0', - '09f911029d74e35bd84156c5635688c0', - '7468697320697320736f6d6520706c61'+ - '696e7465787420746f20656e63727970'+ - '74207573696e67205349562d414553'), - '7f7e7d7c7b7a79787776757473727170', - '7bdb6e3b432667eb06f4d14bff2fbd0f', - AES - ), - - ] - - def test1(self): - """Verify correctness of test vector""" - for tv in self._testData: - s2v = _S2V.new(t2b(tv[1]), tv[3]) - for s in tv[0]: - s2v.update(t2b(s)) - result = s2v.derive() - self.assertEqual(result, t2b(tv[2])) - - def test2(self): - """Verify that no more than 127(AES) and 63(TDES) - components are accepted.""" - key = bchr(0) * 8 + bchr(255) * 8 - for module in (AES, DES3): - s2v = _S2V.new(key, module) - max_comps = module.block_size*8-1 - for i in range(max_comps): - s2v.update(b("XX")) - self.assertRaises(TypeError, s2v.update, b("YY")) + # Sequence of test vectors. + # Each test vector is made up by: + # Item #0: a tuple of strings + # Item #1: an AES key + # Item #2: the result + # Item #3: the cipher module S2V is based on + # Everything is hex encoded + _testData = [ + # RFC5297, A.1 + ( + ( + "101112131415161718191a1b1c1d1e1f2021222324252627", + "112233445566778899aabbccddee", + ), + "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0", + "85632d07c6e8f37f950acd320a2ecc93", + AES, + ), + # RFC5297, A.2 + ( + ( + "00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddcc" + "bbaa99887766554433221100", + "102030405060708090a0", + "09f911029d74e35bd84156c5635688c0", + "7468697320697320736f6d6520706c61" + + "696e7465787420746f20656e63727970" + + "74207573696e67205349562d414553", + ), + "7f7e7d7c7b7a79787776757473727170", + "7bdb6e3b432667eb06f4d14bff2fbd0f", + AES, + ), + ] + + def test1(self): + """Verify correctness of test vector""" + for tv in self._testData: + s2v = _S2V.new(t2b(tv[1]), tv[3]) + for s in tv[0]: + s2v.update(t2b(s)) + result = s2v.derive() + self.assertEqual(result, t2b(tv[2])) + + def test2(self): + """Verify that no more than 127(AES) and 63(TDES) + components are accepted.""" + key = bchr(0) * 8 + bchr(255) * 8 + for module in (AES, DES3): + s2v = _S2V.new(key, module) + max_comps = module.block_size * 8 - 1 + for i in range(max_comps): + s2v.update(b("XX")) + self.assertRaises(TypeError, s2v.update, b("YY")) class HKDF_Tests(unittest.TestCase): - - # Test vectors from RFC5869, Appendix A - # Each tuple is made up by: - # Item #0: hash module - # Item #1: secret - # Item #2: salt - # Item #3: context - # Item #4: expected result - _test_vector = ( - ( - SHA256, - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - 42, - "3cb25f25faacd57a90434f64d0362f2a" + - "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + - "34007208d5b887185865" - ), - ( - SHA256, - "000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f" + - "404142434445464748494a4b4c4d4e4f", - "606162636465666768696a6b6c6d6e6f" + - "707172737475767778797a7b7c7d7e7f" + - "808182838485868788898a8b8c8d8e8f" + - "909192939495969798999a9b9c9d9e9f" + - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", - 82, - "b11e398dc80327a1c8e7f78c596a4934" + - "4f012eda2d4efad8a050cc4c19afa97c" + - "59045a99cac7827271cb41c65e590e09" + - "da3275600c2f09b8367793a9aca3db71" + - "cc30c58179ec3e87c14c01d5c1f3434f" + - "1d87" - ), - ( - SHA256, - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - None, - None, - 42, - "8da4e775a563c18f715f802a063c5a31" + - "b8a11f5c5ee1879ec3454e5f3c738d2d" + - "9d201395faa4b61a96c8" - ), - ( - SHA1, - "0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - 42, - "085a01ea1b10f36933068b56efa5ad81" + - "a4f14b822f5b091568a9cdd4f155fda2" + - "c22e422478d305f3f896" - ), - ( - SHA1, - "000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f" + - "404142434445464748494a4b4c4d4e4f", - "606162636465666768696a6b6c6d6e6f" + - "707172737475767778797a7b7c7d7e7f" + - "808182838485868788898a8b8c8d8e8f" + - "909192939495969798999a9b9c9d9e9f" + - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", - 82, - "0bd770a74d1160f7c9f12cd5912a06eb" + - "ff6adcae899d92191fe4305673ba2ffe" + - "8fa3f1a4e5ad79f3f334b3b202b2173c" + - "486ea37ce3d397ed034c7f9dfeb15c5e" + - "927336d0441f4c4300e2cff0d0900b52" + - "d3b4" - ), - ( - SHA1, - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "", - "", - 42, - "0ac1af7002b3d761d1e55298da9d0506" + - "b9ae52057220a306e07b6b87e8df21d0" + - "ea00033de03984d34918" - ), - ( - SHA1, - "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", - None, - "", - 42, - "2c91117204d745f3500d636a62f64f0a" + - "b3bae548aa53d423b0d1f27ebba6f5e5" + - "673a081d70cce7acfc48" - ) - ) - - def test1(self): - for tv in self._test_vector: - secret, salt, info, exp = [ t2b(tv[x]) for x in (1,2,3,5) ] - key_len, hashmod = [ tv[x] for x in (4,0) ] - - output = HKDF(secret, key_len, salt, hashmod, 1, info) - self.assertEqual(output, exp) - - def test2(self): - ref = HKDF(b("XXXXXX"), 12, b("YYYY"), SHA1) - - # Same output, but this time split over 2 keys - key1, key2 = HKDF(b("XXXXXX"), 6, b("YYYY"), SHA1, 2) - self.assertEqual((ref[:6], ref[6:]), (key1, key2)) - - # Same output, but this time split over 3 keys - key1, key2, key3 = HKDF(b("XXXXXX"), 4, b("YYYY"), SHA1, 3) - self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) + # Test vectors from RFC5869, Appendix A + # Each tuple is made up by: + # Item #0: hash module + # Item #1: secret + # Item #2: salt + # Item #3: context + # Item #4: expected result + _test_vector = ( + ( + SHA256, + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + 42, + "3cb25f25faacd57a90434f64d0362f2a" + "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + "34007208d5b887185865", + ), + ( + SHA256, + "000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f" + + "707172737475767778797a7b7c7d7e7f" + + "808182838485868788898a8b8c8d8e8f" + + "909192939495969798999a9b9c9d9e9f" + + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + 82, + "b11e398dc80327a1c8e7f78c596a4934" + + "4f012eda2d4efad8a050cc4c19afa97c" + + "59045a99cac7827271cb41c65e590e09" + + "da3275600c2f09b8367793a9aca3db71" + + "cc30c58179ec3e87c14c01d5c1f3434f" + + "1d87", + ), + ( + SHA256, + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + None, + None, + 42, + "8da4e775a563c18f715f802a063c5a31" + "b8a11f5c5ee1879ec3454e5f3c738d2d" + "9d201395faa4b61a96c8", + ), + ( + SHA1, + "0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + 42, + "085a01ea1b10f36933068b56efa5ad81" + "a4f14b822f5b091568a9cdd4f155fda2" + "c22e422478d305f3f896", + ), + ( + SHA1, + "000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f" + + "707172737475767778797a7b7c7d7e7f" + + "808182838485868788898a8b8c8d8e8f" + + "909192939495969798999a9b9c9d9e9f" + + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + 82, + "0bd770a74d1160f7c9f12cd5912a06eb" + + "ff6adcae899d92191fe4305673ba2ffe" + + "8fa3f1a4e5ad79f3f334b3b202b2173c" + + "486ea37ce3d397ed034c7f9dfeb15c5e" + + "927336d0441f4c4300e2cff0d0900b52" + + "d3b4", + ), + ( + SHA1, + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + 42, + "0ac1af7002b3d761d1e55298da9d0506" + "b9ae52057220a306e07b6b87e8df21d0" + "ea00033de03984d34918", + ), + ( + SHA1, + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + None, + "", + 42, + "2c91117204d745f3500d636a62f64f0a" + "b3bae548aa53d423b0d1f27ebba6f5e5" + "673a081d70cce7acfc48", + ), + ) + + def test1(self): + for tv in self._test_vector: + secret, salt, info, exp = [t2b(tv[x]) for x in (1, 2, 3, 5)] + key_len, hashmod = [tv[x] for x in (4, 0)] + + output = HKDF(secret, key_len, salt, hashmod, 1, info) + self.assertEqual(output, exp) + + def test2(self): + ref = HKDF(b("XXXXXX"), 12, b("YYYY"), SHA1) + + # Same output, but this time split over 2 keys + key1, key2 = HKDF(b("XXXXXX"), 6, b("YYYY"), SHA1, 2) + self.assertEqual((ref[:6], ref[6:]), (key1, key2)) + + # Same output, but this time split over 3 keys + key1, key2, key3 = HKDF(b("XXXXXX"), 4, b("YYYY"), SHA1, 3) + self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) class scrypt_Tests(unittest.TestCase): - - # Test vectors taken from - # https://tools.ietf.org/html/rfc7914 - # - password - # - salt - # - N - # - r - # - p - data = ( - ( - "", - "", - 16, # 2K - 1, - 1, - """ + # Test vectors taken from + # https://tools.ietf.org/html/rfc7914 + # - password + # - salt + # - N + # - r + # - p + data = ( + ( + "", + "", + 16, # 2K + 1, + 1, + """ 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06 - """ - ), - ( - "password", - "NaCl", - 1024, # 1M - 8, - 16, - """ + """, + ), + ( + "password", + "NaCl", + 1024, # 1M + 8, + 16, + """ fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40 - """ - ), - ( - "pleaseletmein", - "SodiumChloride", - 16384, # 16M - 8, - 1, - """ + """, + ), + ( + "pleaseletmein", + "SodiumChloride", + 16384, # 16M + 8, + 1, + """ 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87 - """ - ), - ( - "pleaseletmein", - "SodiumChloride", - 1048576, # 1G - 8, - 1, - """ + """, + ), + ( + "pleaseletmein", + "SodiumChloride", + 1048576, # 1G + 8, + 1, + """ 21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81 ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47 8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3 37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4 - """ - ), - ) - - def setUp(self): - new_test_vectors = [] - for tv in self.data: - new_tv = TestVector() - new_tv.P = b(tv[0]) - new_tv.S = b(tv[1]) - new_tv.N = tv[2] - new_tv.r = tv[3] - new_tv.p = tv[4] - new_tv.output = t2b(tv[5]) - new_tv.dkLen = len(new_tv.output) - new_test_vectors.append(new_tv) - self.data = new_test_vectors - - def test2(self): - - for tv in self.data: - try: - output = scrypt(tv.P, tv.S, tv.dkLen, tv.N, tv.r, tv.p) - except ValueError as e: - if " 2 " in str(e) and tv.N >= 1048576: - import warnings - warnings.warn("Not enough memory to unit test scrypt() with N=1048576", RuntimeWarning) - continue - else: - raise e - self.assertEqual(output, tv.output) - - def test3(self): - ref = scrypt(b("password"), b("salt"), 12, 16, 1, 1) - - # Same output, but this time split over 2 keys - key1, key2 = scrypt(b("password"), b("salt"), 6, 16, 1, 1, 2) - self.assertEqual((ref[:6], ref[6:]), (key1, key2)) - - # Same output, but this time split over 3 keys - key1, key2, key3 = scrypt(b("password"), b("salt"), 4, 16, 1, 1, 3) - self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) + """, + ), + ) + + def setUp(self): + new_test_vectors = [] + for tv in self.data: + new_tv = TestVector() + new_tv.P = b(tv[0]) + new_tv.S = b(tv[1]) + new_tv.N = tv[2] + new_tv.r = tv[3] + new_tv.p = tv[4] + new_tv.output = t2b(tv[5]) + new_tv.dkLen = len(new_tv.output) + new_test_vectors.append(new_tv) + self.data = new_test_vectors + + def test2(self): + for tv in self.data: + try: + output = scrypt(tv.P, tv.S, tv.dkLen, tv.N, tv.r, tv.p) + except ValueError as e: + if " 2 " in str(e) and tv.N >= 1048576: + import warnings + + warnings.warn("Not enough memory to unit test scrypt() with N=1048576", RuntimeWarning) + continue + else: + raise e + self.assertEqual(output, tv.output) + + def test3(self): + ref = scrypt(b("password"), b("salt"), 12, 16, 1, 1) + + # Same output, but this time split over 2 keys + key1, key2 = scrypt(b("password"), b("salt"), 6, 16, 1, 1, 2) + self.assertEqual((ref[:6], ref[6:]), (key1, key2)) + + # Same output, but this time split over 3 keys + key1, key2, key3 = scrypt(b("password"), b("salt"), 4, 16, 1, 1, 3) + self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) class bcrypt_Tests(unittest.TestCase): - - def test_negative_cases(self): - self.assertRaises(ValueError, bcrypt, b"1" * 73, 10) - self.assertRaises(ValueError, bcrypt, b"1" * 10, 3) - self.assertRaises(ValueError, bcrypt, b"1" * 10, 32) - self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"") - self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1") - self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1" * 17) - self.assertRaises(ValueError, bcrypt, b"1\x00" * 10, 4) - - def test_bytearray_mismatch(self): - ref = bcrypt("pwd", 4) - bcrypt_check("pwd", ref) - bref = bytearray(ref) - bcrypt_check("pwd", bref) - - wrong = ref[:-1] + bchr(bref[-1] ^ 0x01) - self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) - - wrong = b"x" + ref[1:] - self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) - - # https://github.com/patrickfav/bcrypt/wiki/Published-Test-Vectors - - def test_empty_password(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"", 4, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$04$zVHmKQtGGQob.b/Nc7l9NO8UlrYcW05FiuCj/SxsFO/ZtiN9.mNzy"), - (b"", 5, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$05$zVHmKQtGGQob.b/Nc7l9NOWES.1hkVBgy5IWImh9DOjKNU8atY4Iy"), - (b"", 6, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$06$zVHmKQtGGQob.b/Nc7l9NOjOl7l4oz3WSh5fJ6414Uw8IXRAUoiaO"), - (b"", 7, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$07$zVHmKQtGGQob.b/Nc7l9NOBsj1dQpBA1HYNGpIETIByoNX9jc.hOi"), - (b"", 8, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$08$zVHmKQtGGQob.b/Nc7l9NOiLTUh/9MDpX86/DLyEzyiFjqjBFePgO"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_random_password_and_salt_short_pw(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"<.S.2K(Zq'", 4, b"VYAclAMpaXY/oqAo9yUpku", b"$2a$04$VYAclAMpaXY/oqAo9yUpkuWmoYywaPzyhu56HxXpVltnBIfmO9tgu"), - (b"5.rApO%5jA", 5, b"kVNDrnYKvbNr5AIcxNzeIu", b"$2a$05$kVNDrnYKvbNr5AIcxNzeIuRcyIF5cZk6UrwHGxENbxP5dVv.WQM/G"), - (b"oW++kSrQW^", 6, b"QLKkRMH9Am6irtPeSKN5sO", b"$2a$06$QLKkRMH9Am6irtPeSKN5sObJGr3j47cO6Pdf5JZ0AsJXuze0IbsNm"), - (b"ggJ\\KbTnDG", 7, b"4H896R09bzjhapgCPS/LYu", b"$2a$07$4H896R09bzjhapgCPS/LYuMzAQluVgR5iu/ALF8L8Aln6lzzYXwbq"), - (b"49b0:;VkH/", 8, b"hfvO2retKrSrx5f2RXikWe", b"$2a$08$hfvO2retKrSrx5f2RXikWeFWdtSesPlbj08t/uXxCeZoHRWDz/xFe"), - (b">9N^5jc##'", 9, b"XZLvl7rMB3EvM0c1.JHivu", b"$2a$09$XZLvl7rMB3EvM0c1.JHivuIDPJWeNJPTVrpjZIEVRYYB/mF6cYgJK"), - (b"\\$ch)s4WXp", 10, b"aIjpMOLK5qiS9zjhcHR5TO", b"$2a$10$aIjpMOLK5qiS9zjhcHR5TOU7v2NFDmcsBmSFDt5EHOgp/jeTF3O/q"), - (b"RYoj\\_>2P7", 12, b"esIAHiQAJNNBrsr5V13l7.", b"$2a$12$esIAHiQAJNNBrsr5V13l7.RFWWJI2BZFtQlkFyiWXjou05GyuREZa"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_random_password_and_salt_long_pw(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"^Q&\"]A`%/A(BVGt>QaX0M-#1ghq_+\":Y0CRmY", 5, b"YuQvhokOGVnevctykUYpKu", b"$2a$05$YuQvhokOGVnevctykUYpKutZD2pWeGGYn3auyLOasguMY3/0BbIyq"), - (b"F%uN/j>[GuB7-jB'_Yj!Tnb7Y!u^6)", 6, b"5L3vpQ0tG9O7k5gQ8nAHAe", b"$2a$06$5L3vpQ0tG9O7k5gQ8nAHAe9xxQiOcOLh8LGcI0PLWhIznsDt.S.C6"), - (b"Z>BobP32ub\"Cfe*Q<-q-=tRSjOBh8\\mLNW.", 9, b"nArqOfdCsD9kIbVnAixnwe", b"$2a$09$nArqOfdCsD9kIbVnAixnwe6s8QvyPYWtQBpEXKir2OJF9/oNBsEFe"), - (b"/MH51`!BP&0tj3%YCA;Xk%e3S`o\\EI", 10, b"ePiAc.s.yoBi3B6p1iQUCe", b"$2a$10$ePiAc.s.yoBi3B6p1iQUCezn3mraLwpVJ5XGelVyYFKyp5FZn/y.u"), - (b"ptAP\"mcg6oH.\";c0U2_oll.OKi5?Ui\"^ai#iQH7ZFtNMfs3AROnIncE9\"BNNoEgO[[*Yk8;RQ(#S,;I+aT", - 5, b"wgkOlGNXIVE2fWkT3gyRoO", b"$2a$05$wgkOlGNXIVE2fWkT3gyRoOqWi4gbi1Wv2Q2Jx3xVs3apl1w.Wtj8C"), - (b"M.E1=dt<.L0Q&p;94NfGm_Oo23+Kpl@M5?WIAL.[@/:'S)W96G8N^AWb7_smmC]>7#fGoB", - 6, b"W9zTCl35nEvUukhhFzkKMe", b"$2a$06$W9zTCl35nEvUukhhFzkKMekjT9/pj7M0lihRVEZrX3m8/SBNZRX7i"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_increasing_password_length(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"a", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.l4WvgHIVg17ZawDIrDM2IjlE64GDNQS"), - (b"aa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.AyUxBk.ThHlsLvRTH7IqcG7yVHJ3SXq"), - (b"aaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.BxOVac5xPB6XFdRc/ZrzM9FgZkqmvbW"), - (b"aaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.Qbr209bpCtfl5hN7UQlG/L4xiD3AKau"), - (b"aaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.oWszihPjDZI0ypReKsaDOW1jBl7oOii"), - (b"aaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ./k.Xxn9YiqtV/sxh3EHbnOHd0Qsq27K"), - (b"aaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.PYJqRFQbgRbIjMd5VNKmdKS4sBVOyDe"), - (b"aaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ..VMYfzaw1wP/SGxowpLeGf13fxCCt.q"), - (b"aaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.5B0p054nO5WgAD1n04XslDY/bqY9RJi"), - (b"aaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.INBTgqm7sdlBJDg.J5mLMSRK25ri04y"), - (b"aaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.s3y7CdFD0OR5p6rsZw/eZ.Dla40KLfm"), - (b"aaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.Jx742Djra6Q7PqJWnTAS.85c28g.Siq"), - (b"aaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.oKMXW3EZcPHcUV0ib5vDBnh9HojXnLu"), - (b"aaaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.w6nIjWpDPNSH5pZUvLjC1q25ONEQpeS"), - (b"aaaaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.k1b2/r9A/hxdwKEKurg6OCn4MwMdiGq"), - (b"aaaaaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.3prCNHVX1Ws.7Hm2bJxFUnQOX9f7DFa"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_non_ascii_characters(self): - # password, cost, salt, bcrypt hash - tvs = [ - ("àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", 4, b"D3qS2aoTVyqM7z8v8crLm.", b"$2a$04$D3qS2aoTVyqM7z8v8crLm.3nKt4CzBZJbyFB.ZebmfCvRw7BGs.Xm"), - ("àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", 5, b"VA1FujiOCMPkUHQ8kF7IaO", b"$2a$05$VA1FujiOCMPkUHQ8kF7IaOg7NGaNvpxwWzSluQutxEVmbZItRTsAa"), - ("àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", 6, b"TXiaNrPeBSz5ugiQlehRt.", b"$2a$06$TXiaNrPeBSz5ugiQlehRt.gwpeDQnXWteQL4z2FulouBr6G7D9KUi"), - ("âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", 4, b"YTn1Qlvps8e1odqMn6G5x.", b"$2a$04$YTn1Qlvps8e1odqMn6G5x.85pqKql6w773EZJAExk7/BatYAI4tyO"), - ("âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", 5, b"C.8k5vJKD2NtfrRI9o17DO", b"$2a$05$C.8k5vJKD2NtfrRI9o17DOfIW0XnwItA529vJnh2jzYTb1QdoY0py"), - ("âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", 6, b"xqfRPj3RYAgwurrhcA6uRO", b"$2a$06$xqfRPj3RYAgwurrhcA6uROtGlXDp/U6/gkoDYHwlubtcVcNft5.vW"), - ("ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", 4, b"y8vGgMmr9EdyxP9rmMKjH.", b"$2a$04$y8vGgMmr9EdyxP9rmMKjH.wv2y3r7yRD79gykQtmb3N3zrwjKsyay"), - ("ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", 5, b"iYH4XIKAOOm/xPQs7xKP1u", b"$2a$05$iYH4XIKAOOm/xPQs7xKP1upD0cWyMn3Jf0ZWiizXbEkVpS41K1dcO"), - ("ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", 6, b"wCOob.D0VV8twafNDB2ape", b"$2a$06$wCOob.D0VV8twafNDB2apegiGD5nqF6Y1e6K95q6Y.R8C4QGd265q"), - ("ΔημοσιεύθηκεστηνΕφημερίδατης", 4, b"E5SQtS6P4568MDXW7cyUp.", b"$2a$04$E5SQtS6P4568MDXW7cyUp.18wfDisKZBxifnPZjAI1d/KTYMfHPYO"), - ("АБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмН", 4, b"03e26gQFHhQwRNf81/ww9.", b"$2a$04$03e26gQFHhQwRNf81/ww9.p1UbrNwxpzWjLuT.zpTLH4t/w5WhAhC"), - ("нОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮю", 4, b"PHNoJwpXCfe32nUtLv2Upu", b"$2a$04$PHNoJwpXCfe32nUtLv2UpuhJXOzd4k7IdFwnEpYwfJVCZ/f/.8Pje"), - ("電电電島岛島兔兔兎龜龟亀國国国區区区", 4, b"wU4/0i1TmNl2u.1jIwBX.u", b"$2a$04$wU4/0i1TmNl2u.1jIwBX.uZUaOL3Rc5ID7nlQRloQh6q5wwhV/zLW"), - ("诶比伊艾弗豆贝尔维吾艾尺开艾丝维贼德", 4, b"P4kreGLhCd26d4WIy7DJXu", b"$2a$04$P4kreGLhCd26d4WIy7DJXusPkhxLvBouzV6OXkL5EB0jux0osjsry"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_special_case_salt(self): - # password, cost, salt, bcrypt hash - tvs = [ - ("-O_=*N!2JP", 4, b"......................", b"$2a$04$......................JjuKLOX9OOwo5PceZZXSkaLDvdmgb82"), - ("7B[$Q<4b>U", 5, b"......................", b"$2a$05$......................DRiedDQZRL3xq5A5FL8y7/6NM8a2Y5W"), - (">d5-I_8^.h", 6, b"......................", b"$2a$06$......................5Mq1Ng8jgDY.uHNU4h5p/x6BedzNH2W"), - (")V`/UM/]1t", 4, b".OC/.OC/.OC/.OC/.OC/.O", b"$2a$04$.OC/.OC/.OC/.OC/.OC/.OQIvKRDAam.Hm5/IaV/.hc7P8gwwIbmi"), - (":@t2.bWuH]", 5, b".OC/.OC/.OC/.OC/.OC/.O", b"$2a$05$.OC/.OC/.OC/.OC/.OC/.ONDbUvdOchUiKmQORX6BlkPofa/QxW9e"), - ("b(#KljF5s\"", 6, b".OC/.OC/.OC/.OC/.OC/.O", b"$2a$06$.OC/.OC/.OC/.OC/.OC/.OHfTd9e7svOu34vi1PCvOcAEq07ST7.K"), - ("@3YaJ^Xs]*", 4, b"eGA.eGA.eGA.eGA.eGA.e.", b"$2a$04$eGA.eGA.eGA.eGA.eGA.e.stcmvh.R70m.0jbfSFVxlONdj1iws0C"), - ("'\"5\\!k*C(p", 5, b"eGA.eGA.eGA.eGA.eGA.e.", b"$2a$05$eGA.eGA.eGA.eGA.eGA.e.vR37mVSbfdHwu.F0sNMvgn8oruQRghy"), - ("edEu7C?$'W", 6, b"eGA.eGA.eGA.eGA.eGA.e.", b"$2a$06$eGA.eGA.eGA.eGA.eGA.e.tSq0FN8MWHQXJXNFnHTPQKtA.n2a..G"), - ("N7dHmg\\PI^", 4, b"999999999999999999999u", b"$2a$04$999999999999999999999uCZfA/pLrlyngNDMq89r1uUk.bQ9icOu"), - ("\"eJuHh!)7*", 5, b"999999999999999999999u", b"$2a$05$999999999999999999999uj8Pfx.ufrJFAoWFLjapYBS5vVEQQ/hK"), - ("ZeDRJ:_tu:", 6, b"999999999999999999999u", b"$2a$06$999999999999999999999u6RB0P9UmbdbQgjoQFEJsrvrKe.BoU6q"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) + def test_negative_cases(self): + self.assertRaises(ValueError, bcrypt, b"1" * 73, 10) + self.assertRaises(ValueError, bcrypt, b"1" * 10, 3) + self.assertRaises(ValueError, bcrypt, b"1" * 10, 32) + self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"") + self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1") + self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1" * 17) + self.assertRaises(ValueError, bcrypt, b"1\x00" * 10, 4) + + def test_bytearray_mismatch(self): + ref = bcrypt("pwd", 4) + bcrypt_check("pwd", ref) + bref = bytearray(ref) + bcrypt_check("pwd", bref) + + wrong = ref[:-1] + bchr(bref[-1] ^ 0x01) + self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) + + wrong = b"x" + ref[1:] + self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) + + # https://github.com/patrickfav/bcrypt/wiki/Published-Test-Vectors + + def test_empty_password(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + b"", + 4, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$04$zVHmKQtGGQob.b/Nc7l9NO8UlrYcW05FiuCj/SxsFO/ZtiN9.mNzy", + ), + ( + b"", + 5, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$05$zVHmKQtGGQob.b/Nc7l9NOWES.1hkVBgy5IWImh9DOjKNU8atY4Iy", + ), + ( + b"", + 6, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$06$zVHmKQtGGQob.b/Nc7l9NOjOl7l4oz3WSh5fJ6414Uw8IXRAUoiaO", + ), + ( + b"", + 7, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$07$zVHmKQtGGQob.b/Nc7l9NOBsj1dQpBA1HYNGpIETIByoNX9jc.hOi", + ), + ( + b"", + 8, + b"zVHmKQtGGQob.b/Nc7l9NO", + b"$2a$08$zVHmKQtGGQob.b/Nc7l9NOiLTUh/9MDpX86/DLyEzyiFjqjBFePgO", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_random_password_and_salt_short_pw(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + b"<.S.2K(Zq'", + 4, + b"VYAclAMpaXY/oqAo9yUpku", + b"$2a$04$VYAclAMpaXY/oqAo9yUpkuWmoYywaPzyhu56HxXpVltnBIfmO9tgu", + ), + ( + b"5.rApO%5jA", + 5, + b"kVNDrnYKvbNr5AIcxNzeIu", + b"$2a$05$kVNDrnYKvbNr5AIcxNzeIuRcyIF5cZk6UrwHGxENbxP5dVv.WQM/G", + ), + ( + b"oW++kSrQW^", + 6, + b"QLKkRMH9Am6irtPeSKN5sO", + b"$2a$06$QLKkRMH9Am6irtPeSKN5sObJGr3j47cO6Pdf5JZ0AsJXuze0IbsNm", + ), + ( + b"ggJ\\KbTnDG", + 7, + b"4H896R09bzjhapgCPS/LYu", + b"$2a$07$4H896R09bzjhapgCPS/LYuMzAQluVgR5iu/ALF8L8Aln6lzzYXwbq", + ), + ( + b"49b0:;VkH/", + 8, + b"hfvO2retKrSrx5f2RXikWe", + b"$2a$08$hfvO2retKrSrx5f2RXikWeFWdtSesPlbj08t/uXxCeZoHRWDz/xFe", + ), + ( + b">9N^5jc##'", + 9, + b"XZLvl7rMB3EvM0c1.JHivu", + b"$2a$09$XZLvl7rMB3EvM0c1.JHivuIDPJWeNJPTVrpjZIEVRYYB/mF6cYgJK", + ), + ( + b"\\$ch)s4WXp", + 10, + b"aIjpMOLK5qiS9zjhcHR5TO", + b"$2a$10$aIjpMOLK5qiS9zjhcHR5TOU7v2NFDmcsBmSFDt5EHOgp/jeTF3O/q", + ), + ( + b"RYoj\\_>2P7", + 12, + b"esIAHiQAJNNBrsr5V13l7.", + b"$2a$12$esIAHiQAJNNBrsr5V13l7.RFWWJI2BZFtQlkFyiWXjou05GyuREZa", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_random_password_and_salt_long_pw(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + b'^Q&"]A`%/A(BVGt>QaX0M-#1ghq_+":Y0CRmY', + 5, + b"YuQvhokOGVnevctykUYpKu", + b"$2a$05$YuQvhokOGVnevctykUYpKutZD2pWeGGYn3auyLOasguMY3/0BbIyq", + ), + ( + b"F%uN/j>[GuB7-jB'_Yj!Tnb7Y!u^6)", + 6, + b"5L3vpQ0tG9O7k5gQ8nAHAe", + b"$2a$06$5L3vpQ0tG9O7k5gQ8nAHAe9xxQiOcOLh8LGcI0PLWhIznsDt.S.C6", + ), + ( + b'Z>BobP32ub"Cfe*Q<-q-=tRSjOBh8\\mLNW.", + 9, + b"nArqOfdCsD9kIbVnAixnwe", + b"$2a$09$nArqOfdCsD9kIbVnAixnwe6s8QvyPYWtQBpEXKir2OJF9/oNBsEFe", + ), + ( + b"/MH51`!BP&0tj3%YCA;Xk%e3S`o\\EI", + 10, + b"ePiAc.s.yoBi3B6p1iQUCe", + b"$2a$10$ePiAc.s.yoBi3B6p1iQUCezn3mraLwpVJ5XGelVyYFKyp5FZn/y.u", + ), + ( + b'ptAP"mcg6oH.";c0U2_oll.OKi5?Ui"^ai#iQH7ZFtNMfs3AROnIncE9"BNNoEgO[[*Yk8;RQ(#S,;I+aT', + 5, + b"wgkOlGNXIVE2fWkT3gyRoO", + b"$2a$05$wgkOlGNXIVE2fWkT3gyRoOqWi4gbi1Wv2Q2Jx3xVs3apl1w.Wtj8C", + ), + ( + b"M.E1=dt<.L0Q&p;94NfGm_Oo23+Kpl@M5?WIAL.[@/:'S)W96G8N^AWb7_smmC]>7#fGoB", + 6, + b"W9zTCl35nEvUukhhFzkKMe", + b"$2a$06$W9zTCl35nEvUukhhFzkKMekjT9/pj7M0lihRVEZrX3m8/SBNZRX7i", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_increasing_password_length(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + b"a", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.l4WvgHIVg17ZawDIrDM2IjlE64GDNQS", + ), + ( + b"aa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.AyUxBk.ThHlsLvRTH7IqcG7yVHJ3SXq", + ), + ( + b"aaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.BxOVac5xPB6XFdRc/ZrzM9FgZkqmvbW", + ), + ( + b"aaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.Qbr209bpCtfl5hN7UQlG/L4xiD3AKau", + ), + ( + b"aaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.oWszihPjDZI0ypReKsaDOW1jBl7oOii", + ), + ( + b"aaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ./k.Xxn9YiqtV/sxh3EHbnOHd0Qsq27K", + ), + ( + b"aaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.PYJqRFQbgRbIjMd5VNKmdKS4sBVOyDe", + ), + ( + b"aaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ..VMYfzaw1wP/SGxowpLeGf13fxCCt.q", + ), + ( + b"aaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.5B0p054nO5WgAD1n04XslDY/bqY9RJi", + ), + ( + b"aaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.INBTgqm7sdlBJDg.J5mLMSRK25ri04y", + ), + ( + b"aaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.s3y7CdFD0OR5p6rsZw/eZ.Dla40KLfm", + ), + ( + b"aaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.Jx742Djra6Q7PqJWnTAS.85c28g.Siq", + ), + ( + b"aaaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.oKMXW3EZcPHcUV0ib5vDBnh9HojXnLu", + ), + ( + b"aaaaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.w6nIjWpDPNSH5pZUvLjC1q25ONEQpeS", + ), + ( + b"aaaaaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.k1b2/r9A/hxdwKEKurg6OCn4MwMdiGq", + ), + ( + b"aaaaaaaaaaaaaaaa", + 4, + b"5DCebwootqWMCp59ISrMJ.", + b"$2a$04$5DCebwootqWMCp59ISrMJ.3prCNHVX1Ws.7Hm2bJxFUnQOX9f7DFa", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_non_ascii_characters(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", + 4, + b"D3qS2aoTVyqM7z8v8crLm.", + b"$2a$04$D3qS2aoTVyqM7z8v8crLm.3nKt4CzBZJbyFB.ZebmfCvRw7BGs.Xm", + ), + ( + "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", + 5, + b"VA1FujiOCMPkUHQ8kF7IaO", + b"$2a$05$VA1FujiOCMPkUHQ8kF7IaOg7NGaNvpxwWzSluQutxEVmbZItRTsAa", + ), + ( + "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", + 6, + b"TXiaNrPeBSz5ugiQlehRt.", + b"$2a$06$TXiaNrPeBSz5ugiQlehRt.gwpeDQnXWteQL4z2FulouBr6G7D9KUi", + ), + ( + "âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", + 4, + b"YTn1Qlvps8e1odqMn6G5x.", + b"$2a$04$YTn1Qlvps8e1odqMn6G5x.85pqKql6w773EZJAExk7/BatYAI4tyO", + ), + ( + "âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", + 5, + b"C.8k5vJKD2NtfrRI9o17DO", + b"$2a$05$C.8k5vJKD2NtfrRI9o17DOfIW0XnwItA529vJnh2jzYTb1QdoY0py", + ), + ( + "âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", + 6, + b"xqfRPj3RYAgwurrhcA6uRO", + b"$2a$06$xqfRPj3RYAgwurrhcA6uROtGlXDp/U6/gkoDYHwlubtcVcNft5.vW", + ), + ( + "ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", + 4, + b"y8vGgMmr9EdyxP9rmMKjH.", + b"$2a$04$y8vGgMmr9EdyxP9rmMKjH.wv2y3r7yRD79gykQtmb3N3zrwjKsyay", + ), + ( + "ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", + 5, + b"iYH4XIKAOOm/xPQs7xKP1u", + b"$2a$05$iYH4XIKAOOm/xPQs7xKP1upD0cWyMn3Jf0ZWiizXbEkVpS41K1dcO", + ), + ( + "ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", + 6, + b"wCOob.D0VV8twafNDB2ape", + b"$2a$06$wCOob.D0VV8twafNDB2apegiGD5nqF6Y1e6K95q6Y.R8C4QGd265q", + ), + ( + "ΔημοσιεύθηκεστηνΕφημερίδατης", + 4, + b"E5SQtS6P4568MDXW7cyUp.", + b"$2a$04$E5SQtS6P4568MDXW7cyUp.18wfDisKZBxifnPZjAI1d/KTYMfHPYO", + ), + ( + "АБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмН", + 4, + b"03e26gQFHhQwRNf81/ww9.", + b"$2a$04$03e26gQFHhQwRNf81/ww9.p1UbrNwxpzWjLuT.zpTLH4t/w5WhAhC", + ), + ( + "нОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮю", + 4, + b"PHNoJwpXCfe32nUtLv2Upu", + b"$2a$04$PHNoJwpXCfe32nUtLv2UpuhJXOzd4k7IdFwnEpYwfJVCZ/f/.8Pje", + ), + ( + "電电電島岛島兔兔兎龜龟亀國国国區区区", + 4, + b"wU4/0i1TmNl2u.1jIwBX.u", + b"$2a$04$wU4/0i1TmNl2u.1jIwBX.uZUaOL3Rc5ID7nlQRloQh6q5wwhV/zLW", + ), + ( + "诶比伊艾弗豆贝尔维吾艾尺开艾丝维贼德", + 4, + b"P4kreGLhCd26d4WIy7DJXu", + b"$2a$04$P4kreGLhCd26d4WIy7DJXusPkhxLvBouzV6OXkL5EB0jux0osjsry", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) + + def test_special_case_salt(self): + # password, cost, salt, bcrypt hash + tvs = [ + ( + "-O_=*N!2JP", + 4, + b"......................", + b"$2a$04$......................JjuKLOX9OOwo5PceZZXSkaLDvdmgb82", + ), + ( + "7B[$Q<4b>U", + 5, + b"......................", + b"$2a$05$......................DRiedDQZRL3xq5A5FL8y7/6NM8a2Y5W", + ), + ( + ">d5-I_8^.h", + 6, + b"......................", + b"$2a$06$......................5Mq1Ng8jgDY.uHNU4h5p/x6BedzNH2W", + ), + ( + ")V`/UM/]1t", + 4, + b".OC/.OC/.OC/.OC/.OC/.O", + b"$2a$04$.OC/.OC/.OC/.OC/.OC/.OQIvKRDAam.Hm5/IaV/.hc7P8gwwIbmi", + ), + ( + ":@t2.bWuH]", + 5, + b".OC/.OC/.OC/.OC/.OC/.O", + b"$2a$05$.OC/.OC/.OC/.OC/.OC/.ONDbUvdOchUiKmQORX6BlkPofa/QxW9e", + ), + ( + 'b(#KljF5s"', + 6, + b".OC/.OC/.OC/.OC/.OC/.O", + b"$2a$06$.OC/.OC/.OC/.OC/.OC/.OHfTd9e7svOu34vi1PCvOcAEq07ST7.K", + ), + ( + "@3YaJ^Xs]*", + 4, + b"eGA.eGA.eGA.eGA.eGA.e.", + b"$2a$04$eGA.eGA.eGA.eGA.eGA.e.stcmvh.R70m.0jbfSFVxlONdj1iws0C", + ), + ( + "'\"5\\!k*C(p", + 5, + b"eGA.eGA.eGA.eGA.eGA.e.", + b"$2a$05$eGA.eGA.eGA.eGA.eGA.e.vR37mVSbfdHwu.F0sNMvgn8oruQRghy", + ), + ( + "edEu7C?$'W", + 6, + b"eGA.eGA.eGA.eGA.eGA.e.", + b"$2a$06$eGA.eGA.eGA.eGA.eGA.e.tSq0FN8MWHQXJXNFnHTPQKtA.n2a..G", + ), + ( + "N7dHmg\\PI^", + 4, + b"999999999999999999999u", + b"$2a$04$999999999999999999999uCZfA/pLrlyngNDMq89r1uUk.bQ9icOu", + ), + ( + '"eJuHh!)7*', + 5, + b"999999999999999999999u", + b"$2a$05$999999999999999999999uj8Pfx.ufrJFAoWFLjapYBS5vVEQQ/hK", + ), + ( + "ZeDRJ:_tu:", + 6, + b"999999999999999999999u", + b"$2a$06$999999999999999999999u6RB0P9UmbdbQgjoQFEJsrvrKe.BoU6q", + ), + ] + + for idx, (password, cost, salt64, result) in enumerate(tvs): + x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) + self.assertEqual(x, result) + bcrypt_check(password, result) class TestVectorsHKDFWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def add_tests(self, filename): - - def filter_algo(root): - algo_name = root['algorithm'] - if algo_name == "HKDF-SHA-1": - return SHA1 - elif algo_name == "HKDF-SHA-256": - return SHA256 - elif algo_name == "HKDF-SHA-384": - return SHA384 - elif algo_name == "HKDF-SHA-512": - return SHA512 - else: - raise ValueError("Unknown algorithm " + algo_name) - - def filter_size(unit): - return int(unit['size']) - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof HMAC (%s)" % filename, - root_tag={'hash_module': filter_algo}, - unit_tag={'size': filter_size}) - return result - - def setUp(self): - self.tv = [] - self.add_tests("hkdf_sha1_test.json") - self.add_tests("hkdf_sha256_test.json") - self.add_tests("hkdf_sha384_test.json") - self.add_tests("hkdf_sha512_test.json") - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof HKDF Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - - try: - key = HKDF(tv.ikm, tv.size, tv.salt, tv.hash_module, 1, tv.info) - except ValueError: - assert not tv.valid - else: - if key != tv.okm: - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def add_tests(self, filename): + def filter_algo(root): + algo_name = root["algorithm"] + if algo_name == "HKDF-SHA-1": + return SHA1 + elif algo_name == "HKDF-SHA-256": + return SHA256 + elif algo_name == "HKDF-SHA-384": + return SHA384 + elif algo_name == "HKDF-SHA-512": + return SHA512 + else: + raise ValueError("Unknown algorithm " + algo_name) + + def filter_size(unit): + return int(unit["size"]) + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof HMAC (%s)" % filename, + root_tag={"hash_module": filter_algo}, + unit_tag={"size": filter_size}, + ) + return result + + def setUp(self): + self.tv = [] + self.add_tests("hkdf_sha1_test.json") + self.add_tests("hkdf_sha256_test.json") + self.add_tests("hkdf_sha384_test.json") + self.add_tests("hkdf_sha512_test.json") + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof HKDF Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + + try: + key = HKDF(tv.ikm, tv.size, tv.salt, tv.hash_module, 1, tv.info) + except ValueError: + assert not tv.valid + else: + if key != tv.okm: + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) def load_hash_by_name(hash_name): - return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) + return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) class SP800_108_Counter_Tests(unittest.TestCase): - - def test_negative_zeroes(self): - def prf(s, x): - return HMAC.new(s, x, SHA256).digest() - - try: - _ = SP800_108_Counter(b'0' * 16, 1, prf, label=b'A\x00B') - except ValueError: - self.fail('SP800_108_Counter failed with zero in label') - self.assertRaises(ValueError, SP800_108_Counter, b'0' * 16, 1, prf, - context=b'A\x00B') - - def test_multiple_keys(self): - def prf(s, x): - return HMAC.new(s, x, SHA256).digest() - - key = b'0' * 16 - expected = SP800_108_Counter(key, 2*3*23, prf) - for r in (1, 2, 3, 23): - dks = SP800_108_Counter(key, r, prf, 138//r) - self.assertEqual(len(dks), 138//r) - self.assertEqual(len(dks[0]), r) - self.assertEqual(b''.join(dks), expected) + def test_negative_zeroes(self): + def prf(s, x): + return HMAC.new(s, x, SHA256).digest() + + try: + _ = SP800_108_Counter(b"0" * 16, 1, prf, label=b"A\x00B") + except ValueError: + self.fail("SP800_108_Counter failed with zero in label") + self.assertRaises( + ValueError, + SP800_108_Counter, + b"0" * 16, + 1, + prf, + context=b"A\x00B", + ) + + def test_multiple_keys(self): + def prf(s, x): + return HMAC.new(s, x, SHA256).digest() + + key = b"0" * 16 + expected = SP800_108_Counter(key, 2 * 3 * 23, prf) + for r in (1, 2, 3, 23): + dks = SP800_108_Counter(key, r, prf, 138 // r) + self.assertEqual(len(dks), 138 // r) + self.assertEqual(len(dks[0]), r) + self.assertEqual(b"".join(dks), expected) def add_tests_sp800_108_counter(cls): - - test_vectors_sp800_108_counter = load_test_vectors(("Protocol", ), - "KDF_SP800_108_COUNTER.txt", - "NIST SP 800 108 KDF Counter Mode", - {'count': lambda x: int(x)}, - ) or [] - - mac_type = None - for idx, tv in enumerate(test_vectors_sp800_108_counter): - - if isinstance(tv, str): - res = re.match(r"\[HMAC-(SHA-[0-9]+)\]", tv) - if res: - hash_name = res.group(1).replace("-", "") - hash_module = load_hash_by_name(hash_name) - mac_type = "hmac" - continue - res = re.match(r"\[CMAC-AES-128\]", tv) - if res: - mac_type = "cmac" - continue - assert res - - if mac_type == "hmac": - def prf(s, x, hash_module=hash_module): - return HMAC.new(s, x, hash_module).digest() - elif mac_type == "cmac": - def prf(s, x, hash_module=hash_module): - return CMAC.new(s, x, AES).digest() - continue - - def kdf_test(self, prf=prf, kin=tv.kin, label=tv.label, - context=tv.context, kout=tv.kout, count=tv.count): - result = SP800_108_Counter(kin, len(kout), prf, 1, label, context) - assert(len(result) == len(kout)) - self.assertEqual(result, kout) - - setattr(cls, "test_kdf_sp800_108_counter_%d" % idx, kdf_test) + test_vectors_sp800_108_counter = ( + load_test_vectors( + ("Protocol",), + "KDF_SP800_108_COUNTER.txt", + "NIST SP 800 108 KDF Counter Mode", + {"count": lambda x: int(x)}, + ) + or [] + ) + + mac_type = None + for idx, tv in enumerate(test_vectors_sp800_108_counter): + if isinstance(tv, str): + res = re.match(r"\[HMAC-(SHA-[0-9]+)\]", tv) + if res: + hash_name = res.group(1).replace("-", "") + hash_module = load_hash_by_name(hash_name) + mac_type = "hmac" + continue + res = re.match(r"\[CMAC-AES-128\]", tv) + if res: + mac_type = "cmac" + continue + assert res + + if mac_type == "hmac": + + def prf(s, x, hash_module=hash_module): + return HMAC.new(s, x, hash_module).digest() + elif mac_type == "cmac": + + def prf(s, x, hash_module=hash_module): + return CMAC.new(s, x, AES).digest() + + continue + + def kdf_test( + self, + prf=prf, + kin=tv.kin, + label=tv.label, + context=tv.context, + kout=tv.kout, + count=tv.count, + ): + result = SP800_108_Counter(kin, len(kout), prf, 1, label, context) + assert len(result) == len(kout) + self.assertEqual(result, kout) + + setattr(cls, "test_kdf_sp800_108_counter_%d" % idx, kdf_test) add_tests_sp800_108_counter(SP800_108_Counter_Tests) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") - if not config.get('slow_tests'): - PBKDF2_Tests._testData = PBKDF2_Tests._testData[:3] - scrypt_Tests.data = scrypt_Tests.data[:3] + if not config.get("slow_tests"): + PBKDF2_Tests._testData = PBKDF2_Tests._testData[:3] + scrypt_Tests.data = scrypt_Tests.data[:3] - tests = [] - tests += list_test_cases(PBKDF1_Tests) - tests += list_test_cases(PBKDF2_Tests) - tests += list_test_cases(S2V_Tests) - tests += list_test_cases(HKDF_Tests) - tests += [TestVectorsHKDFWycheproof(wycheproof_warnings)] - tests += list_test_cases(scrypt_Tests) - tests += list_test_cases(bcrypt_Tests) - tests += list_test_cases(SP800_108_Counter_Tests) + tests = [] + tests += list_test_cases(PBKDF1_Tests) + tests += list_test_cases(PBKDF2_Tests) + tests += list_test_cases(S2V_Tests) + tests += list_test_cases(HKDF_Tests) + tests += [TestVectorsHKDFWycheproof(wycheproof_warnings)] + tests += list_test_cases(scrypt_Tests) + tests += list_test_cases(bcrypt_Tests) + tests += list_test_cases(SP800_108_Counter_Tests) - return tests + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_SecretSharing.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_SecretSharing.py index afcbb231..f3694434 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_SecretSharing.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_SecretSharing.py @@ -32,259 +32,278 @@ # =================================================================== from unittest import main, TestCase, TestSuite -from binascii import unhexlify, hexlify +from binascii import unhexlify from Cryptodome.Util.py3compat import * from Cryptodome.Hash import SHAKE128 from Cryptodome.SelfTest.st_common import list_test_cases -from Cryptodome.Protocol.SecretSharing import Shamir, _Element, \ - _mult_gf2, _div_gf2 +from Cryptodome.Protocol.SecretSharing import Shamir, _Element, _mult_gf2, _div_gf2 class GF2_Tests(TestCase): + def test_mult_gf2(self): + # Prove mult by zero + x = _mult_gf2(0, 0) + self.assertEqual(x, 0) + + # Prove mult by unity + x = _mult_gf2(34, 1) + self.assertEqual(x, 34) + + z = 3 # (x+1) + y = _mult_gf2(z, z) + self.assertEqual(y, 5) # (x+1)^2 = x^2 + 1 + y = _mult_gf2(y, z) + self.assertEqual(y, 15) # (x+1)^3 = x^3 + x^2 + x + 1 + y = _mult_gf2(y, z) + self.assertEqual(y, 17) # (x+1)^4 = x^4 + 1 + + # Prove linearity works + comps = [1, 4, 128, 2**34] + sum_comps = 1 + 4 + 128 + 2**34 + y = 908 + z = _mult_gf2(sum_comps, y) + w = 0 + for x in comps: + w ^= _mult_gf2(x, y) + self.assertEqual(w, z) + + def test_div_gf2(self): + from Cryptodome.Util.number import size as deg + + x, y = _div_gf2(567, 7) + self.assertTrue(deg(y) < deg(7)) + + w = _mult_gf2(x, 7) ^ y + self.assertEqual(567, w) + + x, y = _div_gf2(7, 567) + self.assertEqual(x, 0) + self.assertEqual(y, 7) - def test_mult_gf2(self): - # Prove mult by zero - x = _mult_gf2(0,0) - self.assertEqual(x, 0) - - # Prove mult by unity - x = _mult_gf2(34, 1) - self.assertEqual(x, 34) - - z = 3 # (x+1) - y = _mult_gf2(z, z) - self.assertEqual(y, 5) # (x+1)^2 = x^2 + 1 - y = _mult_gf2(y, z) - self.assertEqual(y, 15) # (x+1)^3 = x^3 + x^2 + x + 1 - y = _mult_gf2(y, z) - self.assertEqual(y, 17) # (x+1)^4 = x^4 + 1 - - # Prove linearity works - comps = [1, 4, 128, 2**34] - sum_comps = 1+4+128+2**34 - y = 908 - z = _mult_gf2(sum_comps, y) - w = 0 - for x in comps: - w ^= _mult_gf2(x, y) - self.assertEqual(w, z) - - def test_div_gf2(self): - from Cryptodome.Util.number import size as deg - - x, y = _div_gf2(567, 7) - self.assertTrue(deg(y) < deg(7)) - - w = _mult_gf2(x, 7) ^ y - self.assertEqual(567, w) - - x, y = _div_gf2(7, 567) - self.assertEqual(x, 0) - self.assertEqual(y, 7) class Element_Tests(TestCase): + def test1(self): + # Test encondings + e = _Element(256) + self.assertEqual(int(e), 256) + self.assertEqual(e.encode(), bchr(0) * 14 + b("\x01\x00")) - def test1(self): - # Test encondings - e = _Element(256) - self.assertEqual(int(e), 256) - self.assertEqual(e.encode(), bchr(0)*14 + b("\x01\x00")) + e = _Element(bchr(0) * 14 + b("\x01\x10")) + self.assertEqual(int(e), 0x110) + self.assertEqual(e.encode(), bchr(0) * 14 + b("\x01\x10")) - e = _Element(bchr(0)*14 + b("\x01\x10")) - self.assertEqual(int(e), 0x110) - self.assertEqual(e.encode(), bchr(0)*14 + b("\x01\x10")) + # Only 16 byte string are a valid encoding + self.assertRaises(ValueError, _Element, bchr(0)) - # Only 16 byte string are a valid encoding - self.assertRaises(ValueError, _Element, bchr(0)) + def test2(self): + # Test addition + e = _Element(0x10) + f = _Element(0x0A) + self.assertEqual(int(e + f), 0x1A) - def test2(self): - # Test addition - e = _Element(0x10) - f = _Element(0x0A) - self.assertEqual(int(e+f), 0x1A) + def test3(self): + # Test multiplication + zero = _Element(0) + one = _Element(1) + two = _Element(2) - def test3(self): - # Test multiplication - zero = _Element(0) - one = _Element(1) - two = _Element(2) + x = _Element(6) * zero + self.assertEqual(int(x), 0) - x = _Element(6) * zero - self.assertEqual(int(x), 0) + x = _Element(6) * one + self.assertEqual(int(x), 6) - x = _Element(6) * one - self.assertEqual(int(x), 6) + x = _Element(2**127) * two + self.assertEqual(int(x), 1 + 2 + 4 + 128) - x = _Element(2**127) * two - self.assertEqual(int(x), 1 + 2 + 4 + 128) + def test4(self): + # Test inversion + one = _Element(1) - def test4(self): - # Test inversion - one = _Element(1) + x = one.inverse() + self.assertEqual(int(x), 1) - x = one.inverse() - self.assertEqual(int(x), 1) - - x = _Element(82323923) - y = x.inverse() - self.assertEqual(int(x * y), 1) + x = _Element(82323923) + y = x.inverse() + self.assertEqual(int(x * y), 1) class Shamir_Tests(TestCase): - - def test1(self): - # Test splitting - shares = Shamir.split(2, 3, bchr(90)*16) - self.assertEqual(len(shares), 3) - for index in range(3): - self.assertEqual(shares[index][0], index+1) - self.assertEqual(len(shares[index][1]), 16) - - def test2(self): - # Test recombine - from itertools import permutations - - # Generated by ssss (index, secret, shares) - # in hex mode, without "diffusion" mode - test_vectors = ( - (2, "d9fe73909bae28b3757854c0af7ad405", - "1-594ae8964294174d95c33756d2504170", - "2-d897459d29da574eb40e93ec552ffe6e", - "3-5823de9bf0e068b054b5f07a28056b1b", - "4-db2c1f8bff46d748f795da995bd080cb"), - (2, "bf4f902d9a7efafd1f3ffd9291fd5de9", - "1-557bd3b0748064b533469722d1cc7935", - "2-6b2717164783c66d47cd28f2119f14d0", - "3-8113548ba97d58256bb4424251ae300c", - "4-179e9e5a218483ddaeda57539139cf04"), - (3, "ec96aa5c14c9faa699354cf1da74e904", - "1-64579fbf1908d66f7239bf6e2b4e41e1", - "2-6cd9428df8017b52322561e8c672ae3e", - "3-e418776ef5c0579bd9299277374806dd", - "4-ab3f77a0107398d23b323e581bb43f5d", - "5-23fe42431db2b41bd03ecdc7ea8e97ac"), - (3, "44cf249b68b80fcdc27b47be60c2c145", - "1-d6515a3905cd755119b86e311c801e31", - "2-16693d9ac9f10c254036ced5f8917fa3", - "3-84f74338a48476b99bf5e75a84d3a0d1", - "4-3fe8878dc4a5d35811cf3cbcd33dbe52", - "5-ad76f92fa9d0a9c4ca0c1533af7f6132"), - (5, "5398717c982db935d968eebe53a47f5a", - "1-be7be2dd4c068e7ef576aaa1b1c11b01", - "2-f821f5848441cb98b3eb467e2733ee21", - "3-25ee52f53e203f6e29a0297b5ab486b5", - "4-fc9fb58ef74dab947fbf9acd9d5d83cd", - "5-b1949cce46d81552e65f248d3f74cc5c", - "6-d64797f59977c4d4a7956ad916da7699", - "7-ab608a6546a8b9af8820ff832b1135c7"), - (5, "4a78db90fbf35da5545d2fb728e87596", - "1-08daf9a25d8aa184cfbf02b30a0ed6a0", - "2-dda28261e36f0b14168c2cf153fb734e", - "3-e9fdec5505d674a57f9836c417c1ecaa", - "4-4dce5636ae06dee42d2c82e65f06c735", - "5-3963dc118afc2ba798fa1d452b28ef00", - "6-6dfe6ff5b09e94d2f84c382b12f42424", - "7-6faea9d4d4a4e201bf6c90b9000630c3"), - (10, "eccbf6d66d680b49b073c4f1ddf804aa", - "01-7d8ac32fe4ae209ead1f3220fda34466", - "02-f9144e76988aad647d2e61353a6e96d5", - "03-b14c3b80179203363922d60760271c98", - "04-770bb2a8c28f6cee89e00f4d5cc7f861", - "05-6e3d7073ea368334ef67467871c66799", - "06-248792bc74a98ce024477c13c8fb5f8d", - "07-fcea4640d2db820c0604851e293d2487", - "08-2776c36fb714bb1f8525a0be36fc7dba", - "09-6ee7ac8be773e473a4bf75ee5f065762", - "10-33657fc073354cf91d4a68c735aacfc8", - "11-7645c65094a5868bf225c516fdee2d0c", - "12-840485aacb8226631ecd9c70e3018086"), - (10, "377e63bdbb5f7d4dc58a483d035212bb", - "01-32c53260103be431c843b1a633afe3bd", - "02-0107eb16cb8695084d452d2cc50bc7d6", - "03-df1e5c66cd755287fb0446faccd72a06", - "04-361bbcd5d40797f49dfa1898652da197", - "05-160d3ad1512f7dec7fd9344aed318591", - "06-659af6d95df4f25beca4fb9bfee3b7e8", - "07-37f3b208977bad50b3724566b72bfa9d", - "08-6c1de2dfc69c2986142c26a8248eb316", - "09-5e19220837a396bd4bc8cd685ff314c3", - "10-86e7b864fb0f3d628e46d50c1ba92f1c", - "11-065d0082c80b1aea18f4abe0c49df72e", - "12-84a09430c1d20ea9f388f3123c3733a3"), - ) - - def get_share(p): - pos = p.find('-') - return int(p[:pos]), unhexlify(p[pos + 1:]) - - for tv in test_vectors: - k = tv[0] - secret = unhexlify(tv[1]) - max_perms = 10 - for perm, shares_idx in enumerate(permutations(range(2, len(tv)), k)): - if perm > max_perms: - break - shares = [ get_share(tv[x]) for x in shares_idx ] - result = Shamir.combine(shares, True) - self.assertEqual(secret, result) - - def test3(self): - # Loopback split/recombine - - rng = SHAKE128.new(b"test3") - - for _ in range(100): - - secret = rng.read(16) - - shares = Shamir.split(2, 3, secret) - - secret2 = Shamir.combine(shares[:2]) - self.assertEqual(secret, secret2) - - secret3 = Shamir.combine([ shares[0], shares[2] ]) - self.assertEqual(secret, secret3) - - def test4(self): - # Loopback split/recombine (SSSS) - - rng = SHAKE128.new(b"test4") - - for _ in range(10): - secret = rng.read(16) - - shares = Shamir.split(2, 3, secret, ssss=True) - - secret2 = Shamir.combine(shares[:2], ssss=True) - self.assertEqual(secret, secret2) - - for _ in range(10): - secret = rng.read(16) - - shares = Shamir.split(3, 7, secret, ssss=True) - - secret2 = Shamir.combine([shares[3], shares[4], shares[6]], ssss=True) - self.assertEqual(secret, secret2) - - - def test5(self): - # Detect duplicate shares - secret = unhexlify(b("000102030405060708090a0b0c0d0e0f")) - - shares = Shamir.split(2, 3, secret) - self.assertRaises(ValueError, Shamir.combine, (shares[0], shares[0])) + def test1(self): + # Test splitting + shares = Shamir.split(2, 3, bchr(90) * 16) + self.assertEqual(len(shares), 3) + for index in range(3): + self.assertEqual(shares[index][0], index + 1) + self.assertEqual(len(shares[index][1]), 16) + + def test2(self): + # Test recombine + from itertools import permutations + + # Generated by ssss (index, secret, shares) + # in hex mode, without "diffusion" mode + test_vectors = ( + ( + 2, + "d9fe73909bae28b3757854c0af7ad405", + "1-594ae8964294174d95c33756d2504170", + "2-d897459d29da574eb40e93ec552ffe6e", + "3-5823de9bf0e068b054b5f07a28056b1b", + "4-db2c1f8bff46d748f795da995bd080cb", + ), + ( + 2, + "bf4f902d9a7efafd1f3ffd9291fd5de9", + "1-557bd3b0748064b533469722d1cc7935", + "2-6b2717164783c66d47cd28f2119f14d0", + "3-8113548ba97d58256bb4424251ae300c", + "4-179e9e5a218483ddaeda57539139cf04", + ), + ( + 3, + "ec96aa5c14c9faa699354cf1da74e904", + "1-64579fbf1908d66f7239bf6e2b4e41e1", + "2-6cd9428df8017b52322561e8c672ae3e", + "3-e418776ef5c0579bd9299277374806dd", + "4-ab3f77a0107398d23b323e581bb43f5d", + "5-23fe42431db2b41bd03ecdc7ea8e97ac", + ), + ( + 3, + "44cf249b68b80fcdc27b47be60c2c145", + "1-d6515a3905cd755119b86e311c801e31", + "2-16693d9ac9f10c254036ced5f8917fa3", + "3-84f74338a48476b99bf5e75a84d3a0d1", + "4-3fe8878dc4a5d35811cf3cbcd33dbe52", + "5-ad76f92fa9d0a9c4ca0c1533af7f6132", + ), + ( + 5, + "5398717c982db935d968eebe53a47f5a", + "1-be7be2dd4c068e7ef576aaa1b1c11b01", + "2-f821f5848441cb98b3eb467e2733ee21", + "3-25ee52f53e203f6e29a0297b5ab486b5", + "4-fc9fb58ef74dab947fbf9acd9d5d83cd", + "5-b1949cce46d81552e65f248d3f74cc5c", + "6-d64797f59977c4d4a7956ad916da7699", + "7-ab608a6546a8b9af8820ff832b1135c7", + ), + ( + 5, + "4a78db90fbf35da5545d2fb728e87596", + "1-08daf9a25d8aa184cfbf02b30a0ed6a0", + "2-dda28261e36f0b14168c2cf153fb734e", + "3-e9fdec5505d674a57f9836c417c1ecaa", + "4-4dce5636ae06dee42d2c82e65f06c735", + "5-3963dc118afc2ba798fa1d452b28ef00", + "6-6dfe6ff5b09e94d2f84c382b12f42424", + "7-6faea9d4d4a4e201bf6c90b9000630c3", + ), + ( + 10, + "eccbf6d66d680b49b073c4f1ddf804aa", + "01-7d8ac32fe4ae209ead1f3220fda34466", + "02-f9144e76988aad647d2e61353a6e96d5", + "03-b14c3b80179203363922d60760271c98", + "04-770bb2a8c28f6cee89e00f4d5cc7f861", + "05-6e3d7073ea368334ef67467871c66799", + "06-248792bc74a98ce024477c13c8fb5f8d", + "07-fcea4640d2db820c0604851e293d2487", + "08-2776c36fb714bb1f8525a0be36fc7dba", + "09-6ee7ac8be773e473a4bf75ee5f065762", + "10-33657fc073354cf91d4a68c735aacfc8", + "11-7645c65094a5868bf225c516fdee2d0c", + "12-840485aacb8226631ecd9c70e3018086", + ), + ( + 10, + "377e63bdbb5f7d4dc58a483d035212bb", + "01-32c53260103be431c843b1a633afe3bd", + "02-0107eb16cb8695084d452d2cc50bc7d6", + "03-df1e5c66cd755287fb0446faccd72a06", + "04-361bbcd5d40797f49dfa1898652da197", + "05-160d3ad1512f7dec7fd9344aed318591", + "06-659af6d95df4f25beca4fb9bfee3b7e8", + "07-37f3b208977bad50b3724566b72bfa9d", + "08-6c1de2dfc69c2986142c26a8248eb316", + "09-5e19220837a396bd4bc8cd685ff314c3", + "10-86e7b864fb0f3d628e46d50c1ba92f1c", + "11-065d0082c80b1aea18f4abe0c49df72e", + "12-84a09430c1d20ea9f388f3123c3733a3", + ), + ) + + def get_share(p): + pos = p.find("-") + return int(p[:pos]), unhexlify(p[pos + 1 :]) + + for tv in test_vectors: + k = tv[0] + secret = unhexlify(tv[1]) + max_perms = 10 + for perm, shares_idx in enumerate(permutations(range(2, len(tv)), k)): + if perm > max_perms: + break + shares = [get_share(tv[x]) for x in shares_idx] + result = Shamir.combine(shares, True) + self.assertEqual(secret, result) + + def test3(self): + # Loopback split/recombine + + rng = SHAKE128.new(b"test3") + + for _ in range(100): + secret = rng.read(16) + + shares = Shamir.split(2, 3, secret) + + secret2 = Shamir.combine(shares[:2]) + self.assertEqual(secret, secret2) + + secret3 = Shamir.combine([shares[0], shares[2]]) + self.assertEqual(secret, secret3) + + def test4(self): + # Loopback split/recombine (SSSS) + + rng = SHAKE128.new(b"test4") + + for _ in range(10): + secret = rng.read(16) + + shares = Shamir.split(2, 3, secret, ssss=True) + + secret2 = Shamir.combine(shares[:2], ssss=True) + self.assertEqual(secret, secret2) + + for _ in range(10): + secret = rng.read(16) + + shares = Shamir.split(3, 7, secret, ssss=True) + + secret2 = Shamir.combine([shares[3], shares[4], shares[6]], ssss=True) + self.assertEqual(secret, secret2) + + def test5(self): + # Detect duplicate shares + secret = unhexlify(b("000102030405060708090a0b0c0d0e0f")) + + shares = Shamir.split(2, 3, secret) + self.assertRaises(ValueError, Shamir.combine, (shares[0], shares[0])) def get_tests(config={}): - tests = [] - tests += list_test_cases(GF2_Tests) - tests += list_test_cases(Element_Tests) - tests += list_test_cases(Shamir_Tests) - return tests + tests = [] + tests += list_test_cases(GF2_Tests) + tests += list_test_cases(Element_Tests) + tests += list_test_cases(Shamir_Tests) + return tests -if __name__ == '__main__': - suite = lambda: TestSuite(get_tests()) - main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: TestSuite(get_tests()) + main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_ecdh.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_ecdh.py index 8bea7876..4f11c1ac 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_ecdh.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_ecdh.py @@ -11,760 +11,845 @@ from Cryptodome.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof from Cryptodome.Protocol import DH -from Cryptodome.Protocol.DH import (key_agreement, - import_x25519_public_key, - import_x25519_private_key, - import_x448_public_key, - import_x448_private_key) +from Cryptodome.Protocol.DH import ( + key_agreement, + import_x25519_public_key, + import_x25519_private_key, + import_x448_public_key, + import_x448_private_key, +) class FIPS_ECDH_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_verify = load_test_vectors(("Protocol", ), - "KAS_ECC_CDH_PrimitiveTest.txt", - "ECC CDH Primitive (SP800-56A Section 5.7.1.2)", - { - 'qcavsx': lambda x: int(x, 16), - 'qcavsy': lambda x: int(x, 16), - 'diut': lambda x: int(x, 16), - 'qiutx': lambda x: int(x, 16), - 'qiuty': lambda x: int(x, 16), - }) or [] + pass + + +test_vectors_verify = ( + load_test_vectors( + ("Protocol",), + "KAS_ECC_CDH_PrimitiveTest.txt", + "ECC CDH Primitive (SP800-56A Section 5.7.1.2)", + { + "qcavsx": lambda x: int(x, 16), + "qcavsy": lambda x: int(x, 16), + "diut": lambda x: int(x, 16), + "qiutx": lambda x: int(x, 16), + "qiuty": lambda x: int(x, 16), + }, + ) + or [] +) for idx, tv in enumerate(test_vectors_verify): - - # Stand-alone header with curve name - if isinstance(tv, str): - res = re.match(r"\[([A-Za-z0-9-]+)\]", tv) - assert res - curve_name = res.group(1) - continue - - public_key = ECC.construct(curve=curve_name, - point_x=tv.qcavsx, - point_y=tv.qcavsy) - - private_key = ECC.construct(curve=curve_name, - d=tv.diut) - - exp_response = tv.ziut - - def ecdh_test(self, - public_key=public_key, - private_key=private_key, - exp_response=exp_response): - z = key_agreement( - static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - self.assertEqual(z, exp_response) - - def ecdh_test_rev(self, - public_key=public_key, - private_key=private_key, - exp_response=exp_response): - z = key_agreement( - static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - self.assertEqual(z, exp_response) - - setattr(FIPS_ECDH_Tests_KAT, "test_verify_positive_%d" % idx, ecdh_test) - if idx == 1: - setattr(FIPS_ECDH_Tests_KAT, "test_verify_positive_rev_%d" % idx, ecdh_test_rev) + # Stand-alone header with curve name + if isinstance(tv, str): + res = re.match(r"\[([A-Za-z0-9-]+)\]", tv) + assert res + curve_name = res.group(1) + continue + + public_key = ECC.construct( + curve=curve_name, + point_x=tv.qcavsx, + point_y=tv.qcavsy, + ) + + private_key = ECC.construct( + curve=curve_name, + d=tv.diut, + ) + + exp_response = tv.ziut + + def ecdh_test( + self, + public_key=public_key, + private_key=private_key, + exp_response=exp_response, + ): + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + self.assertEqual(z, exp_response) + + def ecdh_test_rev( + self, + public_key=public_key, + private_key=private_key, + exp_response=exp_response, + ): + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + self.assertEqual(z, exp_response) + + setattr(FIPS_ECDH_Tests_KAT, "test_verify_positive_%d" % idx, ecdh_test) + if idx == 1: + setattr(FIPS_ECDH_Tests_KAT, "test_verify_positive_rev_%d" % idx, ecdh_test_rev) class TestVectorsECDHWycheproof(unittest.TestCase): - - desc = "Wycheproof ECDH tests" - - def add_tests(self, filename): - - def curve(g): - return g['curve'] - - def private(u): - return int(u['private'], 16) - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'curve': curve}, - unit_tag={'private': private}, - ) - self.tv += result - - def setUp(self): - self.tv = [] - self.desc = None - - self.add_tests("ecdh_secp224r1_ecpoint_test.json") - self.add_tests("ecdh_secp256r1_ecpoint_test.json") - self.add_tests("ecdh_secp384r1_ecpoint_test.json") - self.add_tests("ecdh_secp521r1_ecpoint_test.json") - - self.add_tests("ecdh_secp224r1_test.json") - self.add_tests("ecdh_secp256r1_test.json") - self.add_tests("ecdh_secp384r1_test.json") - self.add_tests("ecdh_secp521r1_test.json") - - def shortDescription(self): - return self.desc - - def test_verify(self, tv): - - if len(tv.public) == 0: - return - - try: - if bord(tv.public[0]) == 4: # SEC1 - public_key = ECC.import_key(tv.public, curve_name=tv.curve) - else: - public_key = ECC.import_key(tv.public) - except ValueError: - assert tv.warning or not tv.valid - return - - private_key = ECC.construct(curve=tv.curve, d=tv.private) - - try: - z = key_agreement(static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - except ValueError: - assert not tv.valid - except TypeError as e: - assert not tv.valid - assert "incompatible curve" in str(e) - else: - self.assertEqual(z, tv.shared) - assert tv.valid - - def runTest(self): - for tv in self.tv: - self.desc = "Wycheproof ECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - self.test_verify(tv) + desc = "Wycheproof ECDH tests" + + def add_tests(self, filename): + def curve(g): + return g["curve"] + + def private(u): + return int(u["private"], 16) + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"curve": curve}, + unit_tag={"private": private}, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.desc = None + + self.add_tests("ecdh_secp224r1_ecpoint_test.json") + self.add_tests("ecdh_secp256r1_ecpoint_test.json") + self.add_tests("ecdh_secp384r1_ecpoint_test.json") + self.add_tests("ecdh_secp521r1_ecpoint_test.json") + + self.add_tests("ecdh_secp224r1_test.json") + self.add_tests("ecdh_secp256r1_test.json") + self.add_tests("ecdh_secp384r1_test.json") + self.add_tests("ecdh_secp521r1_test.json") + + def shortDescription(self): + return self.desc + + def test_verify(self, tv): + if len(tv.public) == 0: + return + + try: + if bord(tv.public[0]) == 4: # SEC1 + public_key = ECC.import_key(tv.public, curve_name=tv.curve) + else: + public_key = ECC.import_key(tv.public) + except ValueError: + assert tv.warning or not tv.valid + return + + private_key = ECC.construct(curve=tv.curve, d=tv.private) + + try: + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + except ValueError: + assert not tv.valid + except TypeError as e: + assert not tv.valid + assert "incompatible curve" in str(e) + else: + self.assertEqual(z, tv.shared) + assert tv.valid + + def runTest(self): + for tv in self.tv: + self.desc = "Wycheproof ECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + self.test_verify(tv) class ECDH_Tests(unittest.TestCase): - - static_priv = ECC.import_key('-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9VHFVKh2a1aVFifH\n+BiyNaRa2kttEg3165Ye/dJxJ7KhRANCAARImIEXro5ZOcyWU2mq/+d79FEZXtTA\nbKkz1aICQXihQdCMzRNbeNtC9LFLzhu1slRKJ2xsDAlw9r6w6vwtkRzr\n-----END PRIVATE KEY-----') - static_pub = ECC.import_key('-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgHhmv8zmZ+Nw8fsZd\ns8tlZflyfw2NE1CRS9DWr3Y3O46hRANCAAS3hZVUCbk+uk3w4S/YOraEVGG+WYpk\nNO/vrwzufUUks2GV2OnBQESe0EBk4Jq8gn4ij8Lvs3rZX2yT+XfeATYd\n-----END PRIVATE KEY-----').public_key() - - eph_priv = ECC.import_key('-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGPdJmFFFKzLPspIr\nE1T2cEjeIf4ajS9CpneP0e2b3AyhRANCAAQBexAA5BYDcXHs2KOksTYUsst4HhPt\nkp0zkgI2virc3OGJFNGPaCCPfFCQJHwLRaEpiq3SoQlgoBwSc8ZPsl3y\n-----END PRIVATE KEY-----') - - eph_pub = ECC.import_key('-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghaVZXElSEGEojFKF\nOU0JCpxWUWHvWQUR81gwWrOp76ShRANCAATi1Ib2K+YR3AckD8wxypWef7pw5PRw\ntBaB3RDPyE7IjHZC6yu1DbcXoCdtaw+F5DM+4zpl59n5ZaIy/Yl1BdIy\n-----END PRIVATE KEY-----') - - def test_1(self): - # C(0, 2s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - static_priv=self.static_priv) - self.assertEqual(hexlify(z), - b"3960a1101d1193cbaffef4cc7202ebff783c22c6d2e0d5d530ffc66dc197ea9c") - - def test_2(self): - # C(2e, 2s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - static_priv=self.static_priv, - eph_pub=self.eph_pub, - eph_priv=self.eph_priv) - self.assertEqual(hexlify(z), - b"7447b733d40c8fab2c633b3dc61e4a8c742f3a6af7e16fb0cc486f5bdb5d6ba2") - - def test_3(self): - # C(1e, 2s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - static_priv=self.static_priv, - eph_priv=self.eph_priv) - self.assertEqual(hexlify(z), - b"9e977ae45f33bf67f285d064d83e6632bcafe3a7d33fe571233bab4794ace759") - - def test_4(self): - # C(1e, 2s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - static_priv=self.static_priv, - eph_pub=self.eph_pub) - self.assertEqual(hexlify(z), - b"c9532df6aa7e9dbe5fe85da31ee25ff19c179c88691ec4b8328cc2036dcdadf2") - - def test_5(self): - # C(2e, 1s) is not supported - kdf = lambda x: SHA256.new(x).digest() - self.assertRaises(ValueError, - key_agreement, - kdf=kdf, - static_priv=self.static_priv, - eph_pub=self.eph_pub, - eph_priv=self.eph_priv) - - def test_6(self): - # C(2e, 1s) is not supported - kdf = lambda x: SHA256.new(x).digest() - self.assertRaises(ValueError, - key_agreement, - kdf=kdf, - static_pub=self.static_pub, - eph_pub=self.eph_pub, - eph_priv=self.eph_priv) - - def test_7(self): - # C(2e, 0) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - eph_pub=self.eph_pub, - eph_priv=self.eph_priv) - self.assertEqual(hexlify(z), - b"feb257ebe063078b1391aac07913283d7b642ad7df61b46dfc9cd6f420bb896a") - - def test_8(self): - # C(1e, 1s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_priv=self.static_priv, - eph_pub=self.eph_pub) - self.assertEqual(hexlify(z), - b"ee4dc995117476ed57fd17ff0ed44e9f0466d46b929443bc0db9380317583b04") - - def test_9(self): - # C(1e, 1s) - kdf = lambda x: SHA256.new(x).digest() - z = key_agreement( - kdf=kdf, - static_pub=self.static_pub, - eph_priv=self.eph_priv) - self.assertEqual(hexlify(z), - b"2351cc2014f7c40468fa072b5d30f706eeaeef7507311cd8e59bab3b43f03c51") - - def test_10(self): - # No private (local) keys - kdf = lambda x: SHA256.new(x).digest() - self.assertRaises(ValueError, - key_agreement, - kdf=kdf, - static_pub=self.static_pub, - eph_pub=self.eph_pub) - - def test_11(self): - # No public (peer) keys - kdf = lambda x: SHA256.new(x).digest() - self.assertRaises(ValueError, - key_agreement, - kdf=kdf, - static_priv=self.static_priv, - eph_priv=self.eph_priv) - - def test_12(self): - # failure if kdf is missing - self.assertRaises(ValueError, - key_agreement, - static_pub=self.static_pub, - static_priv=self.static_priv) + static_priv = ECC.import_key( + "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9VHFVKh2a1aVFifH\n+BiyNaRa2kttEg3165Ye/dJxJ7KhRANCAARImIEXro5ZOcyWU2mq/+d79FEZXtTA\nbKkz1aICQXihQdCMzRNbeNtC9LFLzhu1slRKJ2xsDAlw9r6w6vwtkRzr\n-----END PRIVATE KEY-----" + ) + static_pub = ECC.import_key( + "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgHhmv8zmZ+Nw8fsZd\ns8tlZflyfw2NE1CRS9DWr3Y3O46hRANCAAS3hZVUCbk+uk3w4S/YOraEVGG+WYpk\nNO/vrwzufUUks2GV2OnBQESe0EBk4Jq8gn4ij8Lvs3rZX2yT+XfeATYd\n-----END PRIVATE KEY-----" + ).public_key() + + eph_priv = ECC.import_key( + "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGPdJmFFFKzLPspIr\nE1T2cEjeIf4ajS9CpneP0e2b3AyhRANCAAQBexAA5BYDcXHs2KOksTYUsst4HhPt\nkp0zkgI2virc3OGJFNGPaCCPfFCQJHwLRaEpiq3SoQlgoBwSc8ZPsl3y\n-----END PRIVATE KEY-----" + ) + + eph_pub = ECC.import_key( + "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghaVZXElSEGEojFKF\nOU0JCpxWUWHvWQUR81gwWrOp76ShRANCAATi1Ib2K+YR3AckD8wxypWef7pw5PRw\ntBaB3RDPyE7IjHZC6yu1DbcXoCdtaw+F5DM+4zpl59n5ZaIy/Yl1BdIy\n-----END PRIVATE KEY-----" + ) + + def test_1(self): + # C(0, 2s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + static_priv=self.static_priv, + ) + self.assertEqual( + hexlify(z), + b"3960a1101d1193cbaffef4cc7202ebff783c22c6d2e0d5d530ffc66dc197ea9c", + ) + + def test_2(self): + # C(2e, 2s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + static_priv=self.static_priv, + eph_pub=self.eph_pub, + eph_priv=self.eph_priv, + ) + self.assertEqual( + hexlify(z), + b"7447b733d40c8fab2c633b3dc61e4a8c742f3a6af7e16fb0cc486f5bdb5d6ba2", + ) + + def test_3(self): + # C(1e, 2s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + static_priv=self.static_priv, + eph_priv=self.eph_priv, + ) + self.assertEqual( + hexlify(z), + b"9e977ae45f33bf67f285d064d83e6632bcafe3a7d33fe571233bab4794ace759", + ) + + def test_4(self): + # C(1e, 2s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + static_priv=self.static_priv, + eph_pub=self.eph_pub, + ) + self.assertEqual( + hexlify(z), + b"c9532df6aa7e9dbe5fe85da31ee25ff19c179c88691ec4b8328cc2036dcdadf2", + ) + + def test_5(self): + # C(2e, 1s) is not supported + kdf = lambda x: SHA256.new(x).digest() + self.assertRaises( + ValueError, + key_agreement, + kdf=kdf, + static_priv=self.static_priv, + eph_pub=self.eph_pub, + eph_priv=self.eph_priv, + ) + + def test_6(self): + # C(2e, 1s) is not supported + kdf = lambda x: SHA256.new(x).digest() + self.assertRaises( + ValueError, + key_agreement, + kdf=kdf, + static_pub=self.static_pub, + eph_pub=self.eph_pub, + eph_priv=self.eph_priv, + ) + + def test_7(self): + # C(2e, 0) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + eph_pub=self.eph_pub, + eph_priv=self.eph_priv, + ) + self.assertEqual( + hexlify(z), + b"feb257ebe063078b1391aac07913283d7b642ad7df61b46dfc9cd6f420bb896a", + ) + + def test_8(self): + # C(1e, 1s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_priv=self.static_priv, + eph_pub=self.eph_pub, + ) + self.assertEqual( + hexlify(z), + b"ee4dc995117476ed57fd17ff0ed44e9f0466d46b929443bc0db9380317583b04", + ) + + def test_9(self): + # C(1e, 1s) + kdf = lambda x: SHA256.new(x).digest() + z = key_agreement( + kdf=kdf, + static_pub=self.static_pub, + eph_priv=self.eph_priv, + ) + self.assertEqual( + hexlify(z), + b"2351cc2014f7c40468fa072b5d30f706eeaeef7507311cd8e59bab3b43f03c51", + ) + + def test_10(self): + # No private (local) keys + kdf = lambda x: SHA256.new(x).digest() + self.assertRaises( + ValueError, + key_agreement, + kdf=kdf, + static_pub=self.static_pub, + eph_pub=self.eph_pub, + ) + + def test_11(self): + # No public (peer) keys + kdf = lambda x: SHA256.new(x).digest() + self.assertRaises( + ValueError, + key_agreement, + kdf=kdf, + static_priv=self.static_priv, + eph_priv=self.eph_priv, + ) + + def test_12(self): + # failure if kdf is missing + self.assertRaises( + ValueError, + key_agreement, + static_pub=self.static_pub, + static_priv=self.static_priv, + ) class X25519_Tests(unittest.TestCase): - - def test_rfc7748_1(self): - tvs = ( - ("a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", - "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", - "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"), - ("4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", - "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", - "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957"), - ) - - for tv1, tv2, tv3 in tvs: - priv_key = DH.import_x25519_private_key(unhexlify(tv1)) - pub_key = DH.import_x25519_public_key(unhexlify(tv2)) - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - self.assertEqual(result, unhexlify(tv3)) - - def test_rfc7748_2(self): - k = unhexlify("0900000000000000000000000000000000000000000000000000000000000000") - - priv_key = DH.import_x25519_private_key(k) - pub_key = DH.import_x25519_public_key(k) - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - self.assertEqual( - result, - unhexlify("422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079") - ) - - for _ in range(999): - priv_key = DH.import_x25519_private_key(result) - pub_key = DH.import_x25519_public_key(k) - k = result - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - - self.assertEqual( - result, - unhexlify("684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51") - ) - - def test_rfc7748_3(self): - tv1 = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a" - tv2 = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a" - tv3 = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb" - tv4 = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f" - tv5 = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" - - alice_priv_key = DH.import_x25519_private_key(unhexlify(tv1)) - alice_pub_key = DH.import_x25519_public_key(unhexlify(tv2)) - bob_priv_key = DH.import_x25519_private_key(unhexlify(tv3)) - bob_pub_key = DH.import_x25519_public_key(unhexlify(tv4)) - secret = unhexlify(tv5) - - result1 = key_agreement(static_pub=alice_pub_key, - static_priv=bob_priv_key, - kdf=lambda x: x) - result2 = key_agreement(static_pub=bob_pub_key, - static_priv=alice_priv_key, - kdf=lambda x: x) - self.assertEqual(result1, secret) - self.assertEqual(result2, secret) - - def test_weak(self): - - weak_keys = ( - "0000000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800", - "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157", - "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - # The implementation will accept these value, but only because - # it will set the MSB to zero (as required by RFC7748, Section 5), - # therefore leading to another public key (and to a point which is - # not of low order anymore). - # "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880", - # "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7", - # "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - # "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - # "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - ) - - for x in weak_keys: - self.assertRaises(ValueError, - DH.import_x25519_public_key, - unhexlify(x)) + def test_rfc7748_1(self): + tvs = ( + ( + "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", + "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", + "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552", + ), + ( + "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", + "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", + "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957", + ), + ) + + for tv1, tv2, tv3 in tvs: + priv_key = DH.import_x25519_private_key(unhexlify(tv1)) + pub_key = DH.import_x25519_public_key(unhexlify(tv2)) + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + self.assertEqual(result, unhexlify(tv3)) + + def test_rfc7748_2(self): + k = unhexlify("0900000000000000000000000000000000000000000000000000000000000000") + + priv_key = DH.import_x25519_private_key(k) + pub_key = DH.import_x25519_public_key(k) + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + self.assertEqual( + result, + unhexlify("422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079"), + ) + + for _ in range(999): + priv_key = DH.import_x25519_private_key(result) + pub_key = DH.import_x25519_public_key(k) + k = result + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + + self.assertEqual( + result, + unhexlify("684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51"), + ) + + def test_rfc7748_3(self): + tv1 = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a" + tv2 = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a" + tv3 = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb" + tv4 = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f" + tv5 = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" + + alice_priv_key = DH.import_x25519_private_key(unhexlify(tv1)) + alice_pub_key = DH.import_x25519_public_key(unhexlify(tv2)) + bob_priv_key = DH.import_x25519_private_key(unhexlify(tv3)) + bob_pub_key = DH.import_x25519_public_key(unhexlify(tv4)) + secret = unhexlify(tv5) + + result1 = key_agreement( + static_pub=alice_pub_key, + static_priv=bob_priv_key, + kdf=lambda x: x, + ) + result2 = key_agreement( + static_pub=bob_pub_key, + static_priv=alice_priv_key, + kdf=lambda x: x, + ) + self.assertEqual(result1, secret) + self.assertEqual(result2, secret) + + def test_weak(self): + weak_keys = ( + "0000000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800", + "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + # The implementation will accept these value, but only because + # it will set the MSB to zero (as required by RFC7748, Section 5), + # therefore leading to another public key (and to a point which is + # not of low order anymore). + # "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880", + # "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7", + # "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + # "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + # "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ) + + for x in weak_keys: + self.assertRaises( + ValueError, + DH.import_x25519_public_key, + unhexlify(x), + ) class X448_Tests(unittest.TestCase): - - def test_rfc7748_1(self): - tvs = ( - ("3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", - "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", - "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f"), - ("203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", - "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", - "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d"), - ) - - for tv1, tv2, tv3 in tvs: - priv_key = DH.import_x448_private_key(unhexlify(tv1)) - pub_key = DH.import_x448_public_key(unhexlify(tv2)) - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - self.assertEqual(result, unhexlify(tv3)) - - def test_rfc7748_2(self): - k = unhexlify("0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") - - priv_key = DH.import_x448_private_key(k) - pub_key = DH.import_x448_public_key(k) - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - self.assertEqual( - result, - unhexlify("3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113") - ) - - for _ in range(999): - priv_key = DH.import_x448_private_key(result) - pub_key = DH.import_x448_public_key(k) - k = result - result = key_agreement(static_pub=pub_key, - static_priv=priv_key, - kdf=lambda x: x) - - self.assertEqual( - result, - unhexlify("aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38") - ) - - def test_rfc7748_3(self): - tv1 = "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b" - tv2 = "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0" - tv3 = "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d" - tv4 = "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609" - tv5 = "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d" - - alice_priv_key = DH.import_x448_private_key(unhexlify(tv1)) - alice_pub_key = DH.import_x448_public_key(unhexlify(tv2)) - bob_priv_key = DH.import_x448_private_key(unhexlify(tv3)) - bob_pub_key = DH.import_x448_public_key(unhexlify(tv4)) - secret = unhexlify(tv5) - - result1 = key_agreement(static_pub=alice_pub_key, - static_priv=bob_priv_key, - kdf=lambda x: x) - result2 = key_agreement(static_pub=bob_pub_key, - static_priv=alice_priv_key, - kdf=lambda x: x) - self.assertEqual(result1, secret) - self.assertEqual(result2, secret) - - def test_weak(self): - - weak_keys = ( - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - ) - - for x in weak_keys: - self.assertRaises(ValueError, - DH.import_x448_public_key, - unhexlify(x)) + def test_rfc7748_1(self): + tvs = ( + ( + "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", + "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", + "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f", + ), + ( + "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", + "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", + "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d", + ), + ) + + for tv1, tv2, tv3 in tvs: + priv_key = DH.import_x448_private_key(unhexlify(tv1)) + pub_key = DH.import_x448_public_key(unhexlify(tv2)) + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + self.assertEqual(result, unhexlify(tv3)) + + def test_rfc7748_2(self): + k = unhexlify( + "0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ) + + priv_key = DH.import_x448_private_key(k) + pub_key = DH.import_x448_public_key(k) + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + self.assertEqual( + result, + unhexlify( + "3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113" + ), + ) + + for _ in range(999): + priv_key = DH.import_x448_private_key(result) + pub_key = DH.import_x448_public_key(k) + k = result + result = key_agreement( + static_pub=pub_key, + static_priv=priv_key, + kdf=lambda x: x, + ) + + self.assertEqual( + result, + unhexlify( + "aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38" + ), + ) + + def test_rfc7748_3(self): + tv1 = "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b" + tv2 = "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0" + tv3 = "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d" + tv4 = "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609" + tv5 = "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d" + + alice_priv_key = DH.import_x448_private_key(unhexlify(tv1)) + alice_pub_key = DH.import_x448_public_key(unhexlify(tv2)) + bob_priv_key = DH.import_x448_private_key(unhexlify(tv3)) + bob_pub_key = DH.import_x448_public_key(unhexlify(tv4)) + secret = unhexlify(tv5) + + result1 = key_agreement( + static_pub=alice_pub_key, + static_priv=bob_priv_key, + kdf=lambda x: x, + ) + result2 = key_agreement( + static_pub=bob_pub_key, + static_priv=alice_priv_key, + kdf=lambda x: x, + ) + self.assertEqual(result1, secret) + self.assertEqual(result2, secret) + + def test_weak(self): + weak_keys = ( + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ) + + for x in weak_keys: + self.assertRaises( + ValueError, + DH.import_x448_public_key, + unhexlify(x), + ) class TestVectorsX25519Wycheproof(unittest.TestCase): - - desc = "Wycheproof X25519 tests" - - def add_tests_hex(self, filename): - - def encoding(g): - return g['type'] - - def private(u): - return unhexlify(u['private']) - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'encoding': encoding}, - unit_tag={'private': private} - ) - self.tv += result - - def add_tests_ascii(self, filename): - - def encoding(g): - return g['type'] - - def public(u): - return u['public'] - - def private(u): - return u['private'] - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'encoding': encoding}, - unit_tag={'public': public, - 'private': private} - ) - self.tv += result - - def setUp(self): - self.tv = [] - self.desc = None - - self.add_tests_hex("x25519_test.json") - self.add_tests_hex("x25519_asn_test.json") - self.add_tests_ascii("x25519_pem_test.json") - self.add_tests_ascii("x25519_jwk_test.json") - - def shortDescription(self): - return self.desc - - def test_verify(self, tv): - - if tv.encoding == "XdhComp": - try: - public_key = import_x25519_public_key(tv.public) - except ValueError as e: - assert tv.valid - assert tv.warning - assert "LowOrderPublic" in tv.flags - assert "Invalid Curve25519" in str(e) - return - private_key = import_x25519_private_key(tv.private) - elif tv.encoding in ("XdhAsnComp", "XdhPemComp"): - try: - public_key = ECC.import_key(tv.public) - private_key = ECC.import_key(tv.private) - except ECC.UnsupportedEccFeature as e: - assert not tv.valid - assert "Unsupported ECC" in str(e) - return - except ValueError: - assert tv.valid - assert tv.warning - assert "LowOrderPublic" in tv.flags - return - elif tv.encoding == "XdhJwkComp": - - if 'y' in tv.public: - return - if 'x' not in tv.public: - return - if 'x' not in tv.private: - return - if tv.public.get('kty') != 'OKP': - return - if tv.public.get('crv') != 'X25519': - return - if tv.private.get('crv') != 'X25519': - return - - def base64url_decode(input_str): - input_str = input_str.replace('-', '+').replace('_', '/') - padding = 4 - (len(input_str) % 4) - if padding != 4: - input_str += '=' * padding - decoded_bytes = base64.b64decode(input_str) - return decoded_bytes - - jwk_public = base64url_decode(tv.public['x']) - jwk_private = base64url_decode(tv.private['d']) - - try: - public_key = import_x25519_public_key(jwk_public) - private_key = import_x25519_private_key(jwk_private) - except ValueError as e: - if tv.valid: - assert tv.warning - assert "LowOrderPublic" in tv.flags - assert "Invalid Curve25519" in str(e) - return - else: - assert "Incorrect length" in str(e) - return - except ValueError: - assert tv.valid - else: - raise ValueError("Unknown encoding", tv.encoding) - - try: - z = key_agreement(static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - except ValueError: - assert not tv.valid - except TypeError as e: - assert not tv.valid - assert "incompatible curve" in str(e) - else: - self.assertEqual(z, tv.shared) - assert tv.valid - - def runTest(self): - for tv in self.tv: - self.desc = "Wycheproof XECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - self.test_verify(tv) + desc = "Wycheproof X25519 tests" + + def add_tests_hex(self, filename): + def encoding(g): + return g["type"] + + def private(u): + return unhexlify(u["private"]) + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"encoding": encoding}, + unit_tag={"private": private}, + ) + self.tv += result + + def add_tests_ascii(self, filename): + def encoding(g): + return g["type"] + + def public(u): + return u["public"] + + def private(u): + return u["private"] + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"encoding": encoding}, + unit_tag={ + "public": public, + "private": private, + }, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.desc = None + + self.add_tests_hex("x25519_test.json") + self.add_tests_hex("x25519_asn_test.json") + self.add_tests_ascii("x25519_pem_test.json") + self.add_tests_ascii("x25519_jwk_test.json") + + def shortDescription(self): + return self.desc + + def test_verify(self, tv): + if tv.encoding == "XdhComp": + try: + public_key = import_x25519_public_key(tv.public) + except ValueError as e: + assert tv.valid + assert tv.warning + assert "LowOrderPublic" in tv.flags + assert "Invalid Curve25519" in str(e) + return + private_key = import_x25519_private_key(tv.private) + elif tv.encoding in ("XdhAsnComp", "XdhPemComp"): + try: + public_key = ECC.import_key(tv.public) + private_key = ECC.import_key(tv.private) + except ECC.UnsupportedEccFeature as e: + assert not tv.valid + assert "Unsupported ECC" in str(e) + return + except ValueError: + assert tv.valid + assert tv.warning + assert "LowOrderPublic" in tv.flags + return + elif tv.encoding == "XdhJwkComp": + if "y" in tv.public: + return + if "x" not in tv.public: + return + if "x" not in tv.private: + return + if tv.public.get("kty") != "OKP": + return + if tv.public.get("crv") != "X25519": + return + if tv.private.get("crv") != "X25519": + return + + def base64url_decode(input_str): + input_str = input_str.replace("-", "+").replace("_", "/") + padding = 4 - (len(input_str) % 4) + if padding != 4: + input_str += "=" * padding + decoded_bytes = base64.b64decode(input_str) + return decoded_bytes + + jwk_public = base64url_decode(tv.public["x"]) + jwk_private = base64url_decode(tv.private["d"]) + + try: + public_key = import_x25519_public_key(jwk_public) + private_key = import_x25519_private_key(jwk_private) + except ValueError as e: + if tv.valid: + assert tv.warning + assert "LowOrderPublic" in tv.flags + assert "Invalid Curve25519" in str(e) + return + else: + assert "Incorrect length" in str(e) + return + except ValueError: + assert tv.valid + else: + raise ValueError("Unknown encoding", tv.encoding) + + try: + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + except ValueError: + assert not tv.valid + except TypeError as e: + assert not tv.valid + assert "incompatible curve" in str(e) + else: + self.assertEqual(z, tv.shared) + assert tv.valid + + def runTest(self): + for tv in self.tv: + self.desc = "Wycheproof XECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + self.test_verify(tv) class TestVectorsX448Wycheproof(unittest.TestCase): - - desc = "Wycheproof X448 tests" - - def add_tests_hex(self, filename): - - def encoding(g): - return g['type'] - - def private(u): - return unhexlify(u['private']) - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'encoding': encoding}, - unit_tag={'private': private} - ) - self.tv += result - - def add_tests_ascii(self, filename): - - def encoding(g): - return g['type'] - - def public(u): - return u['public'] - - def private(u): - return u['private'] - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof ECDH (%s)" - % filename, - group_tag={'encoding': encoding}, - unit_tag={'public': public, - 'private': private} - ) - self.tv += result - - def setUp(self): - self.tv = [] - self.desc = None - - self.add_tests_hex("x448_test.json") - self.add_tests_hex("x448_asn_test.json") - self.add_tests_ascii("x448_pem_test.json") - self.add_tests_ascii("x448_jwk_test.json") - - def shortDescription(self): - return self.desc - - def test_verify(self, tv): - - if tv.encoding == "XdhComp": - try: - public_key = import_x448_public_key(tv.public) - except ValueError as e: - assert tv.valid - assert tv.warning - if len(tv.public) == 56: - assert "LowOrderPublic" in tv.flags - assert "Invalid Curve448" in str(e) - else: - assert "Incorrect Curve448" in str(e) - return - private_key = import_x448_private_key(tv.private) - elif tv.encoding in ("XdhAsnComp", "XdhPemComp"): - try: - public_key = ECC.import_key(tv.public) - private_key = ECC.import_key(tv.private) - except ECC.UnsupportedEccFeature as e: - assert not tv.valid - assert "Unsupported ECC" in str(e) - return - except ValueError as e: - assert tv.valid - assert tv.warning - assert "LowOrderPublic" in tv.flags or "NonCanonicalPublic" in tv.flags - return - elif tv.encoding == "XdhJwkComp": - - if 'y' in tv.public: - return - if 'x' not in tv.public: - return - if 'x' not in tv.private: - return - if tv.public.get('kty') != 'OKP': - return - if tv.public.get('crv') != 'X448': - return - if tv.private.get('crv') != 'X448': - return - - def base64url_decode(input_str): - input_str = input_str.replace('-', '+').replace('_', '/') - padding = 4 - (len(input_str) % 4) - if padding != 4: - input_str += '=' * padding - decoded_bytes = base64.b64decode(input_str) - return decoded_bytes - - jwk_public = base64url_decode(tv.public['x']) - jwk_private = base64url_decode(tv.private['d']) - - try: - public_key = import_x448_public_key(jwk_public) - private_key = import_x448_private_key(jwk_private) - except ValueError as e: - if tv.valid: - assert tv.warning - if len(tv.public['x']) == 75: - assert "LowOrderPublic" in tv.flags or \ - "NonCanonicalPublic" in tv.flags - assert "Invalid Curve448" in str(e) - else: - assert "Incorrect Curve448" in str(e) - return - else: - assert "Incorrect length" in str(e) - return - except ValueError: - assert tv.valid - else: - raise ValueError("Unknown encoding", tv.encoding) - - try: - z = key_agreement(static_pub=public_key, - static_priv=private_key, - kdf=lambda x: x) - except ValueError: - assert not tv.valid - except TypeError as e: - assert not tv.valid - assert "incompatible curve" in str(e) - else: - self.assertEqual(z, tv.shared) - assert tv.valid - - def runTest(self): - for tv in self.tv: - self.desc = "Wycheproof XECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - self.test_verify(tv) + desc = "Wycheproof X448 tests" + + def add_tests_hex(self, filename): + def encoding(g): + return g["type"] + + def private(u): + return unhexlify(u["private"]) + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"encoding": encoding}, + unit_tag={"private": private}, + ) + self.tv += result + + def add_tests_ascii(self, filename): + def encoding(g): + return g["type"] + + def public(u): + return u["public"] + + def private(u): + return u["private"] + + result = load_test_vectors_wycheproof( + ("Protocol", "wycheproof"), + filename, + "Wycheproof ECDH (%s)" % filename, + group_tag={"encoding": encoding}, + unit_tag={ + "public": public, + "private": private, + }, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.desc = None + + self.add_tests_hex("x448_test.json") + self.add_tests_hex("x448_asn_test.json") + self.add_tests_ascii("x448_pem_test.json") + self.add_tests_ascii("x448_jwk_test.json") + + def shortDescription(self): + return self.desc + + def test_verify(self, tv): + if tv.encoding == "XdhComp": + try: + public_key = import_x448_public_key(tv.public) + except ValueError as e: + assert tv.valid + assert tv.warning + if len(tv.public) == 56: + assert "LowOrderPublic" in tv.flags + assert "Invalid Curve448" in str(e) + else: + assert "Incorrect Curve448" in str(e) + return + private_key = import_x448_private_key(tv.private) + elif tv.encoding in ("XdhAsnComp", "XdhPemComp"): + try: + public_key = ECC.import_key(tv.public) + private_key = ECC.import_key(tv.private) + except ECC.UnsupportedEccFeature as e: + assert not tv.valid + assert "Unsupported ECC" in str(e) + return + except ValueError: + assert tv.valid + assert tv.warning + assert "LowOrderPublic" in tv.flags or "NonCanonicalPublic" in tv.flags + return + elif tv.encoding == "XdhJwkComp": + if "y" in tv.public: + return + if "x" not in tv.public: + return + if "x" not in tv.private: + return + if tv.public.get("kty") != "OKP": + return + if tv.public.get("crv") != "X448": + return + if tv.private.get("crv") != "X448": + return + + def base64url_decode(input_str): + input_str = input_str.replace("-", "+").replace("_", "/") + padding = 4 - (len(input_str) % 4) + if padding != 4: + input_str += "=" * padding + decoded_bytes = base64.b64decode(input_str) + return decoded_bytes + + jwk_public = base64url_decode(tv.public["x"]) + jwk_private = base64url_decode(tv.private["d"]) + + try: + public_key = import_x448_public_key(jwk_public) + private_key = import_x448_private_key(jwk_private) + except ValueError as e: + if tv.valid: + assert tv.warning + if len(tv.public["x"]) == 75: + assert "LowOrderPublic" in tv.flags or "NonCanonicalPublic" in tv.flags + assert "Invalid Curve448" in str(e) + else: + assert "Incorrect Curve448" in str(e) + return + else: + assert "Incorrect length" in str(e) + return + except ValueError: + assert tv.valid + else: + raise ValueError("Unknown encoding", tv.encoding) + + try: + z = key_agreement( + static_pub=public_key, + static_priv=private_key, + kdf=lambda x: x, + ) + except ValueError: + assert not tv.valid + except TypeError as e: + assert not tv.valid + assert "incompatible curve" in str(e) + else: + self.assertEqual(z, tv.shared) + assert tv.valid + + def runTest(self): + for tv in self.tv: + self.desc = "Wycheproof XECDH Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + self.test_verify(tv) def get_tests(config={}): + tests = [] + tests += list_test_cases(FIPS_ECDH_Tests_KAT) + tests += [TestVectorsECDHWycheproof()] + tests += list_test_cases(ECDH_Tests) + tests += list_test_cases(X25519_Tests) + tests += list_test_cases(X448_Tests) + tests += [TestVectorsX25519Wycheproof()] + tests += [TestVectorsX448Wycheproof()] + + slow_tests = config.get("slow_tests") + if slow_tests: + pass - tests = [] - tests += list_test_cases(FIPS_ECDH_Tests_KAT) - tests += [TestVectorsECDHWycheproof()] - tests += list_test_cases(ECDH_Tests) - tests += list_test_cases(X25519_Tests) - tests += list_test_cases(X448_Tests) - tests += [TestVectorsX25519Wycheproof()] - tests += [TestVectorsX448Wycheproof()] + return tests - slow_tests = config.get('slow_tests') - if slow_tests: - pass - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_rfc1751.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_rfc1751.py index a79769c2..a42f94bc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_rfc1751.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Protocol/test_rfc1751.py @@ -30,33 +30,41 @@ from Cryptodome.Util import RFC1751 from Cryptodome.Util.py3compat import * -test_data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), - ('CCAC2AED591056BE4F90FD441C534766', - 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), - ('EFF81F9BFBC65350920CDD7416DE8009', - 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') - ] +test_data = [ + ("EB33F77EE73D4053", "TIDE ITCH SLOW REIN RULE MOT"), + ( + "CCAC2AED591056BE4F90FD441C534766", + "RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE", + ), + ( + "EFF81F9BFBC65350920CDD7416DE8009", + "TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL", + ), +] -class RFC1751Test_k2e (unittest.TestCase): - def runTest (self): - "Check converting keys to English" - for key, words in test_data: - key=binascii.a2b_hex(b(key)) - self.assertEqual(RFC1751.key_to_english(key), words) +class RFC1751Test_k2e(unittest.TestCase): + def runTest(self): + "Check converting keys to English" + for key, words in test_data: + key = binascii.a2b_hex(b(key)) + self.assertEqual(RFC1751.key_to_english(key), words) -class RFC1751Test_e2k (unittest.TestCase): - def runTest (self): - "Check converting English strings to keys" - for key, words in test_data: - key=binascii.a2b_hex(b(key)) - self.assertEqual(RFC1751.english_to_key(words), key) +class RFC1751Test_e2k(unittest.TestCase): + def runTest(self): + "Check converting English strings to keys" + for key, words in test_data: + key = binascii.a2b_hex(b(key)) + self.assertEqual(RFC1751.english_to_key(words), key) + # class RFC1751Test + def get_tests(config={}): - return [RFC1751Test_k2e(), RFC1751Test_e2k()] + return [RFC1751Test_k2e(), RFC1751Test_e2k()] + if __name__ == "__main__": - unittest.main() + unittest.main() diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/__init__.py index f16a6ff1..e8e4b80d 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/__init__.py @@ -25,39 +25,46 @@ """Self-test for public-key crypto""" import unittest -from Cryptodome.SelfTest.PublicKey import (test_DSA, test_RSA, - test_ECC_NIST, - test_ECC_Ed25519, - test_ECC_Curve25519, - test_ECC_Ed448, - test_ECC_Curve448, - test_import_DSA, test_import_RSA, - test_import_ECC, test_ElGamal, - test_import_Curve25519, - test_import_Curve448) +from Cryptodome.SelfTest.PublicKey import ( + test_DSA, + test_RSA, + test_ECC_NIST, + test_ECC_Ed25519, + test_ECC_Curve25519, + test_ECC_Ed448, + test_ECC_Curve448, + test_import_DSA, + test_import_RSA, + test_import_ECC, + test_ElGamal, + test_import_Curve25519, + test_import_Curve448, +) def get_tests(config={}): - tests = [] - tests += test_DSA.get_tests(config=config) - tests += test_RSA.get_tests(config=config) - tests += test_ECC_NIST.get_tests(config=config) - tests += test_ECC_Ed25519.get_tests(config=config) - tests += test_ECC_Curve25519.get_tests(config=config) - tests += test_ECC_Ed448.get_tests(config=config) - tests += test_ECC_Curve448.get_tests(config=config) - - tests += test_import_DSA.get_tests(config=config) - tests += test_import_RSA.get_tests(config=config) - tests += test_import_ECC.get_tests(config=config) - tests += test_import_Curve25519.get_tests(config=config) - tests += test_import_Curve448.get_tests(config=config) - - tests += test_ElGamal.get_tests(config=config) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += test_DSA.get_tests(config=config) + tests += test_RSA.get_tests(config=config) + tests += test_ECC_NIST.get_tests(config=config) + tests += test_ECC_Ed25519.get_tests(config=config) + tests += test_ECC_Curve25519.get_tests(config=config) + tests += test_ECC_Ed448.get_tests(config=config) + tests += test_ECC_Curve448.get_tests(config=config) + + tests += test_import_DSA.get_tests(config=config) + tests += test_import_RSA.get_tests(config=config) + tests += test_import_ECC.get_tests(config=config) + tests += test_import_Curve25519.get_tests(config=config) + tests += test_import_Curve448.get_tests(config=config) + + tests += test_ElGamal.get_tests(config=config) + return tests + + +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_DSA.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_DSA.py index 160d8820..b8b3c05d 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_DSA.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_DSA.py @@ -24,224 +24,224 @@ """Self-test suite for Cryptodome.PublicKey.DSA""" -import os from Cryptodome.Util.py3compat import * import unittest from Cryptodome.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex + def _sws(s): - """Remove whitespace from a text or byte string""" - if isinstance(s,str): - return "".join(s.split()) - else: - return b("").join(s.split()) + """Remove whitespace from a text or byte string""" + if isinstance(s, str): + return "".join(s.split()) + else: + return b("").join(s.split()) + class DSATest(unittest.TestCase): - # Test vector from "Appendix 5. Example of the DSA" of - # "Digital Signature Standard (DSS)", - # U.S. Department of Commerce/National Institute of Standards and Technology - # FIPS 186-2 (+Change Notice), 2000 January 27. - # http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf + # Test vector from "Appendix 5. Example of the DSA" of + # "Digital Signature Standard (DSS)", + # U.S. Department of Commerce/National Institute of Standards and Technology + # FIPS 186-2 (+Change Notice), 2000 January 27. + # http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf - y = _sws("""19131871 d75b1612 a819f29d 78d1b0d7 346f7aa7 7bb62a85 + y = _sws("""19131871 d75b1612 a819f29d 78d1b0d7 346f7aa7 7bb62a85 9bfd6c56 75da9d21 2d3a36ef 1672ef66 0b8c7c25 5cc0ec74 858fba33 f44c0669 9630a76b 030ee333""") - g = _sws("""626d0278 39ea0a13 413163a5 5b4cb500 299d5522 956cefcb + g = _sws("""626d0278 39ea0a13 413163a5 5b4cb500 299d5522 956cefcb 3bff10f3 99ce2c2e 71cb9de5 fa24babf 58e5b795 21925c9c c42e9f6f 464b088c c572af53 e6d78802""") - p = _sws("""8df2a494 492276aa 3d25759b b06869cb eac0d83a fb8d0cf7 + p = _sws("""8df2a494 492276aa 3d25759b b06869cb eac0d83a fb8d0cf7 cbb8324f 0d7882e5 d0762fc5 b7210eaf c2e9adac 32ab7aac 49693dfb f83724c2 ec0736ee 31c80291""") - q = _sws("""c773218c 737ec8ee 993b4f2d ed30f48e dace915f""") - - x = _sws("""2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614""") - - k = _sws("""358dad57 1462710f 50e254cf 1a376b2b deaadfbf""") - k_inverse = _sws("""0d516729 8202e49b 4116ac10 4fc3f415 ae52f917""") - m = b2a_hex(b("abc")) - m_hash = _sws("""a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d""") - r = _sws("""8bac1ab6 6410435c b7181f95 b16ab97c 92b341c0""") - s = _sws("""41e2345f 1f56df24 58f426d1 55b4ba2d b6dcd8c8""") - - def setUp(self): - global DSA, Random, bytes_to_long, size - from Cryptodome.PublicKey import DSA - from Cryptodome import Random - from Cryptodome.Util.number import bytes_to_long, inverse, size - - self.dsa = DSA - - def test_generate_1arg(self): - """DSA (default implementation) generated key (1 argument)""" - dsaObj = self.dsa.generate(1024) - self._check_private_key(dsaObj) - pub = dsaObj.public_key() - self._check_public_key(pub) - - def test_generate_2arg(self): - """DSA (default implementation) generated key (2 arguments)""" - dsaObj = self.dsa.generate(1024, Random.new().read) - self._check_private_key(dsaObj) - pub = dsaObj.public_key() - self._check_public_key(pub) - - def test_construct_4tuple(self): - """DSA (default implementation) constructed key (4-tuple)""" - (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] - dsaObj = self.dsa.construct((y, g, p, q)) - self._test_verification(dsaObj) - - def test_construct_5tuple(self): - """DSA (default implementation) constructed key (5-tuple)""" - (y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)] - dsaObj = self.dsa.construct((y, g, p, q, x)) - self._test_signing(dsaObj) - self._test_verification(dsaObj) - - def test_construct_bad_key4(self): - (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] - tup = (y, g, p+1, q) - self.assertRaises(ValueError, self.dsa.construct, tup) - - tup = (y, g, p, q+1) - self.assertRaises(ValueError, self.dsa.construct, tup) - - tup = (y, 1, p, q) - self.assertRaises(ValueError, self.dsa.construct, tup) - - def test_construct_bad_key5(self): - (y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)] - tup = (y, g, p, q, x+1) - self.assertRaises(ValueError, self.dsa.construct, tup) - - tup = (y, g, p, q, q+10) - self.assertRaises(ValueError, self.dsa.construct, tup) - - def _check_private_key(self, dsaObj): - # Check capabilities - self.assertEqual(1, dsaObj.has_private()) - self.assertEqual(1, dsaObj.can_sign()) - self.assertEqual(0, dsaObj.can_encrypt()) - - # Sanity check key data - self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q - self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits - self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 - self.assertEqual(dsaObj.y, pow(dsaObj.g, dsaObj.x, dsaObj.p)) # y == g**x mod p - self.assertEqual(1, 0 < dsaObj.x < dsaObj.q) # 0 < x < q - - def _check_public_key(self, dsaObj): - k = bytes_to_long(a2b_hex(self.k)) - m_hash = bytes_to_long(a2b_hex(self.m_hash)) - - # Check capabilities - self.assertEqual(0, dsaObj.has_private()) - self.assertEqual(1, dsaObj.can_sign()) - self.assertEqual(0, dsaObj.can_encrypt()) - - # Check that private parameters are all missing - self.assertEqual(0, hasattr(dsaObj, 'x')) - - # Sanity check key data - self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q - self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits - self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 - - # Public-only key objects should raise an error when .sign() is called - self.assertRaises(TypeError, dsaObj._sign, m_hash, k) - - # Check __eq__ and __ne__ - self.assertEqual(dsaObj.public_key() == dsaObj.public_key(),True) # assert_ - self.assertEqual(dsaObj.public_key() != dsaObj.public_key(),False) # assertFalse - - self.assertEqual(dsaObj.public_key(), dsaObj.publickey()) - - def _test_signing(self, dsaObj): - k = bytes_to_long(a2b_hex(self.k)) - m_hash = bytes_to_long(a2b_hex(self.m_hash)) - r = bytes_to_long(a2b_hex(self.r)) - s = bytes_to_long(a2b_hex(self.s)) - (r_out, s_out) = dsaObj._sign(m_hash, k) - self.assertEqual((r, s), (r_out, s_out)) - - def _test_verification(self, dsaObj): - m_hash = bytes_to_long(a2b_hex(self.m_hash)) - r = bytes_to_long(a2b_hex(self.r)) - s = bytes_to_long(a2b_hex(self.s)) - self.assertTrue(dsaObj._verify(m_hash, (r, s))) - self.assertFalse(dsaObj._verify(m_hash + 1, (r, s))) - - def test_repr(self): - (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] - dsaObj = self.dsa.construct((y, g, p, q)) - repr(dsaObj) + q = _sws("""c773218c 737ec8ee 993b4f2d ed30f48e dace915f""") + + x = _sws("""2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614""") + + k = _sws("""358dad57 1462710f 50e254cf 1a376b2b deaadfbf""") + k_inverse = _sws("""0d516729 8202e49b 4116ac10 4fc3f415 ae52f917""") + m = b2a_hex(b("abc")) + m_hash = _sws("""a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d""") + r = _sws("""8bac1ab6 6410435c b7181f95 b16ab97c 92b341c0""") + s = _sws("""41e2345f 1f56df24 58f426d1 55b4ba2d b6dcd8c8""") + + def setUp(self): + global DSA, Random, bytes_to_long, size + from Cryptodome.PublicKey import DSA + from Cryptodome import Random + from Cryptodome.Util.number import bytes_to_long, size + + self.dsa = DSA + + def test_generate_1arg(self): + """DSA (default implementation) generated key (1 argument)""" + dsaObj = self.dsa.generate(1024) + self._check_private_key(dsaObj) + pub = dsaObj.public_key() + self._check_public_key(pub) + + def test_generate_2arg(self): + """DSA (default implementation) generated key (2 arguments)""" + dsaObj = self.dsa.generate(1024, Random.new().read) + self._check_private_key(dsaObj) + pub = dsaObj.public_key() + self._check_public_key(pub) + + def test_construct_4tuple(self): + """DSA (default implementation) constructed key (4-tuple)""" + (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] + dsaObj = self.dsa.construct((y, g, p, q)) + self._test_verification(dsaObj) + + def test_construct_5tuple(self): + """DSA (default implementation) constructed key (5-tuple)""" + (y, g, p, q, x) = [ + bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x) + ] + dsaObj = self.dsa.construct((y, g, p, q, x)) + self._test_signing(dsaObj) + self._test_verification(dsaObj) + + def test_construct_bad_key4(self): + (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] + tup = (y, g, p + 1, q) + self.assertRaises(ValueError, self.dsa.construct, tup) + + tup = (y, g, p, q + 1) + self.assertRaises(ValueError, self.dsa.construct, tup) + + tup = (y, 1, p, q) + self.assertRaises(ValueError, self.dsa.construct, tup) + + def test_construct_bad_key5(self): + (y, g, p, q, x) = [ + bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x) + ] + tup = (y, g, p, q, x + 1) + self.assertRaises(ValueError, self.dsa.construct, tup) + + tup = (y, g, p, q, q + 10) + self.assertRaises(ValueError, self.dsa.construct, tup) + + def _check_private_key(self, dsaObj): + # Check capabilities + self.assertEqual(1, dsaObj.has_private()) + self.assertEqual(1, dsaObj.can_sign()) + self.assertEqual(0, dsaObj.can_encrypt()) + + # Sanity check key data + self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q + self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits + self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 + self.assertEqual(dsaObj.y, pow(dsaObj.g, dsaObj.x, dsaObj.p)) # y == g**x mod p + self.assertEqual(1, 0 < dsaObj.x < dsaObj.q) # 0 < x < q + + def _check_public_key(self, dsaObj): + k = bytes_to_long(a2b_hex(self.k)) + m_hash = bytes_to_long(a2b_hex(self.m_hash)) + + # Check capabilities + self.assertEqual(0, dsaObj.has_private()) + self.assertEqual(1, dsaObj.can_sign()) + self.assertEqual(0, dsaObj.can_encrypt()) + + # Check that private parameters are all missing + self.assertEqual(0, hasattr(dsaObj, "x")) + + # Sanity check key data + self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q + self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits + self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 + + # Public-only key objects should raise an error when .sign() is called + self.assertRaises(TypeError, dsaObj._sign, m_hash, k) + + # Check __eq__ and __ne__ + self.assertEqual(dsaObj.public_key() == dsaObj.public_key(), True) # assert_ + self.assertEqual(dsaObj.public_key() != dsaObj.public_key(), False) # assertFalse + + self.assertEqual(dsaObj.public_key(), dsaObj.publickey()) + + def _test_signing(self, dsaObj): + k = bytes_to_long(a2b_hex(self.k)) + m_hash = bytes_to_long(a2b_hex(self.m_hash)) + r = bytes_to_long(a2b_hex(self.r)) + s = bytes_to_long(a2b_hex(self.s)) + (r_out, s_out) = dsaObj._sign(m_hash, k) + self.assertEqual((r, s), (r_out, s_out)) + + def _test_verification(self, dsaObj): + m_hash = bytes_to_long(a2b_hex(self.m_hash)) + r = bytes_to_long(a2b_hex(self.r)) + s = bytes_to_long(a2b_hex(self.s)) + self.assertTrue(dsaObj._verify(m_hash, (r, s))) + self.assertFalse(dsaObj._verify(m_hash + 1, (r, s))) + + def test_repr(self): + (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] + dsaObj = self.dsa.construct((y, g, p, q)) + repr(dsaObj) class DSADomainTest(unittest.TestCase): + def test_domain1(self): + """Verify we can generate new keys in a given domain""" + dsa_key_1 = DSA.generate(1024) + domain_params = dsa_key_1.domain() - def test_domain1(self): - """Verify we can generate new keys in a given domain""" - dsa_key_1 = DSA.generate(1024) - domain_params = dsa_key_1.domain() - - dsa_key_2 = DSA.generate(1024, domain=domain_params) - self.assertEqual(dsa_key_1.p, dsa_key_2.p) - self.assertEqual(dsa_key_1.q, dsa_key_2.q) - self.assertEqual(dsa_key_1.g, dsa_key_2.g) - - self.assertEqual(dsa_key_1.domain(), dsa_key_2.domain()) + dsa_key_2 = DSA.generate(1024, domain=domain_params) + self.assertEqual(dsa_key_1.p, dsa_key_2.p) + self.assertEqual(dsa_key_1.q, dsa_key_2.q) + self.assertEqual(dsa_key_1.g, dsa_key_2.g) - def _get_weak_domain(self): + self.assertEqual(dsa_key_1.domain(), dsa_key_2.domain()) - from Cryptodome.Math.Numbers import Integer - from Cryptodome.Math import Primality + def _get_weak_domain(self): + from Cryptodome.Math.Numbers import Integer + from Cryptodome.Math import Primality - p = Integer(4) - while p.size_in_bits() != 1024 or Primality.test_probable_prime(p) != Primality.PROBABLY_PRIME: - q1 = Integer.random(exact_bits=80) - q2 = Integer.random(exact_bits=80) - q = q1 * q2 - z = Integer.random(exact_bits=1024-160) - p = z * q + 1 + p = Integer(4) + while p.size_in_bits() != 1024 or Primality.test_probable_prime(p) != Primality.PROBABLY_PRIME: + q1 = Integer.random(exact_bits=80) + q2 = Integer.random(exact_bits=80) + q = q1 * q2 + z = Integer.random(exact_bits=1024 - 160) + p = z * q + 1 - h = Integer(2) - g = 1 - while g == 1: - g = pow(h, z, p) - h += 1 + h = Integer(2) + g = 1 + while g == 1: + g = pow(h, z, p) + h += 1 - return (p, q, g) + return (p, q, g) + def test_generate_error_weak_domain(self): + """Verify that domain parameters with composite q are rejected""" - def test_generate_error_weak_domain(self): - """Verify that domain parameters with composite q are rejected""" + domain_params = self._get_weak_domain() + self.assertRaises(ValueError, DSA.generate, 1024, domain=domain_params) - domain_params = self._get_weak_domain() - self.assertRaises(ValueError, DSA.generate, 1024, domain=domain_params) + def test_construct_error_weak_domain(self): + """Verify that domain parameters with composite q are rejected""" + p, q, g = self._get_weak_domain() + y = pow(g, 89, p) + self.assertRaises(ValueError, DSA.construct, (y, g, p, q)) - def test_construct_error_weak_domain(self): - """Verify that domain parameters with composite q are rejected""" - from Cryptodome.Math.Numbers import Integer - - p, q, g = self._get_weak_domain() - y = pow(g, 89, p) - self.assertRaises(ValueError, DSA.construct, (y, g, p, q)) +def get_tests(config={}): + tests = [] + tests += list_test_cases(DSATest) + tests += list_test_cases(DSADomainTest) + return tests -def get_tests(config={}): - tests = [] - tests += list_test_cases(DSATest) - tests += list_test_cases(DSADomainTest) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Curve25519.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Curve25519.py index 8defd001..f1cf1f4c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Curve25519.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Curve25519.py @@ -43,241 +43,290 @@ # The order is 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed # Each tuple is (exponent, X-coordinate) scalar_base9_test = [ - (1, 9), - (2, 0x20d342d51873f1b7d9750c687d1571148f3f5ced1e350b5c5cae469cdd684efb), - (3, 0x1c12bc1a6d57abe645534d91c21bba64f8824e67621c0859c00a03affb713c12), - (4, 0x79ce98b7e0689d7de7d1d074a15b315ffe1805dfcd5d2a230fee85e4550013ef), - (6, 0x26954ccdc99ebf34f8f1dde5e6bb080685fec73640494c28f9fe0bfa8c794531), - (9, 0x192b929197d07748db44600da41bab7499b1c2e6e2f87c6f0e337980668164ba), - (129, 0x7332096a738900085e721103fce2cbf13aee50fef0788ea0d669008eb09ceab7), - (255, 0x1534582fc2b1cea45e8cb776547e209da4fd54a9e473b50c5b8c6b0ae023a9b3), - (256, 0x4300017536976a742ec8747f7505cd6bc80e610d669acab1a1eed36f680d98e8), - (257, 0x6c410611cb484c9016adfb884d37a0e682e075daca1d46f45bb7a4afed10b125), - (0x10101, 0xa679e9d7e043bf76c03362576e2c88abe9093c5d4f6b4a202c64a8397467cf), - (0xAA55CC, 0x2cc02f84c067e3586f4278326689be163e606d69ccae505bb09488e11f295887), - (0x1B29A0E579E0A000567, 0x50c38a72d7bfd7864c8b9083fa123e8d359068e6b491a019a885036e073f6604), - (0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed + 1, 9), + (1, 9), + (2, 0x20D342D51873F1B7D9750C687D1571148F3F5CED1E350B5C5CAE469CDD684EFB), + (3, 0x1C12BC1A6D57ABE645534D91C21BBA64F8824E67621C0859C00A03AFFB713C12), + (4, 0x79CE98B7E0689D7DE7D1D074A15B315FFE1805DFCD5D2A230FEE85E4550013EF), + (6, 0x26954CCDC99EBF34F8F1DDE5E6BB080685FEC73640494C28F9FE0BFA8C794531), + (9, 0x192B929197D07748DB44600DA41BAB7499B1C2E6E2F87C6F0E337980668164BA), + (129, 0x7332096A738900085E721103FCE2CBF13AEE50FEF0788EA0D669008EB09CEAB7), + (255, 0x1534582FC2B1CEA45E8CB776547E209DA4FD54A9E473B50C5B8C6B0AE023A9B3), + (256, 0x4300017536976A742EC8747F7505CD6BC80E610D669ACAB1A1EED36F680D98E8), + (257, 0x6C410611CB484C9016ADFB884D37A0E682E075DACA1D46F45BB7A4AFED10B125), + (0x10101, 0xA679E9D7E043BF76C03362576E2C88ABE9093C5D4F6B4A202C64A8397467CF), + (0xAA55CC, 0x2CC02F84C067E3586F4278326689BE163E606D69CCAE505BB09488E11F295887), + (0x1B29A0E579E0A000567, 0x50C38A72D7BFD7864C8B9083FA123E8D359068E6B491A019A885036E073F6604), + (0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED + 1, 9), ] class TestEccPoint_Curve25519(unittest.TestCase): + v1 = 0x09FA78B39B00A72930BCD8039BE789A0997830BB99F79AEEB93493715390B4E8 + v2 = 0x15210F12786811D3F4B7959D0538AE2C31DBE7106FC03C3EFC4CD549C715A493 - v1 = 0x09fa78b39b00a72930bcd8039be789a0997830bb99f79aeeb93493715390b4e8 - v2 = 0x15210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493 + def test_init(self): + EccXPoint(9, "curve25519") + EccXPoint(2**255 - 19 + 5, "curve25519") - def test_init(self): - EccXPoint(9, "curve25519") - EccXPoint(2**255 - 19 + 5, "curve25519") + def test_curve_attribute(self): + point = EccXPoint(9, "curve25519") + self.assertEqual(point.curve, "Curve25519") - def test_curve_attribute(self): - point = EccXPoint(9, "curve25519") - self.assertEqual(point.curve, "Curve25519") + def test_init_fail(self): + self.assertRaises(ValueError, EccXPoint, 3 * (2**255 - 19), "curve25519") + self.assertRaises(ValueError, EccXPoint, 9, "curve25518") - def test_init_fail(self): - self.assertRaises(ValueError, EccXPoint, 3*(2**255 - 19), "curve25519") - self.assertRaises(ValueError, EccXPoint, 9, "curve25518") + def test_equal_set(self): + point1 = EccXPoint(self.v1, "curve25519") + point2 = EccXPoint(self.v2, "curve25519") - def test_equal_set(self): - point1 = EccXPoint(self.v1, "curve25519") - point2 = EccXPoint(self.v2, "curve25519") + self.assertEqual(point1, point1) + self.assertNotEqual(point1, point2) - self.assertEqual(point1, point1) - self.assertNotEqual(point1, point2) + point2.set(point1) + self.assertEqual(point1.x, point2.x) - point2.set(point1) - self.assertEqual(point1.x, point2.x) + def test_copy(self): + point1 = EccXPoint(self.v1, "curve25519") + point2 = point1.copy() + self.assertEqual(point1.x, point2.x) - def test_copy(self): - point1 = EccXPoint(self.v1, "curve25519") - point2 = point1.copy() - self.assertEqual(point1.x, point2.x) + def test_pai(self): + point1 = EccXPoint(self.v1, "curve25519") + pai = point1.point_at_infinity() + self.assertTrue(pai.point_at_infinity()) - def test_pai(self): - point1 = EccXPoint(self.v1, "curve25519") - pai = point1.point_at_infinity() - self.assertTrue(pai.point_at_infinity()) + point2 = EccXPoint(None, "curve25519") + self.assertTrue(point2.point_at_infinity()) - point2 = EccXPoint(None, "curve25519") - self.assertTrue(point2.point_at_infinity()) + def test_scalar_multiply(self): + base = EccXPoint(9, "curve25519") - def test_scalar_multiply(self): - base = EccXPoint(9, "curve25519") + pointH = 0 * base + self.assertTrue(pointH.point_at_infinity()) - pointH = 0 * base - self.assertTrue(pointH.point_at_infinity()) + pointH = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED * base + self.assertTrue(pointH.point_at_infinity()) - pointH = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed * base - self.assertTrue(pointH.point_at_infinity()) + pointH = base * 1 + self.assertEqual(pointH.x, 9) - pointH = base * 1 - self.assertEqual(pointH.x, 9) + for d, result in scalar_base9_test: + pointH = d * base + self.assertEqual(pointH.x, result) - for d, result in scalar_base9_test: - pointH = d * base - self.assertEqual(pointH.x, result) - - def test_sizes(self): - point = EccXPoint(9, "curve25519") - self.assertEqual(point.size_in_bits(), 255) - self.assertEqual(point.size_in_bytes(), 32) + def test_sizes(self): + point = EccXPoint(9, "curve25519") + self.assertEqual(point.size_in_bits(), 255) + self.assertEqual(point.size_in_bytes(), 32) class TestEccKey_Curve25519(unittest.TestCase): - - def test_private_key(self): - # RFC7748 Section 6.1 - Alice - alice_priv = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") - alice_pub = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a") - alice_pub_x = Integer.from_bytes(alice_pub, byteorder='little') - - key = EccKey(curve="Curve25519", seed=alice_priv) - self.assertEqual(key.seed, alice_priv) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, alice_pub_x) - - # RFC7748 Section 6.1 - Bob - bob_priv = unhexlify("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb") - bob_pub = unhexlify("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f") - bob_pub_x = Integer.from_bytes(bob_pub, byteorder='little') - - key = EccKey(curve="Curve25519", seed=bob_priv) - self.assertEqual(key.seed, bob_priv) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, bob_pub_x) - - # Other names - key = EccKey(curve="curve25519", seed=alice_priv) - - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="curve25519", d=1) - - def test_public_key(self): - point = EccXPoint(_curves['curve25519'].Gx, - curve='curve25519') - key = EccKey(curve="curve25519", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - priv_key = EccKey(curve="curve25519", seed=b'H'*32) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_seed(self): - self.assertRaises(ValueError, lambda: EccKey(curve="curve25519", seed=b'H' * 31)) - - def test_equality(self): - private_key = ECC.construct(seed=b'H'*32, curve="Curve25519") - private_key2 = ECC.construct(seed=b'H'*32, curve="curve25519") - private_key3 = ECC.construct(seed=b'C'*32, curve="Curve25519") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='curve25519') - self.assertIn("curve='Curve25519'", repr(key)) - self.assertEqual(key.curve, 'Curve25519') - self.assertEqual(key.public_key().curve, 'Curve25519') + def test_private_key(self): + # RFC7748 Section 6.1 - Alice + alice_priv = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") + alice_pub = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a") + alice_pub_x = Integer.from_bytes(alice_pub, byteorder="little") + + key = EccKey(curve="Curve25519", seed=alice_priv) + self.assertEqual(key.seed, alice_priv) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, alice_pub_x) + + # RFC7748 Section 6.1 - Bob + bob_priv = unhexlify("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb") + bob_pub = unhexlify("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f") + bob_pub_x = Integer.from_bytes(bob_pub, byteorder="little") + + key = EccKey(curve="Curve25519", seed=bob_priv) + self.assertEqual(key.seed, bob_priv) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, bob_pub_x) + + # Other names + key = EccKey(curve="curve25519", seed=alice_priv) + + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="curve25519", d=1) + + def test_public_key(self): + point = EccXPoint( + _curves["curve25519"].Gx, + curve="curve25519", + ) + key = EccKey(curve="curve25519", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="curve25519", seed=b"H" * 32) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_seed(self): + self.assertRaises(ValueError, lambda: EccKey(curve="curve25519", seed=b"H" * 31)) + + def test_equality(self): + private_key = ECC.construct(seed=b"H" * 32, curve="Curve25519") + private_key2 = ECC.construct(seed=b"H" * 32, curve="curve25519") + private_key3 = ECC.construct(seed=b"C" * 32, curve="Curve25519") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="curve25519") + self.assertIn("curve='Curve25519'", repr(key)) + self.assertEqual(key.curve, "Curve25519") + self.assertEqual(key.public_key().curve, "Curve25519") class TestEccModule_Curve25519(unittest.TestCase): - - def test_generate(self): - key = ECC.generate(curve="Curve25519") - self.assertTrue(key.has_private()) - point = EccXPoint(_curves['Curve25519'].Gx, curve="Curve25519") * key.d - self.assertEqual(key.pointQ, point) - - # Always random - key2 = ECC.generate(curve="Curve25519") - self.assertNotEqual(key, key2) - - # Other names - ECC.generate(curve="curve25519") - - # Random source - key1 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read) - key2 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read) - self.assertEqual(key1, key2) - - def test_construct(self): - seed = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") - point_hex = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a") - Px = Integer.from_bytes(point_hex, byteorder='little') - point = EccXPoint(Px, curve="Curve25519") - - # Private key only - key = ECC.construct(curve="Curve25519", seed=seed) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Public key only - key = ECC.construct(curve="Curve25519", point_x=Px) - self.assertEqual(key.pointQ, point) - self.assertFalse(key.has_private()) - - # Private and public key - key = ECC.construct(curve="Curve25519", seed=seed, point_x=Px) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Other names - key = ECC.construct(curve="curve25519", seed=seed) - - def test_negative_construct(self): - coordG = dict(point_x=_curves['curve25519'].Gx) - - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", d=2, **coordG) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", seed=b'H'*31) - - # Verify you cannot construct weak keys (small-order points) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=0) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=1) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=325606250916557431795983626356110631294008115727848805560023387167927233504) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=39382357235489614581723060781553021112529911719440698176882885853963445705823) - p = 2**255 - 19 - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p-1) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p+1) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p+325606250916557431795983626356110631294008115727848805560023387167927233504) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p+39382357235489614581723060781553021112529911719440698176882885853963445705823) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p*2-1) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p*2) - self.assertRaises(ValueError, ECC.construct, curve="Curve25519", - point_x=p*2+1) + def test_generate(self): + key = ECC.generate(curve="Curve25519") + self.assertTrue(key.has_private()) + point = EccXPoint(_curves["Curve25519"].Gx, curve="Curve25519") * key.d + self.assertEqual(key.pointQ, point) + + # Always random + key2 = ECC.generate(curve="Curve25519") + self.assertNotEqual(key, key2) + + # Other names + ECC.generate(curve="curve25519") + + # Random source + key1 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read) + key2 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read) + self.assertEqual(key1, key2) + + def test_construct(self): + seed = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") + point_hex = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a") + Px = Integer.from_bytes(point_hex, byteorder="little") + point = EccXPoint(Px, curve="Curve25519") + + # Private key only + key = ECC.construct(curve="Curve25519", seed=seed) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Public key only + key = ECC.construct(curve="Curve25519", point_x=Px) + self.assertEqual(key.pointQ, point) + self.assertFalse(key.has_private()) + + # Private and public key + key = ECC.construct(curve="Curve25519", seed=seed, point_x=Px) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Other names + key = ECC.construct(curve="curve25519", seed=seed) + + def test_negative_construct(self): + coordG = dict(point_x=_curves["curve25519"].Gx) + + self.assertRaises(ValueError, ECC.construct, curve="Curve25519", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="Curve25519", seed=b"H" * 31) + + # Verify you cannot construct weak keys (small-order points) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=0, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=325606250916557431795983626356110631294008115727848805560023387167927233504, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=39382357235489614581723060781553021112529911719440698176882885853963445705823, + ) + p = 2**255 - 19 + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p - 1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p + 1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p + 325606250916557431795983626356110631294008115727848805560023387167927233504, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p + 39382357235489614581723060781553021112529911719440698176882885853963445705823, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p * 2 - 1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p * 2, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve25519", + point_x=p * 2 + 1, + ) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint_Curve25519) - tests += list_test_cases(TestEccKey_Curve25519) - tests += list_test_cases(TestEccModule_Curve25519) - return tests + tests = [] + tests += list_test_cases(TestEccPoint_Curve25519) + tests += list_test_cases(TestEccKey_Curve25519) + tests += list_test_cases(TestEccModule_Curve25519) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Curve448.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Curve448.py index 6a05a9bc..bd5f4d89 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Curve448.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Curve448.py @@ -12,235 +12,318 @@ from Cryptodome.PublicKey.ECC import EccKey, EccXPoint, _curves CURVE448_P = 2**448 - 2**224 - 1 -CURVE448_ORDER = 2**446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d +CURVE448_ORDER = 2**446 - 0x8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D # Test vectors for scalar multiplication using point with X=5 as base # Each tuple is (exponent, X-coordinate) scalar_base5_test = [ - (1, 5), - (2, 0x6391322257cae3d49aef4665d8bd5cccac9abefb511e83d75f3c766616266fc1bf3747f1da00ed7125e8f0255a1208087d32a4bc1c743cb6), - (3, 0x1fbe4b3584cab86170c14b9325840b8a2429b61fb93c42492c002a2807a4e7ea63138ea59bf95652ce9a7d13d0321c7511e3314d0553f34c), - (4, 0x93b44a7b78726ba8d0b048bd7144074f8bdad24ef9d0a6c8264f6c00b135ffcea11545e80d18364acc8ebfbcc45358e0da5fd5e5146e2b1), - (6, 0x693d165f453bd62871e5e53845f33e9e5b18b24d79c1f9102608aa7ba6f18ac24864012171d64c90b698f5ce5631cd02cee4e4336b1ad88c), - (9, 0xb970d576e7d9aa427dbf7cb9b7dd65170721d04ee060c9ea8d499dc361d4cfde1ceb19068eae853bac8f5d92827bdbf3d94c22de2fb42dae), - (129, 0x9fbdb50a1450438fe656aa32aa1bb2548d077d5c3a5d327689093a2996a4f94eacd1fb4f90315edb2afe41908a759f0d6db83fa791df80db), - (255, 0x31bc3e9385dfd12e1238927061eb0c911466da394e459bf058ba3b08260a258a3c392b0f85ddbd23828657137b88577a85b83774139fab9e), - (256, 0x735c7f30e6872e5e4215c0147c8a112d697f668c9bd0f92f5f1e4e6badc128a0b654e697cd4bae2144d54e726b54c1fa63a09b00dd3c17f), - (257, 0x95c1b0ce01286dc047aeb5922a5e62b3effb5b9296273a5004eb456f592728dd494a6fb5996a2ea7011ae6423874a48c2927bfa62d8ce8b0), - (0x10101, 0x113bb172c9dc52ab45bd665dd9751ed44e33b8596f943c6cb2f8dd329160ece802960b3eb0d2c21ef3a3ac12c20fccbc2a271fc2f061c1b2), - (0xAA55CC, 0xcf42585d2e0b1e45c0bfd601c91af4b137d7faf139fc761178c7ded432417c307ee1759af2deec6a14dbaf6b868eb13a6039fbdde4b61898), - (0x1B29A0E579E0A000567, 0x7bd9ec9775a664f4d860d82d6be60895113a7c36f92db25583dbba5dc17f09c136ec27e14857bfd6a705311327030aa657dd036325fad330), - (CURVE448_ORDER + 1, 5), + (1, 5), + ( + 2, + 0x6391322257CAE3D49AEF4665D8BD5CCCAC9ABEFB511E83D75F3C766616266FC1BF3747F1DA00ED7125E8F0255A1208087D32A4BC1C743CB6, + ), + ( + 3, + 0x1FBE4B3584CAB86170C14B9325840B8A2429B61FB93C42492C002A2807A4E7EA63138EA59BF95652CE9A7D13D0321C7511E3314D0553F34C, + ), + ( + 4, + 0x93B44A7B78726BA8D0B048BD7144074F8BDAD24EF9D0A6C8264F6C00B135FFCEA11545E80D18364ACC8EBFBCC45358E0DA5FD5E5146E2B1, + ), + ( + 6, + 0x693D165F453BD62871E5E53845F33E9E5B18B24D79C1F9102608AA7BA6F18AC24864012171D64C90B698F5CE5631CD02CEE4E4336B1AD88C, + ), + ( + 9, + 0xB970D576E7D9AA427DBF7CB9B7DD65170721D04EE060C9EA8D499DC361D4CFDE1CEB19068EAE853BAC8F5D92827BDBF3D94C22DE2FB42DAE, + ), + ( + 129, + 0x9FBDB50A1450438FE656AA32AA1BB2548D077D5C3A5D327689093A2996A4F94EACD1FB4F90315EDB2AFE41908A759F0D6DB83FA791DF80DB, + ), + ( + 255, + 0x31BC3E9385DFD12E1238927061EB0C911466DA394E459BF058BA3B08260A258A3C392B0F85DDBD23828657137B88577A85B83774139FAB9E, + ), + ( + 256, + 0x735C7F30E6872E5E4215C0147C8A112D697F668C9BD0F92F5F1E4E6BADC128A0B654E697CD4BAE2144D54E726B54C1FA63A09B00DD3C17F, + ), + ( + 257, + 0x95C1B0CE01286DC047AEB5922A5E62B3EFFB5B9296273A5004EB456F592728DD494A6FB5996A2EA7011AE6423874A48C2927BFA62D8CE8B0, + ), + ( + 0x10101, + 0x113BB172C9DC52AB45BD665DD9751ED44E33B8596F943C6CB2F8DD329160ECE802960B3EB0D2C21EF3A3AC12C20FCCBC2A271FC2F061C1B2, + ), + ( + 0xAA55CC, + 0xCF42585D2E0B1E45C0BFD601C91AF4B137D7FAF139FC761178C7DED432417C307EE1759AF2DEEC6A14DBAF6B868EB13A6039FBDDE4B61898, + ), + ( + 0x1B29A0E579E0A000567, + 0x7BD9EC9775A664F4D860D82D6BE60895113A7C36F92DB25583DBBA5DC17F09C136EC27E14857BFD6A705311327030AA657DD036325FAD330, + ), + (CURVE448_ORDER + 1, 5), ] class TestEccPoint_Curve448(unittest.TestCase): + v1 = 0x09FA78B39B00A72930BCD8039BE789A0997830BB99F79AEEB93493715390B4E8 + v2 = 0x15210F12786811D3F4B7959D0538AE2C31DBE7106FC03C3EFC4CD549C715A493 - v1 = 0x09fa78b39b00a72930bcd8039be789a0997830bb99f79aeeb93493715390b4e8 - v2 = 0x15210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493 + def test_init(self): + EccXPoint(5, "curve448") + EccXPoint(CURVE448_P - 5, "curve448") - def test_init(self): - EccXPoint(5, "curve448") - EccXPoint(CURVE448_P - 5, "curve448") + def test_curve_attribute(self): + point = EccXPoint(5, "curve448") + self.assertEqual(point.curve, "Curve448") - def test_curve_attribute(self): - point = EccXPoint(5, "curve448") - self.assertEqual(point.curve, "Curve448") + def test_init_fail(self): + self.assertRaises(ValueError, EccXPoint, 3 * CURVE448_P, "curve448") + self.assertRaises(ValueError, EccXPoint, 3, "curve449") - def test_init_fail(self): - self.assertRaises(ValueError, EccXPoint, 3*CURVE448_P, "curve448") - self.assertRaises(ValueError, EccXPoint, 3, "curve449") + def test_equal_set(self): + point1 = EccXPoint(self.v1, "curve448") + point2 = EccXPoint(self.v2, "curve448") - def test_equal_set(self): - point1 = EccXPoint(self.v1, "curve448") - point2 = EccXPoint(self.v2, "curve448") + self.assertEqual(point1, point1) + self.assertNotEqual(point1, point2) - self.assertEqual(point1, point1) - self.assertNotEqual(point1, point2) + point2.set(point1) + self.assertEqual(point1.x, point2.x) - point2.set(point1) - self.assertEqual(point1.x, point2.x) + def test_copy(self): + point1 = EccXPoint(self.v1, "curve448") + point2 = point1.copy() + self.assertEqual(point1.x, point2.x) - def test_copy(self): - point1 = EccXPoint(self.v1, "curve448") - point2 = point1.copy() - self.assertEqual(point1.x, point2.x) + def test_pai(self): + point1 = EccXPoint(self.v1, "curve448") + pai = point1.point_at_infinity() + self.assertTrue(pai.point_at_infinity()) - def test_pai(self): - point1 = EccXPoint(self.v1, "curve448") - pai = point1.point_at_infinity() - self.assertTrue(pai.point_at_infinity()) + point2 = EccXPoint(None, "curve448") + self.assertTrue(point2.point_at_infinity()) - point2 = EccXPoint(None, "curve448") - self.assertTrue(point2.point_at_infinity()) + def test_scalar_multiply(self): + base = EccXPoint(5, "curve448") - def test_scalar_multiply(self): - base = EccXPoint(5, "curve448") + pointH = 0 * base + self.assertTrue(pointH.point_at_infinity()) - pointH = 0 * base - self.assertTrue(pointH.point_at_infinity()) + pointH = CURVE448_ORDER * base + self.assertTrue(pointH.point_at_infinity()) - pointH = CURVE448_ORDER * base - self.assertTrue(pointH.point_at_infinity()) + pointH = base * 1 + self.assertEqual(pointH.x, 5) - pointH = base * 1 - self.assertEqual(pointH.x, 5) + for d, result in scalar_base5_test: + pointH = d * base + self.assertEqual(pointH.x, result) - for d, result in scalar_base5_test: - pointH = d * base - self.assertEqual(pointH.x, result) - - def test_sizes(self): - point = EccXPoint(5, "curve448") - self.assertEqual(point.size_in_bits(), 448) - self.assertEqual(point.size_in_bytes(), 56) + def test_sizes(self): + point = EccXPoint(5, "curve448") + self.assertEqual(point.size_in_bits(), 448) + self.assertEqual(point.size_in_bytes(), 56) class TestEccKey_Curve448(unittest.TestCase): - - def test_private_key(self): - # RFC7748 Section 6.2 - Alice - alice_priv = unhexlify("9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b") - alice_pub = unhexlify("9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0") - alice_pub_x = Integer.from_bytes(alice_pub, byteorder='little') - - key = EccKey(curve="Curve448", seed=alice_priv) - self.assertEqual(key.seed, alice_priv) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, alice_pub_x) - - # RFC7748 Section 6.2 - Bob - bob_priv = unhexlify("1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d") - bob_pub = unhexlify("3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609") - bob_pub_x = Integer.from_bytes(bob_pub, byteorder='little') - - key = EccKey(curve="Curve448", seed=bob_priv) - self.assertEqual(key.seed, bob_priv) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, bob_pub_x) - - # Other names - key = EccKey(curve="curve448", seed=alice_priv) - - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="curve448", d=1) - - def test_public_key(self): - point = EccXPoint(_curves['curve448'].Gx, - curve='curve448') - key = EccKey(curve="curve448", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - priv_key = EccKey(curve="curve448", seed=b'H'*56) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_seed(self): - self.assertRaises(ValueError, lambda: EccKey(curve="curve448", - seed=b'H' * 55)) - - def test_equality(self): - private_key = ECC.construct(seed=b'H'*56, curve="Curve448") - private_key2 = ECC.construct(seed=b'H'*56, curve="curve448") - private_key3 = ECC.construct(seed=b'C'*56, curve="Curve448") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='curve448') - self.assertIn("curve='Curve448'", repr(key)) - self.assertEqual(key.curve, 'Curve448') - self.assertEqual(key.public_key().curve, 'Curve448') + def test_private_key(self): + # RFC7748 Section 6.2 - Alice + alice_priv = unhexlify( + "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b" + ) + alice_pub = unhexlify( + "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0" + ) + alice_pub_x = Integer.from_bytes(alice_pub, byteorder="little") + + key = EccKey(curve="Curve448", seed=alice_priv) + self.assertEqual(key.seed, alice_priv) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, alice_pub_x) + + # RFC7748 Section 6.2 - Bob + bob_priv = unhexlify( + "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d" + ) + bob_pub = unhexlify( + "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609" + ) + bob_pub_x = Integer.from_bytes(bob_pub, byteorder="little") + + key = EccKey(curve="Curve448", seed=bob_priv) + self.assertEqual(key.seed, bob_priv) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, bob_pub_x) + + # Other names + key = EccKey(curve="curve448", seed=alice_priv) + + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="curve448", d=1) + + def test_public_key(self): + point = EccXPoint( + _curves["curve448"].Gx, + curve="curve448", + ) + key = EccKey(curve="curve448", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="curve448", seed=b"H" * 56) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_seed(self): + self.assertRaises( + ValueError, + lambda: EccKey( + curve="curve448", + seed=b"H" * 55, + ), + ) + + def test_equality(self): + private_key = ECC.construct(seed=b"H" * 56, curve="Curve448") + private_key2 = ECC.construct(seed=b"H" * 56, curve="curve448") + private_key3 = ECC.construct(seed=b"C" * 56, curve="Curve448") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="curve448") + self.assertIn("curve='Curve448'", repr(key)) + self.assertEqual(key.curve, "Curve448") + self.assertEqual(key.public_key().curve, "Curve448") class TestEccModule_Curve448(unittest.TestCase): - - def test_generate(self): - key = ECC.generate(curve="Curve448") - self.assertTrue(key.has_private()) - point = EccXPoint(_curves['Curve448'].Gx, curve="Curve448") * key.d - self.assertEqual(key.pointQ, point) - - # Always random - key2 = ECC.generate(curve="Curve448") - self.assertNotEqual(key, key2) - - # Other names - ECC.generate(curve="curve448") - - # Random source - key1 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read) - key2 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read) - self.assertEqual(key1, key2) - - def test_construct(self): - seed = unhexlify("9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b") - point_hex = unhexlify("9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0") - Px = Integer.from_bytes(point_hex, byteorder='little') - point = EccXPoint(Px, curve="Curve448") - - # Private key only - key = ECC.construct(curve="Curve448", seed=seed) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Public key only - key = ECC.construct(curve="Curve448", point_x=Px) - self.assertEqual(key.pointQ, point) - self.assertFalse(key.has_private()) - - # Private and public key - key = ECC.construct(curve="Curve448", seed=seed, point_x=Px) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Other names - key = ECC.construct(curve="curve448", seed=seed) - - def test_negative_construct(self): - coordG = dict(point_x=_curves['curve448'].Gx) - - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - d=2, **coordG) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - seed=b'H'*55) - - # Verify you cannot construct weak keys (small-order points) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=0) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=1) - p = 2**448 - 2**224 - 1 - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=p-1) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=p) - self.assertRaises(ValueError, ECC.construct, curve="Curve448", - point_x=p+1) + def test_generate(self): + key = ECC.generate(curve="Curve448") + self.assertTrue(key.has_private()) + point = EccXPoint(_curves["Curve448"].Gx, curve="Curve448") * key.d + self.assertEqual(key.pointQ, point) + + # Always random + key2 = ECC.generate(curve="Curve448") + self.assertNotEqual(key, key2) + + # Other names + ECC.generate(curve="curve448") + + # Random source + key1 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read) + key2 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read) + self.assertEqual(key1, key2) + + def test_construct(self): + seed = unhexlify( + "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b" + ) + point_hex = unhexlify( + "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0" + ) + Px = Integer.from_bytes(point_hex, byteorder="little") + point = EccXPoint(Px, curve="Curve448") + + # Private key only + key = ECC.construct(curve="Curve448", seed=seed) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Public key only + key = ECC.construct(curve="Curve448", point_x=Px) + self.assertEqual(key.pointQ, point) + self.assertFalse(key.has_private()) + + # Private and public key + key = ECC.construct(curve="Curve448", seed=seed, point_x=Px) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Other names + key = ECC.construct(curve="curve448", seed=seed) + + def test_negative_construct(self): + coordG = dict(point_x=_curves["curve448"].Gx) + + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + d=2, + **coordG, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + seed=b"H" * 55, + ) + + # Verify you cannot construct weak keys (small-order points) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=0, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=1, + ) + p = 2**448 - 2**224 - 1 + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=p - 1, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=p, + ) + self.assertRaises( + ValueError, + ECC.construct, + curve="Curve448", + point_x=p + 1, + ) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint_Curve448) - tests += list_test_cases(TestEccKey_Curve448) - tests += list_test_cases(TestEccModule_Curve448) - return tests + tests = [] + tests += list_test_cases(TestEccPoint_Curve448) + tests += list_test_cases(TestEccKey_Curve448) + tests += list_test_cases(TestEccModule_Curve448) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Ed25519.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Ed25519.py index 5018552c..03b72f9d 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Ed25519.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Ed25519.py @@ -32,310 +32,339 @@ from binascii import unhexlify from Cryptodome.SelfTest.st_common import list_test_cases -from Cryptodome.SelfTest.loader import load_test_vectors from Cryptodome.PublicKey import ECC from Cryptodome.PublicKey.ECC import EccPoint, _curves, EccKey -from Cryptodome.Math.Numbers import Integer from Cryptodome.Hash import SHAKE128 class TestEccPoint_Ed25519(unittest.TestCase): - - Gxy = {"x": 15112221349535400772501151409588531511454012693041857206046113283949847762202, - "y": 46316835694926478169428394003475163141307993866256225615783033603165251855960} - - G2xy = {"x": 24727413235106541002554574571675588834622768167397638456726423682521233608206, - "y": 15549675580280190176352668710449542251549572066445060580507079593062643049417} - - G3xy = {"x": 46896733464454938657123544595386787789046198280132665686241321779790909858396, - "y": 8324843778533443976490377120369201138301417226297555316741202210403726505172} - - pointG = EccPoint(Gxy['x'], Gxy['y'], curve="ed25519") - pointG2 = EccPoint(G2xy['x'], G2xy['y'], curve="ed25519") - pointG3 = EccPoint(G3xy['x'], G3xy['y'], curve="ed25519") - - def test_curve_attribute(self): - self.assertEqual(self.pointG.curve, "Ed25519") - - def test_init_xy(self): - EccPoint(self.Gxy['x'], self.Gxy['y'], curve="Ed25519") - - # Neutral point - pai = EccPoint(0, 1, curve="Ed25519") - self.assertEqual(pai.x, 0) - self.assertEqual(pai.y, 1) - self.assertEqual(pai.xy, (0, 1)) - - # G - bp = self.pointG.copy() - self.assertEqual(bp.x, 15112221349535400772501151409588531511454012693041857206046113283949847762202) - self.assertEqual(bp.y, 46316835694926478169428394003475163141307993866256225615783033603165251855960) - self.assertEqual(bp.xy, (bp.x, bp.y)) - - # 2G - bp2 = self.pointG2.copy() - self.assertEqual(bp2.x, 24727413235106541002554574571675588834622768167397638456726423682521233608206) - self.assertEqual(bp2.y, 15549675580280190176352668710449542251549572066445060580507079593062643049417) - self.assertEqual(bp2.xy, (bp2.x, bp2.y)) - - # 5G - EccPoint(x=33467004535436536005251147249499675200073690106659565782908757308821616914995, - y=43097193783671926753355113395909008640284023746042808659097434958891230611693, - curve="Ed25519") - - # Catch if point is not on the curve - self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed25519") - - def test_set(self): - pointW = EccPoint(0, 1, curve="Ed25519") - pointW.set(self.pointG) - self.assertEqual(pointW.x, self.pointG.x) - self.assertEqual(pointW.y, self.pointG.y) - - def test_copy(self): - pointW = self.pointG.copy() - self.assertEqual(pointW.x, self.pointG.x) - self.assertEqual(pointW.y, self.pointG.y) - - def test_equal(self): - pointH = self.pointG.copy() - pointI = self.pointG2.copy() - self.assertEqual(self.pointG, pointH) - self.assertNotEqual(self.pointG, pointI) - - def test_pai(self): - pai = EccPoint(0, 1, curve="Ed25519") - self.assertTrue(pai.is_point_at_infinity()) - self.assertEqual(pai, pai.point_at_infinity()) - - def test_negate(self): - negG = -self.pointG - G100 = self.pointG * 100 - sum_zero = G100 + negG * 100 - self.assertTrue(sum_zero.is_point_at_infinity()) - - sum_99 = G100 + negG - expected = self.pointG * 99 - self.assertEqual(sum_99, expected) - - def test_addition(self): - self.assertEqual(self.pointG + self.pointG2, self.pointG3) - self.assertEqual(self.pointG2 + self.pointG, self.pointG3) - self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2) - self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2) - - G5 = self.pointG2 + self.pointG3 - self.assertEqual(G5.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995) - self.assertEqual(G5.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693) - - def test_inplace_addition(self): - pointH = self.pointG.copy() - pointH += self.pointG - self.assertEqual(pointH, self.pointG2) - pointH += self.pointG - self.assertEqual(pointH, self.pointG3) - pointH += self.pointG.point_at_infinity() - self.assertEqual(pointH, self.pointG3) - - def test_doubling(self): - pointH = self.pointG.copy() - pointH.double() - self.assertEqual(pointH.x, self.pointG2.x) - self.assertEqual(pointH.y, self.pointG2.y) - - # 2*0 - pai = self.pointG.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - def test_scalar_multiply(self): - d = 0 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0) - self.assertEqual(pointH.y, 1) - - d = 1 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG.x) - self.assertEqual(pointH.y, self.pointG.y) - - d = 2 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG2.x) - self.assertEqual(pointH.y, self.pointG2.y) - - d = 3 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG3.x) - self.assertEqual(pointH.y, self.pointG3.y) - - d = 4 - pointH = d * self.pointG - self.assertEqual(pointH.x, 14582954232372986451776170844943001818709880559417862259286374126315108956272) - self.assertEqual(pointH.y, 32483318716863467900234833297694612235682047836132991208333042722294373421359) - - d = 5 - pointH = d * self.pointG - self.assertEqual(pointH.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995) - self.assertEqual(pointH.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693) - - d = 10 - pointH = d * self.pointG - self.assertEqual(pointH.x, 43500613248243327786121022071801015118933854441360174117148262713429272820047) - self.assertEqual(pointH.y, 45005105423099817237495816771148012388779685712352441364231470781391834741548) - - d = 20 - pointH = d * self.pointG - self.assertEqual(pointH.x, 46694936775300686710656303283485882876784402425210400817529601134760286812591) - self.assertEqual(pointH.y, 8786390172762935853260670851718824721296437982862763585171334833968259029560) - - d = 255 - pointH = d * self.pointG - self.assertEqual(pointH.x, 36843863416400016952258312492144504209624961884991522125275155377549541182230) - self.assertEqual(pointH.y, 22327030283879720808995671630924669697661065034121040761798775626517750047180) - - d = 256 - pointH = d * self.pointG - self.assertEqual(pointH.x, 42740085206947573681423002599456489563927820004573071834350074001818321593686) - self.assertEqual(pointH.y, 6935684722522267618220753829624209639984359598320562595061366101608187623111) - - def test_sizes(self): - self.assertEqual(self.pointG.size_in_bits(), 255) - self.assertEqual(self.pointG.size_in_bytes(), 32) + Gxy = { + "x": 15112221349535400772501151409588531511454012693041857206046113283949847762202, + "y": 46316835694926478169428394003475163141307993866256225615783033603165251855960, + } + + G2xy = { + "x": 24727413235106541002554574571675588834622768167397638456726423682521233608206, + "y": 15549675580280190176352668710449542251549572066445060580507079593062643049417, + } + + G3xy = { + "x": 46896733464454938657123544595386787789046198280132665686241321779790909858396, + "y": 8324843778533443976490377120369201138301417226297555316741202210403726505172, + } + + pointG = EccPoint(Gxy["x"], Gxy["y"], curve="ed25519") + pointG2 = EccPoint(G2xy["x"], G2xy["y"], curve="ed25519") + pointG3 = EccPoint(G3xy["x"], G3xy["y"], curve="ed25519") + + def test_curve_attribute(self): + self.assertEqual(self.pointG.curve, "Ed25519") + + def test_init_xy(self): + EccPoint(self.Gxy["x"], self.Gxy["y"], curve="Ed25519") + + # Neutral point + pai = EccPoint(0, 1, curve="Ed25519") + self.assertEqual(pai.x, 0) + self.assertEqual(pai.y, 1) + self.assertEqual(pai.xy, (0, 1)) + + # G + bp = self.pointG.copy() + self.assertEqual(bp.x, 15112221349535400772501151409588531511454012693041857206046113283949847762202) + self.assertEqual(bp.y, 46316835694926478169428394003475163141307993866256225615783033603165251855960) + self.assertEqual(bp.xy, (bp.x, bp.y)) + + # 2G + bp2 = self.pointG2.copy() + self.assertEqual(bp2.x, 24727413235106541002554574571675588834622768167397638456726423682521233608206) + self.assertEqual(bp2.y, 15549675580280190176352668710449542251549572066445060580507079593062643049417) + self.assertEqual(bp2.xy, (bp2.x, bp2.y)) + + # 5G + EccPoint( + x=33467004535436536005251147249499675200073690106659565782908757308821616914995, + y=43097193783671926753355113395909008640284023746042808659097434958891230611693, + curve="Ed25519", + ) + + # Catch if point is not on the curve + self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed25519") + + def test_set(self): + pointW = EccPoint(0, 1, curve="Ed25519") + pointW.set(self.pointG) + self.assertEqual(pointW.x, self.pointG.x) + self.assertEqual(pointW.y, self.pointG.y) + + def test_copy(self): + pointW = self.pointG.copy() + self.assertEqual(pointW.x, self.pointG.x) + self.assertEqual(pointW.y, self.pointG.y) + + def test_equal(self): + pointH = self.pointG.copy() + pointI = self.pointG2.copy() + self.assertEqual(self.pointG, pointH) + self.assertNotEqual(self.pointG, pointI) + + def test_pai(self): + pai = EccPoint(0, 1, curve="Ed25519") + self.assertTrue(pai.is_point_at_infinity()) + self.assertEqual(pai, pai.point_at_infinity()) + + def test_negate(self): + negG = -self.pointG + G100 = self.pointG * 100 + sum_zero = G100 + negG * 100 + self.assertTrue(sum_zero.is_point_at_infinity()) + + sum_99 = G100 + negG + expected = self.pointG * 99 + self.assertEqual(sum_99, expected) + + def test_addition(self): + self.assertEqual(self.pointG + self.pointG2, self.pointG3) + self.assertEqual(self.pointG2 + self.pointG, self.pointG3) + self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2) + self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2) + + G5 = self.pointG2 + self.pointG3 + self.assertEqual(G5.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995) + self.assertEqual(G5.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693) + + def test_inplace_addition(self): + pointH = self.pointG.copy() + pointH += self.pointG + self.assertEqual(pointH, self.pointG2) + pointH += self.pointG + self.assertEqual(pointH, self.pointG3) + pointH += self.pointG.point_at_infinity() + self.assertEqual(pointH, self.pointG3) + + def test_doubling(self): + pointH = self.pointG.copy() + pointH.double() + self.assertEqual(pointH.x, self.pointG2.x) + self.assertEqual(pointH.y, self.pointG2.y) + + # 2*0 + pai = self.pointG.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + def test_scalar_multiply(self): + d = 0 + pointH = d * self.pointG + self.assertEqual(pointH.x, 0) + self.assertEqual(pointH.y, 1) + + d = 1 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG.x) + self.assertEqual(pointH.y, self.pointG.y) + + d = 2 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG2.x) + self.assertEqual(pointH.y, self.pointG2.y) + + d = 3 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG3.x) + self.assertEqual(pointH.y, self.pointG3.y) + + d = 4 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 14582954232372986451776170844943001818709880559417862259286374126315108956272 + ) + self.assertEqual( + pointH.y, 32483318716863467900234833297694612235682047836132991208333042722294373421359 + ) + + d = 5 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995 + ) + self.assertEqual( + pointH.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693 + ) + + d = 10 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 43500613248243327786121022071801015118933854441360174117148262713429272820047 + ) + self.assertEqual( + pointH.y, 45005105423099817237495816771148012388779685712352441364231470781391834741548 + ) + + d = 20 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 46694936775300686710656303283485882876784402425210400817529601134760286812591 + ) + self.assertEqual( + pointH.y, 8786390172762935853260670851718824721296437982862763585171334833968259029560 + ) + + d = 255 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 36843863416400016952258312492144504209624961884991522125275155377549541182230 + ) + self.assertEqual( + pointH.y, 22327030283879720808995671630924669697661065034121040761798775626517750047180 + ) + + d = 256 + pointH = d * self.pointG + self.assertEqual( + pointH.x, 42740085206947573681423002599456489563927820004573071834350074001818321593686 + ) + self.assertEqual( + pointH.y, 6935684722522267618220753829624209639984359598320562595061366101608187623111 + ) + + def test_sizes(self): + self.assertEqual(self.pointG.size_in_bits(), 255) + self.assertEqual(self.pointG.size_in_bytes(), 32) class TestEccKey_Ed25519(unittest.TestCase): + def test_private_key(self): + seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") + Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046 + Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807 - def test_private_key(self): - seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") - Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046 - Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807 - - key = EccKey(curve="Ed25519", seed=seed) - self.assertEqual(key.seed, seed) - self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, Px) - self.assertEqual(key.pointQ.y, Py) + key = EccKey(curve="Ed25519", seed=seed) + self.assertEqual(key.seed, seed) + self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, Px) + self.assertEqual(key.pointQ.y, Py) - point = EccPoint(Px, Py, "ed25519") - key = EccKey(curve="Ed25519", seed=seed, point=point) - self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) + point = EccPoint(Px, Py, "ed25519") + key = EccKey(curve="Ed25519", seed=seed, point=point) + self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) - # Other names - key = EccKey(curve="ed25519", seed=seed) + # Other names + key = EccKey(curve="ed25519", seed=seed) - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="ed25519", d=1) + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="ed25519", d=1) - def test_public_key(self): - point = EccPoint(_curves['ed25519'].Gx, _curves['ed25519'].Gy, curve='ed25519') - key = EccKey(curve="ed25519", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) + def test_public_key(self): + point = EccPoint(_curves["ed25519"].Gx, _curves["ed25519"].Gy, curve="ed25519") + key = EccKey(curve="ed25519", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) - def test_public_key_derived(self): - priv_key = EccKey(curve="ed25519", seed=b'H'*32) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) + def test_public_key_derived(self): + priv_key = EccKey(curve="ed25519", seed=b"H" * 32) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) - def test_invalid_seed(self): - self.assertRaises(ValueError, lambda: EccKey(curve="ed25519", seed=b'H' * 31)) + def test_invalid_seed(self): + self.assertRaises(ValueError, lambda: EccKey(curve="ed25519", seed=b"H" * 31)) - def test_equality(self): - private_key = ECC.construct(seed=b'H'*32, curve="Ed25519") - private_key2 = ECC.construct(seed=b'H'*32, curve="ed25519") - private_key3 = ECC.construct(seed=b'C'*32, curve="Ed25519") + def test_equality(self): + private_key = ECC.construct(seed=b"H" * 32, curve="Ed25519") + private_key2 = ECC.construct(seed=b"H" * 32, curve="ed25519") + private_key3 = ECC.construct(seed=b"C" * 32, curve="Ed25519") - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) - self.assertNotEqual(public_key, private_key) + self.assertNotEqual(public_key, private_key) - def test_name_consistency(self): - key = ECC.generate(curve='ed25519') - self.assertIn("curve='Ed25519'", repr(key)) - self.assertEqual(key.curve, 'Ed25519') - self.assertEqual(key.public_key().curve, 'Ed25519') + def test_name_consistency(self): + key = ECC.generate(curve="ed25519") + self.assertIn("curve='Ed25519'", repr(key)) + self.assertEqual(key.curve, "Ed25519") + self.assertEqual(key.public_key().curve, "Ed25519") class TestEccModule_Ed25519(unittest.TestCase): + def test_generate(self): + key = ECC.generate(curve="Ed25519") + self.assertTrue(key.has_private()) + point = EccPoint(_curves["Ed25519"].Gx, _curves["Ed25519"].Gy, curve="Ed25519") * key.d + self.assertEqual(key.pointQ, point) + + # Always random + key2 = ECC.generate(curve="Ed25519") + self.assertNotEqual(key, key2) + + # Other names + ECC.generate(curve="Ed25519") + + # Random source + key1 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read) + key2 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read) + self.assertEqual(key1, key2) + + def test_construct(self): + seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") + Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046 + Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807 + d = 36144925721603087658594284515452164870581325872720374094707712194495455132720 + point = EccPoint(Px, Py, curve="Ed25519") + + # Private key only + key = ECC.construct(curve="Ed25519", seed=seed) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Public key only + key = ECC.construct(curve="Ed25519", point_x=Px, point_y=Py) + self.assertEqual(key.pointQ, point) + self.assertFalse(key.has_private()) + + # Private and public key + key = ECC.construct(curve="Ed25519", seed=seed, point_x=Px, point_y=Py) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Other names + key = ECC.construct(curve="ed25519", seed=seed) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["ed25519"].Gx, point_y=_curves["ed25519"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="Ed25519", **coord) + self.assertRaises(ValueError, ECC.construct, curve="Ed25519", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="Ed25519", seed=b"H" * 31) - def test_generate(self): - key = ECC.generate(curve="Ed25519") - self.assertTrue(key.has_private()) - point = EccPoint(_curves['Ed25519'].Gx, _curves['Ed25519'].Gy, curve="Ed25519") * key.d - self.assertEqual(key.pointQ, point) - - # Always random - key2 = ECC.generate(curve="Ed25519") - self.assertNotEqual(key, key2) - - # Other names - ECC.generate(curve="Ed25519") - - # Random source - key1 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read) - key2 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read) - self.assertEqual(key1, key2) - - def test_construct(self): - seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") - Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046 - Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807 - d = 36144925721603087658594284515452164870581325872720374094707712194495455132720 - point = EccPoint(Px, Py, curve="Ed25519") - - # Private key only - key = ECC.construct(curve="Ed25519", seed=seed) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - # Public key only - key = ECC.construct(curve="Ed25519", point_x=Px, point_y=Py) - self.assertEqual(key.pointQ, point) - self.assertFalse(key.has_private()) - - # Private and public key - key = ECC.construct(curve="Ed25519", seed=seed, point_x=Px, point_y=Py) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Other names - key = ECC.construct(curve="ed25519", seed=seed) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['ed25519'].Gx, point_y=_curves['ed25519'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="Ed25519", **coord) - self.assertRaises(ValueError, ECC.construct, curve="Ed25519", d=2, **coordG) - self.assertRaises(ValueError, ECC.construct, curve="Ed25519", seed=b'H'*31) +def get_tests(config={}): + tests = [] + tests += list_test_cases(TestEccPoint_Ed25519) + tests += list_test_cases(TestEccKey_Ed25519) + tests += list_test_cases(TestEccModule_Ed25519) + return tests -def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint_Ed25519) - tests += list_test_cases(TestEccKey_Ed25519) - tests += list_test_cases(TestEccModule_Ed25519) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Ed448.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Ed448.py index 3a7b0eb8..4b0212c9 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Ed448.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_Ed448.py @@ -32,305 +32,374 @@ from binascii import unhexlify from Cryptodome.SelfTest.st_common import list_test_cases -from Cryptodome.SelfTest.loader import load_test_vectors from Cryptodome.PublicKey import ECC from Cryptodome.PublicKey.ECC import EccPoint, _curves, EccKey -from Cryptodome.Math.Numbers import Integer from Cryptodome.Hash import SHAKE128 class TestEccPoint_Ed448(unittest.TestCase): - - Gxy = {"x": 0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e, - "y": 0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14} - - G2xy = {"x": 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555, - "y": 0xae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed} - - G3xy = {"x": 0x865886b9108af6455bd64316cb6943332241b8b8cda82c7e2ba077a4a3fcfe8daa9cbf7f6271fd6e862b769465da8575728173286ff2f8f, - "y": 0xe005a8dbd5125cf706cbda7ad43aa6449a4a8d952356c3b9fce43c82ec4e1d58bb3a331bdb6767f0bffa9a68fed02dafb822ac13588ed6fc} - - pointG = EccPoint(Gxy['x'], Gxy['y'], curve="ed448") - pointG2 = EccPoint(G2xy['x'], G2xy['y'], curve="ed448") - pointG3 = EccPoint(G3xy['x'], G3xy['y'], curve="ed448") - - def test_curve_attribute(self): - self.assertEqual(self.pointG.curve, "Ed448") - - def test_init_xy(self): - EccPoint(self.Gxy['x'], self.Gxy['y'], curve="Ed448") - - # Neutral point - pai = EccPoint(0, 1, curve="Ed448") - self.assertEqual(pai.x, 0) - self.assertEqual(pai.y, 1) - self.assertEqual(pai.xy, (0, 1)) - - # G - bp = self.pointG.copy() - self.assertEqual(bp.x, 0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e) - self.assertEqual(bp.y, 0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14) - self.assertEqual(bp.xy, (bp.x, bp.y)) - - # 2G - bp2 = self.pointG2.copy() - self.assertEqual(bp2.x, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555) - self.assertEqual(bp2.y, 0xae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed) - self.assertEqual(bp2.xy, (bp2.x, bp2.y)) - - # 5G - EccPoint(x=0x7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034, - y=0xadfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb, - curve="Ed448") - - # Catch if point is not on the curve - self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed448") - - def test_set(self): - pointW = EccPoint(0, 1, curve="Ed448") - pointW.set(self.pointG) - self.assertEqual(pointW.x, self.pointG.x) - self.assertEqual(pointW.y, self.pointG.y) - - def test_copy(self): - pointW = self.pointG.copy() - self.assertEqual(pointW.x, self.pointG.x) - self.assertEqual(pointW.y, self.pointG.y) - - def test_equal(self): - pointH = self.pointG.copy() - pointI = self.pointG2.copy() - self.assertEqual(self.pointG, pointH) - self.assertNotEqual(self.pointG, pointI) - - def test_pai(self): - pai = EccPoint(0, 1, curve="Ed448") - self.assertTrue(pai.is_point_at_infinity()) - self.assertEqual(pai, pai.point_at_infinity()) - - def test_negate(self): - negG = -self.pointG - sum = self.pointG + negG - self.assertTrue(sum.is_point_at_infinity()) - - def test_addition(self): - self.assertEqual(self.pointG + self.pointG2, self.pointG3) - self.assertEqual(self.pointG2 + self.pointG, self.pointG3) - self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2) - self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2) - - G5 = self.pointG2 + self.pointG3 - self.assertEqual(G5.x, 0x7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034) - self.assertEqual(G5.y, 0xadfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb) - - def test_inplace_addition(self): - pointH = self.pointG.copy() - pointH += self.pointG - self.assertEqual(pointH, self.pointG2) - pointH += self.pointG - self.assertEqual(pointH, self.pointG3) - pointH += self.pointG.point_at_infinity() - self.assertEqual(pointH, self.pointG3) - - def test_doubling(self): - pointH = self.pointG.copy() - pointH.double() - self.assertEqual(pointH.x, self.pointG2.x) - self.assertEqual(pointH.y, self.pointG2.y) - - # 2*0 - pai = self.pointG.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - def test_scalar_multiply(self): - d = 0 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0) - self.assertEqual(pointH.y, 1) - - d = 1 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG.x) - self.assertEqual(pointH.y, self.pointG.y) - - d = 2 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG2.x) - self.assertEqual(pointH.y, self.pointG2.y) - - d = 3 - pointH = d * self.pointG - self.assertEqual(pointH.x, self.pointG3.x) - self.assertEqual(pointH.y, self.pointG3.y) - - d = 4 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0x49dcbc5c6c0cce2c1419a17226f929ea255a09cf4e0891c693fda4be70c74cc301b7bdf1515dd8ba21aee1798949e120e2ce42ac48ba7f30) - self.assertEqual(pointH.y, 0xd49077e4accde527164b33a5de021b979cb7c02f0457d845c90dc3227b8a5bc1c0d8f97ea1ca9472b5d444285d0d4f5b32e236f86de51839) - - d = 5 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0x7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034) - self.assertEqual(pointH.y, 0xadfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb) - - d = 10 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0x77486f9d19f6411cdd35d30d1c3235f71936452c787e5c034134d3e8172278aca61622bc805761ce3dab65118a0122d73b403165d0ed303d) - self.assertEqual(pointH.y, 0x4d2fea0b026be11024f1f0fe7e94e618e8ac17381ada1d1bf7ee293a68ff5d0bf93c1997dc1aabdc0c7e6381428d85b6b1954a89e4cddf67) - - d = 20 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0x3c236422354600fe6763defcc1503737e4ed89e262d0de3ec1e552020f2a56fe3b9e1e012d021072598c3c2821e18268bb8fb8339c0d1216) - self.assertEqual(pointH.y, 0xb555b9721f630ccb05fc466de4c74d3d2781e69eca88e1b040844f04cab39fd946f91c688fa42402bb38fb9c3e61231017020b219b4396e1) - - d = 255 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0xbeb7f8388b05cd9c1aa2e3c0dcf31e2b563659361826225390e7748654f627d5c36cbe627e9019936b56d15d4dad7c337c09bac64ff4197f) - self.assertEqual(pointH.y, 0x1e37312b2dd4e9440c43c6e7725fc4fa3d11e582d4863f1d018e28f50c0efdb1f53f9b01ada7c87fa162b1f0d72401015d57613d25f1ad53) - - d = 256 - pointH = d * self.pointG - self.assertEqual(pointH.x, 0xf19c34feb56730e3e2be761ac0a2a2b24853b281dda019fc35a5ab58e3696beb39609ae756b0d20fb7ccf0d79aaf5f3bca2e4fdb25bfac1c) - self.assertEqual(pointH.y, 0x3beb69cc9111bffcaddc61d363ce6fe5dd44da4aadce78f52e92e985d5442344ced72c4611ed0daac9f4f5661eab73d7a12d25ce8a30241e) - - def test_sizes(self): - self.assertEqual(self.pointG.size_in_bits(), 448) - self.assertEqual(self.pointG.size_in_bytes(), 56) + Gxy = { + "x": 0x4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E, + "y": 0x693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14, + } + + G2xy = { + "x": 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA955555555555555555555555555555555555555555555555555555555, + "y": 0xAE05E9634AD7048DB359D6205086C2B0036ED7A035884DD7B7E36D728AD8C4B80D6565833A2A3098BBBCB2BED1CDA06BDAEAFBCDEA9386ED, + } + + G3xy = { + "x": 0x865886B9108AF6455BD64316CB6943332241B8B8CDA82C7E2BA077A4A3FCFE8DAA9CBF7F6271FD6E862B769465DA8575728173286FF2F8F, + "y": 0xE005A8DBD5125CF706CBDA7AD43AA6449A4A8D952356C3B9FCE43C82EC4E1D58BB3A331BDB6767F0BFFA9A68FED02DAFB822AC13588ED6FC, + } + + pointG = EccPoint(Gxy["x"], Gxy["y"], curve="ed448") + pointG2 = EccPoint(G2xy["x"], G2xy["y"], curve="ed448") + pointG3 = EccPoint(G3xy["x"], G3xy["y"], curve="ed448") + + def test_curve_attribute(self): + self.assertEqual(self.pointG.curve, "Ed448") + + def test_init_xy(self): + EccPoint(self.Gxy["x"], self.Gxy["y"], curve="Ed448") + + # Neutral point + pai = EccPoint(0, 1, curve="Ed448") + self.assertEqual(pai.x, 0) + self.assertEqual(pai.y, 1) + self.assertEqual(pai.xy, (0, 1)) + + # G + bp = self.pointG.copy() + self.assertEqual( + bp.x, + 0x4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E, + ) + self.assertEqual( + bp.y, + 0x693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14, + ) + self.assertEqual(bp.xy, (bp.x, bp.y)) + + # 2G + bp2 = self.pointG2.copy() + self.assertEqual( + bp2.x, + 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA955555555555555555555555555555555555555555555555555555555, + ) + self.assertEqual( + bp2.y, + 0xAE05E9634AD7048DB359D6205086C2B0036ED7A035884DD7B7E36D728AD8C4B80D6565833A2A3098BBBCB2BED1CDA06BDAEAFBCDEA9386ED, + ) + self.assertEqual(bp2.xy, (bp2.x, bp2.y)) + + # 5G + EccPoint( + x=0x7A9F9335A48DCB0E2BA7601EEDB50DEF80CBCF728562ADA756D761E8958812808BC0D57A920C3C96F07B2D8CEFC6F950D0A99D1092030034, + y=0xADFD751A2517EDD3B9109CE4FD580ADE260CA1823AB18FCED86551F7B698017127D7A4EE59D2B33C58405512881F225443B4731472F435EB, + curve="Ed448", + ) + + # Catch if point is not on the curve + self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed448") + + def test_set(self): + pointW = EccPoint(0, 1, curve="Ed448") + pointW.set(self.pointG) + self.assertEqual(pointW.x, self.pointG.x) + self.assertEqual(pointW.y, self.pointG.y) + + def test_copy(self): + pointW = self.pointG.copy() + self.assertEqual(pointW.x, self.pointG.x) + self.assertEqual(pointW.y, self.pointG.y) + + def test_equal(self): + pointH = self.pointG.copy() + pointI = self.pointG2.copy() + self.assertEqual(self.pointG, pointH) + self.assertNotEqual(self.pointG, pointI) + + def test_pai(self): + pai = EccPoint(0, 1, curve="Ed448") + self.assertTrue(pai.is_point_at_infinity()) + self.assertEqual(pai, pai.point_at_infinity()) + + def test_negate(self): + negG = -self.pointG + sum = self.pointG + negG + self.assertTrue(sum.is_point_at_infinity()) + + def test_addition(self): + self.assertEqual(self.pointG + self.pointG2, self.pointG3) + self.assertEqual(self.pointG2 + self.pointG, self.pointG3) + self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2) + self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2) + + G5 = self.pointG2 + self.pointG3 + self.assertEqual( + G5.x, + 0x7A9F9335A48DCB0E2BA7601EEDB50DEF80CBCF728562ADA756D761E8958812808BC0D57A920C3C96F07B2D8CEFC6F950D0A99D1092030034, + ) + self.assertEqual( + G5.y, + 0xADFD751A2517EDD3B9109CE4FD580ADE260CA1823AB18FCED86551F7B698017127D7A4EE59D2B33C58405512881F225443B4731472F435EB, + ) + + def test_inplace_addition(self): + pointH = self.pointG.copy() + pointH += self.pointG + self.assertEqual(pointH, self.pointG2) + pointH += self.pointG + self.assertEqual(pointH, self.pointG3) + pointH += self.pointG.point_at_infinity() + self.assertEqual(pointH, self.pointG3) + + def test_doubling(self): + pointH = self.pointG.copy() + pointH.double() + self.assertEqual(pointH.x, self.pointG2.x) + self.assertEqual(pointH.y, self.pointG2.y) + + # 2*0 + pai = self.pointG.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + def test_scalar_multiply(self): + d = 0 + pointH = d * self.pointG + self.assertEqual(pointH.x, 0) + self.assertEqual(pointH.y, 1) + + d = 1 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG.x) + self.assertEqual(pointH.y, self.pointG.y) + + d = 2 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG2.x) + self.assertEqual(pointH.y, self.pointG2.y) + + d = 3 + pointH = d * self.pointG + self.assertEqual(pointH.x, self.pointG3.x) + self.assertEqual(pointH.y, self.pointG3.y) + + d = 4 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0x49DCBC5C6C0CCE2C1419A17226F929EA255A09CF4E0891C693FDA4BE70C74CC301B7BDF1515DD8BA21AEE1798949E120E2CE42AC48BA7F30, + ) + self.assertEqual( + pointH.y, + 0xD49077E4ACCDE527164B33A5DE021B979CB7C02F0457D845C90DC3227B8A5BC1C0D8F97EA1CA9472B5D444285D0D4F5B32E236F86DE51839, + ) + + d = 5 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0x7A9F9335A48DCB0E2BA7601EEDB50DEF80CBCF728562ADA756D761E8958812808BC0D57A920C3C96F07B2D8CEFC6F950D0A99D1092030034, + ) + self.assertEqual( + pointH.y, + 0xADFD751A2517EDD3B9109CE4FD580ADE260CA1823AB18FCED86551F7B698017127D7A4EE59D2B33C58405512881F225443B4731472F435EB, + ) + + d = 10 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0x77486F9D19F6411CDD35D30D1C3235F71936452C787E5C034134D3E8172278ACA61622BC805761CE3DAB65118A0122D73B403165D0ED303D, + ) + self.assertEqual( + pointH.y, + 0x4D2FEA0B026BE11024F1F0FE7E94E618E8AC17381ADA1D1BF7EE293A68FF5D0BF93C1997DC1AABDC0C7E6381428D85B6B1954A89E4CDDF67, + ) + + d = 20 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0x3C236422354600FE6763DEFCC1503737E4ED89E262D0DE3EC1E552020F2A56FE3B9E1E012D021072598C3C2821E18268BB8FB8339C0D1216, + ) + self.assertEqual( + pointH.y, + 0xB555B9721F630CCB05FC466DE4C74D3D2781E69ECA88E1B040844F04CAB39FD946F91C688FA42402BB38FB9C3E61231017020B219B4396E1, + ) + + d = 255 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0xBEB7F8388B05CD9C1AA2E3C0DCF31E2B563659361826225390E7748654F627D5C36CBE627E9019936B56D15D4DAD7C337C09BAC64FF4197F, + ) + self.assertEqual( + pointH.y, + 0x1E37312B2DD4E9440C43C6E7725FC4FA3D11E582D4863F1D018E28F50C0EFDB1F53F9B01ADA7C87FA162B1F0D72401015D57613D25F1AD53, + ) + + d = 256 + pointH = d * self.pointG + self.assertEqual( + pointH.x, + 0xF19C34FEB56730E3E2BE761AC0A2A2B24853B281DDA019FC35A5AB58E3696BEB39609AE756B0D20FB7CCF0D79AAF5F3BCA2E4FDB25BFAC1C, + ) + self.assertEqual( + pointH.y, + 0x3BEB69CC9111BFFCADDC61D363CE6FE5DD44DA4AADCE78F52E92E985D5442344CED72C4611ED0DAAC9F4F5661EAB73D7A12D25CE8A30241E, + ) + + def test_sizes(self): + self.assertEqual(self.pointG.size_in_bits(), 448) + self.assertEqual(self.pointG.size_in_bytes(), 56) class TestEccKey_Ed448(unittest.TestCase): - - def test_private_key(self): - seed = unhexlify("4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9") - Px = 0x72a01eea003a35f9ac44231dc4aae2a382f351d80bf32508175b0855edcf389aa2bbf308dd961ce361a6e7c2091bc78957f6ebcf3002a617 - Py = 0x9e0d08d84586e9aeefecacb41d049b831f1a3ee0c3eada63e34557b30702b50ab59fb372feff7c30b8cbb7dd51afbe88444ec56238722ec1 - - key = EccKey(curve="Ed448", seed=seed) - self.assertEqual(key.seed, seed) - self.assertEqual(key.d, 0xb07cf179604f83433186e5178760c759c15125ee54ff6f8dcde46e872b709ac82ed0bd0a4e036d774034dcb18a9fb11894657a1485895f80) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, Px) - self.assertEqual(key.pointQ.y, Py) - - point = EccPoint(Px, Py, "ed448") - key = EccKey(curve="Ed448", seed=seed, point=point) - self.assertEqual(key.d, 0xb07cf179604f83433186e5178760c759c15125ee54ff6f8dcde46e872b709ac82ed0bd0a4e036d774034dcb18a9fb11894657a1485895f80) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="ed448", seed=seed) - - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="ed448", d=1) - - def test_public_key(self): - point = EccPoint(_curves['ed448'].Gx, _curves['ed448'].Gy, curve='ed448') - key = EccKey(curve="ed448", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - priv_key = EccKey(curve="ed448", seed=b'H'*57) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_seed(self): - self.assertRaises(ValueError, lambda: EccKey(curve="ed448", seed=b'H' * 56)) - - def test_equality(self): - private_key = ECC.construct(seed=b'H'*57, curve="Ed448") - private_key2 = ECC.construct(seed=b'H'*57, curve="ed448") - private_key3 = ECC.construct(seed=b'C'*57, curve="Ed448") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='ed448') - self.assertIn("curve='Ed448'", repr(key)) - self.assertEqual(key.curve, 'Ed448') - self.assertEqual(key.public_key().curve, 'Ed448') + def test_private_key(self): + seed = unhexlify( + "4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9" + ) + Px = 0x72A01EEA003A35F9AC44231DC4AAE2A382F351D80BF32508175B0855EDCF389AA2BBF308DD961CE361A6E7C2091BC78957F6EBCF3002A617 + Py = 0x9E0D08D84586E9AEEFECACB41D049B831F1A3EE0C3EADA63E34557B30702B50AB59FB372FEFF7C30B8CBB7DD51AFBE88444EC56238722EC1 + + key = EccKey(curve="Ed448", seed=seed) + self.assertEqual(key.seed, seed) + self.assertEqual( + key.d, + 0xB07CF179604F83433186E5178760C759C15125EE54FF6F8DCDE46E872B709AC82ED0BD0A4E036D774034DCB18A9FB11894657A1485895F80, + ) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, Px) + self.assertEqual(key.pointQ.y, Py) + + point = EccPoint(Px, Py, "ed448") + key = EccKey(curve="Ed448", seed=seed, point=point) + self.assertEqual( + key.d, + 0xB07CF179604F83433186E5178760C759C15125EE54FF6F8DCDE46E872B709AC82ED0BD0A4E036D774034DCB18A9FB11894657A1485895F80, + ) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="ed448", seed=seed) + + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="ed448", d=1) + + def test_public_key(self): + point = EccPoint(_curves["ed448"].Gx, _curves["ed448"].Gy, curve="ed448") + key = EccKey(curve="ed448", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="ed448", seed=b"H" * 57) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_seed(self): + self.assertRaises(ValueError, lambda: EccKey(curve="ed448", seed=b"H" * 56)) + + def test_equality(self): + private_key = ECC.construct(seed=b"H" * 57, curve="Ed448") + private_key2 = ECC.construct(seed=b"H" * 57, curve="ed448") + private_key3 = ECC.construct(seed=b"C" * 57, curve="Ed448") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="ed448") + self.assertIn("curve='Ed448'", repr(key)) + self.assertEqual(key.curve, "Ed448") + self.assertEqual(key.public_key().curve, "Ed448") class TestEccModule_Ed448(unittest.TestCase): + def test_generate(self): + key = ECC.generate(curve="Ed448") + self.assertTrue(key.has_private()) + point = EccPoint(_curves["Ed448"].Gx, _curves["Ed448"].Gy, curve="Ed448") * key.d + self.assertEqual(key.pointQ, point) + + # Always random + key2 = ECC.generate(curve="Ed448") + self.assertNotEqual(key, key2) + + # Other names + ECC.generate(curve="Ed448") + + # Random source + key1 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read) + key2 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read) + self.assertEqual(key1, key2) + + def test_construct(self): + seed = unhexlify( + "4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9" + ) + Px = 0x72A01EEA003A35F9AC44231DC4AAE2A382F351D80BF32508175B0855EDCF389AA2BBF308DD961CE361A6E7C2091BC78957F6EBCF3002A617 + Py = 0x9E0D08D84586E9AEEFECACB41D049B831F1A3EE0C3EADA63E34557B30702B50AB59FB372FEFF7C30B8CBB7DD51AFBE88444EC56238722EC1 + d = 0xB07CF179604F83433186E5178760C759C15125EE54FF6F8DCDE46E872B709AC82ED0BD0A4E036D774034DCB18A9FB11894657A1485895F80 + point = EccPoint(Px, Py, curve="Ed448") + + # Private key only + key = ECC.construct(curve="Ed448", seed=seed) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Public key only + key = ECC.construct(curve="Ed448", point_x=Px, point_y=Py) + self.assertEqual(key.pointQ, point) + self.assertFalse(key.has_private()) + + # Private and public key + key = ECC.construct(curve="Ed448", seed=seed, point_x=Px, point_y=Py) + self.assertEqual(key.pointQ, point) + self.assertTrue(key.has_private()) + + # Other names + key = ECC.construct(curve="ed448", seed=seed) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["ed448"].Gx, point_y=_curves["ed448"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="Ed448", **coord) + self.assertRaises(ValueError, ECC.construct, curve="Ed448", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="Ed448", seed=b"H" * 58) - def test_generate(self): - key = ECC.generate(curve="Ed448") - self.assertTrue(key.has_private()) - point = EccPoint(_curves['Ed448'].Gx, _curves['Ed448'].Gy, curve="Ed448") * key.d - self.assertEqual(key.pointQ, point) - - # Always random - key2 = ECC.generate(curve="Ed448") - self.assertNotEqual(key, key2) - - # Other names - ECC.generate(curve="Ed448") - - # Random source - key1 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read) - key2 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read) - self.assertEqual(key1, key2) - - def test_construct(self): - seed = unhexlify("4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9") - Px = 0x72a01eea003a35f9ac44231dc4aae2a382f351d80bf32508175b0855edcf389aa2bbf308dd961ce361a6e7c2091bc78957f6ebcf3002a617 - Py = 0x9e0d08d84586e9aeefecacb41d049b831f1a3ee0c3eada63e34557b30702b50ab59fb372feff7c30b8cbb7dd51afbe88444ec56238722ec1 - d = 0xb07cf179604f83433186e5178760c759c15125ee54ff6f8dcde46e872b709ac82ed0bd0a4e036d774034dcb18a9fb11894657a1485895f80 - point = EccPoint(Px, Py, curve="Ed448") - - # Private key only - key = ECC.construct(curve="Ed448", seed=seed) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - # Public key only - key = ECC.construct(curve="Ed448", point_x=Px, point_y=Py) - self.assertEqual(key.pointQ, point) - self.assertFalse(key.has_private()) - - # Private and public key - key = ECC.construct(curve="Ed448", seed=seed, point_x=Px, point_y=Py) - self.assertEqual(key.pointQ, point) - self.assertTrue(key.has_private()) - - # Other names - key = ECC.construct(curve="ed448", seed=seed) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['ed448'].Gx, point_y=_curves['ed448'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="Ed448", **coord) - self.assertRaises(ValueError, ECC.construct, curve="Ed448", d=2, **coordG) - self.assertRaises(ValueError, ECC.construct, curve="Ed448", seed=b'H'*58) +def get_tests(config={}): + tests = [] + tests += list_test_cases(TestEccPoint_Ed448) + tests += list_test_cases(TestEccKey_Ed448) + tests += list_test_cases(TestEccModule_Ed448) + return tests -def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint_Ed448) - tests += list_test_cases(TestEccKey_Ed448) - tests += list_test_cases(TestEccModule_Ed448) - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_NIST.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_NIST.py index ae790b14..0b4a5210 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_NIST.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ECC_NIST.py @@ -29,7 +29,6 @@ # =================================================================== import unittest -from binascii import unhexlify from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.SelfTest.loader import load_test_vectors @@ -41,1400 +40,1481 @@ class TestEccPoint(unittest.TestCase): - - def test_mix(self): - - p1 = ECC.generate(curve='P-256').pointQ - p2 = ECC.generate(curve='P-384').pointQ - - try: - p1 + p2 - assert(False) - except ValueError as e: - assert "not on the same curve" in str(e) - - try: - p1 += p2 - assert(False) - except ValueError as e: - assert "not on the same curve" in str(e) - - class OtherKeyType: - pass - - self.assertFalse(p1 == OtherKeyType()) - self.assertTrue(p1 != OtherKeyType()) - - def test_repr(self): - p1 = ECC.construct(curve='P-256', - d=75467964919405407085864614198393977741148485328036093939970922195112333446269, - point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, - point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389) - self.assertEqual(repr(p1), "EccKey(curve='NIST P-256', point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389, d=75467964919405407085864614198393977741148485328036093939970922195112333446269)") + def test_mix(self): + p1 = ECC.generate(curve="P-256").pointQ + p2 = ECC.generate(curve="P-384").pointQ + + try: + p1 + p2 + assert False + except ValueError as e: + assert "not on the same curve" in str(e) + + try: + p1 += p2 + assert False + except ValueError as e: + assert "not on the same curve" in str(e) + + class OtherKeyType: + pass + + self.assertFalse(p1 == OtherKeyType()) + self.assertTrue(p1 != OtherKeyType()) + + def test_repr(self): + p1 = ECC.construct( + curve="P-256", + d=75467964919405407085864614198393977741148485328036093939970922195112333446269, + point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, + point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389, + ) + self.assertEqual( + repr(p1), + "EccKey(curve='NIST P-256', point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389, d=75467964919405407085864614198393977741148485328036093939970922195112333446269)", + ) class TestEccPoint_NIST_P192(unittest.TestCase): - """Tests defined in section 4.1 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0xd458e7d127ae671b0c330266d246769353a012073e97acf8, - 0x325930500d851f336bddc050cf7fb11b5673a1645086df3b, - curve='p192') - - pointT = EccPoint( - 0xf22c4395213e9ebe67ddecdd87fdbd01be16fb059b9753a4, - 0x264424096af2b3597796db48f8dfb41fa9cecc97691a9c79, - curve='p192') - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-192") - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x48e1e4096b9b8e5ca9d0f1f077b8abf58e843894de4d0290 - pointRy = 0x408fa77c797cd7dbfb16aa48a3648d3d63c94117d7b6aa4b - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x48e1e4096b9b8e5ca9d0f1f077b8abf58e843894de4d0290 - pointRy = 0x408fa77c797cd7dbfb16aa48a3648d3d63c94117d7b6aa4b - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x30c5bc6b8c7da25354b373dc14dd8a0eba42d25a3f6e6962 - pointRy = 0x0dde14bc4249a721c407aedbf011e2ddbbcb2968c9d889cf - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xa78a236d60baec0c5dd41b33a542463a8255391af64c74ee - pointRx = 0x1faee4205a4f669d2d0a8f25e3bcec9a62a6952965bf6d31 - pointRy = 0x5ff2cdfa508a2581892367087c696f179e7a4d7e8260fb06 - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - # Reverse order - pointR = d * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pointR = Integer(d) * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_joint_scalar_multiply(self): - d = 0xa78a236d60baec0c5dd41b33a542463a8255391af64c74ee - e = 0xc4be3d53ec3089e71e4de8ceab7cce889bc393cd85b972bc - pointRx = 0x019f64eed8fa9b72b7dfea82c17c9bfa60ecb9e1778b5bde - pointRy = 0x16590c5fcd8655fa4ced33fb800e2a7e3c61f35d83503644 - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 192) - self.assertEqual(self.pointS.size_in_bytes(), 24) + """Tests defined in section 4.1 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0xD458E7D127AE671B0C330266D246769353A012073E97ACF8, + 0x325930500D851F336BDDC050CF7FB11B5673A1645086DF3B, + curve="p192", + ) + + pointT = EccPoint( + 0xF22C4395213E9EBE67DDECDD87FDBD01BE16FB059B9753A4, + 0x264424096AF2B3597796DB48F8DFB41FA9CECC97691A9C79, + curve="p192", + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-192") + + def test_set(self): + pointW = EccPoint(0, 0) + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = 0x48E1E4096B9B8E5CA9D0F1F077B8ABF58E843894DE4D0290 + pointRy = 0x408FA77C797CD7DBFB16AA48A3648D3D63C94117D7B6AA4B + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def test_inplace_addition(self): + pointRx = 0x48E1E4096B9B8E5CA9D0F1F077B8ABF58E843894DE4D0290 + pointRy = 0x408FA77C797CD7DBFB16AA48A3648D3D63C94117D7B6AA4B + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = 0x30C5BC6B8C7DA25354B373DC14DD8A0EBA42D25A3F6E6962 + pointRy = 0x0DDE14BC4249A721C407AEDBF011E2DDBBCB2968C9D889CF + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0xA78A236D60BAEC0C5DD41B33A542463A8255391AF64C74EE + pointRx = 0x1FAEE4205A4F669D2D0A8F25E3BCEC9A62A6952965BF6D31 + pointRy = 0x5FF2CDFA508A2581892367087C696F179E7A4D7E8260FB06 + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + # Reverse order + pointR = d * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pointR = Integer(d) * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_joint_scalar_multiply(self): + d = 0xA78A236D60BAEC0C5DD41B33A542463A8255391AF64C74EE + e = 0xC4BE3D53EC3089E71E4DE8CEAB7CCE889BC393CD85B972BC + pointRx = 0x019F64EED8FA9B72B7DFEA82C17C9BFA60ECB9E1778B5BDE + pointRy = 0x16590C5FCD8655FA4CED33FB800E2A7E3C61F35D83503644 + + pointR = self.pointS * d + self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 192) + self.assertEqual(self.pointS.size_in_bytes(), 24) class TestEccPoint_NIST_P224(unittest.TestCase): - """Tests defined in section 4.2 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0x6eca814ba59a930843dc814edd6c97da95518df3c6fdf16e9a10bb5b, - 0xef4b497f0963bc8b6aec0ca0f259b89cd80994147e05dc6b64d7bf22, - curve='p224') - - pointT = EccPoint( - 0xb72b25aea5cb03fb88d7e842002969648e6ef23c5d39ac903826bd6d, - 0xc42a8a4d34984f0b71b5b4091af7dceb33ea729c1a2dc8b434f10c34, - curve='p224') - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-224") - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x236f26d9e84c2f7d776b107bd478ee0a6d2bcfcaa2162afae8d2fd15 - pointRy = 0xe53cc0a7904ce6c3746f6a97471297a0b7d5cdf8d536ae25bb0fda70 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x236f26d9e84c2f7d776b107bd478ee0a6d2bcfcaa2162afae8d2fd15 - pointRy = 0xe53cc0a7904ce6c3746f6a97471297a0b7d5cdf8d536ae25bb0fda70 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0xa9c96f2117dee0f27ca56850ebb46efad8ee26852f165e29cb5cdfc7 - pointRy = 0xadf18c84cf77ced4d76d4930417d9579207840bf49bfbf5837dfdd7d - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xa78ccc30eaca0fcc8e36b2dd6fbb03df06d37f52711e6363aaf1d73b - pointRx = 0x96a7625e92a8d72bff1113abdb95777e736a14c6fdaacc392702bca4 - pointRy = 0x0f8e5702942a3c5e13cd2fd5801915258b43dfadc70d15dbada3ed10 - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - # Reverse order - pointR = d * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pointR = Integer(d) * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_joing_scalar_multiply(self): - d = 0xa78ccc30eaca0fcc8e36b2dd6fbb03df06d37f52711e6363aaf1d73b - e = 0x54d549ffc08c96592519d73e71e8e0703fc8177fa88aa77a6ed35736 - pointRx = 0xdbfe2958c7b2cda1302a67ea3ffd94c918c5b350ab838d52e288c83e - pointRy = 0x2f521b83ac3b0549ff4895abcc7f0c5a861aacb87acbc5b8147bb18b - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 224) - self.assertEqual(self.pointS.size_in_bytes(), 28) + """Tests defined in section 4.2 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0x6ECA814BA59A930843DC814EDD6C97DA95518DF3C6FDF16E9A10BB5B, + 0xEF4B497F0963BC8B6AEC0CA0F259B89CD80994147E05DC6B64D7BF22, + curve="p224", + ) + + pointT = EccPoint( + 0xB72B25AEA5CB03FB88D7E842002969648E6EF23C5D39AC903826BD6D, + 0xC42A8A4D34984F0B71B5B4091AF7DCEB33EA729C1A2DC8B434F10C34, + curve="p224", + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-224") + + def test_set(self): + pointW = EccPoint(0, 0) + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = 0x236F26D9E84C2F7D776B107BD478EE0A6D2BCFCAA2162AFAE8D2FD15 + pointRy = 0xE53CC0A7904CE6C3746F6A97471297A0B7D5CDF8D536AE25BB0FDA70 + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def test_inplace_addition(self): + pointRx = 0x236F26D9E84C2F7D776B107BD478EE0A6D2BCFCAA2162AFAE8D2FD15 + pointRy = 0xE53CC0A7904CE6C3746F6A97471297A0B7D5CDF8D536AE25BB0FDA70 + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = 0xA9C96F2117DEE0F27CA56850EBB46EFAD8EE26852F165E29CB5CDFC7 + pointRy = 0xADF18C84CF77CED4D76D4930417D9579207840BF49BFBF5837DFDD7D + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0xA78CCC30EACA0FCC8E36B2DD6FBB03DF06D37F52711E6363AAF1D73B + pointRx = 0x96A7625E92A8D72BFF1113ABDB95777E736A14C6FDAACC392702BCA4 + pointRy = 0x0F8E5702942A3C5E13CD2FD5801915258B43DFADC70D15DBADA3ED10 + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + # Reverse order + pointR = d * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pointR = Integer(d) * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_joing_scalar_multiply(self): + d = 0xA78CCC30EACA0FCC8E36B2DD6FBB03DF06D37F52711E6363AAF1D73B + e = 0x54D549FFC08C96592519D73E71E8E0703FC8177FA88AA77A6ED35736 + pointRx = 0xDBFE2958C7B2CDA1302A67EA3FFD94C918C5B350AB838D52E288C83E + pointRy = 0x2F521B83AC3B0549FF4895ABCC7F0C5A861AACB87ACBC5B8147BB18B + + pointR = self.pointS * d + self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 224) + self.assertEqual(self.pointS.size_in_bytes(), 28) class TestEccPoint_NIST_P256(unittest.TestCase): - """Tests defined in section 4.3 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0xde2444bebc8d36e682edd27e0f271508617519b3221a8fa0b77cab3989da97c9, - 0xc093ae7ff36e5380fc01a5aad1e66659702de80f53cec576b6350b243042a256) - - pointT = EccPoint( - 0x55a8b00f8da1d44e62f6b3b25316212e39540dc861c89575bb8cf92e35e0986b, - 0x5421c3209c2d6c704835d82ac4c3dd90f61a8a52598b9e7ab656e9d8c8b24316) - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-256") - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e - pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e - pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x7669e6901606ee3ba1a8eef1e0024c33df6c22f3b17481b82a860ffcdb6127b0 - pointRy = 0xfa878162187a54f6c39f6ee0072f33de389ef3eecd03023de10ca2c1db61d0c7 - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd - pointRx = 0x51d08d5f2d4278882946d88d83c97d11e62becc3cfc18bedacc89ba34eeca03f - pointRy = 0x75ee68eb8bf626aa5b673ab51f6e744e06f8fcf8a6c0cf3035beca956a7b41d5 - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - # Reverse order - pointR = d * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pointR = Integer(d) * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_joing_scalar_multiply(self): - d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd - e = 0xd37f628ece72a462f0145cbefe3f0b355ee8332d37acdd83a358016aea029db7 - pointRx = 0xd867b4679221009234939221b8046245efcf58413daacbeff857b8588341f6b8 - pointRy = 0xf2504055c03cede12d22720dad69c745106b6607ec7e50dd35d54bd80f615275 - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 256) - self.assertEqual(self.pointS.size_in_bytes(), 32) + """Tests defined in section 4.3 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0xDE2444BEBC8D36E682EDD27E0F271508617519B3221A8FA0B77CAB3989DA97C9, + 0xC093AE7FF36E5380FC01A5AAD1E66659702DE80F53CEC576B6350B243042A256, + ) + + pointT = EccPoint( + 0x55A8B00F8DA1D44E62F6B3B25316212E39540DC861C89575BB8CF92E35E0986B, + 0x5421C3209C2D6C704835D82AC4C3DD90F61A8A52598B9E7AB656E9D8C8B24316, + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-256") + + def test_set(self): + pointW = EccPoint(0, 0) + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = 0x72B13DD4354B6B81745195E98CC5BA6970349191AC476BD4553CF35A545A067E + pointRy = 0x8D585CBB2E1327D75241A8A122D7620DC33B13315AA5C9D46D013011744AC264 + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def test_inplace_addition(self): + pointRx = 0x72B13DD4354B6B81745195E98CC5BA6970349191AC476BD4553CF35A545A067E + pointRy = 0x8D585CBB2E1327D75241A8A122D7620DC33B13315AA5C9D46D013011744AC264 + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = 0x7669E6901606EE3BA1A8EEF1E0024C33DF6C22F3B17481B82A860FFCDB6127B0 + pointRy = 0xFA878162187A54F6C39F6EE0072F33DE389EF3EECD03023DE10CA2C1DB61D0C7 + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0xC51E4753AFDEC1E6B6C6A5B992F43F8DD0C7A8933072708B6522468B2FFB06FD + pointRx = 0x51D08D5F2D4278882946D88D83C97D11E62BECC3CFC18BEDACC89BA34EECA03F + pointRy = 0x75EE68EB8BF626AA5B673AB51F6E744E06F8FCF8A6C0CF3035BECA956A7B41D5 + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + # Reverse order + pointR = d * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pointR = Integer(d) * self.pointS + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_joing_scalar_multiply(self): + d = 0xC51E4753AFDEC1E6B6C6A5B992F43F8DD0C7A8933072708B6522468B2FFB06FD + e = 0xD37F628ECE72A462F0145CBEFE3F0B355EE8332D37ACDD83A358016AEA029DB7 + pointRx = 0xD867B4679221009234939221B8046245EFCF58413DAACBEFF857B8588341F6B8 + pointRy = 0xF2504055C03CEDE12D22720DAD69C745106B6607EC7E50DD35D54BD80F615275 + + pointR = self.pointS * d + self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 256) + self.assertEqual(self.pointS.size_in_bytes(), 32) class TestEccPoint_NIST_P384(unittest.TestCase): - """Tests defined in section 4.4 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0xfba203b81bbd23f2b3be971cc23997e1ae4d89e69cb6f92385dda82768ada415ebab4167459da98e62b1332d1e73cb0e, - 0x5ffedbaefdeba603e7923e06cdb5d0c65b22301429293376d5c6944e3fa6259f162b4788de6987fd59aed5e4b5285e45, - "p384") - - pointT = EccPoint( - 0xaacc05202e7fda6fc73d82f0a66220527da8117ee8f8330ead7d20ee6f255f582d8bd38c5a7f2b40bcdb68ba13d81051, - 0x84009a263fefba7c2c57cffa5db3634d286131afc0fca8d25afa22a7b5dce0d9470da89233cee178592f49b6fecb5092, - "p384") - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-384") - - def test_set(self): - pointW = EccPoint(0, 0, "p384") - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x12dc5ce7acdfc5844d939f40b4df012e68f865b89c3213ba97090a247a2fc009075cf471cd2e85c489979b65ee0b5eed - pointRy = 0x167312e58fe0c0afa248f2854e3cddcb557f983b3189b67f21eee01341e7e9fe67f6ee81b36988efa406945c8804a4b0 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def _test_inplace_addition(self): - pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e - pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x2a2111b1e0aa8b2fc5a1975516bc4d58017ff96b25e1bdff3c229d5fac3bacc319dcbec29f9478f42dee597b4641504c - pointRy = 0xfa2e3d9dc84db8954ce8085ef28d7184fddfd1344b4d4797343af9b5f9d837520b450f726443e4114bd4e5bdb2f65ddd - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xa4ebcae5a665983493ab3e626085a24c104311a761b5a8fdac052ed1f111a5c44f76f45659d2d111a61b5fdd97583480 - pointRx = 0xe4f77e7ffeb7f0958910e3a680d677a477191df166160ff7ef6bb5261f791aa7b45e3e653d151b95dad3d93ca0290ef2 - pointRy = 0xac7dee41d8c5f4a7d5836960a773cfc1376289d3373f8cf7417b0c6207ac32e913856612fc9ff2e357eb2ee05cf9667f - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - def test_joing_scalar_multiply(self): - d = 0xa4ebcae5a665983493ab3e626085a24c104311a761b5a8fdac052ed1f111a5c44f76f45659d2d111a61b5fdd97583480 - e = 0xafcf88119a3a76c87acbd6008e1349b29f4ba9aa0e12ce89bcfcae2180b38d81ab8cf15095301a182afbc6893e75385d - pointRx = 0x917ea28bcd641741ae5d18c2f1bd917ba68d34f0f0577387dc81260462aea60e2417b8bdc5d954fc729d211db23a02dc - pointRy = 0x1a29f7ce6d074654d77b40888c73e92546c8f16a5ff6bcbd307f758d4aee684beff26f6742f597e2585c86da908f7186 - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 384) - self.assertEqual(self.pointS.size_in_bytes(), 48) + """Tests defined in section 4.4 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0xFBA203B81BBD23F2B3BE971CC23997E1AE4D89E69CB6F92385DDA82768ADA415EBAB4167459DA98E62B1332D1E73CB0E, + 0x5FFEDBAEFDEBA603E7923E06CDB5D0C65B22301429293376D5C6944E3FA6259F162B4788DE6987FD59AED5E4B5285E45, + "p384", + ) + + pointT = EccPoint( + 0xAACC05202E7FDA6FC73D82F0A66220527DA8117EE8F8330EAD7D20EE6F255F582D8BD38C5A7F2B40BCDB68BA13D81051, + 0x84009A263FEFBA7C2C57CFFA5DB3634D286131AFC0FCA8D25AFA22A7B5DCE0D9470DA89233CEE178592F49B6FECB5092, + "p384", + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-384") + + def test_set(self): + pointW = EccPoint(0, 0, "p384") + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = ( + 0x12DC5CE7ACDFC5844D939F40B4DF012E68F865B89C3213BA97090A247A2FC009075CF471CD2E85C489979B65EE0B5EED + ) + pointRy = ( + 0x167312E58FE0C0AFA248F2854E3CDDCB557F983B3189B67F21EEE01341E7E9FE67F6EE81B36988EFA406945C8804A4B0 + ) + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def _test_inplace_addition(self): + pointRx = 0x72B13DD4354B6B81745195E98CC5BA6970349191AC476BD4553CF35A545A067E + pointRy = 0x8D585CBB2E1327D75241A8A122D7620DC33B13315AA5C9D46D013011744AC264 + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = ( + 0x2A2111B1E0AA8B2FC5A1975516BC4D58017FF96B25E1BDFF3C229D5FAC3BACC319DCBEC29F9478F42DEE597B4641504C + ) + pointRy = ( + 0xFA2E3D9DC84DB8954CE8085EF28D7184FDDFD1344B4D4797343AF9B5F9D837520B450F726443E4114BD4E5BDB2F65DDD + ) + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0xA4EBCAE5A665983493AB3E626085A24C104311A761B5A8FDAC052ED1F111A5C44F76F45659D2D111A61B5FDD97583480 + pointRx = ( + 0xE4F77E7FFEB7F0958910E3A680D677A477191DF166160FF7EF6BB5261F791AA7B45E3E653D151B95DAD3D93CA0290EF2 + ) + pointRy = ( + 0xAC7DEE41D8C5F4A7D5836960A773CFC1376289D3373F8CF7417B0C6207AC32E913856612FC9FF2E357EB2EE05CF9667F + ) + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + def test_joing_scalar_multiply(self): + d = 0xA4EBCAE5A665983493AB3E626085A24C104311A761B5A8FDAC052ED1F111A5C44F76F45659D2D111A61B5FDD97583480 + e = 0xAFCF88119A3A76C87ACBD6008E1349B29F4BA9AA0E12CE89BCFCAE2180B38D81AB8CF15095301A182AFBC6893E75385D + pointRx = ( + 0x917EA28BCD641741AE5D18C2F1BD917BA68D34F0F0577387DC81260462AEA60E2417B8BDC5D954FC729D211DB23A02DC + ) + pointRy = ( + 0x1A29F7CE6D074654D77B40888C73E92546C8F16A5FF6BCBD307F758D4AEE684BEFF26F6742F597E2585C86DA908F7186 + ) + + pointR = self.pointS * d + self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 384) + self.assertEqual(self.pointS.size_in_bytes(), 48) class TestEccPoint_NIST_P521(unittest.TestCase): - """Tests defined in section 4.5 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" - - pointS = EccPoint( - 0x000001d5c693f66c08ed03ad0f031f937443458f601fd098d3d0227b4bf62873af50740b0bb84aa157fc847bcf8dc16a8b2b8bfd8e2d0a7d39af04b089930ef6dad5c1b4, - 0x00000144b7770963c63a39248865ff36b074151eac33549b224af5c8664c54012b818ed037b2b7c1a63ac89ebaa11e07db89fcee5b556e49764ee3fa66ea7ae61ac01823, - "p521") - - pointT = EccPoint( - 0x000000f411f2ac2eb971a267b80297ba67c322dba4bb21cec8b70073bf88fc1ca5fde3ba09e5df6d39acb2c0762c03d7bc224a3e197feaf760d6324006fe3be9a548c7d5, - 0x000001fdf842769c707c93c630df6d02eff399a06f1b36fb9684f0b373ed064889629abb92b1ae328fdb45534268384943f0e9222afe03259b32274d35d1b9584c65e305, - "p521") - - def test_curve_attribute(self): - self.assertEqual(self.pointS.curve, "NIST P-521") - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x000001264ae115ba9cbc2ee56e6f0059e24b52c8046321602c59a339cfb757c89a59c358a9a8e1f86d384b3f3b255ea3f73670c6dc9f45d46b6a196dc37bbe0f6b2dd9e9 - pointRy = 0x00000062a9c72b8f9f88a271690bfa017a6466c31b9cadc2fc544744aeb817072349cfddc5ad0e81b03f1897bd9c8c6efbdf68237dc3bb00445979fb373b20c9a967ac55 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x000001264ae115ba9cbc2ee56e6f0059e24b52c8046321602c59a339cfb757c89a59c358a9a8e1f86d384b3f3b255ea3f73670c6dc9f45d46b6a196dc37bbe0f6b2dd9e9 - pointRy = 0x00000062a9c72b8f9f88a271690bfa017a6466c31b9cadc2fc544744aeb817072349cfddc5ad0e81b03f1897bd9c8c6efbdf68237dc3bb00445979fb373b20c9a967ac55 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x0000012879442f2450c119e7119a5f738be1f1eba9e9d7c6cf41b325d9ce6d643106e9d61124a91a96bcf201305a9dee55fa79136dc700831e54c3ca4ff2646bd3c36bc6 - pointRy = 0x0000019864a8b8855c2479cbefe375ae553e2393271ed36fadfc4494fc0583f6bd03598896f39854abeae5f9a6515a021e2c0eef139e71de610143f53382f4104dccb543 - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0x000001eb7f81785c9629f136a7e8f8c674957109735554111a2a866fa5a166699419bfa9936c78b62653964df0d6da940a695c7294d41b2d6600de6dfcf0edcfc89fdcb1 - pointRx = 0x00000091b15d09d0ca0353f8f96b93cdb13497b0a4bb582ae9ebefa35eee61bf7b7d041b8ec34c6c00c0c0671c4ae063318fb75be87af4fe859608c95f0ab4774f8c95bb - pointRy = 0x00000130f8f8b5e1abb4dd94f6baaf654a2d5810411e77b7423965e0c7fd79ec1ae563c207bd255ee9828eb7a03fed565240d2cc80ddd2cecbb2eb50f0951f75ad87977f - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - def test_joing_scalar_multiply(self): - d = 0x000001eb7f81785c9629f136a7e8f8c674957109735554111a2a866fa5a166699419bfa9936c78b62653964df0d6da940a695c7294d41b2d6600de6dfcf0edcfc89fdcb1 - e = 0x00000137e6b73d38f153c3a7575615812608f2bab3229c92e21c0d1c83cfad9261dbb17bb77a63682000031b9122c2f0cdab2af72314be95254de4291a8f85f7c70412e3 - pointRx = 0x0000009d3802642b3bea152beb9e05fba247790f7fc168072d363340133402f2585588dc1385d40ebcb8552f8db02b23d687cae46185b27528adb1bf9729716e4eba653d - pointRy = 0x0000000fe44344e79da6f49d87c1063744e5957d9ac0a505bafa8281c9ce9ff25ad53f8da084a2deb0923e46501de5797850c61b229023dd9cf7fc7f04cd35ebb026d89d - - pointR = self.pointS * d - pointR += self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 521) - self.assertEqual(self.pointS.size_in_bytes(), 66) + """Tests defined in section 4.5 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf""" + + pointS = EccPoint( + 0x000001D5C693F66C08ED03AD0F031F937443458F601FD098D3D0227B4BF62873AF50740B0BB84AA157FC847BCF8DC16A8B2B8BFD8E2D0A7D39AF04B089930EF6DAD5C1B4, + 0x00000144B7770963C63A39248865FF36B074151EAC33549B224AF5C8664C54012B818ED037B2B7C1A63AC89EBAA11E07DB89FCEE5B556E49764EE3FA66EA7AE61AC01823, + "p521", + ) + + pointT = EccPoint( + 0x000000F411F2AC2EB971A267B80297BA67C322DBA4BB21CEC8B70073BF88FC1CA5FDE3BA09E5DF6D39ACB2C0762C03D7BC224A3E197FEAF760D6324006FE3BE9A548C7D5, + 0x000001FDF842769C707C93C630DF6D02EFF399A06F1B36FB9684F0B373ED064889629ABB92B1AE328FDB45534268384943F0E9222AFE03259B32274D35D1B9584C65E305, + "p521", + ) + + def test_curve_attribute(self): + self.assertEqual(self.pointS.curve, "NIST P-521") + + def test_set(self): + pointW = EccPoint(0, 0) + pointW.set(self.pointS) + self.assertEqual(pointW, self.pointS) + + def test_copy(self): + pointW = self.pointS.copy() + self.assertEqual(pointW, self.pointS) + pointW.set(self.pointT) + self.assertEqual(pointW, self.pointT) + self.assertNotEqual(self.pointS, self.pointT) + + def test_negate(self): + negS = -self.pointS + sum = self.pointS + negS + self.assertEqual(sum, self.pointS.point_at_infinity()) + + def test_addition(self): + pointRx = 0x000001264AE115BA9CBC2EE56E6F0059E24B52C8046321602C59A339CFB757C89A59C358A9A8E1F86D384B3F3B255EA3F73670C6DC9F45D46B6A196DC37BBE0F6B2DD9E9 + pointRy = 0x00000062A9C72B8F9F88A271690BFA017A6466C31B9CADC2FC544744AEB817072349CFDDC5AD0E81B03F1897BD9C8C6EFBDF68237DC3BB00445979FB373B20C9A967AC55 + + pointR = self.pointS + self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS + pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai + self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai + pai + self.assertEqual(pointR, pai) + + def test_inplace_addition(self): + pointRx = 0x000001264AE115BA9CBC2EE56E6F0059E24B52C8046321602C59A339CFB757C89A59C358A9A8E1F86D384B3F3B255EA3F73670C6DC9F45D46B6A196DC37BBE0F6B2DD9E9 + pointRy = 0x00000062A9C72B8F9F88A271690BFA017A6466C31B9CADC2FC544744AEB817072349CFDDC5AD0E81B03F1897BD9C8C6EFBDF68237DC3BB00445979FB373B20C9A967AC55 + + pointR = self.pointS.copy() + pointR += self.pointT + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + pai = pointR.point_at_infinity() + + # S + 0 + pointR = self.pointS.copy() + pointR += pai + self.assertEqual(pointR, self.pointS) + + # 0 + S + pointR = pai.copy() + pointR += self.pointS + self.assertEqual(pointR, self.pointS) + + # 0 + 0 + pointR = pai.copy() + pointR += pai + self.assertEqual(pointR, pai) + + def test_doubling(self): + pointRx = 0x0000012879442F2450C119E7119A5F738BE1F1EBA9E9D7C6CF41B325D9CE6D643106E9D61124A91A96BCF201305A9DEE55FA79136DC700831E54C3CA4FF2646BD3C36BC6 + pointRy = 0x0000019864A8B8855C2479CBEFE375AE553E2393271ED36FADFC4494FC0583F6BD03598896F39854ABEAE5F9A6515A021E2C0EEF139E71DE610143F53382F4104DCCB543 + + pointR = self.pointS.copy() + pointR.double() + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 2*0 + pai = self.pointS.point_at_infinity() + pointR = pai.copy() + pointR.double() + self.assertEqual(pointR, pai) + + # S + S + pointR = self.pointS.copy() + pointR += pointR + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_scalar_multiply(self): + d = 0x000001EB7F81785C9629F136A7E8F8C674957109735554111A2A866FA5A166699419BFA9936C78B62653964DF0D6DA940A695C7294D41B2D6600DE6DFCF0EDCFC89FDCB1 + pointRx = 0x00000091B15D09D0CA0353F8F96B93CDB13497B0A4BB582AE9EBEFA35EEE61BF7B7D041B8EC34C6C00C0C0671C4AE063318FB75BE87AF4FE859608C95F0AB4774F8C95BB + pointRy = 0x00000130F8F8B5E1ABB4DD94F6BAAF654A2D5810411E77B7423965E0C7FD79EC1AE563C207BD255EE9828EB7A03FED565240D2CC80DDD2CECBB2EB50F0951F75AD87977F + + pointR = self.pointS * d + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + # 0*S + pai = self.pointS.point_at_infinity() + pointR = self.pointS * 0 + self.assertEqual(pointR, pai) + + # -1*S + self.assertRaises(ValueError, lambda: self.pointS * -1) + + def test_joing_scalar_multiply(self): + d = 0x000001EB7F81785C9629F136A7E8F8C674957109735554111A2A866FA5A166699419BFA9936C78B62653964DF0D6DA940A695C7294D41B2D6600DE6DFCF0EDCFC89FDCB1 + e = 0x00000137E6B73D38F153C3A7575615812608F2BAB3229C92E21C0D1C83CFAD9261DBB17BB77A63682000031B9122C2F0CDAB2AF72314BE95254DE4291A8F85F7C70412E3 + pointRx = 0x0000009D3802642B3BEA152BEB9E05FBA247790F7FC168072D363340133402F2585588DC1385D40EBCB8552F8DB02B23D687CAE46185B27528ADB1BF9729716E4EBA653D + pointRy = 0x0000000FE44344E79DA6F49D87C1063744E5957D9AC0A505BAFA8281C9CE9FF25AD53F8DA084A2DEB0923E46501DE5797850C61B229023DD9CF7FC7F04CD35EBB026D89D + + pointR = self.pointS * d + pointR += self.pointT * e + self.assertEqual(pointR.x, pointRx) + self.assertEqual(pointR.y, pointRy) + + def test_sizes(self): + self.assertEqual(self.pointS.size_in_bits(), 521) + self.assertEqual(self.pointS.size_in_bytes(), 66) class TestEccPoint_PAI_P192(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" - - curve = _curves['p192'] - pointG = EccPoint(curve.Gx, curve.Gy, "p192") - - -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P192.txt", - "P-192 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p192"] + pointG = EccPoint(curve.Gx, curve.Gy, "p192") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P192.txt", + "P-192 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P192, "test_%d" % tv.count, new_test) - -class TestEccPoint_PAI_P224(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) - curve = _curves['p224'] - pointG = EccPoint(curve.Gx, curve.Gy, "p224") + setattr(TestEccPoint_PAI_P192, "test_%d" % tv.count, new_test) -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P224.txt", - "P-224 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] +class TestEccPoint_PAI_P224(unittest.TestCase): + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p224"] + pointG = EccPoint(curve.Gx, curve.Gy, "p224") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P224.txt", + "P-224 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P224, "test_%d" % tv.count, new_test) + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) -class TestEccPoint_PAI_P256(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" - - curve = _curves['p256'] - pointG = EccPoint(curve.Gx, curve.Gy, "p256") + setattr(TestEccPoint_PAI_P224, "test_%d" % tv.count, new_test) -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P256.txt", - "P-256 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] +class TestEccPoint_PAI_P256(unittest.TestCase): + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p256"] + pointG = EccPoint(curve.Gx, curve.Gy, "p256") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P256.txt", + "P-256 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P256, "test_%d" % tv.count, new_test) + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) -class TestEccPoint_PAI_P384(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + setattr(TestEccPoint_PAI_P256, "test_%d" % tv.count, new_test) - curve = _curves['p384'] - pointG = EccPoint(curve.Gx, curve.Gy, "p384") - -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P384.txt", - "P-384 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] +class TestEccPoint_PAI_P384(unittest.TestCase): + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p384"] + pointG = EccPoint(curve.Gx, curve.Gy, "p384") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P384.txt", + "P-384 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P384, "test_%d" % tv.count, new_test) + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) -class TestEccPoint_PAI_P521(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" - - curve = _curves['p521'] - pointG = EccPoint(curve.Gx, curve.Gy, "p521") + setattr(TestEccPoint_PAI_P384, "test_%d" % tv.count, new_test) -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P521.txt", - "P-521 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] +class TestEccPoint_PAI_P521(unittest.TestCase): + """Test vectors from http://point-at-infinity.org/ecc/nisttv""" + + curve = _curves["p521"] + pointG = EccPoint(curve.Gx, curve.Gy, "p521") + + +tv_pai = ( + load_test_vectors( + ("PublicKey", "ECC"), + "point-at-infinity.org-P521.txt", + "P-521 tests from point-at-infinity.org", + { + "k": lambda k: int(k), + "x": lambda x: int(x, 16), + "y": lambda y: int(y, 16), + }, + ) + or [] +) for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P521, "test_%d" % tv.count, new_test) - - -class TestEccKey_P192(unittest.TestCase): - - def test_private_key(self): - - key = EccKey(curve="P-192", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, _curves['p192'].Gx) - self.assertEqual(key.pointQ.y, _curves['p192'].Gy) - - point = EccPoint(_curves['p192'].Gx, _curves['p192'].Gy, curve='P-192') - key = EccKey(curve="P-192", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="secp192r1", d=1) - key = EccKey(curve="prime192v1", d=1) - - def test_public_key(self): - - point = EccPoint(_curves['p192'].Gx, _curves['p192'].Gy, curve='P-192') - key = EccKey(curve="P-192", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-192", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-193", d=1)) + def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): + result = self.pointG * scalar + self.assertEqual(result.x, x) + self.assertEqual(result.y, y) - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-192", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-192", - d=_curves['p192'].order)) + setattr(TestEccPoint_PAI_P521, "test_%d" % tv.count, new_test) - def test_equality(self): - private_key = ECC.construct(d=3, curve="P-192") - private_key2 = ECC.construct(d=3, curve="P-192") - private_key3 = ECC.construct(d=4, curve="P-192") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p192') - self.assertIn("curve='NIST P-192'", repr(key)) - self.assertEqual(key.curve, 'NIST P-192') - self.assertEqual(key.public_key().curve, 'NIST P-192') +class TestEccKey_P192(unittest.TestCase): + def test_private_key(self): + key = EccKey(curve="P-192", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, _curves["p192"].Gx) + self.assertEqual(key.pointQ.y, _curves["p192"].Gy) + + point = EccPoint(_curves["p192"].Gx, _curves["p192"].Gy, curve="P-192") + key = EccKey(curve="P-192", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="secp192r1", d=1) + key = EccKey(curve="prime192v1", d=1) + + def test_public_key(self): + point = EccPoint(_curves["p192"].Gx, _curves["p192"].Gy, curve="P-192") + key = EccKey(curve="P-192", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="P-192", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-193", d=1)) + + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-192", d=0)) + self.assertRaises( + ValueError, + lambda: EccKey( + curve="P-192", + d=_curves["p192"].order, + ), + ) + + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-192") + private_key2 = ECC.construct(d=3, curve="P-192") + private_key3 = ECC.construct(d=4, curve="P-192") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="p192") + self.assertIn("curve='NIST P-192'", repr(key)) + self.assertEqual(key.curve, "NIST P-192") + self.assertEqual(key.public_key().curve, "NIST P-192") class TestEccKey_P224(unittest.TestCase): - - def test_private_key(self): - - key = EccKey(curve="P-224", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, _curves['p224'].Gx) - self.assertEqual(key.pointQ.y, _curves['p224'].Gy) - - point = EccPoint(_curves['p224'].Gx, _curves['p224'].Gy, curve='P-224') - key = EccKey(curve="P-224", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="secp224r1", d=1) - key = EccKey(curve="prime224v1", d=1) - - def test_public_key(self): - - point = EccPoint(_curves['p224'].Gx, _curves['p224'].Gy, curve='P-224') - key = EccKey(curve="P-224", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-224", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-225", d=1)) - - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-224", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-224", - d=_curves['p224'].order)) - - def test_equality(self): - - private_key = ECC.construct(d=3, curve="P-224") - private_key2 = ECC.construct(d=3, curve="P-224") - private_key3 = ECC.construct(d=4, curve="P-224") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p224') - self.assertIn("curve='NIST P-224'", repr(key)) - self.assertEqual(key.curve, 'NIST P-224') - self.assertEqual(key.public_key().curve, 'NIST P-224') + def test_private_key(self): + key = EccKey(curve="P-224", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, _curves["p224"].Gx) + self.assertEqual(key.pointQ.y, _curves["p224"].Gy) + + point = EccPoint(_curves["p224"].Gx, _curves["p224"].Gy, curve="P-224") + key = EccKey(curve="P-224", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="secp224r1", d=1) + key = EccKey(curve="prime224v1", d=1) + + def test_public_key(self): + point = EccPoint(_curves["p224"].Gx, _curves["p224"].Gy, curve="P-224") + key = EccKey(curve="P-224", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="P-224", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-225", d=1)) + + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-224", d=0)) + self.assertRaises( + ValueError, + lambda: EccKey( + curve="P-224", + d=_curves["p224"].order, + ), + ) + + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-224") + private_key2 = ECC.construct(d=3, curve="P-224") + private_key3 = ECC.construct(d=4, curve="P-224") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="p224") + self.assertIn("curve='NIST P-224'", repr(key)) + self.assertEqual(key.curve, "NIST P-224") + self.assertEqual(key.public_key().curve, "NIST P-224") class TestEccKey_P256(unittest.TestCase): + def test_private_key(self): + key = EccKey(curve="P-256", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, _curves["p256"].Gx) + self.assertEqual(key.pointQ.y, _curves["p256"].Gy) - def test_private_key(self): - - key = EccKey(curve="P-256", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, _curves['p256'].Gx) - self.assertEqual(key.pointQ.y, _curves['p256'].Gy) + point = EccPoint(_curves["p256"].Gx, _curves["p256"].Gy) + key = EccKey(curve="P-256", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) - point = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy) - key = EccKey(curve="P-256", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) + # Other names + key = EccKey(curve="secp256r1", d=1) + key = EccKey(curve="prime256v1", d=1) - # Other names - key = EccKey(curve="secp256r1", d=1) - key = EccKey(curve="prime256v1", d=1) + # Must not accept d parameter + self.assertRaises(ValueError, EccKey, curve="p256", seed=b"H" * 32) - # Must not accept d parameter - self.assertRaises(ValueError, EccKey, curve="p256", seed=b'H'*32) + def test_public_key(self): + point = EccPoint(_curves["p256"].Gx, _curves["p256"].Gy) + key = EccKey(curve="P-256", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) - def test_public_key(self): + def test_public_key_derived(self): + priv_key = EccKey(curve="P-256", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) - point = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy) - key = EccKey(curve="P-256", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-257", d=1)) - def test_public_key_derived(self): + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=0)) + self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=_curves["p256"].order)) - priv_key = EccKey(curve="P-256", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-256") + private_key2 = ECC.construct(d=3, curve="P-256") + private_key3 = ECC.construct(d=4, curve="P-256") - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-257", d=1)) + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=_curves['p256'].order)) + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) - def test_equality(self): + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) - private_key = ECC.construct(d=3, curve="P-256") - private_key2 = ECC.construct(d=3, curve="P-256") - private_key3 = ECC.construct(d=4, curve="P-256") + self.assertNotEqual(public_key, private_key) - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p256') - self.assertIn("curve='NIST P-256'", repr(key)) - self.assertEqual(key.curve, 'NIST P-256') - self.assertEqual(key.public_key().curve, 'NIST P-256') + def test_name_consistency(self): + key = ECC.generate(curve="p256") + self.assertIn("curve='NIST P-256'", repr(key)) + self.assertEqual(key.curve, "NIST P-256") + self.assertEqual(key.public_key().curve, "NIST P-256") class TestEccKey_P384(unittest.TestCase): - - def test_private_key(self): - - p384 = _curves['p384'] - - key = EccKey(curve="P-384", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, p384.Gx) - self.assertEqual(key.pointQ.y, p384.Gy) - - point = EccPoint(p384.Gx, p384.Gy, "p384") - key = EccKey(curve="P-384", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="p384", d=1) - key = EccKey(curve="secp384r1", d=1) - key = EccKey(curve="prime384v1", d=1) - - def test_public_key(self): - - p384 = _curves['p384'] - point = EccPoint(p384.Gx, p384.Gy, 'p384') - key = EccKey(curve="P-384", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-384", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-385", d=1)) - - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-384", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-384", - d=_curves['p384'].order)) - - def test_equality(self): - - private_key = ECC.construct(d=3, curve="P-384") - private_key2 = ECC.construct(d=3, curve="P-384") - private_key3 = ECC.construct(d=4, curve="P-384") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p384') - self.assertIn("curve='NIST P-384'", repr(key)) - self.assertEqual(key.curve, 'NIST P-384') - self.assertEqual(key.public_key().curve, 'NIST P-384') + def test_private_key(self): + p384 = _curves["p384"] + + key = EccKey(curve="P-384", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, p384.Gx) + self.assertEqual(key.pointQ.y, p384.Gy) + + point = EccPoint(p384.Gx, p384.Gy, "p384") + key = EccKey(curve="P-384", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="p384", d=1) + key = EccKey(curve="secp384r1", d=1) + key = EccKey(curve="prime384v1", d=1) + + def test_public_key(self): + p384 = _curves["p384"] + point = EccPoint(p384.Gx, p384.Gy, "p384") + key = EccKey(curve="P-384", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="P-384", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-385", d=1)) + + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-384", d=0)) + self.assertRaises( + ValueError, + lambda: EccKey( + curve="P-384", + d=_curves["p384"].order, + ), + ) + + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-384") + private_key2 = ECC.construct(d=3, curve="P-384") + private_key3 = ECC.construct(d=4, curve="P-384") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="p384") + self.assertIn("curve='NIST P-384'", repr(key)) + self.assertEqual(key.curve, "NIST P-384") + self.assertEqual(key.public_key().curve, "NIST P-384") class TestEccKey_P521(unittest.TestCase): - - def test_private_key(self): - - p521 = _curves['p521'] - - key = EccKey(curve="P-521", d=1) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ.x, p521.Gx) - self.assertEqual(key.pointQ.y, p521.Gy) - - point = EccPoint(p521.Gx, p521.Gy, "p521") - key = EccKey(curve="P-521", d=1, point=point) - self.assertEqual(key.d, 1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="p521", d=1) - key = EccKey(curve="secp521r1", d=1) - key = EccKey(curve="prime521v1", d=1) - - def test_public_key(self): - - p521 = _curves['p521'] - point = EccPoint(p521.Gx, p521.Gy, 'p521') - key = EccKey(curve="P-384", point=point) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-521", d=3) - pub_key = priv_key.public_key() - self.assertFalse(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-522", d=1)) - - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-521", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-521", - d=_curves['p521'].order)) - - def test_equality(self): - - private_key = ECC.construct(d=3, curve="P-521") - private_key2 = ECC.construct(d=3, curve="P-521") - private_key3 = ECC.construct(d=4, curve="P-521") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - def test_name_consistency(self): - key = ECC.generate(curve='p521') - self.assertIn("curve='NIST P-521'", repr(key)) - self.assertEqual(key.curve, 'NIST P-521') - self.assertEqual(key.public_key().curve, 'NIST P-521') + def test_private_key(self): + p521 = _curves["p521"] + + key = EccKey(curve="P-521", d=1) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ.x, p521.Gx) + self.assertEqual(key.pointQ.y, p521.Gy) + + point = EccPoint(p521.Gx, p521.Gy, "p521") + key = EccKey(curve="P-521", d=1, point=point) + self.assertEqual(key.d, 1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, point) + + # Other names + key = EccKey(curve="p521", d=1) + key = EccKey(curve="secp521r1", d=1) + key = EccKey(curve="prime521v1", d=1) + + def test_public_key(self): + p521 = _curves["p521"] + point = EccPoint(p521.Gx, p521.Gy, "p521") + key = EccKey(curve="P-384", point=point) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, point) + + def test_public_key_derived(self): + priv_key = EccKey(curve="P-521", d=3) + pub_key = priv_key.public_key() + self.assertFalse(pub_key.has_private()) + self.assertEqual(priv_key.pointQ, pub_key.pointQ) + + def test_invalid_curve(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-522", d=1)) + + def test_invalid_d(self): + self.assertRaises(ValueError, lambda: EccKey(curve="P-521", d=0)) + self.assertRaises( + ValueError, + lambda: EccKey( + curve="P-521", + d=_curves["p521"].order, + ), + ) + + def test_equality(self): + private_key = ECC.construct(d=3, curve="P-521") + private_key2 = ECC.construct(d=3, curve="P-521") + private_key3 = ECC.construct(d=4, curve="P-521") + + public_key = private_key.public_key() + public_key2 = private_key2.public_key() + public_key3 = private_key3.public_key() + + self.assertEqual(private_key, private_key2) + self.assertNotEqual(private_key, private_key3) + + self.assertEqual(public_key, public_key2) + self.assertNotEqual(public_key, public_key3) + + self.assertNotEqual(public_key, private_key) + + def test_name_consistency(self): + key = ECC.generate(curve="p521") + self.assertIn("curve='NIST P-521'", repr(key)) + self.assertEqual(key.curve, "NIST P-521") + self.assertEqual(key.public_key().curve, "NIST P-521") class TestEccModule_P192(unittest.TestCase): - - def test_generate(self): - - key = ECC.generate(curve="P-192") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(_curves['p192'].Gx, - _curves['p192'].Gy, - "P-192") * key.d, - "p192") - - # Other names - ECC.generate(curve="secp192r1") - ECC.generate(curve="prime192v1") - - def test_construct(self): - - key = ECC.construct(curve="P-192", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p192'].G) - - key = ECC.construct(curve="P-192", point_x=_curves['p192'].Gx, - point_y=_curves['p192'].Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, _curves['p192'].G) - - # Other names - ECC.construct(curve="p192", d=1) - ECC.construct(curve="secp192r1", d=1) - ECC.construct(curve="prime192v1", d=1) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p192'].Gx, point_y=_curves['p192'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-192", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-192", d=2, **coordG) + def test_generate(self): + key = ECC.generate(curve="P-192") + self.assertTrue(key.has_private()) + self.assertEqual( + key.pointQ, + EccPoint( + _curves["p192"].Gx, + _curves["p192"].Gy, + "P-192", + ) + * key.d, + "p192", + ) + + # Other names + ECC.generate(curve="secp192r1") + ECC.generate(curve="prime192v1") + + def test_construct(self): + key = ECC.construct(curve="P-192", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p192"].G) + + key = ECC.construct( + curve="P-192", + point_x=_curves["p192"].Gx, + point_y=_curves["p192"].Gy, + ) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, _curves["p192"].G) + + # Other names + ECC.construct(curve="p192", d=1) + ECC.construct(curve="secp192r1", d=1) + ECC.construct(curve="prime192v1", d=1) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p192"].Gx, point_y=_curves["p192"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="P-192", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-192", d=2, **coordG) class TestEccModule_P224(unittest.TestCase): - - def test_generate(self): - - key = ECC.generate(curve="P-224") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(_curves['p224'].Gx, - _curves['p224'].Gy, - "P-224") * key.d, - "p224") - - # Other names - ECC.generate(curve="secp224r1") - ECC.generate(curve="prime224v1") - - def test_construct(self): - - key = ECC.construct(curve="P-224", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p224'].G) - - key = ECC.construct(curve="P-224", point_x=_curves['p224'].Gx, - point_y=_curves['p224'].Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, _curves['p224'].G) - - # Other names - ECC.construct(curve="p224", d=1) - ECC.construct(curve="secp224r1", d=1) - ECC.construct(curve="prime224v1", d=1) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p224'].Gx, point_y=_curves['p224'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-224", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-224", d=2, **coordG) + def test_generate(self): + key = ECC.generate(curve="P-224") + self.assertTrue(key.has_private()) + self.assertEqual( + key.pointQ, + EccPoint( + _curves["p224"].Gx, + _curves["p224"].Gy, + "P-224", + ) + * key.d, + "p224", + ) + + # Other names + ECC.generate(curve="secp224r1") + ECC.generate(curve="prime224v1") + + def test_construct(self): + key = ECC.construct(curve="P-224", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p224"].G) + + key = ECC.construct( + curve="P-224", + point_x=_curves["p224"].Gx, + point_y=_curves["p224"].Gy, + ) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, _curves["p224"].G) + + # Other names + ECC.construct(curve="p224", d=1) + ECC.construct(curve="secp224r1", d=1) + ECC.construct(curve="prime224v1", d=1) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p224"].Gx, point_y=_curves["p224"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="P-224", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-224", d=2, **coordG) class TestEccModule_P256(unittest.TestCase): - - def test_generate(self): - - key = ECC.generate(curve="P-256") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(_curves['p256'].Gx, - _curves['p256'].Gy) * key.d, - "p256") - - # Other names - ECC.generate(curve="secp256r1") - ECC.generate(curve="prime256v1") - - def test_construct(self): - - key = ECC.construct(curve="P-256", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p256'].G) - - key = ECC.construct(curve="P-256", point_x=_curves['p256'].Gx, - point_y=_curves['p256'].Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, _curves['p256'].G) - - # Other names - ECC.construct(curve="p256", d=1) - ECC.construct(curve="secp256r1", d=1) - ECC.construct(curve="prime256v1", d=1) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p256'].Gx, point_y=_curves['p256'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-256", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-256", d=2, **coordG) + def test_generate(self): + key = ECC.generate(curve="P-256") + self.assertTrue(key.has_private()) + self.assertEqual( + key.pointQ, + EccPoint( + _curves["p256"].Gx, + _curves["p256"].Gy, + ) + * key.d, + "p256", + ) + + # Other names + ECC.generate(curve="secp256r1") + ECC.generate(curve="prime256v1") + + def test_construct(self): + key = ECC.construct(curve="P-256", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p256"].G) + + key = ECC.construct( + curve="P-256", + point_x=_curves["p256"].Gx, + point_y=_curves["p256"].Gy, + ) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, _curves["p256"].G) + + # Other names + ECC.construct(curve="p256", d=1) + ECC.construct(curve="secp256r1", d=1) + ECC.construct(curve="prime256v1", d=1) + + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p256"].Gx, point_y=_curves["p256"].Gy) + + self.assertRaises(ValueError, ECC.construct, curve="P-256", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-256", d=2, **coordG) class TestEccModule_P384(unittest.TestCase): + def test_generate(self): + curve = _curves["p384"] + key = ECC.generate(curve="P-384") + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p384") * key.d) - def test_generate(self): - - curve = _curves['p384'] - key = ECC.generate(curve="P-384") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p384") * key.d) - - # Other names - ECC.generate(curve="secp384r1") - ECC.generate(curve="prime384v1") + # Other names + ECC.generate(curve="secp384r1") + ECC.generate(curve="prime384v1") - def test_construct(self): + def test_construct(self): + curve = _curves["p384"] + key = ECC.construct(curve="P-384", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p384"].G) - curve = _curves['p384'] - key = ECC.construct(curve="P-384", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p384'].G) + key = ECC.construct(curve="P-384", point_x=curve.Gx, point_y=curve.Gy) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, curve.G) - key = ECC.construct(curve="P-384", point_x=curve.Gx, point_y=curve.Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, curve.G) + # Other names + ECC.construct(curve="p384", d=1) + ECC.construct(curve="secp384r1", d=1) + ECC.construct(curve="prime384v1", d=1) - # Other names - ECC.construct(curve="p384", d=1) - ECC.construct(curve="secp384r1", d=1) - ECC.construct(curve="prime384v1", d=1) + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p384"].Gx, point_y=_curves["p384"].Gy) - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p384'].Gx, point_y=_curves['p384'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-384", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-384", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="P-384", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-384", d=2, **coordG) class TestEccModule_P521(unittest.TestCase): + def test_generate(self): + curve = _curves["p521"] + key = ECC.generate(curve="P-521") + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p521") * key.d) - def test_generate(self): - - curve = _curves['p521'] - key = ECC.generate(curve="P-521") - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p521") * key.d) - - # Other names - ECC.generate(curve="secp521r1") - ECC.generate(curve="prime521v1") - - def test_construct(self): + # Other names + ECC.generate(curve="secp521r1") + ECC.generate(curve="prime521v1") - curve = _curves['p521'] - key = ECC.construct(curve="P-521", d=1) - self.assertTrue(key.has_private()) - self.assertEqual(key.pointQ, _curves['p521'].G) + def test_construct(self): + curve = _curves["p521"] + key = ECC.construct(curve="P-521", d=1) + self.assertTrue(key.has_private()) + self.assertEqual(key.pointQ, _curves["p521"].G) - key = ECC.construct(curve="P-521", point_x=curve.Gx, point_y=curve.Gy) - self.assertFalse(key.has_private()) - self.assertEqual(key.pointQ, curve.G) + key = ECC.construct(curve="P-521", point_x=curve.Gx, point_y=curve.Gy) + self.assertFalse(key.has_private()) + self.assertEqual(key.pointQ, curve.G) - # Other names - ECC.construct(curve="p521", d=1) - ECC.construct(curve="secp521r1", d=1) - ECC.construct(curve="prime521v1", d=1) + # Other names + ECC.construct(curve="p521", d=1) + ECC.construct(curve="secp521r1", d=1) + ECC.construct(curve="prime521v1", d=1) - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p521'].Gx, point_y=_curves['p521'].Gy) + def test_negative_construct(self): + coord = dict(point_x=10, point_y=4) + coordG = dict(point_x=_curves["p521"].Gx, point_y=_curves["p521"].Gy) - self.assertRaises(ValueError, ECC.construct, curve="P-521", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-521", d=2, **coordG) + self.assertRaises(ValueError, ECC.construct, curve="P-521", **coord) + self.assertRaises(ValueError, ECC.construct, curve="P-521", d=2, **coordG) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint) - tests += list_test_cases(TestEccPoint_NIST_P192) - tests += list_test_cases(TestEccPoint_NIST_P224) - tests += list_test_cases(TestEccPoint_NIST_P256) - tests += list_test_cases(TestEccPoint_NIST_P384) - tests += list_test_cases(TestEccPoint_NIST_P521) - tests += list_test_cases(TestEccPoint_PAI_P192) - tests += list_test_cases(TestEccPoint_PAI_P224) - tests += list_test_cases(TestEccPoint_PAI_P256) - tests += list_test_cases(TestEccPoint_PAI_P384) - tests += list_test_cases(TestEccPoint_PAI_P521) - tests += list_test_cases(TestEccKey_P192) - tests += list_test_cases(TestEccKey_P224) - tests += list_test_cases(TestEccKey_P256) - tests += list_test_cases(TestEccKey_P384) - tests += list_test_cases(TestEccKey_P521) - tests += list_test_cases(TestEccModule_P192) - tests += list_test_cases(TestEccModule_P224) - tests += list_test_cases(TestEccModule_P256) - tests += list_test_cases(TestEccModule_P384) - tests += list_test_cases(TestEccModule_P521) - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(TestEccPoint) + tests += list_test_cases(TestEccPoint_NIST_P192) + tests += list_test_cases(TestEccPoint_NIST_P224) + tests += list_test_cases(TestEccPoint_NIST_P256) + tests += list_test_cases(TestEccPoint_NIST_P384) + tests += list_test_cases(TestEccPoint_NIST_P521) + tests += list_test_cases(TestEccPoint_PAI_P192) + tests += list_test_cases(TestEccPoint_PAI_P224) + tests += list_test_cases(TestEccPoint_PAI_P256) + tests += list_test_cases(TestEccPoint_PAI_P384) + tests += list_test_cases(TestEccPoint_PAI_P521) + tests += list_test_cases(TestEccKey_P192) + tests += list_test_cases(TestEccKey_P224) + tests += list_test_cases(TestEccKey_P256) + tests += list_test_cases(TestEccKey_P384) + tests += list_test_cases(TestEccKey_P521) + tests += list_test_cases(TestEccModule_P192) + tests += list_test_cases(TestEccModule_P224) + tests += list_test_cases(TestEccModule_P256) + tests += list_test_cases(TestEccModule_P384) + tests += list_test_cases(TestEccModule_P521) + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ElGamal.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ElGamal.py index 67d2e0b2..63a0184a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ElGamal.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_ElGamal.py @@ -25,193 +25,191 @@ __revision__ = "$Id$" import unittest -from Cryptodome.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex +from Cryptodome.SelfTest.st_common import list_test_cases, a2b_hex from Cryptodome import Random from Cryptodome.PublicKey import ElGamal from Cryptodome.Util.number import bytes_to_long from Cryptodome.Util.py3compat import * + class ElGamalTest(unittest.TestCase): + # + # Test vectors + # + # There seem to be no real ElGamal test vectors available in the + # public domain. The following test vectors have been generated + # with libgcrypt 1.5.0. + # + # Encryption + tve = [ + { + # 256 bits + "p": "BA4CAEAAED8CBE952AFD2126C63EB3B345D65C2A0A73D2A3AD4138B6D09BD933", + "g": "05", + "y": "60D063600ECED7C7C55146020E7A31C4476E9793BEAED420FEC9E77604CAE4EF", + "x": "1D391BA2EE3C37FE1BA175A69B2C73A11238AD77675932", + "k": "F5893C5BAB4131264066F57AB3D8AD89E391A0B68A68A1", + "pt": "48656C6C6F207468657265", + "ct1": "32BFD5F487966CEA9E9356715788C491EC515E4ED48B58F0F00971E93AAA5EC7", + "ct2": "7BE8FBFF317C93E82FCEF9BD515284BA506603FEA25D01C0CB874A31F315EE68", + }, + { + # 512 bits + "p": "F1B18AE9F7B4E08FDA9A04832F4E919D89462FD31BF12F92791A93519F75076D6CE3942689CDFF2F344CAFF0F82D01864F69F3AECF566C774CBACF728B81A227", + "g": "07", + "y": "688628C676E4F05D630E1BE39D0066178CA7AA83836B645DE5ADD359B4825A12B02EF4252E4E6FA9BEC1DB0BE90F6D7C8629CABB6E531F472B2664868156E20C", + "x": "14E60B1BDFD33436C0DA8A22FDC14A2CCDBBED0627CE68", + "k": "38DBF14E1F319BDA9BAB33EEEADCAF6B2EA5250577ACE7", + "pt": "48656C6C6F207468657265", + "ct1": "290F8530C2CC312EC46178724F196F308AD4C523CEABB001FACB0506BFED676083FE0F27AC688B5C749AB3CB8A80CD6F7094DBA421FB19442F5A413E06A9772B", + "ct2": "1D69AAAD1DC50493FB1B8E8721D621D683F3BF1321BE21BC4A43E11B40C9D4D9C80DE3AAC2AB60D31782B16B61112E68220889D53C4C3136EE6F6CE61F8A23A0", + }, + ] + + # Signature + tvs = [ + { + # 256 bits + "p": "D2F3C41EA66530838A704A48FFAC9334F4701ECE3A97CEE4C69DD01AE7129DD7", + "g": "05", + "y": "C3F9417DC0DAFEA6A05C1D2333B7A95E63B3F4F28CC962254B3256984D1012E7", + "x": "165E4A39BE44D5A2D8B1332D416BC559616F536BC735BB", + "k": "C7F0C794A7EAD726E25A47FF8928013680E73C51DD3D7D99BFDA8F492585928F", + "h": "48656C6C6F207468657265", + "sig1": "35CA98133779E2073EF31165AFCDEB764DD54E96ADE851715495F9C635E1E7C2", + "sig2": "0135B88B1151279FE5D8078D4FC685EE81177EE9802AB123A73925FC1CB059A7", + }, + { + # 512 bits + "p": "E24CF3A4B8A6AF749DCA6D714282FE4AABEEE44A53BB6ED15FBE32B5D3C3EF9CC4124A2ECA331F3C1C1B667ACA3766825217E7B5F9856648D95F05330C6A19CF", + "g": "0B", + "y": "2AD3A1049CA5D4ED207B2431C79A8719BB4073D4A94E450EA6CEE8A760EB07ADB67C0D52C275EE85D7B52789061EE45F2F37D9B2AE522A51C28329766BFE68AC", + "x": "16CBB4F46D9ECCF24FF9F7E63CAA3BD8936341555062AB", + "k": "8A3D89A4E429FD2476D7D717251FB79BF900FFE77444E6BB8299DC3F84D0DD57ABAB50732AE158EA52F5B9E7D8813E81FD9F79470AE22F8F1CF9AEC820A78C69", + "h": "48656C6C6F207468657265", + "sig1": "BE001AABAFFF976EC9016198FBFEA14CBEF96B000CCC0063D3324016F9E91FE80D8F9325812ED24DDB2B4D4CF4430B169880B3CE88313B53255BD4EC0378586F", + "sig2": "5E266F3F837BA204E3BBB6DBECC0611429D96F8C7CE8F4EFDF9D4CB681C2A954468A357BF4242CEC7418B51DFC081BCD21299EF5B5A0DDEF3A139A1817503DDE", + }, + ] + + def test_generate_180(self): + self._test_random_key(180) + + def test_encryption(self): + for tv in self.tve: + d = self.convert_tv(tv, True) + key = ElGamal.construct(d["key"]) + ct = key._encrypt(d["pt"], d["k"]) + self.assertEqual(ct[0], d["ct1"]) + self.assertEqual(ct[1], d["ct2"]) + + def test_decryption(self): + for tv in self.tve: + d = self.convert_tv(tv, True) + key = ElGamal.construct(d["key"]) + pt = key._decrypt((d["ct1"], d["ct2"])) + self.assertEqual(pt, d["pt"]) + + def test_signing(self): + for tv in self.tvs: + d = self.convert_tv(tv, True) + key = ElGamal.construct(d["key"]) + sig1, sig2 = key._sign(d["h"], d["k"]) + self.assertEqual(sig1, d["sig1"]) + self.assertEqual(sig2, d["sig2"]) + + def test_verification(self): + for tv in self.tvs: + d = self.convert_tv(tv, True) + key = ElGamal.construct(d["key"]) + # Positive test + res = key._verify(d["h"], (d["sig1"], d["sig2"])) + self.assertTrue(res) + # Negative test + res = key._verify(d["h"], (d["sig1"] + 1, d["sig2"])) + self.assertFalse(res) + + def test_bad_key3(self): + tup = tup0 = list(self.convert_tv(self.tvs[0], 1)["key"])[:3] + tup[0] += 1 # p += 1 (not prime) + self.assertRaises(ValueError, ElGamal.construct, tup) + + tup = tup0 + tup[1] = 1 # g = 1 + self.assertRaises(ValueError, ElGamal.construct, tup) + + tup = tup0 + tup[2] = tup[0] * 2 # y = 2*p + self.assertRaises(ValueError, ElGamal.construct, tup) + + def test_bad_key4(self): + tup = tup0 = list(self.convert_tv(self.tvs[0], 1)["key"]) + tup[3] += 1 # x += 1 + self.assertRaises(ValueError, ElGamal.construct, tup) + + def convert_tv(self, tv, as_longs=0): + """Convert a test vector from textual form (hexadecimal ascii + to either integers or byte strings.""" + key_comps = "p", "g", "y", "x" + tv2 = {} + for c in tv.keys(): + tv2[c] = a2b_hex(tv[c]) + if as_longs or c in key_comps or c in ("sig1", "sig2"): + tv2[c] = bytes_to_long(tv2[c]) + tv2["key"] = [] + for c in key_comps: + tv2["key"] += [tv2[c]] + del tv2[c] + return tv2 + + def _test_random_key(self, bits): + elgObj = ElGamal.generate(bits, Random.new().read) + self._check_private_key(elgObj) + self._exercise_primitive(elgObj) + pub = elgObj.publickey() + self._check_public_key(pub) + self._exercise_public_primitive(elgObj) + + def _check_private_key(self, elgObj): + # Check capabilities + self.assertTrue(elgObj.has_private()) + + # Sanity check key data + self.assertTrue(1 < elgObj.g < (elgObj.p - 1)) + self.assertEqual(pow(elgObj.g, elgObj.p - 1, elgObj.p), 1) + self.assertTrue(1 < elgObj.x < (elgObj.p - 1)) + self.assertEqual(pow(elgObj.g, elgObj.x, elgObj.p), elgObj.y) + + def _check_public_key(self, elgObj): + # Check capabilities + self.assertFalse(elgObj.has_private()) + + # Sanity check key data + self.assertTrue(1 < elgObj.g < (elgObj.p - 1)) + self.assertEqual(pow(elgObj.g, elgObj.p - 1, elgObj.p), 1) + + def _exercise_primitive(self, elgObj): + # Test encryption/decryption + plaintext = 127218 + ciphertext = elgObj._encrypt(plaintext, 123456789) + plaintextP = elgObj._decrypt(ciphertext) + self.assertEqual(plaintext, plaintextP) + + # Test signature/verification + signature = elgObj._sign(plaintext, 987654321) + elgObj._verify(plaintext, signature) + + def _exercise_public_primitive(self, elgObj): + plaintext = 92987276 + ciphertext = elgObj._encrypt(plaintext, 123456789) - # - # Test vectors - # - # There seem to be no real ElGamal test vectors available in the - # public domain. The following test vectors have been generated - # with libgcrypt 1.5.0. - # - # Encryption - tve=[ - { - # 256 bits - 'p' :'BA4CAEAAED8CBE952AFD2126C63EB3B345D65C2A0A73D2A3AD4138B6D09BD933', - 'g' :'05', - 'y' :'60D063600ECED7C7C55146020E7A31C4476E9793BEAED420FEC9E77604CAE4EF', - 'x' :'1D391BA2EE3C37FE1BA175A69B2C73A11238AD77675932', - 'k' :'F5893C5BAB4131264066F57AB3D8AD89E391A0B68A68A1', - 'pt' :'48656C6C6F207468657265', - 'ct1':'32BFD5F487966CEA9E9356715788C491EC515E4ED48B58F0F00971E93AAA5EC7', - 'ct2':'7BE8FBFF317C93E82FCEF9BD515284BA506603FEA25D01C0CB874A31F315EE68' - }, - - { - # 512 bits - 'p' :'F1B18AE9F7B4E08FDA9A04832F4E919D89462FD31BF12F92791A93519F75076D6CE3942689CDFF2F344CAFF0F82D01864F69F3AECF566C774CBACF728B81A227', - 'g' :'07', - 'y' :'688628C676E4F05D630E1BE39D0066178CA7AA83836B645DE5ADD359B4825A12B02EF4252E4E6FA9BEC1DB0BE90F6D7C8629CABB6E531F472B2664868156E20C', - 'x' :'14E60B1BDFD33436C0DA8A22FDC14A2CCDBBED0627CE68', - 'k' :'38DBF14E1F319BDA9BAB33EEEADCAF6B2EA5250577ACE7', - 'pt' :'48656C6C6F207468657265', - 'ct1':'290F8530C2CC312EC46178724F196F308AD4C523CEABB001FACB0506BFED676083FE0F27AC688B5C749AB3CB8A80CD6F7094DBA421FB19442F5A413E06A9772B', - 'ct2':'1D69AAAD1DC50493FB1B8E8721D621D683F3BF1321BE21BC4A43E11B40C9D4D9C80DE3AAC2AB60D31782B16B61112E68220889D53C4C3136EE6F6CE61F8A23A0' - } - ] - - # Signature - tvs=[ - { - # 256 bits - 'p' :'D2F3C41EA66530838A704A48FFAC9334F4701ECE3A97CEE4C69DD01AE7129DD7', - 'g' :'05', - 'y' :'C3F9417DC0DAFEA6A05C1D2333B7A95E63B3F4F28CC962254B3256984D1012E7', - 'x' :'165E4A39BE44D5A2D8B1332D416BC559616F536BC735BB', - 'k' :'C7F0C794A7EAD726E25A47FF8928013680E73C51DD3D7D99BFDA8F492585928F', - 'h' :'48656C6C6F207468657265', - 'sig1':'35CA98133779E2073EF31165AFCDEB764DD54E96ADE851715495F9C635E1E7C2', - 'sig2':'0135B88B1151279FE5D8078D4FC685EE81177EE9802AB123A73925FC1CB059A7', - }, - { - # 512 bits - 'p' :'E24CF3A4B8A6AF749DCA6D714282FE4AABEEE44A53BB6ED15FBE32B5D3C3EF9CC4124A2ECA331F3C1C1B667ACA3766825217E7B5F9856648D95F05330C6A19CF', - 'g' :'0B', - 'y' :'2AD3A1049CA5D4ED207B2431C79A8719BB4073D4A94E450EA6CEE8A760EB07ADB67C0D52C275EE85D7B52789061EE45F2F37D9B2AE522A51C28329766BFE68AC', - 'x' :'16CBB4F46D9ECCF24FF9F7E63CAA3BD8936341555062AB', - 'k' :'8A3D89A4E429FD2476D7D717251FB79BF900FFE77444E6BB8299DC3F84D0DD57ABAB50732AE158EA52F5B9E7D8813E81FD9F79470AE22F8F1CF9AEC820A78C69', - 'h' :'48656C6C6F207468657265', - 'sig1':'BE001AABAFFF976EC9016198FBFEA14CBEF96B000CCC0063D3324016F9E91FE80D8F9325812ED24DDB2B4D4CF4430B169880B3CE88313B53255BD4EC0378586F', - 'sig2':'5E266F3F837BA204E3BBB6DBECC0611429D96F8C7CE8F4EFDF9D4CB681C2A954468A357BF4242CEC7418B51DFC081BCD21299EF5B5A0DDEF3A139A1817503DDE', - } - ] - - def test_generate_180(self): - self._test_random_key(180) - - def test_encryption(self): - for tv in self.tve: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - ct = key._encrypt(d['pt'], d['k']) - self.assertEqual(ct[0], d['ct1']) - self.assertEqual(ct[1], d['ct2']) - - def test_decryption(self): - for tv in self.tve: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - pt = key._decrypt((d['ct1'], d['ct2'])) - self.assertEqual(pt, d['pt']) - - def test_signing(self): - for tv in self.tvs: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - sig1, sig2 = key._sign(d['h'], d['k']) - self.assertEqual(sig1, d['sig1']) - self.assertEqual(sig2, d['sig2']) - - def test_verification(self): - for tv in self.tvs: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - # Positive test - res = key._verify( d['h'], (d['sig1'],d['sig2']) ) - self.assertTrue(res) - # Negative test - res = key._verify( d['h'], (d['sig1']+1,d['sig2']) ) - self.assertFalse(res) - - def test_bad_key3(self): - tup = tup0 = list(self.convert_tv(self.tvs[0], 1)['key'])[:3] - tup[0] += 1 # p += 1 (not prime) - self.assertRaises(ValueError, ElGamal.construct, tup) - - tup = tup0 - tup[1] = 1 # g = 1 - self.assertRaises(ValueError, ElGamal.construct, tup) - - tup = tup0 - tup[2] = tup[0]*2 # y = 2*p - self.assertRaises(ValueError, ElGamal.construct, tup) - - def test_bad_key4(self): - tup = tup0 = list(self.convert_tv(self.tvs[0], 1)['key']) - tup[3] += 1 # x += 1 - self.assertRaises(ValueError, ElGamal.construct, tup) - - def convert_tv(self, tv, as_longs=0): - """Convert a test vector from textual form (hexadecimal ascii - to either integers or byte strings.""" - key_comps = 'p','g','y','x' - tv2 = {} - for c in tv.keys(): - tv2[c] = a2b_hex(tv[c]) - if as_longs or c in key_comps or c in ('sig1','sig2'): - tv2[c] = bytes_to_long(tv2[c]) - tv2['key']=[] - for c in key_comps: - tv2['key'] += [tv2[c]] - del tv2[c] - return tv2 - - def _test_random_key(self, bits): - elgObj = ElGamal.generate(bits, Random.new().read) - self._check_private_key(elgObj) - self._exercise_primitive(elgObj) - pub = elgObj.publickey() - self._check_public_key(pub) - self._exercise_public_primitive(elgObj) - - def _check_private_key(self, elgObj): - - # Check capabilities - self.assertTrue(elgObj.has_private()) - - # Sanity check key data - self.assertTrue(1 1) # p > 1 - self.assertEqual(1, rsaObj.q > 1) # q > 1 - self.assertEqual(1, rsaObj.e > 1) # e > 1 - self.assertEqual(1, rsaObj.d > 1) # d > 1 - - self.assertEqual(rsaObj.u, rsaObj.invp) - self.assertEqual(1, rsaObj.q * rsaObj.invq % rsaObj.p) - - def _check_public_key(self, rsaObj): - ciphertext = a2b_hex(self.ciphertext) + def setUp(self): + global RSA, Random, bytes_to_long + from Cryptodome.PublicKey import RSA + from Cryptodome import Random + from Cryptodome.Util.number import bytes_to_long, inverse + + self.n = bytes_to_long(a2b_hex(self.modulus)) + self.p = bytes_to_long(a2b_hex(self.prime_factor)) + + # Compute q, d, and u from n, e, and p + self.q = self.n // self.p + self.d = inverse(self.e, (self.p - 1) * (self.q - 1)) + self.u = inverse(self.p, self.q) # u = e**-1 (mod q) + + self.rsa = RSA + + def test_generate_1arg(self): + """RSA (default implementation) generated key (1 argument)""" + rsaObj = self.rsa.generate(1024) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.public_key() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + + def test_generate_2arg(self): + """RSA (default implementation) generated key (2 arguments)""" + rsaObj = self.rsa.generate(1024, Random.new().read) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.public_key() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + + def test_generate_3args(self): + rsaObj = self.rsa.generate(1024, Random.new().read, e=65537) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.public_key() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + self.assertEqual(65537, rsaObj.e) + + def test_construct_2tuple(self): + """RSA (default implementation) constructed key (2-tuple)""" + pub = self.rsa.construct((self.n, self.e)) + self._check_public_key(pub) + self._check_encryption(pub) + + def test_construct_3tuple(self): + """RSA (default implementation) constructed key (3-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d)) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + + def test_construct_4tuple(self): + """RSA (default implementation) constructed key (4-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p)) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + + def test_construct_5tuple(self): + """RSA (default implementation) constructed key (5-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q)) + self._check_private_key(rsaObj) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + + def test_construct_6tuple(self): + """RSA (default implementation) constructed key (6-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q, self.u)) + self._check_private_key(rsaObj) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + + def test_construct_bad_key2(self): + tup = (self.n, 1) + self.assertRaises(ValueError, self.rsa.construct, tup) + + # An even modulus is wrong + tup = (self.n + 1, self.e) + self.assertRaises(ValueError, self.rsa.construct, tup) + + def test_construct_bad_key3(self): + tup = (self.n, self.e, self.d + 1) + self.assertRaises(ValueError, self.rsa.construct, tup) + + def test_construct_bad_key5(self): + tup = (self.n, self.e, self.d, self.p, self.p) + self.assertRaises(ValueError, self.rsa.construct, tup) + + tup = (self.p * self.p, self.e, self.p, self.p) + self.assertRaises(ValueError, self.rsa.construct, tup) + + tup = (self.p * self.p, 3, self.p, self.q) + self.assertRaises(ValueError, self.rsa.construct, tup) + + def test_construct_bad_key6(self): + tup = (self.n, self.e, self.d, self.p, self.q, 10) + self.assertRaises(ValueError, self.rsa.construct, tup) + + from Cryptodome.Util.number import inverse + + tup = (self.n, self.e, self.d, self.p, self.q, inverse(self.q, self.p)) + self.assertRaises(ValueError, self.rsa.construct, tup) + + def test_factoring(self): + rsaObj = self.rsa.construct([self.n, self.e, self.d]) + self.assertTrue(rsaObj.p == self.p or rsaObj.p == self.q) + self.assertTrue(rsaObj.q == self.p or rsaObj.q == self.q) + self.assertTrue(rsaObj.q * rsaObj.p == self.n) + + self.assertRaises(ValueError, self.rsa.construct, [self.n, self.e, self.n - 1]) + + def test_repr(self): + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q)) + repr(rsaObj) + + def test_serialization(self): + """RSA keys are unpickable""" + + rsa_key = self.rsa.generate(1024) + self.assertRaises(PicklingError, pickle.dumps, rsa_key) + + def test_raw_rsa_boundary(self): + # The argument of every RSA raw operation (encrypt/decrypt) must be + # non-negative and no larger than the modulus + rsa_obj = self.rsa.generate(1024) + + self.assertRaises(ValueError, rsa_obj._decrypt, rsa_obj.n) + self.assertRaises(ValueError, rsa_obj._decrypt_to_bytes, rsa_obj.n) + self.assertRaises(ValueError, rsa_obj._encrypt, rsa_obj.n) + + self.assertRaises(ValueError, rsa_obj._decrypt, -1) + self.assertRaises(ValueError, rsa_obj._decrypt_to_bytes, -1) + self.assertRaises(ValueError, rsa_obj._encrypt, -1) + + def test_size(self): + pub = self.rsa.construct((self.n, self.e)) + self.assertEqual(pub.size_in_bits(), 1024) + self.assertEqual(pub.size_in_bytes(), 128) + + def _check_private_key(self, rsaObj): + from Cryptodome.Math.Numbers import Integer + + # Check capabilities + self.assertEqual(1, rsaObj.has_private()) + + # Sanity check key data + self.assertEqual(rsaObj.n, rsaObj.p * rsaObj.q) # n = pq + lcm = int(Integer(rsaObj.p - 1).lcm(rsaObj.q - 1)) + self.assertEqual(1, rsaObj.d * rsaObj.e % lcm) # ed = 1 (mod LCM(p-1, q-1)) + self.assertEqual(1, rsaObj.p * rsaObj.u % rsaObj.q) # pu = 1 (mod q) + self.assertEqual(1, rsaObj.p > 1) # p > 1 + self.assertEqual(1, rsaObj.q > 1) # q > 1 + self.assertEqual(1, rsaObj.e > 1) # e > 1 + self.assertEqual(1, rsaObj.d > 1) # d > 1 + + self.assertEqual(rsaObj.u, rsaObj.invp) + self.assertEqual(1, rsaObj.q * rsaObj.invq % rsaObj.p) - # Check capabilities - self.assertEqual(0, rsaObj.has_private()) + def _check_public_key(self, rsaObj): + ciphertext = a2b_hex(self.ciphertext) - # Check rsaObj.[ne] -> rsaObj.[ne] mapping - self.assertEqual(rsaObj.n, rsaObj.n) - self.assertEqual(rsaObj.e, rsaObj.e) + # Check capabilities + self.assertEqual(0, rsaObj.has_private()) - # Check that private parameters are all missing - self.assertEqual(0, hasattr(rsaObj, 'd')) - self.assertEqual(0, hasattr(rsaObj, 'p')) - self.assertEqual(0, hasattr(rsaObj, 'q')) - self.assertEqual(0, hasattr(rsaObj, 'u')) + # Check rsaObj.[ne] -> rsaObj.[ne] mapping + self.assertEqual(rsaObj.n, rsaObj.n) + self.assertEqual(rsaObj.e, rsaObj.e) - # Sanity check key data - self.assertEqual(1, rsaObj.e > 1) # e > 1 + # Check that private parameters are all missing + self.assertEqual(0, hasattr(rsaObj, "d")) + self.assertEqual(0, hasattr(rsaObj, "p")) + self.assertEqual(0, hasattr(rsaObj, "q")) + self.assertEqual(0, hasattr(rsaObj, "u")) - # Public keys should not be able to sign or decrypt - self.assertRaises(TypeError, rsaObj._decrypt, - bytes_to_long(ciphertext)) - self.assertRaises(TypeError, rsaObj._decrypt_to_bytes, - bytes_to_long(ciphertext)) + # Sanity check key data + self.assertEqual(1, rsaObj.e > 1) # e > 1 - # Check __eq__ and __ne__ - self.assertEqual(rsaObj.public_key() == rsaObj.public_key(),True) # assert_ - self.assertEqual(rsaObj.public_key() != rsaObj.public_key(),False) # assertFalse + # Public keys should not be able to sign or decrypt + self.assertRaises( + TypeError, + rsaObj._decrypt, + bytes_to_long(ciphertext), + ) + self.assertRaises( + TypeError, + rsaObj._decrypt_to_bytes, + bytes_to_long(ciphertext), + ) - self.assertEqual(rsaObj.publickey(), rsaObj.public_key()) + # Check __eq__ and __ne__ + self.assertEqual(rsaObj.public_key() == rsaObj.public_key(), True) # assert_ + self.assertEqual(rsaObj.public_key() != rsaObj.public_key(), False) # assertFalse - def _exercise_primitive(self, rsaObj): - # Since we're using a randomly-generated key, we can't check the test - # vector, but we can make sure encryption and decryption are inverse - # operations. - ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) + self.assertEqual(rsaObj.publickey(), rsaObj.public_key()) - # Test decryption - plaintext = rsaObj._decrypt(ciphertext) + def _exercise_primitive(self, rsaObj): + # Since we're using a randomly-generated key, we can't check the test + # vector, but we can make sure encryption and decryption are inverse + # operations. + ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) - # Test encryption (2 arguments) - new_ciphertext2 = rsaObj._encrypt(plaintext) - self.assertEqual(ciphertext, new_ciphertext2) + # Test decryption + plaintext = rsaObj._decrypt(ciphertext) + + # Test encryption (2 arguments) + new_ciphertext2 = rsaObj._encrypt(plaintext) + self.assertEqual(ciphertext, new_ciphertext2) - def _exercise_public_primitive(self, rsaObj): - plaintext = a2b_hex(self.plaintext) + def _exercise_public_primitive(self, rsaObj): + plaintext = a2b_hex(self.plaintext) - # Test encryption (2 arguments) - new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) + # Test encryption (2 arguments) + new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) - def _check_encryption(self, rsaObj): - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) + def _check_encryption(self, rsaObj): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) - # Test encryption - new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) - self.assertEqual(bytes_to_long(ciphertext), new_ciphertext2) + # Test encryption + new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) + self.assertEqual(bytes_to_long(ciphertext), new_ciphertext2) + + def _check_decryption(self, rsaObj): + plaintext = bytes_to_long(a2b_hex(self.plaintext)) + ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) - def _check_decryption(self, rsaObj): - plaintext = bytes_to_long(a2b_hex(self.plaintext)) - ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) - - # Test plain decryption - new_plaintext = rsaObj._decrypt(ciphertext) - self.assertEqual(plaintext, new_plaintext) + # Test plain decryption + new_plaintext = rsaObj._decrypt(ciphertext) + self.assertEqual(plaintext, new_plaintext) def get_tests(config={}): - tests = [] - tests += list_test_cases(RSATest) - return tests + tests = [] + tests += list_test_cases(RSATest) + return tests + -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_Curve25519.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_Curve25519.py index 2401eace..600650c5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_Curve25519.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_Curve25519.py @@ -43,343 +43,381 @@ from Cryptodome.PublicKey import ECC try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False def load_file(file_name, mode="rb"): - results = None + results = None - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) - dir_comps = ("PublicKey", "ECC") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() + dir_comps = ("PublicKey", "ECC") + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name, mode) as file_in: + results = file_in.read() - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for ECC", - UserWarning, - stacklevel=2) + except FileNotFoundError: + warnings.warn( + "Warning: skipping extended tests for ECC", + UserWarning, + stacklevel=2, + ) - if results is None: - raise SkipTest("Missing %s" % file_name) + if results is None: + raise SkipTest("Missing %s" % file_name) - return results + return results def compact(lines): - ext = b"".join(lines) - return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) + ext = b"".join(lines) + return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) def create_ref_keys_x25519(): - key_lines = load_file("ecc_x25519.txt").splitlines() - seed = compact(key_lines[5:8]) - key = ECC.construct(curve="Curve25519", seed=seed) - return (key, key.public_key()) + key_lines = load_file("ecc_x25519.txt").splitlines() + seed = compact(key_lines[5:8]) + key = ECC.construct(curve="Curve25519", seed=seed) + return (key, key.public_key()) def get_fixed_prng(): - return SHAKE128.new().update(b"SEED").read + return SHAKE128.new().update(b"SEED").read def extract_bitstring_from_spki(data): - seq = DerSequence() - seq.decode(data) - bs = DerBitString() - bs.decode(seq[1]) - return bs.value + seq = DerSequence() + seq.decode(data) + bs = DerBitString() + bs.decode(seq[1]) + return bs.value class TestImport(unittest.TestCase): + def test_empty(self): + self.assertRaises(ValueError, ECC.import_key, b"") - def test_empty(self): - self.assertRaises(ValueError, ECC.import_key, b"") - - def test_mismatch(self): - # Private key with X448 Object ID but X25519 key - mismatch_hex = "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79" - mismatch = unhexlify(mismatch_hex) - self.assertRaises(ValueError, ECC.import_key, mismatch) + def test_mismatch(self): + # Private key with X448 Object ID but X25519 key + mismatch_hex = ( + "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79" + ) + mismatch = unhexlify(mismatch_hex) + self.assertRaises(ValueError, ECC.import_key, mismatch) class TestImport_Curve25519(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_Curve25519, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_x25519() - def __init__(self, *args, **kwargs): - super(TestImport_Curve25519, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_x25519() - - def test_import_public_der(self): - key_file = load_file("ecc_x25519_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_x25519_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_pkcs8_der(self): - key_file = load_file("ecc_x25519_private.der") + def test_import_pkcs8_der(self): + key_file = load_file("ecc_x25519_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_x25519_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_x25519_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_x25519_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_x25519_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_x25519_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_x25519_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_x25519_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_x25519_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_x25519_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_x25519_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_x25519_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_x25519_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256": - key_file = load_file("ecc_x25519_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256": + key_file = load_file("ecc_x25519_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_x25519_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_x25519_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) class TestExport_Curve25519(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestExport_Curve25519, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_x25519() - - def test_export_public_der(self): - key_file = load_file("ecc_x25519_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(True) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_x25519_private.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - self.assertRaises(ValueError, self.ref_private.export_key, - format="DER", use_pkcs8=False) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", - prot_params={'iteration_count': 123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_public_pem(self): - key_file_ref = load_file("ecc_x25519_public.pem", "rt").strip() - key_file = self.ref_public.export_key(format="PEM").strip() - self.assertEqual(key_file_ref, key_file) - - def test_export_private_pem_clear(self): - key_file = load_file("ecc_x25519_private.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM").strip() - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_raw(self): - encoded = self.ref_public.export_key(format='raw') - self.assertEqual(len(encoded), 32) - self.assertEqual(encoded, unhexlify(b'ff7561ef60c9c8a757f6d6372ec14142c9be208d0e719136d8d3c715dfcf7e15')) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="secret") - - # Empty password - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="", - use_pkcs8=False) - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, - self.ref_private.export_key, - format="OpenSSH", - passphrase="secret") + def __init__(self, *args, **kwargs): + super(TestExport_Curve25519, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_x25519() + + def test_export_public_der(self): + key_file = load_file("ecc_x25519_public.der") + + encoded = self.ref_public._export_subjectPublicKeyInfo(True) + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_x25519_private.der") + + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) + + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + use_pkcs8=False, + ) + + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_public_pem(self): + key_file_ref = load_file("ecc_x25519_public.pem", "rt").strip() + key_file = self.ref_public.export_key(format="PEM").strip() + self.assertEqual(key_file_ref, key_file) + + def test_export_private_pem_clear(self): + key_file = load_file("ecc_x25519_private.pem", "rt").strip() + encoded = self.ref_private.export_key(format="PEM").strip() + self.assertEqual(key_file, encoded) + + def test_export_private_pem_encrypted(self): + encoded = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_raw(self): + encoded = self.ref_public.export_key(format="raw") + self.assertEqual(len(encoded), 32) + self.assertEqual( + encoded, unhexlify(b"ff7561ef60c9c8a757f6d6372ec14142c9be208d0e719136d8d3c715dfcf7e15") + ) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) class TestImport_Curve25519_Weak(unittest.TestCase): + def test_weak_pem(self): + p = 2**255 - 19 + weak_x = ( + 0, + 1, + 325606250916557431795983626356110631294008115727848805560023387167927233504, + 39382357235489614581723060781553021112529911719440698176882885853963445705823, + p - 1, + p, + p + 1, + p + 325606250916557431795983626356110631294008115727848805560023387167927233504, + p + 39382357235489614581723060781553021112529911719440698176882885853963445705823, + p * 2 - 1, + p * 2, + p * 2 + 1, + ) + + for x in weak_x: + low_order_point = ECC.EccXPoint(x, "curve25519") + weak_key = ECC.EccKey(point=low_order_point, curve="curve25519") + encoded = weak_key.export_key(format="PEM") + + self.assertRaises( + ValueError, + ECC.import_key, + encoded, + ) - def test_weak_pem(self): - p = 2**255 - 19 - weak_x = (0, - 1, - 325606250916557431795983626356110631294008115727848805560023387167927233504, - 39382357235489614581723060781553021112529911719440698176882885853963445705823, - p - 1, - p, - p + 1, - p + 325606250916557431795983626356110631294008115727848805560023387167927233504, - p + 39382357235489614581723060781553021112529911719440698176882885853963445705823, - p * 2 - 1, - p * 2, - p * 2 + 1) +def get_tests(config={}): + tests = [] + try: + tests += list_test_cases(TestImport) + tests += list_test_cases(TestImport_Curve25519) + tests += list_test_cases(TestExport_Curve25519) + tests += list_test_cases(TestImport_Curve25519_Weak) + except SkipTest: + pass + return tests - for x in weak_x: - low_order_point = ECC.EccXPoint(x, "curve25519") - weak_key = ECC.EccKey(point=low_order_point, curve="curve25519") - encoded = weak_key.export_key(format="PEM") - self.assertRaises(ValueError, - ECC.import_key, - encoded) +if __name__ == "__main__": + def suit(): + return unittest.TestSuite(get_tests()) -def get_tests(config={}): - tests = [] - try: - tests += list_test_cases(TestImport) - tests += list_test_cases(TestImport_Curve25519) - tests += list_test_cases(TestExport_Curve25519) - tests += list_test_cases(TestImport_Curve25519_Weak) - except SkipTest: - pass - return tests - - -if __name__ == '__main__': - def suit(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_Curve448.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_Curve448.py index e1b343b4..9147b4e7 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_Curve448.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_Curve448.py @@ -16,336 +16,377 @@ from Cryptodome.PublicKey import ECC try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False def load_file(file_name, mode="rb"): - results = None + results = None - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) - dir_comps = ("PublicKey", "ECC") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() + dir_comps = ("PublicKey", "ECC") + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name, mode) as file_in: + results = file_in.read() - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for ECC", - UserWarning, - stacklevel=2) + except FileNotFoundError: + warnings.warn( + "Warning: skipping extended tests for ECC", + UserWarning, + stacklevel=2, + ) - if results is None: - raise SkipTest("Missing %s" % file_name) + if results is None: + raise SkipTest("Missing %s" % file_name) - return results + return results def compact(lines): - ext = b"".join(lines) - return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) + ext = b"".join(lines) + return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) def create_ref_keys_x448(): - key_lines = load_file("ecc_x448.txt").splitlines() - seed = compact(key_lines[6:10]) - key = ECC.construct(curve="Curve448", seed=seed) - return (key, key.public_key()) + key_lines = load_file("ecc_x448.txt").splitlines() + seed = compact(key_lines[6:10]) + key = ECC.construct(curve="Curve448", seed=seed) + return (key, key.public_key()) def get_fixed_prng(): - return SHAKE128.new().update(b"SEED").read + return SHAKE128.new().update(b"SEED").read def extract_bitstring_from_spki(data): - seq = DerSequence() - seq.decode(data) - bs = DerBitString() - bs.decode(seq[1]) - return bs.value + seq = DerSequence() + seq.decode(data) + bs = DerBitString() + bs.decode(seq[1]) + return bs.value class TestImport(unittest.TestCase): + def test_empty(self): + self.assertRaises(ValueError, ECC.import_key, b"") - def test_empty(self): - self.assertRaises(ValueError, ECC.import_key, b"") - - def test_mismatch(self): - # Private key with X448 Object ID but X448 key - mismatch_hex = "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79" - mismatch = unhexlify(mismatch_hex) - self.assertRaises(ValueError, ECC.import_key, mismatch) + def test_mismatch(self): + # Private key with X448 Object ID but X448 key + mismatch_hex = ( + "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79" + ) + mismatch = unhexlify(mismatch_hex) + self.assertRaises(ValueError, ECC.import_key, mismatch) class TestImport_Curve448(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_Curve448, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_x448() - def __init__(self, *args, **kwargs): - super(TestImport_Curve448, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_x448() - - def test_import_public_der(self): - key_file = load_file("ecc_x448_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_x448_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_pkcs8_der(self): - key_file = load_file("ecc_x448_private.der") + def test_import_pkcs8_der(self): + key_file = load_file("ecc_x448_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_x448_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_x448_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_x448_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_x448_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_x448_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_x448_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_x448_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_x448_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_x448_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_x448_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_x448_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_x448_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256": - key_file = load_file("ecc_x448_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256": + key_file = load_file("ecc_x448_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_x448_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_x448_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) class TestExport_Curve448(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestExport_Curve448, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_x448() - - def test_export_public_der(self): - key_file = load_file("ecc_x448_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(True) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_x448_private.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - self.assertRaises(ValueError, self.ref_private.export_key, - format="DER", use_pkcs8=False) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", - prot_params={'iteration_count': 123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_public_pem(self): - key_file_ref = load_file("ecc_x448_public.pem", "rt").strip() - key_file = self.ref_public.export_key(format="PEM").strip() - self.assertEqual(key_file_ref, key_file) - - def test_export_private_pem_clear(self): - key_file = load_file("ecc_x448_private.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM").strip() - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_raw(self): - encoded = self.ref_public.export_key(format='raw') - self.assertEqual(len(encoded), 56) - self.assertEqual(encoded, unhexlify(b'e2abae24ab8f65b01969e61f84fee615b525f413a90e3d727f71d0ffe60fb1d0a1a0285f2a7fd88789206e0aa4f3e9fcb9e4ba5d644e691e')) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="secret") - - # Empty password - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="", - use_pkcs8=False) - self.assertRaises(ValueError, - self.ref_private.export_key, - format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, - self.ref_private.export_key, - format="OpenSSH", - passphrase="secret") + def __init__(self, *args, **kwargs): + super(TestExport_Curve448, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_x448() + + def test_export_public_der(self): + key_file = load_file("ecc_x448_public.der") + + encoded = self.ref_public._export_subjectPublicKeyInfo(True) + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_x448_private.der") + + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) + + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + use_pkcs8=False, + ) + + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_public_pem(self): + key_file_ref = load_file("ecc_x448_public.pem", "rt").strip() + key_file = self.ref_public.export_key(format="PEM").strip() + self.assertEqual(key_file_ref, key_file) + + def test_export_private_pem_clear(self): + key_file = load_file("ecc_x448_private.pem", "rt").strip() + encoded = self.ref_private.export_key(format="PEM").strip() + self.assertEqual(key_file, encoded) + + def test_export_private_pem_encrypted(self): + encoded = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_raw(self): + encoded = self.ref_public.export_key(format="raw") + self.assertEqual(len(encoded), 56) + self.assertEqual( + encoded, + unhexlify( + b"e2abae24ab8f65b01969e61f84fee615b525f413a90e3d727f71d0ffe60fb1d0a1a0285f2a7fd88789206e0aa4f3e9fcb9e4ba5d644e691e" + ), + ) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) class TestImport_Curve448_Weak(unittest.TestCase): + def test_weak_pem(self): + p = 2**448 - 2**224 - 1 + weak_x = ( + 0, + 1, + p - 1, + p, + p + 1, + ) + + for x in weak_x: + low_order_point = ECC.EccXPoint(x, "curve448") + weak_key = ECC.EccKey(point=low_order_point, curve="curve448") + encoded = weak_key.export_key(format="PEM") + + self.assertRaises( + ValueError, + ECC.import_key, + encoded, + ) - def test_weak_pem(self): - p = 2**448 - 2**224 - 1 - weak_x = (0, - 1, - p - 1, - p, - p + 1) +def get_tests(config={}): + tests = [] + try: + tests += list_test_cases(TestImport) + tests += list_test_cases(TestImport_Curve448) + tests += list_test_cases(TestExport_Curve448) + tests += list_test_cases(TestImport_Curve448_Weak) + except SkipTest: + pass + return tests - for x in weak_x: - low_order_point = ECC.EccXPoint(x, "curve448") - weak_key = ECC.EccKey(point=low_order_point, curve="curve448") - encoded = weak_key.export_key(format="PEM") - self.assertRaises(ValueError, - ECC.import_key, - encoded) +if __name__ == "__main__": + def suit(): + return unittest.TestSuite(get_tests()) -def get_tests(config={}): - tests = [] - try: - tests += list_test_cases(TestImport) - tests += list_test_cases(TestImport_Curve448) - tests += list_test_cases(TestExport_Curve448) - tests += list_test_cases(TestImport_Curve448_Weak) - except SkipTest: - pass - return tests - - -if __name__ == '__main__': - def suit(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_DSA.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_DSA.py index 5ff01135..a3397267 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_DSA.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_DSA.py @@ -29,58 +29,58 @@ from binascii import unhexlify -class ImportKeyTests(unittest.TestCase): - y = 92137165128186062214622779787483327510946462589285775188003362705875131352591574106484271700740858696583623951844732128165434284507709057439633739849986759064015013893156866539696757799934634945787496920169462601722830899660681779448742875054459716726855443681559131362852474817534616736104831095601710736729 - p = 162452170958135306109773853318304545923250830605675936228618290525164105310663722368377131295055868997377338797580997938253236213714988311430600065853662861806894003694743806769284131194035848116051021923956699231855223389086646903420682639786976554552864568460372266462812137447840653688476258666833303658691 - q = 988791743931120302950649732173330531512663554851 - g = 85583152299197514738065570254868711517748965097380456700369348466136657764813442044039878840094809620913085570225318356734366886985903212775602770761953571967834823306046501307810937486758039063386311593890777319935391363872375452381836756832784184928202587843258855704771836753434368484556809100537243908232 - x = 540873410045082450874416847965843801027716145253 - - def setUp(self): - - # It is easier to write test vectors in text form, - # and convert them to byte strigs dynamically here - for mname, mvalue in ImportKeyTests.__dict__.items(): - if mname[:4] in ('der_', 'pem_', 'ssh_'): - if mname[:4] == 'der_': - mvalue = unhexlify(tobytes(mvalue)) - mvalue = tobytes(mvalue) - setattr(self, mname, mvalue) - - # 1. SubjectPublicKeyInfo - der_public=\ - '308201b73082012b06072a8648ce3804013082011e02818100e756ee1717f4b6'+\ - '794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a2757695ec91'+\ - '5697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8b81b47'+\ - '9a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656cecb4c'+\ - '8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad32f48c'+\ - 'd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb7eaeae'+\ - '3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466cf444f3'+\ - '4b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b92370040a'+\ - 'ca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074b41c56'+\ - 'ae43fd300d89262e4efd89943f99a651b03888038185000281810083352a69a1'+\ - '32f34843d2a0eb995bff4e2f083a73f0049d2c91ea2f0ce43d144abda48199e4'+\ - 'b003c570a8af83303d45105f606c5c48d925a40ed9c2630c2fa4cdbf838539de'+\ - 'b9a29f919085f2046369f627ca84b2cb1e2c7940564b670f963ab1164d4e2ca2'+\ - 'bf6ffd39f12f548928bf4d2d1b5e6980b4f1be4c92a91986fba559' - - def testImportKey1(self): - key_obj = DSA.importKey(self.der_public) - self.assertFalse(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def testExportKey1(self): - tup = (self.y, self.g, self.p, self.q) - key = DSA.construct(tup) - encoded = key.export_key('DER') - self.assertEqual(self.der_public, encoded) - - # 2. - pem_public="""\ +class ImportKeyTests(unittest.TestCase): + y = 92137165128186062214622779787483327510946462589285775188003362705875131352591574106484271700740858696583623951844732128165434284507709057439633739849986759064015013893156866539696757799934634945787496920169462601722830899660681779448742875054459716726855443681559131362852474817534616736104831095601710736729 + p = 162452170958135306109773853318304545923250830605675936228618290525164105310663722368377131295055868997377338797580997938253236213714988311430600065853662861806894003694743806769284131194035848116051021923956699231855223389086646903420682639786976554552864568460372266462812137447840653688476258666833303658691 + q = 988791743931120302950649732173330531512663554851 + g = 85583152299197514738065570254868711517748965097380456700369348466136657764813442044039878840094809620913085570225318356734366886985903212775602770761953571967834823306046501307810937486758039063386311593890777319935391363872375452381836756832784184928202587843258855704771836753434368484556809100537243908232 + x = 540873410045082450874416847965843801027716145253 + + def setUp(self): + # It is easier to write test vectors in text form, + # and convert them to byte strigs dynamically here + for mname, mvalue in ImportKeyTests.__dict__.items(): + if mname[:4] in ("der_", "pem_", "ssh_"): + if mname[:4] == "der_": + mvalue = unhexlify(tobytes(mvalue)) + mvalue = tobytes(mvalue) + setattr(self, mname, mvalue) + + # 1. SubjectPublicKeyInfo + der_public = ( + "308201b73082012b06072a8648ce3804013082011e02818100e756ee1717f4b6" + + "794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a2757695ec91" + + "5697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8b81b47" + + "9a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656cecb4c" + + "8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad32f48c" + + "d3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb7eaeae" + + "3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466cf444f3" + + "4b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b92370040a" + + "ca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074b41c56" + + "ae43fd300d89262e4efd89943f99a651b03888038185000281810083352a69a1" + + "32f34843d2a0eb995bff4e2f083a73f0049d2c91ea2f0ce43d144abda48199e4" + + "b003c570a8af83303d45105f606c5c48d925a40ed9c2630c2fa4cdbf838539de" + + "b9a29f919085f2046369f627ca84b2cb1e2c7940564b670f963ab1164d4e2ca2" + + "bf6ffd39f12f548928bf4d2d1b5e6980b4f1be4c92a91986fba559" + ) + + def testImportKey1(self): + key_obj = DSA.importKey(self.der_public) + self.assertFalse(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + + def testExportKey1(self): + tup = (self.y, self.g, self.p, self.q) + key = DSA.construct(tup) + encoded = key.export_key("DER") + self.assertEqual(self.der_public, encoded) + + # 2. + pem_public = """\ -----BEGIN PUBLIC KEY----- MIIBtzCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/ j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtH @@ -94,55 +94,56 @@ def testExportKey1(self): tPG+TJKpGYb7pVk= -----END PUBLIC KEY-----""" - def testImportKey2(self): - for pem in (self.pem_public, tostr(self.pem_public)): - key_obj = DSA.importKey(pem) - self.assertFalse(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def testExportKey2(self): - tup = (self.y, self.g, self.p, self.q) - key = DSA.construct(tup) - encoded = key.export_key('PEM') - self.assertEqual(self.pem_public, encoded) - - # 3. OpenSSL/OpenSSH format - der_private=\ - '308201bb02010002818100e756ee1717f4b6794c7c214724a19763742c45572b'+\ - '4b3f8ff3b44f3be9f44ce039a2757695ec915697da74ef914fcd1b05660e2419'+\ - 'c761d639f45d2d79b802dbd23e7ab8b81b479a380e1f30932584ba2a0b955032'+\ - '342ebc83cb5ca906e7b0d7cd6fe656cecb4c8b5a77123a8c6750a481e3b06057'+\ - 'aff6aa6eba620b832d60c3021500ad32f48cd3ae0c45a198a61fa4b5e2032076'+\ - '3b2302818079dfdc3d614fe635fceb7eaeae3718dc2efefb45282993ac6749dc'+\ - '83c223d8c1887296316b3b0b54466cf444f34b82e3554d0b90a778faaf1306f0'+\ - '25dae6a3e36c7f93dd5bac4052b92370040aca70b8d5820599711900efbc9618'+\ - '12c355dd9beffe0981da85c5548074b41c56ae43fd300d89262e4efd89943f99'+\ - 'a651b038880281810083352a69a132f34843d2a0eb995bff4e2f083a73f0049d'+\ - '2c91ea2f0ce43d144abda48199e4b003c570a8af83303d45105f606c5c48d925'+\ - 'a40ed9c2630c2fa4cdbf838539deb9a29f919085f2046369f627ca84b2cb1e2c'+\ - '7940564b670f963ab1164d4e2ca2bf6ffd39f12f548928bf4d2d1b5e6980b4f1'+\ - 'be4c92a91986fba55902145ebd9a3f0b82069d98420986b314215025756065' - - def testImportKey3(self): - key_obj = DSA.importKey(self.der_private) - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey3(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('DER', pkcs8=False) - self.assertEqual(self.der_private, encoded) - - # 4. - pem_private="""\ + def testImportKey2(self): + for pem in (self.pem_public, tostr(self.pem_public)): + key_obj = DSA.importKey(pem) + self.assertFalse(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + + def testExportKey2(self): + tup = (self.y, self.g, self.p, self.q) + key = DSA.construct(tup) + encoded = key.export_key("PEM") + self.assertEqual(self.pem_public, encoded) + + # 3. OpenSSL/OpenSSH format + der_private = ( + "308201bb02010002818100e756ee1717f4b6794c7c214724a19763742c45572b" + + "4b3f8ff3b44f3be9f44ce039a2757695ec915697da74ef914fcd1b05660e2419" + + "c761d639f45d2d79b802dbd23e7ab8b81b479a380e1f30932584ba2a0b955032" + + "342ebc83cb5ca906e7b0d7cd6fe656cecb4c8b5a77123a8c6750a481e3b06057" + + "aff6aa6eba620b832d60c3021500ad32f48cd3ae0c45a198a61fa4b5e2032076" + + "3b2302818079dfdc3d614fe635fceb7eaeae3718dc2efefb45282993ac6749dc" + + "83c223d8c1887296316b3b0b54466cf444f34b82e3554d0b90a778faaf1306f0" + + "25dae6a3e36c7f93dd5bac4052b92370040aca70b8d5820599711900efbc9618" + + "12c355dd9beffe0981da85c5548074b41c56ae43fd300d89262e4efd89943f99" + + "a651b038880281810083352a69a132f34843d2a0eb995bff4e2f083a73f0049d" + + "2c91ea2f0ce43d144abda48199e4b003c570a8af83303d45105f606c5c48d925" + + "a40ed9c2630c2fa4cdbf838539deb9a29f919085f2046369f627ca84b2cb1e2c" + + "7940564b670f963ab1164d4e2ca2bf6ffd39f12f548928bf4d2d1b5e6980b4f1" + + "be4c92a91986fba55902145ebd9a3f0b82069d98420986b314215025756065" + ) + + def testImportKey3(self): + key_obj = DSA.importKey(self.der_private) + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey3(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("DER", pkcs8=False) + self.assertEqual(self.der_private, encoded) + + # 4. + pem_private = """\ -----BEGIN DSA PRIVATE KEY----- MIIBuwIBAAKBgQDnVu4XF/S2eUx8IUckoZdjdCxFVytLP4/ztE876fRM4DmidXaV 7JFWl9p075FPzRsFZg4kGcdh1jn0XS15uALb0j56uLgbR5o4Dh8wkyWEuioLlVAy @@ -156,55 +157,56 @@ def testExportKey3(self): ggadmEIJhrMUIVAldWBl -----END DSA PRIVATE KEY-----""" - def testImportKey4(self): - for pem in (self.pem_private, tostr(self.pem_private)): - key_obj = DSA.importKey(pem) - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey4(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('PEM', pkcs8=False) - self.assertEqual(self.pem_private, encoded) - - # 5. PKCS8 (unencrypted) - der_pkcs8=\ - '3082014a0201003082012b06072a8648ce3804013082011e02818100e756ee17'+\ - '17f4b6794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a27576'+\ - '95ec915697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8'+\ - 'b81b479a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656'+\ - 'cecb4c8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad'+\ - '32f48cd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb'+\ - '7eaeae3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466c'+\ - 'f444f34b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b923'+\ - '70040aca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074'+\ - 'b41c56ae43fd300d89262e4efd89943f99a651b03888041602145ebd9a3f0b82'+\ - '069d98420986b314215025756065' - - def testImportKey5(self): - key_obj = DSA.importKey(self.der_pkcs8) - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey5(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('DER') - self.assertEqual(self.der_pkcs8, encoded) - encoded = key.export_key('DER', pkcs8=True) - self.assertEqual(self.der_pkcs8, encoded) - - # 6. - pem_pkcs8="""\ + def testImportKey4(self): + for pem in (self.pem_private, tostr(self.pem_private)): + key_obj = DSA.importKey(pem) + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey4(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("PEM", pkcs8=False) + self.assertEqual(self.pem_private, encoded) + + # 5. PKCS8 (unencrypted) + der_pkcs8 = ( + "3082014a0201003082012b06072a8648ce3804013082011e02818100e756ee17" + + "17f4b6794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a27576" + + "95ec915697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8" + + "b81b479a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656" + + "cecb4c8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad" + + "32f48cd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb" + + "7eaeae3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466c" + + "f444f34b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b923" + + "70040aca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074" + + "b41c56ae43fd300d89262e4efd89943f99a651b03888041602145ebd9a3f0b82" + + "069d98420986b314215025756065" + ) + + def testImportKey5(self): + key_obj = DSA.importKey(self.der_pkcs8) + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey5(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("DER") + self.assertEqual(self.der_pkcs8, encoded) + encoded = key.export_key("DER", pkcs8=True) + self.assertEqual(self.der_pkcs8, encoded) + + # 6. + pem_pkcs8 = """\ -----BEGIN PRIVATE KEY----- MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVX K0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4 @@ -215,44 +217,44 @@ def testExportKey5(self): tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAQWAhRevZo/C4IGnZhCCYazFCFQJXVgZQ== -----END PRIVATE KEY-----""" - def testImportKey6(self): - for pem in (self.pem_pkcs8, tostr(self.pem_pkcs8)): - key_obj = DSA.importKey(pem) - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey6(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('PEM') - self.assertEqual(self.pem_pkcs8, encoded) - encoded = key.export_key('PEM', pkcs8=True) - self.assertEqual(self.pem_pkcs8, encoded) - - # 7. OpenSSH/RFC4253 - ssh_pub="""ssh-dss AAAAB3NzaC1kc3MAAACBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2qm66YguDLWDDAAAAFQCtMvSM064MRaGYph+kteIDIHY7IwAAAIB539w9YU/mNfzrfq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAAAAIEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVk=""" - - def testImportKey7(self): - for ssh in (self.ssh_pub, tostr(self.ssh_pub)): - key_obj = DSA.importKey(ssh) - self.assertFalse(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def testExportKey7(self): - tup = (self.y, self.g, self.p, self.q) - key = DSA.construct(tup) - encoded = key.export_key('OpenSSH') - self.assertEqual(self.ssh_pub, encoded) - - # 8. Encrypted OpenSSL/OpenSSH - pem_private_encrypted="""\ + def testImportKey6(self): + for pem in (self.pem_pkcs8, tostr(self.pem_pkcs8)): + key_obj = DSA.importKey(pem) + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey6(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("PEM") + self.assertEqual(self.pem_pkcs8, encoded) + encoded = key.export_key("PEM", pkcs8=True) + self.assertEqual(self.pem_pkcs8, encoded) + + # 7. OpenSSH/RFC4253 + ssh_pub = """ssh-dss AAAAB3NzaC1kc3MAAACBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2qm66YguDLWDDAAAAFQCtMvSM064MRaGYph+kteIDIHY7IwAAAIB539w9YU/mNfzrfq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAAAAIEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVk=""" + + def testImportKey7(self): + for ssh in (self.ssh_pub, tostr(self.ssh_pub)): + key_obj = DSA.importKey(ssh) + self.assertFalse(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + + def testExportKey7(self): + tup = (self.y, self.g, self.p, self.q) + key = DSA.construct(tup) + encoded = key.export_key("OpenSSH") + self.assertEqual(self.ssh_pub, encoded) + + # 8. Encrypted OpenSSL/OpenSSH + pem_private_encrypted = """\ -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,70B6908939D65E9F2EB999E8729788CE @@ -269,30 +271,30 @@ def testExportKey7(self): xVJtxaV37m3aXxtCsPnbBg== -----END DSA PRIVATE KEY-----""" - def testImportKey8(self): - for pem in (self.pem_private_encrypted, tostr(self.pem_private_encrypted)): - key_obj = DSA.importKey(pem, "PWDTEST") - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey8(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('PEM', pkcs8=False, passphrase="PWDTEST") - key = DSA.importKey(encoded, "PWDTEST") - self.assertEqual(self.y, key.y) - self.assertEqual(self.p, key.p) - self.assertEqual(self.q, key.q) - self.assertEqual(self.g, key.g) - self.assertEqual(self.x, key.x) - - # 9. Encrypted PKCS8 - # pbeWithMD5AndDES-CBC - pem_pkcs8_encrypted="""\ + def testImportKey8(self): + for pem in (self.pem_private_encrypted, tostr(self.pem_private_encrypted)): + key_obj = DSA.importKey(pem, "PWDTEST") + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey8(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + encoded = key.export_key("PEM", pkcs8=False, passphrase="PWDTEST") + key = DSA.importKey(encoded, "PWDTEST") + self.assertEqual(self.y, key.y) + self.assertEqual(self.p, key.p) + self.assertEqual(self.q, key.q) + self.assertEqual(self.g, key.g) + self.assertEqual(self.x, key.x) + + # 9. Encrypted PKCS8 + # pbeWithMD5AndDES-CBC + pem_pkcs8_encrypted = """\ -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBcTAbBgkqhkiG9w0BBQMwDgQI0GC3BJ/jSw8CAggABIIBUHc1cXZpExIE9tC7 7ryiW+5ihtF2Ekurq3e408GYSAu5smJjN2bvQXmzRFBz8W38K8eMf1sbWroZ4+zn @@ -304,88 +306,86 @@ def testExportKey8(self): eZ4k+NQDbEL8GiHmFxzDWQAuPPZKJWEEEV2p/To+WOh+kSDHQw== -----END ENCRYPTED PRIVATE KEY-----""" - def testImportKey9(self): - for pem in (self.pem_pkcs8_encrypted, tostr(self.pem_pkcs8_encrypted)): - key_obj = DSA.importKey(pem, "PWDTEST") - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - # 10. Encrypted PKCS8 - # pkcs5PBES2 / - # pkcs5PBKDF2 (rounds=1000, salt=D725BF1B6B8239F4) / - # des-EDE3-CBC (iv=27A1C66C42AFEECE) - # - der_pkcs8_encrypted=\ - '30820196304006092a864886f70d01050d3033301b06092a864886f70d01050c'+\ - '300e0408d725bf1b6b8239f4020203e8301406082a864886f70d0307040827a1'+\ - 'c66c42afeece048201505cacfde7bf8edabb3e0d387950dc872662ea7e9b1ed4'+\ - '400d2e7e6186284b64668d8d0328c33a9d9397e6f03df7cb68268b0a06b4e22f'+\ - '7d132821449ecf998a8b696dbc6dd2b19e66d7eb2edfeb4153c1771d49702395'+\ - '4f36072868b5fcccf93413a5ac4b2eb47d4b3f681c6bd67ae363ed776f45ae47'+\ - '174a00098a7c930a50f820b227ddf50f9742d8e950d02586ff2dac0e3c372248'+\ - 'e5f9b6a7a02f4004f20c87913e0f7b52bccc209b95d478256a890b31d4c9adec'+\ - '21a4d157a179a93a3dad06f94f3ce486b46dfa7fc15fd852dd7680bbb2f17478'+\ - '7e71bd8dbaf81eca7518d76c1d26256e95424864ba45ca5d47d7c5a421be02fa'+\ - 'b94ab01e18593f66cf9094eb5c94b9ecf3aa08b854a195cf87612fbe5e96c426'+\ - '2b0d573e52dc71ba3f5e468c601e816c49b7d32c698b22175e89aaef0c443770'+\ - '5ef2f88a116d99d8e2869a4fd09a771b84b49e4ccb79aadcb1c9' - - def testImportKey10(self): - key_obj = DSA.importKey(self.der_pkcs8_encrypted, "PWDTEST") - self.assertTrue(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey10(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - randfunc = BytesIO(unhexlify(b("27A1C66C42AFEECE") + b("D725BF1B6B8239F4"))).read - encoded = key.export_key('DER', pkcs8=True, passphrase="PWDTEST", randfunc=randfunc) - self.assertEqual(self.der_pkcs8_encrypted, encoded) - - # ---- - - def testImportError1(self): - self.assertRaises(ValueError, DSA.importKey, self.der_pkcs8_encrypted, "wrongpwd") - - def testExportError2(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - self.assertRaises(ValueError, key.export_key, 'DER', pkcs8=False, passphrase="PWDTEST") - - def test_import_key(self): - """Verify importKey is an alias to import_key""" - - key_obj = DSA.import_key(self.der_public) - self.assertFalse(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def test_exportKey(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - self.assertEqual(key.exportKey(), key.export_key()) - - - def test_import_empty(self): - self.assertRaises(ValueError, DSA.import_key, b'') + def testImportKey9(self): + for pem in (self.pem_pkcs8_encrypted, tostr(self.pem_pkcs8_encrypted)): + key_obj = DSA.importKey(pem, "PWDTEST") + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + # 10. Encrypted PKCS8 + # pkcs5PBES2 / + # pkcs5PBKDF2 (rounds=1000, salt=D725BF1B6B8239F4) / + # des-EDE3-CBC (iv=27A1C66C42AFEECE) + # + der_pkcs8_encrypted = ( + "30820196304006092a864886f70d01050d3033301b06092a864886f70d01050c" + + "300e0408d725bf1b6b8239f4020203e8301406082a864886f70d0307040827a1" + + "c66c42afeece048201505cacfde7bf8edabb3e0d387950dc872662ea7e9b1ed4" + + "400d2e7e6186284b64668d8d0328c33a9d9397e6f03df7cb68268b0a06b4e22f" + + "7d132821449ecf998a8b696dbc6dd2b19e66d7eb2edfeb4153c1771d49702395" + + "4f36072868b5fcccf93413a5ac4b2eb47d4b3f681c6bd67ae363ed776f45ae47" + + "174a00098a7c930a50f820b227ddf50f9742d8e950d02586ff2dac0e3c372248" + + "e5f9b6a7a02f4004f20c87913e0f7b52bccc209b95d478256a890b31d4c9adec" + + "21a4d157a179a93a3dad06f94f3ce486b46dfa7fc15fd852dd7680bbb2f17478" + + "7e71bd8dbaf81eca7518d76c1d26256e95424864ba45ca5d47d7c5a421be02fa" + + "b94ab01e18593f66cf9094eb5c94b9ecf3aa08b854a195cf87612fbe5e96c426" + + "2b0d573e52dc71ba3f5e468c601e816c49b7d32c698b22175e89aaef0c443770" + + "5ef2f88a116d99d8e2869a4fd09a771b84b49e4ccb79aadcb1c9" + ) + + def testImportKey10(self): + key_obj = DSA.importKey(self.der_pkcs8_encrypted, "PWDTEST") + self.assertTrue(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + self.assertEqual(self.x, key_obj.x) + + def testExportKey10(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + randfunc = BytesIO(unhexlify(b("27A1C66C42AFEECE") + b("D725BF1B6B8239F4"))).read + encoded = key.export_key("DER", pkcs8=True, passphrase="PWDTEST", randfunc=randfunc) + self.assertEqual(self.der_pkcs8_encrypted, encoded) + + # ---- + + def testImportError1(self): + self.assertRaises(ValueError, DSA.importKey, self.der_pkcs8_encrypted, "wrongpwd") + + def testExportError2(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + self.assertRaises(ValueError, key.export_key, "DER", pkcs8=False, passphrase="PWDTEST") + + def test_import_key(self): + """Verify importKey is an alias to import_key""" + + key_obj = DSA.import_key(self.der_public) + self.assertFalse(key_obj.has_private()) + self.assertEqual(self.y, key_obj.y) + self.assertEqual(self.p, key_obj.p) + self.assertEqual(self.q, key_obj.q) + self.assertEqual(self.g, key_obj.g) + + def test_exportKey(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = DSA.construct(tup) + self.assertEqual(key.exportKey(), key.export_key()) + + def test_import_empty(self): + self.assertRaises(ValueError, DSA.import_key, b"") class ImportKeyFromX509Cert(unittest.TestCase): - - def test_x509v1(self): - - # Sample V1 certificate with a 1024 bit DSA key - x509_v1_cert = """ + def test_x509v1(self): + # Sample V1 certificate with a 1024 bit DSA key + x509_v1_cert = """ -----BEGIN CERTIFICATE----- MIIDUjCCArsCAQIwDQYJKoZIhvcNAQEFBQAwfjENMAsGA1UEChMEQWNtZTELMAkG A1UECxMCUkQxHDAaBgkqhkiG9w0BCQEWDXNwYW1AYWNtZS5vcmcxEzARBgNVBAcT @@ -408,8 +408,8 @@ def test_x509v1(self): -----END CERTIFICATE----- """.strip() - # DSA public key as dumped by openssl - y_str = """ + # DSA public key as dumped by openssl + y_str = """ 2a:88:ab:3c:07:dc:a7:5a:db:6e:5e:32:d8:51:40: 22:4b:5f:5b:c7:f8:f9:3e:dd:da:22:92:83:bd:da: 89:57:ee:8e:13:4e:b7:56:73:d6:57:c2:d0:d2:36: @@ -420,7 +420,7 @@ def test_x509v1(self): c8:77:c6:31:f1:78:d0:c5:4d:e3:6d:b6:cc:a7:86: a7:bc:61:33:40:8d:88:25 """ - p_str = """ + p_str = """ 00:ce:ac:de:0e:c7:8f:ad:dd:3e:b0:29:e1:df:87: 30:2b:85:ca:cd:10:53:10:e1:2b:3e:e0:f2:0a:ca: 29:83:cb:d0:67:eb:85:8f:90:bd:41:ff:d7:6f:60: @@ -431,11 +431,11 @@ def test_x509v1(self): 7f:95:4d:33:c3:7f:2a:c9:31:80:a4:87:4a:c9:01: f0:8f:fb:9c:6b:98:f3:5e:b7 """ - q_str = """ + q_str = """ 00:bb:57:60:e5:75:ca:84:6b:cc:9d:90:33:9b:84: 8e:27:47:e8:68:99 """ - g_str = """ + g_str = """ 7d:4a:80:d5:20:26:e6:0e:54:eb:c4:88:2c:c5:57: f6:5e:6b:ab:43:a9:07:4c:1a:04:ca:49:43:7d:7f: 47:fc:97:34:3a:a8:73:78:06:59:94:ce:24:55:38: @@ -447,17 +447,16 @@ def test_x509v1(self): 2c:62:a9:58:dd:ff:9b:c9 """ - key = DSA.importKey(x509_v1_cert) - for comp_name in ('y', 'p', 'q', 'g'): - comp_str = locals()[comp_name + "_str"] - comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) - self.assertEqual(getattr(key, comp_name), comp) - self.assertFalse(key.has_private()) - - def test_x509v3(self): + key = DSA.importKey(x509_v1_cert) + for comp_name in ("y", "p", "q", "g"): + comp_str = locals()[comp_name + "_str"] + comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) + self.assertEqual(getattr(key, comp_name), comp) + self.assertFalse(key.has_private()) - # Sample V3 certificate with a 1024 bit DSA key - x509_v3_cert = """ + def test_x509v3(self): + # Sample V3 certificate with a 1024 bit DSA key + x509_v3_cert = """ -----BEGIN CERTIFICATE----- MIIFhjCCA26gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL MAkGA1UECAwCTUQxEjAQBgNVBAcMCUJhbHRpbW9yZTEQMA4GA1UEAwwHVGVzdCBD @@ -492,8 +491,8 @@ def test_x509v3(self): -----END CERTIFICATE----- """.strip() - # DSA public key as dumped by openssl - y_str = """ + # DSA public key as dumped by openssl + y_str = """ 72:95:68:d6:4a:72:87:13:c9:87:c7:50:39:9b:fd: 06:43:1e:b1:9e:15:88:7b:7f:8c:24:09:c4:85:11: b1:03:62:78:48:2b:1f:59:4d:0e:c2:09:48:41:3a: @@ -504,7 +503,7 @@ def test_x509v3(self): 62:29:e4:85:05:f1:67:a0:ca:8b:f9:d7:7d:19:bd: d0:3d:94:a5:94:17:15:0f """ - p_str = """ + p_str = """ 00:b7:dd:f2:0c:84:a5:53:c0:d1:92:3a:f4:aa:77: 9f:22:5c:bb:93:74:65:9d:ca:d4:af:61:95:e4:0b: 36:a2:84:71:93:a1:ed:af:c2:d8:9d:53:3d:d9:87: @@ -515,11 +514,11 @@ def test_x509v3(self): 62:3d:f3:99:97:58:32:86:bd:d3:81:75:68:35:ab: f8:3c:50:23:a0:d5:0b:7f:db """ - q_str = """ + q_str = """ 00:86:a5:cc:08:9e:9f:40:ad:c6:d8:ef:52:df:f0: 82:ff:25:59:5c:2b """ - g_str = """ + g_str = """ 51:5d:13:a5:dd:1d:a4:85:7e:e5:d7:42:d0:8c:31: 20:a3:70:75:23:38:d7:53:f8:cf:31:c3:01:97:a5: ce:fa:70:49:5f:1a:ff:b1:c6:ea:f0:08:e2:bf:b2: @@ -531,24 +530,25 @@ def test_x509v3(self): 07:c6:cb:a8:ee:89:c0:6f """ - key = DSA.importKey(x509_v3_cert) - for comp_name in ('y', 'p', 'q', 'g'): - comp_str = locals()[comp_name + "_str"] - comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) - self.assertEqual(getattr(key, comp_name), comp) - self.assertFalse(key.has_private()) + key = DSA.importKey(x509_v3_cert) + for comp_name in ("y", "p", "q", "g"): + comp_str = locals()[comp_name + "_str"] + comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) + self.assertEqual(getattr(key, comp_name), comp) + self.assertFalse(key.has_private()) + +if __name__ == "__main__": + unittest.main() -if __name__ == '__main__': - unittest.main() def get_tests(config={}): - tests = [] - tests += list_test_cases(ImportKeyTests) - tests += list_test_cases(ImportKeyFromX509Cert) - return tests + tests = [] + tests += list_test_cases(ImportKeyTests) + tests += list_test_cases(ImportKeyFromX509Cert) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_ECC.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_ECC.py index ee80000d..88e8f660 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_ECC.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_ECC.py @@ -45,2215 +45,2465 @@ from Cryptodome.PublicKey.ECC import _import_rfc5915_der try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False class MissingTestVectorException(ValueError): - pass + pass def load_file(file_name, mode="rb"): - results = None + results = None - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) - dir_comps = ("PublicKey", "ECC") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() + dir_comps = ("PublicKey", "ECC") + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name, mode) as file_in: + results = file_in.read() - except FileNotFoundError: - warnings.warn("Skipping extended tests for ECC", - UserWarning, - stacklevel=2) + except FileNotFoundError: + warnings.warn( + "Skipping extended tests for ECC", + UserWarning, + stacklevel=2, + ) - if results is None: - raise MissingTestVectorException("Missing %s" % file_name) + if results is None: + raise MissingTestVectorException("Missing %s" % file_name) - return results + return results def compact(lines): - ext = b"".join(lines) - return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) + ext = b"".join(lines) + return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) def create_ref_keys_p192(): - key_len = 24 - key_lines = load_file("ecc_p192.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:4])) - public_key_xy = compact(key_lines[5:9]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 24 + key_lines = load_file("ecc_p192.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:4])) + public_key_xy = compact(key_lines[5:9]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-192", d=private_key_d), - ECC.construct(curve="P-192", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-192", d=private_key_d), + ECC.construct(curve="P-192", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_p224(): - key_len = 28 - key_lines = load_file("ecc_p224.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:4])) - public_key_xy = compact(key_lines[5:9]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 28 + key_lines = load_file("ecc_p224.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:4])) + public_key_xy = compact(key_lines[5:9]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-224", d=private_key_d), - ECC.construct(curve="P-224", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-224", d=private_key_d), + ECC.construct(curve="P-224", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_p256(): - key_len = 32 - key_lines = load_file("ecc_p256.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:5])) - public_key_xy = compact(key_lines[6:11]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 32 + key_lines = load_file("ecc_p256.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:5])) + public_key_xy = compact(key_lines[6:11]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-256", d=private_key_d), - ECC.construct(curve="P-256", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-256", d=private_key_d), + ECC.construct(curve="P-256", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_p384(): - key_len = 48 - key_lines = load_file("ecc_p384.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:6])) - public_key_xy = compact(key_lines[7:14]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 48 + key_lines = load_file("ecc_p384.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:6])) + public_key_xy = compact(key_lines[7:14]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-384", d=private_key_d), - ECC.construct(curve="P-384", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-384", d=private_key_d), + ECC.construct(curve="P-384", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_p521(): - key_len = 66 - key_lines = load_file("ecc_p521.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:7])) - public_key_xy = compact(key_lines[8:17]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + key_len = 66 + key_lines = load_file("ecc_p521.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:7])) + public_key_xy = compact(key_lines[8:17]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1 : key_len + 1]) + public_key_y = bytes_to_long(public_key_xy[key_len + 1 :]) - return (ECC.construct(curve="P-521", d=private_key_d), - ECC.construct(curve="P-521", point_x=public_key_x, point_y=public_key_y)) + return ( + ECC.construct(curve="P-521", d=private_key_d), + ECC.construct(curve="P-521", point_x=public_key_x, point_y=public_key_y), + ) def create_ref_keys_ed25519(): - key_lines = load_file("ecc_ed25519.txt").splitlines() - seed = compact(key_lines[5:8]) - key = ECC.construct(curve="Ed25519", seed=seed) - return (key, key.public_key()) + key_lines = load_file("ecc_ed25519.txt").splitlines() + seed = compact(key_lines[5:8]) + key = ECC.construct(curve="Ed25519", seed=seed) + return (key, key.public_key()) def create_ref_keys_ed448(): - key_lines = load_file("ecc_ed448.txt").splitlines() - seed = compact(key_lines[6:10]) - key = ECC.construct(curve="Ed448", seed=seed) - return (key, key.public_key()) + key_lines = load_file("ecc_ed448.txt").splitlines() + seed = compact(key_lines[6:10]) + key = ECC.construct(curve="Ed448", seed=seed) + return (key, key.public_key()) # Create reference key pair # ref_private, ref_public = create_ref_keys_p521() + def get_fixed_prng(): - return SHAKE128.new().update(b"SEED").read + return SHAKE128.new().update(b"SEED").read def extract_bitstring_from_spki(data): - seq = DerSequence() - seq.decode(data) - bs = DerBitString() - bs.decode(seq[1]) - return bs.value + seq = DerSequence() + seq.decode(data) + bs = DerBitString() + bs.decode(seq[1]) + return bs.value class TestImport(unittest.TestCase): + def test_empty(self): + self.assertRaises(ValueError, ECC.import_key, b"") - def test_empty(self): - self.assertRaises(ValueError, ECC.import_key, b"") - - def test_mismatch(self): - # The private key does not match the public key - mismatch = """-----BEGIN PRIVATE KEY----- + def test_mismatch(self): + # The private key does not match the public key + mismatch = """-----BEGIN PRIVATE KEY----- MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJChZANiAAQarFRaqflo I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXk= -----END PRIVATE KEY-----""" - self.assertRaises(ValueError, ECC.import_key, mismatch) - - def test_import_private_rfc5915_none(self): - # ECPrivateKey with a P256 private key, without [0] and [1] - data_hex = "302502010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052" - key = _import_rfc5915_der(unhexlify(data_hex), None, "1.2.840.10045.3.1.7") - self.assertEqual(key.d, 0x5c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052) - - def test_import_private_rfc5915_only_0(self): - # ECPrivateKey with a P256 private key, with [0] only - data_hex = "303102010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052a00a06082a8648ce3d030107" - key = _import_rfc5915_der(unhexlify(data_hex), None) - self.assertEqual(key.d, 0x5c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052) - - def test_import_private_rfc5915_only_1(self): - # ECPrivateKey with a P256 private key, with [1] only - data_hex = "306b02010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052a14403420004a40ad59a2050ebe92479bd5fb16bb2e45b6465eb3cb2b1effe423fabe6cb7424db8219ef0bab80acf26fd70595b61fe4760d33eed80dd03d2fd0dfb27b8ce75c" - key = _import_rfc5915_der(unhexlify(data_hex), None, "1.2.840.10045.3.1.7") - self.assertEqual(key.d, 0x5c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052) + self.assertRaises(ValueError, ECC.import_key, mismatch) -class TestImport_P192(unittest.TestCase): + def test_import_private_rfc5915_none(self): + # ECPrivateKey with a P256 private key, without [0] and [1] + data_hex = "302502010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052" + key = _import_rfc5915_der(unhexlify(data_hex), None, "1.2.840.10045.3.1.7") + self.assertEqual(key.d, 0x5C4E4320EF260F91ED9FC597AEE98C8236B60E0CED692CC7A057D5E45798A052) - def __init__(self, *args, **kwargs): - super(TestImport_P192, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p192() + def test_import_private_rfc5915_only_0(self): + # ECPrivateKey with a P256 private key, with [0] only + data_hex = "303102010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052a00a06082a8648ce3d030107" + key = _import_rfc5915_der(unhexlify(data_hex), None) + self.assertEqual(key.d, 0x5C4E4320EF260F91ED9FC597AEE98C8236B60E0CED692CC7A057D5E45798A052) - def test_import_public_der(self): - key_file = load_file("ecc_p192_public.der") + def test_import_private_rfc5915_only_1(self): + # ECPrivateKey with a P256 private key, with [1] only + data_hex = "306b02010104205c4e4320ef260f91ed9fc597aee98c8236b60e0ced692cc7a057d5e45798a052a14403420004a40ad59a2050ebe92479bd5fb16bb2e45b6465eb3cb2b1effe423fabe6cb7424db8219ef0bab80acf26fd70595b61fe4760d33eed80dd03d2fd0dfb27b8ce75c" + key = _import_rfc5915_der(unhexlify(data_hex), None, "1.2.840.10045.3.1.7") + self.assertEqual(key.d, 0x5C4E4320EF260F91ED9FC597AEE98C8236B60E0CED692CC7A057D5E45798A052) - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) +class TestImport_P192(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P192, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p192() - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_public_der(self): + key_file = load_file("ecc_p192_public.der") - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p192_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P192') - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p192_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P192') - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p192_private.der") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p192_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P192") + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p192_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P192") + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p192_private.der") - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p192_private_p8_clear.der") + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p192_private_p8_clear.pem") + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p192_private_p8_clear.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p192_private_p8.der") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p192_private_p8_clear.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p192_private_p8.pem") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p192_private_p8.der") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_p192_x509.der") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p192_private_p8.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_public_pem(self): - key_file = load_file("ecc_p192_public.pem") + def test_import_x509_der(self): + key_file = load_file("ecc_p192_x509.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_p192_private.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_public_pem(self): + key_file = load_file("ecc_p192_public.pem") - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p192_private_enc_%s.pem" % algo) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pem(self): + key_file = load_file("ecc_p192_private.pem") - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_p192_x509.pem") + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p192_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) -class TestImport_P224(unittest.TestCase): + def test_import_x509_pem(self): + key_file = load_file("ecc_p192_x509.pem") - def __init__(self, *args, **kwargs): - super(TestImport_P224, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p224() + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_der(self): - key_file = load_file("ecc_p224_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) +class TestImport_P224(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P224, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p224() - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + def test_import_public_der(self): + key_file = load_file("ecc_p224_public.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p224_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P224') - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p224_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P224') - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p224_private.der") + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p224_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P224") + self.assertEqual(self.ref_public, key) - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p224_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P224") + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p224_private.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p224_private_p8_clear.der") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p224_private_p8_clear.der") - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p224_private_p8_clear.pem") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p224_private_p8.der") + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p224_private_p8_clear.pem") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p224_private_p8.der") - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p224_private_p8.pem") + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_p224_private_p8_2.der") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p224_private_p8.pem") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_p224_private_p8_2.der") - def test_import_x509_der(self): - key_file = load_file("ecc_p224_x509.der") + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_x509_der(self): + key_file = load_file("ecc_p224_x509.der") - def test_import_public_pem(self): - key_file = load_file("ecc_p224_public.pem") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_p224_private.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_p224_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p224_private_enc_%s.pem" % algo) + def test_import_private_pem(self): + key_file = load_file("ecc_p224_private.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p224_private_enc_%s.pem" % algo) - def test_import_x509_pem(self): - key_file = load_file("ecc_p224_x509.pem") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) + def test_import_x509_pem(self): + key_file = load_file("ecc_p224_x509.pem") -class TestImport_P256(unittest.TestCase): + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def __init__(self, *args, **kwargs): - super(TestImport_P256, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p256() - def test_import_public_der(self): - key_file = load_file("ecc_p256_public.der") +class TestImport_P256(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P256, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p256() - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + def test_import_public_der(self): + key_file = load_file("ecc_p256_public.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p256_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P256') - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p256_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P256') - self.assertEqual(self.ref_public, key) + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p256_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P256") + self.assertEqual(self.ref_public, key) - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p256_private.der") + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p256_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P256") + self.assertEqual(self.ref_public, key) - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p256_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p256_private_p8_clear.der") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p256_private_p8_clear.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p256_private_p8_clear.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p256_private_p8_clear.pem") - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p256_private_p8.der") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p256_private_p8.der") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p256_private_p8.pem") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p256_private_p8.pem") - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_p256_private_p8_2.der") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_p256_private_p8_2.der") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_p256_x509.der") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + def test_import_x509_der(self): + key_file = load_file("ecc_p256_x509.der") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_p256_public.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_public_pem(self): + key_file = load_file("ecc_p256_public.pem") - def test_import_private_pem(self): - key_file = load_file("ecc_p256_private.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pem(self): + key_file = load_file("ecc_p256_private.pem") - def test_import_private_pem_with_ecparams(self): - key_file = load_file("ecc_p256_private_ecparams.pem") - key = ECC.import_key(key_file) - # We just check if the import succeeds + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p256_private_enc_%s.pem" % algo) + def test_import_private_pem_with_ecparams(self): + key_file = load_file("ecc_p256_private_ecparams.pem") + key = ECC.import_key(key_file) + # We just check if the import succeeds - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p256_private_enc_%s.pem" % algo) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_p256_x509.pem") + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_x509_pem(self): + key_file = load_file("ecc_p256_x509.pem") - def test_import_openssh_public(self): - key_file = load_file("ecc_p256_public_openssh.txt") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_openssh_public(key_file) - self.assertEqual(self.ref_public, key) + def test_import_openssh_public(self): + key_file = load_file("ecc_p256_public_openssh.txt") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_openssh_public(key_file) + self.assertEqual(self.ref_public, key) - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_p256_private_openssh.pem") - key_file_old = load_file("ecc_p256_private_openssh_old.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + def test_import_openssh_private_clear(self): + key_file = load_file("ecc_p256_private_openssh.pem") + key_file_old = load_file("ecc_p256_private_openssh_old.pem") - def test_import_openssh_private_password(self): - key_file = load_file("ecc_p256_private_openssh_pwd.pem") - key_file_old = load_file("ecc_p256_private_openssh_pwd_old.pem") + key = ECC.import_key(key_file) + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) - key = ECC.import_key(key_file, b"password") - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + def test_import_openssh_private_password(self): + key_file = load_file("ecc_p256_private_openssh_pwd.pem") + key_file_old = load_file("ecc_p256_private_openssh_pwd_old.pem") + key = ECC.import_key(key_file, b"password") + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) -class TestImport_P384(unittest.TestCase): - def __init__(self, *args, **kwargs): - super(TestImport_P384, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p384() +class TestImport_P384(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P384, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p384() - def test_import_public_der(self): - key_file = load_file("ecc_p384_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_p384_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p384_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P384') - self.assertEqual(self.ref_public, key) + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p384_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P384") + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p384_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P384') - self.assertEqual(self.ref_public, key) + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p384_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P384") + self.assertEqual(self.ref_public, key) - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p384_private.der") + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p384_private.der") - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p384_private_p8_clear.der") + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p384_private_p8_clear.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p384_private_p8_clear.pem") + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p384_private_p8_clear.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p384_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p384_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p384_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p384_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_p384_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_p384_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_p384_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_p384_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_p384_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_p384_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_p384_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_p384_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p384_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p384_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_p384_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_p384_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_openssh_public(self): - key_file = load_file("ecc_p384_public_openssh.txt") + def test_import_openssh_public(self): + key_file = load_file("ecc_p384_public_openssh.txt") - key = ECC._import_openssh_public(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_openssh_public(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_p384_private_openssh.pem") - key_file_old = load_file("ecc_p384_private_openssh_old.pem") + def test_import_openssh_private_clear(self): + key_file = load_file("ecc_p384_private_openssh.pem") + key_file_old = load_file("ecc_p384_private_openssh_old.pem") - key = ECC.import_key(key_file) - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + key = ECC.import_key(key_file) + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) - def test_import_openssh_private_password(self): - key_file = load_file("ecc_p384_private_openssh_pwd.pem") - key_file_old = load_file("ecc_p384_private_openssh_pwd_old.pem") + def test_import_openssh_private_password(self): + key_file = load_file("ecc_p384_private_openssh_pwd.pem") + key_file_old = load_file("ecc_p384_private_openssh_pwd_old.pem") - key = ECC.import_key(key_file, b"password") - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + key = ECC.import_key(key_file, b"password") + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) class TestImport_P521(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_P521, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p521() - def __init__(self, *args, **kwargs): - super(TestImport_P521, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p521() + def test_import_public_der(self): + key_file = load_file("ecc_p521_public.der") - def test_import_public_der(self): - key_file = load_file("ecc_p521_public.der") + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_p521_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P521") + self.assertEqual(self.ref_public, key) - def test_import_sec1_uncompressed(self): - key_file = load_file("ecc_p521_public.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P521') - self.assertEqual(self.ref_public, key) + def test_import_sec1_compressed(self): + key_file = load_file("ecc_p521_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name="P521") + self.assertEqual(self.ref_public, key) - def test_import_sec1_compressed(self): - key_file = load_file("ecc_p521_public_compressed.der") - value = extract_bitstring_from_spki(key_file) - key = ECC.import_key(key_file, curve_name='P521') - self.assertEqual(self.ref_public, key) + def test_import_rfc5915_der(self): + key_file = load_file("ecc_p521_private.der") - def test_import_rfc5915_der(self): - key_file = load_file("ecc_p521_private.der") + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_rfc5915_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_p521_private_p8_clear.der") - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p521_private_p8_clear.der") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_p521_private_p8_clear.pem") - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p521_private_p8_clear.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_p521_private_p8.der") - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p521_private_p8.der") + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_p521_private_p8.pem") - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p521_private_p8.pem") + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_p521_private_p8_2.der") - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_p521_private_p8_2.der") + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + def test_import_x509_der(self): + key_file = load_file("ecc_p521_x509.der") - def test_import_x509_der(self): - key_file = load_file("ecc_p521_x509.der") + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_public_pem(self): + key_file = load_file("ecc_p521_public.pem") - def test_import_public_pem(self): - key_file = load_file("ecc_p521_public.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_private_pem(self): + key_file = load_file("ecc_p521_private.pem") - def test_import_private_pem(self): - key_file = load_file("ecc_p521_private.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_p521_private_enc_%s.pem" % algo) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p521_private_enc_%s.pem" % algo) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + def test_import_x509_pem(self): + key_file = load_file("ecc_p521_x509.pem") - def test_import_x509_pem(self): - key_file = load_file("ecc_p521_x509.pem") + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_openssh_public(self): + key_file = load_file("ecc_p521_public_openssh.txt") - def test_import_openssh_public(self): - key_file = load_file("ecc_p521_public_openssh.txt") + key = ECC._import_openssh_public(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_openssh_public(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + def test_import_openssh_private_clear(self): + key_file = load_file("ecc_p521_private_openssh.pem") + key_file_old = load_file("ecc_p521_private_openssh_old.pem") - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_p521_private_openssh.pem") - key_file_old = load_file("ecc_p521_private_openssh_old.pem") + key = ECC.import_key(key_file) + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) - key = ECC.import_key(key_file) - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + def test_import_openssh_private_password(self): + key_file = load_file("ecc_p521_private_openssh_pwd.pem") + key_file_old = load_file("ecc_p521_private_openssh_pwd_old.pem") - def test_import_openssh_private_password(self): - key_file = load_file("ecc_p521_private_openssh_pwd.pem") - key_file_old = load_file("ecc_p521_private_openssh_pwd_old.pem") - - key = ECC.import_key(key_file, b"password") - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) + key = ECC.import_key(key_file, b"password") + key_old = ECC.import_key(key_file_old) + self.assertEqual(key, key_old) class TestExport_P192(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P192, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p192() - def __init__(self, *args, **kwargs): - super(TestExport_P192, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p192() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p192_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p192_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p192_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p192_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p192_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p192_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p192_public.der") - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p192_private.der") + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p192_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p192_private_p8_clear.der") + key_file_compressed_ref = load_file("ecc_p192_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p192_public.der") + value = extract_bitstring_from_spki(key_file) - # --- + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p192_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + key_file_compressed_ref = load_file("ecc_p192_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p192_private.der") - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - # --- + # --- - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - # --- + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p192_private_p8_clear.der") - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA224AndAES192-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p192_public.pem", "rt").strip() + # --- - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - # --- + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p192_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + # --- - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p192_public_compressed.pem", "rt").strip() + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - self.assertEqual(key_file_compressed, key_file_compressed_ref) + # --- - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p192_private.pem", "rt").strip() + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA224AndAES192-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p192_public.pem", "rt").strip() - # --- + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + # --- - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - assert "EC PRIVATE KEY" in encoded + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p192_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p192_public_compressed.pem", "rt").strip() - # --- + self.assertEqual(key_file_compressed, key_file_compressed_ref) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p192_private.pem", "rt").strip() - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p192_private_p8_clear.pem", "rt").strip() + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + # --- - # --- + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - def test_compressed_curve(self): - - # Compressed P-192 curve (Y-point is even) - pem1 = """-----BEGIN EC PRIVATE KEY----- + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "EC PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p192_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + def test_compressed_curve(self): + # Compressed P-192 curve (Y-point is even) + pem1 = """-----BEGIN EC PRIVATE KEY----- MF8CAQEEGHvhXmIW95JxZYfd4AUPu9BwknjuvS36aqAKBggqhkjOPQMBAaE0AzIA BLJZCyTu35DQIlqvMlBynn3k1Ig+dWfg/brRhHecxptrbloqFSP8ITw0CwbGF+2X 5g== -----END EC PRIVATE KEY-----""" - # Compressed P-192 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-192 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MF8CAQEEGA3rAotUaWl7d47eX6tz9JmLzOMJwl13XaAKBggqhkjOPQMBAaE0AzIA BG4tHlTBBBGokcWmGm2xubVB0NvPC/Ou5AYwivs+3iCxmEjsymVAj6iiuX2Lxr6g /Q== -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x97E6) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0x97E6) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0xA0FD) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0xA0FD) class TestExport_P224(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P224, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p224() - def __init__(self, *args, **kwargs): - super(TestExport_P224, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p224() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p224_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p224_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p224_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p224_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p224_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p224_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) - - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p224_private.der") + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p224_public.der") - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p224_private_p8_clear.der") + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p224_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + key_file_compressed_ref = load_file("ecc_p224_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - # --- + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p224_public.der") + value = extract_bitstring_from_spki(key_file) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p224_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + key_file_compressed_ref = load_file("ecc_p224_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p224_private.der") - # --- + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA512-224AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # --- - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p224_public.pem", "rt").strip() + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p224_private_p8_clear.der") - # --- + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + # --- - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p224_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p224_public_compressed.pem", "rt").strip() + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - self.assertEqual(key_file_compressed, key_file_compressed_ref) + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p224_private.pem", "rt").strip() + # --- - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA512-224AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # --- + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p224_public.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + # --- - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - assert "EC PRIVATE KEY" in encoded + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p224_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - # --- + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p224_public_compressed.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + self.assertEqual(key_file_compressed, key_file_compressed_ref) - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p224_private_p8_clear.pem", "rt").strip() + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p224_private.pem", "rt").strip() - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - # --- + # --- - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - def test_compressed_curve(self): - - # Compressed P-224 curve (Y-point is even) - pem1 = """-----BEGIN EC PRIVATE KEY----- + assert "EC PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p224_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + def test_compressed_curve(self): + # Compressed P-224 curve (Y-point is even) + pem1 = """-----BEGIN EC PRIVATE KEY----- MGgCAQEEHPYicBNI9nd6wDKAX2l+f3A0Q+KWUQeMqSt5GoOgBwYFK4EEACGhPAM6 AATCL6rUIDT14zXKoS5GQUMDP/tpc+1iI/FyEZikt2roKDkhU5q08srmqaysbfJN eUr7Xf1lnCVGag== -----END EC PRIVATE KEY-----""" - # Compressed P-224 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-224 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MGgCAQEEHEFjbaVPLJ3ngZyCibCvT0RLUqSlHjC5Z3e0FtugBwYFK4EEACGhPAM6 AAT5IvL2V6m48y1JLMGr6ZbnOqNKP9hMf9mxyVkk6/SaRoBoJVkXrNIpYL0P7DS7 QF8E/OGeZRwvow== -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x466A) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0x466A) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0x2FA3) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0x2FA3) class TestExport_P256(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P256, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p256() - def __init__(self, *args, **kwargs): - super(TestExport_P256, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p256() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p256_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p256_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p256_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p256_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p256_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p256_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) - - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p256_private.der") - - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p256_public.der") - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p256_private_p8_clear.der") + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p256_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + key_file_compressed_ref = load_file("ecc_p256_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p256_public.der") + value = extract_bitstring_from_spki(key_file) - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - # --- + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p256_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + key_file_compressed_ref = load_file("ecc_p256_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - # --- + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p256_private.der") - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA512-256AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p256_public.pem", "rt").strip() + # --- - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - # --- + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p256_private_p8_clear.der") - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + # --- - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p256_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p256_public_compressed.pem", "rt").strip() + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - self.assertEqual(key_file_compressed, key_file_compressed_ref) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p256_private.pem", "rt").strip() + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + # --- - # --- + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + # --- - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA512-256AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p256_public.pem", "rt").strip() - assert "EC PRIVATE KEY" in encoded + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # --- - # --- + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p256_private_p8_clear.pem", "rt").strip() + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p256_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p256_public_compressed.pem", "rt").strip() - # --- + self.assertEqual(key_file_compressed, key_file_compressed_ref) - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p256_private.pem", "rt").strip() - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + # --- - assert "ENCRYPTED PRIVATE KEY" in encoded + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") - # --- + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + assert "EC PRIVATE KEY" in encoded - def test_export_openssh_uncompressed(self): - key_file = load_file("ecc_p256_public_openssh.txt", "rt") + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_public._export_openssh(False) - self.assertEqual(key_file, encoded) + # --- - # --- + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_public.export_key(format="OpenSSH") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="OpenSSH", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_openssh_compressed(self): - key_file = load_file("ecc_p256_public_openssh.txt", "rt") - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) - assert len(key_file) > len(key_file_compressed) - self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") - - - def test_compressed_curve(self): - - # Compressed P-256 curve (Y-point is even) - pem1 = """-----BEGIN EC PRIVATE KEY----- + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p256_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh_uncompressed(self): + key_file = load_file("ecc_p256_public_openssh.txt", "rt") + + encoded = self.ref_public._export_openssh(False) + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_public.export_key(format="OpenSSH") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="OpenSSH", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_openssh_compressed(self): + key_file = load_file("ecc_p256_public_openssh.txt", "rt") + pub_key = ECC.import_key(key_file) + + key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) + assert len(key_file) > len(key_file_compressed) + self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) + + def test_compressed_curve(self): + # Compressed P-256 curve (Y-point is even) + pem1 = """-----BEGIN EC PRIVATE KEY----- MFcCAQEEIHTuc09jC51xXomV6MVCDN+DpAAvSmaJWZPTEHM6D5H1oAoGCCqGSM49 AwEHoSQDIgACWFuGbHe8yJ43rir7PMTE9w8vHz0BSpXHq90Xi7/s+a0= -----END EC PRIVATE KEY-----""" - # Compressed P-256 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-256 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MFcCAQEEIFggiPN9SQP+FAPTCPp08fRUz7rHp2qNBRcBJ1DXhb3ZoAoGCCqGSM49 AwEHoSQDIgADLpph1trTIlVfa8NJvlMUPyWvL+wP+pW3BJITUL/wj9A= -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0xA6FC) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0xA6FC) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0x6E57) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0x6E57) class TestExport_P384(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P384, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p384() - def __init__(self, *args, **kwargs): - super(TestExport_P384, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p384() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p384_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p384_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p384_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p384_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p384_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p384_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) - - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p384_private.der") - - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p384_private_p8_clear.der") + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p384_public.der") - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p384_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + key_file_compressed_ref = load_file("ecc_p384_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p384_public.der") + value = extract_bitstring_from_spki(key_file) - # --- + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p384_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - # --- + key_file_compressed_ref = load_file("ecc_p384_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA384AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p384_private.der") - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p384_public.pem", "rt").strip() + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + # --- - # --- + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p384_private_p8_clear.der") - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p384_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + # --- - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p384_public_compressed.pem", "rt").strip() + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - self.assertEqual(key_file_compressed, key_file_compressed_ref) + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p384_private.pem", "rt").strip() + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # --- + # --- - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + # --- - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA384AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - assert "EC PRIVATE KEY" in encoded + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p384_public.pem", "rt").strip() - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - # --- + # --- - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p384_private_p8_clear.pem", "rt").strip() + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p384_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - # --- + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p384_public_compressed.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) + self.assertEqual(key_file_compressed, key_file_compressed_ref) - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p384_private.pem", "rt").strip() - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - assert "ENCRYPTED PRIVATE KEY" in encoded + # --- - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - # --- + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) - def test_export_openssh_uncompressed(self): - key_file = load_file("ecc_p384_public_openssh.txt", "rt") + assert "EC PRIVATE KEY" in encoded - encoded = self.ref_public._export_openssh(False) - self.assertEqual(key_file, encoded) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # --- + # --- - encoded = self.ref_public.export_key(format="OpenSSH") - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_public.export_key(format="OpenSSH", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_openssh_compressed(self): - key_file = load_file("ecc_p384_public_openssh.txt", "rt") - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) - assert len(key_file) > len(key_file_compressed) - self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") - - def test_compressed_curve(self): - - # Compressed P-384 curve (Y-point is even) - # openssl ecparam -name secp384p1 -genkey -noout -conv_form compressed -out /tmp/a.pem - # openssl ec -in /tmp/a.pem -text -noout - pem1 = """-----BEGIN EC PRIVATE KEY----- + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p384_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh_uncompressed(self): + key_file = load_file("ecc_p384_public_openssh.txt", "rt") + + encoded = self.ref_public._export_openssh(False) + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_public.export_key(format="OpenSSH") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="OpenSSH", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_openssh_compressed(self): + key_file = load_file("ecc_p384_public_openssh.txt", "rt") + pub_key = ECC.import_key(key_file) + + key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) + assert len(key_file) > len(key_file_compressed) + self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) + + def test_compressed_curve(self): + # Compressed P-384 curve (Y-point is even) + # openssl ecparam -name secp384p1 -genkey -noout -conv_form compressed -out /tmp/a.pem + # openssl ec -in /tmp/a.pem -text -noout + pem1 = """-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDAM0lEIhvXuekK2SWtdbgOcZtBaxa9TxfpO/GcDFZLCJ3JVXaTgwken QT+C+XLtD6WgBwYFK4EEACKhZANiAATs0kZMhFDu8DoBC21jrSDPyAUn4aXZ/DM4 ylhDfWmb4LEbeszXceIzfhIUaaGs5y1xXaqf5KXTiAAYx2pKUzAAM9lcGUHCGKJG k4AgUmVJON29XoUilcFrzjDmuye3B6Q= -----END EC PRIVATE KEY-----""" - # Compressed P-384 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-384 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDDHPFTslYLltE16fHdSDTtE/2HTmd3M8mqy5MttAm4wZ833KXiGS9oe kFdx9sNV0KygBwYFK4EEACKhZANiAASLIE5RqVMtNhtBH/u/p/ifqOAlKnK/+RrQ YC46ZRsnKNayw3wATdPjgja7L/DSII3nZK0G6KOOVwJBznT/e+zudUJYhZKaBLRx /bgXyxUtYClOXxb1Y/5N7txLstYRyP0= -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x07a4) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0x07A4) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0xc8fd) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0xC8FD) class TestExport_P521(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_P521, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_p521() - def __init__(self, *args, **kwargs): - super(TestExport_P521, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p521() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p521_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p521_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p521_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_public_sec1_uncompressed(self): - key_file = load_file("ecc_p521_public.der") - value = extract_bitstring_from_spki(key_file) - - encoded = self.ref_public.export_key(format="SEC1") - self.assertEqual(value, encoded) - - encoded = self.ref_public.export_key(format="raw") - self.assertEqual(value, encoded) - - def test_export_public_sec1_compressed(self): - key_file = load_file("ecc_p521_public.der") - encoded = self.ref_public.export_key(format="SEC1", compress=True) - - key_file_compressed_ref = load_file("ecc_p521_public_compressed.der") - value = extract_bitstring_from_spki(key_file_compressed_ref) - self.assertEqual(value, encoded) - - encoded = self.ref_public.export_key(format="raw", compress=True) - self.assertEqual(value, encoded) - - def test_export_rfc5915_private_der(self): - key_file = load_file("ecc_p521_private.der") - - encoded = self.ref_private._export_rfc5915_private_der() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_p521_public.der") - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p521_private_p8_clear.der") + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - # --- + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) + def test_export_public_der_compressed(self): + key_file = load_file("ecc_p521_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + key_file_compressed_ref = load_file("ecc_p521_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_p521_public.der") + value = extract_bitstring_from_spki(key_file) - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) - # --- + encoded = self.ref_public.export_key(format="raw") + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_p521_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) - # --- + key_file_compressed_ref = load_file("ecc_p521_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public.export_key(format="raw", compress=True) + self.assertEqual(value, encoded) - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p521_public.pem", "rt").strip() + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_p521_private.der") - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) - # --- + # --- - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_p521_private_p8_clear.der") - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p521_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p521_public_compressed.pem", "rt").strip() + # --- - self.assertEqual(key_file_compressed, key_file_compressed_ref) + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p521_private.pem", "rt").strip() + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - # --- + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) + # --- - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + # --- - assert "EC PRIVATE KEY" in encoded + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_p521_public.pem", "rt").strip() - # --- + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # --- - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p521_private_p8_clear.pem", "rt").strip() + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) - # --- + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_p521_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_p521_public_compressed.pem", "rt").strip() - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + self.assertEqual(key_file_compressed, key_file_compressed_ref) - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) + def test_export_private_pem_clear(self): + key_file = load_file("ecc_p521_private.pem", "rt").strip() - assert "ENCRYPTED PRIVATE KEY" in encoded + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + # --- - # --- + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") - def test_export_openssh_uncompressed(self): - key_file = load_file("ecc_p521_public_openssh.txt", "rt") + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) - encoded = self.ref_public._export_openssh(False) - self.assertEqual(key_file, encoded) + assert "EC PRIVATE KEY" in encoded - # --- + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - encoded = self.ref_public.export_key(format="OpenSSH") - self.assertEqual(key_file, encoded) + # --- - encoded = self.ref_public.export_key(format="OpenSSH", compress=False) - self.assertEqual(key_file, encoded) + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) - def test_export_openssh_compressed(self): - key_file = load_file("ecc_p521_public_openssh.txt", "rt") - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) - assert len(key_file) > len(key_file_compressed) - self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") - - def test_compressed_curve(self): - - # Compressed P-521 curve (Y-point is even) - # openssl ecparam -name secp521r1 -genkey -noout -conv_form compressed -out /tmp/a.pem - # openssl ec -in /tmp/a.pem -text -noout - pem1 = """-----BEGIN EC PRIVATE KEY----- + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_p521_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem( + "secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh_uncompressed(self): + key_file = load_file("ecc_p521_public_openssh.txt", "rt") + + encoded = self.ref_public._export_openssh(False) + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_public.export_key(format="OpenSSH") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="OpenSSH", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_openssh_compressed(self): + key_file = load_file("ecc_p521_public_openssh.txt", "rt") + pub_key = ECC.import_key(key_file) + + key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) + assert len(key_file) > len(key_file_compressed) + self.assertEqual(pub_key, ECC.import_key(key_file_compressed)) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key( + format="PEM", + passphrase="secret", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # DER format but no PKCS#8 + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # Incorrect parameters for public keys + self.assertRaises( + ValueError, + self.ref_public.export_key, + format="DER", + use_pkcs8=False, + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) + + def test_compressed_curve(self): + # Compressed P-521 curve (Y-point is even) + # openssl ecparam -name secp521r1 -genkey -noout -conv_form compressed -out /tmp/a.pem + # openssl ec -in /tmp/a.pem -text -noout + pem1 = """-----BEGIN EC PRIVATE KEY----- MIHcAgEBBEIAnm1CEjVjvNfXEN730p+D6su5l+mOztdc5XmTEoti+s2R4GQ4mAv3 0zYLvyklvOHw0+yy8d0cyGEJGb8T3ZVKmg2gBwYFK4EEACOhgYkDgYYABAHzjTI1 ckxQ3Togi0LAxiG0PucdBBBs5oIy3df95xv6SInp70z+4qQ2EltEmdNMssH8eOrl @@ -2261,8 +2511,8 @@ def test_compressed_curve(self): uGxO8tM6r3w89/qzpG2SvFM/fvv3mIR30wSZDD84qA== -----END EC PRIVATE KEY-----""" - # Compressed P-521 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- + # Compressed P-521 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- MIHcAgEBBEIB84OfhJluLBRLn3+cC/RQ37C2SfQVP/t0gQK2tCsTf5avRcWYRrOJ PmX9lNnkC0Hobd75QFRmdxrB0Wd1/M4jZOWgBwYFK4EEACOhgYkDgYYABAAMZcdJ 1YLCGHt3bHCEzdidVy6+brlJIbv1aQ9fPQLF7WKNv4c8w3H8d5a2+SDZilBOsk5c @@ -2270,513 +2520,589 @@ def test_compressed_curve(self): vv6oYkMIIi7r5oQWAiQDrR2mlrrFDL9V7GH/r8SWQw== -----END EC PRIVATE KEY-----""" - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x38a8) + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0x38A8) - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0x9643) + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0x9643) class TestImport_Ed25519(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_Ed25519, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_ed25519() - def __init__(self, *args, **kwargs): - super(TestImport_Ed25519, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_ed25519() - - def test_import_public_der(self): - key_file = load_file("ecc_ed25519_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_ed25519_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_pkcs8_der(self): - key_file = load_file("ecc_ed25519_private.der") + def test_import_pkcs8_der(self): + key_file = load_file("ecc_ed25519_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_ed25519_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_ed25519_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_ed25519_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_ed25519_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_ed25519_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_ed25519_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_ed25519_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_ed25519_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_ed25519_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_ed25519_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_ed25519_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_ed25519_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256": - key_file = load_file("ecc_ed25519_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256": + key_file = load_file("ecc_ed25519_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_ed25519_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_ed25519_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_openssh_public(self): - key_file = load_file("ecc_ed25519_public_openssh.txt") - key = ECC._import_openssh_public(key_file) - self.assertFalse(key.has_private()) - key = ECC.import_key(key_file) - self.assertFalse(key.has_private()) + def test_import_openssh_public(self): + key_file = load_file("ecc_ed25519_public_openssh.txt") + key = ECC._import_openssh_public(key_file) + self.assertFalse(key.has_private()) + key = ECC.import_key(key_file) + self.assertFalse(key.has_private()) - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_ed25519_private_openssh.pem") - key = ECC.import_key(key_file) + def test_import_openssh_private_clear(self): + key_file = load_file("ecc_ed25519_private_openssh.pem") + key = ECC.import_key(key_file) - def test_import_openssh_private_password(self): - key_file = load_file("ecc_ed25519_private_openssh_pwd.pem") - key = ECC.import_key(key_file, b"password") + def test_import_openssh_private_password(self): + key_file = load_file("ecc_ed25519_private_openssh_pwd.pem") + key = ECC.import_key(key_file, b"password") class TestExport_Ed25519(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestExport_Ed25519, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_ed25519() - def __init__(self, *args, **kwargs): - super(TestExport_Ed25519, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_ed25519() - - def test_export_public_der(self): - key_file = load_file("ecc_ed25519_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(True) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_sec1(self): - self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1") - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_ed25519_private.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - self.assertRaises(ValueError, self.ref_private.export_key, - format="DER", use_pkcs8=False) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- + def test_export_public_der(self): + key_file = load_file("ecc_ed25519_public.der") - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) + encoded = self.ref_public._export_subjectPublicKeyInfo(True) + self.assertEqual(key_file, encoded) - def test_export_public_pem(self): - key_file_ref = load_file("ecc_ed25519_public.pem", "rt").strip() - key_file = self.ref_public.export_key(format="PEM").strip() - self.assertEqual(key_file_ref, key_file) + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) - def test_export_private_pem_clear(self): - key_file = load_file("ecc_ed25519_private.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM").strip() - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_openssh(self): - key_file = load_file("ecc_ed25519_public_openssh.txt", "rt") - public_key = ECC.import_key(key_file) - key_file = " ".join(key_file.split(' ')[:2]) # remove comment - - encoded = public_key._export_openssh(False) - self.assertEqual(key_file, encoded.strip()) - - encoded = public_key.export_key(format="OpenSSH") - self.assertEqual(key_file, encoded.strip()) - - def test_export_raw(self): - encoded = self.ref_public.export_key(format='raw') - self.assertEqual(encoded, unhexlify(b'bc85b8cf585d20a4de47e84d1cb6183f63d9ba96223fcbc886e363ffdea20cff')) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_public_sec1(self): + self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1") + + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_ed25519_private.der") + + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) + + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + use_pkcs8=False, + ) + + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA256AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_public_pem(self): + key_file_ref = load_file("ecc_ed25519_public.pem", "rt").strip() + key_file = self.ref_public.export_key(format="PEM").strip() + self.assertEqual(key_file_ref, key_file) + + def test_export_private_pem_clear(self): + key_file = load_file("ecc_ed25519_private.pem", "rt").strip() + encoded = self.ref_private.export_key(format="PEM").strip() + self.assertEqual(key_file, encoded) + + def test_export_private_pem_encrypted(self): + encoded = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh(self): + key_file = load_file("ecc_ed25519_public_openssh.txt", "rt") + public_key = ECC.import_key(key_file) + key_file = " ".join(key_file.split(" ")[:2]) # remove comment + + encoded = public_key._export_openssh(False) + self.assertEqual(key_file, encoded.strip()) + + encoded = public_key.export_key(format="OpenSSH") + self.assertEqual(key_file, encoded.strip()) + + def test_export_raw(self): + encoded = self.ref_public.export_key(format="raw") + self.assertEqual( + encoded, unhexlify(b"bc85b8cf585d20a4de47e84d1cb6183f63d9ba96223fcbc886e363ffdea20cff") + ) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) class TestImport_Ed448(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(TestImport_Ed448, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_ed448() - def __init__(self, *args, **kwargs): - super(TestImport_Ed448, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_ed448() - - def test_import_public_der(self): - key_file = load_file("ecc_ed448_public.der") + def test_import_public_der(self): + key_file = load_file("ecc_ed448_public.der") - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_pkcs8_der(self): - key_file = load_file("ecc_ed448_private.der") + def test_import_pkcs8_der(self): + key_file = load_file("ecc_ed448_private.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_ed448_private_p8.der") + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_ed448_private_p8.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_ed448_private_p8.pem") + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_ed448_private_p8.pem") - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_private_pkcs8_encrypted_3(self): - key_file = load_file("ecc_ed448_private_p8_2.der") + def test_import_private_pkcs8_encrypted_3(self): + key_file = load_file("ecc_ed448_private_p8_2.der") - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_der(self): - key_file = load_file("ecc_ed448_x509.der") + def test_import_x509_der(self): + key_file = load_file("ecc_ed448_x509.der") - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_public_pem(self): - key_file = load_file("ecc_ed448_public.pem") + def test_import_public_pem(self): + key_file = load_file("ecc_ed448_public.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) - def test_import_private_pem(self): - key_file = load_file("ecc_ed448_private.pem") + def test_import_private_pem(self): + key_file = load_file("ecc_ed448_private.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256": - key_file = load_file("ecc_ed448_private_enc_%s.pem" % algo) + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256": + key_file = load_file("ecc_ed448_private_enc_%s.pem" % algo) - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) - def test_import_x509_pem(self): - key_file = load_file("ecc_ed448_x509.pem") + def test_import_x509_pem(self): + key_file = load_file("ecc_ed448_x509.pem") - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) class TestExport_Ed448(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestExport_Ed448, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_ed448() - - def test_export_public_der(self): - key_file = load_file("ecc_ed448_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(True) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_sec1(self): - self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1") - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_ed448_private.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - self.assertRaises(ValueError, self.ref_private.export_key, - format="DER", use_pkcs8=False) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA384AndAES128-CBC", - prot_params={'iteration_count':123}) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - - def test_export_public_pem(self): - key_file_ref = load_file("ecc_ed448_public.pem", "rt").strip() - key_file = self.ref_public.export_key(format="PEM").strip() - self.assertEqual(key_file_ref, key_file) - - def test_export_private_pem_clear(self): - key_file = load_file("ecc_ed448_private.pem", "rt").strip() - encoded = self.ref_private.export_key(format="PEM").strip() - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_openssh(self): - # Not supported - self.assertRaises(ValueError, self.ref_public.export_key, format="OpenSSH") - - def test_export_raw(self): - encoded = self.ref_public.export_key(format='raw') - self.assertEqual(encoded, unhexlify(b'899014ddc0a0e1260cfc1085afdf952019e9fd63372e3e366e26dad32b176624884330a14617237e3081febd9d1a15069e7499433d2f55dd80')) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase=b"secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEqual(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") + def __init__(self, *args, **kwargs): + super(TestExport_Ed448, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_ed448() + + def test_export_public_der(self): + key_file = load_file("ecc_ed448_public.der") + + encoded = self.ref_public._export_subjectPublicKeyInfo(True) + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_public_sec1(self): + self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1") + + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_ed448_private.der") + + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) + + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="DER", + use_pkcs8=False, + ) + + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8( + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key( + format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA384AndAES128-CBC", + prot_params={"iteration_count": 123}, + ) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_public_pem(self): + key_file_ref = load_file("ecc_ed448_public.pem", "rt").strip() + key_file = self.ref_public.export_key(format="PEM").strip() + self.assertEqual(key_file_ref, key_file) + + def test_export_private_pem_clear(self): + key_file = load_file("ecc_ed448_private.pem", "rt").strip() + encoded = self.ref_private.export_key(format="PEM").strip() + self.assertEqual(key_file, encoded) + + def test_export_private_pem_encrypted(self): + encoded = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_openssh(self): + # Not supported + self.assertRaises(ValueError, self.ref_public.export_key, format="OpenSSH") + + def test_export_raw(self): + encoded = self.ref_public.export_key(format="raw") + self.assertEqual( + encoded, + unhexlify( + b"899014ddc0a0e1260cfc1085afdf952019e9fd63372e3e366e26dad32b176624884330a14617237e3081febd9d1a15069e7499433d2f55dd80" + ), + ) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key( + format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + encoded2 = self.ref_private.export_key( + format="PEM", + passphrase=b"secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng(), + ) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="secret", + ) + + # Empty password + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + use_pkcs8=False, + ) + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + ) + + # No private keys with OpenSSH + self.assertRaises( + ValueError, + self.ref_private.export_key, + format="OpenSSH", + passphrase="secret", + ) def get_tests(config={}): - tests = [] - tests += list_test_cases(TestImport) - try: - tests += list_test_cases(TestImport_P192) - tests += list_test_cases(TestImport_P224) - tests += list_test_cases(TestImport_P256) - tests += list_test_cases(TestImport_P384) - tests += list_test_cases(TestImport_P521) - tests += list_test_cases(TestImport_Ed25519) - tests += list_test_cases(TestImport_Ed448) - - tests += list_test_cases(TestExport_P192) - tests += list_test_cases(TestExport_P224) - tests += list_test_cases(TestExport_P256) - tests += list_test_cases(TestExport_P384) - tests += list_test_cases(TestExport_P521) - tests += list_test_cases(TestExport_Ed25519) - tests += list_test_cases(TestExport_Ed448) - - except MissingTestVectorException: - pass - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(TestImport) + try: + tests += list_test_cases(TestImport_P192) + tests += list_test_cases(TestImport_P224) + tests += list_test_cases(TestImport_P256) + tests += list_test_cases(TestImport_P384) + tests += list_test_cases(TestImport_P521) + tests += list_test_cases(TestImport_Ed25519) + tests += list_test_cases(TestImport_Ed448) + + tests += list_test_cases(TestExport_P192) + tests += list_test_cases(TestExport_P224) + tests += list_test_cases(TestExport_P256) + tests += list_test_cases(TestExport_P384) + tests += list_test_cases(TestExport_P521) + tests += list_test_cases(TestExport_Ed25519) + tests += list_test_cases(TestExport_Ed448) + + except MissingTestVectorException: + pass + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_RSA.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_RSA.py index b57676d0..ed976015 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_RSA.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/PublicKey/test_import_RSA.py @@ -35,50 +35,56 @@ from Cryptodome.Util import asn1 try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False def load_file(file_name, mode="rb"): - results = None + results = None + + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) + dir_comps = ("PublicKey", "RSA") + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name, mode) as file_in: + results = file_in.read() - dir_comps = ("PublicKey", "RSA") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() + except FileNotFoundError: + warnings.warn( + "Skipping tests for RSA based on %s" % file_name, + UserWarning, + stacklevel=2, + ) - except FileNotFoundError: - warnings.warn("Skipping tests for RSA based on %s" % file_name, - UserWarning, - stacklevel=2) + if results is None: + raise SkipTest("Missing %s" % file_name) - if results is None: - raise SkipTest("Missing %s" % file_name) + return results - return results +def der2pem(der, text="PUBLIC"): + import binascii -def der2pem(der, text='PUBLIC'): - import binascii - chunks = [binascii.b2a_base64(der[i:i+48]) for i in range(0, len(der), 48)] - pem = b('-----BEGIN %s KEY-----\n' % text) - pem += b('').join(chunks) - pem += b('-----END %s KEY-----' % text) - return pem + chunks = [binascii.b2a_base64(der[i : i + 48]) for i in range(0, len(der), 48)] + pem = b("-----BEGIN %s KEY-----\n" % text) + pem += b("").join(chunks) + pem += b("-----END %s KEY-----" % text) + return pem class ImportKeyTests(unittest.TestCase): - # 512-bit RSA key generated with openssl - rsaKeyPEM = u'''-----BEGIN RSA PRIVATE KEY----- + # 512-bit RSA key generated with openssl + rsaKeyPEM = """-----BEGIN RSA PRIVATE KEY----- MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8 Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI @@ -86,10 +92,10 @@ class ImportKeyTests(unittest.TestCase): +rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9 n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ== ------END RSA PRIVATE KEY-----''' +-----END RSA PRIVATE KEY-----""" - # As above, but this is actually an unencrypted PKCS#8 key - rsaKeyPEM8 = u'''-----BEGIN PRIVATE KEY----- + # As above, but this is actually an unencrypted PKCS#8 key + rsaKeyPEM8 = """-----BEGIN PRIVATE KEY----- MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvx4nkAqgiyNRGlwS ga5tkzEsPv6RP5MuvtSS8S0WtGEMMoy24girX0WsvilQgzKY8xIsGfeEkt7fQPDj wZAzhQIDAQABAkAJRIMSnxFN7fZ+2rwjAbxaiOXmYB3XAWIg6tn9S/xv3rdYk4mK @@ -98,14 +104,15 @@ class ImportKeyTests(unittest.TestCase): NwIhAIe+HDApUEvPNOxxPYd5R0R4EyiJdcokAICvewlAkbEhAiBqtGn6bVZIpXUx yLAxpM6dtTvDEWz0M/Wm9rvqVgHOBQIhAL2fQKdkInohlipK3Qfk3v5D7ZGjrie7 BX85JB8zqwHB ------END PRIVATE KEY-----''' - - # The same RSA private key as in rsaKeyPEM, but now encrypted - rsaKeyEncryptedPEM = ( - - # PEM encryption - # With DES and passphrase 'test' - ('test', u'''-----BEGIN RSA PRIVATE KEY----- +-----END PRIVATE KEY-----""" + + # The same RSA private key as in rsaKeyPEM, but now encrypted + rsaKeyEncryptedPEM = ( + # PEM encryption + # With DES and passphrase 'test' + ( + "test", + """-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-CBC,AF8F9A40BD2FA2FC @@ -116,10 +123,12 @@ class ImportKeyTests(unittest.TestCase): 9bMbdb/1PSvsSzPsqW7KSSrTw6MgJAFJg6lzIYvR5F4poTVBxwBX3+EyEmShiaNY IRX3TgQI0IjrVuLmvlZKbGWP18FXj7I7k9tSsNOOzllTTdq3ny5vgM3A+ynfAaxp dysKznQ6P+IoqML1WxAID4aGRMWka+uArOJ148Rbj9s= ------END RSA PRIVATE KEY-----'''), - - # PKCS8 encryption - ('winter', u'''-----BEGIN ENCRYPTED PRIVATE KEY----- +-----END RSA PRIVATE KEY-----""", + ), + # PKCS8 encryption + ( + "winter", + """-----BEGIN ENCRYPTED PRIVATE KEY----- MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeZIsbW3O+JcCAggA MBQGCCqGSIb3DQMHBAgSM2p0D8FilgSCAWBhFyP2tiGKVpGj3mO8qIBzinU60ApR 3unvP+N6j7LVgnV2lFGaXbJ6a1PbQXe+2D6DUyBLo8EMXrKKVLqOMGkFMHc0UaV6 @@ -129,21 +138,23 @@ class ImportKeyTests(unittest.TestCase): ntvgJwnCn2XR1h6LA8Wp+0ghDTsL2NhJpWd78zClGhyU4r3hqu1XDjoXa7YCXCix jCV15+ViDJzlNCwg+W6lRg18sSLkCT7alviIE0U5tHc6UPbbHwT5QqAxAABaP+nZ CGqJGyiwBzrKebjgSm/KRd4C91XqcsysyH2kKPfT51MLAoD4xelOURBP ------END ENCRYPTED PRIVATE KEY-----''' - ), - ) +-----END ENCRYPTED PRIVATE KEY-----""", + ), + ) - rsaPublicKeyPEM = u'''-----BEGIN PUBLIC KEY----- + rsaPublicKeyPEM = """-----BEGIN PUBLIC KEY----- MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+T Lr7UkvEtFrRhDDKMtuIIq19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQ== ------END PUBLIC KEY-----''' +-----END PUBLIC KEY-----""" - # Obtained using 'ssh-keygen -i -m PKCS8 -f rsaPublicKeyPEM' - rsaPublicKeyOpenSSH = b('''ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQC/HieQCqCLI1EaXBKBrm2TMSw+/pE/ky6+1JLxLRa0YQwyjLbiCKtfRay+KVCDMpjzEiwZ94SS3t9A8OPBkDOF comment\n''') + # Obtained using 'ssh-keygen -i -m PKCS8 -f rsaPublicKeyPEM' + rsaPublicKeyOpenSSH = b( + """ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQC/HieQCqCLI1EaXBKBrm2TMSw+/pE/ky6+1JLxLRa0YQwyjLbiCKtfRay+KVCDMpjzEiwZ94SS3t9A8OPBkDOF comment\n""" + ) - # The private key, in PKCS#1 format encoded with DER - rsaKeyDER = a2b_hex( - '''3082013b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe + # The private key, in PKCS#1 format encoded with DER + rsaKeyDER = a2b_hex( + """3082013b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe 913f932ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f312 2c19f78492dedf40f0e3c190338502030100010240094483129f114dedf6 7edabc2301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c @@ -154,11 +165,12 @@ class ImportKeyTests(unittest.TestCase): 240080af7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53b c3116cf433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07 e4defe43ed91a3ae27bb057f39241f33ab01c1 - '''.replace(" ","")) + """.replace(" ", ""), + ) - # The private key, in unencrypted PKCS#8 format encoded with DER - rsaKeyDER8 = a2b_hex( - '''30820155020100300d06092a864886f70d01010105000482013f3082013 + # The private key, in unencrypted PKCS#8 format encoded with DER + rsaKeyDER8 = a2b_hex( + """30820155020100300d06092a864886f70d01010105000482013f3082013 b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe913f932 ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f3122c19f78 492dedf40f0e3c190338502030100010240094483129f114dedf67edabc2 @@ -170,308 +182,340 @@ class ImportKeyTests(unittest.TestCase): f7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53bc3116cf 433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07e4defe4 3ed91a3ae27bb057f39241f33ab01c1 - '''.replace(" ","")) + """.replace(" ", ""), + ) - rsaPublicKeyDER = a2b_hex( - '''305c300d06092a864886f70d0101010500034b003048024100bf1e27900a + rsaPublicKeyDER = a2b_hex( + """305c300d06092a864886f70d0101010500034b003048024100bf1e27900a a08b23511a5c1281ae6d93312c3efe913f932ebed492f12d16b4610c328c b6e208ab5f45acbe2950833298f3122c19f78492dedf40f0e3c190338502 03010001 - '''.replace(" ","")) - - n = int('BF 1E 27 90 0A A0 8B 23 51 1A 5C 12 81 AE 6D 93 31 2C 3E FE 91 3F 93 2E BE D4 92 F1 2D 16 B4 61 0C 32 8C B6 E2 08 AB 5F 45 AC BE 29 50 83 32 98 F3 12 2C 19 F7 84 92 DE DF 40 F0 E3 C1 90 33 85'.replace(" ",""),16) - e = 65537 - d = int('09 44 83 12 9F 11 4D ED F6 7E DA BC 23 01 BC 5A 88 E5 E6 60 1D D7 01 62 20 EA D9 FD 4B FC 6F DE B7 58 93 89 8A E4 1C 54 DD BD BF 15 39 F8 CC BD 18 F6 7B 44 0D E1 AC 30 44 02 81 D4 0C FA C8 39'.replace(" ",""),16) - p = int('00 F2 0F 2F 3E 1D A6 18 83 F6 29 80 92 2B D8 DF 54 5C E4 07 C7 26 24 11 03 B5 E2 C5 37 23 12 4A 23'.replace(" ",""),16) - q = int('00 CA 1F E9 24 79 2C FC C9 6B FA B7 4F 34 4A 68 B4 18 DF 57 83 38 06 48 06 00 0F E2 A5 C9 9A 02 37'.replace(" ",""),16) - - # This is q^{-1} mod p). fastmath and slowmath use pInv (p^{-1} - # mod q) instead! - qInv = int('00 BD 9F 40 A7 64 22 7A 21 96 2A 4A DD 07 E4 DE FE 43 ED 91 A3 AE 27 BB 05 7F 39 24 1F 33 AB 01 C1'.replace(" ",""),16) - pInv = inverse(p,q) - - def testImportKey1(self): - """Verify import of RSAPrivateKey DER SEQUENCE""" - key = RSA.importKey(self.rsaKeyDER) - self.assertTrue(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey2(self): - """Verify import of SubjectPublicKeyInfo DER SEQUENCE""" - key = RSA.importKey(self.rsaPublicKeyDER) - self.assertFalse(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey3unicode(self): - """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" - key = RSA.importKey(self.rsaKeyPEM) - self.assertEqual(key.has_private(),True) # assert_ - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey3bytes(self): - """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as byte string""" - key = RSA.importKey(b(self.rsaKeyPEM)) - self.assertEqual(key.has_private(),True) # assert_ - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey4unicode(self): - """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" - key = RSA.importKey(self.rsaPublicKeyPEM) - self.assertEqual(key.has_private(),False) # assertFalse - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey4bytes(self): - """Verify import of SubjectPublicKeyInfo DER SEQUENCE, encoded with PEM as byte string""" - key = RSA.importKey(b(self.rsaPublicKeyPEM)) - self.assertEqual(key.has_private(),False) # assertFalse - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey5(self): - """Verifies that the imported key is still a valid RSA pair""" - key = RSA.importKey(self.rsaKeyPEM) - idem = key._encrypt(key._decrypt(89)) - self.assertEqual(idem, 89) - - def testImportKey6(self): - """Verifies that the imported key is still a valid RSA pair""" - key = RSA.importKey(self.rsaKeyDER) - idem = key._encrypt(key._decrypt(65)) - self.assertEqual(idem, 65) - - def testImportKey7(self): - """Verify import of OpenSSH public key""" - key = RSA.importKey(self.rsaPublicKeyOpenSSH) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey8(self): - """Verify import of encrypted PrivateKeyInfo DER SEQUENCE""" - for t in self.rsaKeyEncryptedPEM: - key = RSA.importKey(t[1], t[0]) - self.assertTrue(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey9(self): - """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE""" - key = RSA.importKey(self.rsaKeyDER8) - self.assertTrue(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey10(self): - """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE, encoded with PEM""" - key = RSA.importKey(self.rsaKeyPEM8) - self.assertTrue(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey11(self): - """Verify import of RSAPublicKey DER SEQUENCE""" - der = asn1.DerSequence([17, 3]).encode() - key = RSA.importKey(der) - self.assertEqual(key.n, 17) - self.assertEqual(key.e, 3) - - def testImportKey12(self): - """Verify import of RSAPublicKey DER SEQUENCE, encoded with PEM""" - der = asn1.DerSequence([17, 3]).encode() - pem = der2pem(der) - key = RSA.importKey(pem) - self.assertEqual(key.n, 17) - self.assertEqual(key.e, 3) - - def test_import_key_windows_cr_lf(self): - pem_cr_lf = "\r\n".join(self.rsaKeyPEM.splitlines()) - key = RSA.importKey(pem_cr_lf) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def test_import_empty(self): - self.assertRaises(ValueError, RSA.import_key, b"") - - ### - def testExportKey1(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - derKey = key.export_key("DER") - self.assertEqual(derKey, self.rsaKeyDER) - - def testExportKey2(self): - key = RSA.construct([self.n, self.e]) - derKey = key.export_key("DER") - self.assertEqual(derKey, self.rsaPublicKeyDER) - - def testExportKey3(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - pemKey = key.export_key("PEM") - self.assertEqual(pemKey, b(self.rsaKeyPEM)) - - def testExportKey4(self): - key = RSA.construct([self.n, self.e]) - pemKey = key.export_key("PEM") - self.assertEqual(pemKey, b(self.rsaPublicKeyPEM)) - - def testExportKey5(self): - key = RSA.construct([self.n, self.e]) - openssh_1 = key.export_key("OpenSSH").split() - openssh_2 = self.rsaPublicKeyOpenSSH.split() - self.assertEqual(openssh_1[0], openssh_2[0]) - self.assertEqual(openssh_1[1], openssh_2[1]) - - def testExportKey7(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - derKey = key.export_key("DER", pkcs=8) - self.assertEqual(derKey, self.rsaKeyDER8) - - def testExportKey8(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - pemKey = key.export_key("PEM", pkcs=8) - self.assertEqual(pemKey, b(self.rsaKeyPEM8)) - - def testExportKey9(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - self.assertRaises(ValueError, key.export_key, "invalid-format") - - def testExportKey10(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#1, old PEM encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test') - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')!=-1) - self.assertTrue(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey11(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#1, old PEM encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=1) - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')!=-1) - self.assertTrue(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey12(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#8, old PEM encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=8) - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')!=-1) - self.assertTrue(tostr(outkey).find('BEGIN PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey13(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#8, PKCS#8 encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=8, - protection='PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC') - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')==-1) - self.assertTrue(tostr(outkey).find('BEGIN ENCRYPTED PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey14(self): - # Export and re-import the encrypted key. It must match. - # DER envelope, PKCS#8, PKCS#8 encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('DER', 'test', pkcs=8) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey15(self): - # Verify that that error an condition is detected when trying to - # use a password with DER encoding and PKCS#1. - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - self.assertRaises(ValueError, key.export_key, 'DER', 'test', 1) - - def testExportKey16(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#8, PKCS#8 encryption with parameters - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=8, - protection='PBKDF2WithHMAC-SHA512AndAES256-CBC', - prot_params={'iteration_count':123} - ) - self.assertTrue(tostr(outkey).find('4,ENCRYPTED')==-1) - self.assertTrue(tostr(outkey).find('BEGIN ENCRYPTED PRIVATE KEY')!=-1) - - # Verify the iteration count - der = PEM.decode(tostr(outkey))[0] - seq1 = asn1.DerSequence().decode(der) - seq2 = asn1.DerSequence().decode(seq1[0]) - seq3 = asn1.DerSequence().decode(seq2[1]) - seq4 = asn1.DerSequence().decode(seq3[0]) - seq5 = asn1.DerSequence().decode(seq4[1]) - self.assertEqual(seq5[1], 123) - - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def test_import_key(self): - """Verify that import_key is an alias to importKey""" - key = RSA.import_key(self.rsaPublicKeyDER) - self.assertFalse(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def test_import_key_ba_mv(self): - """Verify that import_key can be used on bytearrays and memoryviews""" - key = RSA.import_key(bytearray(self.rsaPublicKeyDER)) - key = RSA.import_key(memoryview(self.rsaPublicKeyDER)) - - def test_exportKey(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - self.assertEqual(key.export_key(), key.exportKey()) + """.replace(" ", ""), + ) + + n = int( + "BF 1E 27 90 0A A0 8B 23 51 1A 5C 12 81 AE 6D 93 31 2C 3E FE 91 3F 93 2E BE D4 92 F1 2D 16 B4 61 0C 32 8C B6 E2 08 AB 5F 45 AC BE 29 50 83 32 98 F3 12 2C 19 F7 84 92 DE DF 40 F0 E3 C1 90 33 85".replace( + " ", "" + ), + 16, + ) + e = 65537 + d = int( + "09 44 83 12 9F 11 4D ED F6 7E DA BC 23 01 BC 5A 88 E5 E6 60 1D D7 01 62 20 EA D9 FD 4B FC 6F DE B7 58 93 89 8A E4 1C 54 DD BD BF 15 39 F8 CC BD 18 F6 7B 44 0D E1 AC 30 44 02 81 D4 0C FA C8 39".replace( + " ", "" + ), + 16, + ) + p = int( + "00 F2 0F 2F 3E 1D A6 18 83 F6 29 80 92 2B D8 DF 54 5C E4 07 C7 26 24 11 03 B5 E2 C5 37 23 12 4A 23".replace( + " ", "" + ), + 16, + ) + q = int( + "00 CA 1F E9 24 79 2C FC C9 6B FA B7 4F 34 4A 68 B4 18 DF 57 83 38 06 48 06 00 0F E2 A5 C9 9A 02 37".replace( + " ", "" + ), + 16, + ) + + # This is q^{-1} mod p). fastmath and slowmath use pInv (p^{-1} + # mod q) instead! + qInv = int( + "00 BD 9F 40 A7 64 22 7A 21 96 2A 4A DD 07 E4 DE FE 43 ED 91 A3 AE 27 BB 05 7F 39 24 1F 33 AB 01 C1".replace( + " ", "" + ), + 16, + ) + pInv = inverse(p, q) + + def testImportKey1(self): + """Verify import of RSAPrivateKey DER SEQUENCE""" + key = RSA.importKey(self.rsaKeyDER) + self.assertTrue(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey2(self): + """Verify import of SubjectPublicKeyInfo DER SEQUENCE""" + key = RSA.importKey(self.rsaPublicKeyDER) + self.assertFalse(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey3unicode(self): + """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" + key = RSA.importKey(self.rsaKeyPEM) + self.assertEqual(key.has_private(), True) # assert_ + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey3bytes(self): + """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as byte string""" + key = RSA.importKey(b(self.rsaKeyPEM)) + self.assertEqual(key.has_private(), True) # assert_ + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey4unicode(self): + """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" + key = RSA.importKey(self.rsaPublicKeyPEM) + self.assertEqual(key.has_private(), False) # assertFalse + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey4bytes(self): + """Verify import of SubjectPublicKeyInfo DER SEQUENCE, encoded with PEM as byte string""" + key = RSA.importKey(b(self.rsaPublicKeyPEM)) + self.assertEqual(key.has_private(), False) # assertFalse + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey5(self): + """Verifies that the imported key is still a valid RSA pair""" + key = RSA.importKey(self.rsaKeyPEM) + idem = key._encrypt(key._decrypt(89)) + self.assertEqual(idem, 89) + + def testImportKey6(self): + """Verifies that the imported key is still a valid RSA pair""" + key = RSA.importKey(self.rsaKeyDER) + idem = key._encrypt(key._decrypt(65)) + self.assertEqual(idem, 65) + + def testImportKey7(self): + """Verify import of OpenSSH public key""" + key = RSA.importKey(self.rsaPublicKeyOpenSSH) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey8(self): + """Verify import of encrypted PrivateKeyInfo DER SEQUENCE""" + for t in self.rsaKeyEncryptedPEM: + key = RSA.importKey(t[1], t[0]) + self.assertTrue(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey9(self): + """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE""" + key = RSA.importKey(self.rsaKeyDER8) + self.assertTrue(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey10(self): + """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE, encoded with PEM""" + key = RSA.importKey(self.rsaKeyPEM8) + self.assertTrue(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey11(self): + """Verify import of RSAPublicKey DER SEQUENCE""" + der = asn1.DerSequence([17, 3]).encode() + key = RSA.importKey(der) + self.assertEqual(key.n, 17) + self.assertEqual(key.e, 3) + + def testImportKey12(self): + """Verify import of RSAPublicKey DER SEQUENCE, encoded with PEM""" + der = asn1.DerSequence([17, 3]).encode() + pem = der2pem(der) + key = RSA.importKey(pem) + self.assertEqual(key.n, 17) + self.assertEqual(key.e, 3) + + def test_import_key_windows_cr_lf(self): + pem_cr_lf = "\r\n".join(self.rsaKeyPEM.splitlines()) + key = RSA.importKey(pem_cr_lf) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def test_import_empty(self): + self.assertRaises(ValueError, RSA.import_key, b"") + + ### + def testExportKey1(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + derKey = key.export_key("DER") + self.assertEqual(derKey, self.rsaKeyDER) + + def testExportKey2(self): + key = RSA.construct([self.n, self.e]) + derKey = key.export_key("DER") + self.assertEqual(derKey, self.rsaPublicKeyDER) + + def testExportKey3(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + pemKey = key.export_key("PEM") + self.assertEqual(pemKey, b(self.rsaKeyPEM)) + + def testExportKey4(self): + key = RSA.construct([self.n, self.e]) + pemKey = key.export_key("PEM") + self.assertEqual(pemKey, b(self.rsaPublicKeyPEM)) + + def testExportKey5(self): + key = RSA.construct([self.n, self.e]) + openssh_1 = key.export_key("OpenSSH").split() + openssh_2 = self.rsaPublicKeyOpenSSH.split() + self.assertEqual(openssh_1[0], openssh_2[0]) + self.assertEqual(openssh_1[1], openssh_2[1]) + + def testExportKey7(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + derKey = key.export_key("DER", pkcs=8) + self.assertEqual(derKey, self.rsaKeyDER8) + + def testExportKey8(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + pemKey = key.export_key("PEM", pkcs=8) + self.assertEqual(pemKey, b(self.rsaKeyPEM8)) + + def testExportKey9(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + self.assertRaises(ValueError, key.export_key, "invalid-format") + + def testExportKey10(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#1, old PEM encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key("PEM", "test") + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") != -1) + self.assertTrue(tostr(outkey).find("BEGIN RSA PRIVATE KEY") != -1) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey11(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#1, old PEM encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key("PEM", "test", pkcs=1) + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") != -1) + self.assertTrue(tostr(outkey).find("BEGIN RSA PRIVATE KEY") != -1) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey12(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#8, old PEM encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key("PEM", "test", pkcs=8) + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") != -1) + self.assertTrue(tostr(outkey).find("BEGIN PRIVATE KEY") != -1) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey13(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#8, PKCS#8 encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key( + "PEM", + "test", + pkcs=8, + protection="PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC", + ) + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") == -1) + self.assertTrue(tostr(outkey).find("BEGIN ENCRYPTED PRIVATE KEY") != -1) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey14(self): + # Export and re-import the encrypted key. It must match. + # DER envelope, PKCS#8, PKCS#8 encryption + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key("DER", "test", pkcs=8) + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey15(self): + # Verify that that error an condition is detected when trying to + # use a password with DER encoding and PKCS#1. + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + self.assertRaises(ValueError, key.export_key, "DER", "test", 1) + + def testExportKey16(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#8, PKCS#8 encryption with parameters + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.export_key( + "PEM", + "test", + pkcs=8, + protection="PBKDF2WithHMAC-SHA512AndAES256-CBC", + prot_params={"iteration_count": 123}, + ) + self.assertTrue(tostr(outkey).find("4,ENCRYPTED") == -1) + self.assertTrue(tostr(outkey).find("BEGIN ENCRYPTED PRIVATE KEY") != -1) + + # Verify the iteration count + der = PEM.decode(tostr(outkey))[0] + seq1 = asn1.DerSequence().decode(der) + seq2 = asn1.DerSequence().decode(seq1[0]) + seq3 = asn1.DerSequence().decode(seq2[1]) + seq4 = asn1.DerSequence().decode(seq3[0]) + seq5 = asn1.DerSequence().decode(seq4[1]) + self.assertEqual(seq5[1], 123) + + inkey = RSA.importKey(outkey, "test") + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def test_import_key(self): + """Verify that import_key is an alias to importKey""" + key = RSA.import_key(self.rsaPublicKeyDER) + self.assertFalse(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def test_import_key_ba_mv(self): + """Verify that import_key can be used on bytearrays and memoryviews""" + key = RSA.import_key(bytearray(self.rsaPublicKeyDER)) + key = RSA.import_key(memoryview(self.rsaPublicKeyDER)) + + def test_exportKey(self): + key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + self.assertEqual(key.export_key(), key.exportKey()) class ImportKeyFromX509Cert(unittest.TestCase): - - def test_x509v1(self): - - # Sample V1 certificate with a 1024 bit RSA key - x509_v1_cert = """ + def test_x509v1(self): + # Sample V1 certificate with a 1024 bit RSA key + x509_v1_cert = """ -----BEGIN CERTIFICATE----- MIICOjCCAaMCAQEwDQYJKoZIhvcNAQEEBQAwfjENMAsGA1UEChMEQWNtZTELMAkG A1UECxMCUkQxHDAaBgkqhkiG9w0BCQEWDXNwYW1AYWNtZS5vcmcxEzARBgNVBAcT @@ -488,9 +532,9 @@ def test_x509v1(self): -----END CERTIFICATE----- """.strip() - # RSA public key as dumped by openssl - exponent = 65537 - modulus_str = """ + # RSA public key as dumped by openssl + exponent = 65537 + modulus_str = """ 00:c8:6f:a4:ca:d7:51:8f:74:c5:6d:19:87:0d:8a: 77:4d:7b:a0:55:0f:35:72:17:b0:d2:a7:8e:c5:95: 8e:cf:cd:08:8e:d5:a9:81:d3:9a:0a:f2:96:34:2b: @@ -501,17 +545,16 @@ def test_x509v1(self): a3:18:d0:da:95:9f:05:d6:99:37:db:e0:81:b3:c8: 75:c4:dc:79:0f:2c:6e:10:75 """ - modulus = int(re.sub("[^0-9a-f]","", modulus_str), 16) - - key = RSA.importKey(x509_v1_cert) - self.assertEqual(key.e, exponent) - self.assertEqual(key.n, modulus) - self.assertFalse(key.has_private()) + modulus = int(re.sub("[^0-9a-f]", "", modulus_str), 16) - def test_x509v3(self): + key = RSA.importKey(x509_v1_cert) + self.assertEqual(key.e, exponent) + self.assertEqual(key.n, modulus) + self.assertFalse(key.has_private()) - # Sample V3 certificate with a 1024 bit RSA key - x509_v3_cert = """ + def test_x509v3(self): + # Sample V3 certificate with a 1024 bit RSA key + x509_v3_cert = """ -----BEGIN CERTIFICATE----- MIIEcjCCAlqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL MAkGA1UECAwCTUQxEjAQBgNVBAcMCUJhbHRpbW9yZTEQMA4GA1UEAwwHVGVzdCBD @@ -540,9 +583,9 @@ def test_x509v3(self): -----END CERTIFICATE----- """.strip() - # RSA public key as dumped by openssl - exponent = 65537 - modulus_str = """ + # RSA public key as dumped by openssl + exponent = 65537 + modulus_str = """ 00:fd:2e:c6:25:5d:8e:70:57:72:34:c4:38:2b:be: 4a:ad:81:6d:30:49:f7:56:71:05:74:f1:da:8f:24: b7:ed:79:4c:c5:28:74:a1:2e:06:79:31:95:50:22: @@ -553,84 +596,85 @@ def test_x509v3(self): eb:3d:0f:fb:78:07:5d:cc:a5:2b:cf:06:9c:55:b9: d6:fa:d8:36:42:d4:97:29:17 """ - modulus = int(re.sub("[^0-9a-f]","", modulus_str), 16) + modulus = int(re.sub("[^0-9a-f]", "", modulus_str), 16) - key = RSA.importKey(x509_v3_cert) - self.assertEqual(key.e, exponent) - self.assertEqual(key.n, modulus) - self.assertFalse(key.has_private()) + key = RSA.importKey(x509_v3_cert) + self.assertEqual(key.e, exponent) + self.assertEqual(key.n, modulus) + self.assertFalse(key.has_private()) class TestImport_2048(unittest.TestCase): + def test_import_pss(self): + pub_key_file = load_file("rsa2048_pss_public.pem") + pub_key = RSA.import_key(pub_key_file) - def test_import_pss(self): - pub_key_file = load_file("rsa2048_pss_public.pem") - pub_key = RSA.import_key(pub_key_file) - - priv_key_file = load_file("rsa2048_pss_private.pem") - priv_key = RSA.import_key(priv_key_file) + priv_key_file = load_file("rsa2048_pss_private.pem") + priv_key = RSA.import_key(priv_key_file) - self.assertEqual(pub_key.n, priv_key.n) + self.assertEqual(pub_key.n, priv_key.n) - def test_import_openssh_public(self): - key_file_ref = load_file("rsa2048_private.pem") - key_file = load_file("rsa2048_public_openssh.txt") + def test_import_openssh_public(self): + key_file_ref = load_file("rsa2048_private.pem") + key_file = load_file("rsa2048_public_openssh.txt") - # Skip test if test vectors are not installed - if None in (key_file_ref, key_file): - return + # Skip test if test vectors are not installed + if None in (key_file_ref, key_file): + return - key_ref = RSA.import_key(key_file_ref).public_key() - key = RSA.import_key(key_file) - self.assertEqual(key_ref, key) + key_ref = RSA.import_key(key_file_ref).public_key() + key = RSA.import_key(key_file) + self.assertEqual(key_ref, key) - def test_import_openssh_private_clear(self): - key_file = load_file("rsa2048_private_openssh.pem") - key_file_old = load_file("rsa2048_private_openssh_old.pem") + def test_import_openssh_private_clear(self): + key_file = load_file("rsa2048_private_openssh.pem") + key_file_old = load_file("rsa2048_private_openssh_old.pem") - # Skip test if test vectors are not installed - if None in (key_file_old, key_file): - return + # Skip test if test vectors are not installed + if None in (key_file_old, key_file): + return - key = RSA.import_key(key_file) - key_old = RSA.import_key(key_file_old) + key = RSA.import_key(key_file) + key_old = RSA.import_key(key_file_old) - self.assertEqual(key, key_old) + self.assertEqual(key, key_old) - def test_import_openssh_private_password(self): - key_file = load_file("rsa2048_private_openssh_pwd.pem") - key_file_old = load_file("rsa2048_private_openssh_pwd_old.pem") + def test_import_openssh_private_password(self): + key_file = load_file("rsa2048_private_openssh_pwd.pem") + key_file_old = load_file("rsa2048_private_openssh_pwd_old.pem") - # Skip test if test vectors are not installed - if None in (key_file_old, key_file): - return + # Skip test if test vectors are not installed + if None in (key_file_old, key_file): + return - key = RSA.import_key(key_file, b"password") - key_old = RSA.import_key(key_file_old) - self.assertEqual(key, key_old) + key = RSA.import_key(key_file, b"password") + key_old = RSA.import_key(key_file_old) + self.assertEqual(key, key_old) - def test_import_pkcs8_private(self): - key_file_ref = load_file("rsa2048_private.pem") - key_file = load_file("rsa2048_private_p8.der") + def test_import_pkcs8_private(self): + key_file_ref = load_file("rsa2048_private.pem") + key_file = load_file("rsa2048_private_p8.der") - # Skip test if test vectors are not installed - if None in (key_file_ref, key_file): - return + # Skip test if test vectors are not installed + if None in (key_file_ref, key_file): + return - key_ref = RSA.import_key(key_file_ref) - key = RSA.import_key(key_file, b'secret') - self.assertEqual(key_ref, key) + key_ref = RSA.import_key(key_file_ref) + key = RSA.import_key(key_file, b"secret") + self.assertEqual(key_ref, key) def get_tests(config={}): - tests = [] - tests += list_test_cases(ImportKeyTests) - tests += list_test_cases(ImportKeyFromX509Cert) - tests += list_test_cases(TestImport_2048) - return tests + tests = [] + tests += list_test_cases(ImportKeyTests) + tests += list_test_cases(ImportKeyFromX509Cert) + tests += list_test_cases(TestImport_2048) + return tests + + +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Random/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Random/__init__.py index 763ee9c4..492a0fef 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Random/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Random/__init__.py @@ -26,14 +26,19 @@ __revision__ = "$Id$" + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Random import test_random; tests += test_random.get_tests(config=config) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + from Cryptodome.SelfTest.Random import test_random + + tests += test_random.get_tests(config=config) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Random/test_random.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Random/test_random.py index 30e9194e..6422fb69 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Random/test_random.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Random/test_random.py @@ -28,140 +28,145 @@ import unittest from Cryptodome.Util.py3compat import b + class SimpleTest(unittest.TestCase): - def runTest(self): - """Cryptodome.Random.new()""" - # Import the Random module and try to use it - from Cryptodome import Random - randobj = Random.new() - x = randobj.read(16) - y = randobj.read(16) - self.assertNotEqual(x, y) - z = Random.get_random_bytes(16) - self.assertNotEqual(x, z) - self.assertNotEqual(y, z) - # Test the Random.random module, which - # implements a subset of Python's random API - # Not implemented: - # seed(), getstate(), setstate(), jumpahead() - # random(), uniform(), triangular(), betavariate() - # expovariate(), gammavariate(), gauss(), - # longnormvariate(), normalvariate(), - # vonmisesvariate(), paretovariate() - # weibullvariate() - # WichmannHill(), whseed(), SystemRandom() - from Cryptodome.Random import random - x = random.getrandbits(16*8) - y = random.getrandbits(16*8) - self.assertNotEqual(x, y) - # Test randrange - if x>y: - start = y - stop = x - else: - start = x - stop = y - for step in range(1,10): - x = random.randrange(start,stop,step) - y = random.randrange(start,stop,step) - self.assertNotEqual(x, y) - self.assertEqual(start <= x < stop, True) - self.assertEqual(start <= y < stop, True) - self.assertEqual((x - start) % step, 0) - self.assertEqual((y - start) % step, 0) - for i in range(10): - self.assertEqual(random.randrange(1,2), 1) - self.assertRaises(ValueError, random.randrange, start, start) - self.assertRaises(ValueError, random.randrange, stop, start, step) - self.assertRaises(TypeError, random.randrange, start, stop, step, step) - self.assertRaises(TypeError, random.randrange, start, stop, "1") - self.assertRaises(TypeError, random.randrange, "1", stop, step) - self.assertRaises(TypeError, random.randrange, 1, "2", step) - self.assertRaises(ValueError, random.randrange, start, stop, 0) - # Test randint - x = random.randint(start,stop) - y = random.randint(start,stop) - self.assertNotEqual(x, y) - self.assertEqual(start <= x <= stop, True) - self.assertEqual(start <= y <= stop, True) - for i in range(10): - self.assertEqual(random.randint(1,1), 1) - self.assertRaises(ValueError, random.randint, stop, start) - self.assertRaises(TypeError, random.randint, start, stop, step) - self.assertRaises(TypeError, random.randint, "1", stop) - self.assertRaises(TypeError, random.randint, 1, "2") - # Test choice - seq = range(10000) - x = random.choice(seq) - y = random.choice(seq) - self.assertNotEqual(x, y) - self.assertEqual(x in seq, True) - self.assertEqual(y in seq, True) - for i in range(10): - self.assertEqual(random.choice((1,2,3)) in (1,2,3), True) - self.assertEqual(random.choice([1,2,3]) in [1,2,3], True) - if sys.version_info[0] == 3: - self.assertEqual(random.choice(bytearray(b('123'))) in bytearray(b('123')), True) - self.assertEqual(1, random.choice([1])) - self.assertRaises(IndexError, random.choice, []) - self.assertRaises(TypeError, random.choice, 1) - # Test shuffle. Lacks random parameter to specify function. - # Make copies of seq - seq = range(500) - x = list(seq) - y = list(seq) - random.shuffle(x) - random.shuffle(y) - self.assertNotEqual(x, y) - self.assertEqual(len(seq), len(x)) - self.assertEqual(len(seq), len(y)) - for i in range(len(seq)): - self.assertEqual(x[i] in seq, True) - self.assertEqual(y[i] in seq, True) - self.assertEqual(seq[i] in x, True) - self.assertEqual(seq[i] in y, True) - z = [1] - random.shuffle(z) - self.assertEqual(z, [1]) - if sys.version_info[0] == 3: - z = bytearray(b('12')) - random.shuffle(z) - self.assertEqual(b('1') in z, True) - self.assertRaises(TypeError, random.shuffle, b('12')) - self.assertRaises(TypeError, random.shuffle, 1) - self.assertRaises(TypeError, random.shuffle, "11") - self.assertRaises(TypeError, random.shuffle, (1,2)) - # 2to3 wraps a list() around it, alas - but I want to shoot - # myself in the foot here! :D - # if sys.version_info[0] == 3: - # self.assertRaises(TypeError, random.shuffle, range(3)) - # Test sample - x = random.sample(seq, 20) - y = random.sample(seq, 20) - self.assertNotEqual(x, y) - for i in range(20): - self.assertEqual(x[i] in seq, True) - self.assertEqual(y[i] in seq, True) - z = random.sample([1], 1) - self.assertEqual(z, [1]) - z = random.sample((1,2,3), 1) - self.assertEqual(z[0] in (1,2,3), True) - z = random.sample("123", 1) - self.assertEqual(z[0] in "123", True) - z = random.sample(range(3), 1) - self.assertEqual(z[0] in range(3), True) - if sys.version_info[0] == 3: - z = random.sample(b("123"), 1) - self.assertEqual(z[0] in b("123"), True) - z = random.sample(bytearray(b("123")), 1) - self.assertEqual(z[0] in bytearray(b("123")), True) - self.assertRaises(TypeError, random.sample, 1) + def runTest(self): + """Cryptodome.Random.new()""" + # Import the Random module and try to use it + from Cryptodome import Random + + randobj = Random.new() + x = randobj.read(16) + y = randobj.read(16) + self.assertNotEqual(x, y) + z = Random.get_random_bytes(16) + self.assertNotEqual(x, z) + self.assertNotEqual(y, z) + # Test the Random.random module, which + # implements a subset of Python's random API + # Not implemented: + # seed(), getstate(), setstate(), jumpahead() + # random(), uniform(), triangular(), betavariate() + # expovariate(), gammavariate(), gauss(), + # longnormvariate(), normalvariate(), + # vonmisesvariate(), paretovariate() + # weibullvariate() + # WichmannHill(), whseed(), SystemRandom() + from Cryptodome.Random import random + + x = random.getrandbits(16 * 8) + y = random.getrandbits(16 * 8) + self.assertNotEqual(x, y) + # Test randrange + if x > y: + start = y + stop = x + else: + start = x + stop = y + for step in range(1, 10): + x = random.randrange(start, stop, step) + y = random.randrange(start, stop, step) + self.assertNotEqual(x, y) + self.assertEqual(start <= x < stop, True) + self.assertEqual(start <= y < stop, True) + self.assertEqual((x - start) % step, 0) + self.assertEqual((y - start) % step, 0) + for i in range(10): + self.assertEqual(random.randrange(1, 2), 1) + self.assertRaises(ValueError, random.randrange, start, start) + self.assertRaises(ValueError, random.randrange, stop, start, step) + self.assertRaises(TypeError, random.randrange, start, stop, step, step) + self.assertRaises(TypeError, random.randrange, start, stop, "1") + self.assertRaises(TypeError, random.randrange, "1", stop, step) + self.assertRaises(TypeError, random.randrange, 1, "2", step) + self.assertRaises(ValueError, random.randrange, start, stop, 0) + # Test randint + x = random.randint(start, stop) + y = random.randint(start, stop) + self.assertNotEqual(x, y) + self.assertEqual(start <= x <= stop, True) + self.assertEqual(start <= y <= stop, True) + for i in range(10): + self.assertEqual(random.randint(1, 1), 1) + self.assertRaises(ValueError, random.randint, stop, start) + self.assertRaises(TypeError, random.randint, start, stop, step) + self.assertRaises(TypeError, random.randint, "1", stop) + self.assertRaises(TypeError, random.randint, 1, "2") + # Test choice + seq = range(10000) + x = random.choice(seq) + y = random.choice(seq) + self.assertNotEqual(x, y) + self.assertEqual(x in seq, True) + self.assertEqual(y in seq, True) + for i in range(10): + self.assertEqual(random.choice((1, 2, 3)) in (1, 2, 3), True) + self.assertEqual(random.choice([1, 2, 3]) in [1, 2, 3], True) + if sys.version_info[0] == 3: + self.assertEqual(random.choice(bytearray(b("123"))) in bytearray(b("123")), True) + self.assertEqual(1, random.choice([1])) + self.assertRaises(IndexError, random.choice, []) + self.assertRaises(TypeError, random.choice, 1) + # Test shuffle. Lacks random parameter to specify function. + # Make copies of seq + seq = range(500) + x = list(seq) + y = list(seq) + random.shuffle(x) + random.shuffle(y) + self.assertNotEqual(x, y) + self.assertEqual(len(seq), len(x)) + self.assertEqual(len(seq), len(y)) + for i in range(len(seq)): + self.assertEqual(x[i] in seq, True) + self.assertEqual(y[i] in seq, True) + self.assertEqual(seq[i] in x, True) + self.assertEqual(seq[i] in y, True) + z = [1] + random.shuffle(z) + self.assertEqual(z, [1]) + if sys.version_info[0] == 3: + z = bytearray(b("12")) + random.shuffle(z) + self.assertEqual(b("1") in z, True) + self.assertRaises(TypeError, random.shuffle, b("12")) + self.assertRaises(TypeError, random.shuffle, 1) + self.assertRaises(TypeError, random.shuffle, "11") + self.assertRaises(TypeError, random.shuffle, (1, 2)) + # 2to3 wraps a list() around it, alas - but I want to shoot + # myself in the foot here! :D + # if sys.version_info[0] == 3: + # self.assertRaises(TypeError, random.shuffle, range(3)) + # Test sample + x = random.sample(seq, 20) + y = random.sample(seq, 20) + self.assertNotEqual(x, y) + for i in range(20): + self.assertEqual(x[i] in seq, True) + self.assertEqual(y[i] in seq, True) + z = random.sample([1], 1) + self.assertEqual(z, [1]) + z = random.sample((1, 2, 3), 1) + self.assertEqual(z[0] in (1, 2, 3), True) + z = random.sample("123", 1) + self.assertEqual(z[0] in "123", True) + z = random.sample(range(3), 1) + self.assertEqual(z[0] in range(3), True) + if sys.version_info[0] == 3: + z = random.sample(b("123"), 1) + self.assertEqual(z[0] in b("123"), True) + z = random.sample(bytearray(b("123")), 1) + self.assertEqual(z[0] in bytearray(b("123")), True) + self.assertRaises(TypeError, random.sample, 1) + def get_tests(config={}): - return [SimpleTest()] + return [SimpleTest()] + -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/__init__.py index 83cf0f39..90eff314 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/__init__.py @@ -27,15 +27,17 @@ def get_tests(config={}): - tests = [] - tests += test_pkcs1_15.get_tests(config=config) - tests += test_pss.get_tests(config=config) - tests += test_dss.get_tests(config=config) - tests += test_eddsa.get_tests(config=config) - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += test_pkcs1_15.get_tests(config=config) + tests += test_pss.get_tests(config=config) + tests += test_dss.get_tests(config=config) + tests += test_eddsa.get_tests(config=config) + return tests + + +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_dss.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_dss.py index 156ee67a..70aba52b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_dss.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_dss.py @@ -37,8 +37,17 @@ from Cryptodome.Util.py3compat import tobytes, bord, bchr -from Cryptodome.Hash import (SHA1, SHA224, SHA256, SHA384, SHA512, - SHA3_224, SHA3_256, SHA3_384, SHA3_512) +from Cryptodome.Hash import ( + SHA1, + SHA224, + SHA256, + SHA384, + SHA512, + SHA3_224, + SHA3_256, + SHA3_384, + SHA3_512, +) from Cryptodome.Signature import DSS from Cryptodome.PublicKey import DSA, ECC from Cryptodome.SelfTest.st_common import list_test_cases @@ -47,364 +56,386 @@ def t2b(hexstring): - ws = hexstring.replace(" ", "").replace("\n", "") - return unhexlify(tobytes(ws)) + ws = hexstring.replace(" ", "").replace("\n", "") + return unhexlify(tobytes(ws)) def t2l(hexstring): - ws = hexstring.replace(" ", "").replace("\n", "") - return int(ws, 16) + ws = hexstring.replace(" ", "").replace("\n", "") + return int(ws, 16) def load_hash_by_name(hash_name): - return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) + return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) class StrRNG: + def __init__(self, randomness): + length = len(randomness) + self._idx = 0 + # Fix required to get the right K (see how randint() works!) + self._randomness = long_to_bytes(bytes_to_long(randomness) - 1, length) - def __init__(self, randomness): - length = len(randomness) - self._idx = 0 - # Fix required to get the right K (see how randint() works!) - self._randomness = long_to_bytes(bytes_to_long(randomness) - 1, length) - - def __call__(self, n): - out = self._randomness[self._idx:self._idx + n] - self._idx += n - return out + def __call__(self, n): + out = self._randomness[self._idx : self._idx + n] + self._idx += n + return out class FIPS_DSA_Tests(unittest.TestCase): + # 1st 1024 bit key from SigGen.txt + P = 0xA8F9CD201E5E35D892F85F80E4DB2599A5676A3B1D4F190330ED3256B26D0E80A0E49A8FFFAAAD2A24F472D2573241D4D6D6C7480C80B4C67BB4479C15ADA7EA8424D2502FA01472E760241713DAB025AE1B02E1703A1435F62DDF4EE4C1B664066EB22F2E3BF28BB70A2A76E4FD5EBE2D1229681B5B06439AC9C7E9D8BDE283 + Q = 0xF85F0F83AC4DF7EA0CDF8F469BFEEAEA14156495 + G = 0x2B3152FF6C62F14622B8F48E59F8AF46883B38E79B8C74DEEAE9DF131F8B856E3AD6C8455DAB87CC0DA8AC973417CE4F7878557D6CDF40B35B4A0CA3EB310C6A95D68CE284AD4E25EA28591611EE08B8444BD64B25F3F7C572410DDFB39CC728B9C936F85F419129869929CDB909A6A3A99BBE089216368171BD0BA81DE4FE33 + X = 0xC53EAE6D45323164C7D07AF5715703744A63FC3A + Y = 0x313FD9EBCA91574E1C2EEBE1517C57E0C21B0209872140C5328761BBB2450B33F1B18B409CE9AB7C4CD8FDA3391E8E34868357C199E16A6B2EBA06D6749DEF791D79E95D3A4D09B24C392AD89DBF100995AE19C01062056BB14BCE005E8731EFDE175F95B975089BDCDAEA562B32786D96F5A31AEDF75364008AD4FFFEBB970B - # 1st 1024 bit key from SigGen.txt - P = 0xa8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed3256b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b02e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd5ebe2d1229681b5b06439ac9c7e9d8bde283 - Q = 0xf85f0f83ac4df7ea0cdf8f469bfeeaea14156495 - G = 0x2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df131f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909a6a3a99bbe089216368171bd0ba81de4fe33 - X = 0xc53eae6d45323164c7d07af5715703744a63fc3a - Y = 0x313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761bbb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae19c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32786d96f5a31aedf75364008ad4fffebb970b - - key_pub = DSA.construct((Y, G, P, Q)) - key_priv = DSA.construct((Y, G, P, Q, X)) + key_pub = DSA.construct((Y, G, P, Q)) + key_priv = DSA.construct((Y, G, P, Q, X)) - def shortDescription(self): - return "FIPS DSA Tests" + def shortDescription(self): + return "FIPS DSA Tests" - def test_loopback(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv, 'fips-186-3') - signature = signer.sign(hashed_msg) + def test_loopback(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv, "fips-186-3") + signature = signer.sign(hashed_msg) - verifier = DSS.new(self.key_pub, 'fips-186-3') - verifier.verify(hashed_msg, signature) + verifier = DSS.new(self.key_pub, "fips-186-3") + verifier.verify(hashed_msg, signature) - def test_negative_unapproved_hashes(self): - """Verify that unapproved hashes are rejected""" + def test_negative_unapproved_hashes(self): + """Verify that unapproved hashes are rejected""" - from Cryptodome.Hash import RIPEMD160 + from Cryptodome.Hash import RIPEMD160 - self.description = "Unapproved hash (RIPEMD160) test" - hash_obj = RIPEMD160.new() - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertRaises(ValueError, signer.sign, hash_obj) - self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) + self.description = "Unapproved hash (RIPEMD160) test" + hash_obj = RIPEMD160.new() + signer = DSS.new(self.key_priv, "fips-186-3") + self.assertRaises(ValueError, signer.sign, hash_obj) + self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) - def test_negative_unknown_modes_encodings(self): - """Verify that unknown modes/encodings are rejected""" + def test_negative_unknown_modes_encodings(self): + """Verify that unknown modes/encodings are rejected""" - self.description = "Unknown mode test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-0') + self.description = "Unknown mode test" + self.assertRaises(ValueError, DSS.new, self.key_priv, "fips-186-0") - self.description = "Unknown encoding test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-3', 'xml') + self.description = "Unknown encoding test" + self.assertRaises(ValueError, DSS.new, self.key_priv, "fips-186-3", "xml") - def test_asn1_encoding(self): - """Verify ASN.1 encoding""" + def test_asn1_encoding(self): + """Verify ASN.1 encoding""" - self.description = "ASN.1 encoding test" - hash_obj = SHA1.new() - signer = DSS.new(self.key_priv, 'fips-186-3', 'der') - signature = signer.sign(hash_obj) + self.description = "ASN.1 encoding test" + hash_obj = SHA1.new() + signer = DSS.new(self.key_priv, "fips-186-3", "der") + signature = signer.sign(hash_obj) - # Verify that output looks like a DER SEQUENCE - self.assertEqual(bord(signature[0]), 48) - signer.verify(hash_obj, signature) + # Verify that output looks like a DER SEQUENCE + self.assertEqual(bord(signature[0]), 48) + signer.verify(hash_obj, signature) - # Verify that ASN.1 parsing fails as expected - signature = bchr(7) + signature[1:] - self.assertRaises(ValueError, signer.verify, hash_obj, signature) + # Verify that ASN.1 parsing fails as expected + signature = bchr(7) + signature[1:] + self.assertRaises(ValueError, signer.verify, hash_obj, signature) - def test_sign_verify(self): - """Verify public/private method""" + def test_sign_verify(self): + """Verify public/private method""" - self.description = "can_sign() test" - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertTrue(signer.can_sign()) + self.description = "can_sign() test" + signer = DSS.new(self.key_priv, "fips-186-3") + self.assertTrue(signer.can_sign()) - signer = DSS.new(self.key_pub, 'fips-186-3') - self.assertFalse(signer.can_sign()) + signer = DSS.new(self.key_pub, "fips-186-3") + self.assertFalse(signer.can_sign()) - try: - signer.sign(SHA256.new(b'xyz')) - except TypeError as e: - msg = str(e) - else: - msg = "" - self.assertTrue("Private key is needed" in msg) + try: + signer.sign(SHA256.new(b"xyz")) + except TypeError as e: + msg = str(e) + else: + msg = "" + self.assertTrue("Private key is needed" in msg) class FIPS_DSA_Tests_KAT(unittest.TestCase): - pass + pass -test_vectors_verify = load_test_vectors(("Signature", "DSA"), - "FIPS_186_3_SigVer.rsp", - "Signature Verification 186-3", - {'result': lambda x: x}) or [] +test_vectors_verify = ( + load_test_vectors( + ("Signature", "DSA"), + "FIPS_186_3_SigVer.rsp", + "Signature Verification 186-3", + {"result": lambda x: x}, + ) + or [] +) for idx, tv in enumerate(test_vectors_verify): - - if isinstance(tv, str): - res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) - assert(res) - hash_name = res.group(3).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue - - if hasattr(tv, "p"): - modulus = tv.p - generator = tv.g - suborder = tv.q - continue - - hash_obj = hash_module.new(tv.msg) - - comps = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder)] - key = DSA.construct(comps, False) # type: ignore - verifier = DSS.new(key, 'fips-186-3') - - def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result == 'p': - setattr(FIPS_DSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) - else: - setattr(FIPS_DSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) - - -test_vectors_sign = load_test_vectors(("Signature", "DSA"), - "FIPS_186_3_SigGen.txt", - "Signature Creation 186-3", - {}) or [] + if isinstance(tv, str): + res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) + assert res + hash_name = res.group(3).replace("-", "") + hash_module = load_hash_by_name(hash_name) + continue + + if hasattr(tv, "p"): + modulus = tv.p + generator = tv.g + suborder = tv.q + continue + + hash_obj = hash_module.new(tv.msg) + + comps = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder)] + key = DSA.construct(comps, False) # type: ignore + verifier = DSS.new(key, "fips-186-3") + + def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r + tv.s): + verifier.verify(hash_obj, signature) + + def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r + tv.s): + self.assertRaises(ValueError, verifier.verify, hash_obj, signature) + + if tv.result == "p": + setattr(FIPS_DSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) + else: + setattr(FIPS_DSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) + + +test_vectors_sign = ( + load_test_vectors( + ("Signature", "DSA"), + "FIPS_186_3_SigGen.txt", + "Signature Creation 186-3", + {}, + ) + or [] +) for idx, tv in enumerate(test_vectors_sign): + if isinstance(tv, str): + res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) + assert res + hash_name = res.group(3).replace("-", "") + hash_module = load_hash_by_name(hash_name) + continue - if isinstance(tv, str): - res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) - assert(res) - hash_name = res.group(3).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue + if hasattr(tv, "p"): + modulus = tv.p + generator = tv.g + suborder = tv.q + continue - if hasattr(tv, "p"): - modulus = tv.p - generator = tv.g - suborder = tv.q - continue + hash_obj = hash_module.new(tv.msg) + comps_dsa = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder, tv.x)] + key = DSA.construct(comps_dsa, False) # type: ignore + signer = DSS.new(key, "fips-186-3", randfunc=StrRNG(tv.k)) - hash_obj = hash_module.new(tv.msg) - comps_dsa = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder, tv.x)] - key = DSA.construct(comps_dsa, False) # type: ignore - signer = DSS.new(key, 'fips-186-3', randfunc=StrRNG(tv.k)) + def new_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r + tv.s): + self.assertEqual(signer.sign(hash_obj), signature) - def new_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertEqual(signer.sign(hash_obj), signature) - setattr(FIPS_DSA_Tests_KAT, "test_sign_%d" % idx, new_test) + setattr(FIPS_DSA_Tests_KAT, "test_sign_%d" % idx, new_test) class FIPS_ECDSA_Tests(unittest.TestCase): + key_priv = ECC.generate(curve="P-256") + key_pub = key_priv.public_key() - key_priv = ECC.generate(curve="P-256") - key_pub = key_priv.public_key() - - def shortDescription(self): - return "FIPS ECDSA Tests" + def shortDescription(self): + return "FIPS ECDSA Tests" - def test_loopback(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv, 'fips-186-3') - signature = signer.sign(hashed_msg) + def test_loopback(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv, "fips-186-3") + signature = signer.sign(hashed_msg) - verifier = DSS.new(self.key_pub, 'fips-186-3') - verifier.verify(hashed_msg, signature) + verifier = DSS.new(self.key_pub, "fips-186-3") + verifier.verify(hashed_msg, signature) - def test_negative_unapproved_hashes(self): - """Verify that unapproved hashes are rejected""" + def test_negative_unapproved_hashes(self): + """Verify that unapproved hashes are rejected""" - from Cryptodome.Hash import SHA1 + from Cryptodome.Hash import SHA1 - self.description = "Unapproved hash (SHA-1) test" - hash_obj = SHA1.new() - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertRaises(ValueError, signer.sign, hash_obj) - self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) + self.description = "Unapproved hash (SHA-1) test" + hash_obj = SHA1.new() + signer = DSS.new(self.key_priv, "fips-186-3") + self.assertRaises(ValueError, signer.sign, hash_obj) + self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) - def test_negative_eddsa_key(self): - key = ECC.generate(curve="ed25519") - self.assertRaises(ValueError, DSS.new, key, 'fips-186-3') + def test_negative_eddsa_key(self): + key = ECC.generate(curve="ed25519") + self.assertRaises(ValueError, DSS.new, key, "fips-186-3") - def test_sign_verify(self): - """Verify public/private method""" + def test_sign_verify(self): + """Verify public/private method""" - self.description = "can_sign() test" - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertTrue(signer.can_sign()) + self.description = "can_sign() test" + signer = DSS.new(self.key_priv, "fips-186-3") + self.assertTrue(signer.can_sign()) - signer = DSS.new(self.key_pub, 'fips-186-3') - self.assertFalse(signer.can_sign()) - self.assertRaises(TypeError, signer.sign, SHA256.new(b'xyz')) + signer = DSS.new(self.key_pub, "fips-186-3") + self.assertFalse(signer.can_sign()) + self.assertRaises(TypeError, signer.sign, SHA256.new(b"xyz")) - try: - signer.sign(SHA256.new(b'xyz')) - except TypeError as e: - msg = str(e) - else: - msg = "" - self.assertTrue("Private key is needed" in msg) + try: + signer.sign(SHA256.new(b"xyz")) + except TypeError as e: + msg = str(e) + else: + msg = "" + self.assertTrue("Private key is needed" in msg) - def test_negative_unknown_modes_encodings(self): - """Verify that unknown modes/encodings are rejected""" + def test_negative_unknown_modes_encodings(self): + """Verify that unknown modes/encodings are rejected""" - self.description = "Unknown mode test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-0') + self.description = "Unknown mode test" + self.assertRaises(ValueError, DSS.new, self.key_priv, "fips-186-0") - self.description = "Unknown encoding test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-3', 'xml') + self.description = "Unknown encoding test" + self.assertRaises(ValueError, DSS.new, self.key_priv, "fips-186-3", "xml") - def test_asn1_encoding(self): - """Verify ASN.1 encoding""" + def test_asn1_encoding(self): + """Verify ASN.1 encoding""" - self.description = "ASN.1 encoding test" - hash_obj = SHA256.new() - signer = DSS.new(self.key_priv, 'fips-186-3', 'der') - signature = signer.sign(hash_obj) + self.description = "ASN.1 encoding test" + hash_obj = SHA256.new() + signer = DSS.new(self.key_priv, "fips-186-3", "der") + signature = signer.sign(hash_obj) - # Verify that output looks like a DER SEQUENCE - self.assertEqual(bord(signature[0]), 48) - signer.verify(hash_obj, signature) + # Verify that output looks like a DER SEQUENCE + self.assertEqual(bord(signature[0]), 48) + signer.verify(hash_obj, signature) - # Verify that ASN.1 parsing fails as expected - signature = bchr(7) + signature[1:] - self.assertRaises(ValueError, signer.verify, hash_obj, signature) + # Verify that ASN.1 parsing fails as expected + signature = bchr(7) + signature[1:] + self.assertRaises(ValueError, signer.verify, hash_obj, signature) class FIPS_ECDSA_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_verify = load_test_vectors(("Signature", "ECDSA"), - "SigVer.rsp", - "ECDSA Signature Verification 186-3", - {'result': lambda x: x, - 'qx': lambda x: int(x, 16), - 'qy': lambda x: int(x, 16), - }) or [] -test_vectors_verify += load_test_vectors(("Signature", "ECDSA"), - "SigVer_TruncatedSHAs.rsp", - "ECDSA Signature Verification 186-3", - {'result': lambda x: x, - 'qx': lambda x: int(x, 16), - 'qy': lambda x: int(x, 16), - }) or [] + pass + + +test_vectors_verify = ( + load_test_vectors( + ("Signature", "ECDSA"), + "SigVer.rsp", + "ECDSA Signature Verification 186-3", + { + "result": lambda x: x, + "qx": lambda x: int(x, 16), + "qy": lambda x: int(x, 16), + }, + ) + or [] +) +test_vectors_verify += ( + load_test_vectors( + ("Signature", "ECDSA"), + "SigVer_TruncatedSHAs.rsp", + "ECDSA Signature Verification 186-3", + { + "result": lambda x: x, + "qx": lambda x: int(x, 16), + "qy": lambda x: int(x, 16), + }, + ) + or [] +) for idx, tv in enumerate(test_vectors_verify): - - if isinstance(tv, str): - res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) - assert res - curve_name = res.group(1) - hash_name = res.group(2).replace("-", "") - if hash_name in ("SHA512224", "SHA512256"): - truncate = hash_name[-3:] - hash_name = hash_name[:-3] - else: - truncate = None - hash_module = load_hash_by_name(hash_name) - continue - - if truncate is None: - hash_obj = hash_module.new(tv.msg) - else: - hash_obj = hash_module.new(tv.msg, truncate=truncate) - ecc_key = ECC.construct(curve=curve_name, point_x=tv.qx, point_y=tv.qy) - verifier = DSS.new(ecc_key, 'fips-186-3') - - def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result.startswith('p'): - setattr(FIPS_ECDSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) - else: - setattr(FIPS_ECDSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) - - -test_vectors_sign = load_test_vectors(("Signature", "ECDSA"), - "SigGen.txt", - "ECDSA Signature Verification 186-3", - {'d': lambda x: int(x, 16)}) or [] + if isinstance(tv, str): + res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) + assert res + curve_name = res.group(1) + hash_name = res.group(2).replace("-", "") + if hash_name in ("SHA512224", "SHA512256"): + truncate = hash_name[-3:] + hash_name = hash_name[:-3] + else: + truncate = None + hash_module = load_hash_by_name(hash_name) + continue + + if truncate is None: + hash_obj = hash_module.new(tv.msg) + else: + hash_obj = hash_module.new(tv.msg, truncate=truncate) + ecc_key = ECC.construct(curve=curve_name, point_x=tv.qx, point_y=tv.qy) + verifier = DSS.new(ecc_key, "fips-186-3") + + def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r + tv.s): + verifier.verify(hash_obj, signature) + + def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r + tv.s): + self.assertRaises(ValueError, verifier.verify, hash_obj, signature) + + if tv.result.startswith("p"): + setattr(FIPS_ECDSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) + else: + setattr(FIPS_ECDSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) + + +test_vectors_sign = ( + load_test_vectors( + ("Signature", "ECDSA"), + "SigGen.txt", + "ECDSA Signature Verification 186-3", + {"d": lambda x: int(x, 16)}, + ) + or [] +) for idx, tv in enumerate(test_vectors_sign): + if isinstance(tv, str): + res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) + assert res + curve_name = res.group(1) + hash_name = res.group(2).replace("-", "") + hash_module = load_hash_by_name(hash_name) + continue - if isinstance(tv, str): - res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) - assert res - curve_name = res.group(1) - hash_name = res.group(2).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue + hash_obj = hash_module.new(tv.msg) + ecc_key = ECC.construct(curve=curve_name, d=tv.d) + signer = DSS.new(ecc_key, "fips-186-3", randfunc=StrRNG(tv.k)) - hash_obj = hash_module.new(tv.msg) - ecc_key = ECC.construct(curve=curve_name, d=tv.d) - signer = DSS.new(ecc_key, 'fips-186-3', randfunc=StrRNG(tv.k)) + def sign_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r + tv.s): + self.assertEqual(signer.sign(hash_obj), signature) - def sign_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertEqual(signer.sign(hash_obj), signature) - setattr(FIPS_ECDSA_Tests_KAT, "test_sign_%d" % idx, sign_test) + setattr(FIPS_ECDSA_Tests_KAT, "test_sign_%d" % idx, sign_test) class Det_DSA_Tests(unittest.TestCase): - """Tests from rfc6979""" + """Tests from rfc6979""" - # Each key is (p, q, g, x, y, desc) - keys = [ - ( - """ + # Each key is (p, q, g, x, y, desc) + keys = [ + ( + """ 86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447 E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88 73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C 881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779""", - "996F967F6C8E388D9E28D01E205FBA957A5698B1", - """ + "996F967F6C8E388D9E28D01E205FBA957A5698B1", + """ 07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D 89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD 87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4 17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD""", - "411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", - """ + "411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", + """ 5DF5E01DED31D0297E274E1691C192FE5868FEF9E19A84776454B100CF16F653 92195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D 4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E6 82F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B""", - "DSA1024" - ), - ( - """ + "DSA1024", + ), + ( + """ 9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48 C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5 @@ -413,8 +444,8 @@ class Det_DSA_Tests(unittest.TestCase): F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE 92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15 3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B""", - "F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", - """ + "F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", + """ 5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613 D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4 6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472 @@ -423,8 +454,8 @@ class Det_DSA_Tests(unittest.TestCase): 3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71 BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0 DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7""", - "69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC", - """ + "69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC", + """ 667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD94 9F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA61 1728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADE @@ -433,937 +464,961 @@ class Det_DSA_Tests(unittest.TestCase): 687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D1 23AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA 74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF""", - "DSA2048" - ), - ] - - # This is a sequence of items: - # message, k, r, s, hash module - signatures = [ - ( - "sample", - "7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B", - "2E1A0C2562B2912CAAF89186FB0F42001585DA55", - "29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5", - SHA1, - 'DSA1024' - ), - ( - "sample", - "562097C06782D60C3037BA7BE104774344687649", - "4BC3B686AEA70145856814A6F1BB53346F02101E", - "410697B92295D994D21EDD2F4ADA85566F6F94C1", - SHA224, - 'DSA1024' - ), - ( - "sample", - "519BA0546D0C39202A7D34D7DFA5E760B318BCFB", - "81F2F5850BE5BC123C43F71A3033E9384611C545", - "4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89", - SHA256, - 'DSA1024' - ), - ( - "sample", - "95897CD7BBB944AA932DBC579C1C09EB6FCFC595", - "07F2108557EE0E3921BC1774F1CA9B410B4CE65A", - "54DF70456C86FAC10FAB47C1949AB83F2C6F7595", - SHA384, - 'DSA1024' - ), - ( - "sample", - "09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B", - "16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", - "02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C", - SHA512, - 'DSA1024' - ), - ( - "test", - "5C842DF4F9E344EE09F056838B42C7A17F4A6433", - "42AB2052FD43E123F0607F115052A67DCD9C5C77", - "183916B0230D45B9931491D4C6B0BD2FB4AAF088", - SHA1, - 'DSA1024' - ), - ( - "test", - "4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297", - "6868E9964E36C1689F6037F91F28D5F2C30610F2", - "49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F", - SHA224, - 'DSA1024' - ), - ( - "test", - "5A67592E8128E03A417B0484410FB72C0B630E1A", - "22518C127299B0F6FDC9872B282B9E70D0790812", - "6837EC18F150D55DE95B5E29BE7AF5D01E4FE160", - SHA256, - 'DSA1024' - ), - ( - "test", - "220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89", - "854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", - "91D0E0F53E22F898D158380676A871A157CDA622", - SHA384, - 'DSA1024' - ), - ( - "test", - "65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C", - "8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", - "7C670C7AD72B6C050C109E1790008097125433E8", - SHA512, - 'DSA1024' - ), - ( - "sample", - "888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E", - "3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", - "D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF", - SHA1, - 'DSA2048' - ), - ( - "sample", - "BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806", - "DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", - "A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC", - SHA224, - 'DSA2048' - ), - ( - "sample", - "8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52", - "EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", - "7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53", - SHA256, - 'DSA2048' - ), - ( - "sample", - "C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920", - "B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", - "19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B", - SHA384, - 'DSA2048' - ), - ( - "sample", - "5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC", - "2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", - "D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351", - SHA512, - 'DSA2048' - ), - ( - "test", - "6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F", - "C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", - "414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA", - SHA1, - 'DSA2048' - ), - ( - "test", - "06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670", - "272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", - "E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806", - SHA224, - 'DSA2048' - ), - ( - "test", - "1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7", - "8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", - "7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E", - SHA256, - 'DSA2048' - ), - ( - "test", - "206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C", - "239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", - "6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961", - SHA384, - 'DSA2048' - ), - ( - "test", - "AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA", - "89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", - "C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1", - SHA512, - 'DSA2048' - ) - ] - - def setUp(self): - # Convert DSA key components from hex strings to integers - # Each key is (p, q, g, x, y, desc) - - from collections import namedtuple - - TestKey = namedtuple('TestKey', 'p q g x y') - new_keys = {} - for k in self.keys: - tk = TestKey(*[t2l(y) for y in k[:-1]]) - new_keys[k[-1]] = tk - self.keys = new_keys - - # Convert signature encoding - TestSig = namedtuple('TestSig', 'message nonce result module test_key') - new_signatures = [] - for message, nonce, r, s, module, test_key in self.signatures: - tsig = TestSig( - tobytes(message), - t2l(nonce), - t2b(r) + t2b(s), - module, - self.keys[test_key] - ) - new_signatures.append(tsig) - self.signatures = new_signatures - - def test1(self): - q = 0x4000000000000000000020108A2E0CC0D99F8A5EF - x = 0x09A4D6792295A7F730FC3F2B49CBC0F62E862272F - p = 2 * q + 1 - y = pow(2, x, p) - key = DSA.construct([pow(y, 2, p), 2, p, q, x], False) - signer = DSS.new(key, 'deterministic-rfc6979') - - # Test _int2octets - self.assertEqual(hexlify(signer._int2octets(x)), - b'009a4d6792295a7f730fc3f2b49cbc0f62e862272f') - - # Test _bits2octets - h1 = SHA256.new(b"sample").digest() - self.assertEqual(hexlify(signer._bits2octets(h1)), - b'01795edf0d54db760f156d0dac04c0322b3a204224') - - def test2(self): - - for sig in self.signatures: - tk = sig.test_key - key = DSA.construct([tk.y, tk.g, tk.p, tk.q, tk.x], False) - signer = DSS.new(key, 'deterministic-rfc6979') - - hash_obj = sig.module.new(sig.message) - result = signer.sign(hash_obj) - self.assertEqual(sig.result, result) + "DSA2048", + ), + ] + + # This is a sequence of items: + # message, k, r, s, hash module + signatures = [ + ( + "sample", + "7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B", + "2E1A0C2562B2912CAAF89186FB0F42001585DA55", + "29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5", + SHA1, + "DSA1024", + ), + ( + "sample", + "562097C06782D60C3037BA7BE104774344687649", + "4BC3B686AEA70145856814A6F1BB53346F02101E", + "410697B92295D994D21EDD2F4ADA85566F6F94C1", + SHA224, + "DSA1024", + ), + ( + "sample", + "519BA0546D0C39202A7D34D7DFA5E760B318BCFB", + "81F2F5850BE5BC123C43F71A3033E9384611C545", + "4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89", + SHA256, + "DSA1024", + ), + ( + "sample", + "95897CD7BBB944AA932DBC579C1C09EB6FCFC595", + "07F2108557EE0E3921BC1774F1CA9B410B4CE65A", + "54DF70456C86FAC10FAB47C1949AB83F2C6F7595", + SHA384, + "DSA1024", + ), + ( + "sample", + "09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B", + "16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", + "02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C", + SHA512, + "DSA1024", + ), + ( + "test", + "5C842DF4F9E344EE09F056838B42C7A17F4A6433", + "42AB2052FD43E123F0607F115052A67DCD9C5C77", + "183916B0230D45B9931491D4C6B0BD2FB4AAF088", + SHA1, + "DSA1024", + ), + ( + "test", + "4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297", + "6868E9964E36C1689F6037F91F28D5F2C30610F2", + "49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F", + SHA224, + "DSA1024", + ), + ( + "test", + "5A67592E8128E03A417B0484410FB72C0B630E1A", + "22518C127299B0F6FDC9872B282B9E70D0790812", + "6837EC18F150D55DE95B5E29BE7AF5D01E4FE160", + SHA256, + "DSA1024", + ), + ( + "test", + "220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89", + "854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", + "91D0E0F53E22F898D158380676A871A157CDA622", + SHA384, + "DSA1024", + ), + ( + "test", + "65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C", + "8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", + "7C670C7AD72B6C050C109E1790008097125433E8", + SHA512, + "DSA1024", + ), + ( + "sample", + "888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E", + "3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", + "D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF", + SHA1, + "DSA2048", + ), + ( + "sample", + "BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806", + "DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", + "A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC", + SHA224, + "DSA2048", + ), + ( + "sample", + "8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52", + "EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", + "7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53", + SHA256, + "DSA2048", + ), + ( + "sample", + "C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920", + "B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", + "19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B", + SHA384, + "DSA2048", + ), + ( + "sample", + "5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC", + "2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", + "D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351", + SHA512, + "DSA2048", + ), + ( + "test", + "6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F", + "C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", + "414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA", + SHA1, + "DSA2048", + ), + ( + "test", + "06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670", + "272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", + "E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806", + SHA224, + "DSA2048", + ), + ( + "test", + "1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7", + "8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", + "7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E", + SHA256, + "DSA2048", + ), + ( + "test", + "206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C", + "239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", + "6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961", + SHA384, + "DSA2048", + ), + ( + "test", + "AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA", + "89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", + "C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1", + SHA512, + "DSA2048", + ), + ] + + def setUp(self): + # Convert DSA key components from hex strings to integers + # Each key is (p, q, g, x, y, desc) + + from collections import namedtuple + + TestKey = namedtuple("TestKey", "p q g x y") + new_keys = {} + for k in self.keys: + tk = TestKey(*[t2l(y) for y in k[:-1]]) + new_keys[k[-1]] = tk + self.keys = new_keys + + # Convert signature encoding + TestSig = namedtuple("TestSig", "message nonce result module test_key") + new_signatures = [] + for message, nonce, r, s, module, test_key in self.signatures: + tsig = TestSig( + tobytes(message), + t2l(nonce), + t2b(r) + t2b(s), + module, + self.keys[test_key], + ) + new_signatures.append(tsig) + self.signatures = new_signatures + + def test1(self): + q = 0x4000000000000000000020108A2E0CC0D99F8A5EF + x = 0x09A4D6792295A7F730FC3F2B49CBC0F62E862272F + p = 2 * q + 1 + y = pow(2, x, p) + key = DSA.construct([pow(y, 2, p), 2, p, q, x], False) + signer = DSS.new(key, "deterministic-rfc6979") + + # Test _int2octets + self.assertEqual( + hexlify(signer._int2octets(x)), + b"009a4d6792295a7f730fc3f2b49cbc0f62e862272f", + ) + + # Test _bits2octets + h1 = SHA256.new(b"sample").digest() + self.assertEqual( + hexlify(signer._bits2octets(h1)), + b"01795edf0d54db760f156d0dac04c0322b3a204224", + ) + + def test2(self): + for sig in self.signatures: + tk = sig.test_key + key = DSA.construct([tk.y, tk.g, tk.p, tk.q, tk.x], False) + signer = DSS.new(key, "deterministic-rfc6979") + + hash_obj = sig.module.new(sig.message) + result = signer.sign(hash_obj) + self.assertEqual(sig.result, result) class Det_ECDSA_Tests(unittest.TestCase): - - key_priv_p192 = ECC.construct(curve="P-192", d=0x6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4) - key_pub_p192 = key_priv_p192.public_key() - - key_priv_p224 = ECC.construct(curve="P-224", d=0xF220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1) - key_pub_p224 = key_priv_p224.public_key() - - key_priv_p256 = ECC.construct(curve="P-256", d=0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721) - key_pub_p256 = key_priv_p256.public_key() - - key_priv_p384 = ECC.construct(curve="P-384", d=0x6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5) - key_pub_p384 = key_priv_p384.public_key() - - key_priv_p521 = ECC.construct(curve="P-521", d=0x0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538) - key_pub_p521 = key_priv_p521.public_key() - - # This is a sequence of items: - # message, k, r, s, hash module - # taken from RFC6979 - signatures_p192_ = ( - ( - "sample", - "37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", - "98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", - "57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64", - SHA1 - ), - ( - "sample", - "4381526B3FC1E7128F202E194505592F01D5FF4C5AF015D8", - "A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", - "E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A", - SHA224 - ), - ( - "sample", - "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", - "4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", - "CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85", - SHA256 - ), - ( - "sample", - "4730005C4FCB01834C063A7B6760096DBE284B8252EF4311", - "DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", - "C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E", - SHA384 - ), - ( - "sample", - "A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", - "4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", - "3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67", - SHA512 - ), - ( - "test", - "D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", - "0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", - "EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7", - SHA1 - ), - ( - "test", - "F5DC805F76EF851800700CCE82E7B98D8911B7D510059FBE", - "6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", - "B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293", - SHA224 - ), - ( - "test", - "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", - "3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", - "5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F", - SHA256 - ), - ( - "test", - "5AFEFB5D3393261B828DB6C91FBC68C230727B030C975693", - "B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", - "7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A", - SHA384 - ), - ( - "test", - "0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", - "FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", - "74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290", - SHA512 - ) - ) - - signatures_p224_ = ( - ( - "sample", - "7EEFADD91110D8DE6C2C470831387C50D3357F7F4D477054B8B426BC", - "22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC", - "66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69", - SHA1 - ), - ( - "sample", - "C1D1F2F10881088301880506805FEB4825FE09ACB6816C36991AA06D", - "1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E", - "A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC", - SHA224 - ), - ( - "sample", - "AD3029E0278F80643DE33917CE6908C70A8FF50A411F06E41DEDFCDC", - "61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", - "BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101", - SHA256 - ), - ( - "sample", - "52B40F5A9D3D13040F494E83D3906C6079F29981035C7BD51E5CAC40", - "0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953", - "830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D", - SHA384 - ), - ( - "sample", - "9DB103FFEDEDF9CFDBA05184F925400C1653B8501BAB89CEA0FBEC14", - "074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397", - "A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084", - SHA512 - ), - ( - "test", - "2519178F82C3F0E4F87ED5883A4E114E5B7A6E374043D8EFD329C253", - "DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C", - "95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2", - SHA1 - ), - ( - "test", - "DF8B38D40DCA3E077D0AC520BF56B6D565134D9B5F2EAE0D34900524", - "C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019", - "902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4", - SHA224 - ), - ( - "test", - "FF86F57924DA248D6E44E8154EB69F0AE2AEBAEE9931D0B5A969F904", - "AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", - "178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD", - SHA256 - ), - ( - "test", - "7046742B839478C1B5BD31DB2E862AD868E1A45C863585B5F22BDC2D", - "389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4", - "414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB", - SHA384 - ), - ( - "test", - "E39C2AA4EA6BE2306C72126D40ED77BF9739BB4D6EF2BBB1DCB6169D", - "049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C", - "077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF", - SHA512 - ) - ) - - signatures_p256_ = ( - ( - "sample", - "882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4", - "61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", - "6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB", - SHA1 - ), - ( - "sample", - "103F90EE9DC52E5E7FB5132B7033C63066D194321491862059967C715985D473", - "53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", - "B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C", - SHA224 - ), - ( - "sample", - "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60", - "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", - "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8", - SHA256 - ), - ( - "sample", - "09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4", - "0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", - "4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954", - SHA384 - ), - ( - "sample", - "5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5", - "8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", - "2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE", - SHA512 - ), - ( - "test", - "8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E", - "0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", - "01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1", - SHA1 - ), - ( - "test", - "669F4426F2688B8BE0DB3A6BD1989BDAEFFF84B649EEB84F3DD26080F667FAA7", - "C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", - "C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D", - SHA224 - ), - ( - "test", - "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0", - "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", - "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083", - SHA256 - ), - ( - "test", - "16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8", - "83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", - "8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C", - SHA384 - ), - ( - "test", - "6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F", - "461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", - "39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55", - SHA512 - ) - ) - - signatures_p384_ = ( - ( - "sample", - "4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB096630F29E5938D25106C3C340045A2DB01A7", - "EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2", - "A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443", - SHA1 - ), - ( - "sample", - "A4E4D2F0E729EB786B31FC20AD5D849E304450E0AE8E3E341134A5C1AFA03CAB8083EE4E3C45B06A5899EA56C51B5879", - "42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE060122", - "9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D", - SHA224 - ), - ( - "sample", - "180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E375572342863C899F9F2EDF9747A9B60", - "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD", - "F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0", - SHA256 - ), - ( - "sample", - "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9", - "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46", - "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8", - SHA384 - ), - ( - "sample", - "92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331A4E966532593A52980D0E3AAA5E10EC3", - "ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD7882433709", - "512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5", - SHA512 - ), - ( - "test", - "66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47EC3727F3A3C186C15054492E30698497", - "4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7", - "D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282", - SHA1 - ), - ( - "test", - "18FA39DB95AA5F561F30FA3591DC59C0FA3653A80DAFFA0B48D1A4C6DFCBFF6E3D33BE4DC5EB8886A8ECD093F2935726", - "E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E72", - "07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66", - SHA224 - ), - ( - "test", - "0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FAA48DD070BA79921A3457ABFF2D630AD7", - "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B", - "2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265", - SHA256 - ), - ( - "test", - "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA", - "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB", - "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5", - SHA384 - ), - ( - "test", - "3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE0E2CC8A136036DC4B9C00E6888F66B6C", - "A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277", - "976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736", - SHA512 - ), - ) - - signatures_p521_ = ( - ( - "sample", - "0089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9", - "00343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D", - "00E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16", - SHA1 - ), - ( - "sample", - "0121415EC2CD7726330A61F7F3FA5DE14BE9436019C4DB8CB4041F3B54CF31BE0493EE3F427FB906393D895A19C9523F3A1D54BB8702BD4AA9C99DAB2597B92113F3", - "01776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E", - "0050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F", - SHA224 - ), - ( - "sample", - "00EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0", - "01511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7", - "004A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC", - SHA256 - ), - ( - "sample", - "01546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FFAD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4211", - "01EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67451", - "01F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61", - SHA384 - ), - ( - "sample", - "01DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3", - "00C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA", - "00617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A", - SHA512 - ), - ( - "test", - "00BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DDBA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B222", - "013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0367", - "01E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF", - SHA1 - ), - ( - "test", - "0040D09FCF3C8A5F62CF4FB223CBBB2B9937F6B0577C27020A99602C25A01136987E452988781484EDBBCF1C47E554E7FC901BC3085E5206D9F619CFF07E73D6F706", - "01C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB", - "0177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4", - SHA224 - ), - ( - "test", - "001DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E843841AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909258", - "000E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8", - "00CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86", - SHA256 - ), - ( - "test", - "01F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5DCEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0C88", - "014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C", - "0133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979", - SHA384 - ), - ( - "test", - "016200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D", - "013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D", - "01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3", - SHA512 - ), - ) - - signatures_p192 = [] - for a, b, c, d, e in signatures_p192_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p192.append(new_tv) - - signatures_p224 = [] - for a, b, c, d, e in signatures_p224_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p224.append(new_tv) - - signatures_p256 = [] - for a, b, c, d, e in signatures_p256_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p256.append(new_tv) - - signatures_p384 = [] - for a, b, c, d, e in signatures_p384_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p384.append(new_tv) - - signatures_p521 = [] - for a, b, c, d, e in signatures_p521_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p521.append(new_tv) - - def shortDescription(self): - return "Deterministic ECDSA Tests" - - def test_loopback_p192(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p192, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p192, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p224(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p224, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p224, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p256(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p256, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p256, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p384(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p384, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p384, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p521(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p521, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p521, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_data_rfc6979_p192(self): - signer = DSS.new(self.key_priv_p192, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p192: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p224(self): - signer = DSS.new(self.key_priv_p224, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p224: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p256(self): - signer = DSS.new(self.key_priv_p256, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p256: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p384(self): - signer = DSS.new(self.key_priv_p384, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p384: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p521(self): - signer = DSS.new(self.key_priv_p521, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p521: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) + key_priv_p192 = ECC.construct(curve="P-192", d=0x6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4) + key_pub_p192 = key_priv_p192.public_key() + + key_priv_p224 = ECC.construct(curve="P-224", d=0xF220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1) + key_pub_p224 = key_priv_p224.public_key() + + key_priv_p256 = ECC.construct( + curve="P-256", d=0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721 + ) + key_pub_p256 = key_priv_p256.public_key() + + key_priv_p384 = ECC.construct( + curve="P-384", + d=0x6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5, + ) + key_pub_p384 = key_priv_p384.public_key() + + key_priv_p521 = ECC.construct( + curve="P-521", + d=0x0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538, + ) + key_pub_p521 = key_priv_p521.public_key() + + # This is a sequence of items: + # message, k, r, s, hash module + # taken from RFC6979 + signatures_p192_ = ( + ( + "sample", + "37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", + "98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", + "57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64", + SHA1, + ), + ( + "sample", + "4381526B3FC1E7128F202E194505592F01D5FF4C5AF015D8", + "A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", + "E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A", + SHA224, + ), + ( + "sample", + "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", + "4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", + "CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85", + SHA256, + ), + ( + "sample", + "4730005C4FCB01834C063A7B6760096DBE284B8252EF4311", + "DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", + "C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E", + SHA384, + ), + ( + "sample", + "A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", + "4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", + "3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67", + SHA512, + ), + ( + "test", + "D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", + "0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", + "EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7", + SHA1, + ), + ( + "test", + "F5DC805F76EF851800700CCE82E7B98D8911B7D510059FBE", + "6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", + "B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293", + SHA224, + ), + ( + "test", + "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", + "3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", + "5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F", + SHA256, + ), + ( + "test", + "5AFEFB5D3393261B828DB6C91FBC68C230727B030C975693", + "B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", + "7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A", + SHA384, + ), + ( + "test", + "0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", + "FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", + "74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290", + SHA512, + ), + ) + + signatures_p224_ = ( + ( + "sample", + "7EEFADD91110D8DE6C2C470831387C50D3357F7F4D477054B8B426BC", + "22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC", + "66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69", + SHA1, + ), + ( + "sample", + "C1D1F2F10881088301880506805FEB4825FE09ACB6816C36991AA06D", + "1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E", + "A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC", + SHA224, + ), + ( + "sample", + "AD3029E0278F80643DE33917CE6908C70A8FF50A411F06E41DEDFCDC", + "61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", + "BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101", + SHA256, + ), + ( + "sample", + "52B40F5A9D3D13040F494E83D3906C6079F29981035C7BD51E5CAC40", + "0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953", + "830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D", + SHA384, + ), + ( + "sample", + "9DB103FFEDEDF9CFDBA05184F925400C1653B8501BAB89CEA0FBEC14", + "074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397", + "A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084", + SHA512, + ), + ( + "test", + "2519178F82C3F0E4F87ED5883A4E114E5B7A6E374043D8EFD329C253", + "DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C", + "95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2", + SHA1, + ), + ( + "test", + "DF8B38D40DCA3E077D0AC520BF56B6D565134D9B5F2EAE0D34900524", + "C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019", + "902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4", + SHA224, + ), + ( + "test", + "FF86F57924DA248D6E44E8154EB69F0AE2AEBAEE9931D0B5A969F904", + "AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", + "178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD", + SHA256, + ), + ( + "test", + "7046742B839478C1B5BD31DB2E862AD868E1A45C863585B5F22BDC2D", + "389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4", + "414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB", + SHA384, + ), + ( + "test", + "E39C2AA4EA6BE2306C72126D40ED77BF9739BB4D6EF2BBB1DCB6169D", + "049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C", + "077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF", + SHA512, + ), + ) + + signatures_p256_ = ( + ( + "sample", + "882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4", + "61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", + "6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB", + SHA1, + ), + ( + "sample", + "103F90EE9DC52E5E7FB5132B7033C63066D194321491862059967C715985D473", + "53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", + "B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C", + SHA224, + ), + ( + "sample", + "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60", + "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", + "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8", + SHA256, + ), + ( + "sample", + "09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4", + "0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", + "4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954", + SHA384, + ), + ( + "sample", + "5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5", + "8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", + "2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE", + SHA512, + ), + ( + "test", + "8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E", + "0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", + "01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1", + SHA1, + ), + ( + "test", + "669F4426F2688B8BE0DB3A6BD1989BDAEFFF84B649EEB84F3DD26080F667FAA7", + "C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", + "C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D", + SHA224, + ), + ( + "test", + "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0", + "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", + "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083", + SHA256, + ), + ( + "test", + "16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8", + "83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", + "8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C", + SHA384, + ), + ( + "test", + "6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F", + "461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", + "39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55", + SHA512, + ), + ) + + signatures_p384_ = ( + ( + "sample", + "4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB096630F29E5938D25106C3C340045A2DB01A7", + "EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2", + "A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443", + SHA1, + ), + ( + "sample", + "A4E4D2F0E729EB786B31FC20AD5D849E304450E0AE8E3E341134A5C1AFA03CAB8083EE4E3C45B06A5899EA56C51B5879", + "42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE060122", + "9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D", + SHA224, + ), + ( + "sample", + "180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E375572342863C899F9F2EDF9747A9B60", + "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD", + "F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0", + SHA256, + ), + ( + "sample", + "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9", + "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46", + "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8", + SHA384, + ), + ( + "sample", + "92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331A4E966532593A52980D0E3AAA5E10EC3", + "ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD7882433709", + "512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5", + SHA512, + ), + ( + "test", + "66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47EC3727F3A3C186C15054492E30698497", + "4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7", + "D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282", + SHA1, + ), + ( + "test", + "18FA39DB95AA5F561F30FA3591DC59C0FA3653A80DAFFA0B48D1A4C6DFCBFF6E3D33BE4DC5EB8886A8ECD093F2935726", + "E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E72", + "07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66", + SHA224, + ), + ( + "test", + "0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FAA48DD070BA79921A3457ABFF2D630AD7", + "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B", + "2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265", + SHA256, + ), + ( + "test", + "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA", + "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB", + "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5", + SHA384, + ), + ( + "test", + "3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE0E2CC8A136036DC4B9C00E6888F66B6C", + "A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277", + "976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736", + SHA512, + ), + ) + + signatures_p521_ = ( + ( + "sample", + "0089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9", + "00343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D", + "00E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16", + SHA1, + ), + ( + "sample", + "0121415EC2CD7726330A61F7F3FA5DE14BE9436019C4DB8CB4041F3B54CF31BE0493EE3F427FB906393D895A19C9523F3A1D54BB8702BD4AA9C99DAB2597B92113F3", + "01776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E", + "0050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F", + SHA224, + ), + ( + "sample", + "00EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0", + "01511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7", + "004A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC", + SHA256, + ), + ( + "sample", + "01546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FFAD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4211", + "01EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67451", + "01F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61", + SHA384, + ), + ( + "sample", + "01DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3", + "00C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA", + "00617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A", + SHA512, + ), + ( + "test", + "00BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DDBA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B222", + "013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0367", + "01E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF", + SHA1, + ), + ( + "test", + "0040D09FCF3C8A5F62CF4FB223CBBB2B9937F6B0577C27020A99602C25A01136987E452988781484EDBBCF1C47E554E7FC901BC3085E5206D9F619CFF07E73D6F706", + "01C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB", + "0177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4", + SHA224, + ), + ( + "test", + "001DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E843841AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909258", + "000E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8", + "00CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86", + SHA256, + ), + ( + "test", + "01F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5DCEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0C88", + "014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C", + "0133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979", + SHA384, + ), + ( + "test", + "016200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D", + "013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D", + "01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3", + SHA512, + ), + ) + + signatures_p192 = [] + for a, b, c, d, e in signatures_p192_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p192.append(new_tv) + + signatures_p224 = [] + for a, b, c, d, e in signatures_p224_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p224.append(new_tv) + + signatures_p256 = [] + for a, b, c, d, e in signatures_p256_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p256.append(new_tv) + + signatures_p384 = [] + for a, b, c, d, e in signatures_p384_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p384.append(new_tv) + + signatures_p521 = [] + for a, b, c, d, e in signatures_p521_: + new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) + signatures_p521.append(new_tv) + + def shortDescription(self): + return "Deterministic ECDSA Tests" + + def test_loopback_p192(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p192, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p192, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_loopback_p224(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p224, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p224, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_loopback_p256(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p256, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p256, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_loopback_p384(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p384, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p384, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_loopback_p521(self): + hashed_msg = SHA512.new(b"test") + signer = DSS.new(self.key_priv_p521, "deterministic-rfc6979") + signature = signer.sign(hashed_msg) + + verifier = DSS.new(self.key_pub_p521, "deterministic-rfc6979") + verifier.verify(hashed_msg, signature) + + def test_data_rfc6979_p192(self): + signer = DSS.new(self.key_priv_p192, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p192: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) + + def test_data_rfc6979_p224(self): + signer = DSS.new(self.key_priv_p224, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p224: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) + + def test_data_rfc6979_p256(self): + signer = DSS.new(self.key_priv_p256, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p256: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) + + def test_data_rfc6979_p384(self): + signer = DSS.new(self.key_priv_p384, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p384: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) + + def test_data_rfc6979_p521(self): + signer = DSS.new(self.key_priv_p521, "deterministic-rfc6979") + for message, k, r, s, module in self.signatures_p521: + hash_obj = module.new(message) + result = signer.sign(hash_obj) + self.assertEqual(r + s, result) def get_hash_module(hash_name): - if hash_name == "SHA-512": - hash_module = SHA512 - elif hash_name == "SHA-512/224": - hash_module = SHA512.new(truncate="224") - elif hash_name == "SHA-512/256": - hash_module = SHA512.new(truncate="256") - elif hash_name == "SHA-384": - hash_module = SHA384 - elif hash_name == "SHA-256": - hash_module = SHA256 - elif hash_name == "SHA-224": - hash_module = SHA224 - elif hash_name == "SHA-1": - hash_module = SHA1 - elif hash_name == "SHA3-224": - hash_module = SHA3_224 - elif hash_name == "SHA3-256": - hash_module = SHA3_256 - elif hash_name == "SHA3-384": - hash_module = SHA3_384 - elif hash_name == "SHA3-512": - hash_module = SHA3_512 - else: - raise ValueError("Unknown hash algorithm: " + hash_name) - return hash_module + if hash_name == "SHA-512": + hash_module = SHA512 + elif hash_name == "SHA-512/224": + hash_module = SHA512.new(truncate="224") + elif hash_name == "SHA-512/256": + hash_module = SHA512.new(truncate="256") + elif hash_name == "SHA-384": + hash_module = SHA384 + elif hash_name == "SHA-256": + hash_module = SHA256 + elif hash_name == "SHA-224": + hash_module = SHA224 + elif hash_name == "SHA-1": + hash_module = SHA1 + elif hash_name == "SHA3-224": + hash_module = SHA3_224 + elif hash_name == "SHA3-256": + hash_module = SHA3_256 + elif hash_name == "SHA3-384": + hash_module = SHA3_384 + elif hash_name == "SHA3-512": + hash_module = SHA3_512 + else: + raise ValueError("Unknown hash algorithm: " + hash_name) + return hash_module class TestVectorsDSAWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._slow_tests = slow_tests - self._id = "None" - self.tv = [] - - def setUp(self): - - def filter_dsa(group): - return DSA.import_key(group['keyPem']) - - def filter_sha(group): - return get_hash_module(group['sha']) - - def filter_type(group): - sig_type = group['type'] - if sig_type != 'DsaVerify': - raise ValueError("Unknown signature type " + sig_type) - return sig_type - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - "dsa_test.json", - "Wycheproof DSA signature", - group_tag={'key': filter_dsa, - 'hash_module': filter_sha, - 'sig_type': filter_type}) - self.tv += result - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof DSA Test #" + str(tv.id) - - hashed_msg = tv.hash_module.new(tv.msg) - signer = DSS.new(tv.key, 'fips-186-3', encoding='der') - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings, slow_tests): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._slow_tests = slow_tests + self._id = "None" + self.tv = [] + + def setUp(self): + def filter_dsa(group): + return DSA.import_key(group["keyPem"]) + + def filter_sha(group): + return get_hash_module(group["sha"]) + + def filter_type(group): + sig_type = group["type"] + if sig_type != "DsaVerify": + raise ValueError("Unknown signature type " + sig_type) + return sig_type + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + "dsa_test.json", + "Wycheproof DSA signature", + group_tag={ + "key": filter_dsa, + "hash_module": filter_sha, + "sig_type": filter_type, + }, + ) + self.tv += result + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof DSA Test #" + str(tv.id) + + hashed_msg = tv.hash_module.new(tv.msg) + signer = DSS.new(tv.key, "fips-186-3", encoding="der") + try: + signature = signer.verify(hashed_msg, tv.sig) + except ValueError: + if tv.warning: + return + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) class TestVectorsECDSAWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._slow_tests = slow_tests - self._id = "None" - - def add_tests(self, filename): - - def filter_ecc(group): - # These are the only curves we accept to skip - if group['key']['curve'] in ('secp224k1', 'secp256k1', - 'brainpoolP224r1', 'brainpoolP224t1', - 'brainpoolP256r1', 'brainpoolP256t1', - 'brainpoolP320r1', 'brainpoolP320t1', - 'brainpoolP384r1', 'brainpoolP384t1', - 'brainpoolP512r1', 'brainpoolP512t1', - ): - return None - return ECC.import_key(group['keyPem']) - - def filter_sha(group): - return get_hash_module(group['sha']) - - def filter_encoding(group): - encoding_name = group['type'] - if encoding_name == "EcdsaVerify": - return "der" - elif encoding_name == "EcdsaP1363Verify": - return "binary" - else: - raise ValueError("Unknown signature type " + encoding_name) - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof ECDSA signature (%s)" % filename, - group_tag={'key': filter_ecc, - 'hash_module': filter_sha, - 'encoding': filter_encoding, - }) - self.tv += result - - def setUp(self): - self.tv = [] - self.add_tests("ecdsa_secp224r1_sha224_p1363_test.json") - self.add_tests("ecdsa_secp224r1_sha224_test.json") - if self._slow_tests: - self.add_tests("ecdsa_secp224r1_sha256_p1363_test.json") - self.add_tests("ecdsa_secp224r1_sha256_test.json") - self.add_tests("ecdsa_secp224r1_sha3_224_test.json") - self.add_tests("ecdsa_secp224r1_sha3_256_test.json") - self.add_tests("ecdsa_secp224r1_sha3_512_test.json") - self.add_tests("ecdsa_secp224r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp224r1_sha512_test.json") - self.add_tests("ecdsa_secp256r1_sha256_p1363_test.json") - self.add_tests("ecdsa_secp256r1_sha256_test.json") - self.add_tests("ecdsa_secp256r1_sha3_256_test.json") - self.add_tests("ecdsa_secp256r1_sha3_512_test.json") - self.add_tests("ecdsa_secp256r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp256r1_sha512_test.json") - if self._slow_tests: - self.add_tests("ecdsa_secp384r1_sha3_384_test.json") - self.add_tests("ecdsa_secp384r1_sha3_512_test.json") - self.add_tests("ecdsa_secp384r1_sha384_p1363_test.json") - self.add_tests("ecdsa_secp384r1_sha384_test.json") - self.add_tests("ecdsa_secp384r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp384r1_sha512_test.json") - if self._slow_tests: - self.add_tests("ecdsa_secp521r1_sha3_512_test.json") - self.add_tests("ecdsa_secp521r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp521r1_sha512_test.json") - self.add_tests("ecdsa_test.json") - self.add_tests("ecdsa_webcrypto_test.json") - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof ECDSA Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - - # Skip tests with unsupported curves - if tv.key is None: - return - - hashed_msg = tv.hash_module.new(tv.msg) - signer = DSS.new(tv.key, 'fips-186-3', encoding=tv.encoding) - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - if tv.comment == "k*G has a large x-coordinate": - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings, slow_tests): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._slow_tests = slow_tests + self._id = "None" + + def add_tests(self, filename): + def filter_ecc(group): + # These are the only curves we accept to skip + if group["key"]["curve"] in ( + "secp224k1", + "secp256k1", + "brainpoolP224r1", + "brainpoolP224t1", + "brainpoolP256r1", + "brainpoolP256t1", + "brainpoolP320r1", + "brainpoolP320t1", + "brainpoolP384r1", + "brainpoolP384t1", + "brainpoolP512r1", + "brainpoolP512t1", + ): + return None + return ECC.import_key(group["keyPem"]) + + def filter_sha(group): + return get_hash_module(group["sha"]) + + def filter_encoding(group): + encoding_name = group["type"] + if encoding_name == "EcdsaVerify": + return "der" + elif encoding_name == "EcdsaP1363Verify": + return "binary" + else: + raise ValueError("Unknown signature type " + encoding_name) + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + filename, + "Wycheproof ECDSA signature (%s)" % filename, + group_tag={ + "key": filter_ecc, + "hash_module": filter_sha, + "encoding": filter_encoding, + }, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.add_tests("ecdsa_secp224r1_sha224_p1363_test.json") + self.add_tests("ecdsa_secp224r1_sha224_test.json") + if self._slow_tests: + self.add_tests("ecdsa_secp224r1_sha256_p1363_test.json") + self.add_tests("ecdsa_secp224r1_sha256_test.json") + self.add_tests("ecdsa_secp224r1_sha3_224_test.json") + self.add_tests("ecdsa_secp224r1_sha3_256_test.json") + self.add_tests("ecdsa_secp224r1_sha3_512_test.json") + self.add_tests("ecdsa_secp224r1_sha512_p1363_test.json") + self.add_tests("ecdsa_secp224r1_sha512_test.json") + self.add_tests("ecdsa_secp256r1_sha256_p1363_test.json") + self.add_tests("ecdsa_secp256r1_sha256_test.json") + self.add_tests("ecdsa_secp256r1_sha3_256_test.json") + self.add_tests("ecdsa_secp256r1_sha3_512_test.json") + self.add_tests("ecdsa_secp256r1_sha512_p1363_test.json") + self.add_tests("ecdsa_secp256r1_sha512_test.json") + if self._slow_tests: + self.add_tests("ecdsa_secp384r1_sha3_384_test.json") + self.add_tests("ecdsa_secp384r1_sha3_512_test.json") + self.add_tests("ecdsa_secp384r1_sha384_p1363_test.json") + self.add_tests("ecdsa_secp384r1_sha384_test.json") + self.add_tests("ecdsa_secp384r1_sha512_p1363_test.json") + self.add_tests("ecdsa_secp384r1_sha512_test.json") + if self._slow_tests: + self.add_tests("ecdsa_secp521r1_sha3_512_test.json") + self.add_tests("ecdsa_secp521r1_sha512_p1363_test.json") + self.add_tests("ecdsa_secp521r1_sha512_test.json") + self.add_tests("ecdsa_test.json") + self.add_tests("ecdsa_webcrypto_test.json") + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof ECDSA Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + + # Skip tests with unsupported curves + if tv.key is None: + return + + hashed_msg = tv.hash_module.new(tv.msg) + signer = DSS.new(tv.key, "fips-186-3", encoding=tv.encoding) + try: + signature = signer.verify(hashed_msg, tv.sig) + except ValueError: + if tv.warning: + return + if tv.comment == "k*G has a large x-coordinate": + return + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(FIPS_DSA_Tests) + tests += list_test_cases(FIPS_ECDSA_Tests) + tests += list_test_cases(Det_DSA_Tests) + tests += list_test_cases(Det_ECDSA_Tests) + + slow_tests = config.get("slow_tests") + if slow_tests: + tests += list_test_cases(FIPS_DSA_Tests_KAT) + tests += list_test_cases(FIPS_ECDSA_Tests_KAT) - tests = [] - tests += list_test_cases(FIPS_DSA_Tests) - tests += list_test_cases(FIPS_ECDSA_Tests) - tests += list_test_cases(Det_DSA_Tests) - tests += list_test_cases(Det_ECDSA_Tests) + tests += [TestVectorsDSAWycheproof(wycheproof_warnings, slow_tests)] + tests += [TestVectorsECDSAWycheproof(wycheproof_warnings, slow_tests)] - slow_tests = config.get('slow_tests') - if slow_tests: - tests += list_test_cases(FIPS_DSA_Tests_KAT) - tests += list_test_cases(FIPS_ECDSA_Tests_KAT) + return tests - tests += [TestVectorsDSAWycheproof(wycheproof_warnings, slow_tests)] - tests += [TestVectorsECDSAWycheproof(wycheproof_warnings, slow_tests)] - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_eddsa.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_eddsa.py index 3215bbca..87859247 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_eddsa.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_eddsa.py @@ -38,567 +38,554 @@ from Cryptodome.Util.number import bytes_to_long rfc8032_tv_str = ( - # 7.1 Ed25519 - ( - "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", - "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", - "", - None, - "", - "e5564300c360ac729086e2cc806e828a" - "84877f1eb8e5d974d873e06522490155" - "5fb8821590a33bacc61e39701cf9b46b" - "d25bf5f0595bbe24655141438e7a100b" - ), - ( - "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", - "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", - "72", - None, - "", - "92a009a9f0d4cab8720e820b5f642540" - "a2b27b5416503f8fb3762223ebdb69da" - "085ac1e43e15996e458f3613d0f11d8c" - "387b2eaeb4302aeeb00d291612bb0c00" - ), - ( - "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", - "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", - "af82", - None, - "", - "6291d657deec24024827e69c3abe01a3" - "0ce548a284743a445e3680d7db5ac3ac" - "18ff9b538d16f290ae67f760984dc659" - "4a7c15e9716ed28dc027beceea1ec40a" - ), - ( - "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5", - "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", - "08b8b2b733424243760fe426a4b54908" - "632110a66c2f6591eabd3345e3e4eb98" - "fa6e264bf09efe12ee50f8f54e9f77b1" - "e355f6c50544e23fb1433ddf73be84d8" - "79de7c0046dc4996d9e773f4bc9efe57" - "38829adb26c81b37c93a1b270b20329d" - "658675fc6ea534e0810a4432826bf58c" - "941efb65d57a338bbd2e26640f89ffbc" - "1a858efcb8550ee3a5e1998bd177e93a" - "7363c344fe6b199ee5d02e82d522c4fe" - "ba15452f80288a821a579116ec6dad2b" - "3b310da903401aa62100ab5d1a36553e" - "06203b33890cc9b832f79ef80560ccb9" - "a39ce767967ed628c6ad573cb116dbef" - "efd75499da96bd68a8a97b928a8bbc10" - "3b6621fcde2beca1231d206be6cd9ec7" - "aff6f6c94fcd7204ed3455c68c83f4a4" - "1da4af2b74ef5c53f1d8ac70bdcb7ed1" - "85ce81bd84359d44254d95629e9855a9" - "4a7c1958d1f8ada5d0532ed8a5aa3fb2" - "d17ba70eb6248e594e1a2297acbbb39d" - "502f1a8c6eb6f1ce22b3de1a1f40cc24" - "554119a831a9aad6079cad88425de6bd" - "e1a9187ebb6092cf67bf2b13fd65f270" - "88d78b7e883c8759d2c4f5c65adb7553" - "878ad575f9fad878e80a0c9ba63bcbcc" - "2732e69485bbc9c90bfbd62481d9089b" - "eccf80cfe2df16a2cf65bd92dd597b07" - "07e0917af48bbb75fed413d238f5555a" - "7a569d80c3414a8d0859dc65a46128ba" - "b27af87a71314f318c782b23ebfe808b" - "82b0ce26401d2e22f04d83d1255dc51a" - "ddd3b75a2b1ae0784504df543af8969b" - "e3ea7082ff7fc9888c144da2af58429e" - "c96031dbcad3dad9af0dcbaaaf268cb8" - "fcffead94f3c7ca495e056a9b47acdb7" - "51fb73e666c6c655ade8297297d07ad1" - "ba5e43f1bca32301651339e22904cc8c" - "42f58c30c04aafdb038dda0847dd988d" - "cda6f3bfd15c4b4c4525004aa06eeff8" - "ca61783aacec57fb3d1f92b0fe2fd1a8" - "5f6724517b65e614ad6808d6f6ee34df" - "f7310fdc82aebfd904b01e1dc54b2927" - "094b2db68d6f903b68401adebf5a7e08" - "d78ff4ef5d63653a65040cf9bfd4aca7" - "984a74d37145986780fc0b16ac451649" - "de6188a7dbdf191f64b5fc5e2ab47b57" - "f7f7276cd419c17a3ca8e1b939ae49e4" - "88acba6b965610b5480109c8b17b80e1" - "b7b750dfc7598d5d5011fd2dcc5600a3" - "2ef5b52a1ecc820e308aa342721aac09" - "43bf6686b64b2579376504ccc493d97e" - "6aed3fb0f9cd71a43dd497f01f17c0e2" - "cb3797aa2a2f256656168e6c496afc5f" - "b93246f6b1116398a346f1a641f3b041" - "e989f7914f90cc2c7fff357876e506b5" - "0d334ba77c225bc307ba537152f3f161" - "0e4eafe595f6d9d90d11faa933a15ef1" - "369546868a7f3a45a96768d40fd9d034" - "12c091c6315cf4fde7cb68606937380d" - "b2eaaa707b4c4185c32eddcdd306705e" - "4dc1ffc872eeee475a64dfac86aba41c" - "0618983f8741c5ef68d3a101e8a3b8ca" - "c60c905c15fc910840b94c00a0b9d0", - None, - "", - "0aab4c900501b3e24d7cdf4663326a3a" - "87df5e4843b2cbdb67cbf6e460fec350" - "aa5371b1508f9f4528ecea23c436d94b" - "5e8fcd4f681e30a6ac00a9704a188a03" - ), - # 7.2 Ed25519ctx - ( - "0305334e381af78f141cb666f6199f57" - "bc3495335a256a95bd2a55bf546663f6", - "dfc9425e4f968f7f0c29f0259cf5f9ae" - "d6851c2bb4ad8bfb860cfee0ab248292", - "f726936d19c800494e3fdaff20b276a8", - None, - "666f6f", - "55a4cc2f70a54e04288c5f4cd1e45a7b" - "b520b36292911876cada7323198dd87a" - "8b36950b95130022907a7fb7c4e9b2d5" - "f6cca685a587b4b21f4b888e4e7edb0d" - ), - ( - "0305334e381af78f141cb666f6199f57" - "bc3495335a256a95bd2a55bf546663f6", - "dfc9425e4f968f7f0c29f0259cf5f9ae" - "d6851c2bb4ad8bfb860cfee0ab248292", - "f726936d19c800494e3fdaff20b276a8", - None, - "626172", - "fc60d5872fc46b3aa69f8b5b4351d580" - "8f92bcc044606db097abab6dbcb1aee3" - "216c48e8b3b66431b5b186d1d28f8ee1" - "5a5ca2df6668346291c2043d4eb3e90d" - ), - ( - "0305334e381af78f141cb666f6199f57" - "bc3495335a256a95bd2a55bf546663f6", - "dfc9425e4f968f7f0c29f0259cf5f9ae" - "d6851c2bb4ad8bfb860cfee0ab248292", - "508e9e6882b979fea900f62adceaca35", - None, - "666f6f", - "8b70c1cc8310e1de20ac53ce28ae6e72" - "07f33c3295e03bb5c0732a1d20dc6490" - "8922a8b052cf99b7c4fe107a5abb5b2c" - "4085ae75890d02df26269d8945f84b0b" - ), - ( - "ab9c2853ce297ddab85c993b3ae14bca" - "d39b2c682beabc27d6d4eb20711d6560", - "0f1d1274943b91415889152e893d80e9" - "3275a1fc0b65fd71b4b0dda10ad7d772", - "f726936d19c800494e3fdaff20b276a8", - None, - "666f6f", - "21655b5f1aa965996b3f97b3c849eafb" - "a922a0a62992f73b3d1b73106a84ad85" - "e9b86a7b6005ea868337ff2d20a7f5fb" - "d4cd10b0be49a68da2b2e0dc0ad8960f" - ), - # 7.3 Ed25519ph - ( - "833fe62409237b9d62ec77587520911e" - "9a759cec1d19755b7da901b96dca3d42", - "ec172b93ad5e563bf4932c70e1245034" - "c35467ef2efd4d64ebf819683467e2bf", - "616263", - SHA512, - "", - "98a70222f0b8121aa9d30f813d683f80" - "9e462b469c7ff87639499bb94e6dae41" - "31f85042463c2a355a2003d062adf5aa" - "a10b8c61e636062aaad11c2a26083406" - ), - # 7.4 Ed448 - ( - "6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3" - "528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b", - "5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778" - "edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180", - "", - None, - "", - "533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f" - "2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a" - "9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4db" - "b61149f05a7363268c71d95808ff2e652600" - ), - ( - "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463a" - "fbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e", - "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c086" - "6aea01eb00742802b8438ea4cb82169c235160627b4c3a9480", - "03", - None, - "", - "26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f435" - "2541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cb" - "cee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0f" - "f3348ab21aa4adafd1d234441cf807c03a00", - ), - ( - "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463a" - "fbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e", - "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c086" - "6aea01eb00742802b8438ea4cb82169c235160627b4c3a9480", - "03", - None, - "666f6f", - "d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2" - "151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da" - "1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d" - "5428407e85dcbc98a49155c13764e66c3c00", - ), - ( - "cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffd" - "f60500553abc0e05cd02184bdb89c4ccd67e187951267eb328", - "dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e3" - "65fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400", - "0c3e544074ec63b0265e0c", - None, - "", - "1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d3" - "89dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b05" - "1068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5" - "028961c9bf8ffd973fe5d5c206492b140e00", - ), - ( - "258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d93" - "9f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b", - "3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc" - "24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580", - "64a65f3cdedcdd66811e2915", - None, - "", - "7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4a" - "e90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457e" - "b1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861" - "e72003cbae6d6b8b827e4e6c143064ff3c00", - ), - ( - "7ef4e84544236752fbb56b8f31a23a10e42814f5f55ca037cdcc11c64c9a3b29" - "49c1bb60700314611732a6c2fea98eebc0266a11a93970100e", - "b3da079b0aa493a5772029f0467baebee5a8112d9d3a22532361da294f7bb381" - "5c5dc59e176b4d9f381ca0938e13c6c07b174be65dfa578e80", - "64a65f3cdedcdd66811e2915e7", - None, - "", - "6a12066f55331b6c22acd5d5bfc5d71228fbda80ae8dec26bdd306743c5027cb" - "4890810c162c027468675ecf645a83176c0d7323a2ccde2d80efe5a1268e8aca" - "1d6fbc194d3f77c44986eb4ab4177919ad8bec33eb47bbb5fc6e28196fd1caf5" - "6b4e7e0ba5519234d047155ac727a1053100", - ), - ( - "d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bf" - "f21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01", - "df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a" - "39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00", - "bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5" - "512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944", - None, - "", - "554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b1" - "8dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722e" - "f552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba" - "5f30e88e36ec2703b349ca229c2670833900", - ), - ( - "2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d3756" - "9b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5", - "79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9b" - "fe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00", - "15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567c" - "fa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89" - "e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072f" - "c1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a60" - "39c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b5" - "90316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce0" - "12d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409" - "a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11", - None, - "", - "c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f" - "00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a" - "61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc6" - "0987fd08527c1a8e80d5823e65cafe2a3d00", - ), - ( - "872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec" - "44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8", - "a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799d" - "a08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400", - "6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412" - "a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd" - "86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc" - "3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e9" - "72660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9" - "b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd32321" - "9b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab79717" - "2b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813" - "a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0" - "596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f520" - "96cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1" - "526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998" - "d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee" - "85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6" - "155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4" - "c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db9" - "77025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f041" - "0a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456" - "f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab" - "0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3" - "120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535" - "aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf969614" - "9e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67" - "a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a605" - "9d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263" - "be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d" - "02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c" - "392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e" - "79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd" - "7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4" - "b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695" - "568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87", - None, - "", - "e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bd" - "df7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d" - "76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed57" - "3603ce30d8bb761785dc30dbc320869e1a00" - ), - # 7.5 Ed448ph - ( - "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42" - "ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49", - "259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743" - "c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880", - "616263", - SHAKE256, - "", - "822f6901f7480f3d5f562c592994d9693602875614483256505600bbc281ae38" - "1f54d6bce2ea911574932f52a4e6cadd78769375ec3ffd1b801a0d9b3f4030cd" - "433964b6457ea39476511214f97469b57dd32dbc560a9a94d00bff07620464a3" - "ad203df7dc7ce360c3cd3696d9d9fab90f00" - ), - ( - "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42" - "ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49", - "259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743" - "c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880", - "616263", - SHAKE256, - "666f6f", - "c32299d46ec8ff02b54540982814dce9a05812f81962b649d528095916a2aa48" - "1065b1580423ef927ecf0af5888f90da0f6a9a85ad5dc3f280d91224ba9911a3" - "653d00e484e2ce232521481c8658df304bb7745a73514cdb9bf3e15784ab7128" - "4f8d0704a608c54a6b62d97beb511d132100", - ), + # 7.1 Ed25519 + ( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", + "", + None, + "", + "e5564300c360ac729086e2cc806e828a" + "84877f1eb8e5d974d873e06522490155" + "5fb8821590a33bacc61e39701cf9b46b" + "d25bf5f0595bbe24655141438e7a100b", + ), + ( + "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", + "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", + "72", + None, + "", + "92a009a9f0d4cab8720e820b5f642540" + "a2b27b5416503f8fb3762223ebdb69da" + "085ac1e43e15996e458f3613d0f11d8c" + "387b2eaeb4302aeeb00d291612bb0c00", + ), + ( + "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", + "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", + "af82", + None, + "", + "6291d657deec24024827e69c3abe01a3" + "0ce548a284743a445e3680d7db5ac3ac" + "18ff9b538d16f290ae67f760984dc659" + "4a7c15e9716ed28dc027beceea1ec40a", + ), + ( + "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5", + "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", + "08b8b2b733424243760fe426a4b54908" + "632110a66c2f6591eabd3345e3e4eb98" + "fa6e264bf09efe12ee50f8f54e9f77b1" + "e355f6c50544e23fb1433ddf73be84d8" + "79de7c0046dc4996d9e773f4bc9efe57" + "38829adb26c81b37c93a1b270b20329d" + "658675fc6ea534e0810a4432826bf58c" + "941efb65d57a338bbd2e26640f89ffbc" + "1a858efcb8550ee3a5e1998bd177e93a" + "7363c344fe6b199ee5d02e82d522c4fe" + "ba15452f80288a821a579116ec6dad2b" + "3b310da903401aa62100ab5d1a36553e" + "06203b33890cc9b832f79ef80560ccb9" + "a39ce767967ed628c6ad573cb116dbef" + "efd75499da96bd68a8a97b928a8bbc10" + "3b6621fcde2beca1231d206be6cd9ec7" + "aff6f6c94fcd7204ed3455c68c83f4a4" + "1da4af2b74ef5c53f1d8ac70bdcb7ed1" + "85ce81bd84359d44254d95629e9855a9" + "4a7c1958d1f8ada5d0532ed8a5aa3fb2" + "d17ba70eb6248e594e1a2297acbbb39d" + "502f1a8c6eb6f1ce22b3de1a1f40cc24" + "554119a831a9aad6079cad88425de6bd" + "e1a9187ebb6092cf67bf2b13fd65f270" + "88d78b7e883c8759d2c4f5c65adb7553" + "878ad575f9fad878e80a0c9ba63bcbcc" + "2732e69485bbc9c90bfbd62481d9089b" + "eccf80cfe2df16a2cf65bd92dd597b07" + "07e0917af48bbb75fed413d238f5555a" + "7a569d80c3414a8d0859dc65a46128ba" + "b27af87a71314f318c782b23ebfe808b" + "82b0ce26401d2e22f04d83d1255dc51a" + "ddd3b75a2b1ae0784504df543af8969b" + "e3ea7082ff7fc9888c144da2af58429e" + "c96031dbcad3dad9af0dcbaaaf268cb8" + "fcffead94f3c7ca495e056a9b47acdb7" + "51fb73e666c6c655ade8297297d07ad1" + "ba5e43f1bca32301651339e22904cc8c" + "42f58c30c04aafdb038dda0847dd988d" + "cda6f3bfd15c4b4c4525004aa06eeff8" + "ca61783aacec57fb3d1f92b0fe2fd1a8" + "5f6724517b65e614ad6808d6f6ee34df" + "f7310fdc82aebfd904b01e1dc54b2927" + "094b2db68d6f903b68401adebf5a7e08" + "d78ff4ef5d63653a65040cf9bfd4aca7" + "984a74d37145986780fc0b16ac451649" + "de6188a7dbdf191f64b5fc5e2ab47b57" + "f7f7276cd419c17a3ca8e1b939ae49e4" + "88acba6b965610b5480109c8b17b80e1" + "b7b750dfc7598d5d5011fd2dcc5600a3" + "2ef5b52a1ecc820e308aa342721aac09" + "43bf6686b64b2579376504ccc493d97e" + "6aed3fb0f9cd71a43dd497f01f17c0e2" + "cb3797aa2a2f256656168e6c496afc5f" + "b93246f6b1116398a346f1a641f3b041" + "e989f7914f90cc2c7fff357876e506b5" + "0d334ba77c225bc307ba537152f3f161" + "0e4eafe595f6d9d90d11faa933a15ef1" + "369546868a7f3a45a96768d40fd9d034" + "12c091c6315cf4fde7cb68606937380d" + "b2eaaa707b4c4185c32eddcdd306705e" + "4dc1ffc872eeee475a64dfac86aba41c" + "0618983f8741c5ef68d3a101e8a3b8ca" + "c60c905c15fc910840b94c00a0b9d0", + None, + "", + "0aab4c900501b3e24d7cdf4663326a3a" + "87df5e4843b2cbdb67cbf6e460fec350" + "aa5371b1508f9f4528ecea23c436d94b" + "5e8fcd4f681e30a6ac00a9704a188a03", + ), + # 7.2 Ed25519ctx + ( + "0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6", + "dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292", + "f726936d19c800494e3fdaff20b276a8", + None, + "666f6f", + "55a4cc2f70a54e04288c5f4cd1e45a7b" + "b520b36292911876cada7323198dd87a" + "8b36950b95130022907a7fb7c4e9b2d5" + "f6cca685a587b4b21f4b888e4e7edb0d", + ), + ( + "0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6", + "dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292", + "f726936d19c800494e3fdaff20b276a8", + None, + "626172", + "fc60d5872fc46b3aa69f8b5b4351d580" + "8f92bcc044606db097abab6dbcb1aee3" + "216c48e8b3b66431b5b186d1d28f8ee1" + "5a5ca2df6668346291c2043d4eb3e90d", + ), + ( + "0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6", + "dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292", + "508e9e6882b979fea900f62adceaca35", + None, + "666f6f", + "8b70c1cc8310e1de20ac53ce28ae6e72" + "07f33c3295e03bb5c0732a1d20dc6490" + "8922a8b052cf99b7c4fe107a5abb5b2c" + "4085ae75890d02df26269d8945f84b0b", + ), + ( + "ab9c2853ce297ddab85c993b3ae14bcad39b2c682beabc27d6d4eb20711d6560", + "0f1d1274943b91415889152e893d80e93275a1fc0b65fd71b4b0dda10ad7d772", + "f726936d19c800494e3fdaff20b276a8", + None, + "666f6f", + "21655b5f1aa965996b3f97b3c849eafb" + "a922a0a62992f73b3d1b73106a84ad85" + "e9b86a7b6005ea868337ff2d20a7f5fb" + "d4cd10b0be49a68da2b2e0dc0ad8960f", + ), + # 7.3 Ed25519ph + ( + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42", + "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf", + "616263", + SHA512, + "", + "98a70222f0b8121aa9d30f813d683f80" + "9e462b469c7ff87639499bb94e6dae41" + "31f85042463c2a355a2003d062adf5aa" + "a10b8c61e636062aaad11c2a26083406", + ), + # 7.4 Ed448 + ( + "6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3" + "528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b", + "5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778" + "edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180", + "", + None, + "", + "533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f" + "2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a" + "9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4db" + "b61149f05a7363268c71d95808ff2e652600", + ), + ( + "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463a" + "fbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e", + "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c086" + "6aea01eb00742802b8438ea4cb82169c235160627b4c3a9480", + "03", + None, + "", + "26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f435" + "2541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cb" + "cee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0f" + "f3348ab21aa4adafd1d234441cf807c03a00", + ), + ( + "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463a" + "fbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e", + "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c086" + "6aea01eb00742802b8438ea4cb82169c235160627b4c3a9480", + "03", + None, + "666f6f", + "d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2" + "151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da" + "1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d" + "5428407e85dcbc98a49155c13764e66c3c00", + ), + ( + "cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffd" + "f60500553abc0e05cd02184bdb89c4ccd67e187951267eb328", + "dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e3" + "65fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400", + "0c3e544074ec63b0265e0c", + None, + "", + "1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d3" + "89dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b05" + "1068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5" + "028961c9bf8ffd973fe5d5c206492b140e00", + ), + ( + "258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d93" + "9f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b", + "3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc" + "24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580", + "64a65f3cdedcdd66811e2915", + None, + "", + "7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4a" + "e90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457e" + "b1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861" + "e72003cbae6d6b8b827e4e6c143064ff3c00", + ), + ( + "7ef4e84544236752fbb56b8f31a23a10e42814f5f55ca037cdcc11c64c9a3b29" + "49c1bb60700314611732a6c2fea98eebc0266a11a93970100e", + "b3da079b0aa493a5772029f0467baebee5a8112d9d3a22532361da294f7bb381" + "5c5dc59e176b4d9f381ca0938e13c6c07b174be65dfa578e80", + "64a65f3cdedcdd66811e2915e7", + None, + "", + "6a12066f55331b6c22acd5d5bfc5d71228fbda80ae8dec26bdd306743c5027cb" + "4890810c162c027468675ecf645a83176c0d7323a2ccde2d80efe5a1268e8aca" + "1d6fbc194d3f77c44986eb4ab4177919ad8bec33eb47bbb5fc6e28196fd1caf5" + "6b4e7e0ba5519234d047155ac727a1053100", + ), + ( + "d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bf" + "f21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01", + "df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a" + "39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00", + "bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5" + "512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944", + None, + "", + "554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b1" + "8dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722e" + "f552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba" + "5f30e88e36ec2703b349ca229c2670833900", + ), + ( + "2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d3756" + "9b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5", + "79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9b" + "fe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00", + "15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567c" + "fa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89" + "e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072f" + "c1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a60" + "39c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b5" + "90316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce0" + "12d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409" + "a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11", + None, + "", + "c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f" + "00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a" + "61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc6" + "0987fd08527c1a8e80d5823e65cafe2a3d00", + ), + ( + "872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec" + "44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8", + "a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799d" + "a08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400", + "6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412" + "a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd" + "86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc" + "3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e9" + "72660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9" + "b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd32321" + "9b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab79717" + "2b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813" + "a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0" + "596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f520" + "96cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1" + "526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998" + "d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee" + "85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6" + "155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4" + "c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db9" + "77025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f041" + "0a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456" + "f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab" + "0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3" + "120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535" + "aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf969614" + "9e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67" + "a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a605" + "9d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263" + "be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d" + "02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c" + "392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e" + "79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd" + "7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4" + "b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695" + "568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87", + None, + "", + "e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bd" + "df7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d" + "76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed57" + "3603ce30d8bb761785dc30dbc320869e1a00", + ), + # 7.5 Ed448ph + ( + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42" + "ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49", + "259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743" + "c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880", + "616263", + SHAKE256, + "", + "822f6901f7480f3d5f562c592994d9693602875614483256505600bbc281ae38" + "1f54d6bce2ea911574932f52a4e6cadd78769375ec3ffd1b801a0d9b3f4030cd" + "433964b6457ea39476511214f97469b57dd32dbc560a9a94d00bff07620464a3" + "ad203df7dc7ce360c3cd3696d9d9fab90f00", + ), + ( + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42" + "ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49", + "259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743" + "c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880", + "616263", + SHAKE256, + "666f6f", + "c32299d46ec8ff02b54540982814dce9a05812f81962b649d528095916a2aa48" + "1065b1580423ef927ecf0af5888f90da0f6a9a85ad5dc3f280d91224ba9911a3" + "653d00e484e2ce232521481c8658df304bb7745a73514cdb9bf3e15784ab7128" + "4f8d0704a608c54a6b62d97beb511d132100", + ), ) rfc8032_tv_bytes = [] for tv_str in rfc8032_tv_str: - rfc8032_tv_bytes.append([unhexlify(i) if isinstance(i, str) else i for i in tv_str]) + rfc8032_tv_bytes.append([unhexlify(i) if isinstance(i, str) else i for i in tv_str]) class TestEdDSA(unittest.TestCase): - - def test_sign(self): - for sk, _, msg, hashmod, ctx, exp_signature in rfc8032_tv_bytes: - key = eddsa.import_private_key(sk) - signer = eddsa.new(key, 'rfc8032', context=ctx) - if hashmod is None: - # PureEdDSA - signature = signer.sign(msg) - else: - # HashEdDSA - hashobj = hashmod.new(msg) - signature = signer.sign(hashobj) - self.assertEqual(exp_signature, signature) - - def test_verify(self): - for _, pk, msg, hashmod, ctx, exp_signature in rfc8032_tv_bytes: - key = eddsa.import_public_key(pk) - verifier = eddsa.new(key, 'rfc8032', context=ctx) - if hashmod is None: - # PureEdDSA - verifier.verify(msg, exp_signature) - else: - # HashEdDSA - hashobj = hashmod.new(msg) - verifier.verify(hashobj, exp_signature) - - def test_double_sign_verify_ed25519(self): - msg_hash = SHA512.new(b'abc') - key = ECC.generate(curve='ed25519') - signer = eddsa.new(key, 'rfc8032') - verifier = eddsa.new(key, 'rfc8032') - - signature = signer.sign(msg_hash) - signature2 = signer.sign(msg_hash) - self.assertEqual(signature, signature2) - - verifier.verify(msg_hash, signature) - verifier.verify(msg_hash, signature) - - def test_double_sign_verify_ed448(self): - msg_hash = SHAKE256.new(b'abc') - key = ECC.generate(curve='ed448') - signer = eddsa.new(key, 'rfc8032') - verifier = eddsa.new(key, 'rfc8032') - - signature = signer.sign(msg_hash) - signature2 = signer.sign(msg_hash) - self.assertEqual(signature, signature2) - - verifier.verify(msg_hash, signature) - verifier.verify(msg_hash, signature) - - def test_negative(self): - key = ECC.generate(curve="ed25519") - self.assertRaises(ValueError, eddsa.new, key, 'rfc9999') - - nist_key = ECC.generate(curve="p256") - self.assertRaises(ValueError, eddsa.new, nist_key, 'rfc8032') + def test_sign(self): + for sk, _, msg, hashmod, ctx, exp_signature in rfc8032_tv_bytes: + key = eddsa.import_private_key(sk) + signer = eddsa.new(key, "rfc8032", context=ctx) + if hashmod is None: + # PureEdDSA + signature = signer.sign(msg) + else: + # HashEdDSA + hashobj = hashmod.new(msg) + signature = signer.sign(hashobj) + self.assertEqual(exp_signature, signature) + + def test_verify(self): + for _, pk, msg, hashmod, ctx, exp_signature in rfc8032_tv_bytes: + key = eddsa.import_public_key(pk) + verifier = eddsa.new(key, "rfc8032", context=ctx) + if hashmod is None: + # PureEdDSA + verifier.verify(msg, exp_signature) + else: + # HashEdDSA + hashobj = hashmod.new(msg) + verifier.verify(hashobj, exp_signature) + + def test_double_sign_verify_ed25519(self): + msg_hash = SHA512.new(b"abc") + key = ECC.generate(curve="ed25519") + signer = eddsa.new(key, "rfc8032") + verifier = eddsa.new(key, "rfc8032") + + signature = signer.sign(msg_hash) + signature2 = signer.sign(msg_hash) + self.assertEqual(signature, signature2) + + verifier.verify(msg_hash, signature) + verifier.verify(msg_hash, signature) + + def test_double_sign_verify_ed448(self): + msg_hash = SHAKE256.new(b"abc") + key = ECC.generate(curve="ed448") + signer = eddsa.new(key, "rfc8032") + verifier = eddsa.new(key, "rfc8032") + + signature = signer.sign(msg_hash) + signature2 = signer.sign(msg_hash) + self.assertEqual(signature, signature2) + + verifier.verify(msg_hash, signature) + verifier.verify(msg_hash, signature) + + def test_negative(self): + key = ECC.generate(curve="ed25519") + self.assertRaises(ValueError, eddsa.new, key, "rfc9999") + + nist_key = ECC.generate(curve="p256") + self.assertRaises(ValueError, eddsa.new, nist_key, "rfc8032") class TestExport_Ed25519(unittest.TestCase): + def test_raw(self): + key = ECC.generate(curve="Ed25519") + x, y = key.pointQ.xy + raw = bytearray(key._export_eddsa_public()) + sign_x = raw[31] >> 7 + raw[31] &= 0x7F + yt = bytes_to_long(raw[::-1]) + self.assertEqual(y, yt) + self.assertEqual(x & 1, sign_x) - def test_raw(self): - key = ECC.generate(curve="Ed25519") - x, y = key.pointQ.xy - raw = bytearray(key._export_eddsa_public()) - sign_x = raw[31] >> 7 - raw[31] &= 0x7F - yt = bytes_to_long(raw[::-1]) - self.assertEqual(y, yt) - self.assertEqual(x & 1, sign_x) - - key = ECC.construct(point_x=0, point_y=1, curve="Ed25519") - out = key._export_eddsa_public() - self.assertEqual(b'\x01' + b'\x00' * 31, out) + key = ECC.construct(point_x=0, point_y=1, curve="Ed25519") + out = key._export_eddsa_public() + self.assertEqual(b"\x01" + b"\x00" * 31, out) class TestExport_Ed448(unittest.TestCase): + def test_raw(self): + key = ECC.generate(curve="Ed448") + x, y = key.pointQ.xy + raw = bytearray(key._export_eddsa_public()) + sign_x = raw[56] >> 7 + raw[56] &= 0x7F + yt = bytes_to_long(raw[::-1]) + self.assertEqual(y, yt) + self.assertEqual(x & 1, sign_x) - def test_raw(self): - key = ECC.generate(curve="Ed448") - x, y = key.pointQ.xy - raw = bytearray(key._export_eddsa_public()) - sign_x = raw[56] >> 7 - raw[56] &= 0x7F - yt = bytes_to_long(raw[::-1]) - self.assertEqual(y, yt) - self.assertEqual(x & 1, sign_x) - - key = ECC.construct(point_x=0, point_y=1, curve="Ed448") - out = key._export_eddsa_public() - self.assertEqual(b'\x01' + b'\x00' * 56, out) + key = ECC.construct(point_x=0, point_y=1, curve="Ed448") + out = key._export_eddsa_public() + self.assertEqual(b"\x01" + b"\x00" * 56, out) class TestImport_Ed25519(unittest.TestCase): + def test_raw(self): + Px = 24407857220263921307776619664228778204996144802740950419837658238229122415920 + Py = 56480760040633817885061096979765646085062883740629155052073094891081309750690 + encoded = b"\xa2\x05\xd6\x00\xe1 \xe1\xc0\xff\x96\xee?V\x8e\xba/\xd3\x89\x06\xd7\xc4c\xe8$\xc2d\xd7a1\xfa\xde|" + key = eddsa.import_public_key(encoded) + self.assertEqual(Py, key.pointQ.y) + self.assertEqual(Px, key.pointQ.x) - def test_raw(self): - Px = 24407857220263921307776619664228778204996144802740950419837658238229122415920 - Py = 56480760040633817885061096979765646085062883740629155052073094891081309750690 - encoded = b'\xa2\x05\xd6\x00\xe1 \xe1\xc0\xff\x96\xee?V\x8e\xba/\xd3\x89\x06\xd7\xc4c\xe8$\xc2d\xd7a1\xfa\xde|' - key = eddsa.import_public_key(encoded) - self.assertEqual(Py, key.pointQ.y) - self.assertEqual(Px, key.pointQ.x) - - encoded = b'\x01' + b'\x00' * 31 - key = eddsa.import_public_key(encoded) - self.assertEqual(1, key.pointQ.y) - self.assertEqual(0, key.pointQ.x) + encoded = b"\x01" + b"\x00" * 31 + key = eddsa.import_public_key(encoded) + self.assertEqual(1, key.pointQ.y) + self.assertEqual(0, key.pointQ.x) class TestImport_Ed448(unittest.TestCase): - - def test_raw(self): - Px = 0x153f42025aba3b0daecaa5cd79458b3146c7c9378c16c17b4a59bc3561113d90c169045bc12966c3f93e140c2ca0a3acc33d9205b9daf9b1 - Py = 0x38f5c0015d3dedd576c232810dd90373b5b1d631a12894c043b7be529cbae03ede177d8fa490b56131dbcb2465d2aba777ef839fc1719b25 - encoded = unhexlify("259b71c19f83ef77a7abd26524cbdb31" - "61b590a48f7d17de3ee0ba9c52beb743" - "c09428a131d6b1b57303d90d8132c276" - "d5ed3d5d01c0f53880") - key = eddsa.import_public_key(encoded) - self.assertEqual(Py, key.pointQ.y) - self.assertEqual(Px, key.pointQ.x) - - encoded = b'\x01' + b'\x00' * 56 - key = eddsa.import_public_key(encoded) - self.assertEqual(1, key.pointQ.y) - self.assertEqual(0, key.pointQ.x) + def test_raw(self): + Px = 0x153F42025ABA3B0DAECAA5CD79458B3146C7C9378C16C17B4A59BC3561113D90C169045BC12966C3F93E140C2CA0A3ACC33D9205B9DAF9B1 + Py = 0x38F5C0015D3DEDD576C232810DD90373B5B1D631A12894C043B7BE529CBAE03EDE177D8FA490B56131DBCB2465D2ABA777EF839FC1719B25 + encoded = unhexlify( + "259b71c19f83ef77a7abd26524cbdb31" + "61b590a48f7d17de3ee0ba9c52beb743" + "c09428a131d6b1b57303d90d8132c276" + "d5ed3d5d01c0f53880", + ) + key = eddsa.import_public_key(encoded) + self.assertEqual(Py, key.pointQ.y) + self.assertEqual(Px, key.pointQ.x) + + encoded = b"\x01" + b"\x00" * 56 + key = eddsa.import_public_key(encoded) + self.assertEqual(1, key.pointQ.y) + self.assertEqual(0, key.pointQ.x) class TestVectorsEdDSAWycheproof(unittest.TestCase): - - def add_tests(self, filename): - - def pk(group): - elem = group['key']['pk'] - return unhexlify(elem) - - def sk(group): - elem = group['key']['sk'] - return unhexlify(elem) - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof ECDSA signature (%s)" - % filename, - group_tag={'pk': pk, 'sk': sk}) - self.tv += result - - def setUp(self): - self.tv = [] - self.add_tests("eddsa_test.json") - self.add_tests("ed448_test.json") - - def test_sign(self, tv): - if not tv.valid: - return - - self._id = "Wycheproof EdDSA Sign Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - key = eddsa.import_private_key(tv.sk) - signer = eddsa.new(key, 'rfc8032') - signature = signer.sign(tv.msg) - self.assertEqual(signature, tv.sig) - - def test_verify(self, tv): - self._id = "Wycheproof EdDSA Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - key = eddsa.import_public_key(tv.pk) - verifier = eddsa.new(key, 'rfc8032') - try: - verifier.verify(tv.msg, tv.sig) - except ValueError: - assert not tv.valid - else: - assert tv.valid - - def runTest(self): - for tv in self.tv: - self.test_sign(tv) - self.test_verify(tv) + def add_tests(self, filename): + def pk(group): + elem = group["key"]["pk"] + return unhexlify(elem) + + def sk(group): + elem = group["key"]["sk"] + return unhexlify(elem) + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + filename, + "Wycheproof ECDSA signature (%s)" % filename, + group_tag={"pk": pk, "sk": sk}, + ) + self.tv += result + + def setUp(self): + self.tv = [] + self.add_tests("eddsa_test.json") + self.add_tests("ed448_test.json") + + def test_sign(self, tv): + if not tv.valid: + return + + self._id = "Wycheproof EdDSA Sign Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + key = eddsa.import_private_key(tv.sk) + signer = eddsa.new(key, "rfc8032") + signature = signer.sign(tv.msg) + self.assertEqual(signature, tv.sig) + + def test_verify(self, tv): + self._id = "Wycheproof EdDSA Verify Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) + key = eddsa.import_public_key(tv.pk) + verifier = eddsa.new(key, "rfc8032") + try: + verifier.verify(tv.msg, tv.sig) + except ValueError: + assert not tv.valid + else: + assert tv.valid + + def runTest(self): + for tv in self.tv: + self.test_sign(tv) + self.test_verify(tv) def get_tests(config={}): + tests = [] + tests += list_test_cases(TestExport_Ed25519) + tests += list_test_cases(TestExport_Ed448) + tests += list_test_cases(TestImport_Ed25519) + tests += list_test_cases(TestImport_Ed448) + tests += list_test_cases(TestEdDSA) + tests += [TestVectorsEdDSAWycheproof()] + return tests + - tests = [] - tests += list_test_cases(TestExport_Ed25519) - tests += list_test_cases(TestExport_Ed448) - tests += list_test_cases(TestImport_Ed25519) - tests += list_test_cases(TestImport_Ed448) - tests += list_test_cases(TestEdDSA) - tests += [TestVectorsEdDSAWycheproof()] - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_pkcs1_15.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_pkcs1_15.py index 3a3e30b5..309f9ce9 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_pkcs1_15.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_pkcs1_15.py @@ -28,7 +28,6 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -import json import unittest from binascii import unhexlify @@ -38,118 +37,139 @@ from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof -from Cryptodome.Hash import (SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_384, - SHA3_224, SHA3_256, SHA3_512) +from Cryptodome.Hash import ( + SHA1, + SHA224, + SHA256, + SHA384, + SHA512, + SHA3_384, + SHA3_224, + SHA3_256, + SHA3_512, +) from Cryptodome.PublicKey import RSA from Cryptodome.Signature import pkcs1_15 from Cryptodome.Signature import PKCS1_v1_5 -from Cryptodome.Util._file_system import pycryptodome_filename -from Cryptodome.Util.strxor import strxor - def load_hash_by_name(hash_name): - return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) + return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) class FIPS_PKCS1_Verify_Tests(unittest.TestCase): + def shortDescription(self): + return "FIPS PKCS1 Tests (Verify)" - def shortDescription(self): - return "FIPS PKCS1 Tests (Verify)" - - def test_can_sign(self): - test_public_key = RSA.generate(1024).public_key() - verifier = pkcs1_15.new(test_public_key) - self.assertEqual(verifier.can_sign(), False) + def test_can_sign(self): + test_public_key = RSA.generate(1024).public_key() + verifier = pkcs1_15.new(test_public_key) + self.assertEqual(verifier.can_sign(), False) class FIPS_PKCS1_Verify_Tests_KAT(unittest.TestCase): - pass + pass -test_vectors_verify = load_test_vectors(("Signature", "PKCS1-v1.5"), - "SigVer15_186-3.rsp", - "Signature Verification 186-3", - {'shaalg': lambda x: x, - 'd': lambda x: int(x), - 'result': lambda x: x}) or [] +test_vectors_verify = ( + load_test_vectors( + ("Signature", "PKCS1-v1.5"), + "SigVer15_186-3.rsp", + "Signature Verification 186-3", + { + "shaalg": lambda x: x, + "d": lambda x: int(x), + "result": lambda x: x, + }, + ) + or [] +) for count, tv in enumerate(test_vectors_verify): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue + if isinstance(tv, str): + continue + if hasattr(tv, "n"): + modulus = tv.n + continue - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore - verifier = pkcs1_15.new(public_key) + hash_module = load_hash_by_name(tv.shaalg.upper()) + hash_obj = hash_module.new(tv.msg) + public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore + verifier = pkcs1_15.new(public_key) - def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - verifier.verify(hash_obj, signature) + def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): + verifier.verify(hash_obj, signature) - def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) + def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): + self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - if tv.result == 'f': - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) - else: - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) + if tv.result == "f": + setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) + else: + setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) class FIPS_PKCS1_Sign_Tests(unittest.TestCase): + def shortDescription(self): + return "FIPS PKCS1 Tests (Sign)" - def shortDescription(self): - return "FIPS PKCS1 Tests (Sign)" - - def test_can_sign(self): - test_private_key = RSA.generate(1024) - signer = pkcs1_15.new(test_private_key) - self.assertEqual(signer.can_sign(), True) + def test_can_sign(self): + test_private_key = RSA.generate(1024) + signer = pkcs1_15.new(test_private_key) + self.assertEqual(signer.can_sign(), True) class FIPS_PKCS1_Sign_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_sign = load_test_vectors(("Signature", "PKCS1-v1.5"), - "SigGen15_186-2.txt", - "Signature Generation 186-2", - {'shaalg': lambda x: x}) or [] - -test_vectors_sign += load_test_vectors(("Signature", "PKCS1-v1.5"), - "SigGen15_186-3.txt", - "Signature Generation 186-3", - {'shaalg': lambda x: x}) or [] + pass + + +test_vectors_sign = ( + load_test_vectors( + ("Signature", "PKCS1-v1.5"), + "SigGen15_186-2.txt", + "Signature Generation 186-2", + {"shaalg": lambda x: x}, + ) + or [] +) + +test_vectors_sign += ( + load_test_vectors( + ("Signature", "PKCS1-v1.5"), + "SigGen15_186-3.txt", + "Signature Generation 186-3", + {"shaalg": lambda x: x}, + ) + or [] +) for count, tv in enumerate(test_vectors_sign): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - if hasattr(tv, "e"): - private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore - signer = pkcs1_15.new(private_key) - continue + if isinstance(tv, str): + continue + if hasattr(tv, "n"): + modulus = tv.n + continue + if hasattr(tv, "e"): + private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore + signer = pkcs1_15.new(private_key) + continue - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) + hash_module = load_hash_by_name(tv.shaalg.upper()) + hash_obj = hash_module.new(tv.msg) - def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): - signature = signer.sign(hash_obj) - self.assertEqual(signature, result) + def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): + signature = signer.sign(hash_obj) + self.assertEqual(signature, result) - setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) + setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) class PKCS1_15_NoParams(unittest.TestCase): - """Verify that PKCS#1 v1.5 signatures pass even without NULL parameters in - the algorithm identifier (PyCrypto/LP bug #1119552).""" + """Verify that PKCS#1 v1.5 signatures pass even without NULL parameters in + the algorithm identifier (PyCrypto/LP bug #1119552).""" - rsakey = """-----BEGIN RSA PRIVATE KEY----- + rsakey = """-----BEGIN RSA PRIVATE KEY----- MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8 Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI @@ -159,190 +179,207 @@ class PKCS1_15_NoParams(unittest.TestCase): n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ== -----END RSA PRIVATE KEY-----""" - msg = b"This is a test\x0a" + msg = b"This is a test\x0a" - # PKCS1 v1.5 signature of the message computed using SHA-1. - # The digestAlgorithm SEQUENCE does NOT contain the NULL parameter. - sig_str = "a287a13517f716e72fb14eea8e33a8db4a4643314607e7ca3e3e28"\ - "1893db74013dda8b855fd99f6fecedcb25fcb7a434f35cd0a101f8"\ - "b19348e0bd7b6f152dfc" - signature = unhexlify(sig_str) + # PKCS1 v1.5 signature of the message computed using SHA-1. + # The digestAlgorithm SEQUENCE does NOT contain the NULL parameter. + sig_str = ( + "a287a13517f716e72fb14eea8e33a8db4a4643314607e7ca3e3e28" + "1893db74013dda8b855fd99f6fecedcb25fcb7a434f35cd0a101f8" + "b19348e0bd7b6f152dfc" + ) + signature = unhexlify(sig_str) - def runTest(self): - verifier = pkcs1_15.new(RSA.importKey(self.rsakey)) - hashed = SHA1.new(self.msg) - verifier.verify(hashed, self.signature) + def runTest(self): + verifier = pkcs1_15.new(RSA.importKey(self.rsakey)) + hashed = SHA1.new(self.msg) + verifier.verify(hashed, self.signature) class PKCS1_Legacy_Module_Tests(unittest.TestCase): - """Verify that the legacy module Cryptodome.Signature.PKCS1_v1_5 - behaves as expected. The only difference is that the verify() - method returns True/False and does not raise exceptions.""" + """Verify that the legacy module Cryptodome.Signature.PKCS1_v1_5 + behaves as expected. The only difference is that the verify() + method returns True/False and does not raise exceptions.""" - def shortDescription(self): - return "Test legacy Cryptodome.Signature.PKCS1_v1_5" + def shortDescription(self): + return "Test legacy Cryptodome.Signature.PKCS1_v1_5" - def runTest(self): - key = RSA.importKey(PKCS1_15_NoParams.rsakey) - hashed = SHA1.new(b"Test") - good_signature = PKCS1_v1_5.new(key).sign(hashed) - verifier = PKCS1_v1_5.new(key.public_key()) + def runTest(self): + key = RSA.importKey(PKCS1_15_NoParams.rsakey) + hashed = SHA1.new(b"Test") + good_signature = PKCS1_v1_5.new(key).sign(hashed) + verifier = PKCS1_v1_5.new(key.public_key()) - self.assertEqual(verifier.verify(hashed, good_signature), True) + self.assertEqual(verifier.verify(hashed, good_signature), True) - # Flip a few bits in the signature - bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) - self.assertEqual(verifier.verify(hashed, bad_signature), False) + # Flip a few bits in the signature + bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) + self.assertEqual(verifier.verify(hashed, bad_signature), False) class PKCS1_All_Hashes_Tests(unittest.TestCase): - - def shortDescription(self): - return "Test PKCS#1v1.5 signature in combination with all hashes" - - def runTest(self): - - key = RSA.generate(1024) - signer = pkcs1_15.new(key) - hash_names = ("MD2", "MD4", "MD5", "RIPEMD160", "SHA1", - "SHA224", "SHA256", "SHA384", "SHA512", - "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512") - - for name in hash_names: - hashed = load_hash_by_name(name).new(b"Test") - signer.sign(hashed) - - from Cryptodome.Hash import BLAKE2b, BLAKE2s - for hash_size in (20, 32, 48, 64): - hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b"Test") - signer.sign(hashed_b) - for hash_size in (16, 20, 28, 32): - hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b"Test") - signer.sign(hashed_s) + def shortDescription(self): + return "Test PKCS#1v1.5 signature in combination with all hashes" + + def runTest(self): + key = RSA.generate(1024) + signer = pkcs1_15.new(key) + hash_names = ( + "MD2", + "MD4", + "MD5", + "RIPEMD160", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA3_224", + "SHA3_256", + "SHA3_384", + "SHA3_512", + ) + + for name in hash_names: + hashed = load_hash_by_name(name).new(b"Test") + signer.sign(hashed) + + from Cryptodome.Hash import BLAKE2b, BLAKE2s + + for hash_size in (20, 32, 48, 64): + hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b"Test") + signer.sign(hashed_b) + for hash_size in (16, 20, 28, 32): + hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b"Test") + signer.sign(hashed_s) class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def setUp(self): - self.tv = [] - self.add_tests("rsa_sig_gen_misc_test.json") - self.add_tests("rsa_signature_2048_sha224_test.json") - self.add_tests("rsa_signature_2048_sha256_test.json") - self.add_tests("rsa_signature_2048_sha384_test.json") - self.add_tests("rsa_signature_2048_sha3_224_test.json") - self.add_tests("rsa_signature_2048_sha3_256_test.json") - self.add_tests("rsa_signature_2048_sha3_384_test.json") - self.add_tests("rsa_signature_2048_sha3_512_test.json") - self.add_tests("rsa_signature_2048_sha512_test.json") - self.add_tests("rsa_signature_2048_sha512_224_test.json") - self.add_tests("rsa_signature_2048_sha512_256_test.json") - self.add_tests("rsa_signature_3072_sha256_test.json") - self.add_tests("rsa_signature_3072_sha384_test.json") - self.add_tests("rsa_signature_3072_sha3_256_test.json") - self.add_tests("rsa_signature_3072_sha3_384_test.json") - self.add_tests("rsa_signature_3072_sha3_512_test.json") - self.add_tests("rsa_signature_3072_sha512_test.json") - self.add_tests("rsa_signature_3072_sha512_256_test.json") - self.add_tests("rsa_signature_4096_sha384_test.json") - self.add_tests("rsa_signature_4096_sha512_test.json") - self.add_tests("rsa_signature_4096_sha512_256_test.json") - self.add_tests("rsa_signature_test.json") - - def add_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['keyPem']) - - def filter_sha(group): - hash_name = group['sha'] - if hash_name == "SHA-512": - return SHA512 - elif hash_name == "SHA-512/224": - return SHA512.new(truncate="224") - elif hash_name == "SHA-512/256": - return SHA512.new(truncate="256") - elif hash_name == "SHA3-512": - return SHA3_512 - elif hash_name == "SHA-384": - return SHA384 - elif hash_name == "SHA3-384": - return SHA3_384 - elif hash_name == "SHA-256": - return SHA256 - elif hash_name == "SHA3-256": - return SHA3_256 - elif hash_name == "SHA-224": - return SHA224 - elif hash_name == "SHA3-224": - return SHA3_224 - elif hash_name == "SHA-1": - return SHA1 - else: - raise ValueError("Unknown hash algorithm: " + hash_name) - - def filter_type(group): - type_name = group['type'] - if type_name not in ("RsassaPkcs1Verify", "RsassaPkcs1Generate"): - raise ValueError("Unknown type name " + type_name) - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof PKCS#1v1.5 signature (%s)" % filename, - group_tag={'rsa_key': filter_rsa, - 'hash_mod': filter_sha, - 'type': filter_type}) - return result - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof RSA PKCS$#1 Test #" + str(tv.id) - - hashed_msg = tv.hash_module.new(tv.msg) - signer = pkcs1_15.new(tv.key) - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def setUp(self): + self.tv = [] + self.add_tests("rsa_sig_gen_misc_test.json") + self.add_tests("rsa_signature_2048_sha224_test.json") + self.add_tests("rsa_signature_2048_sha256_test.json") + self.add_tests("rsa_signature_2048_sha384_test.json") + self.add_tests("rsa_signature_2048_sha3_224_test.json") + self.add_tests("rsa_signature_2048_sha3_256_test.json") + self.add_tests("rsa_signature_2048_sha3_384_test.json") + self.add_tests("rsa_signature_2048_sha3_512_test.json") + self.add_tests("rsa_signature_2048_sha512_test.json") + self.add_tests("rsa_signature_2048_sha512_224_test.json") + self.add_tests("rsa_signature_2048_sha512_256_test.json") + self.add_tests("rsa_signature_3072_sha256_test.json") + self.add_tests("rsa_signature_3072_sha384_test.json") + self.add_tests("rsa_signature_3072_sha3_256_test.json") + self.add_tests("rsa_signature_3072_sha3_384_test.json") + self.add_tests("rsa_signature_3072_sha3_512_test.json") + self.add_tests("rsa_signature_3072_sha512_test.json") + self.add_tests("rsa_signature_3072_sha512_256_test.json") + self.add_tests("rsa_signature_4096_sha384_test.json") + self.add_tests("rsa_signature_4096_sha512_test.json") + self.add_tests("rsa_signature_4096_sha512_256_test.json") + self.add_tests("rsa_signature_test.json") + + def add_tests(self, filename): + def filter_rsa(group): + return RSA.import_key(group["keyPem"]) + + def filter_sha(group): + hash_name = group["sha"] + if hash_name == "SHA-512": + return SHA512 + elif hash_name == "SHA-512/224": + return SHA512.new(truncate="224") + elif hash_name == "SHA-512/256": + return SHA512.new(truncate="256") + elif hash_name == "SHA3-512": + return SHA3_512 + elif hash_name == "SHA-384": + return SHA384 + elif hash_name == "SHA3-384": + return SHA3_384 + elif hash_name == "SHA-256": + return SHA256 + elif hash_name == "SHA3-256": + return SHA3_256 + elif hash_name == "SHA-224": + return SHA224 + elif hash_name == "SHA3-224": + return SHA3_224 + elif hash_name == "SHA-1": + return SHA1 + else: + raise ValueError("Unknown hash algorithm: " + hash_name) + + def filter_type(group): + type_name = group["type"] + if type_name not in ("RsassaPkcs1Verify", "RsassaPkcs1Generate"): + raise ValueError("Unknown type name " + type_name) + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + filename, + "Wycheproof PKCS#1v1.5 signature (%s)" % filename, + group_tag={ + "rsa_key": filter_rsa, + "hash_mod": filter_sha, + "type": filter_type, + }, + ) + return result + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof RSA PKCS$#1 Test #" + str(tv.id) + + hashed_msg = tv.hash_module.new(tv.msg) + signer = pkcs1_15.new(tv.key) + try: + signature = signer.verify(hashed_msg, tv.sig) + except ValueError: + if tv.warning: + return + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(FIPS_PKCS1_Verify_Tests) + tests += list_test_cases(FIPS_PKCS1_Sign_Tests) + tests += list_test_cases(PKCS1_15_NoParams) + tests += list_test_cases(PKCS1_Legacy_Module_Tests) + tests += list_test_cases(PKCS1_All_Hashes_Tests) + tests += [TestVectorsWycheproof(wycheproof_warnings)] - tests = [] - tests += list_test_cases(FIPS_PKCS1_Verify_Tests) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests) - tests += list_test_cases(PKCS1_15_NoParams) - tests += list_test_cases(PKCS1_Legacy_Module_Tests) - tests += list_test_cases(PKCS1_All_Hashes_Tests) - tests += [ TestVectorsWycheproof(wycheproof_warnings) ] + if config.get("slow_tests"): + tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) + tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) - if config.get('slow_tests'): - tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) + return tests - return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_pss.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_pss.py index c3b1ce56..fbf441d5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_pss.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Signature/test_pss.py @@ -45,333 +45,362 @@ def load_hash_by_name(hash_name): - return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) + return __import__("Cryptodome.Hash." + hash_name, globals(), locals(), ["new"]) class PRNG(object): + def __init__(self, stream): + self.stream = stream + self.idx = 0 - def __init__(self, stream): - self.stream = stream - self.idx = 0 - - def __call__(self, rnd_size): - result = self.stream[self.idx:self.idx + rnd_size] - self.idx += rnd_size - return result + def __call__(self, rnd_size): + result = self.stream[self.idx : self.idx + rnd_size] + self.idx += rnd_size + return result class PSS_Tests(unittest.TestCase): - - rsa_key = b'-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAsvI34FgiTK8+txBvmooNGpNwk23YTU51dwNZi5yha3W4lA/Q\nvcZrDalkmD7ekWQwnduxVKa6pRSI13KBgeUOIqJoGXSWhntEtY3FEwvWOHW5AE7Q\njUzTzCiYT6TVaCcpa/7YLai+p6ai2g5f5Zfh4jSawa9uYeuggFygQq4IVW796MgV\nyqxYMM/arEj+/sKz3Viua9Rp9fFosertCYCX4DUTgW0mX9bwEnEOgjSI3pLOPXz1\n8vx+DRZS5wMCmwCUa0sKonLn3cAUPq+sGix7+eo7T0Z12MU8ud7IYVX/75r3cXiF\nPaYE2q8Le0kgOApIXbb+x74x0rNgyIh1yGygkwIDAQABAoIBABz4t1A0pLT6qHI2\nEIOaNz3mwhK0dZEqkz0GB1Dhtoax5ATgvKCFB98J3lYB08IBURe1snOsnMpOVUtg\naBRSM+QqnCUG6bnzKjAkuFP5liDE+oNQv1YpKp9CsUovuzdmI8Au3ewihl+ZTIN2\nUVNYMEOR1b5m+z2SSwWNOYsiJwpBrT7zkpdlDyjat7FiiPhMMIMXjhQFVxURMIcB\njUBtPzGvV/PG90cVDWi1wRGeeP1dDqti/jsnvykQ15KW1MqGrpeNKRmDdTy/Ucl1\nWIoYklKw3U456lgZ/rDTDB818+Tlnk35z4yF7d5ANPM8CKfqOPcnO1BCKVFzf4eq\n54wvUtkCgYEA1Zv2lp06l7rXMsvNtyYQjbFChezRDRnPwZmN4NCdRtTgGG1G0Ryd\nYz6WWoPGqZp0b4LAaaHd3W2GTcpXF8WXMKfMX1W+tMAxMozfsXRKMcHoypwuS5wT\nfJRXJCG4pvd57AB0iVUEJW2we+uGKU5Zxcx//id2nXGCpoRyViIplQsCgYEA1nVC\neHupHChht0Fh4N09cGqZHZzuwXjOUMzR3Vsfz+4WzVS3NvIgN4g5YgmQFOeKwo5y\niRq5yvubcNdFvf85eHWClg0zPAyxJCVUWigCrrOanGEhJo6re4idJvNVzu4Ucg0v\n6B3SJ1HsCda+ZSNz24bSyqRep8A+RoAaoVSFx5kCgYEAn3RvXPs9s+obnqWYiPF3\nRe5etE6Vt2vfNKwFxx6zaR6bsmBQjuUHcABWiHb6I71S0bMPI0tbrWGG8ibrYKl1\nNTLtUvVVCOS3VP7oNTWT9RTFTAnOXU7DFSo+6o/poWn3r36ff6zhDXeWWMr2OXtt\ndEQ1/2lCGEGVv+v61eVmmQUCgYABFHITPTwqwiFL1O5zPWnzyPWgaovhOYSAb6eW\n38CXQXGn8wdBJZL39J2lWrr4//l45VK6UgIhfYbY2JynSkO10ZGow8RARygVMILu\nOUlaK9lZdDvAf/NpGdUAvzTtZ9F+iYZ2OsA2JnlzyzsGM1l//3vMPWukmJk3ral0\nqoJJ8QKBgGRG3eVHnIegBbFVuMDp2NTcfuSuDVUQ1fGAwtPiFa8u81IodJnMk2pq\niXu2+0ytNA/M+SVrAnE2AgIzcaJbtr0p2srkuVM7KMWnG1vWFNjtXN8fAhf/joOv\nD+NmPL/N4uE57e40tbiU/H7KdyZaDt+5QiTmdhuyAe6CBjKsF2jy\n-----END RSA PRIVATE KEY-----' - msg = b'AAA' - tag = b'\x00[c5\xd8\xb0\x8b!D\x81\x83\x07\xc0\xdd\xb9\xb4\xb2`\x92\xe7\x02\xf1\xe1P\xea\xc3\xf0\xe3>\xddX5\xdd\x8e\xc5\x89\xef\xf3\xc2\xdc\xfeP\x02\x7f\x12+\xc9\xaf\xbb\xec\xfe\xb0\xa5\xb9\x08\x11P\x8fL\xee5\x9b\xb0k{=_\xd2\x14\xfb\x01R\xb7\xfe\x14}b\x03\x8d5Y\x89~}\xfc\xf2l\xd01-\xbd\xeb\x11\xcdV\x11\xe9l\x19k/o5\xa2\x0f\x15\xe7Q$\t=\xec\x1dAB\x19\xa5P\x9a\xaf\xa3G\x86"\xd6~\xf0j\xfcqkbs\x13\x84b\xe4\xbdm(\xed`\xa4F\xfb\x8f.\xe1\x8c)/_\x9eS\x98\xa4v\xb8\xdc\xfe\xf7/D\x18\x19\xb3T\x97:\xe2\x96s\xe8<\xa2\xb4\xb9\xf8/' - - def test_positive_1(self): - key = RSA.import_key(self.rsa_key) - h = SHA256.new(self.msg) - verifier = pss.new(key) - verifier.verify(h, self.tag) - - def test_negative_1(self): - key = RSA.import_key(self.rsa_key) - h = SHA256.new(self.msg + b'A') - verifier = pss.new(key) - tag = bytearray(self.tag) - self.assertRaises(ValueError, verifier.verify, h, tag) - - def test_negative_2(self): - key = RSA.import_key(self.rsa_key) - h = SHA256.new(self.msg) - verifier = pss.new(key, salt_bytes=1000) - tag = bytearray(self.tag) - self.assertRaises(ValueError, verifier.verify, h, tag) + rsa_key = b"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAsvI34FgiTK8+txBvmooNGpNwk23YTU51dwNZi5yha3W4lA/Q\nvcZrDalkmD7ekWQwnduxVKa6pRSI13KBgeUOIqJoGXSWhntEtY3FEwvWOHW5AE7Q\njUzTzCiYT6TVaCcpa/7YLai+p6ai2g5f5Zfh4jSawa9uYeuggFygQq4IVW796MgV\nyqxYMM/arEj+/sKz3Viua9Rp9fFosertCYCX4DUTgW0mX9bwEnEOgjSI3pLOPXz1\n8vx+DRZS5wMCmwCUa0sKonLn3cAUPq+sGix7+eo7T0Z12MU8ud7IYVX/75r3cXiF\nPaYE2q8Le0kgOApIXbb+x74x0rNgyIh1yGygkwIDAQABAoIBABz4t1A0pLT6qHI2\nEIOaNz3mwhK0dZEqkz0GB1Dhtoax5ATgvKCFB98J3lYB08IBURe1snOsnMpOVUtg\naBRSM+QqnCUG6bnzKjAkuFP5liDE+oNQv1YpKp9CsUovuzdmI8Au3ewihl+ZTIN2\nUVNYMEOR1b5m+z2SSwWNOYsiJwpBrT7zkpdlDyjat7FiiPhMMIMXjhQFVxURMIcB\njUBtPzGvV/PG90cVDWi1wRGeeP1dDqti/jsnvykQ15KW1MqGrpeNKRmDdTy/Ucl1\nWIoYklKw3U456lgZ/rDTDB818+Tlnk35z4yF7d5ANPM8CKfqOPcnO1BCKVFzf4eq\n54wvUtkCgYEA1Zv2lp06l7rXMsvNtyYQjbFChezRDRnPwZmN4NCdRtTgGG1G0Ryd\nYz6WWoPGqZp0b4LAaaHd3W2GTcpXF8WXMKfMX1W+tMAxMozfsXRKMcHoypwuS5wT\nfJRXJCG4pvd57AB0iVUEJW2we+uGKU5Zxcx//id2nXGCpoRyViIplQsCgYEA1nVC\neHupHChht0Fh4N09cGqZHZzuwXjOUMzR3Vsfz+4WzVS3NvIgN4g5YgmQFOeKwo5y\niRq5yvubcNdFvf85eHWClg0zPAyxJCVUWigCrrOanGEhJo6re4idJvNVzu4Ucg0v\n6B3SJ1HsCda+ZSNz24bSyqRep8A+RoAaoVSFx5kCgYEAn3RvXPs9s+obnqWYiPF3\nRe5etE6Vt2vfNKwFxx6zaR6bsmBQjuUHcABWiHb6I71S0bMPI0tbrWGG8ibrYKl1\nNTLtUvVVCOS3VP7oNTWT9RTFTAnOXU7DFSo+6o/poWn3r36ff6zhDXeWWMr2OXtt\ndEQ1/2lCGEGVv+v61eVmmQUCgYABFHITPTwqwiFL1O5zPWnzyPWgaovhOYSAb6eW\n38CXQXGn8wdBJZL39J2lWrr4//l45VK6UgIhfYbY2JynSkO10ZGow8RARygVMILu\nOUlaK9lZdDvAf/NpGdUAvzTtZ9F+iYZ2OsA2JnlzyzsGM1l//3vMPWukmJk3ral0\nqoJJ8QKBgGRG3eVHnIegBbFVuMDp2NTcfuSuDVUQ1fGAwtPiFa8u81IodJnMk2pq\niXu2+0ytNA/M+SVrAnE2AgIzcaJbtr0p2srkuVM7KMWnG1vWFNjtXN8fAhf/joOv\nD+NmPL/N4uE57e40tbiU/H7KdyZaDt+5QiTmdhuyAe6CBjKsF2jy\n-----END RSA PRIVATE KEY-----" + msg = b"AAA" + tag = b'\x00[c5\xd8\xb0\x8b!D\x81\x83\x07\xc0\xdd\xb9\xb4\xb2`\x92\xe7\x02\xf1\xe1P\xea\xc3\xf0\xe3>\xddX5\xdd\x8e\xc5\x89\xef\xf3\xc2\xdc\xfeP\x02\x7f\x12+\xc9\xaf\xbb\xec\xfe\xb0\xa5\xb9\x08\x11P\x8fL\xee5\x9b\xb0k{=_\xd2\x14\xfb\x01R\xb7\xfe\x14}b\x03\x8d5Y\x89~}\xfc\xf2l\xd01-\xbd\xeb\x11\xcdV\x11\xe9l\x19k/o5\xa2\x0f\x15\xe7Q$\t=\xec\x1dAB\x19\xa5P\x9a\xaf\xa3G\x86"\xd6~\xf0j\xfcqkbs\x13\x84b\xe4\xbdm(\xed`\xa4F\xfb\x8f.\xe1\x8c)/_\x9eS\x98\xa4v\xb8\xdc\xfe\xf7/D\x18\x19\xb3T\x97:\xe2\x96s\xe8<\xa2\xb4\xb9\xf8/' + + def test_positive_1(self): + key = RSA.import_key(self.rsa_key) + h = SHA256.new(self.msg) + verifier = pss.new(key) + verifier.verify(h, self.tag) + + def test_negative_1(self): + key = RSA.import_key(self.rsa_key) + h = SHA256.new(self.msg + b"A") + verifier = pss.new(key) + tag = bytearray(self.tag) + self.assertRaises(ValueError, verifier.verify, h, tag) + + def test_negative_2(self): + key = RSA.import_key(self.rsa_key) + h = SHA256.new(self.msg) + verifier = pss.new(key, salt_bytes=1000) + tag = bytearray(self.tag) + self.assertRaises(ValueError, verifier.verify, h, tag) class FIPS_PKCS1_Verify_Tests(unittest.TestCase): + def shortDescription(self): + return "FIPS PKCS1 Tests (Verify)" - def shortDescription(self): - return "FIPS PKCS1 Tests (Verify)" + def verify_positive(self, hashmod, message, public_key, salt, signature): + prng = PRNG(salt) + hashed = hashmod.new(message) + verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) + verifier.verify(hashed, signature) - def verify_positive(self, hashmod, message, public_key, salt, signature): - prng = PRNG(salt) - hashed = hashmod.new(message) - verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) - verifier.verify(hashed, signature) + def verify_negative(self, hashmod, message, public_key, salt, signature): + prng = PRNG(salt) + hashed = hashmod.new(message) + verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) + self.assertRaises(ValueError, verifier.verify, hashed, signature) - def verify_negative(self, hashmod, message, public_key, salt, signature): - prng = PRNG(salt) - hashed = hashmod.new(message) - verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) - self.assertRaises(ValueError, verifier.verify, hashed, signature) - - def test_can_sign(self): - test_public_key = RSA.generate(1024).public_key() - verifier = pss.new(test_public_key) - self.assertEqual(verifier.can_sign(), False) + def test_can_sign(self): + test_public_key = RSA.generate(1024).public_key() + verifier = pss.new(test_public_key) + self.assertEqual(verifier.can_sign(), False) class FIPS_PKCS1_Verify_Tests_KAT(unittest.TestCase): - pass + pass -test_vectors_verify = load_test_vectors(("Signature", "PKCS1-PSS"), - "SigVerPSS_186-3.rsp", - "Signature Verification 186-3", - {'shaalg': lambda x: x, - 'result': lambda x: x}) or [] +test_vectors_verify = ( + load_test_vectors( + ("Signature", "PKCS1-PSS"), + "SigVerPSS_186-3.rsp", + "Signature Verification 186-3", + { + "shaalg": lambda x: x, + "result": lambda x: x, + }, + ) + or [] +) for count, tv in enumerate(test_vectors_verify): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - if hasattr(tv, "p"): - continue - - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore - if tv.saltval != b("\x00"): - prng = PRNG(tv.saltval) - verifier = pss.new(public_key, salt_bytes=len(tv.saltval), rand_func=prng) - else: - verifier = pss.new(public_key, salt_bytes=0) - - def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result == 'p': - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) - else: - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) + if isinstance(tv, str): + continue + if hasattr(tv, "n"): + modulus = tv.n + continue + if hasattr(tv, "p"): + continue + + hash_module = load_hash_by_name(tv.shaalg.upper()) + hash_obj = hash_module.new(tv.msg) + public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore + if tv.saltval != b("\x00"): + prng = PRNG(tv.saltval) + verifier = pss.new(public_key, salt_bytes=len(tv.saltval), rand_func=prng) + else: + verifier = pss.new(public_key, salt_bytes=0) + + def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): + verifier.verify(hash_obj, signature) + + def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): + self.assertRaises(ValueError, verifier.verify, hash_obj, signature) + + if tv.result == "p": + setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) + else: + setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) class FIPS_PKCS1_Sign_Tests(unittest.TestCase): + def shortDescription(self): + return "FIPS PKCS1 Tests (Sign)" - def shortDescription(self): - return "FIPS PKCS1 Tests (Sign)" - - def test_can_sign(self): - test_private_key = RSA.generate(1024) - signer = pss.new(test_private_key) - self.assertEqual(signer.can_sign(), True) + def test_can_sign(self): + test_private_key = RSA.generate(1024) + signer = pss.new(test_private_key) + self.assertEqual(signer.can_sign(), True) class FIPS_PKCS1_Sign_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_sign = load_test_vectors(("Signature", "PKCS1-PSS"), - "SigGenPSS_186-2.txt", - "Signature Generation 186-2", - {'shaalg': lambda x: x}) or [] - -test_vectors_sign += load_test_vectors(("Signature", "PKCS1-PSS"), - "SigGenPSS_186-3.txt", - "Signature Generation 186-3", - {'shaalg': lambda x: x}) or [] + pass + + +test_vectors_sign = ( + load_test_vectors( + ("Signature", "PKCS1-PSS"), + "SigGenPSS_186-2.txt", + "Signature Generation 186-2", + {"shaalg": lambda x: x}, + ) + or [] +) + +test_vectors_sign += ( + load_test_vectors( + ("Signature", "PKCS1-PSS"), + "SigGenPSS_186-3.txt", + "Signature Generation 186-3", + {"shaalg": lambda x: x}, + ) + or [] +) for count, tv in enumerate(test_vectors_sign): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - if hasattr(tv, "e"): - private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore - continue - - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - if tv.saltval != b("\x00"): - prng = PRNG(tv.saltval) - signer = pss.new(private_key, salt_bytes=len(tv.saltval), rand_func=prng) - else: - signer = pss.new(private_key, salt_bytes=0) - - def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): - signature = signer.sign(hash_obj) - self.assertEqual(signature, result) - - setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) + if isinstance(tv, str): + continue + if hasattr(tv, "n"): + modulus = tv.n + continue + if hasattr(tv, "e"): + private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore + continue + + hash_module = load_hash_by_name(tv.shaalg.upper()) + hash_obj = hash_module.new(tv.msg) + if tv.saltval != b("\x00"): + prng = PRNG(tv.saltval) + signer = pss.new(private_key, salt_bytes=len(tv.saltval), rand_func=prng) + else: + signer = pss.new(private_key, salt_bytes=0) + + def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): + signature = signer.sign(hash_obj) + self.assertEqual(signature, result) + + setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) class PKCS1_Legacy_Module_Tests(unittest.TestCase): - """Verify that the legacy module Cryptodome.Signature.PKCS1_PSS - behaves as expected. The only difference is that the verify() - method returns True/False and does not raise exceptions.""" + """Verify that the legacy module Cryptodome.Signature.PKCS1_PSS + behaves as expected. The only difference is that the verify() + method returns True/False and does not raise exceptions.""" - def shortDescription(self): - return "Test legacy Cryptodome.Signature.PKCS1_PSS" + def shortDescription(self): + return "Test legacy Cryptodome.Signature.PKCS1_PSS" - def runTest(self): - key = RSA.generate(1024) - hashed = SHA1.new(b("Test")) - good_signature = PKCS1_PSS.new(key).sign(hashed) - verifier = PKCS1_PSS.new(key.public_key()) + def runTest(self): + key = RSA.generate(1024) + hashed = SHA1.new(b("Test")) + good_signature = PKCS1_PSS.new(key).sign(hashed) + verifier = PKCS1_PSS.new(key.public_key()) - self.assertEqual(verifier.verify(hashed, good_signature), True) + self.assertEqual(verifier.verify(hashed, good_signature), True) - # Flip a few bits in the signature - bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) - self.assertEqual(verifier.verify(hashed, bad_signature), False) + # Flip a few bits in the signature + bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) + self.assertEqual(verifier.verify(hashed, bad_signature), False) class PKCS1_All_Hashes_Tests(unittest.TestCase): - - def shortDescription(self): - return "Test PKCS#1 PSS signature in combination with all hashes" - - def runTest(self): - - key = RSA.generate(1280) - signer = pss.new(key) - hash_names = ("MD2", "MD4", "MD5", "RIPEMD160", "SHA1", - "SHA224", "SHA256", "SHA384", "SHA512", - "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512") - - for name in hash_names: - hashed = load_hash_by_name(name).new(b("Test")) - signer.sign(hashed) - - from Cryptodome.Hash import BLAKE2b, BLAKE2s - for hash_size in (20, 32, 48, 64): - hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b("Test")) - signer.sign(hashed_b) - for hash_size in (16, 20, 28, 32): - hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b("Test")) - signer.sign(hashed_s) + def shortDescription(self): + return "Test PKCS#1 PSS signature in combination with all hashes" + + def runTest(self): + key = RSA.generate(1280) + signer = pss.new(key) + hash_names = ( + "MD2", + "MD4", + "MD5", + "RIPEMD160", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA3_224", + "SHA3_256", + "SHA3_384", + "SHA3_512", + ) + + for name in hash_names: + hashed = load_hash_by_name(name).new(b("Test")) + signer.sign(hashed) + + from Cryptodome.Hash import BLAKE2b, BLAKE2s + + for hash_size in (20, 32, 48, 64): + hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b("Test")) + signer.sign(hashed_b) + for hash_size in (16, 20, 28, 32): + hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b("Test")) + signer.sign(hashed_s) def get_hash_module(hash_name): - if hash_name == "SHA-512": - hash_module = SHA512 - elif hash_name == "SHA-512/224": - hash_module = SHA512.new(truncate="224") - elif hash_name == "SHA-512/256": - hash_module = SHA512.new(truncate="256") - elif hash_name == "SHA-384": - hash_module = SHA384 - elif hash_name == "SHA-256": - hash_module = SHA256 - elif hash_name == "SHA-224": - hash_module = SHA224 - elif hash_name == "SHA-1": - hash_module = SHA1 - else: - raise ValueError("Unknown hash algorithm: " + hash_name) - return hash_module + if hash_name == "SHA-512": + hash_module = SHA512 + elif hash_name == "SHA-512/224": + hash_module = SHA512.new(truncate="224") + elif hash_name == "SHA-512/256": + hash_module = SHA512.new(truncate="256") + elif hash_name == "SHA-384": + hash_module = SHA384 + elif hash_name == "SHA-256": + hash_module = SHA256 + elif hash_name == "SHA-224": + hash_module = SHA224 + elif hash_name == "SHA-1": + hash_module = SHA1 + else: + raise ValueError("Unknown hash algorithm: " + hash_name) + return hash_module class TestVectorsPSSWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def add_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['keyPem']) - - def filter_sha(group): - return get_hash_module(group['sha']) - - def filter_type(group): - type_name = group['type'] - if type_name not in ("RsassaPssVerify", ): - raise ValueError("Unknown type name " + type_name) - - def filter_slen(group): - return group['sLen'] - - def filter_mgf(group): - mgf = group['mgf'] - if mgf not in ("MGF1", ): - raise ValueError("Unknown MGF " + mgf) - mgf1_hash = get_hash_module(group['mgfSha']) - - def mgf(x, y, mh=mgf1_hash): - return MGF1(x, y, mh) - - return mgf - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof PSS signature (%s)" % filename, - group_tag={'key': filter_rsa, - 'hash_module': filter_sha, - 'sLen': filter_slen, - 'mgf': filter_mgf, - 'type': filter_type}) - return result - - def setUp(self): - self.tv = [] - self.add_tests("rsa_pss_2048_sha1_mgf1_20_test.json") - self.add_tests("rsa_pss_2048_sha256_mgf1_0_test.json") - self.add_tests("rsa_pss_2048_sha256_mgf1_32_test.json") - self.add_tests("rsa_pss_2048_sha512_256_mgf1_28_test.json") - self.add_tests("rsa_pss_2048_sha512_256_mgf1_32_test.json") - self.add_tests("rsa_pss_3072_sha256_mgf1_32_test.json") - self.add_tests("rsa_pss_4096_sha256_mgf1_32_test.json") - self.add_tests("rsa_pss_4096_sha512_mgf1_32_test.json") - self.add_tests("rsa_pss_misc_test.json") - - def shortDescription(self): - return self._id - - def warn(self, tv): - if tv.warning and self._wycheproof_warnings: - import warnings - warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) - - def test_verify(self, tv): - self._id = "Wycheproof RSA PSS Test #%d (%s)" % (tv.id, tv.comment) - - hashed_msg = tv.hash_module.new(tv.msg) - signer = pss.new(tv.key, mask_func=tv.mgf, salt_bytes=tv.sLen) - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) + def __init__(self, wycheproof_warnings): + unittest.TestCase.__init__(self) + self._wycheproof_warnings = wycheproof_warnings + self._id = "None" + + def add_tests(self, filename): + def filter_rsa(group): + return RSA.import_key(group["keyPem"]) + + def filter_sha(group): + return get_hash_module(group["sha"]) + + def filter_type(group): + type_name = group["type"] + if type_name not in ("RsassaPssVerify",): + raise ValueError("Unknown type name " + type_name) + + def filter_slen(group): + return group["sLen"] + + def filter_mgf(group): + mgf = group["mgf"] + if mgf not in ("MGF1",): + raise ValueError("Unknown MGF " + mgf) + mgf1_hash = get_hash_module(group["mgfSha"]) + + def mgf(x, y, mh=mgf1_hash): + return MGF1(x, y, mh) + + return mgf + + result = load_test_vectors_wycheproof( + ("Signature", "wycheproof"), + filename, + "Wycheproof PSS signature (%s)" % filename, + group_tag={ + "key": filter_rsa, + "hash_module": filter_sha, + "sLen": filter_slen, + "mgf": filter_mgf, + "type": filter_type, + }, + ) + return result + + def setUp(self): + self.tv = [] + self.add_tests("rsa_pss_2048_sha1_mgf1_20_test.json") + self.add_tests("rsa_pss_2048_sha256_mgf1_0_test.json") + self.add_tests("rsa_pss_2048_sha256_mgf1_32_test.json") + self.add_tests("rsa_pss_2048_sha512_256_mgf1_28_test.json") + self.add_tests("rsa_pss_2048_sha512_256_mgf1_32_test.json") + self.add_tests("rsa_pss_3072_sha256_mgf1_32_test.json") + self.add_tests("rsa_pss_4096_sha256_mgf1_32_test.json") + self.add_tests("rsa_pss_4096_sha512_mgf1_32_test.json") + self.add_tests("rsa_pss_misc_test.json") + + def shortDescription(self): + return self._id + + def warn(self, tv): + if tv.warning and self._wycheproof_warnings: + import warnings + + warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment)) + + def test_verify(self, tv): + self._id = "Wycheproof RSA PSS Test #%d (%s)" % (tv.id, tv.comment) + + hashed_msg = tv.hash_module.new(tv.msg) + signer = pss.new(tv.key, mask_func=tv.mgf, salt_bytes=tv.sLen) + try: + signature = signer.verify(hashed_msg, tv.sig) + except ValueError: + if tv.warning: + return + assert not tv.valid + else: + assert tv.valid + self.warn(tv) + + def runTest(self): + for tv in self.tv: + self.test_verify(tv) def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') + wycheproof_warnings = config.get("wycheproof_warnings") + + tests = [] + tests += list_test_cases(PSS_Tests) + tests += list_test_cases(FIPS_PKCS1_Verify_Tests) + tests += list_test_cases(FIPS_PKCS1_Sign_Tests) + tests += list_test_cases(PKCS1_Legacy_Module_Tests) + tests += list_test_cases(PKCS1_All_Hashes_Tests) + + if config.get("slow_tests"): + tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) + tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) - tests = [] - tests += list_test_cases(PSS_Tests) - tests += list_test_cases(FIPS_PKCS1_Verify_Tests) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests) - tests += list_test_cases(PKCS1_Legacy_Module_Tests) - tests += list_test_cases(PKCS1_All_Hashes_Tests) + tests += [TestVectorsPSSWycheproof(wycheproof_warnings)] - if config.get('slow_tests'): - tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) + return tests - tests += [TestVectorsPSSWycheproof(wycheproof_warnings)] - return tests +if __name__ == "__main__": + def suite(): + return unittest.TestSuite(get_tests()) -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/__init__.py index e52c4901..56f5bc9d 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/__init__.py @@ -28,19 +28,34 @@ import os + def get_tests(config={}): - tests = [] - from Cryptodome.SelfTest.Util import test_number; tests += test_number.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_Counter; tests += test_Counter.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_Padding; tests += test_Padding.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_strxor; tests += test_strxor.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_asn1; tests += test_asn1.get_tests(config=config) - from Cryptodome.SelfTest.Util import test_rfc1751; tests += test_rfc1751.get_tests(config=config) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + from Cryptodome.SelfTest.Util import test_number + + tests += test_number.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_Counter + + tests += test_Counter.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_Padding + + tests += test_Padding.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_strxor + + tests += test_strxor.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_asn1 + + tests += test_asn1.get_tests(config=config) + from Cryptodome.SelfTest.Util import test_rfc1751 + + tests += test_rfc1751.get_tests(config=config) + return tests + + +if __name__ == "__main__": + import unittest + + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_Counter.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_Counter.py index 0d1e0897..b0b8560b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_Counter.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_Counter.py @@ -28,40 +28,44 @@ import unittest + class CounterTests(unittest.TestCase): - def setUp(self): - global Counter - from Cryptodome.Util import Counter + def setUp(self): + global Counter + from Cryptodome.Util import Counter + + def test_BE(self): + """Big endian""" + c = Counter.new(128) + c = Counter.new(128, little_endian=False) - def test_BE(self): - """Big endian""" - c = Counter.new(128) - c = Counter.new(128, little_endian=False) + def test_LE(self): + """Little endian""" + c = Counter.new(128, little_endian=True) - def test_LE(self): - """Little endian""" - c = Counter.new(128, little_endian=True) + def test_nbits(self): + c = Counter.new(nbits=128) + self.assertRaises(ValueError, Counter.new, 129) - def test_nbits(self): - c = Counter.new(nbits=128) - self.assertRaises(ValueError, Counter.new, 129) + def test_prefix(self): + c = Counter.new(128, prefix=b("xx")) - def test_prefix(self): - c = Counter.new(128, prefix=b("xx")) + def test_suffix(self): + c = Counter.new(128, suffix=b("xx")) - def test_suffix(self): - c = Counter.new(128, suffix=b("xx")) + def test_iv(self): + c = Counter.new(128, initial_value=2) + self.assertRaises(ValueError, Counter.new, 16, initial_value=0x1FFFF) - def test_iv(self): - c = Counter.new(128, initial_value=2) - self.assertRaises(ValueError, Counter.new, 16, initial_value=0x1FFFF) def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - return list_test_cases(CounterTests) + from Cryptodome.SelfTest.st_common import list_test_cases + + return list_test_cases(CounterTests) + -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_Padding.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_Padding.py index a9c3eb67..1d78a8ec 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_Padding.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_Padding.py @@ -38,116 +38,117 @@ from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Util.Padding import pad, unpad + class PKCS7_Tests(unittest.TestCase): + def test1(self): + padded = pad(b(""), 4) + self.assertTrue(padded == uh(b("04040404"))) + padded = pad(b(""), 4, "pkcs7") + self.assertTrue(padded == uh(b("04040404"))) + back = unpad(padded, 4) + self.assertTrue(back == b("")) + + def test2(self): + padded = pad(uh(b("12345678")), 4) + self.assertTrue(padded == uh(b("1234567804040404"))) + back = unpad(padded, 4) + self.assertTrue(back == uh(b("12345678"))) + + def test3(self): + padded = pad(uh(b("123456")), 4) + self.assertTrue(padded == uh(b("12345601"))) + back = unpad(padded, 4) + self.assertTrue(back == uh(b("123456"))) + + def test4(self): + padded = pad(uh(b("1234567890")), 4) + self.assertTrue(padded == uh(b("1234567890030303"))) + back = unpad(padded, 4) + self.assertTrue(back == uh(b("1234567890"))) + + def testn1(self): + self.assertRaises(ValueError, pad, uh(b("12")), 4, "pkcs8") + + def testn2(self): + self.assertRaises(ValueError, unpad, b("\0\0\0"), 4) + self.assertRaises(ValueError, unpad, b(""), 4) + + def testn3(self): + self.assertRaises(ValueError, unpad, b("123456\x02"), 4) + self.assertRaises(ValueError, unpad, b("123456\x00"), 4) + self.assertRaises(ValueError, unpad, b("123456\x05\x05\x05\x05\x05"), 4) - def test1(self): - padded = pad(b(""), 4) - self.assertTrue(padded == uh(b("04040404"))) - padded = pad(b(""), 4, 'pkcs7') - self.assertTrue(padded == uh(b("04040404"))) - back = unpad(padded, 4) - self.assertTrue(back == b("")) - - def test2(self): - padded = pad(uh(b("12345678")), 4) - self.assertTrue(padded == uh(b("1234567804040404"))) - back = unpad(padded, 4) - self.assertTrue(back == uh(b("12345678"))) - - def test3(self): - padded = pad(uh(b("123456")), 4) - self.assertTrue(padded == uh(b("12345601"))) - back = unpad(padded, 4) - self.assertTrue(back == uh(b("123456"))) - - def test4(self): - padded = pad(uh(b("1234567890")), 4) - self.assertTrue(padded == uh(b("1234567890030303"))) - back = unpad(padded, 4) - self.assertTrue(back == uh(b("1234567890"))) - - def testn1(self): - self.assertRaises(ValueError, pad, uh(b("12")), 4, 'pkcs8') - - def testn2(self): - self.assertRaises(ValueError, unpad, b("\0\0\0"), 4) - self.assertRaises(ValueError, unpad, b(""), 4) - - def testn3(self): - self.assertRaises(ValueError, unpad, b("123456\x02"), 4) - self.assertRaises(ValueError, unpad, b("123456\x00"), 4) - self.assertRaises(ValueError, unpad, b("123456\x05\x05\x05\x05\x05"), 4) class X923_Tests(unittest.TestCase): + def test1(self): + padded = pad(b(""), 4, "x923") + self.assertTrue(padded == uh(b("00000004"))) + back = unpad(padded, 4, "x923") + self.assertTrue(back == b("")) + + def test2(self): + padded = pad(uh(b("12345678")), 4, "x923") + self.assertTrue(padded == uh(b("1234567800000004"))) + back = unpad(padded, 4, "x923") + self.assertTrue(back == uh(b("12345678"))) + + def test3(self): + padded = pad(uh(b("123456")), 4, "x923") + self.assertTrue(padded == uh(b("12345601"))) + back = unpad(padded, 4, "x923") + self.assertTrue(back == uh(b("123456"))) + + def test4(self): + padded = pad(uh(b("1234567890")), 4, "x923") + self.assertTrue(padded == uh(b("1234567890000003"))) + back = unpad(padded, 4, "x923") + self.assertTrue(back == uh(b("1234567890"))) + + def testn1(self): + self.assertRaises(ValueError, unpad, b("123456\x02"), 4, "x923") + self.assertRaises(ValueError, unpad, b("123456\x00"), 4, "x923") + self.assertRaises(ValueError, unpad, b("123456\x00\x00\x00\x00\x05"), 4, "x923") + self.assertRaises(ValueError, unpad, b(""), 4, "x923") - def test1(self): - padded = pad(b(""), 4, 'x923') - self.assertTrue(padded == uh(b("00000004"))) - back = unpad(padded, 4, 'x923') - self.assertTrue(back == b("")) - - def test2(self): - padded = pad(uh(b("12345678")), 4, 'x923') - self.assertTrue(padded == uh(b("1234567800000004"))) - back = unpad(padded, 4, 'x923') - self.assertTrue(back == uh(b("12345678"))) - - def test3(self): - padded = pad(uh(b("123456")), 4, 'x923') - self.assertTrue(padded == uh(b("12345601"))) - back = unpad(padded, 4, 'x923') - self.assertTrue(back == uh(b("123456"))) - - def test4(self): - padded = pad(uh(b("1234567890")), 4, 'x923') - self.assertTrue(padded == uh(b("1234567890000003"))) - back = unpad(padded, 4, 'x923') - self.assertTrue(back == uh(b("1234567890"))) - - def testn1(self): - self.assertRaises(ValueError, unpad, b("123456\x02"), 4, 'x923') - self.assertRaises(ValueError, unpad, b("123456\x00"), 4, 'x923') - self.assertRaises(ValueError, unpad, b("123456\x00\x00\x00\x00\x05"), 4, 'x923') - self.assertRaises(ValueError, unpad, b(""), 4, 'x923') class ISO7816_Tests(unittest.TestCase): + def test1(self): + padded = pad(b(""), 4, "iso7816") + self.assertTrue(padded == uh(b("80000000"))) + back = unpad(padded, 4, "iso7816") + self.assertTrue(back == b("")) + + def test2(self): + padded = pad(uh(b("12345678")), 4, "iso7816") + self.assertTrue(padded == uh(b("1234567880000000"))) + back = unpad(padded, 4, "iso7816") + self.assertTrue(back == uh(b("12345678"))) + + def test3(self): + padded = pad(uh(b("123456")), 4, "iso7816") + self.assertTrue(padded == uh(b("12345680"))) + back = unpad(padded, 4, "iso7816") + self.assertTrue(back == uh(b("123456"))) + + def test4(self): + padded = pad(uh(b("1234567890")), 4, "iso7816") + self.assertTrue(padded == uh(b("1234567890800000"))) + back = unpad(padded, 4, "iso7816") + self.assertTrue(back == uh(b("1234567890"))) + + def testn1(self): + self.assertRaises(ValueError, unpad, b("123456\x81"), 4, "iso7816") + self.assertRaises(ValueError, unpad, b(""), 4, "iso7816") - def test1(self): - padded = pad(b(""), 4, 'iso7816') - self.assertTrue(padded == uh(b("80000000"))) - back = unpad(padded, 4, 'iso7816') - self.assertTrue(back == b("")) - - def test2(self): - padded = pad(uh(b("12345678")), 4, 'iso7816') - self.assertTrue(padded == uh(b("1234567880000000"))) - back = unpad(padded, 4, 'iso7816') - self.assertTrue(back == uh(b("12345678"))) - - def test3(self): - padded = pad(uh(b("123456")), 4, 'iso7816') - self.assertTrue(padded == uh(b("12345680"))) - back = unpad(padded, 4, 'iso7816') - self.assertTrue(back == uh(b("123456"))) - - def test4(self): - padded = pad(uh(b("1234567890")), 4, 'iso7816') - self.assertTrue(padded == uh(b("1234567890800000"))) - back = unpad(padded, 4, 'iso7816') - self.assertTrue(back == uh(b("1234567890"))) - - def testn1(self): - self.assertRaises(ValueError, unpad, b("123456\x81"), 4, 'iso7816') - self.assertRaises(ValueError, unpad, b(""), 4, 'iso7816') def get_tests(config={}): - tests = [] - tests += list_test_cases(PKCS7_Tests) - tests += list_test_cases(X923_Tests) - tests += list_test_cases(ISO7816_Tests) - return tests + tests = [] + tests += list_test_cases(PKCS7_Tests) + tests += list_test_cases(X923_Tests) + tests += list_test_cases(ISO7816_Tests) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_asn1.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_asn1.py index 811ac843..82409619 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_asn1.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_asn1.py @@ -36,816 +36,838 @@ import unittest from Cryptodome.Util.py3compat import * -from Cryptodome.Util.asn1 import (DerObject, DerSetOf, DerInteger, - DerBitString, - DerObjectId, DerNull, DerOctetString, - DerSequence, DerBoolean) +from Cryptodome.Util.asn1 import ( + DerObject, + DerSetOf, + DerInteger, + DerBitString, + DerObjectId, + DerNull, + DerOctetString, + DerSequence, + DerBoolean, +) + class DerObjectTests(unittest.TestCase): + def testObjInit1(self): + # Fail with invalid tag format (must be 1 byte) + self.assertRaises(ValueError, DerObject, b("\x00\x99")) + # Fail with invalid implicit tag (must be <0x1F) + self.assertRaises(ValueError, DerObject, 0x1F) + + # ------ + + def testObjEncode1(self): + # No payload + der = DerObject(b("\x02")) + self.assertEqual(der.encode(), b("\x02\x00")) + # Small payload (primitive) + der.payload = b("\x45") + self.assertEqual(der.encode(), b("\x02\x01\x45")) + # Invariant + self.assertEqual(der.encode(), b("\x02\x01\x45")) + # Initialize with numerical tag + der = DerObject(0x04) + der.payload = b("\x45") + self.assertEqual(der.encode(), b("\x04\x01\x45")) + # Initialize with constructed type + der = DerObject(b("\x10"), constructed=True) + self.assertEqual(der.encode(), b("\x30\x00")) + + def testObjEncode2(self): + # Initialize with payload + der = DerObject(0x03, b("\x12\x12")) + self.assertEqual(der.encode(), b("\x03\x02\x12\x12")) + + def testObjEncode3(self): + # Long payload + der = DerObject(b("\x10")) + der.payload = b("0") * 128 + self.assertEqual(der.encode(), b("\x10\x81\x80" + "0" * 128)) + + def testObjEncode4(self): + # Implicit tags (constructed) + der = DerObject(0x10, implicit=1, constructed=True) + der.payload = b("ppll") + self.assertEqual(der.encode(), b("\xa1\x04ppll")) + # Implicit tags (primitive) + der = DerObject(0x02, implicit=0x1E, constructed=False) + der.payload = b("ppll") + self.assertEqual(der.encode(), b("\x9e\x04ppll")) + + def testObjEncode5(self): + # Encode type with explicit tag + der = DerObject(0x10, explicit=5) + der.payload = b("xxll") + self.assertEqual(der.encode(), b("\xa5\x06\x10\x04xxll")) + + # ----- + + def testObjDecode1(self): + # Decode short payload + der = DerObject(0x02) + der.decode(b("\x02\x02\x01\x02")) + self.assertEqual(der.payload, b("\x01\x02")) + self.assertEqual(der._tag_octet, 0x02) + + def testObjDecode2(self): + # Decode long payload + der = DerObject(0x02) + der.decode(b("\x02\x81\x80" + "1" * 128)) + self.assertEqual(der.payload, b("1") * 128) + self.assertEqual(der._tag_octet, 0x02) + + def testObjDecode3(self): + # Decode payload with too much data gives error + der = DerObject(0x02) + self.assertRaises(ValueError, der.decode, b("\x02\x02\x01\x02\xff")) + # Decode payload with too little data gives error + der = DerObject(0x02) + self.assertRaises(ValueError, der.decode, b("\x02\x02\x01")) + + def testObjDecode4(self): + # Decode implicit tag (primitive) + der = DerObject(0x02, constructed=False, implicit=0xF) + self.assertRaises(ValueError, der.decode, b("\x02\x02\x01\x02")) + der.decode(b("\x8f\x01\x00")) + self.assertEqual(der.payload, b("\x00")) + # Decode implicit tag (constructed) + der = DerObject(0x02, constructed=True, implicit=0xF) + self.assertRaises(ValueError, der.decode, b("\x02\x02\x01\x02")) + der.decode(b("\xaf\x01\x00")) + self.assertEqual(der.payload, b("\x00")) + + def testObjDecode5(self): + # Decode payload with unexpected tag gives error + der = DerObject(0x02) + self.assertRaises(ValueError, der.decode, b("\x03\x02\x01\x02")) + + def testObjDecode6(self): + # Arbitrary DER object + der = DerObject() + der.decode(b("\x65\x01\x88")) + self.assertEqual(der._tag_octet, 0x65) + self.assertEqual(der.payload, b("\x88")) + + def testObjDecode7(self): + # Decode explicit tag + der = DerObject(0x10, explicit=5) + der.decode(b("\xa5\x06\x10\x04xxll")) + self.assertEqual(der._inner_tag_octet, 0x10) + self.assertEqual(der.payload, b("xxll")) + + # Explicit tag may be 0 + der = DerObject(0x10, explicit=0) + der.decode(b("\xa0\x06\x10\x04xxll")) + self.assertEqual(der._inner_tag_octet, 0x10) + self.assertEqual(der.payload, b("xxll")) + + def testObjDecode8(self): + # Verify that decode returns the object + der = DerObject(0x02) + self.assertEqual(der, der.decode(b("\x02\x02\x01\x02"))) - def testObjInit1(self): - # Fail with invalid tag format (must be 1 byte) - self.assertRaises(ValueError, DerObject, b('\x00\x99')) - # Fail with invalid implicit tag (must be <0x1F) - self.assertRaises(ValueError, DerObject, 0x1F) - - # ------ - - def testObjEncode1(self): - # No payload - der = DerObject(b('\x02')) - self.assertEqual(der.encode(), b('\x02\x00')) - # Small payload (primitive) - der.payload = b('\x45') - self.assertEqual(der.encode(), b('\x02\x01\x45')) - # Invariant - self.assertEqual(der.encode(), b('\x02\x01\x45')) - # Initialize with numerical tag - der = DerObject(0x04) - der.payload = b('\x45') - self.assertEqual(der.encode(), b('\x04\x01\x45')) - # Initialize with constructed type - der = DerObject(b('\x10'), constructed=True) - self.assertEqual(der.encode(), b('\x30\x00')) - - def testObjEncode2(self): - # Initialize with payload - der = DerObject(0x03, b('\x12\x12')) - self.assertEqual(der.encode(), b('\x03\x02\x12\x12')) - - def testObjEncode3(self): - # Long payload - der = DerObject(b('\x10')) - der.payload = b("0")*128 - self.assertEqual(der.encode(), b('\x10\x81\x80' + "0"*128)) - - def testObjEncode4(self): - # Implicit tags (constructed) - der = DerObject(0x10, implicit=1, constructed=True) - der.payload = b('ppll') - self.assertEqual(der.encode(), b('\xa1\x04ppll')) - # Implicit tags (primitive) - der = DerObject(0x02, implicit=0x1E, constructed=False) - der.payload = b('ppll') - self.assertEqual(der.encode(), b('\x9E\x04ppll')) - - def testObjEncode5(self): - # Encode type with explicit tag - der = DerObject(0x10, explicit=5) - der.payload = b("xxll") - self.assertEqual(der.encode(), b("\xa5\x06\x10\x04xxll")) - - # ----- - - def testObjDecode1(self): - # Decode short payload - der = DerObject(0x02) - der.decode(b('\x02\x02\x01\x02')) - self.assertEqual(der.payload, b("\x01\x02")) - self.assertEqual(der._tag_octet, 0x02) - - def testObjDecode2(self): - # Decode long payload - der = DerObject(0x02) - der.decode(b('\x02\x81\x80' + "1"*128)) - self.assertEqual(der.payload, b("1")*128) - self.assertEqual(der._tag_octet, 0x02) - - def testObjDecode3(self): - # Decode payload with too much data gives error - der = DerObject(0x02) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02\xFF')) - # Decode payload with too little data gives error - der = DerObject(0x02) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01')) - - def testObjDecode4(self): - # Decode implicit tag (primitive) - der = DerObject(0x02, constructed=False, implicit=0xF) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02')) - der.decode(b('\x8F\x01\x00')) - self.assertEqual(der.payload, b('\x00')) - # Decode implicit tag (constructed) - der = DerObject(0x02, constructed=True, implicit=0xF) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02')) - der.decode(b('\xAF\x01\x00')) - self.assertEqual(der.payload, b('\x00')) - - def testObjDecode5(self): - # Decode payload with unexpected tag gives error - der = DerObject(0x02) - self.assertRaises(ValueError, der.decode, b('\x03\x02\x01\x02')) - - def testObjDecode6(self): - # Arbitrary DER object - der = DerObject() - der.decode(b('\x65\x01\x88')) - self.assertEqual(der._tag_octet, 0x65) - self.assertEqual(der.payload, b('\x88')) - - def testObjDecode7(self): - # Decode explicit tag - der = DerObject(0x10, explicit=5) - der.decode(b("\xa5\x06\x10\x04xxll")) - self.assertEqual(der._inner_tag_octet, 0x10) - self.assertEqual(der.payload, b('xxll')) - - # Explicit tag may be 0 - der = DerObject(0x10, explicit=0) - der.decode(b("\xa0\x06\x10\x04xxll")) - self.assertEqual(der._inner_tag_octet, 0x10) - self.assertEqual(der.payload, b('xxll')) - - def testObjDecode8(self): - # Verify that decode returns the object - der = DerObject(0x02) - self.assertEqual(der, der.decode(b('\x02\x02\x01\x02'))) class DerIntegerTests(unittest.TestCase): - - def testInit1(self): - der = DerInteger(1) - self.assertEqual(der.encode(), b('\x02\x01\x01')) - - def testEncode1(self): - # Single-byte integers - # Value 0 - der = DerInteger(0) - self.assertEqual(der.encode(), b('\x02\x01\x00')) - # Value 1 - der = DerInteger(1) - self.assertEqual(der.encode(), b('\x02\x01\x01')) - # Value 127 - der = DerInteger(127) - self.assertEqual(der.encode(), b('\x02\x01\x7F')) - - def testEncode2(self): - # Multi-byte integers - # Value 128 - der = DerInteger(128) - self.assertEqual(der.encode(), b('\x02\x02\x00\x80')) - # Value 0x180 - der = DerInteger(0x180) - self.assertEqual(der.encode(), b('\x02\x02\x01\x80')) - # One very long integer - der = DerInteger(2**2048) - self.assertEqual(der.encode(), - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - - def testEncode3(self): - # Negative integers - # Value -1 - der = DerInteger(-1) - self.assertEqual(der.encode(), b('\x02\x01\xFF')) - # Value -128 - der = DerInteger(-128) - self.assertEqual(der.encode(), b('\x02\x01\x80')) - # Value - der = DerInteger(-87873) - self.assertEqual(der.encode(), b('\x02\x03\xFE\xA8\xBF')) - - def testEncode4(self): - # Explicit encoding - number = DerInteger(0x34, explicit=3) - self.assertEqual(number.encode(), b('\xa3\x03\x02\x01\x34')) - - # ----- - - def testDecode1(self): - # Single-byte integer - der = DerInteger() - # Value 0 - der.decode(b('\x02\x01\x00')) - self.assertEqual(der.value, 0) - # Value 1 - der.decode(b('\x02\x01\x01')) - self.assertEqual(der.value, 1) - # Value 127 - der.decode(b('\x02\x01\x7F')) - self.assertEqual(der.value, 127) - - def testDecode2(self): - # Multi-byte integer - der = DerInteger() - # Value 0x180L - der.decode(b('\x02\x02\x01\x80')) - self.assertEqual(der.value,0x180) - # One very long integer - der.decode( - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - self.assertEqual(der.value,2**2048) - - def testDecode3(self): - # Negative integer - der = DerInteger() - # Value -1 - der.decode(b('\x02\x01\xFF')) - self.assertEqual(der.value, -1) - # Value -32768 - der.decode(b('\x02\x02\x80\x00')) - self.assertEqual(der.value, -32768) - - def testDecode5(self): - # We still accept BER integer format - der = DerInteger() - # Redundant leading zeroes - der.decode(b('\x02\x02\x00\x01')) - self.assertEqual(der.value, 1) - # Redundant leading 0xFF - der.decode(b('\x02\x02\xFF\xFF')) - self.assertEqual(der.value, -1) - # Empty payload - der.decode(b('\x02\x00')) - self.assertEqual(der.value, 0) - - def testDecode6(self): - # Explicit encoding - number = DerInteger(explicit=3) - number.decode(b('\xa3\x03\x02\x01\x34')) - self.assertEqual(number.value, 0x34) - - def testDecode7(self): - # Verify decode returns the DerInteger - der = DerInteger() - self.assertEqual(der, der.decode(b('\x02\x01\x7F'))) - - ### - - def testStrict1(self): - number = DerInteger() - - number.decode(b'\x02\x02\x00\x01') - number.decode(b'\x02\x02\x00\x7F') - self.assertRaises(ValueError, number.decode, b'\x02\x02\x00\x01', strict=True) - self.assertRaises(ValueError, number.decode, b'\x02\x02\x00\x7F', strict=True) - - ### - - def testErrDecode1(self): - # Wide length field - der = DerInteger() - self.assertRaises(ValueError, der.decode, b('\x02\x81\x01\x01')) + def testInit1(self): + der = DerInteger(1) + self.assertEqual(der.encode(), b("\x02\x01\x01")) + + def testEncode1(self): + # Single-byte integers + # Value 0 + der = DerInteger(0) + self.assertEqual(der.encode(), b("\x02\x01\x00")) + # Value 1 + der = DerInteger(1) + self.assertEqual(der.encode(), b("\x02\x01\x01")) + # Value 127 + der = DerInteger(127) + self.assertEqual(der.encode(), b("\x02\x01\x7f")) + + def testEncode2(self): + # Multi-byte integers + # Value 128 + der = DerInteger(128) + self.assertEqual(der.encode(), b("\x02\x02\x00\x80")) + # Value 0x180 + der = DerInteger(0x180) + self.assertEqual(der.encode(), b("\x02\x02\x01\x80")) + # One very long integer + der = DerInteger(2**2048) + self.assertEqual( + der.encode(), + b("\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + ) + + def testEncode3(self): + # Negative integers + # Value -1 + der = DerInteger(-1) + self.assertEqual(der.encode(), b("\x02\x01\xff")) + # Value -128 + der = DerInteger(-128) + self.assertEqual(der.encode(), b("\x02\x01\x80")) + # Value + der = DerInteger(-87873) + self.assertEqual(der.encode(), b("\x02\x03\xfe\xa8\xbf")) + + def testEncode4(self): + # Explicit encoding + number = DerInteger(0x34, explicit=3) + self.assertEqual(number.encode(), b("\xa3\x03\x02\x01\x34")) + + # ----- + + def testDecode1(self): + # Single-byte integer + der = DerInteger() + # Value 0 + der.decode(b("\x02\x01\x00")) + self.assertEqual(der.value, 0) + # Value 1 + der.decode(b("\x02\x01\x01")) + self.assertEqual(der.value, 1) + # Value 127 + der.decode(b("\x02\x01\x7f")) + self.assertEqual(der.value, 127) + + def testDecode2(self): + # Multi-byte integer + der = DerInteger() + # Value 0x180L + der.decode(b("\x02\x02\x01\x80")) + self.assertEqual(der.value, 0x180) + # One very long integer + der.decode( + b("\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + ) + self.assertEqual(der.value, 2**2048) + + def testDecode3(self): + # Negative integer + der = DerInteger() + # Value -1 + der.decode(b("\x02\x01\xff")) + self.assertEqual(der.value, -1) + # Value -32768 + der.decode(b("\x02\x02\x80\x00")) + self.assertEqual(der.value, -32768) + + def testDecode5(self): + # We still accept BER integer format + der = DerInteger() + # Redundant leading zeroes + der.decode(b("\x02\x02\x00\x01")) + self.assertEqual(der.value, 1) + # Redundant leading 0xFF + der.decode(b("\x02\x02\xff\xff")) + self.assertEqual(der.value, -1) + # Empty payload + der.decode(b("\x02\x00")) + self.assertEqual(der.value, 0) + + def testDecode6(self): + # Explicit encoding + number = DerInteger(explicit=3) + number.decode(b("\xa3\x03\x02\x01\x34")) + self.assertEqual(number.value, 0x34) + + def testDecode7(self): + # Verify decode returns the DerInteger + der = DerInteger() + self.assertEqual(der, der.decode(b("\x02\x01\x7f"))) + + ### + + def testStrict1(self): + number = DerInteger() + + number.decode(b"\x02\x02\x00\x01") + number.decode(b"\x02\x02\x00\x7f") + self.assertRaises(ValueError, number.decode, b"\x02\x02\x00\x01", strict=True) + self.assertRaises(ValueError, number.decode, b"\x02\x02\x00\x7f", strict=True) + + ### + + def testErrDecode1(self): + # Wide length field + der = DerInteger() + self.assertRaises(ValueError, der.decode, b("\x02\x81\x01\x01")) class DerSequenceTests(unittest.TestCase): - - def testInit1(self): - der = DerSequence([1, DerInteger(2), b('0\x00')]) - self.assertEqual(der.encode(), b('0\x08\x02\x01\x01\x02\x01\x020\x00')) - - def testEncode1(self): - # Empty sequence - der = DerSequence() - self.assertEqual(der.encode(), b('0\x00')) - self.assertFalse(der.hasOnlyInts()) - # One single-byte integer (zero) - der.append(0) - self.assertEqual(der.encode(), b('0\x03\x02\x01\x00')) - self.assertEqual(der.hasInts(),1) - self.assertEqual(der.hasInts(False),1) - self.assertTrue(der.hasOnlyInts()) - self.assertTrue(der.hasOnlyInts(False)) - # Invariant - self.assertEqual(der.encode(), b('0\x03\x02\x01\x00')) - - def testEncode2(self): - # Indexing - der = DerSequence() - der.append(0) - der[0] = 1 - self.assertEqual(len(der),1) - self.assertEqual(der[0],1) - self.assertEqual(der[-1],1) - self.assertEqual(der.encode(), b('0\x03\x02\x01\x01')) - # - der[:] = [1] - self.assertEqual(len(der),1) - self.assertEqual(der[0],1) - self.assertEqual(der.encode(), b('0\x03\x02\x01\x01')) - - def testEncode3(self): - # One multi-byte integer (non-zero) - der = DerSequence() - der.append(0x180) - self.assertEqual(der.encode(), b('0\x04\x02\x02\x01\x80')) - - def testEncode4(self): - # One very long integer - der = DerSequence() - der.append(2**2048) - self.assertEqual(der.encode(), b('0\x82\x01\x05')+ - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - - def testEncode5(self): - der = DerSequence() - der += 1 - der += b('\x30\x00') - self.assertEqual(der.encode(), b('\x30\x05\x02\x01\x01\x30\x00')) - - def testEncode6(self): - # Two positive integers - der = DerSequence() - der.append(0x180) - der.append(0xFF) - self.assertEqual(der.encode(), b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')) - self.assertTrue(der.hasOnlyInts()) - self.assertTrue(der.hasOnlyInts(False)) - # Two mixed integers - der = DerSequence() - der.append(2) - der.append(-2) - self.assertEqual(der.encode(), b('0\x06\x02\x01\x02\x02\x01\xFE')) - self.assertEqual(der.hasInts(), 1) - self.assertEqual(der.hasInts(False), 2) - self.assertFalse(der.hasOnlyInts()) - self.assertTrue(der.hasOnlyInts(False)) - # - der.append(0x01) - der[1:] = [9,8] - self.assertEqual(len(der),3) - self.assertEqual(der[1:],[9,8]) - self.assertEqual(der[1:-1],[9]) - self.assertEqual(der.encode(), b('0\x09\x02\x01\x02\x02\x01\x09\x02\x01\x08')) - - def testEncode7(self): - # One integer and another type (already encoded) - der = DerSequence() - der.append(0x180) - der.append(b('0\x03\x02\x01\x05')) - self.assertEqual(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05')) - self.assertFalse(der.hasOnlyInts()) - - def testEncode8(self): - # One integer and another type (yet to encode) - der = DerSequence() - der.append(0x180) - der.append(DerSequence([5])) - self.assertEqual(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05')) - self.assertFalse(der.hasOnlyInts()) - - #### - - def testDecode1(self): - # Empty sequence - der = DerSequence() - der.decode(b('0\x00')) - self.assertEqual(len(der),0) - # One single-byte integer (zero) - der.decode(b('0\x03\x02\x01\x00')) - self.assertEqual(len(der),1) - self.assertEqual(der[0],0) - # Invariant - der.decode(b('0\x03\x02\x01\x00')) - self.assertEqual(len(der),1) - self.assertEqual(der[0],0) - - def testDecode2(self): - # One single-byte integer (non-zero) - der = DerSequence() - der.decode(b('0\x03\x02\x01\x7f')) - self.assertEqual(len(der),1) - self.assertEqual(der[0],127) - - def testDecode4(self): - # One very long integer - der = DerSequence() - der.decode(b('0\x82\x01\x05')+ - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - self.assertEqual(len(der),1) - self.assertEqual(der[0],2**2048) - - def testDecode6(self): - # Two integers - der = DerSequence() - der.decode(b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')) - self.assertEqual(len(der),2) - self.assertEqual(der[0],0x180) - self.assertEqual(der[1],0xFF) - - def testDecode7(self): - # One integer and 2 other types - der = DerSequence() - der.decode(b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')) - self.assertEqual(len(der),3) - self.assertEqual(der[0],0x180) - self.assertEqual(der[1],b('\x24\x02\xb6\x63')) - self.assertEqual(der[2],b('\x12\x00')) - - def testDecode8(self): - # Only 2 other types - der = DerSequence() - der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00')) - self.assertEqual(len(der),2) - self.assertEqual(der[0],b('\x24\x02\xb6\x63')) - self.assertEqual(der[1],b('\x12\x00')) - self.assertEqual(der.hasInts(), 0) - self.assertEqual(der.hasInts(False), 0) - self.assertFalse(der.hasOnlyInts()) - self.assertFalse(der.hasOnlyInts(False)) - - def testDecode9(self): - # Verify that decode returns itself - der = DerSequence() - self.assertEqual(der, der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00'))) - - ### - - def testErrDecode1(self): - # Not a sequence - der = DerSequence() - self.assertRaises(ValueError, der.decode, b('')) - self.assertRaises(ValueError, der.decode, b('\x00')) - self.assertRaises(ValueError, der.decode, b('\x30')) - - def testErrDecode2(self): - der = DerSequence() - # Too much data - self.assertRaises(ValueError, der.decode, b('\x30\x00\x00')) - - def testErrDecode3(self): - # Wrong length format - der = DerSequence() - # Missing length in sub-item - self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x01\x01\x00')) - # Valid BER, but invalid DER length - self.assertRaises(ValueError, der.decode, b('\x30\x81\x03\x02\x01\x01')) - self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x81\x01\x01')) - - def test_expected_nr_elements(self): - der_bin = DerSequence([1, 2, 3]).encode() - - DerSequence().decode(der_bin, nr_elements=3) - DerSequence().decode(der_bin, nr_elements=(2,3)) - self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=1) - self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=(4,5)) - - def test_expected_only_integers(self): - - der_bin1 = DerSequence([1, 2, 3]).encode() - der_bin2 = DerSequence([1, 2, DerSequence([3, 4])]).encode() - - DerSequence().decode(der_bin1, only_ints_expected=True) - DerSequence().decode(der_bin1, only_ints_expected=False) - DerSequence().decode(der_bin2, only_ints_expected=False) - self.assertRaises(ValueError, DerSequence().decode, der_bin2, only_ints_expected=True) + def testInit1(self): + der = DerSequence([1, DerInteger(2), b("0\x00")]) + self.assertEqual(der.encode(), b("0\x08\x02\x01\x01\x02\x01\x020\x00")) + + def testEncode1(self): + # Empty sequence + der = DerSequence() + self.assertEqual(der.encode(), b("0\x00")) + self.assertFalse(der.hasOnlyInts()) + # One single-byte integer (zero) + der.append(0) + self.assertEqual(der.encode(), b("0\x03\x02\x01\x00")) + self.assertEqual(der.hasInts(), 1) + self.assertEqual(der.hasInts(False), 1) + self.assertTrue(der.hasOnlyInts()) + self.assertTrue(der.hasOnlyInts(False)) + # Invariant + self.assertEqual(der.encode(), b("0\x03\x02\x01\x00")) + + def testEncode2(self): + # Indexing + der = DerSequence() + der.append(0) + der[0] = 1 + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 1) + self.assertEqual(der[-1], 1) + self.assertEqual(der.encode(), b("0\x03\x02\x01\x01")) + # + der[:] = [1] + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 1) + self.assertEqual(der.encode(), b("0\x03\x02\x01\x01")) + + def testEncode3(self): + # One multi-byte integer (non-zero) + der = DerSequence() + der.append(0x180) + self.assertEqual(der.encode(), b("0\x04\x02\x02\x01\x80")) + + def testEncode4(self): + # One very long integer + der = DerSequence() + der.append(2**2048) + self.assertEqual( + der.encode(), + b("0\x82\x01\x05") + + b("\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + ) + + def testEncode5(self): + der = DerSequence() + der += 1 + der += b("\x30\x00") + self.assertEqual(der.encode(), b("\x30\x05\x02\x01\x01\x30\x00")) + + def testEncode6(self): + # Two positive integers + der = DerSequence() + der.append(0x180) + der.append(0xFF) + self.assertEqual(der.encode(), b("0\x08\x02\x02\x01\x80\x02\x02\x00\xff")) + self.assertTrue(der.hasOnlyInts()) + self.assertTrue(der.hasOnlyInts(False)) + # Two mixed integers + der = DerSequence() + der.append(2) + der.append(-2) + self.assertEqual(der.encode(), b("0\x06\x02\x01\x02\x02\x01\xfe")) + self.assertEqual(der.hasInts(), 1) + self.assertEqual(der.hasInts(False), 2) + self.assertFalse(der.hasOnlyInts()) + self.assertTrue(der.hasOnlyInts(False)) + # + der.append(0x01) + der[1:] = [9, 8] + self.assertEqual(len(der), 3) + self.assertEqual(der[1:], [9, 8]) + self.assertEqual(der[1:-1], [9]) + self.assertEqual(der.encode(), b("0\x09\x02\x01\x02\x02\x01\x09\x02\x01\x08")) + + def testEncode7(self): + # One integer and another type (already encoded) + der = DerSequence() + der.append(0x180) + der.append(b("0\x03\x02\x01\x05")) + self.assertEqual(der.encode(), b("0\x09\x02\x02\x01\x800\x03\x02\x01\x05")) + self.assertFalse(der.hasOnlyInts()) + + def testEncode8(self): + # One integer and another type (yet to encode) + der = DerSequence() + der.append(0x180) + der.append(DerSequence([5])) + self.assertEqual(der.encode(), b("0\x09\x02\x02\x01\x800\x03\x02\x01\x05")) + self.assertFalse(der.hasOnlyInts()) + + #### + + def testDecode1(self): + # Empty sequence + der = DerSequence() + der.decode(b("0\x00")) + self.assertEqual(len(der), 0) + # One single-byte integer (zero) + der.decode(b("0\x03\x02\x01\x00")) + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 0) + # Invariant + der.decode(b("0\x03\x02\x01\x00")) + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 0) + + def testDecode2(self): + # One single-byte integer (non-zero) + der = DerSequence() + der.decode(b("0\x03\x02\x01\x7f")) + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 127) + + def testDecode4(self): + # One very long integer + der = DerSequence() + der.decode( + b("0\x82\x01\x05") + + b("\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + b("\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + ) + self.assertEqual(len(der), 1) + self.assertEqual(der[0], 2**2048) + + def testDecode6(self): + # Two integers + der = DerSequence() + der.decode(b("0\x08\x02\x02\x01\x80\x02\x02\x00\xff")) + self.assertEqual(len(der), 2) + self.assertEqual(der[0], 0x180) + self.assertEqual(der[1], 0xFF) + + def testDecode7(self): + # One integer and 2 other types + der = DerSequence() + der.decode(b("0\x0a\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00")) + self.assertEqual(len(der), 3) + self.assertEqual(der[0], 0x180) + self.assertEqual(der[1], b("\x24\x02\xb6\x63")) + self.assertEqual(der[2], b("\x12\x00")) + + def testDecode8(self): + # Only 2 other types + der = DerSequence() + der.decode(b("0\x06\x24\x02\xb6\x63\x12\x00")) + self.assertEqual(len(der), 2) + self.assertEqual(der[0], b("\x24\x02\xb6\x63")) + self.assertEqual(der[1], b("\x12\x00")) + self.assertEqual(der.hasInts(), 0) + self.assertEqual(der.hasInts(False), 0) + self.assertFalse(der.hasOnlyInts()) + self.assertFalse(der.hasOnlyInts(False)) + + def testDecode9(self): + # Verify that decode returns itself + der = DerSequence() + self.assertEqual(der, der.decode(b("0\x06\x24\x02\xb6\x63\x12\x00"))) + + ### + + def testErrDecode1(self): + # Not a sequence + der = DerSequence() + self.assertRaises(ValueError, der.decode, b("")) + self.assertRaises(ValueError, der.decode, b("\x00")) + self.assertRaises(ValueError, der.decode, b("\x30")) + + def testErrDecode2(self): + der = DerSequence() + # Too much data + self.assertRaises(ValueError, der.decode, b("\x30\x00\x00")) + + def testErrDecode3(self): + # Wrong length format + der = DerSequence() + # Missing length in sub-item + self.assertRaises(ValueError, der.decode, b("\x30\x04\x02\x01\x01\x00")) + # Valid BER, but invalid DER length + self.assertRaises(ValueError, der.decode, b("\x30\x81\x03\x02\x01\x01")) + self.assertRaises(ValueError, der.decode, b("\x30\x04\x02\x81\x01\x01")) + + def test_expected_nr_elements(self): + der_bin = DerSequence([1, 2, 3]).encode() + + DerSequence().decode(der_bin, nr_elements=3) + DerSequence().decode(der_bin, nr_elements=(2, 3)) + self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=1) + self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=(4, 5)) + + def test_expected_only_integers(self): + der_bin1 = DerSequence([1, 2, 3]).encode() + der_bin2 = DerSequence([1, 2, DerSequence([3, 4])]).encode() + + DerSequence().decode(der_bin1, only_ints_expected=True) + DerSequence().decode(der_bin1, only_ints_expected=False) + DerSequence().decode(der_bin2, only_ints_expected=False) + self.assertRaises(ValueError, DerSequence().decode, der_bin2, only_ints_expected=True) class DerOctetStringTests(unittest.TestCase): + def testInit1(self): + der = DerOctetString(b("\xff")) + self.assertEqual(der.encode(), b("\x04\x01\xff")) + + def testEncode1(self): + # Empty sequence + der = DerOctetString() + self.assertEqual(der.encode(), b("\x04\x00")) + # Small payload + der.payload = b("\x01\x02") + self.assertEqual(der.encode(), b("\x04\x02\x01\x02")) + + #### + + def testDecode1(self): + # Empty sequence + der = DerOctetString() + der.decode(b("\x04\x00")) + self.assertEqual(der.payload, b("")) + # Small payload + der.decode(b("\x04\x02\x01\x02")) + self.assertEqual(der.payload, b("\x01\x02")) + + def testDecode2(self): + # Verify that decode returns the object + der = DerOctetString() + self.assertEqual(der, der.decode(b("\x04\x00"))) + + def testErrDecode1(self): + # No leftovers allowed + der = DerOctetString() + self.assertRaises(ValueError, der.decode, b("\x04\x01\x01\xff")) - def testInit1(self): - der = DerOctetString(b('\xFF')) - self.assertEqual(der.encode(), b('\x04\x01\xFF')) - - def testEncode1(self): - # Empty sequence - der = DerOctetString() - self.assertEqual(der.encode(), b('\x04\x00')) - # Small payload - der.payload = b('\x01\x02') - self.assertEqual(der.encode(), b('\x04\x02\x01\x02')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerOctetString() - der.decode(b('\x04\x00')) - self.assertEqual(der.payload, b('')) - # Small payload - der.decode(b('\x04\x02\x01\x02')) - self.assertEqual(der.payload, b('\x01\x02')) - - def testDecode2(self): - # Verify that decode returns the object - der = DerOctetString() - self.assertEqual(der, der.decode(b('\x04\x00'))) - - def testErrDecode1(self): - # No leftovers allowed - der = DerOctetString() - self.assertRaises(ValueError, der.decode, b('\x04\x01\x01\xff')) class DerNullTests(unittest.TestCase): + def testEncode1(self): + der = DerNull() + self.assertEqual(der.encode(), b("\x05\x00")) - def testEncode1(self): - der = DerNull() - self.assertEqual(der.encode(), b('\x05\x00')) + #### - #### + def testDecode1(self): + # Empty sequence + der = DerNull() + self.assertEqual(der, der.decode(b("\x05\x00"))) - def testDecode1(self): - # Empty sequence - der = DerNull() - self.assertEqual(der, der.decode(b('\x05\x00'))) class DerObjectIdTests(unittest.TestCase): + def testInit1(self): + der = DerObjectId("1.1") + self.assertEqual(der.encode(), b"\x06\x01)") - def testInit1(self): - der = DerObjectId("1.1") - self.assertEqual(der.encode(), b'\x06\x01)') + def testEncode1(self): + der = DerObjectId("1.2.840.113549.1.1.1") + self.assertEqual(der.encode(), b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01") - def testEncode1(self): - der = DerObjectId('1.2.840.113549.1.1.1') - self.assertEqual(der.encode(), b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01') + der = DerObjectId() + der.value = "1.2.840.113549.1.1.1" + self.assertEqual(der.encode(), b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01") - der = DerObjectId() - der.value = '1.2.840.113549.1.1.1' - self.assertEqual(der.encode(), b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01') + der = DerObjectId("2.999.1234") + self.assertEqual(der.encode(), b"\x06\x04\x88\x37\x89\x52") - der = DerObjectId('2.999.1234') - self.assertEqual(der.encode(), b'\x06\x04\x88\x37\x89\x52') + def testEncode2(self): + der = DerObjectId("3.4") + self.assertRaises(ValueError, der.encode) - def testEncode2(self): - der = DerObjectId('3.4') - self.assertRaises(ValueError, der.encode) + der = DerObjectId("1.40") + self.assertRaises(ValueError, der.encode) - der = DerObjectId('1.40') - self.assertRaises(ValueError, der.encode) + #### - #### + def testDecode1(self): + # Empty sequence + der = DerObjectId() + der.decode(b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01") + self.assertEqual(der.value, "1.2.840.113549.1.1.1") - def testDecode1(self): - # Empty sequence - der = DerObjectId() - der.decode(b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01') - self.assertEqual(der.value, '1.2.840.113549.1.1.1') + def testDecode2(self): + # Verify that decode returns the object + der = DerObjectId() + self.assertEqual( + der, + der.decode(b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01"), + ) - def testDecode2(self): - # Verify that decode returns the object - der = DerObjectId() - self.assertEqual(der, - der.decode(b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01')) + def testDecode3(self): + der = DerObjectId() + der.decode(b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x00\x01") + self.assertEqual(der.value, "1.2.840.113549.1.0.1") - def testDecode3(self): - der = DerObjectId() - der.decode(b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x00\x01') - self.assertEqual(der.value, '1.2.840.113549.1.0.1') - - def testDecode4(self): - der = DerObjectId() - der.decode(b'\x06\x04\x88\x37\x89\x52') - self.assertEqual(der.value, '2.999.1234') + def testDecode4(self): + der = DerObjectId() + der.decode(b"\x06\x04\x88\x37\x89\x52") + self.assertEqual(der.value, "2.999.1234") class DerBitStringTests(unittest.TestCase): - - def testInit1(self): - der = DerBitString(b("\xFF")) - self.assertEqual(der.encode(), b('\x03\x02\x00\xFF')) - - def testInit2(self): - der = DerBitString(DerInteger(1)) - self.assertEqual(der.encode(), b('\x03\x04\x00\x02\x01\x01')) - - def testEncode1(self): - # Empty sequence - der = DerBitString() - self.assertEqual(der.encode(), b('\x03\x01\x00')) - # Small payload - der = DerBitString(b('\x01\x02')) - self.assertEqual(der.encode(), b('\x03\x03\x00\x01\x02')) - # Small payload - der = DerBitString() - der.value = b('\x01\x02') - self.assertEqual(der.encode(), b('\x03\x03\x00\x01\x02')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerBitString() - der.decode(b('\x03\x00')) - self.assertEqual(der.value, b('')) - # Small payload - der.decode(b('\x03\x03\x00\x01\x02')) - self.assertEqual(der.value, b('\x01\x02')) - - def testDecode2(self): - # Verify that decode returns the object - der = DerBitString() - self.assertEqual(der, der.decode(b('\x03\x00'))) + def testInit1(self): + der = DerBitString(b("\xff")) + self.assertEqual(der.encode(), b("\x03\x02\x00\xff")) + + def testInit2(self): + der = DerBitString(DerInteger(1)) + self.assertEqual(der.encode(), b("\x03\x04\x00\x02\x01\x01")) + + def testEncode1(self): + # Empty sequence + der = DerBitString() + self.assertEqual(der.encode(), b("\x03\x01\x00")) + # Small payload + der = DerBitString(b("\x01\x02")) + self.assertEqual(der.encode(), b("\x03\x03\x00\x01\x02")) + # Small payload + der = DerBitString() + der.value = b("\x01\x02") + self.assertEqual(der.encode(), b("\x03\x03\x00\x01\x02")) + + #### + + def testDecode1(self): + # Empty sequence + der = DerBitString() + der.decode(b("\x03\x00")) + self.assertEqual(der.value, b("")) + # Small payload + der.decode(b("\x03\x03\x00\x01\x02")) + self.assertEqual(der.value, b("\x01\x02")) + + def testDecode2(self): + # Verify that decode returns the object + der = DerBitString() + self.assertEqual(der, der.decode(b("\x03\x00"))) class DerSetOfTests(unittest.TestCase): - - def testInit1(self): - der = DerSetOf([DerInteger(1), DerInteger(2)]) - self.assertEqual(der.encode(), b('1\x06\x02\x01\x01\x02\x01\x02')) - - def testEncode1(self): - # Empty set - der = DerSetOf() - self.assertEqual(der.encode(), b('1\x00')) - # One single-byte integer (zero) - der.add(0) - self.assertEqual(der.encode(), b('1\x03\x02\x01\x00')) - # Invariant - self.assertEqual(der.encode(), b('1\x03\x02\x01\x00')) - - def testEncode2(self): - # Two integers - der = DerSetOf() - der.add(0x180) - der.add(0xFF) - self.assertEqual(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80')) - # Initialize with integers - der = DerSetOf([0x180, 0xFF]) - self.assertEqual(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80')) - - def testEncode3(self): - # One integer and another type (no matter what it is) - der = DerSetOf() - der.add(0x180) - self.assertRaises(ValueError, der.add, b('\x00\x02\x00\x00')) - - def testEncode4(self): - # Only non integers - der = DerSetOf() - der.add(b('\x01\x00')) - der.add(b('\x01\x01\x01')) - self.assertEqual(der.encode(), b('1\x05\x01\x00\x01\x01\x01')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerSetOf() - der.decode(b('1\x00')) - self.assertEqual(len(der),0) - # One single-byte integer (zero) - der.decode(b('1\x03\x02\x01\x00')) - self.assertEqual(len(der),1) - self.assertEqual(list(der),[0]) - - def testDecode2(self): - # Two integers - der = DerSetOf() - der.decode(b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff')) - self.assertEqual(len(der),2) - l = list(der) - self.assertTrue(0x180 in l) - self.assertTrue(0xFF in l) - - def testDecode3(self): - # One integer and 2 other types - der = DerSetOf() - #import pdb; pdb.set_trace() - self.assertRaises(ValueError, der.decode, - b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')) - - def testDecode4(self): - # Verify that decode returns the object - der = DerSetOf() - self.assertEqual(der, - der.decode(b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff'))) - - ### - - def testErrDecode1(self): - # No leftovers allowed - der = DerSetOf() - self.assertRaises(ValueError, der.decode, - b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff\xAA')) + def testInit1(self): + der = DerSetOf([DerInteger(1), DerInteger(2)]) + self.assertEqual(der.encode(), b("1\x06\x02\x01\x01\x02\x01\x02")) + + def testEncode1(self): + # Empty set + der = DerSetOf() + self.assertEqual(der.encode(), b("1\x00")) + # One single-byte integer (zero) + der.add(0) + self.assertEqual(der.encode(), b("1\x03\x02\x01\x00")) + # Invariant + self.assertEqual(der.encode(), b("1\x03\x02\x01\x00")) + + def testEncode2(self): + # Two integers + der = DerSetOf() + der.add(0x180) + der.add(0xFF) + self.assertEqual(der.encode(), b("1\x08\x02\x02\x00\xff\x02\x02\x01\x80")) + # Initialize with integers + der = DerSetOf([0x180, 0xFF]) + self.assertEqual(der.encode(), b("1\x08\x02\x02\x00\xff\x02\x02\x01\x80")) + + def testEncode3(self): + # One integer and another type (no matter what it is) + der = DerSetOf() + der.add(0x180) + self.assertRaises(ValueError, der.add, b("\x00\x02\x00\x00")) + + def testEncode4(self): + # Only non integers + der = DerSetOf() + der.add(b("\x01\x00")) + der.add(b("\x01\x01\x01")) + self.assertEqual(der.encode(), b("1\x05\x01\x00\x01\x01\x01")) + + #### + + def testDecode1(self): + # Empty sequence + der = DerSetOf() + der.decode(b("1\x00")) + self.assertEqual(len(der), 0) + # One single-byte integer (zero) + der.decode(b("1\x03\x02\x01\x00")) + self.assertEqual(len(der), 1) + self.assertEqual(list(der), [0]) + + def testDecode2(self): + # Two integers + der = DerSetOf() + der.decode(b("1\x08\x02\x02\x01\x80\x02\x02\x00\xff")) + self.assertEqual(len(der), 2) + l = list(der) + self.assertTrue(0x180 in l) + self.assertTrue(0xFF in l) + + def testDecode3(self): + # One integer and 2 other types + der = DerSetOf() + # import pdb; pdb.set_trace() + self.assertRaises( + ValueError, + der.decode, + b("0\x0a\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00"), + ) + + def testDecode4(self): + # Verify that decode returns the object + der = DerSetOf() + self.assertEqual( + der, + der.decode(b("1\x08\x02\x02\x01\x80\x02\x02\x00\xff")), + ) + + ### + + def testErrDecode1(self): + # No leftovers allowed + der = DerSetOf() + self.assertRaises( + ValueError, + der.decode, + b("1\x08\x02\x02\x01\x80\x02\x02\x00\xff\xaa"), + ) class DerBooleanTests(unittest.TestCase): + def testEncode1(self): + der = DerBoolean(False) + self.assertEqual(der.encode(), b"\x01\x01\x00") - def testEncode1(self): - der = DerBoolean(False) - self.assertEqual(der.encode(), b'\x01\x01\x00') + def testEncode2(self): + der = DerBoolean(True) + self.assertEqual(der.encode(), b"\x01\x01\xff") - def testEncode2(self): - der = DerBoolean(True) - self.assertEqual(der.encode(), b'\x01\x01\xFF') + def testEncode3(self): + der = DerBoolean(False, implicit=0x12) + self.assertEqual(der.encode(), b"\x92\x01\x00") - def testEncode3(self): - der = DerBoolean(False, implicit=0x12) - self.assertEqual(der.encode(), b'\x92\x01\x00') + def testEncode4(self): + der = DerBoolean(False, explicit=0x05) + self.assertEqual(der.encode(), b"\xa5\x03\x01\x01\x00") - def testEncode4(self): - der = DerBoolean(False, explicit=0x05) - self.assertEqual(der.encode(), b'\xA5\x03\x01\x01\x00') - #### + #### - def testDecode1(self): - der = DerBoolean() - der.decode(b'\x01\x01\x00') - self.assertEqual(der.value, False) + def testDecode1(self): + der = DerBoolean() + der.decode(b"\x01\x01\x00") + self.assertEqual(der.value, False) - def testDecode2(self): - der = DerBoolean() - der.decode(b'\x01\x01\xFF') - self.assertEqual(der.value, True) + def testDecode2(self): + der = DerBoolean() + der.decode(b"\x01\x01\xff") + self.assertEqual(der.value, True) - def testDecode3(self): - der = DerBoolean(implicit=0x12) - der.decode(b'\x92\x01\x00') - self.assertEqual(der.value, False) + def testDecode3(self): + der = DerBoolean(implicit=0x12) + der.decode(b"\x92\x01\x00") + self.assertEqual(der.value, False) - def testDecode4(self): - der = DerBoolean(explicit=0x05) - der.decode(b'\xA5\x03\x01\x01\x00') - self.assertEqual(der.value, False) + def testDecode4(self): + der = DerBoolean(explicit=0x05) + der.decode(b"\xa5\x03\x01\x01\x00") + self.assertEqual(der.value, False) - def testErrorDecode1(self): - der = DerBoolean() - # Wrong tag - self.assertRaises(ValueError, der.decode, b'\x02\x01\x00') + def testErrorDecode1(self): + der = DerBoolean() + # Wrong tag + self.assertRaises(ValueError, der.decode, b"\x02\x01\x00") - def testErrorDecode2(self): - der = DerBoolean() - # Payload too long - self.assertRaises(ValueError, der.decode, b'\x01\x01\x00\xFF') + def testErrorDecode2(self): + der = DerBoolean() + # Payload too long + self.assertRaises(ValueError, der.decode, b"\x01\x01\x00\xff") def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - listTests = [] - listTests += list_test_cases(DerObjectTests) - listTests += list_test_cases(DerIntegerTests) - listTests += list_test_cases(DerSequenceTests) - listTests += list_test_cases(DerOctetStringTests) - listTests += list_test_cases(DerNullTests) - listTests += list_test_cases(DerObjectIdTests) - listTests += list_test_cases(DerBitStringTests) - listTests += list_test_cases(DerSetOfTests) - listTests += list_test_cases(DerBooleanTests) - return listTests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + from Cryptodome.SelfTest.st_common import list_test_cases + + listTests = [] + listTests += list_test_cases(DerObjectTests) + listTests += list_test_cases(DerIntegerTests) + listTests += list_test_cases(DerSequenceTests) + listTests += list_test_cases(DerOctetStringTests) + listTests += list_test_cases(DerNullTests) + listTests += list_test_cases(DerObjectIdTests) + listTests += list_test_cases(DerBitStringTests) + listTests += list_test_cases(DerSetOfTests) + listTests += list_test_cases(DerBooleanTests) + return listTests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_number.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_number.py index 8221443d..48ea9455 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_number.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_number.py @@ -24,7 +24,6 @@ """Self-tests for (some of) Cryptodome.Util.number""" -import math import unittest from Cryptodome.Util.py3compat import * @@ -35,158 +34,177 @@ class MyError(Exception): - """Dummy exception used for tests""" + """Dummy exception used for tests""" + # NB: In some places, we compare tuples instead of just output values so that # if any inputs cause a test failure, we'll be able to tell which ones. -class MiscTests(unittest.TestCase): - def test_ceil_div(self): - """Util.number.ceil_div""" - self.assertRaises(TypeError, number.ceil_div, "1", 1) - self.assertRaises(ZeroDivisionError, number.ceil_div, 1, 0) - self.assertRaises(ZeroDivisionError, number.ceil_div, -1, 0) - - # b = 1 - self.assertEqual(0, number.ceil_div(0, 1)) - self.assertEqual(1, number.ceil_div(1, 1)) - self.assertEqual(2, number.ceil_div(2, 1)) - self.assertEqual(3, number.ceil_div(3, 1)) - - # b = 2 - self.assertEqual(0, number.ceil_div(0, 2)) - self.assertEqual(1, number.ceil_div(1, 2)) - self.assertEqual(1, number.ceil_div(2, 2)) - self.assertEqual(2, number.ceil_div(3, 2)) - self.assertEqual(2, number.ceil_div(4, 2)) - self.assertEqual(3, number.ceil_div(5, 2)) - - # b = 3 - self.assertEqual(0, number.ceil_div(0, 3)) - self.assertEqual(1, number.ceil_div(1, 3)) - self.assertEqual(1, number.ceil_div(2, 3)) - self.assertEqual(1, number.ceil_div(3, 3)) - self.assertEqual(2, number.ceil_div(4, 3)) - self.assertEqual(2, number.ceil_div(5, 3)) - self.assertEqual(2, number.ceil_div(6, 3)) - self.assertEqual(3, number.ceil_div(7, 3)) - - # b = 4 - self.assertEqual(0, number.ceil_div(0, 4)) - self.assertEqual(1, number.ceil_div(1, 4)) - self.assertEqual(1, number.ceil_div(2, 4)) - self.assertEqual(1, number.ceil_div(3, 4)) - self.assertEqual(1, number.ceil_div(4, 4)) - self.assertEqual(2, number.ceil_div(5, 4)) - self.assertEqual(2, number.ceil_div(6, 4)) - self.assertEqual(2, number.ceil_div(7, 4)) - self.assertEqual(2, number.ceil_div(8, 4)) - self.assertEqual(3, number.ceil_div(9, 4)) - - def test_getPrime(self): - """Util.number.getPrime""" - self.assertRaises(ValueError, number.getPrime, -100) - self.assertRaises(ValueError, number.getPrime, 0) - self.assertRaises(ValueError, number.getPrime, 1) - - bits = 4 - for i in range(100): - x = number.getPrime(bits) - self.assertEqual(x >= (1 << bits - 1), 1) - self.assertEqual(x < (1 << bits), 1) - - bits = 512 - x = number.getPrime(bits) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x >= (1 << bits - 1), 1) - self.assertEqual(x < (1 << bits), 1) - - def test_getStrongPrime(self): - """Util.number.getStrongPrime""" - self.assertRaises(ValueError, number.getStrongPrime, 256) - self.assertRaises(ValueError, number.getStrongPrime, 513) - bits = 512 - x = number.getStrongPrime(bits) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x > (1 << bits-1)-1, 1) - self.assertEqual(x < (1 << bits), 1) - e = 2**16+1 - x = number.getStrongPrime(bits, e) - self.assertEqual(number.GCD(x-1, e), 1) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x > (1 << bits-1)-1, 1) - self.assertEqual(x < (1 << bits), 1) - e = 2**16+2 - x = number.getStrongPrime(bits, e) - self.assertEqual(number.GCD((x-1)>>1, e), 1) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x > (1 << bits-1)-1, 1) - self.assertEqual(x < (1 << bits), 1) - - def test_isPrime(self): - """Util.number.isPrime""" - self.assertEqual(number.isPrime(-3), False) # Regression test: negative numbers should not be prime - self.assertEqual(number.isPrime(-2), False) # Regression test: negative numbers should not be prime - self.assertEqual(number.isPrime(1), False) # Regression test: isPrime(1) caused some versions of PyCryptodome to crash. - self.assertEqual(number.isPrime(2), True) - self.assertEqual(number.isPrime(3), True) - self.assertEqual(number.isPrime(4), False) - self.assertEqual(number.isPrime(2**1279-1), True) - self.assertEqual(number.isPrime(-(2**1279-1)), False) # Regression test: negative numbers should not be prime - # test some known gmp pseudo-primes taken from - # http://www.trnicely.net/misc/mpzspsp.html - for composite in (43 * 127 * 211, 61 * 151 * 211, 15259 * 30517, - 346141 * 692281, 1007119 * 2014237, 3589477 * 7178953, - 4859419 * 9718837, 2730439 * 5460877, - 245127919 * 490255837, 963939391 * 1927878781, - 4186358431 * 8372716861, 1576820467 * 3153640933): - self.assertEqual(number.isPrime(int(composite)), False) - - def test_size(self): - self.assertEqual(number.size(2),2) - self.assertEqual(number.size(3),2) - self.assertEqual(number.size(0xa2),8) - self.assertEqual(number.size(0xa2ba40),8*3) - self.assertEqual(number.size(0xa2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5), 1024) - self.assertRaises(ValueError, number.size, -1) +class MiscTests(unittest.TestCase): + def test_ceil_div(self): + """Util.number.ceil_div""" + self.assertRaises(TypeError, number.ceil_div, "1", 1) + self.assertRaises(ZeroDivisionError, number.ceil_div, 1, 0) + self.assertRaises(ZeroDivisionError, number.ceil_div, -1, 0) + + # b = 1 + self.assertEqual(0, number.ceil_div(0, 1)) + self.assertEqual(1, number.ceil_div(1, 1)) + self.assertEqual(2, number.ceil_div(2, 1)) + self.assertEqual(3, number.ceil_div(3, 1)) + + # b = 2 + self.assertEqual(0, number.ceil_div(0, 2)) + self.assertEqual(1, number.ceil_div(1, 2)) + self.assertEqual(1, number.ceil_div(2, 2)) + self.assertEqual(2, number.ceil_div(3, 2)) + self.assertEqual(2, number.ceil_div(4, 2)) + self.assertEqual(3, number.ceil_div(5, 2)) + + # b = 3 + self.assertEqual(0, number.ceil_div(0, 3)) + self.assertEqual(1, number.ceil_div(1, 3)) + self.assertEqual(1, number.ceil_div(2, 3)) + self.assertEqual(1, number.ceil_div(3, 3)) + self.assertEqual(2, number.ceil_div(4, 3)) + self.assertEqual(2, number.ceil_div(5, 3)) + self.assertEqual(2, number.ceil_div(6, 3)) + self.assertEqual(3, number.ceil_div(7, 3)) + + # b = 4 + self.assertEqual(0, number.ceil_div(0, 4)) + self.assertEqual(1, number.ceil_div(1, 4)) + self.assertEqual(1, number.ceil_div(2, 4)) + self.assertEqual(1, number.ceil_div(3, 4)) + self.assertEqual(1, number.ceil_div(4, 4)) + self.assertEqual(2, number.ceil_div(5, 4)) + self.assertEqual(2, number.ceil_div(6, 4)) + self.assertEqual(2, number.ceil_div(7, 4)) + self.assertEqual(2, number.ceil_div(8, 4)) + self.assertEqual(3, number.ceil_div(9, 4)) + + def test_getPrime(self): + """Util.number.getPrime""" + self.assertRaises(ValueError, number.getPrime, -100) + self.assertRaises(ValueError, number.getPrime, 0) + self.assertRaises(ValueError, number.getPrime, 1) + + bits = 4 + for i in range(100): + x = number.getPrime(bits) + self.assertEqual(x >= (1 << bits - 1), 1) + self.assertEqual(x < (1 << bits), 1) + + bits = 512 + x = number.getPrime(bits) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x >= (1 << bits - 1), 1) + self.assertEqual(x < (1 << bits), 1) + + def test_getStrongPrime(self): + """Util.number.getStrongPrime""" + self.assertRaises(ValueError, number.getStrongPrime, 256) + self.assertRaises(ValueError, number.getStrongPrime, 513) + bits = 512 + x = number.getStrongPrime(bits) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x > (1 << bits - 1) - 1, 1) + self.assertEqual(x < (1 << bits), 1) + e = 2**16 + 1 + x = number.getStrongPrime(bits, e) + self.assertEqual(number.GCD(x - 1, e), 1) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x > (1 << bits - 1) - 1, 1) + self.assertEqual(x < (1 << bits), 1) + e = 2**16 + 2 + x = number.getStrongPrime(bits, e) + self.assertEqual(number.GCD((x - 1) >> 1, e), 1) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x > (1 << bits - 1) - 1, 1) + self.assertEqual(x < (1 << bits), 1) + + def test_isPrime(self): + """Util.number.isPrime""" + self.assertEqual(number.isPrime(-3), False) # Regression test: negative numbers should not be prime + self.assertEqual(number.isPrime(-2), False) # Regression test: negative numbers should not be prime + self.assertEqual( + number.isPrime(1), False + ) # Regression test: isPrime(1) caused some versions of PyCryptodome to crash. + self.assertEqual(number.isPrime(2), True) + self.assertEqual(number.isPrime(3), True) + self.assertEqual(number.isPrime(4), False) + self.assertEqual(number.isPrime(2**1279 - 1), True) + self.assertEqual( + number.isPrime(-(2**1279 - 1)), False + ) # Regression test: negative numbers should not be prime + # test some known gmp pseudo-primes taken from + # http://www.trnicely.net/misc/mpzspsp.html + for composite in ( + 43 * 127 * 211, + 61 * 151 * 211, + 15259 * 30517, + 346141 * 692281, + 1007119 * 2014237, + 3589477 * 7178953, + 4859419 * 9718837, + 2730439 * 5460877, + 245127919 * 490255837, + 963939391 * 1927878781, + 4186358431 * 8372716861, + 1576820467 * 3153640933, + ): + self.assertEqual(number.isPrime(int(composite)), False) + + def test_size(self): + self.assertEqual(number.size(2), 2) + self.assertEqual(number.size(3), 2) + self.assertEqual(number.size(0xA2), 8) + self.assertEqual(number.size(0xA2BA40), 8 * 3) + self.assertEqual( + number.size( + 0xA2BA40EE07E3B2BD2F02CE227F36A195024486E49C19CB41BBBDFBBA98B22B0E577C2EEAFFA20D883A76E65E394C69D4B3C05A1E8FADDA27EDB2A42BC000FE888B9B32C22D15ADD0CD76B3E7936E19955B220DD17D4EA904B1EC102B2E4DE7751222AA99151024C7CB41CC5EA21D00EEB41F7C800834D2C6E06BCE3BCE7EA9A5 + ), + 1024, + ) + self.assertRaises(ValueError, number.size, -1) class LongTests(unittest.TestCase): - - def test1(self): - self.assertEqual(long_to_bytes(0), b'\x00') - self.assertEqual(long_to_bytes(1), b'\x01') - self.assertEqual(long_to_bytes(0x100), b'\x01\x00') - self.assertEqual(long_to_bytes(0xFF00000000), b'\xFF\x00\x00\x00\x00') - self.assertEqual(long_to_bytes(0xFF00000000), b'\xFF\x00\x00\x00\x00') - self.assertEqual(long_to_bytes(0x1122334455667788), b'\x11\x22\x33\x44\x55\x66\x77\x88') - self.assertEqual(long_to_bytes(0x112233445566778899), b'\x11\x22\x33\x44\x55\x66\x77\x88\x99') - - def test2(self): - self.assertEqual(long_to_bytes(0, 1), b'\x00') - self.assertEqual(long_to_bytes(0, 2), b'\x00\x00') - self.assertEqual(long_to_bytes(1, 3), b'\x00\x00\x01') - self.assertEqual(long_to_bytes(65535, 2), b'\xFF\xFF') - self.assertEqual(long_to_bytes(65536, 2), b'\x00\x01\x00\x00') - self.assertEqual(long_to_bytes(0x100, 1), b'\x01\x00') - self.assertEqual(long_to_bytes(0xFF00000001, 6), b'\x00\xFF\x00\x00\x00\x01') - self.assertEqual(long_to_bytes(0xFF00000001, 8), b'\x00\x00\x00\xFF\x00\x00\x00\x01') - self.assertEqual(long_to_bytes(0xFF00000001, 10), b'\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x01') - self.assertEqual(long_to_bytes(0xFF00000001, 11), b'\x00\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x01') - - def test_err1(self): - self.assertRaises(ValueError, long_to_bytes, -1) + def test1(self): + self.assertEqual(long_to_bytes(0), b"\x00") + self.assertEqual(long_to_bytes(1), b"\x01") + self.assertEqual(long_to_bytes(0x100), b"\x01\x00") + self.assertEqual(long_to_bytes(0xFF00000000), b"\xff\x00\x00\x00\x00") + self.assertEqual(long_to_bytes(0xFF00000000), b"\xff\x00\x00\x00\x00") + self.assertEqual(long_to_bytes(0x1122334455667788), b"\x11\x22\x33\x44\x55\x66\x77\x88") + self.assertEqual(long_to_bytes(0x112233445566778899), b"\x11\x22\x33\x44\x55\x66\x77\x88\x99") + + def test2(self): + self.assertEqual(long_to_bytes(0, 1), b"\x00") + self.assertEqual(long_to_bytes(0, 2), b"\x00\x00") + self.assertEqual(long_to_bytes(1, 3), b"\x00\x00\x01") + self.assertEqual(long_to_bytes(65535, 2), b"\xff\xff") + self.assertEqual(long_to_bytes(65536, 2), b"\x00\x01\x00\x00") + self.assertEqual(long_to_bytes(0x100, 1), b"\x01\x00") + self.assertEqual(long_to_bytes(0xFF00000001, 6), b"\x00\xff\x00\x00\x00\x01") + self.assertEqual(long_to_bytes(0xFF00000001, 8), b"\x00\x00\x00\xff\x00\x00\x00\x01") + self.assertEqual(long_to_bytes(0xFF00000001, 10), b"\x00\x00\x00\x00\x00\xff\x00\x00\x00\x01") + self.assertEqual(long_to_bytes(0xFF00000001, 11), b"\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x01") + + def test_err1(self): + self.assertRaises(ValueError, long_to_bytes, -1) def get_tests(config={}): - tests = [] - tests += list_test_cases(MiscTests) - tests += list_test_cases(LongTests) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') + tests = [] + tests += list_test_cases(MiscTests) + tests += list_test_cases(LongTests) + return tests + + +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_rfc1751.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_rfc1751.py index 43b137dc..6aac612a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_rfc1751.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_rfc1751.py @@ -5,34 +5,33 @@ class RFC1751_Tests(unittest.TestCase): + def test1(self): + data = [ + ("EB33F77EE73D4053", "TIDE ITCH SLOW REIN RULE MOT"), + ("CCAC2AED591056BE4F90FD441C534766", "RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE"), + ("EFF81F9BFBC65350920CDD7416DE8009", "TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL"), + ] - def test1(self): - data = [ - ('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), - ('CCAC2AED591056BE4F90FD441C534766', 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), - ('EFF81F9BFBC65350920CDD7416DE8009', 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') - ] + for key_hex, words in data: + key_bin = binascii.a2b_hex(key_hex) - for key_hex, words in data: - key_bin = binascii.a2b_hex(key_hex) + w2 = key_to_english(key_bin) + self.assertEqual(w2, words) - w2 = key_to_english(key_bin) - self.assertEqual(w2, words) + k2 = english_to_key(words) + self.assertEqual(k2, key_bin) - k2 = english_to_key(words) - self.assertEqual(k2, key_bin) - - def test_error_key_to_english(self): - - self.assertRaises(ValueError, key_to_english, b'0' * 7) + def test_error_key_to_english(self): + self.assertRaises(ValueError, key_to_english, b"0" * 7) def get_tests(config={}): - from Cryptodome.SelfTest.st_common import list_test_cases - tests = list_test_cases(RFC1751_Tests) - return tests + from Cryptodome.SelfTest.st_common import list_test_cases + + tests = list_test_cases(RFC1751_Tests) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_strxor.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_strxor.py index 6a96129a..25191d25 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_strxor.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/Util/test_strxor.py @@ -32,249 +32,247 @@ # =================================================================== import unittest -from binascii import unhexlify, hexlify +from binascii import unhexlify from Cryptodome.SelfTest.st_common import list_test_cases from Cryptodome.Util.strxor import strxor, strxor_c class StrxorTests(unittest.TestCase): + def test1(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + result = unhexlify(b"c70ed123c59a7fcb6f12") + self.assertEqual(strxor(term1, term2), result) + self.assertEqual(strxor(term2, term1), result) - def test1(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - result = unhexlify(b"c70ed123c59a7fcb6f12") - self.assertEqual(strxor(term1, term2), result) - self.assertEqual(strxor(term2, term1), result) - - def test2(self): - es = b"" - self.assertEqual(strxor(es, es), es) - - def test3(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - all_zeros = b"\x00" * len(term1) - self.assertEqual(strxor(term1, term1), all_zeros) - - def test_wrong_length(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"ff339a83e5cd4cdf564990") - self.assertRaises(ValueError, strxor, term1, term2) - - def test_bytearray(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_ba = bytearray(term1) - term2 = unhexlify(b"383d4ba020573314395b") - result = unhexlify(b"c70ed123c59a7fcb6f12") - - self.assertEqual(strxor(term1_ba, term2), result) - - def test_memoryview(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_mv = memoryview(term1) - term2 = unhexlify(b"383d4ba020573314395b") - result = unhexlify(b"c70ed123c59a7fcb6f12") - - self.assertEqual(strxor(term1_mv, term2), result) - - def test_output_bytearray(self): - """Verify result can be stored in pre-allocated memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - original_term1 = term1[:] - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - output = bytearray(len(term1)) - - result = strxor(term1, term2, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_xor) - self.assertEqual(term1, original_term1) - self.assertEqual(term2, original_term2) - - def test_output_memoryview(self): - """Verify result can be stored in pre-allocated memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - original_term1 = term1[:] - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - output = memoryview(bytearray(len(term1))) - - result = strxor(term1, term2, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_xor) - self.assertEqual(term1, original_term1) - self.assertEqual(term2, original_term2) - - def test_output_overlapping_bytearray(self): - """Verify result can be stored in overlapping memory""" - - term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) - term2 = unhexlify(b"383d4ba020573314395b") - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - - result = strxor(term1, term2, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - self.assertEqual(term2, original_term2) - - def test_output_overlapping_memoryview(self): - """Verify result can be stored in overlapping memory""" - - term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) - term2 = unhexlify(b"383d4ba020573314395b") - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - - result = strxor(term1, term2, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - self.assertEqual(term2, original_term2) - - def test_output_ro_bytes(self): - """Verify result cannot be stored in read-only memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - - self.assertRaises(TypeError, strxor, term1, term2, output=term1) - - def test_output_ro_memoryview(self): - """Verify result cannot be stored in read-only memory""" - - term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) - term2 = unhexlify(b"383d4ba020573314395b") - - self.assertRaises(TypeError, strxor, term1, term2, output=term1) - - def test_output_incorrect_length(self): - """Verify result cannot be stored in memory of incorrect length""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - output = bytearray(len(term1) - 1) - - self.assertRaises(ValueError, strxor, term1, term2, output=output) + def test2(self): + es = b"" + self.assertEqual(strxor(es, es), es) + + def test3(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + all_zeros = b"\x00" * len(term1) + self.assertEqual(strxor(term1, term1), all_zeros) + + def test_wrong_length(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"ff339a83e5cd4cdf564990") + self.assertRaises(ValueError, strxor, term1, term2) + + def test_bytearray(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term1_ba = bytearray(term1) + term2 = unhexlify(b"383d4ba020573314395b") + result = unhexlify(b"c70ed123c59a7fcb6f12") + + self.assertEqual(strxor(term1_ba, term2), result) + + def test_memoryview(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term1_mv = memoryview(term1) + term2 = unhexlify(b"383d4ba020573314395b") + result = unhexlify(b"c70ed123c59a7fcb6f12") + + self.assertEqual(strxor(term1_mv, term2), result) + + def test_output_bytearray(self): + """Verify result can be stored in pre-allocated memory""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + original_term1 = term1[:] + original_term2 = term2[:] + expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") + output = bytearray(len(term1)) + + result = strxor(term1, term2, output=output) + + self.assertEqual(result, None) + self.assertEqual(output, expected_xor) + self.assertEqual(term1, original_term1) + self.assertEqual(term2, original_term2) + + def test_output_memoryview(self): + """Verify result can be stored in pre-allocated memory""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + original_term1 = term1[:] + original_term2 = term2[:] + expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") + output = memoryview(bytearray(len(term1))) + + result = strxor(term1, term2, output=output) + + self.assertEqual(result, None) + self.assertEqual(output, expected_xor) + self.assertEqual(term1, original_term1) + self.assertEqual(term2, original_term2) + + def test_output_overlapping_bytearray(self): + """Verify result can be stored in overlapping memory""" + + term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) + term2 = unhexlify(b"383d4ba020573314395b") + original_term2 = term2[:] + expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") + + result = strxor(term1, term2, output=term1) + + self.assertEqual(result, None) + self.assertEqual(term1, expected_xor) + self.assertEqual(term2, original_term2) + + def test_output_overlapping_memoryview(self): + """Verify result can be stored in overlapping memory""" + + term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) + term2 = unhexlify(b"383d4ba020573314395b") + original_term2 = term2[:] + expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") + + result = strxor(term1, term2, output=term1) + + self.assertEqual(result, None) + self.assertEqual(term1, expected_xor) + self.assertEqual(term2, original_term2) + + def test_output_ro_bytes(self): + """Verify result cannot be stored in read-only memory""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + + self.assertRaises(TypeError, strxor, term1, term2, output=term1) + + def test_output_ro_memoryview(self): + """Verify result cannot be stored in read-only memory""" + + term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) + term2 = unhexlify(b"383d4ba020573314395b") + + self.assertRaises(TypeError, strxor, term1, term2, output=term1) + + def test_output_incorrect_length(self): + """Verify result cannot be stored in memory of incorrect length""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term2 = unhexlify(b"383d4ba020573314395b") + output = bytearray(len(term1) - 1) + + self.assertRaises(ValueError, strxor, term1, term2, output=output) class Strxor_cTests(unittest.TestCase): + def test1(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + result = unhexlify(b"be72dbc2a48c0d9e1708") + self.assertEqual(strxor_c(term1, 65), result) + + def test2(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + self.assertEqual(strxor_c(term1, 0), term1) + + def test3(self): + self.assertEqual(strxor_c(b"", 90), b"") + + def test_wrong_range(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + self.assertRaises(ValueError, strxor_c, term1, -1) + self.assertRaises(ValueError, strxor_c, term1, 256) + + def test_bytearray(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term1_ba = bytearray(term1) + result = unhexlify(b"be72dbc2a48c0d9e1708") + + self.assertEqual(strxor_c(term1_ba, 65), result) + + def test_memoryview(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + term1_mv = memoryview(term1) + result = unhexlify(b"be72dbc2a48c0d9e1708") + + self.assertEqual(strxor_c(term1_mv, 65), result) + + def test_output_bytearray(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + original_term1 = term1[:] + expected_result = unhexlify(b"be72dbc2a48c0d9e1708") + output = bytearray(len(term1)) + + result = strxor_c(term1, 65, output=output) + + self.assertEqual(result, None) + self.assertEqual(output, expected_result) + self.assertEqual(term1, original_term1) + + def test_output_memoryview(self): + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + original_term1 = term1[:] + expected_result = unhexlify(b"be72dbc2a48c0d9e1708") + output = memoryview(bytearray(len(term1))) + + result = strxor_c(term1, 65, output=output) + + self.assertEqual(result, None) + self.assertEqual(output, expected_result) + self.assertEqual(term1, original_term1) + + def test_output_overlapping_bytearray(self): + """Verify result can be stored in overlapping memory""" + + term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) + expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") + + result = strxor_c(term1, 65, output=term1) + + self.assertEqual(result, None) + self.assertEqual(term1, expected_xor) + + def test_output_overlapping_memoryview(self): + """Verify result can be stored in overlapping memory""" + + term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) + expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") + + result = strxor_c(term1, 65, output=term1) + + self.assertEqual(result, None) + self.assertEqual(term1, expected_xor) + + def test_output_ro_bytes(self): + """Verify result cannot be stored in read-only memory""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + + self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) + + def test_output_ro_memoryview(self): + """Verify result cannot be stored in read-only memory""" + + term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) + term2 = unhexlify(b"383d4ba020573314395b") + + self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) + + def test_output_incorrect_length(self): + """Verify result cannot be stored in memory of incorrect length""" + + term1 = unhexlify(b"ff339a83e5cd4cdf5649") + output = bytearray(len(term1) - 1) - def test1(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - result = unhexlify(b"be72dbc2a48c0d9e1708") - self.assertEqual(strxor_c(term1, 65), result) - - def test2(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - self.assertEqual(strxor_c(term1, 0), term1) - - def test3(self): - self.assertEqual(strxor_c(b"", 90), b"") - - def test_wrong_range(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - self.assertRaises(ValueError, strxor_c, term1, -1) - self.assertRaises(ValueError, strxor_c, term1, 256) - - def test_bytearray(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_ba = bytearray(term1) - result = unhexlify(b"be72dbc2a48c0d9e1708") - - self.assertEqual(strxor_c(term1_ba, 65), result) - - def test_memoryview(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_mv = memoryview(term1) - result = unhexlify(b"be72dbc2a48c0d9e1708") - - self.assertEqual(strxor_c(term1_mv, 65), result) - - def test_output_bytearray(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - original_term1 = term1[:] - expected_result = unhexlify(b"be72dbc2a48c0d9e1708") - output = bytearray(len(term1)) - - result = strxor_c(term1, 65, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_result) - self.assertEqual(term1, original_term1) - - def test_output_memoryview(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - original_term1 = term1[:] - expected_result = unhexlify(b"be72dbc2a48c0d9e1708") - output = memoryview(bytearray(len(term1))) - - result = strxor_c(term1, 65, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_result) - self.assertEqual(term1, original_term1) - - def test_output_overlapping_bytearray(self): - """Verify result can be stored in overlapping memory""" - - term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) - expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") - - result = strxor_c(term1, 65, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - - def test_output_overlapping_memoryview(self): - """Verify result can be stored in overlapping memory""" - - term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) - expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") - - result = strxor_c(term1, 65, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - - def test_output_ro_bytes(self): - """Verify result cannot be stored in read-only memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - - self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) - - def test_output_ro_memoryview(self): - """Verify result cannot be stored in read-only memory""" - - term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) - term2 = unhexlify(b"383d4ba020573314395b") - - self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) - - def test_output_incorrect_length(self): - """Verify result cannot be stored in memory of incorrect length""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - output = bytearray(len(term1) - 1) - - self.assertRaises(ValueError, strxor_c, term1, 65, output=output) + self.assertRaises(ValueError, strxor_c, term1, 65, output=output) def get_tests(config={}): - tests = [] - tests += list_test_cases(StrxorTests) - tests += list_test_cases(Strxor_cTests) - return tests + tests = [] + tests += list_test_cases(StrxorTests) + tests += list_test_cases(Strxor_cTests) + return tests -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest="suite") diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/__init__.py index 09bb48c6..89c0cec8 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/__init__.py @@ -35,68 +35,77 @@ class SelfTestError(Exception): - def __init__(self, message, result): - Exception.__init__(self, message, result) - self.message = message - self.result = result + def __init__(self, message, result): + Exception.__init__(self, message, result) + self.message = message + self.result = result def run(module=None, verbosity=0, stream=None, tests=None, config=None, **kwargs): - """Execute self-tests. - - This raises SelfTestError if any test is unsuccessful. - - You may optionally pass in a sub-module of SelfTest if you only want to - perform some of the tests. For example, the following would test only the - hash modules: - - Cryptodome.SelfTest.run(Cryptodome.SelfTest.Hash) - - """ - - if config is None: - config = {} - suite = unittest.TestSuite() - if module is None: - if tests is None: - tests = get_tests(config=config) - suite.addTests(tests) - else: - if tests is None: - suite.addTests(module.get_tests(config=config)) - else: - raise ValueError("'module' and 'tests' arguments are mutually exclusive") - if stream is None: - kwargs['stream'] = StringIO() - else: - kwargs['stream'] = stream - runner = unittest.TextTestRunner(verbosity=verbosity, **kwargs) - result = runner.run(suite) - if not result.wasSuccessful(): - if stream is None: - sys.stderr.write(kwargs['stream'].getvalue()) - raise SelfTestError("Self-test failed", result) - return result + """Execute self-tests. + + This raises SelfTestError if any test is unsuccessful. + + You may optionally pass in a sub-module of SelfTest if you only want to + perform some of the tests. For example, the following would test only the + hash modules: + + Cryptodome.SelfTest.run(Cryptodome.SelfTest.Hash) + + """ + + if config is None: + config = {} + suite = unittest.TestSuite() + if module is None: + if tests is None: + tests = get_tests(config=config) + suite.addTests(tests) + else: + if tests is None: + suite.addTests(module.get_tests(config=config)) + else: + raise ValueError("'module' and 'tests' arguments are mutually exclusive") + if stream is None: + kwargs["stream"] = StringIO() + else: + kwargs["stream"] = stream + runner = unittest.TextTestRunner(verbosity=verbosity, **kwargs) + result = runner.run(suite) + if not result.wasSuccessful(): + if stream is None: + sys.stderr.write(kwargs["stream"].getvalue()) + raise SelfTestError("Self-test failed", result) + return result def get_tests(config={}): - tests = [] + tests = [] - module_names = [ - "Cipher", "Hash", "Protocol", "PublicKey", "Random", - "Util", "Signature", "IO", "Math", - ] + module_names = [ + "Cipher", + "Hash", + "Protocol", + "PublicKey", + "Random", + "Util", + "Signature", + "IO", + "Math", + ] - for name in module_names: - module = import_module("Cryptodome.SelfTest." + name) - tests += module.get_tests(config=config) + for name in module_names: + module = import_module("Cryptodome.SelfTest." + name) + tests += module.get_tests(config=config) - return tests + return tests -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') +if __name__ == "__main__": + + def suite(): + return unittest.TestSuite(get_tests()) + + unittest.main(defaultTest="suite") # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/__main__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/__main__.py index 242d7818..654c9bde 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/__main__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/__main__.py @@ -26,18 +26,18 @@ from Cryptodome import SelfTest -slow_tests = not ("--skip-slow-tests" in sys.argv) +slow_tests = "--skip-slow-tests" not in sys.argv if not slow_tests: - print("Skipping slow tests") + print("Skipping slow tests") wycheproof_warnings = "--wycheproof-warnings" in sys.argv if wycheproof_warnings: - print("Printing Wycheproof warnings") + print("Printing Wycheproof warnings") if "-v" in sys.argv: - verbosity=2 + verbosity = 2 else: - verbosity=1 + verbosity = 1 -config = {'slow_tests': slow_tests, 'wycheproof_warnings': wycheproof_warnings} +config = {"slow_tests": slow_tests, "wycheproof_warnings": wycheproof_warnings} SelfTest.run(stream=sys.stdout, verbosity=verbosity, config=config) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/loader.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/loader.py index 8699c3d9..0bbcca1a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/loader.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/loader.py @@ -39,212 +39,239 @@ try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True + import pycryptodome_test_vectors # type: ignore + + test_vectors_available = True except ImportError: - test_vectors_available = False + test_vectors_available = False def _load_tests(dir_comps, file_in, description, conversions): - """Load and parse a test vector file - - Return a list of objects, one per group of adjacent - KV lines or for a single line in the form "[.*]". - - For a group of lines, the object has one attribute per line. - """ - - line_number = 0 - results = [] - - class TestVector(object): - def __init__(self, description, count): - self.desc = description - self.count = count - self.others = [] - - test_vector = None - count = 0 - new_group = True - - while True: - line_number += 1 - line = file_in.readline() - if not line: - if test_vector is not None: - results.append(test_vector) - break - line = line.strip() - - # Skip comments and empty lines - if line.startswith('#') or not line: - new_group = True - continue - - if line.startswith("["): - if test_vector is not None: - results.append(test_vector) - test_vector = None - results.append(line) - continue - - if new_group: - count += 1 - new_group = False - if test_vector is not None: - results.append(test_vector) - test_vector = TestVector("%s (#%d)" % (description, count), count) - - res = re.match("([A-Za-z0-9]+) = ?(.*)", line) - if not res: - test_vector.others += [line] - else: - token = res.group(1).lower() - data = res.group(2).lower() - - conversion = conversions.get(token, None) - if conversion is None: - if len(data) % 2 != 0: - data = "0" + data - setattr(test_vector, token, binascii.unhexlify(data)) - else: - setattr(test_vector, token, conversion(data)) - - # This line is ignored - return results + """Load and parse a test vector file + + Return a list of objects, one per group of adjacent + KV lines or for a single line in the form "[.*]". + + For a group of lines, the object has one attribute per line. + """ + + line_number = 0 + results = [] + + class TestVector(object): + def __init__(self, description, count): + self.desc = description + self.count = count + self.others = [] + + test_vector = None + count = 0 + new_group = True + + while True: + line_number += 1 + line = file_in.readline() + if not line: + if test_vector is not None: + results.append(test_vector) + break + line = line.strip() + + # Skip comments and empty lines + if line.startswith("#") or not line: + new_group = True + continue + + if line.startswith("["): + if test_vector is not None: + results.append(test_vector) + test_vector = None + results.append(line) + continue + + if new_group: + count += 1 + new_group = False + if test_vector is not None: + results.append(test_vector) + test_vector = TestVector("%s (#%d)" % (description, count), count) + + res = re.match("([A-Za-z0-9]+) = ?(.*)", line) + if not res: + test_vector.others += [line] + else: + token = res.group(1).lower() + data = res.group(2).lower() + + conversion = conversions.get(token, None) + if conversion is None: + if len(data) % 2 != 0: + data = "0" + data + setattr(test_vector, token, binascii.unhexlify(data)) + else: + setattr(test_vector, token, conversion(data)) + + # This line is ignored + return results def load_test_vectors(dir_comps, file_name, description, conversions): - """Load and parse a test vector file, formatted using the NIST style. - - Args: - dir_comps (list of strings): - The path components under the ``pycryptodome_test_vectors`` package. - For instance ``("Cipher", "AES")``. - file_name (string): - The name of the file with the test vectors. - description (string): - A description applicable to the test vectors in the file. - conversions (dictionary): - The dictionary contains functions. - Values in the file that have an entry in this dictionary - will be converted usign the matching function. - Otherwise, values will be considered as hexadecimal and - converted to binary. - - Returns: - A list of test vector objects. - - The file is formatted in the following way: - - - Lines starting with "#" are comments and will be ignored. - - Each test vector is a sequence of 1 or more adjacent lines, where - each lines is an assignement. - - Test vectors are separated by an empty line, a comment, or - a line starting with "[". - - A test vector object has the following attributes: - - - desc (string): description - - counter (int): the order of the test vector in the file (from 1) - - others (list): zero or more lines of the test vector that were not assignments - - left-hand side of each assignment (lowercase): the value of the - assignement, either converted or bytes. - """ - - results = None - - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) - - description = "%s test (%s)" % (description, file_name) - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name) as file_in: - results = _load_tests(dir_comps, file_in, description, conversions) - - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for " + description, - UserWarning, - stacklevel=2) - - return results - - -def load_test_vectors_wycheproof(dir_comps, file_name, description, - root_tag={}, group_tag={}, unit_tag={}): - - result = [] - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name) as file_in: - tv_tree = json.load(file_in) - - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for " + description, - UserWarning, - stacklevel=2) - return result - - class TestVector(object): - pass - - # Unique attributes that will be converted from - # hexadecimal to binary, unless the attribute is - # listed in the unit_tag dict - unit_attr_hex = {'key', 'iv', 'aad', 'msg', 'ct', 'tag', 'label', - 'ikm', 'salt', 'info', 'okm', 'sig', 'public', - 'shared'} - unit_attr_hex -= set(unit_tag.keys()) - - common_root = {} - for k, v in root_tag.items(): - common_root[k] = v(tv_tree) - - for group in tv_tree['testGroups']: - - common_group = {} - for k, v in group_tag.items(): - common_group[k] = v(group) - - for test in group['tests']: - tv = TestVector() - - for k, v in common_root.items(): - setattr(tv, k, v) - for k, v in common_group.items(): - setattr(tv, k, v) - - tv.id = test['tcId'] - tv.comment = test['comment'] - for attr in unit_attr_hex: - if attr in test: - try: - setattr(tv, attr, unhexlify(test[attr])) - except binascii.Error: - raise ValueError("Error decoding attribute '%s' (tcId=%s, file %s)" % (attr, tv.id, file_name)) - tv.filename = file_name - - for k, v in unit_tag.items(): - setattr(tv, k, v(test)) - - tv.valid = test['result'] != "invalid" - tv.warning = test['result'] == "acceptable" - tv.flags = test.get('flags') - - tv.filename = file_name - - result.append(tv) - - return result - + """Load and parse a test vector file, formatted using the NIST style. + + Args: + dir_comps (list of strings): + The path components under the ``pycryptodome_test_vectors`` package. + For instance ``("Cipher", "AES")``. + file_name (string): + The name of the file with the test vectors. + description (string): + A description applicable to the test vectors in the file. + conversions (dictionary): + The dictionary contains functions. + Values in the file that have an entry in this dictionary + will be converted usign the matching function. + Otherwise, values will be considered as hexadecimal and + converted to binary. + + Returns: + A list of test vector objects. + + The file is formatted in the following way: + + - Lines starting with "#" are comments and will be ignored. + - Each test vector is a sequence of 1 or more adjacent lines, where + each lines is an assignement. + - Test vectors are separated by an empty line, a comment, or + a line starting with "[". + + A test vector object has the following attributes: + + - desc (string): description + - counter (int): the order of the test vector in the file (from 1) + - others (list): zero or more lines of the test vector that were not assignments + - left-hand side of each assignment (lowercase): the value of the + assignement, either converted or bytes. + """ + + results = None + + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) + + description = "%s test (%s)" % (description, file_name) + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name) as file_in: + results = _load_tests(dir_comps, file_in, description, conversions) + + except FileNotFoundError: + warnings.warn( + "Warning: skipping extended tests for " + description, + UserWarning, + stacklevel=2, + ) + + return results + + +def load_test_vectors_wycheproof( + dir_comps, + file_name, + description, + root_tag={}, + group_tag={}, + unit_tag={}, +): + result = [] + try: + if not test_vectors_available: + raise FileNotFoundError( + errno.ENOENT, + os.strerror(errno.ENOENT), + file_name, + ) + + init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) + full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) + with open(full_file_name) as file_in: + tv_tree = json.load(file_in) + + except FileNotFoundError: + warnings.warn( + "Warning: skipping extended tests for " + description, + UserWarning, + stacklevel=2, + ) + return result + + class TestVector(object): + pass + + # Unique attributes that will be converted from + # hexadecimal to binary, unless the attribute is + # listed in the unit_tag dict + unit_attr_hex = { + "key", + "iv", + "aad", + "msg", + "ct", + "tag", + "label", + "ikm", + "salt", + "info", + "okm", + "sig", + "public", + "shared", + } + unit_attr_hex -= set(unit_tag.keys()) + + common_root = {} + for k, v in root_tag.items(): + common_root[k] = v(tv_tree) + + for group in tv_tree["testGroups"]: + common_group = {} + for k, v in group_tag.items(): + common_group[k] = v(group) + + for test in group["tests"]: + tv = TestVector() + + for k, v in common_root.items(): + setattr(tv, k, v) + for k, v in common_group.items(): + setattr(tv, k, v) + + tv.id = test["tcId"] + tv.comment = test["comment"] + for attr in unit_attr_hex: + if attr in test: + try: + setattr(tv, attr, unhexlify(test[attr])) + except binascii.Error: + raise ValueError( + "Error decoding attribute '%s' (tcId=%s, file %s)" % (attr, tv.id, file_name) + ) + tv.filename = file_name + + for k, v in unit_tag.items(): + setattr(tv, k, v(test)) + + tv.valid = test["result"] != "invalid" + tv.warning = test["result"] == "acceptable" + tv.flags = test.get("flags") + + tv.filename = file_name + + result.append(tv) + + return result diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/st_common.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/st_common.py index 35652519..780352b9 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/st_common.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/SelfTest/st_common.py @@ -30,26 +30,30 @@ def list_test_cases(class_): - """Return a list of TestCase instances given a TestCase class + """Return a list of TestCase instances given a TestCase class + + This is useful when you have defined test* methods on your TestCase class. + """ + return unittest.TestLoader().loadTestsFromTestCase(class_) - This is useful when you have defined test* methods on your TestCase class. - """ - return unittest.TestLoader().loadTestsFromTestCase(class_) def strip_whitespace(s): - """Remove whitespace from a text or byte string""" - if isinstance(s,str): - return b("".join(s.split())) - else: - return b("").join(s.split()) + """Remove whitespace from a text or byte string""" + if isinstance(s, str): + return b("".join(s.split())) + else: + return b("").join(s.split()) + def a2b_hex(s): - """Convert hexadecimal to binary, ignoring whitespace""" - return binascii.a2b_hex(strip_whitespace(s)) + """Convert hexadecimal to binary, ignoring whitespace""" + return binascii.a2b_hex(strip_whitespace(s)) + def b2a_hex(s): - """Convert binary to hexadecimal""" - # For completeness - return binascii.b2a_hex(s) + """Convert binary to hexadecimal""" + # For completeness + return binascii.b2a_hex(s) + # vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/DSS.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/DSS.py index 97d9c850..3b9ecbba 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/DSS.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/DSS.py @@ -39,365 +39,372 @@ from Cryptodome.PublicKey.ECC import EccKey from Cryptodome.PublicKey.DSA import DsaKey -__all__ = ['DssSigScheme', 'new'] +__all__ = ["DssSigScheme", "new"] class DssSigScheme(object): - """A (EC)DSA signature object. - Do not instantiate directly. - Use :func:`Cryptodome.Signature.DSS.new`. - """ - - def __init__(self, key, encoding, order): - """Create a new Digital Signature Standard (DSS) object. - - Do not instantiate this object directly, - use `Cryptodome.Signature.DSS.new` instead. - """ - - self._key = key - self._encoding = encoding - self._order = order - - self._order_bits = self._order.size_in_bits() - self._order_bytes = (self._order_bits - 1) // 8 + 1 - - def can_sign(self): - """Return ``True`` if this signature object can be used - for signing messages.""" - - return self._key.has_private() - - def _compute_nonce(self, msg_hash): - raise NotImplementedError("To be provided by subclasses") - - def _valid_hash(self, msg_hash): - raise NotImplementedError("To be provided by subclasses") - - def sign(self, msg_hash): - """Compute the DSA/ECDSA signature of a message. - - Args: - msg_hash (hash object): - The hash that was carried out over the message. - The object belongs to the :mod:`Cryptodome.Hash` package. - Under mode ``'fips-186-3'``, the hash must be a FIPS - approved secure hash (SHA-2 or SHA-3). - - :return: The signature as ``bytes`` - :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key - :raise TypeError: if the (EC)DSA key has no private half - """ - - if not self._key.has_private(): - raise TypeError("Private key is needed to sign") - - if not self._valid_hash(msg_hash): - raise ValueError("Hash is not sufficiently strong") - - # Generate the nonce k (critical!) - nonce = self._compute_nonce(msg_hash) - - # Perform signature using the raw API - z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) - sig_pair = self._key._sign(z, nonce) - - # Encode the signature into a single byte string - if self._encoding == 'binary': - output = b"".join([long_to_bytes(x, self._order_bytes) - for x in sig_pair]) - else: - # Dss-sig ::= SEQUENCE { - # r INTEGER, - # s INTEGER - # } - # Ecdsa-Sig-Value ::= SEQUENCE { - # r INTEGER, - # s INTEGER - # } - output = DerSequence(sig_pair).encode() - - return output - - def verify(self, msg_hash, signature): - """Check if a certain (EC)DSA signature is authentic. - - Args: - msg_hash (hash object): - The hash that was carried out over the message. - This is an object belonging to the :mod:`Cryptodome.Hash` module. - Under mode ``'fips-186-3'``, the hash must be a FIPS - approved secure hash (SHA-2 or SHA-3). - - signature (``bytes``): - The signature that needs to be validated. - - :raise ValueError: if the signature is not authentic - """ - - if not self._valid_hash(msg_hash): - raise ValueError("Hash is not sufficiently strong") - - if self._encoding == 'binary': - if len(signature) != (2 * self._order_bytes): - raise ValueError("The signature is not authentic (length)") - r_prime, s_prime = [Integer.from_bytes(x) - for x in (signature[:self._order_bytes], - signature[self._order_bytes:])] - else: - try: - der_seq = DerSequence().decode(signature, strict=True) - except (ValueError, IndexError): - raise ValueError("The signature is not authentic (DER)") - if len(der_seq) != 2 or not der_seq.hasOnlyInts(): - raise ValueError("The signature is not authentic (DER content)") - r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1]) - - if not (0 < r_prime < self._order) or not (0 < s_prime < self._order): - raise ValueError("The signature is not authentic (d)") - - z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) - result = self._key._verify(z, (r_prime, s_prime)) - if not result: - raise ValueError("The signature is not authentic") - # Make PyCryptodome code to fail - return False + """A (EC)DSA signature object. + Do not instantiate directly. + Use :func:`Cryptodome.Signature.DSS.new`. + """ + + def __init__(self, key, encoding, order): + """Create a new Digital Signature Standard (DSS) object. + + Do not instantiate this object directly, + use `Cryptodome.Signature.DSS.new` instead. + """ + + self._key = key + self._encoding = encoding + self._order = order + + self._order_bits = self._order.size_in_bits() + self._order_bytes = (self._order_bits - 1) // 8 + 1 + + def can_sign(self): + """Return ``True`` if this signature object can be used + for signing messages.""" + + return self._key.has_private() + + def _compute_nonce(self, msg_hash): + raise NotImplementedError("To be provided by subclasses") + + def _valid_hash(self, msg_hash): + raise NotImplementedError("To be provided by subclasses") + + def sign(self, msg_hash): + """Compute the DSA/ECDSA signature of a message. + + Args: + msg_hash (hash object): + The hash that was carried out over the message. + The object belongs to the :mod:`Cryptodome.Hash` package. + Under mode ``'fips-186-3'``, the hash must be a FIPS + approved secure hash (SHA-2 or SHA-3). + + :return: The signature as ``bytes`` + :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key + :raise TypeError: if the (EC)DSA key has no private half + """ + + if not self._key.has_private(): + raise TypeError("Private key is needed to sign") + + if not self._valid_hash(msg_hash): + raise ValueError("Hash is not sufficiently strong") + + # Generate the nonce k (critical!) + nonce = self._compute_nonce(msg_hash) + + # Perform signature using the raw API + z = Integer.from_bytes(msg_hash.digest()[: self._order_bytes]) + sig_pair = self._key._sign(z, nonce) + + # Encode the signature into a single byte string + if self._encoding == "binary": + output = b"".join([long_to_bytes(x, self._order_bytes) for x in sig_pair]) + else: + # Dss-sig ::= SEQUENCE { + # r INTEGER, + # s INTEGER + # } + # Ecdsa-Sig-Value ::= SEQUENCE { + # r INTEGER, + # s INTEGER + # } + output = DerSequence(sig_pair).encode() + + return output + + def verify(self, msg_hash, signature): + """Check if a certain (EC)DSA signature is authentic. + + Args: + msg_hash (hash object): + The hash that was carried out over the message. + This is an object belonging to the :mod:`Cryptodome.Hash` module. + Under mode ``'fips-186-3'``, the hash must be a FIPS + approved secure hash (SHA-2 or SHA-3). + + signature (``bytes``): + The signature that needs to be validated. + + :raise ValueError: if the signature is not authentic + """ + + if not self._valid_hash(msg_hash): + raise ValueError("Hash is not sufficiently strong") + + if self._encoding == "binary": + if len(signature) != (2 * self._order_bytes): + raise ValueError("The signature is not authentic (length)") + r_prime, s_prime = [ + Integer.from_bytes(x) + for x in ( + signature[: self._order_bytes], + signature[self._order_bytes :], + ) + ] + else: + try: + der_seq = DerSequence().decode(signature, strict=True) + except (ValueError, IndexError): + raise ValueError("The signature is not authentic (DER)") + if len(der_seq) != 2 or not der_seq.hasOnlyInts(): + raise ValueError("The signature is not authentic (DER content)") + r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1]) + + if not (0 < r_prime < self._order) or not (0 < s_prime < self._order): + raise ValueError("The signature is not authentic (d)") + + z = Integer.from_bytes(msg_hash.digest()[: self._order_bytes]) + result = self._key._verify(z, (r_prime, s_prime)) + if not result: + raise ValueError("The signature is not authentic") + # Make PyCryptodome code to fail + return False class DeterministicDsaSigScheme(DssSigScheme): - # Also applicable to ECDSA - - def __init__(self, key, encoding, order, private_key): - super(DeterministicDsaSigScheme, self).__init__(key, encoding, order) - self._private_key = private_key - - def _bits2int(self, bstr): - """See 2.3.2 in RFC6979""" - - result = Integer.from_bytes(bstr) - q_len = self._order.size_in_bits() - b_len = len(bstr) * 8 - if b_len > q_len: - # Only keep leftmost q_len bits - result >>= (b_len - q_len) - return result - - def _int2octets(self, int_mod_q): - """See 2.3.3 in RFC6979""" - - assert 0 < int_mod_q < self._order - return long_to_bytes(int_mod_q, self._order_bytes) - - def _bits2octets(self, bstr): - """See 2.3.4 in RFC6979""" - - z1 = self._bits2int(bstr) - if z1 < self._order: - z2 = z1 - else: - z2 = z1 - self._order - return self._int2octets(z2) - - def _compute_nonce(self, mhash): - """Generate k in a deterministic way""" - - # See section 3.2 in RFC6979.txt - # Step a - h1 = mhash.digest() - # Step b - mask_v = b'\x01' * mhash.digest_size - # Step c - nonce_k = b'\x00' * mhash.digest_size - - for int_oct in (b'\x00', b'\x01'): - # Step d/f - nonce_k = HMAC.new(nonce_k, - mask_v + int_oct + - self._int2octets(self._private_key) + - self._bits2octets(h1), mhash).digest() - # Step e/g - mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() - - nonce = -1 - while not (0 < nonce < self._order): - # Step h.C (second part) - if nonce != -1: - nonce_k = HMAC.new(nonce_k, mask_v + b'\x00', - mhash).digest() - mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() - - # Step h.A - mask_t = b"" - - # Step h.B - while len(mask_t) < self._order_bytes: - mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() - mask_t += mask_v - - # Step h.C (first part) - nonce = self._bits2int(mask_t) - return nonce - - def _valid_hash(self, msg_hash): - return True + # Also applicable to ECDSA + + def __init__(self, key, encoding, order, private_key): + super(DeterministicDsaSigScheme, self).__init__(key, encoding, order) + self._private_key = private_key + + def _bits2int(self, bstr): + """See 2.3.2 in RFC6979""" + + result = Integer.from_bytes(bstr) + q_len = self._order.size_in_bits() + b_len = len(bstr) * 8 + if b_len > q_len: + # Only keep leftmost q_len bits + result >>= b_len - q_len + return result + + def _int2octets(self, int_mod_q): + """See 2.3.3 in RFC6979""" + + assert 0 < int_mod_q < self._order + return long_to_bytes(int_mod_q, self._order_bytes) + + def _bits2octets(self, bstr): + """See 2.3.4 in RFC6979""" + + z1 = self._bits2int(bstr) + if z1 < self._order: + z2 = z1 + else: + z2 = z1 - self._order + return self._int2octets(z2) + + def _compute_nonce(self, mhash): + """Generate k in a deterministic way""" + + # See section 3.2 in RFC6979.txt + # Step a + h1 = mhash.digest() + # Step b + mask_v = b"\x01" * mhash.digest_size + # Step c + nonce_k = b"\x00" * mhash.digest_size + + for int_oct in (b"\x00", b"\x01"): + # Step d/f + nonce_k = HMAC.new( + nonce_k, + mask_v + int_oct + self._int2octets(self._private_key) + self._bits2octets(h1), + mhash, + ).digest() + # Step e/g + mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() + + nonce = -1 + while not (0 < nonce < self._order): + # Step h.C (second part) + if nonce != -1: + nonce_k = HMAC.new( + nonce_k, + mask_v + b"\x00", + mhash, + ).digest() + mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() + + # Step h.A + mask_t = b"" + + # Step h.B + while len(mask_t) < self._order_bytes: + mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() + mask_t += mask_v + + # Step h.C (first part) + nonce = self._bits2int(mask_t) + return nonce + + def _valid_hash(self, msg_hash): + return True class FipsDsaSigScheme(DssSigScheme): - - #: List of L (bit length of p) and N (bit length of q) combinations - #: that are allowed by FIPS 186-3. The security level is provided in - #: Table 2 of FIPS 800-57 (rev3). - _fips_186_3_L_N = ( - (1024, 160), # 80 bits (SHA-1 or stronger) - (2048, 224), # 112 bits (SHA-224 or stronger) - (2048, 256), # 128 bits (SHA-256 or stronger) - (3072, 256) # 256 bits (SHA-512) - ) - - def __init__(self, key, encoding, order, randfunc): - super(FipsDsaSigScheme, self).__init__(key, encoding, order) - self._randfunc = randfunc - - L = Integer(key.p).size_in_bits() - if (L, self._order_bits) not in self._fips_186_3_L_N: - error = ("L/N (%d, %d) is not compliant to FIPS 186-3" - % (L, self._order_bits)) - raise ValueError(error) - - def _compute_nonce(self, msg_hash): - # hash is not used - return Integer.random_range(min_inclusive=1, - max_exclusive=self._order, - randfunc=self._randfunc) - - def _valid_hash(self, msg_hash): - """Verify that SHA-1, SHA-2 or SHA-3 are used""" - return (msg_hash.oid == "1.3.14.3.2.26" or - msg_hash.oid.startswith("2.16.840.1.101.3.4.2.")) + #: List of L (bit length of p) and N (bit length of q) combinations + #: that are allowed by FIPS 186-3. The security level is provided in + #: Table 2 of FIPS 800-57 (rev3). + _fips_186_3_L_N = ( + (1024, 160), # 80 bits (SHA-1 or stronger) + (2048, 224), # 112 bits (SHA-224 or stronger) + (2048, 256), # 128 bits (SHA-256 or stronger) + (3072, 256), # 256 bits (SHA-512) + ) + + def __init__(self, key, encoding, order, randfunc): + super(FipsDsaSigScheme, self).__init__(key, encoding, order) + self._randfunc = randfunc + + L = Integer(key.p).size_in_bits() + if (L, self._order_bits) not in self._fips_186_3_L_N: + error = "L/N (%d, %d) is not compliant to FIPS 186-3" % (L, self._order_bits) + raise ValueError(error) + + def _compute_nonce(self, msg_hash): + # hash is not used + return Integer.random_range( + min_inclusive=1, + max_exclusive=self._order, + randfunc=self._randfunc, + ) + + def _valid_hash(self, msg_hash): + """Verify that SHA-1, SHA-2 or SHA-3 are used""" + return msg_hash.oid == "1.3.14.3.2.26" or msg_hash.oid.startswith("2.16.840.1.101.3.4.2.") class FipsEcDsaSigScheme(DssSigScheme): - - def __init__(self, key, encoding, order, randfunc): - super(FipsEcDsaSigScheme, self).__init__(key, encoding, order) - self._randfunc = randfunc - - def _compute_nonce(self, msg_hash): - return Integer.random_range(min_inclusive=1, - max_exclusive=self._key._curve.order, - randfunc=self._randfunc) - - def _valid_hash(self, msg_hash): - """Verify that the strength of the hash matches or exceeds - the strength of the EC. We fail if the hash is too weak.""" - - modulus_bits = self._key.pointQ.size_in_bits() - - # SHS: SHA-2, SHA-3, truncated SHA-512 - sha224 = ("2.16.840.1.101.3.4.2.4", "2.16.840.1.101.3.4.2.7", "2.16.840.1.101.3.4.2.5") - sha256 = ("2.16.840.1.101.3.4.2.1", "2.16.840.1.101.3.4.2.8", "2.16.840.1.101.3.4.2.6") - sha384 = ("2.16.840.1.101.3.4.2.2", "2.16.840.1.101.3.4.2.9") - sha512 = ("2.16.840.1.101.3.4.2.3", "2.16.840.1.101.3.4.2.10") - shs = sha224 + sha256 + sha384 + sha512 - - try: - result = msg_hash.oid in shs - except AttributeError: - result = False - return result - - -def new(key, mode, encoding='binary', randfunc=None): - """Create a signature object :class:`DssSigScheme` that - can perform (EC)DSA signature or verification. - - .. note:: - Refer to `NIST SP 800 Part 1 Rev 4`_ (or newer release) for an - overview of the recommended key lengths. - - Args: - key (:class:`Cryptodome.PublicKey.DSA` or :class:`Cryptodome.PublicKey.ECC`): - The key to use for computing the signature (*private* keys only) - or for verifying one. - For DSA keys, let ``L`` and ``N`` be the bit lengths of the modulus ``p`` - and of ``q``: the pair ``(L,N)`` must appear in the following list, - in compliance to section 4.2 of `FIPS 186-4`_: - - - (1024, 160) *legacy only; do not create new signatures with this* - - (2048, 224) *deprecated; do not create new signatures with this* - - (2048, 256) - - (3072, 256) - - For ECC, only keys over P-224, P-256, P-384, and P-521 are accepted. - - mode (string): - The parameter can take these values: - - - ``'fips-186-3'``. The signature generation is randomized and carried out - according to `FIPS 186-3`_: the nonce ``k`` is taken from the RNG. - - ``'deterministic-rfc6979'``. The signature generation is not - randomized. See RFC6979_. - - encoding (string): - How the signature is encoded. This value determines the output of - :meth:`sign` and the input to :meth:`verify`. - - The following values are accepted: - - - ``'binary'`` (default), the signature is the raw concatenation - of ``r`` and ``s``. It is defined in the IEEE P.1363 standard. - For DSA, the size in bytes of the signature is ``N/4`` bytes - (e.g. 64 for ``N=256``). - For ECDSA, the signature is always twice the length of a point - coordinate (e.g. 64 bytes for P-256). - - - ``'der'``, the signature is a ASN.1 DER SEQUENCE - with two INTEGERs (``r`` and ``s``). It is defined in RFC3279_. - The size of the signature is variable. - - randfunc (callable): - A function that returns random ``bytes``, of a given length. - If omitted, the internal RNG is used. - Only applicable for the *'fips-186-3'* mode. - - .. _FIPS 186-3: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf - .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - .. _NIST SP 800 Part 1 Rev 4: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf - .. _RFC6979: http://tools.ietf.org/html/rfc6979 - .. _RFC3279: https://tools.ietf.org/html/rfc3279#section-2.2.2 - """ - - # The goal of the 'mode' parameter is to avoid to - # have the current version of the standard as default. - # - # Over time, such version will be superseded by (for instance) - # FIPS 186-4 and it will be odd to have -3 as default. - - if encoding not in ('binary', 'der'): - raise ValueError("Unknown encoding '%s'" % encoding) - - if isinstance(key, EccKey): - order = key._curve.order - private_key_attr = 'd' - if not key.curve.startswith("NIST"): - raise ValueError("ECC key is not on a NIST P curve") - elif isinstance(key, DsaKey): - order = Integer(key.q) - private_key_attr = 'x' - else: - raise ValueError("Unsupported key type " + str(type(key))) - - if key.has_private(): - private_key = getattr(key, private_key_attr) - else: - private_key = None - - if mode == 'deterministic-rfc6979': - return DeterministicDsaSigScheme(key, encoding, order, private_key) - elif mode == 'fips-186-3': - if isinstance(key, EccKey): - return FipsEcDsaSigScheme(key, encoding, order, randfunc) - else: - return FipsDsaSigScheme(key, encoding, order, randfunc) - else: - raise ValueError("Unknown DSS mode '%s'" % mode) + def __init__(self, key, encoding, order, randfunc): + super(FipsEcDsaSigScheme, self).__init__(key, encoding, order) + self._randfunc = randfunc + + def _compute_nonce(self, msg_hash): + return Integer.random_range( + min_inclusive=1, + max_exclusive=self._key._curve.order, + randfunc=self._randfunc, + ) + + def _valid_hash(self, msg_hash): + """Verify that the strength of the hash matches or exceeds + the strength of the EC. We fail if the hash is too weak.""" + + modulus_bits = self._key.pointQ.size_in_bits() + + # SHS: SHA-2, SHA-3, truncated SHA-512 + sha224 = ("2.16.840.1.101.3.4.2.4", "2.16.840.1.101.3.4.2.7", "2.16.840.1.101.3.4.2.5") + sha256 = ("2.16.840.1.101.3.4.2.1", "2.16.840.1.101.3.4.2.8", "2.16.840.1.101.3.4.2.6") + sha384 = ("2.16.840.1.101.3.4.2.2", "2.16.840.1.101.3.4.2.9") + sha512 = ("2.16.840.1.101.3.4.2.3", "2.16.840.1.101.3.4.2.10") + shs = sha224 + sha256 + sha384 + sha512 + + try: + result = msg_hash.oid in shs + except AttributeError: + result = False + return result + + +def new(key, mode, encoding="binary", randfunc=None): + """Create a signature object :class:`DssSigScheme` that + can perform (EC)DSA signature or verification. + + .. note:: + Refer to `NIST SP 800 Part 1 Rev 4`_ (or newer release) for an + overview of the recommended key lengths. + + Args: + key (:class:`Cryptodome.PublicKey.DSA` or :class:`Cryptodome.PublicKey.ECC`): + The key to use for computing the signature (*private* keys only) + or for verifying one. + For DSA keys, let ``L`` and ``N`` be the bit lengths of the modulus ``p`` + and of ``q``: the pair ``(L,N)`` must appear in the following list, + in compliance to section 4.2 of `FIPS 186-4`_: + + - (1024, 160) *legacy only; do not create new signatures with this* + - (2048, 224) *deprecated; do not create new signatures with this* + - (2048, 256) + - (3072, 256) + + For ECC, only keys over P-224, P-256, P-384, and P-521 are accepted. + + mode (string): + The parameter can take these values: + + - ``'fips-186-3'``. The signature generation is randomized and carried out + according to `FIPS 186-3`_: the nonce ``k`` is taken from the RNG. + - ``'deterministic-rfc6979'``. The signature generation is not + randomized. See RFC6979_. + + encoding (string): + How the signature is encoded. This value determines the output of + :meth:`sign` and the input to :meth:`verify`. + + The following values are accepted: + + - ``'binary'`` (default), the signature is the raw concatenation + of ``r`` and ``s``. It is defined in the IEEE P.1363 standard. + For DSA, the size in bytes of the signature is ``N/4`` bytes + (e.g. 64 for ``N=256``). + For ECDSA, the signature is always twice the length of a point + coordinate (e.g. 64 bytes for P-256). + + - ``'der'``, the signature is a ASN.1 DER SEQUENCE + with two INTEGERs (``r`` and ``s``). It is defined in RFC3279_. + The size of the signature is variable. + + randfunc (callable): + A function that returns random ``bytes``, of a given length. + If omitted, the internal RNG is used. + Only applicable for the *'fips-186-3'* mode. + + .. _FIPS 186-3: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + .. _NIST SP 800 Part 1 Rev 4: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf + .. _RFC6979: http://tools.ietf.org/html/rfc6979 + .. _RFC3279: https://tools.ietf.org/html/rfc3279#section-2.2.2 + """ + + # The goal of the 'mode' parameter is to avoid to + # have the current version of the standard as default. + # + # Over time, such version will be superseded by (for instance) + # FIPS 186-4 and it will be odd to have -3 as default. + + if encoding not in ("binary", "der"): + raise ValueError("Unknown encoding '%s'" % encoding) + + if isinstance(key, EccKey): + order = key._curve.order + private_key_attr = "d" + if not key.curve.startswith("NIST"): + raise ValueError("ECC key is not on a NIST P curve") + elif isinstance(key, DsaKey): + order = Integer(key.q) + private_key_attr = "x" + else: + raise ValueError("Unsupported key type " + str(type(key))) + + if key.has_private(): + private_key = getattr(key, private_key_attr) + else: + private_key = None + + if mode == "deterministic-rfc6979": + return DeterministicDsaSigScheme(key, encoding, order, private_key) + elif mode == "fips-186-3": + if isinstance(key, EccKey): + return FipsEcDsaSigScheme(key, encoding, order, randfunc) + else: + return FipsDsaSigScheme(key, encoding, order, randfunc) + else: + raise ValueError("Unknown DSS mode '%s'" % mode) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/DSS.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/DSS.pyi index 52ecc8fb..7f69e321 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/DSS.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/DSS.pyi @@ -5,23 +5,28 @@ from Cryptodome.PublicKey.DSA import DsaKey from Cryptodome.PublicKey.ECC import EccKey class Hash(Protocol): - def digest(self) -> bytes: ... + def digest(self) -> bytes: ... -__all__ = ['new'] +__all__ = ["new"] class DssSigScheme: - def __init__(self, key: Union[DsaKey, EccKey], encoding: str, order: int) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... + def __init__(self, key: Union[DsaKey, EccKey], encoding: str, order: int) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... class DeterministicDsaSigScheme(DssSigScheme): - def __init__(self, key, encoding, order, private_key) -> None: ... + def __init__(self, key, encoding, order, private_key) -> None: ... class FipsDsaSigScheme(DssSigScheme): - def __init__(self, key: DsaKey, encoding: str, order: int, randfunc: Callable) -> None: ... + def __init__(self, key: DsaKey, encoding: str, order: int, randfunc: Callable) -> None: ... class FipsEcDsaSigScheme(DssSigScheme): - def __init__(self, key: EccKey, encoding: str, order: int, randfunc: Callable) -> None: ... - -def new(key: Union[DsaKey, EccKey], mode: str, encoding: Optional[str]='binary', randfunc: Optional[Callable]=None) -> Union[DeterministicDsaSigScheme, FipsDsaSigScheme, FipsEcDsaSigScheme]: ... + def __init__(self, key: EccKey, encoding: str, order: int, randfunc: Callable) -> None: ... + +def new( + key: Union[DsaKey, EccKey], + mode: str, + encoding: Optional[str] = "binary", + randfunc: Optional[Callable] = None, +) -> Union[DeterministicDsaSigScheme, FipsDsaSigScheme, FipsEcDsaSigScheme]: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_PSS.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_PSS.py index 1e7e5b56..17d7d7f7 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_PSS.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_PSS.py @@ -40,16 +40,20 @@ def _pycrypto_verify(self, hash_object, signature): - try: - self._verify(hash_object, signature) - except (ValueError, TypeError): - return False - return True + try: + self._verify(hash_object, signature) + except (ValueError, TypeError): + return False + return True def new(rsa_key, mgfunc=None, saltLen=None, randfunc=None): - pkcs1 = pss.new(rsa_key, mask_func=mgfunc, - salt_bytes=saltLen, rand_func=randfunc) - pkcs1._verify = pkcs1.verify - pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) - return pkcs1 + pkcs1 = pss.new( + rsa_key, + mask_func=mgfunc, + salt_bytes=saltLen, + rand_func=randfunc, + ) + pkcs1._verify = pkcs1.verify + pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) + return pkcs1 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_PSS.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_PSS.pyi index e7424f58..16da2db2 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_PSS.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_PSS.pyi @@ -3,26 +3,26 @@ from typing_extensions import Protocol from Cryptodome.PublicKey.RSA import RsaKey - class Hash(Protocol): - def digest(self) -> bytes: ... - def update(self, bytes) -> None: ... - + def digest(self) -> bytes: ... + def update(self, bytes) -> None: ... class HashModule(Protocol): - @staticmethod - def new(data: Optional[bytes]) -> Hash: ... - + @staticmethod + def new(data: Optional[bytes]) -> Hash: ... MaskFunction = Callable[[bytes, int, Union[Hash, HashModule]], bytes] RndFunction = Callable[[int], bytes] class PSS_SigScheme: - def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... - - - -def new(rsa_key: RsaKey, mgfunc: Optional[MaskFunction]=None, saltLen: Optional[int]=None, randfunc: Optional[RndFunction]=None) -> PSS_SigScheme: ... + def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... + +def new( + rsa_key: RsaKey, + mgfunc: Optional[MaskFunction] = None, + saltLen: Optional[int] = None, + randfunc: Optional[RndFunction] = None, +) -> PSS_SigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_v1_5.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_v1_5.py index d560663c..51262d13 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_v1_5.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_v1_5.py @@ -38,16 +38,17 @@ from Cryptodome.Signature import pkcs1_15 + def _pycrypto_verify(self, hash_object, signature): - try: - self._verify(hash_object, signature) - except (ValueError, TypeError): - return False - return True + try: + self._verify(hash_object, signature) + except (ValueError, TypeError): + return False + return True -def new(rsa_key): - pkcs1 = pkcs1_15.new(rsa_key) - pkcs1._verify = pkcs1.verify - pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) - return pkcs1 +def new(rsa_key): + pkcs1 = pkcs1_15.new(rsa_key) + pkcs1._verify = pkcs1.verify + pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) + return pkcs1 diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_v1_5.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_v1_5.pyi index d02555cd..6fd91ffb 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_v1_5.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/PKCS1_v1_5.pyi @@ -1,16 +1,14 @@ -from typing import Optional from typing_extensions import Protocol from Cryptodome.PublicKey.RSA import RsaKey class Hash(Protocol): - def digest(self) -> bytes: ... + def digest(self) -> bytes: ... class PKCS115_SigScheme: - def __init__(self, rsa_key: RsaKey) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... - + def __init__(self, rsa_key: RsaKey) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/__init__.py index 11ca64c3..c5d37273 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/__init__.py @@ -33,4 +33,4 @@ A collection of standardized protocols to carry out digital signatures. """ -__all__ = ['PKCS1_v1_5', 'PKCS1_PSS', 'DSS', 'pkcs1_15', 'pss', 'eddsa'] +__all__ = ["PKCS1_v1_5", "PKCS1_PSS", "DSS", "pkcs1_15", "pss", "eddsa"] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/eddsa.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/eddsa.py index 02e1e3e4..c607ed5c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/eddsa.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/eddsa.py @@ -32,312 +32,306 @@ from Cryptodome.Hash import SHA512, SHAKE256 from Cryptodome.Util.py3compat import bchr, is_bytes -from Cryptodome.PublicKey.ECC import (EccKey, - construct, - _import_ed25519_public_key, - _import_ed448_public_key) +from Cryptodome.PublicKey.ECC import ( + EccKey, + construct, + _import_ed25519_public_key, + _import_ed448_public_key, +) def import_public_key(encoded): - """Create a new Ed25519 or Ed448 public key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC8032. + """Create a new Ed25519 or Ed448 public key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC8032. - Args: - encoded (bytes): - The EdDSA public key to import. - It must be 32 bytes for Ed25519, and 57 bytes for Ed448. + Args: + encoded (bytes): + The EdDSA public key to import. + It must be 32 bytes for Ed25519, and 57 bytes for Ed448. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - if len(encoded) == 32: - x, y = _import_ed25519_public_key(encoded) - curve_name = "Ed25519" - elif len(encoded) == 57: - x, y = _import_ed448_public_key(encoded) - curve_name = "Ed448" - else: - raise ValueError("Not an EdDSA key (%d bytes)" % len(encoded)) - return construct(curve=curve_name, point_x=x, point_y=y) + if len(encoded) == 32: + x, y = _import_ed25519_public_key(encoded) + curve_name = "Ed25519" + elif len(encoded) == 57: + x, y = _import_ed448_public_key(encoded) + curve_name = "Ed448" + else: + raise ValueError("Not an EdDSA key (%d bytes)" % len(encoded)) + return construct(curve=curve_name, point_x=x, point_y=y) def import_private_key(encoded): - """Create a new Ed25519 or Ed448 private key object, - starting from the key encoded as raw ``bytes``, - in the format described in RFC8032. + """Create a new Ed25519 or Ed448 private key object, + starting from the key encoded as raw ``bytes``, + in the format described in RFC8032. - Args: - encoded (bytes): - The EdDSA private key to import. - It must be 32 bytes for Ed25519, and 57 bytes for Ed448. + Args: + encoded (bytes): + The EdDSA private key to import. + It must be 32 bytes for Ed25519, and 57 bytes for Ed448. - Returns: - :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. + Returns: + :class:`Cryptodome.PublicKey.EccKey` : a new ECC key object. - Raises: - ValueError: when the given key cannot be parsed. - """ + Raises: + ValueError: when the given key cannot be parsed. + """ - if len(encoded) == 32: - curve_name = "ed25519" - elif len(encoded) == 57: - curve_name = "ed448" - else: - raise ValueError("Incorrect length. Only EdDSA private keys are supported.") + if len(encoded) == 32: + curve_name = "ed25519" + elif len(encoded) == 57: + curve_name = "ed448" + else: + raise ValueError("Incorrect length. Only EdDSA private keys are supported.") - # Note that the private key is truly a sequence of random bytes, - # so we cannot check its correctness in any way. + # Note that the private key is truly a sequence of random bytes, + # so we cannot check its correctness in any way. - return construct(seed=encoded, curve=curve_name) + return construct(seed=encoded, curve=curve_name) class EdDSASigScheme(object): - """An EdDSA signature object. - Do not instantiate directly. - Use :func:`Cryptodome.Signature.eddsa.new`. - """ - - def __init__(self, key, context): - """Create a new EdDSA object. - - Do not instantiate this object directly, - use `Cryptodome.Signature.DSS.new` instead. - """ + """An EdDSA signature object. + Do not instantiate directly. + Use :func:`Cryptodome.Signature.eddsa.new`. + """ + + def __init__(self, key, context): + """Create a new EdDSA object. + + Do not instantiate this object directly, + use `Cryptodome.Signature.DSS.new` instead. + """ + + self._key = key + self._context = context + self._A = key._export_eddsa_public() + self._order = key._curve.order + + def can_sign(self): + """Return ``True`` if this signature object can be used + for signing messages.""" + + return self._key.has_private() - self._key = key - self._context = context - self._A = key._export_eddsa_public() - self._order = key._curve.order - - def can_sign(self): - """Return ``True`` if this signature object can be used - for signing messages.""" - - return self._key.has_private() - - def sign(self, msg_or_hash): - """Compute the EdDSA signature of a message. - - Args: - msg_or_hash (bytes or a hash object): - The message to sign (``bytes``, in case of *PureEdDSA*) or - the hash that was carried out over the message (hash object, for *HashEdDSA*). - - The hash object must be :class:`Cryptodome.Hash.SHA512` for Ed25519, - and :class:`Cryptodome.Hash.SHAKE256` object for Ed448. - - :return: The signature as ``bytes``. It is always 64 bytes for Ed25519, and 114 bytes for Ed448. - :raise TypeError: if the EdDSA key has no private half - """ - - if not self._key.has_private(): - raise TypeError("Private key is needed to sign") - - if self._key.curve == "Ed25519": - ph = isinstance(msg_or_hash, SHA512.SHA512Hash) - if not (ph or is_bytes(msg_or_hash)): - raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash") - eddsa_sign_method = self._sign_ed25519 - - elif self._key.curve == "Ed448": - ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF) - if not (ph or is_bytes(msg_or_hash)): - raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash") - eddsa_sign_method = self._sign_ed448 - - else: - raise ValueError("Incorrect curve for EdDSA") - - return eddsa_sign_method(msg_or_hash, ph) - - def _sign_ed25519(self, msg_or_hash, ph): - - if self._context or ph: - flag = int(ph) - # dom2(flag, self._context) - dom2 = b'SigEd25519 no Ed25519 collisions' + bchr(flag) + \ - bchr(len(self._context)) + self._context - else: - dom2 = b'' - - PHM = msg_or_hash.digest() if ph else msg_or_hash - - # See RFC 8032, section 5.1.6 - - # Step 2 - r_hash = SHA512.new(dom2 + self._key._prefix + PHM).digest() - r = Integer.from_bytes(r_hash, 'little') % self._order - # Step 3 - R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public() - # Step 4 - k_hash = SHA512.new(dom2 + R_pk + self._A + PHM).digest() - k = Integer.from_bytes(k_hash, 'little') % self._order - # Step 5 - s = (r + k * self._key.d) % self._order - - return R_pk + s.to_bytes(32, 'little') - - def _sign_ed448(self, msg_or_hash, ph): - - flag = int(ph) - # dom4(flag, self._context) - dom4 = b'SigEd448' + bchr(flag) + \ - bchr(len(self._context)) + self._context - - PHM = msg_or_hash.copy().read(64) if ph else msg_or_hash - - # See RFC 8032, section 5.2.6 - - # Step 2 - r_hash = SHAKE256.new(dom4 + self._key._prefix + PHM).read(114) - r = Integer.from_bytes(r_hash, 'little') % self._order - # Step 3 - R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public() - # Step 4 - k_hash = SHAKE256.new(dom4 + R_pk + self._A + PHM).read(114) - k = Integer.from_bytes(k_hash, 'little') % self._order - # Step 5 - s = (r + k * self._key.d) % self._order - - return R_pk + s.to_bytes(57, 'little') - - def verify(self, msg_or_hash, signature): - """Check if an EdDSA signature is authentic. - - Args: - msg_or_hash (bytes or a hash object): - The message to verify (``bytes``, in case of *PureEdDSA*) or - the hash that was carried out over the message (hash object, for *HashEdDSA*). - - The hash object must be :class:`Cryptodome.Hash.SHA512` object for Ed25519, - and :class:`Cryptodome.Hash.SHAKE256` for Ed448. - - signature (``bytes``): - The signature that needs to be validated. - It must be 64 bytes for Ed25519, and 114 bytes for Ed448. - - :raise ValueError: if the signature is not authentic - """ - - if self._key.curve == "Ed25519": - ph = isinstance(msg_or_hash, SHA512.SHA512Hash) - if not (ph or is_bytes(msg_or_hash)): - raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash") - eddsa_verify_method = self._verify_ed25519 - - elif self._key.curve == "Ed448": - ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF) - if not (ph or is_bytes(msg_or_hash)): - raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash") - eddsa_verify_method = self._verify_ed448 - - else: - raise ValueError("Incorrect curve for EdDSA") - - return eddsa_verify_method(msg_or_hash, signature, ph) - - def _verify_ed25519(self, msg_or_hash, signature, ph): - - if len(signature) != 64: - raise ValueError("The signature is not authentic (length)") - - if self._context or ph: - flag = int(ph) - dom2 = b'SigEd25519 no Ed25519 collisions' + bchr(flag) + \ - bchr(len(self._context)) + self._context - else: - dom2 = b'' - - PHM = msg_or_hash.digest() if ph else msg_or_hash - - # Section 5.1.7 - - # Step 1 - try: - R = import_public_key(signature[:32]).pointQ - except ValueError: - raise ValueError("The signature is not authentic (R)") - s = Integer.from_bytes(signature[32:], 'little') - if s > self._order: - raise ValueError("The signature is not authentic (S)") - # Step 2 - k_hash = SHA512.new(dom2 + signature[:32] + self._A + PHM).digest() - k = Integer.from_bytes(k_hash, 'little') % self._order - # Step 3 - point1 = s * 8 * self._key._curve.G - # OPTIMIZE: with double-scalar multiplication, with no SCA - # countermeasures because it is public values - point2 = 8 * R + k * 8 * self._key.pointQ - if point1 != point2: - raise ValueError("The signature is not authentic") - - def _verify_ed448(self, msg_or_hash, signature, ph): - - if len(signature) != 114: - raise ValueError("The signature is not authentic (length)") - - flag = int(ph) - # dom4(flag, self._context) - dom4 = b'SigEd448' + bchr(flag) + \ - bchr(len(self._context)) + self._context - - PHM = msg_or_hash.copy().read(64) if ph else msg_or_hash - - # Section 5.2.7 - - # Step 1 - try: - R = import_public_key(signature[:57]).pointQ - except ValueError: - raise ValueError("The signature is not authentic (R)") - s = Integer.from_bytes(signature[57:], 'little') - if s > self._order: - raise ValueError("The signature is not authentic (S)") - # Step 2 - k_hash = SHAKE256.new(dom4 + signature[:57] + self._A + PHM).read(114) - k = Integer.from_bytes(k_hash, 'little') % self._order - # Step 3 - point1 = s * 8 * self._key._curve.G - # OPTIMIZE: with double-scalar multiplication, with no SCA - # countermeasures because it is public values - point2 = 8 * R + k * 8 * self._key.pointQ - if point1 != point2: - raise ValueError("The signature is not authentic") + def sign(self, msg_or_hash): + """Compute the EdDSA signature of a message. + + Args: + msg_or_hash (bytes or a hash object): + The message to sign (``bytes``, in case of *PureEdDSA*) or + the hash that was carried out over the message (hash object, for *HashEdDSA*). + + The hash object must be :class:`Cryptodome.Hash.SHA512` for Ed25519, + and :class:`Cryptodome.Hash.SHAKE256` object for Ed448. + + :return: The signature as ``bytes``. It is always 64 bytes for Ed25519, and 114 bytes for Ed448. + :raise TypeError: if the EdDSA key has no private half + """ + + if not self._key.has_private(): + raise TypeError("Private key is needed to sign") + + if self._key.curve == "Ed25519": + ph = isinstance(msg_or_hash, SHA512.SHA512Hash) + if not (ph or is_bytes(msg_or_hash)): + raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash") + eddsa_sign_method = self._sign_ed25519 + + elif self._key.curve == "Ed448": + ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF) + if not (ph or is_bytes(msg_or_hash)): + raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash") + eddsa_sign_method = self._sign_ed448 + + else: + raise ValueError("Incorrect curve for EdDSA") + + return eddsa_sign_method(msg_or_hash, ph) + + def _sign_ed25519(self, msg_or_hash, ph): + if self._context or ph: + flag = int(ph) + # dom2(flag, self._context) + dom2 = b"SigEd25519 no Ed25519 collisions" + bchr(flag) + bchr(len(self._context)) + self._context + else: + dom2 = b"" + + PHM = msg_or_hash.digest() if ph else msg_or_hash + + # See RFC 8032, section 5.1.6 + + # Step 2 + r_hash = SHA512.new(dom2 + self._key._prefix + PHM).digest() + r = Integer.from_bytes(r_hash, "little") % self._order + # Step 3 + R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public() + # Step 4 + k_hash = SHA512.new(dom2 + R_pk + self._A + PHM).digest() + k = Integer.from_bytes(k_hash, "little") % self._order + # Step 5 + s = (r + k * self._key.d) % self._order + + return R_pk + s.to_bytes(32, "little") + + def _sign_ed448(self, msg_or_hash, ph): + flag = int(ph) + # dom4(flag, self._context) + dom4 = b"SigEd448" + bchr(flag) + bchr(len(self._context)) + self._context + + PHM = msg_or_hash.copy().read(64) if ph else msg_or_hash + + # See RFC 8032, section 5.2.6 + + # Step 2 + r_hash = SHAKE256.new(dom4 + self._key._prefix + PHM).read(114) + r = Integer.from_bytes(r_hash, "little") % self._order + # Step 3 + R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public() + # Step 4 + k_hash = SHAKE256.new(dom4 + R_pk + self._A + PHM).read(114) + k = Integer.from_bytes(k_hash, "little") % self._order + # Step 5 + s = (r + k * self._key.d) % self._order + + return R_pk + s.to_bytes(57, "little") + + def verify(self, msg_or_hash, signature): + """Check if an EdDSA signature is authentic. + + Args: + msg_or_hash (bytes or a hash object): + The message to verify (``bytes``, in case of *PureEdDSA*) or + the hash that was carried out over the message (hash object, for *HashEdDSA*). + + The hash object must be :class:`Cryptodome.Hash.SHA512` object for Ed25519, + and :class:`Cryptodome.Hash.SHAKE256` for Ed448. + + signature (``bytes``): + The signature that needs to be validated. + It must be 64 bytes for Ed25519, and 114 bytes for Ed448. + + :raise ValueError: if the signature is not authentic + """ + + if self._key.curve == "Ed25519": + ph = isinstance(msg_or_hash, SHA512.SHA512Hash) + if not (ph or is_bytes(msg_or_hash)): + raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash") + eddsa_verify_method = self._verify_ed25519 + + elif self._key.curve == "Ed448": + ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF) + if not (ph or is_bytes(msg_or_hash)): + raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash") + eddsa_verify_method = self._verify_ed448 + + else: + raise ValueError("Incorrect curve for EdDSA") + + return eddsa_verify_method(msg_or_hash, signature, ph) + + def _verify_ed25519(self, msg_or_hash, signature, ph): + if len(signature) != 64: + raise ValueError("The signature is not authentic (length)") + + if self._context or ph: + flag = int(ph) + dom2 = b"SigEd25519 no Ed25519 collisions" + bchr(flag) + bchr(len(self._context)) + self._context + else: + dom2 = b"" + + PHM = msg_or_hash.digest() if ph else msg_or_hash + + # Section 5.1.7 + + # Step 1 + try: + R = import_public_key(signature[:32]).pointQ + except ValueError: + raise ValueError("The signature is not authentic (R)") + s = Integer.from_bytes(signature[32:], "little") + if s > self._order: + raise ValueError("The signature is not authentic (S)") + # Step 2 + k_hash = SHA512.new(dom2 + signature[:32] + self._A + PHM).digest() + k = Integer.from_bytes(k_hash, "little") % self._order + # Step 3 + point1 = s * 8 * self._key._curve.G + # OPTIMIZE: with double-scalar multiplication, with no SCA + # countermeasures because it is public values + point2 = 8 * R + k * 8 * self._key.pointQ + if point1 != point2: + raise ValueError("The signature is not authentic") + + def _verify_ed448(self, msg_or_hash, signature, ph): + if len(signature) != 114: + raise ValueError("The signature is not authentic (length)") + + flag = int(ph) + # dom4(flag, self._context) + dom4 = b"SigEd448" + bchr(flag) + bchr(len(self._context)) + self._context + + PHM = msg_or_hash.copy().read(64) if ph else msg_or_hash + + # Section 5.2.7 + + # Step 1 + try: + R = import_public_key(signature[:57]).pointQ + except ValueError: + raise ValueError("The signature is not authentic (R)") + s = Integer.from_bytes(signature[57:], "little") + if s > self._order: + raise ValueError("The signature is not authentic (S)") + # Step 2 + k_hash = SHAKE256.new(dom4 + signature[:57] + self._A + PHM).read(114) + k = Integer.from_bytes(k_hash, "little") % self._order + # Step 3 + point1 = s * 8 * self._key._curve.G + # OPTIMIZE: with double-scalar multiplication, with no SCA + # countermeasures because it is public values + point2 = 8 * R + k * 8 * self._key.pointQ + if point1 != point2: + raise ValueError("The signature is not authentic") def new(key, mode, context=None): - """Create a signature object :class:`EdDSASigScheme` that - can perform or verify an EdDSA signature. + """Create a signature object :class:`EdDSASigScheme` that + can perform or verify an EdDSA signature. - Args: - key (:class:`Cryptodome.PublicKey.ECC` object): - The key to use for computing the signature (*private* keys only) - or for verifying one. - The key must be on the curve ``Ed25519`` or ``Ed448``. + Args: + key (:class:`Cryptodome.PublicKey.ECC` object): + The key to use for computing the signature (*private* keys only) + or for verifying one. + The key must be on the curve ``Ed25519`` or ``Ed448``. - mode (string): - This parameter must be ``'rfc8032'``. + mode (string): + This parameter must be ``'rfc8032'``. - context (bytes): - Up to 255 bytes of `context `_, - which is a constant byte string to segregate different protocols or - different applications of the same key. - """ + context (bytes): + Up to 255 bytes of `context `_, + which is a constant byte string to segregate different protocols or + different applications of the same key. + """ - if not isinstance(key, EccKey) or key.curve not in ("Ed25519", "Ed448"): - raise ValueError("EdDSA can only be used with EdDSA keys") + if not isinstance(key, EccKey) or key.curve not in ("Ed25519", "Ed448"): + raise ValueError("EdDSA can only be used with EdDSA keys") - if mode != 'rfc8032': - raise ValueError("Mode must be 'rfc8032'") + if mode != "rfc8032": + raise ValueError("Mode must be 'rfc8032'") - if context is None: - context = b'' - elif len(context) > 255: - raise ValueError("Context for EdDSA must not be longer than 255 bytes") + if context is None: + context = b"" + elif len(context) > 255: + raise ValueError("Context for EdDSA must not be longer than 255 bytes") - return EdDSASigScheme(key, context) + return EdDSASigScheme(key, context) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/eddsa.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/eddsa.pyi index 809a7ad0..ffc5cafc 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/eddsa.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/eddsa.pyi @@ -3,19 +3,18 @@ from typing_extensions import Protocol from Cryptodome.PublicKey.ECC import EccKey class Hash(Protocol): - def digest(self) -> bytes: ... + def digest(self) -> bytes: ... class XOF(Protocol): - def read(self, len: int) -> bytes: ... + def read(self, len: int) -> bytes: ... def import_public_key(encoded: bytes) -> EccKey: ... def import_private_key(encoded: bytes) -> EccKey: ... class EdDSASigScheme(object): + def __init__(self, key: EccKey, context: bytes) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_or_hash: Union[bytes, Hash, XOF]) -> bytes: ... + def verify(self, msg_or_hash: Union[bytes, Hash, XOF], signature: bytes) -> None: ... - def __init__(self, key: EccKey, context: bytes) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_or_hash: Union[bytes, Hash, XOF]) -> bytes: ... - def verify(self, msg_or_hash: Union[bytes, Hash, XOF], signature: bytes) -> None: ... - -def new(key: EccKey, mode: str, context: Optional[bytes]=None) -> EdDSASigScheme: ... +def new(key: EccKey, mode: str, context: Optional[bytes] = None) -> EdDSASigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pkcs1_15.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pkcs1_15.py index bdde78ab..781436b5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pkcs1_15.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pkcs1_15.py @@ -32,192 +32,195 @@ from Cryptodome.Util.number import ceil_div, bytes_to_long, long_to_bytes from Cryptodome.Util.asn1 import DerSequence, DerNull, DerOctetString, DerObjectId + class PKCS115_SigScheme: - """A signature object for ``RSASSA-PKCS1-v1_5``. - Do not instantiate directly. - Use :func:`Cryptodome.Signature.pkcs1_15.new`. - """ - - def __init__(self, rsa_key): - """Initialize this PKCS#1 v1.5 signature scheme object. - - :Parameters: - rsa_key : an RSA key object - Creation of signatures is only possible if this is a *private* - RSA key. Verification of signatures is always possible. - """ - self._key = rsa_key - - def can_sign(self): - """Return ``True`` if this object can be used to sign messages.""" - return self._key.has_private() - - def sign(self, msg_hash): - """Create the PKCS#1 v1.5 signature of a message. - - This function is also called ``RSASSA-PKCS1-V1_5-SIGN`` and - it is specified in - `section 8.2.1 of RFC8017 `_. - - :parameter msg_hash: - This is an object from the :mod:`Cryptodome.Hash` package. - It has been used to digest the message to sign. - :type msg_hash: hash object - - :return: the signature encoded as a *byte string*. - :raise ValueError: if the RSA key is not long enough for the given hash algorithm. - :raise TypeError: if the RSA key has no private half. - """ - - # See 8.2.1 in RFC3447 - modBits = Cryptodome.Util.number.size(self._key.n) - k = ceil_div(modBits,8) # Convert from bits to bytes - - # Step 1 - em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k) - # Step 2a (OS2IP) - em_int = bytes_to_long(em) - # Step 2b (RSASP1) and Step 2c (I2OSP) - signature = self._key._decrypt_to_bytes(em_int) - # Verify no faults occurred - if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): - raise ValueError("Fault detected in RSA private key operation") - return signature - - def verify(self, msg_hash, signature): - """Check if the PKCS#1 v1.5 signature over a message is valid. - - This function is also called ``RSASSA-PKCS1-V1_5-VERIFY`` and - it is specified in - `section 8.2.2 of RFC8037 `_. - - :parameter msg_hash: - The hash that was carried out over the message. This is an object - belonging to the :mod:`Cryptodome.Hash` module. - :type parameter: hash object - - :parameter signature: - The signature that needs to be validated. - :type signature: byte string - - :raise ValueError: if the signature is not valid. - """ - - # See 8.2.2 in RFC3447 - modBits = Cryptodome.Util.number.size(self._key.n) - k = ceil_div(modBits, 8) # Convert from bits to bytes - - # Step 1 - if len(signature) != k: - raise ValueError("Invalid signature") - # Step 2a (O2SIP) - signature_int = bytes_to_long(signature) - # Step 2b (RSAVP1) - em_int = self._key._encrypt(signature_int) - # Step 2c (I2OSP) - em1 = long_to_bytes(em_int, k) - # Step 3 - try: - possible_em1 = [ _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True) ] - # MD2/4/5 hashes always require NULL params in AlgorithmIdentifier. - # For all others, it is optional. - try: - algorithm_is_md = msg_hash.oid.startswith('1.2.840.113549.2.') - except AttributeError: - algorithm_is_md = False - if not algorithm_is_md: # MD2/MD4/MD5 - possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False)) - except ValueError: - raise ValueError("Invalid signature") - # Step 4 - # By comparing the full encodings (as opposed to checking each - # of its components one at a time) we avoid attacks to the padding - # scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptography@metzdowd.com/msg06537). - # - if em1 not in possible_em1: - raise ValueError("Invalid signature") - pass + """A signature object for ``RSASSA-PKCS1-v1_5``. + Do not instantiate directly. + Use :func:`Cryptodome.Signature.pkcs1_15.new`. + """ + + def __init__(self, rsa_key): + """Initialize this PKCS#1 v1.5 signature scheme object. + + :Parameters: + rsa_key : an RSA key object + Creation of signatures is only possible if this is a *private* + RSA key. Verification of signatures is always possible. + """ + self._key = rsa_key + + def can_sign(self): + """Return ``True`` if this object can be used to sign messages.""" + return self._key.has_private() + + def sign(self, msg_hash): + """Create the PKCS#1 v1.5 signature of a message. + + This function is also called ``RSASSA-PKCS1-V1_5-SIGN`` and + it is specified in + `section 8.2.1 of RFC8017 `_. + + :parameter msg_hash: + This is an object from the :mod:`Cryptodome.Hash` package. + It has been used to digest the message to sign. + :type msg_hash: hash object + + :return: the signature encoded as a *byte string*. + :raise ValueError: if the RSA key is not long enough for the given hash algorithm. + :raise TypeError: if the RSA key has no private half. + """ + + # See 8.2.1 in RFC3447 + modBits = Cryptodome.Util.number.size(self._key.n) + k = ceil_div(modBits, 8) # Convert from bits to bytes + + # Step 1 + em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k) + # Step 2a (OS2IP) + em_int = bytes_to_long(em) + # Step 2b (RSASP1) and Step 2c (I2OSP) + signature = self._key._decrypt_to_bytes(em_int) + # Verify no faults occurred + if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): + raise ValueError("Fault detected in RSA private key operation") + return signature + + def verify(self, msg_hash, signature): + """Check if the PKCS#1 v1.5 signature over a message is valid. + + This function is also called ``RSASSA-PKCS1-V1_5-VERIFY`` and + it is specified in + `section 8.2.2 of RFC8037 `_. + + :parameter msg_hash: + The hash that was carried out over the message. This is an object + belonging to the :mod:`Cryptodome.Hash` module. + :type parameter: hash object + + :parameter signature: + The signature that needs to be validated. + :type signature: byte string + + :raise ValueError: if the signature is not valid. + """ + + # See 8.2.2 in RFC3447 + modBits = Cryptodome.Util.number.size(self._key.n) + k = ceil_div(modBits, 8) # Convert from bits to bytes + + # Step 1 + if len(signature) != k: + raise ValueError("Invalid signature") + # Step 2a (O2SIP) + signature_int = bytes_to_long(signature) + # Step 2b (RSAVP1) + em_int = self._key._encrypt(signature_int) + # Step 2c (I2OSP) + em1 = long_to_bytes(em_int, k) + # Step 3 + try: + possible_em1 = [_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True)] + # MD2/4/5 hashes always require NULL params in AlgorithmIdentifier. + # For all others, it is optional. + try: + algorithm_is_md = msg_hash.oid.startswith("1.2.840.113549.2.") + except AttributeError: + algorithm_is_md = False + if not algorithm_is_md: # MD2/MD4/MD5 + possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False)) + except ValueError: + raise ValueError("Invalid signature") + # Step 4 + # By comparing the full encodings (as opposed to checking each + # of its components one at a time) we avoid attacks to the padding + # scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptography@metzdowd.com/msg06537). + # + if em1 not in possible_em1: + raise ValueError("Invalid signature") + pass def _EMSA_PKCS1_V1_5_ENCODE(msg_hash, emLen, with_hash_parameters=True): - """ - Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined - in PKCS#1 v2.1 (RFC3447, 9.2). - - ``_EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input, - and hash it internally. Here, we expect that the message has already - been hashed instead. - - :Parameters: - msg_hash : hash object - The hash object that holds the digest of the message being signed. - emLen : int - The length the final encoding must have, in bytes. - with_hash_parameters : bool - If True (default), include NULL parameters for the hash - algorithm in the ``digestAlgorithm`` SEQUENCE. - - :attention: the early standard (RFC2313) stated that ``DigestInfo`` - had to be BER-encoded. This means that old signatures - might have length tags in indefinite form, which - is not supported in DER. Such encoding cannot be - reproduced by this function. - - :Return: An ``emLen`` byte long string that encodes the hash. - """ - - # First, build the ASN.1 DER object DigestInfo: - # - # DigestInfo ::= SEQUENCE { - # digestAlgorithm AlgorithmIdentifier, - # digest OCTET STRING - # } - # - # where digestAlgorithm identifies the hash function and shall be an - # algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms. - # - # PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= { - # { OID id-md2 PARAMETERS NULL }| - # { OID id-md5 PARAMETERS NULL }| - # { OID id-sha1 PARAMETERS NULL }| - # { OID id-sha256 PARAMETERS NULL }| - # { OID id-sha384 PARAMETERS NULL }| - # { OID id-sha512 PARAMETERS NULL } - # } - # - # Appendix B.1 also says that for SHA-1/-2 algorithms, the parameters - # should be omitted. They may be present, but when they are, they shall - # have NULL value. - - digestAlgo = DerSequence([ DerObjectId(msg_hash.oid).encode() ]) - - if with_hash_parameters: - digestAlgo.append(DerNull().encode()) - - digest = DerOctetString(msg_hash.digest()) - digestInfo = DerSequence([ - digestAlgo.encode(), - digest.encode() - ]).encode() - - # We need at least 11 bytes for the remaining data: 3 fixed bytes and - # at least 8 bytes of padding). - if emLen bytes: ... + def digest(self) -> bytes: ... class PKCS115_SigScheme: - def __init__(self, rsa_key: RsaKey) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> None: ... - -def _EMSA_PKCS1_V1_5_ENCODE(msg_hash: Hash, emLen: int, with_hash_parameters: Optional[bool]=True) -> bytes: ... + def __init__(self, rsa_key: RsaKey) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> None: ... +def _EMSA_PKCS1_V1_5_ENCODE( + msg_hash: Hash, emLen: int, with_hash_parameters: Optional[bool] = True +) -> bytes: ... def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pss.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pss.py index b929e26a..0059c98a 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pss.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pss.py @@ -30,358 +30,360 @@ from Cryptodome.Util.py3compat import bchr, bord, iter_range import Cryptodome.Util.number -from Cryptodome.Util.number import (ceil_div, - long_to_bytes, - bytes_to_long - ) +from Cryptodome.Util.number import ( + ceil_div, + long_to_bytes, + bytes_to_long, +) from Cryptodome.Util.strxor import strxor from Cryptodome import Random class PSS_SigScheme: - """A signature object for ``RSASSA-PSS``. - Do not instantiate directly. - Use :func:`Cryptodome.Signature.pss.new`. - """ - - def __init__(self, key, mgfunc, saltLen, randfunc): - """Initialize this PKCS#1 PSS signature scheme object. - - :Parameters: - key : an RSA key object - If a private half is given, both signature and - verification are possible. - If a public half is given, only verification is possible. - mgfunc : callable - A mask generation function that accepts two parameters: - a string to use as seed, and the lenth of the mask to - generate, in bytes. - saltLen : integer - Length of the salt, in bytes. - randfunc : callable - A function that returns random bytes. - """ - - self._key = key - self._saltLen = saltLen - self._mgfunc = mgfunc - self._randfunc = randfunc - - def can_sign(self): - """Return ``True`` if this object can be used to sign messages.""" - return self._key.has_private() - - def sign(self, msg_hash): - """Create the PKCS#1 PSS signature of a message. - - This function is also called ``RSASSA-PSS-SIGN`` and - it is specified in - `section 8.1.1 of RFC8017 `_. - - :parameter msg_hash: - This is an object from the :mod:`Cryptodome.Hash` package. - It has been used to digest the message to sign. - :type msg_hash: hash object - - :return: the signature encoded as a *byte string*. - :raise ValueError: if the RSA key is not long enough for the given hash algorithm. - :raise TypeError: if the RSA key has no private half. - """ - - # Set defaults for salt length and mask generation function - if self._saltLen is None: - sLen = msg_hash.digest_size - else: - sLen = self._saltLen - - if self._mgfunc is None: - mgf = lambda x, y: MGF1(x, y, msg_hash) - else: - mgf = self._mgfunc - - modBits = Cryptodome.Util.number.size(self._key.n) - - # See 8.1.1 in RFC3447 - k = ceil_div(modBits, 8) # k is length in bytes of the modulus - # Step 1 - em = _EMSA_PSS_ENCODE(msg_hash, modBits-1, self._randfunc, mgf, sLen) - # Step 2a (OS2IP) - em_int = bytes_to_long(em) - # Step 2b (RSASP1) and Step 2c (I2OSP) - signature = self._key._decrypt_to_bytes(em_int) - # Verify no faults occurred - if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): - raise ValueError("Fault detected in RSA private key operation") - return signature - - def verify(self, msg_hash, signature): - """Check if the PKCS#1 PSS signature over a message is valid. - - This function is also called ``RSASSA-PSS-VERIFY`` and - it is specified in - `section 8.1.2 of RFC8037 `_. - - :parameter msg_hash: - The hash that was carried out over the message. This is an object - belonging to the :mod:`Cryptodome.Hash` module. - :type parameter: hash object - - :parameter signature: - The signature that needs to be validated. - :type signature: bytes - - :raise ValueError: if the signature is not valid. - """ - - # Set defaults for salt length and mask generation function - if self._saltLen is None: - sLen = msg_hash.digest_size - else: - sLen = self._saltLen - if self._mgfunc: - mgf = self._mgfunc - else: - mgf = lambda x, y: MGF1(x, y, msg_hash) - - modBits = Cryptodome.Util.number.size(self._key.n) - - # See 8.1.2 in RFC3447 - k = ceil_div(modBits, 8) # Convert from bits to bytes - # Step 1 - if len(signature) != k: - raise ValueError("Incorrect signature") - # Step 2a (O2SIP) - signature_int = bytes_to_long(signature) - # Step 2b (RSAVP1) - em_int = self._key._encrypt(signature_int) - # Step 2c (I2OSP) - emLen = ceil_div(modBits - 1, 8) - em = long_to_bytes(em_int, emLen) - # Step 3/4 - _EMSA_PSS_VERIFY(msg_hash, em, modBits-1, mgf, sLen) + """A signature object for ``RSASSA-PSS``. + Do not instantiate directly. + Use :func:`Cryptodome.Signature.pss.new`. + """ + + def __init__(self, key, mgfunc, saltLen, randfunc): + """Initialize this PKCS#1 PSS signature scheme object. + + :Parameters: + key : an RSA key object + If a private half is given, both signature and + verification are possible. + If a public half is given, only verification is possible. + mgfunc : callable + A mask generation function that accepts two parameters: + a string to use as seed, and the lenth of the mask to + generate, in bytes. + saltLen : integer + Length of the salt, in bytes. + randfunc : callable + A function that returns random bytes. + """ + + self._key = key + self._saltLen = saltLen + self._mgfunc = mgfunc + self._randfunc = randfunc + + def can_sign(self): + """Return ``True`` if this object can be used to sign messages.""" + return self._key.has_private() + + def sign(self, msg_hash): + """Create the PKCS#1 PSS signature of a message. + + This function is also called ``RSASSA-PSS-SIGN`` and + it is specified in + `section 8.1.1 of RFC8017 `_. + + :parameter msg_hash: + This is an object from the :mod:`Cryptodome.Hash` package. + It has been used to digest the message to sign. + :type msg_hash: hash object + + :return: the signature encoded as a *byte string*. + :raise ValueError: if the RSA key is not long enough for the given hash algorithm. + :raise TypeError: if the RSA key has no private half. + """ + + # Set defaults for salt length and mask generation function + if self._saltLen is None: + sLen = msg_hash.digest_size + else: + sLen = self._saltLen + + if self._mgfunc is None: + mgf = lambda x, y: MGF1(x, y, msg_hash) + else: + mgf = self._mgfunc + + modBits = Cryptodome.Util.number.size(self._key.n) + + # See 8.1.1 in RFC3447 + k = ceil_div(modBits, 8) # k is length in bytes of the modulus + # Step 1 + em = _EMSA_PSS_ENCODE(msg_hash, modBits - 1, self._randfunc, mgf, sLen) + # Step 2a (OS2IP) + em_int = bytes_to_long(em) + # Step 2b (RSASP1) and Step 2c (I2OSP) + signature = self._key._decrypt_to_bytes(em_int) + # Verify no faults occurred + if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): + raise ValueError("Fault detected in RSA private key operation") + return signature + + def verify(self, msg_hash, signature): + """Check if the PKCS#1 PSS signature over a message is valid. + + This function is also called ``RSASSA-PSS-VERIFY`` and + it is specified in + `section 8.1.2 of RFC8037 `_. + + :parameter msg_hash: + The hash that was carried out over the message. This is an object + belonging to the :mod:`Cryptodome.Hash` module. + :type parameter: hash object + + :parameter signature: + The signature that needs to be validated. + :type signature: bytes + + :raise ValueError: if the signature is not valid. + """ + + # Set defaults for salt length and mask generation function + if self._saltLen is None: + sLen = msg_hash.digest_size + else: + sLen = self._saltLen + if self._mgfunc: + mgf = self._mgfunc + else: + mgf = lambda x, y: MGF1(x, y, msg_hash) + + modBits = Cryptodome.Util.number.size(self._key.n) + + # See 8.1.2 in RFC3447 + k = ceil_div(modBits, 8) # Convert from bits to bytes + # Step 1 + if len(signature) != k: + raise ValueError("Incorrect signature") + # Step 2a (O2SIP) + signature_int = bytes_to_long(signature) + # Step 2b (RSAVP1) + em_int = self._key._encrypt(signature_int) + # Step 2c (I2OSP) + emLen = ceil_div(modBits - 1, 8) + em = long_to_bytes(em_int, emLen) + # Step 3/4 + _EMSA_PSS_VERIFY(msg_hash, em, modBits - 1, mgf, sLen) def MGF1(mgfSeed, maskLen, hash_gen): - """Mask Generation Function, described in `B.2.1 of RFC8017 - `_. + """Mask Generation Function, described in `B.2.1 of RFC8017 + `_. - :param mfgSeed: - seed from which the mask is generated - :type mfgSeed: byte string + :param mfgSeed: + seed from which the mask is generated + :type mfgSeed: byte string - :param maskLen: - intended length in bytes of the mask - :type maskLen: integer + :param maskLen: + intended length in bytes of the mask + :type maskLen: integer - :param hash_gen: - A module or a hash object from :mod:`Cryptodome.Hash` - :type hash_object: + :param hash_gen: + A module or a hash object from :mod:`Cryptodome.Hash` + :type hash_object: - :return: the mask, as a *byte string* - """ + :return: the mask, as a *byte string* + """ - T = b"" - for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)): - c = long_to_bytes(counter, 4) - hobj = hash_gen.new() - hobj.update(mgfSeed + c) - T = T + hobj.digest() - assert(len(T) >= maskLen) - return T[:maskLen] + T = b"" + for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)): + c = long_to_bytes(counter, 4) + hobj = hash_gen.new() + hobj.update(mgfSeed + c) + T = T + hobj.digest() + assert len(T) >= maskLen + return T[:maskLen] def _EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen): - r""" - Implement the ``EMSA-PSS-ENCODE`` function, as defined - in PKCS#1 v2.1 (RFC3447, 9.1.1). - - The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` - as input, and hash it internally. Here, we expect that the message - has already been hashed instead. - - :Parameters: - mhash : hash object - The hash object that holds the digest of the message being signed. - emBits : int - Maximum length of the final encoding, in bits. - randFunc : callable - An RNG function that accepts as only parameter an int, and returns - a string of random bytes, to be used as salt. - mgf : callable - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - sLen : int - Length of the salt, in bytes. - - :Return: An ``emLen`` byte long string that encodes the hash - (with ``emLen = \ceil(emBits/8)``). - - :Raise ValueError: - When digest or salt length are too big. - """ - - emLen = ceil_div(emBits, 8) - - # Bitmask of digits that fill up - lmask = 0 - for i in iter_range(8*emLen-emBits): - lmask = lmask >> 1 | 0x80 - - # Step 1 and 2 have been already done - # Step 3 - if emLen < mhash.digest_size+sLen+2: - raise ValueError("Digest or salt length are too long" - " for given key size.") - # Step 4 - salt = randFunc(sLen) - # Step 5 - m_prime = bchr(0)*8 + mhash.digest() + salt - # Step 6 - h = mhash.new() - h.update(m_prime) - # Step 7 - ps = bchr(0)*(emLen-sLen-mhash.digest_size-2) - # Step 8 - db = ps + bchr(1) + salt - # Step 9 - dbMask = mgf(h.digest(), emLen-mhash.digest_size-1) - # Step 10 - maskedDB = strxor(db, dbMask) - # Step 11 - maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:] - # Step 12 - em = maskedDB + h.digest() + bchr(0xBC) - return em + r""" + Implement the ``EMSA-PSS-ENCODE`` function, as defined + in PKCS#1 v2.1 (RFC3447, 9.1.1). + + The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` + as input, and hash it internally. Here, we expect that the message + has already been hashed instead. + + :Parameters: + mhash : hash object + The hash object that holds the digest of the message being signed. + emBits : int + Maximum length of the final encoding, in bits. + randFunc : callable + An RNG function that accepts as only parameter an int, and returns + a string of random bytes, to be used as salt. + mgf : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + sLen : int + Length of the salt, in bytes. + + :Return: An ``emLen`` byte long string that encodes the hash + (with ``emLen = \ceil(emBits/8)``). + + :Raise ValueError: + When digest or salt length are too big. + """ + + emLen = ceil_div(emBits, 8) + + # Bitmask of digits that fill up + lmask = 0 + for i in iter_range(8 * emLen - emBits): + lmask = lmask >> 1 | 0x80 + + # Step 1 and 2 have been already done + # Step 3 + if emLen < mhash.digest_size + sLen + 2: + raise ValueError( + "Digest or salt length are too long for given key size.", + ) + # Step 4 + salt = randFunc(sLen) + # Step 5 + m_prime = bchr(0) * 8 + mhash.digest() + salt + # Step 6 + h = mhash.new() + h.update(m_prime) + # Step 7 + ps = bchr(0) * (emLen - sLen - mhash.digest_size - 2) + # Step 8 + db = ps + bchr(1) + salt + # Step 9 + dbMask = mgf(h.digest(), emLen - mhash.digest_size - 1) + # Step 10 + maskedDB = strxor(db, dbMask) + # Step 11 + maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:] + # Step 12 + em = maskedDB + h.digest() + bchr(0xBC) + return em def _EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen): - """ - Implement the ``EMSA-PSS-VERIFY`` function, as defined - in PKCS#1 v2.1 (RFC3447, 9.1.2). - - ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input, - and hash it internally. Here, we expect that the message has already - been hashed instead. - - :Parameters: - mhash : hash object - The hash object that holds the digest of the message to be verified. - em : string - The signature to verify, therefore proving that the sender really - signed the message that was received. - emBits : int - Length of the final encoding (em), in bits. - mgf : callable - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - sLen : int - Length of the salt, in bytes. - - :Raise ValueError: - When the encoding is inconsistent, or the digest or salt lengths - are too big. - """ - - emLen = ceil_div(emBits, 8) - - # Bitmask of digits that fill up - lmask = 0 - for i in iter_range(8*emLen-emBits): - lmask = lmask >> 1 | 0x80 - - # Step 1 and 2 have been already done - # Step 3 - if emLen < mhash.digest_size+sLen+2: - raise ValueError("Incorrect signature") - # Step 4 - if ord(em[-1:]) != 0xBC: - raise ValueError("Incorrect signature") - # Step 5 - maskedDB = em[:emLen-mhash.digest_size-1] - h = em[emLen-mhash.digest_size-1:-1] - # Step 6 - if lmask & bord(em[0]): - raise ValueError("Incorrect signature") - # Step 7 - dbMask = mgf(h, emLen-mhash.digest_size-1) - # Step 8 - db = strxor(maskedDB, dbMask) - # Step 9 - db = bchr(bord(db[0]) & ~lmask) + db[1:] - # Step 10 - if not db.startswith(bchr(0)*(emLen-mhash.digest_size-sLen-2) + bchr(1)): - raise ValueError("Incorrect signature") - # Step 11 - if sLen > 0: - salt = db[-sLen:] - else: - salt = b"" - # Step 12 - m_prime = bchr(0)*8 + mhash.digest() + salt - # Step 13 - hobj = mhash.new() - hobj.update(m_prime) - hp = hobj.digest() - # Step 14 - if h != hp: - raise ValueError("Incorrect signature") + """ + Implement the ``EMSA-PSS-VERIFY`` function, as defined + in PKCS#1 v2.1 (RFC3447, 9.1.2). + + ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input, + and hash it internally. Here, we expect that the message has already + been hashed instead. + + :Parameters: + mhash : hash object + The hash object that holds the digest of the message to be verified. + em : string + The signature to verify, therefore proving that the sender really + signed the message that was received. + emBits : int + Length of the final encoding (em), in bits. + mgf : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + sLen : int + Length of the salt, in bytes. + + :Raise ValueError: + When the encoding is inconsistent, or the digest or salt lengths + are too big. + """ + + emLen = ceil_div(emBits, 8) + + # Bitmask of digits that fill up + lmask = 0 + for i in iter_range(8 * emLen - emBits): + lmask = lmask >> 1 | 0x80 + + # Step 1 and 2 have been already done + # Step 3 + if emLen < mhash.digest_size + sLen + 2: + raise ValueError("Incorrect signature") + # Step 4 + if ord(em[-1:]) != 0xBC: + raise ValueError("Incorrect signature") + # Step 5 + maskedDB = em[: emLen - mhash.digest_size - 1] + h = em[emLen - mhash.digest_size - 1 : -1] + # Step 6 + if lmask & bord(em[0]): + raise ValueError("Incorrect signature") + # Step 7 + dbMask = mgf(h, emLen - mhash.digest_size - 1) + # Step 8 + db = strxor(maskedDB, dbMask) + # Step 9 + db = bchr(bord(db[0]) & ~lmask) + db[1:] + # Step 10 + if not db.startswith(bchr(0) * (emLen - mhash.digest_size - sLen - 2) + bchr(1)): + raise ValueError("Incorrect signature") + # Step 11 + if sLen > 0: + salt = db[-sLen:] + else: + salt = b"" + # Step 12 + m_prime = bchr(0) * 8 + mhash.digest() + salt + # Step 13 + hobj = mhash.new() + hobj.update(m_prime) + hp = hobj.digest() + # Step 14 + if h != hp: + raise ValueError("Incorrect signature") def new(rsa_key, **kwargs): - """Create an object for making or verifying PKCS#1 PSS signatures. - - :parameter rsa_key: - The RSA key to use for signing or verifying the message. - This is a :class:`Cryptodome.PublicKey.RSA` object. - Signing is only possible when ``rsa_key`` is a **private** RSA key. - :type rsa_key: RSA object - - :Keyword Arguments: - - * *mask_func* (``callable``) -- - A function that returns the mask (as `bytes`). - It must accept two parameters: a seed (as `bytes`) - and the length of the data to return. - - If not specified, it will be the function :func:`MGF1` defined in - `RFC8017 `_ and - combined with the same hash algorithm applied to the - message to sign or verify. - - If you want to use a different function, for instance still :func:`MGF1` - but together with another hash, you can do:: - - from Cryptodome.Hash import SHA256 - from Cryptodome.Signature.pss import MGF1 - mgf = lambda x, y: MGF1(x, y, SHA256) - - * *salt_bytes* (``integer``) -- - Length of the salt, in bytes. - It is a value between 0 and ``emLen - hLen - 2``, where ``emLen`` - is the size of the RSA modulus and ``hLen`` is the size of the digest - applied to the message to sign or verify. - - The salt is generated internally, you don't need to provide it. - - If not specified, the salt length will be ``hLen``. - If it is zero, the signature scheme becomes deterministic. - - Note that in some implementations such as OpenSSL the default - salt length is ``emLen - hLen - 2`` (even though it is not more - secure than ``hLen``). - - * *rand_func* (``callable``) -- - A function that returns random ``bytes``, of the desired length. - The default is :func:`Cryptodome.Random.get_random_bytes`. - - :return: a :class:`PSS_SigScheme` signature object - """ - - mask_func = kwargs.pop("mask_func", None) - salt_len = kwargs.pop("salt_bytes", None) - rand_func = kwargs.pop("rand_func", None) - if rand_func is None: - rand_func = Random.get_random_bytes - if kwargs: - raise ValueError("Unknown keywords: " + str(kwargs.keys())) - return PSS_SigScheme(rsa_key, mask_func, salt_len, rand_func) + """Create an object for making or verifying PKCS#1 PSS signatures. + + :parameter rsa_key: + The RSA key to use for signing or verifying the message. + This is a :class:`Cryptodome.PublicKey.RSA` object. + Signing is only possible when ``rsa_key`` is a **private** RSA key. + :type rsa_key: RSA object + + :Keyword Arguments: + + * *mask_func* (``callable``) -- + A function that returns the mask (as `bytes`). + It must accept two parameters: a seed (as `bytes`) + and the length of the data to return. + + If not specified, it will be the function :func:`MGF1` defined in + `RFC8017 `_ and + combined with the same hash algorithm applied to the + message to sign or verify. + + If you want to use a different function, for instance still :func:`MGF1` + but together with another hash, you can do:: + + from Cryptodome.Hash import SHA256 + from Cryptodome.Signature.pss import MGF1 + mgf = lambda x, y: MGF1(x, y, SHA256) + + * *salt_bytes* (``integer``) -- + Length of the salt, in bytes. + It is a value between 0 and ``emLen - hLen - 2``, where ``emLen`` + is the size of the RSA modulus and ``hLen`` is the size of the digest + applied to the message to sign or verify. + + The salt is generated internally, you don't need to provide it. + + If not specified, the salt length will be ``hLen``. + If it is zero, the signature scheme becomes deterministic. + + Note that in some implementations such as OpenSSL the default + salt length is ``emLen - hLen - 2`` (even though it is not more + secure than ``hLen``). + + * *rand_func* (``callable``) -- + A function that returns random ``bytes``, of the desired length. + The default is :func:`Cryptodome.Random.get_random_bytes`. + + :return: a :class:`PSS_SigScheme` signature object + """ + + mask_func = kwargs.pop("mask_func", None) + salt_len = kwargs.pop("salt_bytes", None) + rand_func = kwargs.pop("rand_func", None) + if rand_func is None: + rand_func = Random.get_random_bytes + if kwargs: + raise ValueError("Unknown keywords: " + str(kwargs.keys())) + return PSS_SigScheme(rsa_key, mask_func, salt_len, rand_func) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pss.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pss.pyi index 84a960e2..09a94500 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pss.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Signature/pss.pyi @@ -3,28 +3,27 @@ from typing_extensions import Protocol from Cryptodome.PublicKey.RSA import RsaKey - class Hash(Protocol): - def digest(self) -> bytes: ... - def update(self, bytes) -> None: ... - + def digest(self) -> bytes: ... + def update(self, bytes) -> None: ... class HashModule(Protocol): - @staticmethod - def new(data: Optional[bytes]) -> Hash: ... - + @staticmethod + def new(data: Optional[bytes]) -> Hash: ... MaskFunction = Callable[[bytes, int, Union[Hash, HashModule]], bytes] RndFunction = Callable[[int], bytes] class PSS_SigScheme: - def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> None: ... + def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ... + def can_sign(self) -> bool: ... + def sign(self, msg_hash: Hash) -> bytes: ... + def verify(self, msg_hash: Hash, signature: bytes) -> None: ... +MGF1: MaskFunction -MGF1 : MaskFunction -def _EMSA_PSS_ENCODE(mhash: Hash, emBits: int, randFunc: RndFunction, mgf:MaskFunction, sLen: int) -> str: ... +def _EMSA_PSS_ENCODE( + mhash: Hash, emBits: int, randFunc: RndFunction, mgf: MaskFunction, sLen: int +) -> str: ... def _EMSA_PSS_VERIFY(mhash: Hash, em: str, emBits: int, mgf: MaskFunction, sLen: int) -> None: ... def new(rsa_key: RsaKey, **kwargs: Union[MaskFunction, RndFunction, int]) -> PSS_SigScheme: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Counter.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Counter.py index e3bdcbec..0f301db8 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Counter.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Counter.py @@ -22,58 +22,60 @@ # SOFTWARE. # =================================================================== + def new(nbits, prefix=b"", suffix=b"", initial_value=1, little_endian=False, allow_wraparound=False): - """Create a stateful counter block function suitable for CTR encryption modes. + """Create a stateful counter block function suitable for CTR encryption modes. - Each call to the function returns the next counter block. - Each counter block is made up by three parts: + Each call to the function returns the next counter block. + Each counter block is made up by three parts: - +------+--------------+-------+ - |prefix| counter value|postfix| - +------+--------------+-------+ + +------+--------------+-------+ + |prefix| counter value|postfix| + +------+--------------+-------+ - The counter value is incremented by 1 at each call. + The counter value is incremented by 1 at each call. - Args: - nbits (integer): - Length of the desired counter value, in bits. It must be a multiple of 8. - prefix (byte string): - The constant prefix of the counter block. By default, no prefix is - used. - suffix (byte string): - The constant postfix of the counter block. By default, no suffix is - used. - initial_value (integer): - The initial value of the counter. Default value is 1. - Its length in bits must not exceed the argument ``nbits``. - little_endian (boolean): - If ``True``, the counter number will be encoded in little endian format. - If ``False`` (default), in big endian format. - allow_wraparound (boolean): - This parameter is ignored. - An ``OverflowError`` exception is always raised when the counter wraps - around to zero. - Returns: - An object that can be passed with the :data:`counter` parameter to a CTR mode - cipher. + Args: + nbits (integer): + Length of the desired counter value, in bits. It must be a multiple of 8. + prefix (byte string): + The constant prefix of the counter block. By default, no prefix is + used. + suffix (byte string): + The constant postfix of the counter block. By default, no suffix is + used. + initial_value (integer): + The initial value of the counter. Default value is 1. + Its length in bits must not exceed the argument ``nbits``. + little_endian (boolean): + If ``True``, the counter number will be encoded in little endian format. + If ``False`` (default), in big endian format. + allow_wraparound (boolean): + This parameter is ignored. + An ``OverflowError`` exception is always raised when the counter wraps + around to zero. + Returns: + An object that can be passed with the :data:`counter` parameter to a CTR mode + cipher. - It must hold that *len(prefix) + nbits//8 + len(suffix)* matches the - block size of the underlying block cipher. - """ + It must hold that *len(prefix) + nbits//8 + len(suffix)* matches the + block size of the underlying block cipher. + """ - if (nbits % 8) != 0: - raise ValueError("'nbits' must be a multiple of 8") + if (nbits % 8) != 0: + raise ValueError("'nbits' must be a multiple of 8") - iv_bl = initial_value.bit_length() - if iv_bl > nbits: - raise ValueError("Initial value takes %d bits but it is longer than " - "the counter (%d bits)" % - (iv_bl, nbits)) + iv_bl = initial_value.bit_length() + if iv_bl > nbits: + raise ValueError( + "Initial value takes %d bits but it is longer than the counter (%d bits)" % (iv_bl, nbits), + ) - # Ignore wraparound - return {"counter_len": nbits // 8, - "prefix": prefix, - "suffix": suffix, - "initial_value": initial_value, - "little_endian": little_endian - } + # Ignore wraparound + return { + "counter_len": nbits // 8, + "prefix": prefix, + "suffix": suffix, + "initial_value": initial_value, + "little_endian": little_endian, + } diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Counter.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Counter.pyi index fa2ffdd8..2372a87f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Counter.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Counter.pyi @@ -1,5 +1,10 @@ from typing import Optional, Union, Dict -def new(nbits: int, prefix: Optional[bytes]=..., suffix: Optional[bytes]=..., initial_value: Optional[int]=1, - little_endian: Optional[bool]=False, allow_wraparound: Optional[bool]=False) -> \ - Dict[str, Union[int, bytes, bool]]: ... +def new( + nbits: int, + prefix: Optional[bytes] = ..., + suffix: Optional[bytes] = ..., + initial_value: Optional[int] = 1, + little_endian: Optional[bool] = False, + allow_wraparound: Optional[bool] = False, +) -> Dict[str, Union[int, bytes, bool]]: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Padding.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Padding.py index 10165680..a337c819 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Padding.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Padding.py @@ -31,89 +31,88 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -__all__ = [ 'pad', 'unpad' ] +__all__ = ["pad", "unpad"] from Cryptodome.Util.py3compat import * -def pad(data_to_pad, block_size, style='pkcs7'): - """Apply standard padding. +def pad(data_to_pad, block_size, style="pkcs7"): + """Apply standard padding. - Args: - data_to_pad (byte string): - The data that needs to be padded. - block_size (integer): - The block boundary to use for padding. The output length is guaranteed - to be a multiple of :data:`block_size`. - style (string): - Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. + Args: + data_to_pad (byte string): + The data that needs to be padded. + block_size (integer): + The block boundary to use for padding. The output length is guaranteed + to be a multiple of :data:`block_size`. + style (string): + Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. - Return: - byte string : the original data with the appropriate padding added at the end. - """ + Return: + byte string : the original data with the appropriate padding added at the end. + """ - padding_len = block_size - len(data_to_pad) % block_size + padding_len = block_size - len(data_to_pad) % block_size - if style == 'pkcs7': - padding = bchr(padding_len) * padding_len - elif style == 'x923': - padding = bchr(0)*(padding_len-1) + bchr(padding_len) - elif style == 'iso7816': - padding = bchr(128) + bchr(0) * (padding_len-1) - else: - raise ValueError("Unknown padding style") + if style == "pkcs7": + padding = bchr(padding_len) * padding_len + elif style == "x923": + padding = bchr(0) * (padding_len - 1) + bchr(padding_len) + elif style == "iso7816": + padding = bchr(128) + bchr(0) * (padding_len - 1) + else: + raise ValueError("Unknown padding style") - return data_to_pad + padding + return data_to_pad + padding -def unpad(padded_data, block_size, style='pkcs7'): - """Remove standard padding. +def unpad(padded_data, block_size, style="pkcs7"): + """Remove standard padding. - Args: - padded_data (byte string): - A piece of data with padding that needs to be stripped. - block_size (integer): - The block boundary to use for padding. The input length - must be a multiple of :data:`block_size`. - style (string): - Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. - Return: - byte string : data without padding. - Raises: - ValueError: if the padding is incorrect. - """ + Args: + padded_data (byte string): + A piece of data with padding that needs to be stripped. + block_size (integer): + The block boundary to use for padding. The input length + must be a multiple of :data:`block_size`. + style (string): + Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. + Return: + byte string : data without padding. + Raises: + ValueError: if the padding is incorrect. + """ - pdata_len = len(padded_data) + pdata_len = len(padded_data) - if pdata_len == 0: - raise ValueError("Zero-length input cannot be unpadded") + if pdata_len == 0: + raise ValueError("Zero-length input cannot be unpadded") - if pdata_len % block_size: - raise ValueError("Input data is not padded") + if pdata_len % block_size: + raise ValueError("Input data is not padded") - if style in ('pkcs7', 'x923'): - padding_len = bord(padded_data[-1]) + if style in ("pkcs7", "x923"): + padding_len = bord(padded_data[-1]) - if padding_len < 1 or padding_len > min(block_size, pdata_len): - raise ValueError("Padding is incorrect.") + if padding_len < 1 or padding_len > min(block_size, pdata_len): + raise ValueError("Padding is incorrect.") - if style == 'pkcs7': - if padded_data[-padding_len:] != bchr(padding_len)*padding_len: - raise ValueError("PKCS#7 padding is incorrect.") - else: - if padded_data[-padding_len:-1] != bchr(0)*(padding_len-1): - raise ValueError("ANSI X.923 padding is incorrect.") + if style == "pkcs7": + if padded_data[-padding_len:] != bchr(padding_len) * padding_len: + raise ValueError("PKCS#7 padding is incorrect.") + else: + if padded_data[-padding_len:-1] != bchr(0) * (padding_len - 1): + raise ValueError("ANSI X.923 padding is incorrect.") - elif style == 'iso7816': - padding_len = pdata_len - padded_data.rfind(bchr(128)) + elif style == "iso7816": + padding_len = pdata_len - padded_data.rfind(bchr(128)) - if padding_len < 1 or padding_len > min(block_size, pdata_len): - raise ValueError("Padding is incorrect.") + if padding_len < 1 or padding_len > min(block_size, pdata_len): + raise ValueError("Padding is incorrect.") - if padding_len > 1 and padded_data[1-padding_len:] != bchr(0)*(padding_len-1): - raise ValueError("ISO 7816-4 padding is incorrect.") - else: - raise ValueError("Unknown padding style") - - return padded_data[:-padding_len] + if padding_len > 1 and padded_data[1 - padding_len :] != bchr(0) * (padding_len - 1): + raise ValueError("ISO 7816-4 padding is incorrect.") + else: + raise ValueError("Unknown padding style") + return padded_data[:-padding_len] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Padding.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Padding.pyi index 4d8d30df..d381eac5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Padding.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/Padding.pyi @@ -1,6 +1,6 @@ from typing import Optional -__all__ = [ 'pad', 'unpad' ] +__all__ = ["pad", "unpad"] -def pad(data_to_pad: bytes, block_size: int, style: Optional[str]='pkcs7') -> bytes: ... -def unpad(padded_data: bytes, block_size: int, style: Optional[str]='pkcs7') -> bytes: ... \ No newline at end of file +def pad(data_to_pad: bytes, block_size: int, style: Optional[str] = "pkcs7") -> bytes: ... +def unpad(padded_data: bytes, block_size: int, style: Optional[str] = "pkcs7") -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/RFC1751.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/RFC1751.py index 10859c3f..a8211936 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/RFC1751.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/RFC1751.py @@ -26,361 +26,2181 @@ from __future__ import print_function -import binascii from Cryptodome.Util.py3compat import bord, bchr -binary = {0: '0000', 1: '0001', 2: '0010', 3: '0011', 4: '0100', 5: '0101', - 6: '0110', 7: '0111', 8: '1000', 9: '1001', 10: '1010', 11: '1011', - 12: '1100', 13: '1101', 14: '1110', 15: '1111'} +binary = { + 0: "0000", + 1: "0001", + 2: "0010", + 3: "0011", + 4: "0100", + 5: "0101", + 6: "0110", + 7: "0111", + 8: "1000", + 9: "1001", + 10: "1010", + 11: "1011", + 12: "1100", + 13: "1101", + 14: "1110", + 15: "1111", +} def _key2bin(s): - "Convert a key into a string of binary digits" - kl = map(lambda x: bord(x), s) - kl = map(lambda x: binary[x >> 4] + binary[x & 15], kl) - return ''.join(kl) + "Convert a key into a string of binary digits" + kl = map(lambda x: bord(x), s) + kl = map(lambda x: binary[x >> 4] + binary[x & 15], kl) + return "".join(kl) def _extract(key, start, length): - """Extract a bitstring(2.x)/bytestring(2.x) from a string of binary digits, and return its - numeric value.""" + """Extract a bitstring(2.x)/bytestring(2.x) from a string of binary digits, and return its + numeric value.""" - result = 0 - for y in key[start:start+length]: - result = result * 2 + ord(y) - 48 - return result + result = 0 + for y in key[start : start + length]: + result = result * 2 + ord(y) - 48 + return result def key_to_english(key): - """Transform an arbitrary key into a string containing English words. + """Transform an arbitrary key into a string containing English words. - Example:: + Example:: - >>> from Cryptodome.Util.RFC1751 import key_to_english - >>> key_to_english(b'66666666') - 'RAM LOIS GOAD CREW CARE HIT' + >>> from Cryptodome.Util.RFC1751 import key_to_english + >>> key_to_english(b'66666666') + 'RAM LOIS GOAD CREW CARE HIT' - Args: - key (byte string): - The key to convert. Its length must be a multiple of 8. - Return: - A string of English words. - """ + Args: + key (byte string): + The key to convert. Its length must be a multiple of 8. + Return: + A string of English words. + """ - if len(key) % 8 != 0: - raise ValueError('The length of the key must be a multiple of 8.') + if len(key) % 8 != 0: + raise ValueError("The length of the key must be a multiple of 8.") - english = '' - for index in range(0, len(key), 8): # Loop over 8-byte subkeys - subkey = key[index:index + 8] - # Compute the parity of the key - skbin = _key2bin(subkey) - p = 0 - for i in range(0, 64, 2): - p = p + _extract(skbin, i, 2) - # Append parity bits to the subkey - skbin = _key2bin(subkey + bchr((p << 6) & 255)) - for i in range(0, 64, 11): - english = english + wordlist[_extract(skbin, i, 11)] + ' ' + english = "" + for index in range(0, len(key), 8): # Loop over 8-byte subkeys + subkey = key[index : index + 8] + # Compute the parity of the key + skbin = _key2bin(subkey) + p = 0 + for i in range(0, 64, 2): + p = p + _extract(skbin, i, 2) + # Append parity bits to the subkey + skbin = _key2bin(subkey + bchr((p << 6) & 255)) + for i in range(0, 64, 11): + english = english + wordlist[_extract(skbin, i, 11)] + " " - return english.strip() + return english.strip() def english_to_key(s): - """Transform a string into a corresponding key. + """Transform a string into a corresponding key. - Example:: + Example:: - >>> from Cryptodome.Util.RFC1751 import english_to_key - >>> english_to_key('RAM LOIS GOAD CREW CARE HIT') - b'66666666' + >>> from Cryptodome.Util.RFC1751 import english_to_key + >>> english_to_key('RAM LOIS GOAD CREW CARE HIT') + b'66666666' - Args: - s (string): the string with the words separated by whitespace; - the number of words must be a multiple of 6. - Return: - A byte string. - """ + Args: + s (string): the string with the words separated by whitespace; + the number of words must be a multiple of 6. + Return: + A byte string. + """ - L = s.upper().split() - key = b'' - for index in range(0, len(L), 6): - sublist = L[index:index + 6] - char = 9 * [0] - bits = 0 - for i in sublist: - index = wordlist.index(i) - shift = (8 - (bits + 11) % 8) % 8 - y = index << shift - cl, cc, cr = (y >> 16), (y >> 8) & 0xff, y & 0xff - if (shift > 5): - char[bits >> 3] = char[bits >> 3] | cl - char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cc - char[(bits >> 3) + 2] = char[(bits >> 3) + 2] | cr - elif shift > -3: - char[bits >> 3] = char[bits >> 3] | cc - char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cr - else: - char[bits >> 3] = char[bits >> 3] | cr - bits = bits + 11 + L = s.upper().split() + key = b"" + for index in range(0, len(L), 6): + sublist = L[index : index + 6] + char = 9 * [0] + bits = 0 + for i in sublist: + index = wordlist.index(i) + shift = (8 - (bits + 11) % 8) % 8 + y = index << shift + cl, cc, cr = (y >> 16), (y >> 8) & 0xFF, y & 0xFF + if shift > 5: + char[bits >> 3] = char[bits >> 3] | cl + char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cc + char[(bits >> 3) + 2] = char[(bits >> 3) + 2] | cr + elif shift > -3: + char[bits >> 3] = char[bits >> 3] | cc + char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cr + else: + char[bits >> 3] = char[bits >> 3] | cr + bits = bits + 11 - subkey = b'' - for y in char: - subkey = subkey + bchr(y) + subkey = b"" + for y in char: + subkey = subkey + bchr(y) - # Check the parity of the resulting key - skbin = _key2bin(subkey) - p = 0 - for i in range(0, 64, 2): - p = p + _extract(skbin, i, 2) - if (p & 3) != _extract(skbin, 64, 2): - raise ValueError("Parity error in resulting key") - key = key + subkey[0:8] - return key + # Check the parity of the resulting key + skbin = _key2bin(subkey) + p = 0 + for i in range(0, 64, 2): + p = p + _extract(skbin, i, 2) + if (p & 3) != _extract(skbin, 64, 2): + raise ValueError("Parity error in resulting key") + key = key + subkey[0:8] + return key wordlist = [ - "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", - "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA", - "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK", - "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE", - "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM", - "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", - "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO", - "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT", - "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", - "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY", - "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN", - "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG", - "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB", - "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO", - "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE", - "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW", - "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", - "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP", - "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO", - "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD", - "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", - "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT", - "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE", - "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL", - "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", - "ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", - "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", - "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", - "LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", - "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", - "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", - "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", - "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", - "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", - "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", - "NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", - "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", - "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", - "OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", - "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", - "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", - "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", - "PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", - "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", - "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", - "RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", - "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", - "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", - "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", - "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", - "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", - "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", - "TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", - "TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", - "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", - "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", - "WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", - "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", - "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", - "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", - "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA", - "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN", - "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW", - "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA", - "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM", - "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW", - "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", - "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", - "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK", - "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", - "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT", - "BEAU", "BECK", "BEEF", "BEEN", "BEER", - "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", - "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", - "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE", - "BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", - "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", - "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT", - "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK", - "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS", - "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN", - "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", - "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", - "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", - "BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", - "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL", - "CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL", - "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF", - "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG", - "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY", - "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", - "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", - "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK", - "COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST", - "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB", - "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY", - "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE", - "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN", - "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS", - "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", - "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", - "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT", - "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", - "DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA", - "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG", - "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK", - "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK", - "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", - "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", - "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", - "EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", - "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", - "FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT", - "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST", - "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE", - "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE", - "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", - "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", - "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", - "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", - "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", - "FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY", - "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA", - "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH", - "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE", - "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", - "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", - "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", - "GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", - "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", - "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN", - "GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH", - "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR", - "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK", - "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE", - "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", - "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", - "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", - "HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT", - "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", - "HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK", - "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL", - "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK", - "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE", - "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", - "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", - "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", - "JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL", - "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", - "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY", - "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST", - "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL", - "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL", - "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", - "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", - "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", - "LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", - "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS", - "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER", - "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST", - "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU", - "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB", - "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", - "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", - "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", - "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", - "LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE", - "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE", - "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI", - "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK", - "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE", - "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", - "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", - "MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", - "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", - "MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD", - "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON", - "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH", - "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK", - "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", - "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", - "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", - "NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", - "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", - "NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB", - "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY", - "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE", - "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS", - "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", - "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", - "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", - "RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", - "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA", - "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT", - "RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD", - "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME", - "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS", - "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", - "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", - "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", - "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE", - "SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", - "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK", - "SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS", - "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN", - "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE", - "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE", - "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", - "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", - "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", - "SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", - "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA", - "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE", - "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR", - "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH", - "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF", - "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", - "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", - "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", - "TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS", - "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN", - "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER", - "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY", - "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG", - "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR", - "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", - "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", - "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", - "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", - "USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST", - "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", - "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE", - "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK", - "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM", - "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", - "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", - "WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", - "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", - "WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE", - "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD", - "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", - "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR", - "YELL", "YOGA", "YOKE" ] + "A", + "ABE", + "ACE", + "ACT", + "AD", + "ADA", + "ADD", + "AGO", + "AID", + "AIM", + "AIR", + "ALL", + "ALP", + "AM", + "AMY", + "AN", + "ANA", + "AND", + "ANN", + "ANT", + "ANY", + "APE", + "APS", + "APT", + "ARC", + "ARE", + "ARK", + "ARM", + "ART", + "AS", + "ASH", + "ASK", + "AT", + "ATE", + "AUG", + "AUK", + "AVE", + "AWE", + "AWK", + "AWL", + "AWN", + "AX", + "AYE", + "BAD", + "BAG", + "BAH", + "BAM", + "BAN", + "BAR", + "BAT", + "BAY", + "BE", + "BED", + "BEE", + "BEG", + "BEN", + "BET", + "BEY", + "BIB", + "BID", + "BIG", + "BIN", + "BIT", + "BOB", + "BOG", + "BON", + "BOO", + "BOP", + "BOW", + "BOY", + "BUB", + "BUD", + "BUG", + "BUM", + "BUN", + "BUS", + "BUT", + "BUY", + "BY", + "BYE", + "CAB", + "CAL", + "CAM", + "CAN", + "CAP", + "CAR", + "CAT", + "CAW", + "COD", + "COG", + "COL", + "CON", + "COO", + "COP", + "COT", + "COW", + "COY", + "CRY", + "CUB", + "CUE", + "CUP", + "CUR", + "CUT", + "DAB", + "DAD", + "DAM", + "DAN", + "DAR", + "DAY", + "DEE", + "DEL", + "DEN", + "DES", + "DEW", + "DID", + "DIE", + "DIG", + "DIN", + "DIP", + "DO", + "DOE", + "DOG", + "DON", + "DOT", + "DOW", + "DRY", + "DUB", + "DUD", + "DUE", + "DUG", + "DUN", + "EAR", + "EAT", + "ED", + "EEL", + "EGG", + "EGO", + "ELI", + "ELK", + "ELM", + "ELY", + "EM", + "END", + "EST", + "ETC", + "EVA", + "EVE", + "EWE", + "EYE", + "FAD", + "FAN", + "FAR", + "FAT", + "FAY", + "FED", + "FEE", + "FEW", + "FIB", + "FIG", + "FIN", + "FIR", + "FIT", + "FLO", + "FLY", + "FOE", + "FOG", + "FOR", + "FRY", + "FUM", + "FUN", + "FUR", + "GAB", + "GAD", + "GAG", + "GAL", + "GAM", + "GAP", + "GAS", + "GAY", + "GEE", + "GEL", + "GEM", + "GET", + "GIG", + "GIL", + "GIN", + "GO", + "GOT", + "GUM", + "GUN", + "GUS", + "GUT", + "GUY", + "GYM", + "GYP", + "HA", + "HAD", + "HAL", + "HAM", + "HAN", + "HAP", + "HAS", + "HAT", + "HAW", + "HAY", + "HE", + "HEM", + "HEN", + "HER", + "HEW", + "HEY", + "HI", + "HID", + "HIM", + "HIP", + "HIS", + "HIT", + "HO", + "HOB", + "HOC", + "HOE", + "HOG", + "HOP", + "HOT", + "HOW", + "HUB", + "HUE", + "HUG", + "HUH", + "HUM", + "HUT", + "I", + "ICY", + "IDA", + "IF", + "IKE", + "ILL", + "INK", + "INN", + "IO", + "ION", + "IQ", + "IRA", + "IRE", + "IRK", + "IS", + "IT", + "ITS", + "IVY", + "JAB", + "JAG", + "JAM", + "JAN", + "JAR", + "JAW", + "JAY", + "JET", + "JIG", + "JIM", + "JO", + "JOB", + "JOE", + "JOG", + "JOT", + "JOY", + "JUG", + "JUT", + "KAY", + "KEG", + "KEN", + "KEY", + "KID", + "KIM", + "KIN", + "KIT", + "LA", + "LAB", + "LAC", + "LAD", + "LAG", + "LAM", + "LAP", + "LAW", + "LAY", + "LEA", + "LED", + "LEE", + "LEG", + "LEN", + "LEO", + "LET", + "LEW", + "LID", + "LIE", + "LIN", + "LIP", + "LIT", + "LO", + "LOB", + "LOG", + "LOP", + "LOS", + "LOT", + "LOU", + "LOW", + "LOY", + "LUG", + "LYE", + "MA", + "MAC", + "MAD", + "MAE", + "MAN", + "MAO", + "MAP", + "MAT", + "MAW", + "MAY", + "ME", + "MEG", + "MEL", + "MEN", + "MET", + "MEW", + "MID", + "MIN", + "MIT", + "MOB", + "MOD", + "MOE", + "MOO", + "MOP", + "MOS", + "MOT", + "MOW", + "MUD", + "MUG", + "MUM", + "MY", + "NAB", + "NAG", + "NAN", + "NAP", + "NAT", + "NAY", + "NE", + "NED", + "NEE", + "NET", + "NEW", + "NIB", + "NIL", + "NIP", + "NIT", + "NO", + "NOB", + "NOD", + "NON", + "NOR", + "NOT", + "NOV", + "NOW", + "NU", + "NUN", + "NUT", + "O", + "OAF", + "OAK", + "OAR", + "OAT", + "ODD", + "ODE", + "OF", + "OFF", + "OFT", + "OH", + "OIL", + "OK", + "OLD", + "ON", + "ONE", + "OR", + "ORB", + "ORE", + "ORR", + "OS", + "OTT", + "OUR", + "OUT", + "OVA", + "OW", + "OWE", + "OWL", + "OWN", + "OX", + "PA", + "PAD", + "PAL", + "PAM", + "PAN", + "PAP", + "PAR", + "PAT", + "PAW", + "PAY", + "PEA", + "PEG", + "PEN", + "PEP", + "PER", + "PET", + "PEW", + "PHI", + "PI", + "PIE", + "PIN", + "PIT", + "PLY", + "PO", + "POD", + "POE", + "POP", + "POT", + "POW", + "PRO", + "PRY", + "PUB", + "PUG", + "PUN", + "PUP", + "PUT", + "QUO", + "RAG", + "RAM", + "RAN", + "RAP", + "RAT", + "RAW", + "RAY", + "REB", + "RED", + "REP", + "RET", + "RIB", + "RID", + "RIG", + "RIM", + "RIO", + "RIP", + "ROB", + "ROD", + "ROE", + "RON", + "ROT", + "ROW", + "ROY", + "RUB", + "RUE", + "RUG", + "RUM", + "RUN", + "RYE", + "SAC", + "SAD", + "SAG", + "SAL", + "SAM", + "SAN", + "SAP", + "SAT", + "SAW", + "SAY", + "SEA", + "SEC", + "SEE", + "SEN", + "SET", + "SEW", + "SHE", + "SHY", + "SIN", + "SIP", + "SIR", + "SIS", + "SIT", + "SKI", + "SKY", + "SLY", + "SO", + "SOB", + "SOD", + "SON", + "SOP", + "SOW", + "SOY", + "SPA", + "SPY", + "SUB", + "SUD", + "SUE", + "SUM", + "SUN", + "SUP", + "TAB", + "TAD", + "TAG", + "TAN", + "TAP", + "TAR", + "TEA", + "TED", + "TEE", + "TEN", + "THE", + "THY", + "TIC", + "TIE", + "TIM", + "TIN", + "TIP", + "TO", + "TOE", + "TOG", + "TOM", + "TON", + "TOO", + "TOP", + "TOW", + "TOY", + "TRY", + "TUB", + "TUG", + "TUM", + "TUN", + "TWO", + "UN", + "UP", + "US", + "USE", + "VAN", + "VAT", + "VET", + "VIE", + "WAD", + "WAG", + "WAR", + "WAS", + "WAY", + "WE", + "WEB", + "WED", + "WEE", + "WET", + "WHO", + "WHY", + "WIN", + "WIT", + "WOK", + "WON", + "WOO", + "WOW", + "WRY", + "WU", + "YAM", + "YAP", + "YAW", + "YE", + "YEA", + "YES", + "YET", + "YOU", + "ABED", + "ABEL", + "ABET", + "ABLE", + "ABUT", + "ACHE", + "ACID", + "ACME", + "ACRE", + "ACTA", + "ACTS", + "ADAM", + "ADDS", + "ADEN", + "AFAR", + "AFRO", + "AGEE", + "AHEM", + "AHOY", + "AIDA", + "AIDE", + "AIDS", + "AIRY", + "AJAR", + "AKIN", + "ALAN", + "ALEC", + "ALGA", + "ALIA", + "ALLY", + "ALMA", + "ALOE", + "ALSO", + "ALTO", + "ALUM", + "ALVA", + "AMEN", + "AMES", + "AMID", + "AMMO", + "AMOK", + "AMOS", + "AMRA", + "ANDY", + "ANEW", + "ANNA", + "ANNE", + "ANTE", + "ANTI", + "AQUA", + "ARAB", + "ARCH", + "AREA", + "ARGO", + "ARID", + "ARMY", + "ARTS", + "ARTY", + "ASIA", + "ASKS", + "ATOM", + "AUNT", + "AURA", + "AUTO", + "AVER", + "AVID", + "AVIS", + "AVON", + "AVOW", + "AWAY", + "AWRY", + "BABE", + "BABY", + "BACH", + "BACK", + "BADE", + "BAIL", + "BAIT", + "BAKE", + "BALD", + "BALE", + "BALI", + "BALK", + "BALL", + "BALM", + "BAND", + "BANE", + "BANG", + "BANK", + "BARB", + "BARD", + "BARE", + "BARK", + "BARN", + "BARR", + "BASE", + "BASH", + "BASK", + "BASS", + "BATE", + "BATH", + "BAWD", + "BAWL", + "BEAD", + "BEAK", + "BEAM", + "BEAN", + "BEAR", + "BEAT", + "BEAU", + "BECK", + "BEEF", + "BEEN", + "BEER", + "BEET", + "BELA", + "BELL", + "BELT", + "BEND", + "BENT", + "BERG", + "BERN", + "BERT", + "BESS", + "BEST", + "BETA", + "BETH", + "BHOY", + "BIAS", + "BIDE", + "BIEN", + "BILE", + "BILK", + "BILL", + "BIND", + "BING", + "BIRD", + "BITE", + "BITS", + "BLAB", + "BLAT", + "BLED", + "BLEW", + "BLOB", + "BLOC", + "BLOT", + "BLOW", + "BLUE", + "BLUM", + "BLUR", + "BOAR", + "BOAT", + "BOCA", + "BOCK", + "BODE", + "BODY", + "BOGY", + "BOHR", + "BOIL", + "BOLD", + "BOLO", + "BOLT", + "BOMB", + "BONA", + "BOND", + "BONE", + "BONG", + "BONN", + "BONY", + "BOOK", + "BOOM", + "BOON", + "BOOT", + "BORE", + "BORG", + "BORN", + "BOSE", + "BOSS", + "BOTH", + "BOUT", + "BOWL", + "BOYD", + "BRAD", + "BRAE", + "BRAG", + "BRAN", + "BRAY", + "BRED", + "BREW", + "BRIG", + "BRIM", + "BROW", + "BUCK", + "BUDD", + "BUFF", + "BULB", + "BULK", + "BULL", + "BUNK", + "BUNT", + "BUOY", + "BURG", + "BURL", + "BURN", + "BURR", + "BURT", + "BURY", + "BUSH", + "BUSS", + "BUST", + "BUSY", + "BYTE", + "CADY", + "CAFE", + "CAGE", + "CAIN", + "CAKE", + "CALF", + "CALL", + "CALM", + "CAME", + "CANE", + "CANT", + "CARD", + "CARE", + "CARL", + "CARR", + "CART", + "CASE", + "CASH", + "CASK", + "CAST", + "CAVE", + "CEIL", + "CELL", + "CENT", + "CERN", + "CHAD", + "CHAR", + "CHAT", + "CHAW", + "CHEF", + "CHEN", + "CHEW", + "CHIC", + "CHIN", + "CHOU", + "CHOW", + "CHUB", + "CHUG", + "CHUM", + "CITE", + "CITY", + "CLAD", + "CLAM", + "CLAN", + "CLAW", + "CLAY", + "CLOD", + "CLOG", + "CLOT", + "CLUB", + "CLUE", + "COAL", + "COAT", + "COCA", + "COCK", + "COCO", + "CODA", + "CODE", + "CODY", + "COED", + "COIL", + "COIN", + "COKE", + "COLA", + "COLD", + "COLT", + "COMA", + "COMB", + "COME", + "COOK", + "COOL", + "COON", + "COOT", + "CORD", + "CORE", + "CORK", + "CORN", + "COST", + "COVE", + "COWL", + "CRAB", + "CRAG", + "CRAM", + "CRAY", + "CREW", + "CRIB", + "CROW", + "CRUD", + "CUBA", + "CUBE", + "CUFF", + "CULL", + "CULT", + "CUNY", + "CURB", + "CURD", + "CURE", + "CURL", + "CURT", + "CUTS", + "DADE", + "DALE", + "DAME", + "DANA", + "DANE", + "DANG", + "DANK", + "DARE", + "DARK", + "DARN", + "DART", + "DASH", + "DATA", + "DATE", + "DAVE", + "DAVY", + "DAWN", + "DAYS", + "DEAD", + "DEAF", + "DEAL", + "DEAN", + "DEAR", + "DEBT", + "DECK", + "DEED", + "DEEM", + "DEER", + "DEFT", + "DEFY", + "DELL", + "DENT", + "DENY", + "DESK", + "DIAL", + "DICE", + "DIED", + "DIET", + "DIME", + "DINE", + "DING", + "DINT", + "DIRE", + "DIRT", + "DISC", + "DISH", + "DISK", + "DIVE", + "DOCK", + "DOES", + "DOLE", + "DOLL", + "DOLT", + "DOME", + "DONE", + "DOOM", + "DOOR", + "DORA", + "DOSE", + "DOTE", + "DOUG", + "DOUR", + "DOVE", + "DOWN", + "DRAB", + "DRAG", + "DRAM", + "DRAW", + "DREW", + "DRUB", + "DRUG", + "DRUM", + "DUAL", + "DUCK", + "DUCT", + "DUEL", + "DUET", + "DUKE", + "DULL", + "DUMB", + "DUNE", + "DUNK", + "DUSK", + "DUST", + "DUTY", + "EACH", + "EARL", + "EARN", + "EASE", + "EAST", + "EASY", + "EBEN", + "ECHO", + "EDDY", + "EDEN", + "EDGE", + "EDGY", + "EDIT", + "EDNA", + "EGAN", + "ELAN", + "ELBA", + "ELLA", + "ELSE", + "EMIL", + "EMIT", + "EMMA", + "ENDS", + "ERIC", + "EROS", + "EVEN", + "EVER", + "EVIL", + "EYED", + "FACE", + "FACT", + "FADE", + "FAIL", + "FAIN", + "FAIR", + "FAKE", + "FALL", + "FAME", + "FANG", + "FARM", + "FAST", + "FATE", + "FAWN", + "FEAR", + "FEAT", + "FEED", + "FEEL", + "FEET", + "FELL", + "FELT", + "FEND", + "FERN", + "FEST", + "FEUD", + "FIEF", + "FIGS", + "FILE", + "FILL", + "FILM", + "FIND", + "FINE", + "FINK", + "FIRE", + "FIRM", + "FISH", + "FISK", + "FIST", + "FITS", + "FIVE", + "FLAG", + "FLAK", + "FLAM", + "FLAT", + "FLAW", + "FLEA", + "FLED", + "FLEW", + "FLIT", + "FLOC", + "FLOG", + "FLOW", + "FLUB", + "FLUE", + "FOAL", + "FOAM", + "FOGY", + "FOIL", + "FOLD", + "FOLK", + "FOND", + "FONT", + "FOOD", + "FOOL", + "FOOT", + "FORD", + "FORE", + "FORK", + "FORM", + "FORT", + "FOSS", + "FOUL", + "FOUR", + "FOWL", + "FRAU", + "FRAY", + "FRED", + "FREE", + "FRET", + "FREY", + "FROG", + "FROM", + "FUEL", + "FULL", + "FUME", + "FUND", + "FUNK", + "FURY", + "FUSE", + "FUSS", + "GAFF", + "GAGE", + "GAIL", + "GAIN", + "GAIT", + "GALA", + "GALE", + "GALL", + "GALT", + "GAME", + "GANG", + "GARB", + "GARY", + "GASH", + "GATE", + "GAUL", + "GAUR", + "GAVE", + "GAWK", + "GEAR", + "GELD", + "GENE", + "GENT", + "GERM", + "GETS", + "GIBE", + "GIFT", + "GILD", + "GILL", + "GILT", + "GINA", + "GIRD", + "GIRL", + "GIST", + "GIVE", + "GLAD", + "GLEE", + "GLEN", + "GLIB", + "GLOB", + "GLOM", + "GLOW", + "GLUE", + "GLUM", + "GLUT", + "GOAD", + "GOAL", + "GOAT", + "GOER", + "GOES", + "GOLD", + "GOLF", + "GONE", + "GONG", + "GOOD", + "GOOF", + "GORE", + "GORY", + "GOSH", + "GOUT", + "GOWN", + "GRAB", + "GRAD", + "GRAY", + "GREG", + "GREW", + "GREY", + "GRID", + "GRIM", + "GRIN", + "GRIT", + "GROW", + "GRUB", + "GULF", + "GULL", + "GUNK", + "GURU", + "GUSH", + "GUST", + "GWEN", + "GWYN", + "HAAG", + "HAAS", + "HACK", + "HAIL", + "HAIR", + "HALE", + "HALF", + "HALL", + "HALO", + "HALT", + "HAND", + "HANG", + "HANK", + "HANS", + "HARD", + "HARK", + "HARM", + "HART", + "HASH", + "HAST", + "HATE", + "HATH", + "HAUL", + "HAVE", + "HAWK", + "HAYS", + "HEAD", + "HEAL", + "HEAR", + "HEAT", + "HEBE", + "HECK", + "HEED", + "HEEL", + "HEFT", + "HELD", + "HELL", + "HELM", + "HERB", + "HERD", + "HERE", + "HERO", + "HERS", + "HESS", + "HEWN", + "HICK", + "HIDE", + "HIGH", + "HIKE", + "HILL", + "HILT", + "HIND", + "HINT", + "HIRE", + "HISS", + "HIVE", + "HOBO", + "HOCK", + "HOFF", + "HOLD", + "HOLE", + "HOLM", + "HOLT", + "HOME", + "HONE", + "HONK", + "HOOD", + "HOOF", + "HOOK", + "HOOT", + "HORN", + "HOSE", + "HOST", + "HOUR", + "HOVE", + "HOWE", + "HOWL", + "HOYT", + "HUCK", + "HUED", + "HUFF", + "HUGE", + "HUGH", + "HUGO", + "HULK", + "HULL", + "HUNK", + "HUNT", + "HURD", + "HURL", + "HURT", + "HUSH", + "HYDE", + "HYMN", + "IBIS", + "ICON", + "IDEA", + "IDLE", + "IFFY", + "INCA", + "INCH", + "INTO", + "IONS", + "IOTA", + "IOWA", + "IRIS", + "IRMA", + "IRON", + "ISLE", + "ITCH", + "ITEM", + "IVAN", + "JACK", + "JADE", + "JAIL", + "JAKE", + "JANE", + "JAVA", + "JEAN", + "JEFF", + "JERK", + "JESS", + "JEST", + "JIBE", + "JILL", + "JILT", + "JIVE", + "JOAN", + "JOBS", + "JOCK", + "JOEL", + "JOEY", + "JOHN", + "JOIN", + "JOKE", + "JOLT", + "JOVE", + "JUDD", + "JUDE", + "JUDO", + "JUDY", + "JUJU", + "JUKE", + "JULY", + "JUNE", + "JUNK", + "JUNO", + "JURY", + "JUST", + "JUTE", + "KAHN", + "KALE", + "KANE", + "KANT", + "KARL", + "KATE", + "KEEL", + "KEEN", + "KENO", + "KENT", + "KERN", + "KERR", + "KEYS", + "KICK", + "KILL", + "KIND", + "KING", + "KIRK", + "KISS", + "KITE", + "KLAN", + "KNEE", + "KNEW", + "KNIT", + "KNOB", + "KNOT", + "KNOW", + "KOCH", + "KONG", + "KUDO", + "KURD", + "KURT", + "KYLE", + "LACE", + "LACK", + "LACY", + "LADY", + "LAID", + "LAIN", + "LAIR", + "LAKE", + "LAMB", + "LAME", + "LAND", + "LANE", + "LANG", + "LARD", + "LARK", + "LASS", + "LAST", + "LATE", + "LAUD", + "LAVA", + "LAWN", + "LAWS", + "LAYS", + "LEAD", + "LEAF", + "LEAK", + "LEAN", + "LEAR", + "LEEK", + "LEER", + "LEFT", + "LEND", + "LENS", + "LENT", + "LEON", + "LESK", + "LESS", + "LEST", + "LETS", + "LIAR", + "LICE", + "LICK", + "LIED", + "LIEN", + "LIES", + "LIEU", + "LIFE", + "LIFT", + "LIKE", + "LILA", + "LILT", + "LILY", + "LIMA", + "LIMB", + "LIME", + "LIND", + "LINE", + "LINK", + "LINT", + "LION", + "LISA", + "LIST", + "LIVE", + "LOAD", + "LOAF", + "LOAM", + "LOAN", + "LOCK", + "LOFT", + "LOGE", + "LOIS", + "LOLA", + "LONE", + "LONG", + "LOOK", + "LOON", + "LOOT", + "LORD", + "LORE", + "LOSE", + "LOSS", + "LOST", + "LOUD", + "LOVE", + "LOWE", + "LUCK", + "LUCY", + "LUGE", + "LUKE", + "LULU", + "LUND", + "LUNG", + "LURA", + "LURE", + "LURK", + "LUSH", + "LUST", + "LYLE", + "LYNN", + "LYON", + "LYRA", + "MACE", + "MADE", + "MAGI", + "MAID", + "MAIL", + "MAIN", + "MAKE", + "MALE", + "MALI", + "MALL", + "MALT", + "MANA", + "MANN", + "MANY", + "MARC", + "MARE", + "MARK", + "MARS", + "MART", + "MARY", + "MASH", + "MASK", + "MASS", + "MAST", + "MATE", + "MATH", + "MAUL", + "MAYO", + "MEAD", + "MEAL", + "MEAN", + "MEAT", + "MEEK", + "MEET", + "MELD", + "MELT", + "MEMO", + "MEND", + "MENU", + "MERT", + "MESH", + "MESS", + "MICE", + "MIKE", + "MILD", + "MILE", + "MILK", + "MILL", + "MILT", + "MIMI", + "MIND", + "MINE", + "MINI", + "MINK", + "MINT", + "MIRE", + "MISS", + "MIST", + "MITE", + "MITT", + "MOAN", + "MOAT", + "MOCK", + "MODE", + "MOLD", + "MOLE", + "MOLL", + "MOLT", + "MONA", + "MONK", + "MONT", + "MOOD", + "MOON", + "MOOR", + "MOOT", + "MORE", + "MORN", + "MORT", + "MOSS", + "MOST", + "MOTH", + "MOVE", + "MUCH", + "MUCK", + "MUDD", + "MUFF", + "MULE", + "MULL", + "MURK", + "MUSH", + "MUST", + "MUTE", + "MUTT", + "MYRA", + "MYTH", + "NAGY", + "NAIL", + "NAIR", + "NAME", + "NARY", + "NASH", + "NAVE", + "NAVY", + "NEAL", + "NEAR", + "NEAT", + "NECK", + "NEED", + "NEIL", + "NELL", + "NEON", + "NERO", + "NESS", + "NEST", + "NEWS", + "NEWT", + "NIBS", + "NICE", + "NICK", + "NILE", + "NINA", + "NINE", + "NOAH", + "NODE", + "NOEL", + "NOLL", + "NONE", + "NOOK", + "NOON", + "NORM", + "NOSE", + "NOTE", + "NOUN", + "NOVA", + "NUDE", + "NULL", + "NUMB", + "OATH", + "OBEY", + "OBOE", + "ODIN", + "OHIO", + "OILY", + "OINT", + "OKAY", + "OLAF", + "OLDY", + "OLGA", + "OLIN", + "OMAN", + "OMEN", + "OMIT", + "ONCE", + "ONES", + "ONLY", + "ONTO", + "ONUS", + "ORAL", + "ORGY", + "OSLO", + "OTIS", + "OTTO", + "OUCH", + "OUST", + "OUTS", + "OVAL", + "OVEN", + "OVER", + "OWLY", + "OWNS", + "QUAD", + "QUIT", + "QUOD", + "RACE", + "RACK", + "RACY", + "RAFT", + "RAGE", + "RAID", + "RAIL", + "RAIN", + "RAKE", + "RANK", + "RANT", + "RARE", + "RASH", + "RATE", + "RAVE", + "RAYS", + "READ", + "REAL", + "REAM", + "REAR", + "RECK", + "REED", + "REEF", + "REEK", + "REEL", + "REID", + "REIN", + "RENA", + "REND", + "RENT", + "REST", + "RICE", + "RICH", + "RICK", + "RIDE", + "RIFT", + "RILL", + "RIME", + "RING", + "RINK", + "RISE", + "RISK", + "RITE", + "ROAD", + "ROAM", + "ROAR", + "ROBE", + "ROCK", + "RODE", + "ROIL", + "ROLL", + "ROME", + "ROOD", + "ROOF", + "ROOK", + "ROOM", + "ROOT", + "ROSA", + "ROSE", + "ROSS", + "ROSY", + "ROTH", + "ROUT", + "ROVE", + "ROWE", + "ROWS", + "RUBE", + "RUBY", + "RUDE", + "RUDY", + "RUIN", + "RULE", + "RUNG", + "RUNS", + "RUNT", + "RUSE", + "RUSH", + "RUSK", + "RUSS", + "RUST", + "RUTH", + "SACK", + "SAFE", + "SAGE", + "SAID", + "SAIL", + "SALE", + "SALK", + "SALT", + "SAME", + "SAND", + "SANE", + "SANG", + "SANK", + "SARA", + "SAUL", + "SAVE", + "SAYS", + "SCAN", + "SCAR", + "SCAT", + "SCOT", + "SEAL", + "SEAM", + "SEAR", + "SEAT", + "SEED", + "SEEK", + "SEEM", + "SEEN", + "SEES", + "SELF", + "SELL", + "SEND", + "SENT", + "SETS", + "SEWN", + "SHAG", + "SHAM", + "SHAW", + "SHAY", + "SHED", + "SHIM", + "SHIN", + "SHOD", + "SHOE", + "SHOT", + "SHOW", + "SHUN", + "SHUT", + "SICK", + "SIDE", + "SIFT", + "SIGH", + "SIGN", + "SILK", + "SILL", + "SILO", + "SILT", + "SINE", + "SING", + "SINK", + "SIRE", + "SITE", + "SITS", + "SITU", + "SKAT", + "SKEW", + "SKID", + "SKIM", + "SKIN", + "SKIT", + "SLAB", + "SLAM", + "SLAT", + "SLAY", + "SLED", + "SLEW", + "SLID", + "SLIM", + "SLIT", + "SLOB", + "SLOG", + "SLOT", + "SLOW", + "SLUG", + "SLUM", + "SLUR", + "SMOG", + "SMUG", + "SNAG", + "SNOB", + "SNOW", + "SNUB", + "SNUG", + "SOAK", + "SOAR", + "SOCK", + "SODA", + "SOFA", + "SOFT", + "SOIL", + "SOLD", + "SOME", + "SONG", + "SOON", + "SOOT", + "SORE", + "SORT", + "SOUL", + "SOUR", + "SOWN", + "STAB", + "STAG", + "STAN", + "STAR", + "STAY", + "STEM", + "STEW", + "STIR", + "STOW", + "STUB", + "STUN", + "SUCH", + "SUDS", + "SUIT", + "SULK", + "SUMS", + "SUNG", + "SUNK", + "SURE", + "SURF", + "SWAB", + "SWAG", + "SWAM", + "SWAN", + "SWAT", + "SWAY", + "SWIM", + "SWUM", + "TACK", + "TACT", + "TAIL", + "TAKE", + "TALE", + "TALK", + "TALL", + "TANK", + "TASK", + "TATE", + "TAUT", + "TEAL", + "TEAM", + "TEAR", + "TECH", + "TEEM", + "TEEN", + "TEET", + "TELL", + "TEND", + "TENT", + "TERM", + "TERN", + "TESS", + "TEST", + "THAN", + "THAT", + "THEE", + "THEM", + "THEN", + "THEY", + "THIN", + "THIS", + "THUD", + "THUG", + "TICK", + "TIDE", + "TIDY", + "TIED", + "TIER", + "TILE", + "TILL", + "TILT", + "TIME", + "TINA", + "TINE", + "TINT", + "TINY", + "TIRE", + "TOAD", + "TOGO", + "TOIL", + "TOLD", + "TOLL", + "TONE", + "TONG", + "TONY", + "TOOK", + "TOOL", + "TOOT", + "TORE", + "TORN", + "TOTE", + "TOUR", + "TOUT", + "TOWN", + "TRAG", + "TRAM", + "TRAY", + "TREE", + "TREK", + "TRIG", + "TRIM", + "TRIO", + "TROD", + "TROT", + "TROY", + "TRUE", + "TUBA", + "TUBE", + "TUCK", + "TUFT", + "TUNA", + "TUNE", + "TUNG", + "TURF", + "TURN", + "TUSK", + "TWIG", + "TWIN", + "TWIT", + "ULAN", + "UNIT", + "URGE", + "USED", + "USER", + "USES", + "UTAH", + "VAIL", + "VAIN", + "VALE", + "VARY", + "VASE", + "VAST", + "VEAL", + "VEDA", + "VEIL", + "VEIN", + "VEND", + "VENT", + "VERB", + "VERY", + "VETO", + "VICE", + "VIEW", + "VINE", + "VISE", + "VOID", + "VOLT", + "VOTE", + "WACK", + "WADE", + "WAGE", + "WAIL", + "WAIT", + "WAKE", + "WALE", + "WALK", + "WALL", + "WALT", + "WAND", + "WANE", + "WANG", + "WANT", + "WARD", + "WARM", + "WARN", + "WART", + "WASH", + "WAST", + "WATS", + "WATT", + "WAVE", + "WAVY", + "WAYS", + "WEAK", + "WEAL", + "WEAN", + "WEAR", + "WEED", + "WEEK", + "WEIR", + "WELD", + "WELL", + "WELT", + "WENT", + "WERE", + "WERT", + "WEST", + "WHAM", + "WHAT", + "WHEE", + "WHEN", + "WHET", + "WHOA", + "WHOM", + "WICK", + "WIFE", + "WILD", + "WILL", + "WIND", + "WINE", + "WING", + "WINK", + "WINO", + "WIRE", + "WISE", + "WISH", + "WITH", + "WOLF", + "WONT", + "WOOD", + "WOOL", + "WORD", + "WORE", + "WORK", + "WORM", + "WORN", + "WOVE", + "WRIT", + "WYNN", + "YALE", + "YANG", + "YANK", + "YARD", + "YARN", + "YAWL", + "YAWN", + "YEAH", + "YEAR", + "YELL", + "YOGA", + "YOKE", +] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/__init__.py index 1862b828..fc63f03c 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/__init__.py @@ -37,5 +37,4 @@ :undocumented: _galois, _number_new, cpuid, py3compat, _raw_api """ -__all__ = ['RFC1751', 'number', 'strxor', 'asn1', 'Counter', 'Padding'] - +__all__ = ["RFC1751", "number", "strxor", "asn1", "Counter", "Padding"] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_cpu_features.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_cpu_features.py index 4794a027..99dc7235 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_cpu_features.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_cpu_features.py @@ -31,16 +31,18 @@ from Cryptodome.Util._raw_api import load_pycryptodome_raw_lib -_raw_cpuid_lib = load_pycryptodome_raw_lib("Cryptodome.Util._cpuid_c", - """ +_raw_cpuid_lib = load_pycryptodome_raw_lib( + "Cryptodome.Util._cpuid_c", + """ int have_aes_ni(void); int have_clmul(void); - """) + """, +) def have_aes_ni(): - return _raw_cpuid_lib.have_aes_ni() + return _raw_cpuid_lib.have_aes_ni() def have_clmul(): - return _raw_cpuid_lib.have_clmul() + return _raw_cpuid_lib.have_clmul() diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_file_system.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_file_system.py index 282f0dc3..26ace45f 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_file_system.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_file_system.py @@ -32,23 +32,22 @@ def pycryptodome_filename(dir_comps, filename): - """Return the complete file name for the module + """Return the complete file name for the module - dir_comps : list of string - The list of directory names in the PyCryptodome package. - The first element must be "Cryptodome". + dir_comps : list of string + The list of directory names in the PyCryptodome package. + The first element must be "Cryptodome". - filename : string - The filename (inclusing extension) in the target directory. - """ + filename : string + The filename (inclusing extension) in the target directory. + """ - if dir_comps[0] != "Cryptodome": - raise ValueError("Only available for modules under 'Cryptodome'") + if dir_comps[0] != "Cryptodome": + raise ValueError("Only available for modules under 'Cryptodome'") - dir_comps = list(dir_comps[1:]) + [filename] + dir_comps = list(dir_comps[1:]) + [filename] - util_lib, _ = os.path.split(os.path.abspath(__file__)) - root_lib = os.path.join(util_lib, "..") - - return os.path.join(root_lib, *dir_comps) + util_lib, _ = os.path.split(os.path.abspath(__file__)) + root_lib = os.path.join(util_lib, "..") + return os.path.join(root_lib, *dir_comps) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_file_system.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_file_system.pyi index d54a1268..85b403c8 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_file_system.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_file_system.pyi @@ -1,4 +1,3 @@ from typing import List - -def pycryptodome_filename(dir_comps: List[str], filename: str) -> str: ... \ No newline at end of file +def pycryptodome_filename(dir_comps: List[str], filename: str) -> str: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_raw_api.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_raw_api.py index cd64ac82..22a3a8a5 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_raw_api.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_raw_api.py @@ -38,288 +38,292 @@ # List of file suffixes for Python extensions # if sys.version_info[0] < 3: + import imp - import imp - extension_suffixes = [] - for ext, mod, typ in imp.get_suffixes(): - if typ == imp.C_EXTENSION: - extension_suffixes.append(ext) + extension_suffixes = [] + for ext, mod, typ in imp.get_suffixes(): + if typ == imp.C_EXTENSION: + extension_suffixes.append(ext) else: + from importlib import machinery - from importlib import machinery - extension_suffixes = machinery.EXTENSION_SUFFIXES + extension_suffixes = machinery.EXTENSION_SUFFIXES # Which types with buffer interface we support (apart from byte strings) _buffer_type = (bytearray, memoryview) class _VoidPointer(object): - @abc.abstractmethod - def get(self): - """Return the memory location we point to""" - return + @abc.abstractmethod + def get(self): + """Return the memory location we point to""" + return - @abc.abstractmethod - def address_of(self): - """Return a raw pointer to this pointer""" - return + @abc.abstractmethod + def address_of(self): + """Return a raw pointer to this pointer""" + return try: - # Starting from v2.18, pycparser (used by cffi for in-line ABI mode) - # stops working correctly when PYOPTIMIZE==2 or the parameter -OO is - # passed. In that case, we fall back to ctypes. - # Note that PyPy ships with an old version of pycparser so we can keep - # using cffi there. - # See https://github.com/Legrandin/pycryptodome/issues/228 - if '__pypy__' not in sys.builtin_module_names and sys.flags.optimize == 2: - raise ImportError("CFFI with optimize=2 fails due to pycparser bug.") - - # cffi still uses PyUnicode_GetSize, which was removed in Python 3.12 - # thus leading to a crash on cffi.dlopen() - # See https://groups.google.com/u/1/g/python-cffi/c/oZkOIZ_zi5k - if sys.version_info >= (3, 12) and os.name == "nt": - raise ImportError("CFFI is not compatible with Python 3.12 on Windows") - - from cffi import FFI - - ffi = FFI() - null_pointer = ffi.NULL - uint8_t_type = ffi.typeof(ffi.new("const uint8_t*")) - - _Array = ffi.new("uint8_t[1]").__class__.__bases__ - - def load_lib(name, cdecl): - """Load a shared library and return a handle to it. - - @name, either an absolute path or the name of a library - in the system search path. - - @cdecl, the C function declarations. - """ - - if hasattr(ffi, "RTLD_DEEPBIND") and not os.getenv('PYCRYPTODOME_DISABLE_DEEPBIND'): - lib = ffi.dlopen(name, ffi.RTLD_DEEPBIND) - else: - lib = ffi.dlopen(name) - ffi.cdef(cdecl) - return lib - - def c_ulong(x): - """Convert a Python integer to unsigned long""" - return x - - c_ulonglong = c_ulong - c_uint = c_ulong - c_ubyte = c_ulong - - def c_size_t(x): - """Convert a Python integer to size_t""" - return x - - def create_string_buffer(init_or_size, size=None): - """Allocate the given amount of bytes (initially set to 0)""" - - if isinstance(init_or_size, bytes): - size = max(len(init_or_size) + 1, size) - result = ffi.new("uint8_t[]", size) - result[:] = init_or_size - else: - if size: - raise ValueError("Size must be specified once only") - result = ffi.new("uint8_t[]", init_or_size) - return result - - def get_c_string(c_string): - """Convert a C string into a Python byte sequence""" - return ffi.string(c_string) - - def get_raw_buffer(buf): - """Convert a C buffer into a Python byte sequence""" - return ffi.buffer(buf)[:] - - def c_uint8_ptr(data): - if isinstance(data, _buffer_type): - # This only works for cffi >= 1.7 - return ffi.cast(uint8_t_type, ffi.from_buffer(data)) - elif byte_string(data) or isinstance(data, _Array): - return data - else: - raise TypeError("Object type %s cannot be passed to C code" % type(data)) - - class VoidPointer_cffi(_VoidPointer): - """Model a newly allocated pointer to void""" - - def __init__(self): - self._pp = ffi.new("void *[1]") - - def get(self): - return self._pp[0] - - def address_of(self): - return self._pp - - def VoidPointer(): - return VoidPointer_cffi() - - backend = "cffi" + # Starting from v2.18, pycparser (used by cffi for in-line ABI mode) + # stops working correctly when PYOPTIMIZE==2 or the parameter -OO is + # passed. In that case, we fall back to ctypes. + # Note that PyPy ships with an old version of pycparser so we can keep + # using cffi there. + # See https://github.com/Legrandin/pycryptodome/issues/228 + if "__pypy__" not in sys.builtin_module_names and sys.flags.optimize == 2: + raise ImportError("CFFI with optimize=2 fails due to pycparser bug.") + + # cffi still uses PyUnicode_GetSize, which was removed in Python 3.12 + # thus leading to a crash on cffi.dlopen() + # See https://groups.google.com/u/1/g/python-cffi/c/oZkOIZ_zi5k + if sys.version_info >= (3, 12) and os.name == "nt": + raise ImportError("CFFI is not compatible with Python 3.12 on Windows") + + from cffi import FFI + + ffi = FFI() + null_pointer = ffi.NULL + uint8_t_type = ffi.typeof(ffi.new("const uint8_t*")) + + _Array = ffi.new("uint8_t[1]").__class__.__bases__ + + def load_lib(name, cdecl): + """Load a shared library and return a handle to it. + + @name, either an absolute path or the name of a library + in the system search path. + + @cdecl, the C function declarations. + """ + + if hasattr(ffi, "RTLD_DEEPBIND") and not os.getenv("PYCRYPTODOME_DISABLE_DEEPBIND"): + lib = ffi.dlopen(name, ffi.RTLD_DEEPBIND) + else: + lib = ffi.dlopen(name) + ffi.cdef(cdecl) + return lib + + def c_ulong(x): + """Convert a Python integer to unsigned long""" + return x + + c_ulonglong = c_ulong + c_uint = c_ulong + c_ubyte = c_ulong + + def c_size_t(x): + """Convert a Python integer to size_t""" + return x + + def create_string_buffer(init_or_size, size=None): + """Allocate the given amount of bytes (initially set to 0)""" + + if isinstance(init_or_size, bytes): + size = max(len(init_or_size) + 1, size) + result = ffi.new("uint8_t[]", size) + result[:] = init_or_size + else: + if size: + raise ValueError("Size must be specified once only") + result = ffi.new("uint8_t[]", init_or_size) + return result + + def get_c_string(c_string): + """Convert a C string into a Python byte sequence""" + return ffi.string(c_string) + + def get_raw_buffer(buf): + """Convert a C buffer into a Python byte sequence""" + return ffi.buffer(buf)[:] + + def c_uint8_ptr(data): + if isinstance(data, _buffer_type): + # This only works for cffi >= 1.7 + return ffi.cast(uint8_t_type, ffi.from_buffer(data)) + elif byte_string(data) or isinstance(data, _Array): + return data + else: + raise TypeError("Object type %s cannot be passed to C code" % type(data)) + + class VoidPointer_cffi(_VoidPointer): + """Model a newly allocated pointer to void""" + + def __init__(self): + self._pp = ffi.new("void *[1]") + + def get(self): + return self._pp[0] + + def address_of(self): + return self._pp + + def VoidPointer(): + return VoidPointer_cffi() + + backend = "cffi" except ImportError: - - import ctypes - from ctypes import (CDLL, c_void_p, byref, c_ulong, c_ulonglong, c_size_t, - create_string_buffer, c_ubyte, c_uint) - from ctypes.util import find_library - from ctypes import Array as _Array - - null_pointer = None - cached_architecture = [] - - def c_ubyte(c): - if not (0 <= c < 256): - raise OverflowError() - return ctypes.c_ubyte(c) - - def load_lib(name, cdecl): - if not cached_architecture: - # platform.architecture() creates a subprocess, so caching the - # result makes successive imports faster. - import platform - cached_architecture[:] = platform.architecture() - bits, linkage = cached_architecture - if "." not in name and not linkage.startswith("Win"): - full_name = find_library(name) - if full_name is None: - raise OSError("Cannot load library '%s'" % name) - name = full_name - return CDLL(name) - - def get_c_string(c_string): - return c_string.value - - def get_raw_buffer(buf): - return buf.raw - - # ---- Get raw pointer --- - - _c_ssize_t = ctypes.c_ssize_t - - _PyBUF_SIMPLE = 0 - _PyObject_GetBuffer = ctypes.pythonapi.PyObject_GetBuffer - _PyBuffer_Release = ctypes.pythonapi.PyBuffer_Release - _py_object = ctypes.py_object - _c_ssize_p = ctypes.POINTER(_c_ssize_t) - - # See Include/object.h for CPython - # and https://github.com/pallets/click/blob/master/src/click/_winconsole.py - class _Py_buffer(ctypes.Structure): - _fields_ = [ - ('buf', c_void_p), - ('obj', ctypes.py_object), - ('len', _c_ssize_t), - ('itemsize', _c_ssize_t), - ('readonly', ctypes.c_int), - ('ndim', ctypes.c_int), - ('format', ctypes.c_char_p), - ('shape', _c_ssize_p), - ('strides', _c_ssize_p), - ('suboffsets', _c_ssize_p), - ('internal', c_void_p) - ] - - # Extra field for CPython 2.6/2.7 - if sys.version_info[0] == 2: - _fields_.insert(-1, ('smalltable', _c_ssize_t * 2)) - - def c_uint8_ptr(data): - if byte_string(data) or isinstance(data, _Array): - return data - elif isinstance(data, _buffer_type): - obj = _py_object(data) - buf = _Py_buffer() - _PyObject_GetBuffer(obj, byref(buf), _PyBUF_SIMPLE) - try: - buffer_type = ctypes.c_ubyte * buf.len - return buffer_type.from_address(buf.buf) - finally: - _PyBuffer_Release(byref(buf)) - else: - raise TypeError("Object type %s cannot be passed to C code" % type(data)) - - # --- - - class VoidPointer_ctypes(_VoidPointer): - """Model a newly allocated pointer to void""" - - def __init__(self): - self._p = c_void_p() - - def get(self): - return self._p - - def address_of(self): - return byref(self._p) - - def VoidPointer(): - return VoidPointer_ctypes() - - backend = "ctypes" + import ctypes + from ctypes import ( + CDLL, + c_void_p, + byref, + c_ulong, + c_ubyte, + ) + from ctypes.util import find_library + from ctypes import Array as _Array + + null_pointer = None + cached_architecture = [] + + def c_ubyte(c): + if not (0 <= c < 256): + raise OverflowError() + return ctypes.c_ubyte(c) + + def load_lib(name, cdecl): + if not cached_architecture: + # platform.architecture() creates a subprocess, so caching the + # result makes successive imports faster. + import platform + + cached_architecture[:] = platform.architecture() + bits, linkage = cached_architecture + if "." not in name and not linkage.startswith("Win"): + full_name = find_library(name) + if full_name is None: + raise OSError("Cannot load library '%s'" % name) + name = full_name + return CDLL(name) + + def get_c_string(c_string): + return c_string.value + + def get_raw_buffer(buf): + return buf.raw + + # ---- Get raw pointer --- + + _c_ssize_t = ctypes.c_ssize_t + + _PyBUF_SIMPLE = 0 + _PyObject_GetBuffer = ctypes.pythonapi.PyObject_GetBuffer + _PyBuffer_Release = ctypes.pythonapi.PyBuffer_Release + _py_object = ctypes.py_object + _c_ssize_p = ctypes.POINTER(_c_ssize_t) + + # See Include/object.h for CPython + # and https://github.com/pallets/click/blob/master/src/click/_winconsole.py + class _Py_buffer(ctypes.Structure): + _fields_ = [ + ("buf", c_void_p), + ("obj", ctypes.py_object), + ("len", _c_ssize_t), + ("itemsize", _c_ssize_t), + ("readonly", ctypes.c_int), + ("ndim", ctypes.c_int), + ("format", ctypes.c_char_p), + ("shape", _c_ssize_p), + ("strides", _c_ssize_p), + ("suboffsets", _c_ssize_p), + ("internal", c_void_p), + ] + + # Extra field for CPython 2.6/2.7 + if sys.version_info[0] == 2: + _fields_.insert(-1, ("smalltable", _c_ssize_t * 2)) + + def c_uint8_ptr(data): + if byte_string(data) or isinstance(data, _Array): + return data + elif isinstance(data, _buffer_type): + obj = _py_object(data) + buf = _Py_buffer() + _PyObject_GetBuffer(obj, byref(buf), _PyBUF_SIMPLE) + try: + buffer_type = ctypes.c_ubyte * buf.len + return buffer_type.from_address(buf.buf) + finally: + _PyBuffer_Release(byref(buf)) + else: + raise TypeError("Object type %s cannot be passed to C code" % type(data)) + + # --- + + class VoidPointer_ctypes(_VoidPointer): + """Model a newly allocated pointer to void""" + + def __init__(self): + self._p = c_void_p() + + def get(self): + return self._p + + def address_of(self): + return byref(self._p) + + def VoidPointer(): + return VoidPointer_ctypes() + + backend = "ctypes" class SmartPointer(object): - """Class to hold a non-managed piece of memory""" + """Class to hold a non-managed piece of memory""" - def __init__(self, raw_pointer, destructor): - self._raw_pointer = raw_pointer - self._destructor = destructor + def __init__(self, raw_pointer, destructor): + self._raw_pointer = raw_pointer + self._destructor = destructor - def get(self): - return self._raw_pointer + def get(self): + return self._raw_pointer - def release(self): - rp, self._raw_pointer = self._raw_pointer, None - return rp + def release(self): + rp, self._raw_pointer = self._raw_pointer, None + return rp - def __del__(self): - try: - if self._raw_pointer is not None: - self._destructor(self._raw_pointer) - self._raw_pointer = None - except AttributeError: - pass + def __del__(self): + try: + if self._raw_pointer is not None: + self._destructor(self._raw_pointer) + self._raw_pointer = None + except AttributeError: + pass def load_pycryptodome_raw_lib(name, cdecl): - """Load a shared library and return a handle to it. - - @name, the name of the library expressed as a PyCryptodome module, - for instance Cryptodome.Cipher._raw_cbc. - - @cdecl, the C function declarations. - """ - - split = name.split(".") - dir_comps, basename = split[:-1], split[-1] - attempts = [] - for ext in extension_suffixes: - try: - filename = basename + ext - full_name = pycryptodome_filename(dir_comps, filename) - if not os.path.isfile(full_name): - attempts.append("Not found '%s'" % filename) - continue - return load_lib(full_name, cdecl) - except OSError as exp: - attempts.append("Cannot load '%s': %s" % (filename, str(exp))) - raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts))) + """Load a shared library and return a handle to it. + + @name, the name of the library expressed as a PyCryptodome module, + for instance Cryptodome.Cipher._raw_cbc. + + @cdecl, the C function declarations. + """ + + split = name.split(".") + dir_comps, basename = split[:-1], split[-1] + attempts = [] + for ext in extension_suffixes: + try: + filename = basename + ext + full_name = pycryptodome_filename(dir_comps, filename) + if not os.path.isfile(full_name): + attempts.append("Not found '%s'" % filename) + continue + return load_lib(full_name, cdecl) + except OSError as exp: + attempts.append("Cannot load '%s': %s" % (filename, str(exp))) + raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts))) def is_buffer(x): - """Return True if object x supports the buffer interface""" - return isinstance(x, (bytes, bytearray, memoryview)) + """Return True if object x supports the buffer interface""" + return isinstance(x, (bytes, bytearray, memoryview)) def is_writeable_buffer(x): - return (isinstance(x, bytearray) or - (isinstance(x, memoryview) and not x.readonly)) + return isinstance(x, bytearray) or (isinstance(x, memoryview) and not x.readonly) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_raw_api.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_raw_api.pyi index 2bc53016..a5c78dac 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_raw_api.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/_raw_api.pyi @@ -1,27 +1,27 @@ from typing import Any, Optional, Union -def load_lib(name: str, cdecl: str) -> Any : ... -def c_ulong(x: int ) -> Any : ... -def c_ulonglong(x: int ) -> Any : ... -def c_size_t(x: int) -> Any : ... -def create_string_buffer(init_or_size: Union[bytes,int], size: Optional[int]) -> Any : ... -def get_c_string(c_string: Any) -> bytes : ... -def get_raw_buffer(buf: Any) -> bytes : ... -def c_uint8_ptr(data: Union[bytes, memoryview, bytearray]) -> Any : ... +def load_lib(name: str, cdecl: str) -> Any: ... +def c_ulong(x: int) -> Any: ... +def c_ulonglong(x: int) -> Any: ... +def c_size_t(x: int) -> Any: ... +def create_string_buffer(init_or_size: Union[bytes, int], size: Optional[int]) -> Any: ... +def get_c_string(c_string: Any) -> bytes: ... +def get_raw_buffer(buf: Any) -> bytes: ... +def c_uint8_ptr(data: Union[bytes, memoryview, bytearray]) -> Any: ... class VoidPointer(object): - def get(self) -> Any : ... - def address_of(self) -> Any : ... + def get(self) -> Any: ... + def address_of(self) -> Any: ... class SmartPointer(object): - def __init__(self, raw_pointer: Any, destructor: Any) -> None : ... - def get(self) -> Any : ... - def release(self) -> Any : ... + def __init__(self, raw_pointer: Any, destructor: Any) -> None: ... + def get(self) -> Any: ... + def release(self) -> Any: ... -backend : str -null_pointer : Any +backend: str +null_pointer: Any ffi: Any -def load_pycryptodome_raw_lib(name: str, cdecl: str) -> Any : ... -def is_buffer(x: Any) -> bool : ... -def is_writeable_buffer(x: Any) -> bool : ... +def load_pycryptodome_raw_lib(name: str, cdecl: str) -> Any: ... +def is_buffer(x: Any) -> bool: ... +def is_writeable_buffer(x: Any) -> bool: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/asn1.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/asn1.py index 9987fdac..937c81c6 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/asn1.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/asn1.py @@ -26,8 +26,17 @@ from Cryptodome.Util.number import long_to_bytes, bytes_to_long -__all__ = ['DerObject', 'DerInteger', 'DerBoolean', 'DerOctetString', - 'DerNull', 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf'] +__all__ = [ + "DerObject", + "DerInteger", + "DerBoolean", + "DerOctetString", + "DerNull", + "DerSequence", + "DerObjectId", + "DerBitString", + "DerSetOf", +] # Useful references: # - https://luca.ntop.org/Teaching/Appunti/asn1.html @@ -37,1028 +46,1045 @@ # - https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf # - https://misc.daniel-marschall.de/asn.1/oid-converter/online.php + def _is_number(x, only_non_negative=False): - test = 0 - try: - test = x + test - except TypeError: - return False - return not only_non_negative or x >= 0 + test = 0 + try: + test = x + test + except TypeError: + return False + return not only_non_negative or x >= 0 class BytesIO_EOF(object): - """This class differs from BytesIO in that a ValueError exception is - raised whenever EOF is reached.""" + """This class differs from BytesIO in that a ValueError exception is + raised whenever EOF is reached.""" - def __init__(self, initial_bytes): - self._buffer = initial_bytes - self._index = 0 - self._bookmark = None + def __init__(self, initial_bytes): + self._buffer = initial_bytes + self._index = 0 + self._bookmark = None - def set_bookmark(self): - self._bookmark = self._index + def set_bookmark(self): + self._bookmark = self._index - def data_since_bookmark(self): - assert self._bookmark is not None - return self._buffer[self._bookmark:self._index] + def data_since_bookmark(self): + assert self._bookmark is not None + return self._buffer[self._bookmark : self._index] - def remaining_data(self): - return len(self._buffer) - self._index + def remaining_data(self): + return len(self._buffer) - self._index - def read(self, length): - new_index = self._index + length - if new_index > len(self._buffer): - raise ValueError("Not enough data for DER decoding: expected %d bytes and found %d" % (new_index, len(self._buffer))) + def read(self, length): + new_index = self._index + length + if new_index > len(self._buffer): + raise ValueError( + "Not enough data for DER decoding: expected %d bytes and found %d" + % (new_index, len(self._buffer)) + ) - result = self._buffer[self._index:new_index] - self._index = new_index - return result + result = self._buffer[self._index : new_index] + self._index = new_index + return result - def read_byte(self): - return bord(self.read(1)[0]) + def read_byte(self): + return bord(self.read(1)[0]) class DerObject(object): - """Base class for defining a single DER object. - - This class should never be directly instantiated. - """ - - def __init__(self, asn1Id=None, payload=b'', implicit=None, - constructed=False, explicit=None): - """Initialize the DER object according to a specific ASN.1 type. - - :Parameters: - asn1Id : integer or byte - The universal DER tag number for this object - (e.g. 0x10 for a SEQUENCE). - If None, the tag is not known yet. - - payload : byte string - The initial payload of the object (that it, - the content octets). - If not specified, the payload is empty. - - implicit : integer or byte - The IMPLICIT tag number (< 0x1F) to use for the encoded object. - It overrides the universal tag *asn1Id*. - It cannot be combined with the ``explicit`` parameter. - By default, there is no IMPLICIT tag. - - constructed : bool - True when the ASN.1 type is *constructed*. - False when it is *primitive* (default). - - explicit : integer or byte - The EXPLICIT tag number (< 0x1F) to use for the encoded object. - It cannot be combined with the ``implicit`` parameter. - By default, there is no EXPLICIT tag. - """ - - if asn1Id is None: - # The tag octet will be read in with ``decode`` - self._tag_octet = None - return - asn1Id = self._convertTag(asn1Id) - - self.payload = payload - - # In a BER/DER identifier octet: - # * bits 4-0 contain the tag value - # * bit 5 is set if the type is 'constructed' - # and unset if 'primitive' - # * bits 7-6 depend on the encoding class - # - # Class | Bit 7, Bit 6 - # ---------------------------------- - # universal | 0 0 - # application | 0 1 - # context-spec | 1 0 (default for IMPLICIT/EXPLICIT) - # private | 1 1 - # - - constructed_bit = 0x20 if constructed else 0x00 - - if None not in (explicit, implicit): - raise ValueError("Explicit and implicit tags are" - " mutually exclusive") - - if implicit is not None: - # IMPLICIT tag overrides asn1Id - self._tag_octet = 0x80 | constructed_bit | self._convertTag(implicit) - elif explicit is not None: - # 'constructed bit' is always asserted for an EXPLICIT tag - self._tag_octet = 0x80 | 0x20 | self._convertTag(explicit) - self._inner_tag_octet = constructed_bit | asn1Id - else: - # Neither IMPLICIT nor EXPLICIT - self._tag_octet = constructed_bit | asn1Id - - def _convertTag(self, tag): - """Check if *tag* is a real DER tag (5 bits). - Convert it from a character to number if necessary. - """ - if not _is_number(tag): - if len(tag) == 1: - tag = bord(tag[0]) - # Ensure that tag is a low tag - if not (_is_number(tag) and 0 <= tag < 0x1F): - raise ValueError("Wrong DER tag") - return tag - - @staticmethod - def _definite_form(length): - """Build length octets according to BER/DER - definite form. - """ - if length > 127: - encoding = long_to_bytes(length) - return bchr(len(encoding) + 128) + encoding - return bchr(length) - - def encode(self): - """Return this DER element, fully encoded as a binary byte string.""" - - # Concatenate identifier octets, length octets, - # and contents octets - - output_payload = self.payload - - # In case of an EXTERNAL tag, first encode the inner - # element. - if hasattr(self, "_inner_tag_octet"): - output_payload = (bchr(self._inner_tag_octet) + - self._definite_form(len(self.payload)) + - self.payload) - - return (bchr(self._tag_octet) + - self._definite_form(len(output_payload)) + - output_payload) - - def _decodeLen(self, s): - """Decode DER length octets from a file.""" - - length = s.read_byte() - - if length > 127: - encoded_length = s.read(length & 0x7F) - if bord(encoded_length[0]) == 0: - raise ValueError("Invalid DER: length has leading zero") - length = bytes_to_long(encoded_length) - if length <= 127: - raise ValueError("Invalid DER: length in long form but smaller than 128") - - return length - - def decode(self, der_encoded, strict=False): - """Decode a complete DER element, and re-initializes this - object with it. - - Args: - der_encoded (byte string): A complete DER element. - - Raises: - ValueError: in case of parsing errors. - """ - - if not byte_string(der_encoded): - raise ValueError("Input is not a byte string") - - s = BytesIO_EOF(der_encoded) - self._decodeFromStream(s, strict) - - # There shouldn't be other bytes left - if s.remaining_data() > 0: - raise ValueError("Unexpected extra data after the DER structure") - - return self - - def _decodeFromStream(self, s, strict): - """Decode a complete DER element from a file.""" - - idOctet = s.read_byte() - if self._tag_octet is not None: - if idOctet != self._tag_octet: - raise ValueError("Unexpected DER tag") - else: - self._tag_octet = idOctet - length = self._decodeLen(s) - self.payload = s.read(length) - - # In case of an EXTERNAL tag, further decode the inner - # element. - if hasattr(self, "_inner_tag_octet"): - p = BytesIO_EOF(self.payload) - inner_octet = p.read_byte() - if inner_octet != self._inner_tag_octet: - raise ValueError("Unexpected internal DER tag") - length = self._decodeLen(p) - self.payload = p.read(length) - - # There shouldn't be other bytes left - if p.remaining_data() > 0: - raise ValueError("Unexpected extra data after the DER structure") + """Base class for defining a single DER object. + + This class should never be directly instantiated. + """ + + def __init__( + self, + asn1Id=None, + payload=b"", + implicit=None, + constructed=False, + explicit=None, + ): + """Initialize the DER object according to a specific ASN.1 type. + + :Parameters: + asn1Id : integer or byte + The universal DER tag number for this object + (e.g. 0x10 for a SEQUENCE). + If None, the tag is not known yet. + + payload : byte string + The initial payload of the object (that it, + the content octets). + If not specified, the payload is empty. + + implicit : integer or byte + The IMPLICIT tag number (< 0x1F) to use for the encoded object. + It overrides the universal tag *asn1Id*. + It cannot be combined with the ``explicit`` parameter. + By default, there is no IMPLICIT tag. + + constructed : bool + True when the ASN.1 type is *constructed*. + False when it is *primitive* (default). + + explicit : integer or byte + The EXPLICIT tag number (< 0x1F) to use for the encoded object. + It cannot be combined with the ``implicit`` parameter. + By default, there is no EXPLICIT tag. + """ + + if asn1Id is None: + # The tag octet will be read in with ``decode`` + self._tag_octet = None + return + asn1Id = self._convertTag(asn1Id) + + self.payload = payload + + # In a BER/DER identifier octet: + # * bits 4-0 contain the tag value + # * bit 5 is set if the type is 'constructed' + # and unset if 'primitive' + # * bits 7-6 depend on the encoding class + # + # Class | Bit 7, Bit 6 + # ---------------------------------- + # universal | 0 0 + # application | 0 1 + # context-spec | 1 0 (default for IMPLICIT/EXPLICIT) + # private | 1 1 + # + + constructed_bit = 0x20 if constructed else 0x00 + + if None not in (explicit, implicit): + raise ValueError( + "Explicit and implicit tags are mutually exclusive", + ) + + if implicit is not None: + # IMPLICIT tag overrides asn1Id + self._tag_octet = 0x80 | constructed_bit | self._convertTag(implicit) + elif explicit is not None: + # 'constructed bit' is always asserted for an EXPLICIT tag + self._tag_octet = 0x80 | 0x20 | self._convertTag(explicit) + self._inner_tag_octet = constructed_bit | asn1Id + else: + # Neither IMPLICIT nor EXPLICIT + self._tag_octet = constructed_bit | asn1Id + + def _convertTag(self, tag): + """Check if *tag* is a real DER tag (5 bits). + Convert it from a character to number if necessary. + """ + if not _is_number(tag): + if len(tag) == 1: + tag = bord(tag[0]) + # Ensure that tag is a low tag + if not (_is_number(tag) and 0 <= tag < 0x1F): + raise ValueError("Wrong DER tag") + return tag + + @staticmethod + def _definite_form(length): + """Build length octets according to BER/DER + definite form. + """ + if length > 127: + encoding = long_to_bytes(length) + return bchr(len(encoding) + 128) + encoding + return bchr(length) + + def encode(self): + """Return this DER element, fully encoded as a binary byte string.""" + + # Concatenate identifier octets, length octets, + # and contents octets + + output_payload = self.payload + + # In case of an EXTERNAL tag, first encode the inner + # element. + if hasattr(self, "_inner_tag_octet"): + output_payload = ( + bchr(self._inner_tag_octet) + self._definite_form(len(self.payload)) + self.payload + ) + + return bchr(self._tag_octet) + self._definite_form(len(output_payload)) + output_payload + + def _decodeLen(self, s): + """Decode DER length octets from a file.""" + + length = s.read_byte() + + if length > 127: + encoded_length = s.read(length & 0x7F) + if bord(encoded_length[0]) == 0: + raise ValueError("Invalid DER: length has leading zero") + length = bytes_to_long(encoded_length) + if length <= 127: + raise ValueError("Invalid DER: length in long form but smaller than 128") + + return length + + def decode(self, der_encoded, strict=False): + """Decode a complete DER element, and re-initializes this + object with it. + + Args: + der_encoded (byte string): A complete DER element. + + Raises: + ValueError: in case of parsing errors. + """ + + if not byte_string(der_encoded): + raise ValueError("Input is not a byte string") + + s = BytesIO_EOF(der_encoded) + self._decodeFromStream(s, strict) + + # There shouldn't be other bytes left + if s.remaining_data() > 0: + raise ValueError("Unexpected extra data after the DER structure") + + return self + + def _decodeFromStream(self, s, strict): + """Decode a complete DER element from a file.""" + + idOctet = s.read_byte() + if self._tag_octet is not None: + if idOctet != self._tag_octet: + raise ValueError("Unexpected DER tag") + else: + self._tag_octet = idOctet + length = self._decodeLen(s) + self.payload = s.read(length) + + # In case of an EXTERNAL tag, further decode the inner + # element. + if hasattr(self, "_inner_tag_octet"): + p = BytesIO_EOF(self.payload) + inner_octet = p.read_byte() + if inner_octet != self._inner_tag_octet: + raise ValueError("Unexpected internal DER tag") + length = self._decodeLen(p) + self.payload = p.read(length) + + # There shouldn't be other bytes left + if p.remaining_data() > 0: + raise ValueError("Unexpected extra data after the DER structure") class DerInteger(DerObject): - """Class to model a DER INTEGER. - - An example of encoding is:: - - >>> from Cryptodome.Util.asn1 import DerInteger - >>> from binascii import hexlify, unhexlify - >>> int_der = DerInteger(9) - >>> print hexlify(int_der.encode()) - - which will show ``020109``, the DER encoding of 9. - - And for decoding:: - - >>> s = unhexlify(b'020109') - >>> try: - >>> int_der = DerInteger() - >>> int_der.decode(s) - >>> print int_der.value - >>> except ValueError: - >>> print "Not a valid DER INTEGER" - - the output will be ``9``. - - :ivar value: The integer value - :vartype value: integer - """ - - def __init__(self, value=0, implicit=None, explicit=None): - """Initialize the DER object as an INTEGER. - - :Parameters: - value : integer - The value of the integer. - - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for INTEGER (2). - """ - - DerObject.__init__(self, 0x02, b'', implicit, - False, explicit) - self.value = value # The integer value - - def encode(self): - """Return the DER INTEGER, fully encoded as a - binary string.""" - - number = self.value - self.payload = b'' - while True: - self.payload = bchr(int(number & 255)) + self.payload - if 128 <= number <= 255: - self.payload = bchr(0x00) + self.payload - if -128 <= number <= 255: - break - number >>= 8 - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False): - """Decode a DER-encoded INTEGER, and re-initializes this - object with it. - - Args: - der_encoded (byte string): A complete INTEGER DER element. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict=strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER INTEGER from a file.""" - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - if strict: - if len(self.payload) == 0: - raise ValueError("Invalid encoding for DER INTEGER: empty payload") - if len(self.payload) >= 2 and struct.unpack('>H', self.payload[:2])[0] < 0x80: - raise ValueError("Invalid encoding for DER INTEGER: leading zero") - - # Derive self.value from self.payload - self.value = 0 - bits = 1 - for i in self.payload: - self.value *= 256 - self.value += bord(i) - bits <<= 8 - if self.payload and bord(self.payload[0]) & 0x80: - self.value -= bits + """Class to model a DER INTEGER. + + An example of encoding is:: + + >>> from Cryptodome.Util.asn1 import DerInteger + >>> from binascii import hexlify, unhexlify + >>> int_der = DerInteger(9) + >>> print hexlify(int_der.encode()) + + which will show ``020109``, the DER encoding of 9. + + And for decoding:: + + >>> s = unhexlify(b'020109') + >>> try: + >>> int_der = DerInteger() + >>> int_der.decode(s) + >>> print int_der.value + >>> except ValueError: + >>> print "Not a valid DER INTEGER" + + the output will be ``9``. + + :ivar value: The integer value + :vartype value: integer + """ + + def __init__(self, value=0, implicit=None, explicit=None): + """Initialize the DER object as an INTEGER. + + :Parameters: + value : integer + The value of the integer. + + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for INTEGER (2). + """ + + DerObject.__init__( + self, + 0x02, + b"", + implicit, + False, + explicit, + ) + self.value = value # The integer value + + def encode(self): + """Return the DER INTEGER, fully encoded as a + binary string.""" + + number = self.value + self.payload = b"" + while True: + self.payload = bchr(int(number & 255)) + self.payload + if 128 <= number <= 255: + self.payload = bchr(0x00) + self.payload + if -128 <= number <= 255: + break + number >>= 8 + return DerObject.encode(self) + + def decode(self, der_encoded, strict=False): + """Decode a DER-encoded INTEGER, and re-initializes this + object with it. + + Args: + der_encoded (byte string): A complete INTEGER DER element. + + Raises: + ValueError: in case of parsing errors. + """ + + return DerObject.decode(self, der_encoded, strict=strict) + + def _decodeFromStream(self, s, strict): + """Decode a complete DER INTEGER from a file.""" + + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) + + if strict: + if len(self.payload) == 0: + raise ValueError("Invalid encoding for DER INTEGER: empty payload") + if len(self.payload) >= 2 and struct.unpack(">H", self.payload[:2])[0] < 0x80: + raise ValueError("Invalid encoding for DER INTEGER: leading zero") + + # Derive self.value from self.payload + self.value = 0 + bits = 1 + for i in self.payload: + self.value *= 256 + self.value += bord(i) + bits <<= 8 + if self.payload and bord(self.payload[0]) & 0x80: + self.value -= bits class DerBoolean(DerObject): - """Class to model a DER-encoded BOOLEAN. + """Class to model a DER-encoded BOOLEAN. - An example of encoding is:: + An example of encoding is:: - >>> from Cryptodome.Util.asn1 import DerBoolean - >>> bool_der = DerBoolean(True) - >>> print(bool_der.encode().hex()) + >>> from Cryptodome.Util.asn1 import DerBoolean + >>> bool_der = DerBoolean(True) + >>> print(bool_der.encode().hex()) - which will show ``0101ff``, the DER encoding of True. + which will show ``0101ff``, the DER encoding of True. - And for decoding:: + And for decoding:: - >>> s = bytes.fromhex('0101ff') - >>> try: - >>> bool_der = DerBoolean() - >>> bool_der.decode(s) - >>> print(bool_der.value) - >>> except ValueError: - >>> print "Not a valid DER BOOLEAN" + >>> s = bytes.fromhex('0101ff') + >>> try: + >>> bool_der = DerBoolean() + >>> bool_der.decode(s) + >>> print(bool_der.value) + >>> except ValueError: + >>> print "Not a valid DER BOOLEAN" - the output will be ``True``. + the output will be ``True``. - :ivar value: The boolean value - :vartype value: boolean - """ - def __init__(self, value=False, implicit=None, explicit=None): - """Initialize the DER object as a BOOLEAN. + :ivar value: The boolean value + :vartype value: boolean + """ - Args: - value (boolean): - The value of the boolean. Default is False. + def __init__(self, value=False, implicit=None, explicit=None): + """Initialize the DER object as a BOOLEAN. - implicit (integer or byte): - The IMPLICIT tag number (< 0x1F) to use for the encoded object. - It overrides the universal tag for BOOLEAN (1). - It cannot be combined with the ``explicit`` parameter. - By default, there is no IMPLICIT tag. + Args: + value (boolean): + The value of the boolean. Default is False. - explicit (integer or byte): - The EXPLICIT tag number (< 0x1F) to use for the encoded object. - It cannot be combined with the ``implicit`` parameter. - By default, there is no EXPLICIT tag. - """ + implicit (integer or byte): + The IMPLICIT tag number (< 0x1F) to use for the encoded object. + It overrides the universal tag for BOOLEAN (1). + It cannot be combined with the ``explicit`` parameter. + By default, there is no IMPLICIT tag. - DerObject.__init__(self, 0x01, b'', implicit, False, explicit) - self.value = value # The boolean value + explicit (integer or byte): + The EXPLICIT tag number (< 0x1F) to use for the encoded object. + It cannot be combined with the ``implicit`` parameter. + By default, there is no EXPLICIT tag. + """ - def encode(self): - """Return the DER BOOLEAN, fully encoded as a binary string.""" + DerObject.__init__(self, 0x01, b"", implicit, False, explicit) + self.value = value # The boolean value - self.payload = b'\xFF' if self.value else b'\x00' - return DerObject.encode(self) + def encode(self): + """Return the DER BOOLEAN, fully encoded as a binary string.""" - def decode(self, der_encoded, strict=False): - """Decode a DER-encoded BOOLEAN, and re-initializes this object with it. + self.payload = b"\xff" if self.value else b"\x00" + return DerObject.encode(self) - Args: - der_encoded (byte string): A DER-encoded BOOLEAN. + def decode(self, der_encoded, strict=False): + """Decode a DER-encoded BOOLEAN, and re-initializes this object with it. - Raises: - ValueError: in case of parsing errors. - """ + Args: + der_encoded (byte string): A DER-encoded BOOLEAN. - return DerObject.decode(self, der_encoded, strict) + Raises: + ValueError: in case of parsing errors. + """ - def _decodeFromStream(self, s, strict): - """Decode a DER-encoded BOOLEAN from a file.""" + return DerObject.decode(self, der_encoded, strict) - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) + def _decodeFromStream(self, s, strict): + """Decode a DER-encoded BOOLEAN from a file.""" - if len(self.payload) != 1: - raise ValueError("Invalid encoding for DER BOOLEAN: payload is not 1 byte") + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) - if bord(self.payload[0]) == 0: - self.value = False - elif bord(self.payload[0]) == 0xFF: - self.value = True - else: - raise ValueError("Invalid payload for DER BOOLEAN") + if len(self.payload) != 1: + raise ValueError("Invalid encoding for DER BOOLEAN: payload is not 1 byte") + if bord(self.payload[0]) == 0: + self.value = False + elif bord(self.payload[0]) == 0xFF: + self.value = True + else: + raise ValueError("Invalid payload for DER BOOLEAN") -class DerSequence(DerObject): - """Class to model a DER SEQUENCE. - This object behaves like a dynamic Python sequence. +class DerSequence(DerObject): + """Class to model a DER SEQUENCE. - Sub-elements that are INTEGERs behave like Python integers. + This object behaves like a dynamic Python sequence. - Any other sub-element is a binary string encoded as a complete DER - sub-element (TLV). + Sub-elements that are INTEGERs behave like Python integers. - An example of encoding is: + Any other sub-element is a binary string encoded as a complete DER + sub-element (TLV). - >>> from Cryptodome.Util.asn1 import DerSequence, DerInteger - >>> from binascii import hexlify, unhexlify - >>> obj_der = unhexlify('070102') - >>> seq_der = DerSequence([4]) - >>> seq_der.append(9) - >>> seq_der.append(obj_der.encode()) - >>> print hexlify(seq_der.encode()) + An example of encoding is: - which will show ``3009020104020109070102``, the DER encoding of the - sequence containing ``4``, ``9``, and the object with payload ``02``. + >>> from Cryptodome.Util.asn1 import DerSequence, DerInteger + >>> from binascii import hexlify, unhexlify + >>> obj_der = unhexlify('070102') + >>> seq_der = DerSequence([4]) + >>> seq_der.append(9) + >>> seq_der.append(obj_der.encode()) + >>> print hexlify(seq_der.encode()) - For decoding: + which will show ``3009020104020109070102``, the DER encoding of the + sequence containing ``4``, ``9``, and the object with payload ``02``. - >>> s = unhexlify(b'3009020104020109070102') - >>> try: - >>> seq_der = DerSequence() - >>> seq_der.decode(s) - >>> print len(seq_der) - >>> print seq_der[0] - >>> print seq_der[:] - >>> except ValueError: - >>> print "Not a valid DER SEQUENCE" + For decoding: - the output will be:: + >>> s = unhexlify(b'3009020104020109070102') + >>> try: + >>> seq_der = DerSequence() + >>> seq_der.decode(s) + >>> print len(seq_der) + >>> print seq_der[0] + >>> print seq_der[:] + >>> except ValueError: + >>> print "Not a valid DER SEQUENCE" - 3 - 4 - [4, 9, b'\x07\x01\x02'] + the output will be:: - """ + 3 + 4 + [4, 9, b'\x07\x01\x02'] - def __init__(self, startSeq=None, implicit=None, explicit=None): - """Initialize the DER object as a SEQUENCE. - - :Parameters: - startSeq : Python sequence - A sequence whose element are either integers or - other DER objects. + """ - implicit : integer or byte - The IMPLICIT tag number (< 0x1F) to use for the encoded object. - It overrides the universal tag for SEQUENCE (16). - It cannot be combined with the ``explicit`` parameter. - By default, there is no IMPLICIT tag. - - explicit : integer or byte - The EXPLICIT tag number (< 0x1F) to use for the encoded object. - It cannot be combined with the ``implicit`` parameter. - By default, there is no EXPLICIT tag. - """ - - DerObject.__init__(self, 0x10, b'', implicit, True, explicit) - if startSeq is None: - self._seq = [] - else: - self._seq = startSeq - - # A few methods to make it behave like a python sequence - - def __delitem__(self, n): - del self._seq[n] - - def __getitem__(self, n): - return self._seq[n] - - def __setitem__(self, key, value): - self._seq[key] = value + def __init__(self, startSeq=None, implicit=None, explicit=None): + """Initialize the DER object as a SEQUENCE. + + :Parameters: + startSeq : Python sequence + A sequence whose element are either integers or + other DER objects. - def __setslice__(self, i, j, sequence): - self._seq[i:j] = sequence + implicit : integer or byte + The IMPLICIT tag number (< 0x1F) to use for the encoded object. + It overrides the universal tag for SEQUENCE (16). + It cannot be combined with the ``explicit`` parameter. + By default, there is no IMPLICIT tag. + + explicit : integer or byte + The EXPLICIT tag number (< 0x1F) to use for the encoded object. + It cannot be combined with the ``implicit`` parameter. + By default, there is no EXPLICIT tag. + """ + + DerObject.__init__(self, 0x10, b"", implicit, True, explicit) + if startSeq is None: + self._seq = [] + else: + self._seq = startSeq + + # A few methods to make it behave like a python sequence + + def __delitem__(self, n): + del self._seq[n] + + def __getitem__(self, n): + return self._seq[n] + + def __setitem__(self, key, value): + self._seq[key] = value - def __delslice__(self, i, j): - del self._seq[i:j] + def __setslice__(self, i, j, sequence): + self._seq[i:j] = sequence - def __getslice__(self, i, j): - return self._seq[max(0, i):max(0, j)] + def __delslice__(self, i, j): + del self._seq[i:j] - def __len__(self): - return len(self._seq) + def __getslice__(self, i, j): + return self._seq[max(0, i) : max(0, j)] - def __iadd__(self, item): - self._seq.append(item) - return self + def __len__(self): + return len(self._seq) - def append(self, item): - self._seq.append(item) - return self - - def insert(self, index, item): - self._seq.insert(index, item) - return self - - def hasInts(self, only_non_negative=True): - """Return the number of items in this sequence that are - integers. - - Args: - only_non_negative (boolean): - If ``True``, negative integers are not counted in. - """ - - items = [x for x in self._seq if _is_number(x, only_non_negative)] - return len(items) - - def hasOnlyInts(self, only_non_negative=True): - """Return ``True`` if all items in this sequence are integers - or non-negative integers. - - This function returns False is the sequence is empty, - or at least one member is not an integer. - - Args: - only_non_negative (boolean): - If ``True``, the presence of negative integers - causes the method to return ``False``.""" - return self._seq and self.hasInts(only_non_negative) == len(self._seq) - - def encode(self): - """Return this DER SEQUENCE, fully encoded as a - binary string. - - Raises: - ValueError: if some elements in the sequence are neither integers - nor byte strings. - """ - self.payload = b'' - for item in self._seq: - if byte_string(item): - self.payload += item - elif _is_number(item): - self.payload += DerInteger(item).encode() - else: - self.payload += item.encode() - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False, nr_elements=None, only_ints_expected=False): - """Decode a complete DER SEQUENCE, and re-initializes this - object with it. - - Args: - der_encoded (byte string): - A complete SEQUENCE DER element. - nr_elements (None or integer or list of integers): - The number of members the SEQUENCE can have - only_ints_expected (boolean): - Whether the SEQUENCE is expected to contain only integers. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - - DER INTEGERs are decoded into Python integers. Any other DER - element is not decoded. Its validity is not checked. - """ + def __iadd__(self, item): + self._seq.append(item) + return self - self._nr_elements = nr_elements - result = DerObject.decode(self, der_encoded, strict=strict) + def append(self, item): + self._seq.append(item) + return self + + def insert(self, index, item): + self._seq.insert(index, item) + return self + + def hasInts(self, only_non_negative=True): + """Return the number of items in this sequence that are + integers. + + Args: + only_non_negative (boolean): + If ``True``, negative integers are not counted in. + """ + + items = [x for x in self._seq if _is_number(x, only_non_negative)] + return len(items) + + def hasOnlyInts(self, only_non_negative=True): + """Return ``True`` if all items in this sequence are integers + or non-negative integers. + + This function returns False is the sequence is empty, + or at least one member is not an integer. + + Args: + only_non_negative (boolean): + If ``True``, the presence of negative integers + causes the method to return ``False``.""" + return self._seq and self.hasInts(only_non_negative) == len(self._seq) + + def encode(self): + """Return this DER SEQUENCE, fully encoded as a + binary string. + + Raises: + ValueError: if some elements in the sequence are neither integers + nor byte strings. + """ + self.payload = b"" + for item in self._seq: + if byte_string(item): + self.payload += item + elif _is_number(item): + self.payload += DerInteger(item).encode() + else: + self.payload += item.encode() + return DerObject.encode(self) + + def decode(self, der_encoded, strict=False, nr_elements=None, only_ints_expected=False): + """Decode a complete DER SEQUENCE, and re-initializes this + object with it. + + Args: + der_encoded (byte string): + A complete SEQUENCE DER element. + nr_elements (None or integer or list of integers): + The number of members the SEQUENCE can have + only_ints_expected (boolean): + Whether the SEQUENCE is expected to contain only integers. + strict (boolean): + Whether decoding must check for strict DER compliancy. + + Raises: + ValueError: in case of parsing errors. + + DER INTEGERs are decoded into Python integers. Any other DER + element is not decoded. Its validity is not checked. + """ - if only_ints_expected and not self.hasOnlyInts(): - raise ValueError("Some members are not INTEGERs") - - return result - - def _decodeFromStream(self, s, strict): - """Decode a complete DER SEQUENCE from a file.""" - - self._seq = [] - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - # Add one item at a time to self.seq, by scanning self.payload - p = BytesIO_EOF(self.payload) - while p.remaining_data() > 0: - p.set_bookmark() - - der = DerObject() - der._decodeFromStream(p, strict) - - # Parse INTEGERs differently - if der._tag_octet != 0x02: - self._seq.append(p.data_since_bookmark()) - else: - derInt = DerInteger() - data = p.data_since_bookmark() - derInt.decode(data, strict=strict) - self._seq.append(derInt.value) - - ok = True - if self._nr_elements is not None: - try: - ok = len(self._seq) in self._nr_elements - except TypeError: - ok = len(self._seq) == self._nr_elements - - if not ok: - raise ValueError("Unexpected number of members (%d)" - " in the sequence" % len(self._seq)) + self._nr_elements = nr_elements + result = DerObject.decode(self, der_encoded, strict=strict) + + if only_ints_expected and not self.hasOnlyInts(): + raise ValueError("Some members are not INTEGERs") + + return result + + def _decodeFromStream(self, s, strict): + """Decode a complete DER SEQUENCE from a file.""" + + self._seq = [] + + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) + + # Add one item at a time to self.seq, by scanning self.payload + p = BytesIO_EOF(self.payload) + while p.remaining_data() > 0: + p.set_bookmark() + + der = DerObject() + der._decodeFromStream(p, strict) + + # Parse INTEGERs differently + if der._tag_octet != 0x02: + self._seq.append(p.data_since_bookmark()) + else: + derInt = DerInteger() + data = p.data_since_bookmark() + derInt.decode(data, strict=strict) + self._seq.append(derInt.value) + + ok = True + if self._nr_elements is not None: + try: + ok = len(self._seq) in self._nr_elements + except TypeError: + ok = len(self._seq) == self._nr_elements + + if not ok: + raise ValueError( + "Unexpected number of members (%d) in the sequence" % len(self._seq), + ) class DerOctetString(DerObject): - """Class to model a DER OCTET STRING. + """Class to model a DER OCTET STRING. - An example of encoding is: + An example of encoding is: - >>> from Cryptodome.Util.asn1 import DerOctetString - >>> from binascii import hexlify, unhexlify - >>> os_der = DerOctetString(b'\\xaa') - >>> os_der.payload += b'\\xbb' - >>> print hexlify(os_der.encode()) + >>> from Cryptodome.Util.asn1 import DerOctetString + >>> from binascii import hexlify, unhexlify + >>> os_der = DerOctetString(b'\\xaa') + >>> os_der.payload += b'\\xbb' + >>> print hexlify(os_der.encode()) - which will show ``0402aabb``, the DER encoding for the byte string - ``b'\\xAA\\xBB'``. + which will show ``0402aabb``, the DER encoding for the byte string + ``b'\\xAA\\xBB'``. - For decoding: + For decoding: - >>> s = unhexlify(b'0402aabb') - >>> try: - >>> os_der = DerOctetString() - >>> os_der.decode(s) - >>> print hexlify(os_der.payload) - >>> except ValueError: - >>> print "Not a valid DER OCTET STRING" + >>> s = unhexlify(b'0402aabb') + >>> try: + >>> os_der = DerOctetString() + >>> os_der.decode(s) + >>> print hexlify(os_der.payload) + >>> except ValueError: + >>> print "Not a valid DER OCTET STRING" - the output will be ``aabb``. + the output will be ``aabb``. - :ivar payload: The content of the string - :vartype payload: byte string - """ + :ivar payload: The content of the string + :vartype payload: byte string + """ - def __init__(self, value=b'', implicit=None): - """Initialize the DER object as an OCTET STRING. + def __init__(self, value=b"", implicit=None): + """Initialize the DER object as an OCTET STRING. - :Parameters: - value : byte string - The initial payload of the object. - If not specified, the payload is empty. + :Parameters: + value : byte string + The initial payload of the object. + If not specified, the payload is empty. - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for OCTET STRING (4). - """ - DerObject.__init__(self, 0x04, value, implicit, False) + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for OCTET STRING (4). + """ + DerObject.__init__(self, 0x04, value, implicit, False) class DerNull(DerObject): - """Class to model a DER NULL element.""" + """Class to model a DER NULL element.""" - def __init__(self): - """Initialize the DER object as a NULL.""" + def __init__(self): + """Initialize the DER object as a NULL.""" - DerObject.__init__(self, 0x05, b'', None, False) + DerObject.__init__(self, 0x05, b"", None, False) class DerObjectId(DerObject): - """Class to model a DER OBJECT ID. - - An example of encoding is: - - >>> from Cryptodome.Util.asn1 import DerObjectId - >>> from binascii import hexlify, unhexlify - >>> oid_der = DerObjectId("1.2") - >>> oid_der.value += ".840.113549.1.1.1" - >>> print hexlify(oid_der.encode()) - - which will show ``06092a864886f70d010101``, the DER encoding for the - RSA Object Identifier ``1.2.840.113549.1.1.1``. - - For decoding: - - >>> s = unhexlify(b'06092a864886f70d010101') - >>> try: - >>> oid_der = DerObjectId() - >>> oid_der.decode(s) - >>> print oid_der.value - >>> except ValueError: - >>> print "Not a valid DER OBJECT ID" - - the output will be ``1.2.840.113549.1.1.1``. - - :ivar value: The Object ID (OID), a dot separated list of integers - :vartype value: string - """ - - def __init__(self, value='', implicit=None, explicit=None): - """Initialize the DER object as an OBJECT ID. - - :Parameters: - value : string - The initial Object Identifier (e.g. "1.2.0.0.6.2"). - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for OBJECT ID (6). - explicit : integer - The EXPLICIT tag to use for the encoded object. - """ - DerObject.__init__(self, 0x06, b'', implicit, False, explicit) - self.value = value - - def encode(self): - """Return the DER OBJECT ID, fully encoded as a - binary string.""" - - comps = [int(x) for x in self.value.split(".")] - - if len(comps) < 2: - raise ValueError("Not a valid Object Identifier string") - if comps[0] > 2: - raise ValueError("First component must be 0, 1 or 2") - if comps[0] < 2 and comps[1] > 39: - raise ValueError("Second component must be 39 at most") - - subcomps = [40 * comps[0] + comps[1]] + comps[2:] - - encoding = [] - for v in reversed(subcomps): - encoding.append(v & 0x7F) - v >>= 7 - while v: - encoding.append((v & 0x7F) | 0x80) - v >>= 7 - - self.payload = b''.join([bchr(x) for x in reversed(encoding)]) - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False): - """Decode a complete DER OBJECT ID, and re-initializes this - object with it. - - Args: - der_encoded (byte string): - A complete DER OBJECT ID. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER OBJECT ID from a file.""" - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - # Derive self.value from self.payload - p = BytesIO_EOF(self.payload) - - subcomps = [] - v = 0 - while p.remaining_data(): - c = p.read_byte() - v = (v << 7) + (c & 0x7F) - if not (c & 0x80): - subcomps.append(v) - v = 0 - - if len(subcomps) == 0: - raise ValueError("Empty payload") - - if subcomps[0] < 40: - subcomps[:1] = [0, subcomps[0]] - elif subcomps[0] < 80: - subcomps[:1] = [1, subcomps[0] - 40] - else: - subcomps[:1] = [2, subcomps[0] - 80] - - self.value = ".".join([str(x) for x in subcomps]) + """Class to model a DER OBJECT ID. + + An example of encoding is: + + >>> from Cryptodome.Util.asn1 import DerObjectId + >>> from binascii import hexlify, unhexlify + >>> oid_der = DerObjectId("1.2") + >>> oid_der.value += ".840.113549.1.1.1" + >>> print hexlify(oid_der.encode()) + + which will show ``06092a864886f70d010101``, the DER encoding for the + RSA Object Identifier ``1.2.840.113549.1.1.1``. + + For decoding: + + >>> s = unhexlify(b'06092a864886f70d010101') + >>> try: + >>> oid_der = DerObjectId() + >>> oid_der.decode(s) + >>> print oid_der.value + >>> except ValueError: + >>> print "Not a valid DER OBJECT ID" + + the output will be ``1.2.840.113549.1.1.1``. + + :ivar value: The Object ID (OID), a dot separated list of integers + :vartype value: string + """ + + def __init__(self, value="", implicit=None, explicit=None): + """Initialize the DER object as an OBJECT ID. + + :Parameters: + value : string + The initial Object Identifier (e.g. "1.2.0.0.6.2"). + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for OBJECT ID (6). + explicit : integer + The EXPLICIT tag to use for the encoded object. + """ + DerObject.__init__(self, 0x06, b"", implicit, False, explicit) + self.value = value + + def encode(self): + """Return the DER OBJECT ID, fully encoded as a + binary string.""" + + comps = [int(x) for x in self.value.split(".")] + + if len(comps) < 2: + raise ValueError("Not a valid Object Identifier string") + if comps[0] > 2: + raise ValueError("First component must be 0, 1 or 2") + if comps[0] < 2 and comps[1] > 39: + raise ValueError("Second component must be 39 at most") + + subcomps = [40 * comps[0] + comps[1]] + comps[2:] + + encoding = [] + for v in reversed(subcomps): + encoding.append(v & 0x7F) + v >>= 7 + while v: + encoding.append((v & 0x7F) | 0x80) + v >>= 7 + + self.payload = b"".join([bchr(x) for x in reversed(encoding)]) + return DerObject.encode(self) + + def decode(self, der_encoded, strict=False): + """Decode a complete DER OBJECT ID, and re-initializes this + object with it. + + Args: + der_encoded (byte string): + A complete DER OBJECT ID. + strict (boolean): + Whether decoding must check for strict DER compliancy. + + Raises: + ValueError: in case of parsing errors. + """ + + return DerObject.decode(self, der_encoded, strict) + + def _decodeFromStream(self, s, strict): + """Decode a complete DER OBJECT ID from a file.""" + + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) + + # Derive self.value from self.payload + p = BytesIO_EOF(self.payload) + + subcomps = [] + v = 0 + while p.remaining_data(): + c = p.read_byte() + v = (v << 7) + (c & 0x7F) + if not (c & 0x80): + subcomps.append(v) + v = 0 + + if len(subcomps) == 0: + raise ValueError("Empty payload") + + if subcomps[0] < 40: + subcomps[:1] = [0, subcomps[0]] + elif subcomps[0] < 80: + subcomps[:1] = [1, subcomps[0] - 40] + else: + subcomps[:1] = [2, subcomps[0] - 80] + + self.value = ".".join([str(x) for x in subcomps]) class DerBitString(DerObject): - """Class to model a DER BIT STRING. + """Class to model a DER BIT STRING. - An example of encoding is: + An example of encoding is: - >>> from Cryptodome.Util.asn1 import DerBitString - >>> bs_der = DerBitString(b'\\xAA') - >>> bs_der.value += b'\\xBB' - >>> print(bs_der.encode().hex()) + >>> from Cryptodome.Util.asn1 import DerBitString + >>> bs_der = DerBitString(b'\\xAA') + >>> bs_der.value += b'\\xBB' + >>> print(bs_der.encode().hex()) - which will show ``030300aabb``, the DER encoding for the bit string - ``b'\\xAA\\xBB'``. + which will show ``030300aabb``, the DER encoding for the bit string + ``b'\\xAA\\xBB'``. - For decoding: + For decoding: - >>> s = bytes.fromhex('030300aabb') - >>> try: - >>> bs_der = DerBitString() - >>> bs_der.decode(s) - >>> print(bs_der.value.hex()) - >>> except ValueError: - >>> print "Not a valid DER BIT STRING" + >>> s = bytes.fromhex('030300aabb') + >>> try: + >>> bs_der = DerBitString() + >>> bs_der.decode(s) + >>> print(bs_der.value.hex()) + >>> except ValueError: + >>> print "Not a valid DER BIT STRING" - the output will be ``aabb``. + the output will be ``aabb``. - :ivar value: The content of the string - :vartype value: byte string - """ + :ivar value: The content of the string + :vartype value: byte string + """ - def __init__(self, value=b'', implicit=None, explicit=None): - """Initialize the DER object as a BIT STRING. + def __init__(self, value=b"", implicit=None, explicit=None): + """Initialize the DER object as a BIT STRING. - :Parameters: - value : byte string or DER object - The initial, packed bit string. - If not specified, the bit string is empty. - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for BIT STRING (3). - explicit : integer - The EXPLICIT tag to use for the encoded object. - """ - DerObject.__init__(self, 0x03, b'', implicit, False, explicit) + :Parameters: + value : byte string or DER object + The initial, packed bit string. + If not specified, the bit string is empty. + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for BIT STRING (3). + explicit : integer + The EXPLICIT tag to use for the encoded object. + """ + DerObject.__init__(self, 0x03, b"", implicit, False, explicit) - # The bitstring value (packed) - if isinstance(value, DerObject): - self.value = value.encode() - else: - self.value = value + # The bitstring value (packed) + if isinstance(value, DerObject): + self.value = value.encode() + else: + self.value = value - def encode(self): - """Return the DER BIT STRING, fully encoded as a - byte string.""" + def encode(self): + """Return the DER BIT STRING, fully encoded as a + byte string.""" - # Add padding count byte - self.payload = b'\x00' + self.value - return DerObject.encode(self) + # Add padding count byte + self.payload = b"\x00" + self.value + return DerObject.encode(self) - def decode(self, der_encoded, strict=False): - """Decode a complete DER BIT STRING, and re-initializes this - object with it. + def decode(self, der_encoded, strict=False): + """Decode a complete DER BIT STRING, and re-initializes this + object with it. - Args: - der_encoded (byte string): a complete DER BIT STRING. - strict (boolean): - Whether decoding must check for strict DER compliancy. + Args: + der_encoded (byte string): a complete DER BIT STRING. + strict (boolean): + Whether decoding must check for strict DER compliancy. - Raises: - ValueError: in case of parsing errors. - """ + Raises: + ValueError: in case of parsing errors. + """ - return DerObject.decode(self, der_encoded, strict) + return DerObject.decode(self, der_encoded, strict) - def _decodeFromStream(self, s, strict): - """Decode a complete DER BIT STRING DER from a file.""" + def _decodeFromStream(self, s, strict): + """Decode a complete DER BIT STRING DER from a file.""" - # Fill-up self.payload - DerObject._decodeFromStream(self, s, strict) + # Fill-up self.payload + DerObject._decodeFromStream(self, s, strict) - if self.payload and bord(self.payload[0]) != 0: - raise ValueError("Not a valid BIT STRING") + if self.payload and bord(self.payload[0]) != 0: + raise ValueError("Not a valid BIT STRING") - # Fill-up self.value - self.value = b'' - # Remove padding count byte - if self.payload: - self.value = self.payload[1:] + # Fill-up self.value + self.value = b"" + # Remove padding count byte + if self.payload: + self.value = self.payload[1:] class DerSetOf(DerObject): - """Class to model a DER SET OF. + """Class to model a DER SET OF. - An example of encoding is: + An example of encoding is: - >>> from Cryptodome.Util.asn1 import DerBitString - >>> from binascii import hexlify, unhexlify - >>> so_der = DerSetOf([4,5]) - >>> so_der.add(6) - >>> print hexlify(so_der.encode()) + >>> from Cryptodome.Util.asn1 import DerBitString + >>> from binascii import hexlify, unhexlify + >>> so_der = DerSetOf([4,5]) + >>> so_der.add(6) + >>> print hexlify(so_der.encode()) - which will show ``3109020104020105020106``, the DER encoding - of a SET OF with items 4,5, and 6. + which will show ``3109020104020105020106``, the DER encoding + of a SET OF with items 4,5, and 6. - For decoding: + For decoding: - >>> s = unhexlify(b'3109020104020105020106') - >>> try: - >>> so_der = DerSetOf() - >>> so_der.decode(s) - >>> print [x for x in so_der] - >>> except ValueError: - >>> print "Not a valid DER SET OF" + >>> s = unhexlify(b'3109020104020105020106') + >>> try: + >>> so_der = DerSetOf() + >>> so_der.decode(s) + >>> print [x for x in so_der] + >>> except ValueError: + >>> print "Not a valid DER SET OF" - the output will be ``[4, 5, 6]``. - """ - - def __init__(self, startSet=None, implicit=None): - """Initialize the DER object as a SET OF. - - :Parameters: - startSet : container - The initial set of integers or DER encoded objects. - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for SET OF (17). - """ - DerObject.__init__(self, 0x11, b'', implicit, True) - self._seq = [] - - # All elements must be of the same type (and therefore have the - # same leading octet) - self._elemOctet = None - - if startSet: - for e in startSet: - self.add(e) - - def __getitem__(self, n): - return self._seq[n] - - def __iter__(self): - return iter(self._seq) - - def __len__(self): - return len(self._seq) - - def add(self, elem): - """Add an element to the set. - - Args: - elem (byte string or integer): - An element of the same type of objects already in the set. - It can be an integer or a DER encoded object. - """ - - if _is_number(elem): - eo = 0x02 - elif isinstance(elem, DerObject): - eo = self._tag_octet - else: - eo = bord(elem[0]) - - if self._elemOctet != eo: - if self._elemOctet is not None: - raise ValueError("New element does not belong to the set") - self._elemOctet = eo - - if elem not in self._seq: - self._seq.append(elem) - - def decode(self, der_encoded, strict=False): - """Decode a complete SET OF DER element, and re-initializes this - object with it. - - DER INTEGERs are decoded into Python integers. Any other DER - element is left undecoded; its validity is not checked. - - Args: - der_encoded (byte string): a complete DER BIT SET OF. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER SET OF from a file.""" - - self._seq = [] - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - # Add one item at a time to self.seq, by scanning self.payload - p = BytesIO_EOF(self.payload) - setIdOctet = -1 - while p.remaining_data() > 0: - p.set_bookmark() - - der = DerObject() - der._decodeFromStream(p, strict) - - # Verify that all members are of the same type - if setIdOctet < 0: - setIdOctet = der._tag_octet - else: - if setIdOctet != der._tag_octet: - raise ValueError("Not all elements are of the same DER type") - - # Parse INTEGERs differently - if setIdOctet != 0x02: - self._seq.append(p.data_since_bookmark()) - else: - derInt = DerInteger() - derInt.decode(p.data_since_bookmark(), strict) - self._seq.append(derInt.value) - # end - - def encode(self): - """Return this SET OF DER element, fully encoded as a - binary string. - """ - - # Elements in the set must be ordered in lexicographic order - ordered = [] - for item in self._seq: - if _is_number(item): - bys = DerInteger(item).encode() - elif isinstance(item, DerObject): - bys = item.encode() - else: - bys = item - ordered.append(bys) - ordered.sort() - self.payload = b''.join(ordered) - return DerObject.encode(self) + the output will be ``[4, 5, 6]``. + """ + + def __init__(self, startSet=None, implicit=None): + """Initialize the DER object as a SET OF. + + :Parameters: + startSet : container + The initial set of integers or DER encoded objects. + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for SET OF (17). + """ + DerObject.__init__(self, 0x11, b"", implicit, True) + self._seq = [] + + # All elements must be of the same type (and therefore have the + # same leading octet) + self._elemOctet = None + + if startSet: + for e in startSet: + self.add(e) + + def __getitem__(self, n): + return self._seq[n] + + def __iter__(self): + return iter(self._seq) + + def __len__(self): + return len(self._seq) + + def add(self, elem): + """Add an element to the set. + + Args: + elem (byte string or integer): + An element of the same type of objects already in the set. + It can be an integer or a DER encoded object. + """ + + if _is_number(elem): + eo = 0x02 + elif isinstance(elem, DerObject): + eo = self._tag_octet + else: + eo = bord(elem[0]) + + if self._elemOctet != eo: + if self._elemOctet is not None: + raise ValueError("New element does not belong to the set") + self._elemOctet = eo + + if elem not in self._seq: + self._seq.append(elem) + + def decode(self, der_encoded, strict=False): + """Decode a complete SET OF DER element, and re-initializes this + object with it. + + DER INTEGERs are decoded into Python integers. Any other DER + element is left undecoded; its validity is not checked. + + Args: + der_encoded (byte string): a complete DER BIT SET OF. + strict (boolean): + Whether decoding must check for strict DER compliancy. + + Raises: + ValueError: in case of parsing errors. + """ + + return DerObject.decode(self, der_encoded, strict) + + def _decodeFromStream(self, s, strict): + """Decode a complete DER SET OF from a file.""" + + self._seq = [] + + # Fill up self.payload + DerObject._decodeFromStream(self, s, strict) + + # Add one item at a time to self.seq, by scanning self.payload + p = BytesIO_EOF(self.payload) + setIdOctet = -1 + while p.remaining_data() > 0: + p.set_bookmark() + + der = DerObject() + der._decodeFromStream(p, strict) + + # Verify that all members are of the same type + if setIdOctet < 0: + setIdOctet = der._tag_octet + else: + if setIdOctet != der._tag_octet: + raise ValueError("Not all elements are of the same DER type") + + # Parse INTEGERs differently + if setIdOctet != 0x02: + self._seq.append(p.data_since_bookmark()) + else: + derInt = DerInteger() + derInt.decode(p.data_since_bookmark(), strict) + self._seq.append(derInt.value) + # end + + def encode(self): + """Return this SET OF DER element, fully encoded as a + binary string. + """ + + # Elements in the set must be ordered in lexicographic order + ordered = [] + for item in self._seq: + if _is_number(item): + bys = DerInteger(item).encode() + elif isinstance(item, DerObject): + bys = item.encode() + else: + bys = item + ordered.append(bys) + ordered.sort() + self.payload = b"".join(ordered) + return DerObject.encode(self) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/asn1.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/asn1.pyi index ee4891c5..b4fe4e7e 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/asn1.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/asn1.pyi @@ -1,80 +1,117 @@ from typing import Optional, Sequence, Union, Set, Iterable -__all__ = ['DerObject', 'DerInteger', 'DerOctetString', 'DerNull', - 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf'] +__all__ = [ + "DerObject", + "DerInteger", + "DerOctetString", + "DerNull", + "DerSequence", + "DerObjectId", + "DerBitString", + "DerSetOf", +] # TODO: Make the encoded DerObjects their own type, so that DerSequence and # DerSetOf can check their contents better class BytesIO_EOF: - def __init__(self, initial_bytes: bytes) -> None: ... - def set_bookmark(self) -> None: ... - def data_since_bookmark(self) -> bytes: ... - def remaining_data(self) -> int: ... - def read(self, length: int) -> bytes: ... - def read_byte(self) -> bytes: ... + def __init__(self, initial_bytes: bytes) -> None: ... + def set_bookmark(self) -> None: ... + def data_since_bookmark(self) -> bytes: ... + def remaining_data(self) -> int: ... + def read(self, length: int) -> bytes: ... + def read_byte(self) -> bytes: ... class DerObject: - payload: bytes - def __init__(self, asn1Id: Optional[int]=None, payload: Optional[bytes]=..., implicit: Optional[int]=None, - constructed: Optional[bool]=False, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerObject: ... + payload: bytes + def __init__( + self, + asn1Id: Optional[int] = None, + payload: Optional[bytes] = ..., + implicit: Optional[int] = None, + constructed: Optional[bool] = False, + explicit: Optional[int] = None, + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerObject: ... class DerInteger(DerObject): - value: int - def __init__(self, value: Optional[int]= 0, implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerInteger: ... + value: int + def __init__( + self, value: Optional[int] = 0, implicit: Optional[int] = None, explicit: Optional[int] = None + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerInteger: ... class DerBoolean(DerObject): - value: bool - def __init__(self, value: bool=..., implicit: Optional[Union[int, bytes]]=..., explicit: Optional[Union[int, bytes]]=...) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerBoolean: ... + value: bool + def __init__( + self, + value: bool = ..., + implicit: Optional[Union[int, bytes]] = ..., + explicit: Optional[Union[int, bytes]] = ..., + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerBoolean: ... class DerSequence(DerObject): - def __init__(self, startSeq: Optional[Sequence[Union[int, DerInteger, DerObject]]]=None, implicit: Optional[int]=None) -> None: ... - def __delitem__(self, n: int) -> None: ... - def __getitem__(self, n: int) -> None: ... - def __setitem__(self, key: int, value: DerObject) -> None: ... - def __setslice__(self, i: int, j: int, sequence: Sequence) -> None: ... - def __delslice__(self, i: int, j: int) -> None: ... - def __getslice__(self, i: int, j: int) -> DerSequence: ... - def __len__(self) -> int: ... - def __iadd__(self, item: DerObject) -> DerSequence: ... - def append(self, item: DerObject) -> DerSequence: ... - def hasInts(self, only_non_negative: Optional[bool]=True) -> int: ... - def hasOnlyInts(self, only_non_negative: Optional[bool]=True) -> bool: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=..., nr_elements: Optional[int]=None, only_ints_expected: Optional[bool]=False) -> DerSequence: ... + def __init__( + self, + startSeq: Optional[Sequence[Union[int, DerInteger, DerObject]]] = None, + implicit: Optional[int] = None, + ) -> None: ... + def __delitem__(self, n: int) -> None: ... + def __getitem__(self, n: int) -> None: ... + def __setitem__(self, key: int, value: DerObject) -> None: ... + def __setslice__(self, i: int, j: int, sequence: Sequence) -> None: ... + def __delslice__(self, i: int, j: int) -> None: ... + def __getslice__(self, i: int, j: int) -> DerSequence: ... + def __len__(self) -> int: ... + def __iadd__(self, item: DerObject) -> DerSequence: ... + def append(self, item: DerObject) -> DerSequence: ... + def hasInts(self, only_non_negative: Optional[bool] = True) -> int: ... + def hasOnlyInts(self, only_non_negative: Optional[bool] = True) -> bool: ... + def encode(self) -> bytes: ... + def decode( + self, + der_encoded: bytes, + strict: bool = ..., + nr_elements: Optional[int] = None, + only_ints_expected: Optional[bool] = False, + ) -> DerSequence: ... class DerOctetString(DerObject): - payload: bytes - def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None) -> None: ... + payload: bytes + def __init__(self, value: Optional[bytes] = ..., implicit: Optional[int] = None) -> None: ... class DerNull(DerObject): - def __init__(self) -> None: ... + def __init__(self) -> None: ... class DerObjectId(DerObject): - value: str - def __init__(self, value: Optional[str]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerObjectId: ... + value: str + def __init__( + self, value: Optional[str] = ..., implicit: Optional[int] = None, explicit: Optional[int] = None + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerObjectId: ... class DerBitString(DerObject): - value: bytes - def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerBitString: ... + value: bytes + def __init__( + self, value: Optional[bytes] = ..., implicit: Optional[int] = None, explicit: Optional[int] = None + ) -> None: ... + def encode(self) -> bytes: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerBitString: ... DerSetElement = Union[bytes, int] class DerSetOf(DerObject): - def __init__(self, startSet: Optional[Set[DerSetElement]]=None, implicit: Optional[int]=None) -> None: ... - def __getitem__(self, n: int) -> DerSetElement: ... - def __iter__(self) -> Iterable: ... - def __len__(self) -> int: ... - def add(self, elem: DerSetElement) -> None: ... - def decode(self, der_encoded: bytes, strict: bool=...) -> DerObject: ... - def encode(self) -> bytes: ... + def __init__( + self, startSet: Optional[Set[DerSetElement]] = None, implicit: Optional[int] = None + ) -> None: ... + def __getitem__(self, n: int) -> DerSetElement: ... + def __iter__(self) -> Iterable: ... + def __len__(self) -> int: ... + def add(self, elem: DerSetElement) -> None: ... + def decode(self, der_encoded: bytes, strict: bool = ...) -> DerObject: ... + def encode(self) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/number.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/number.py index 701c21c3..5e8aaa3b 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/number.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/number.py @@ -35,1491 +35,10504 @@ def ceil_div(n, d): - """Return ceil(n/d), that is, the smallest integer r such that r*d >= n""" + """Return ceil(n/d), that is, the smallest integer r such that r*d >= n""" - if d == 0: - raise ZeroDivisionError() - if (n < 0) or (d < 0): - raise ValueError("Non positive values") - r, q = divmod(n, d) - if (n != 0) and (q != 0): - r += 1 - return r + if d == 0: + raise ZeroDivisionError() + if (n < 0) or (d < 0): + raise ValueError("Non positive values") + r, q = divmod(n, d) + if (n != 0) and (q != 0): + r += 1 + return r -def size (N): - """Returns the size of the number N in bits.""" +def size(N): + """Returns the size of the number N in bits.""" - if N < 0: - raise ValueError("Size in bits only available for non-negative numbers") - return N.bit_length() + if N < 0: + raise ValueError("Size in bits only available for non-negative numbers") + return N.bit_length() def getRandomInteger(N, randfunc=None): - """Return a random number at most N bits long. + """Return a random number at most N bits long. - If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. + If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. Use :func:`Cryptodome.Random.random.getrandbits` instead. - """ + .. deprecated:: 3.0 + This function is for internal use only and may be renamed or removed in + the future. Use :func:`Cryptodome.Random.random.getrandbits` instead. + """ - if randfunc is None: - randfunc = Random.get_random_bytes + if randfunc is None: + randfunc = Random.get_random_bytes + + S = randfunc(N >> 3) + odd_bits = N % 8 + if odd_bits != 0: + rand_bits = ord(randfunc(1)) >> (8 - odd_bits) + S = struct.pack("B", rand_bits) + S + value = bytes_to_long(S) + return value - S = randfunc(N>>3) - odd_bits = N % 8 - if odd_bits != 0: - rand_bits = ord(randfunc(1)) >> (8-odd_bits) - S = struct.pack('B', rand_bits) + S - value = bytes_to_long(S) - return value def getRandomRange(a, b, randfunc=None): - """Return a random number *n* so that *a <= n < b*. + """Return a random number *n* so that *a <= n < b*. + + If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. - If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. + .. deprecated:: 3.0 + This function is for internal use only and may be renamed or removed in + the future. Use :func:`Cryptodome.Random.random.randrange` instead. + """ - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. Use :func:`Cryptodome.Random.random.randrange` instead. - """ + range_ = b - a - 1 + bits = size(range_) + value = getRandomInteger(bits, randfunc) + while value > range_: + value = getRandomInteger(bits, randfunc) + return a + value - range_ = b - a - 1 - bits = size(range_) - value = getRandomInteger(bits, randfunc) - while value > range_: - value = getRandomInteger(bits, randfunc) - return a + value def getRandomNBitInteger(N, randfunc=None): - """Return a random number with exactly N-bits, - i.e. a random number between 2**(N-1) and (2**N)-1. + """Return a random number with exactly N-bits, + i.e. a random number between 2**(N-1) and (2**N)-1. - If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. + If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. - """ + .. deprecated:: 3.0 + This function is for internal use only and may be renamed or removed in + the future. + """ - value = getRandomInteger (N-1, randfunc) - value |= 2 ** (N-1) # Ensure high bit is set - assert size(value) >= N - return value + value = getRandomInteger(N - 1, randfunc) + value |= 2 ** (N - 1) # Ensure high bit is set + assert size(value) >= N + return value if sys.version_info[:2] >= (3, 5): - - GCD = math.gcd + GCD = math.gcd else: - def GCD(x,y): - """Greatest Common Denominator of :data:`x` and :data:`y`. - """ + def GCD(x, y): + """Greatest Common Denominator of :data:`x` and :data:`y`.""" - x = abs(x) ; y = abs(y) - while x > 0: - x, y = y % x, x - return y + x = abs(x) + y = abs(y) + while x > 0: + x, y = y % x, x + return y if sys.version_info[:2] >= (3, 8): - def inverse(u, v): - """The inverse of :data:`u` *mod* :data:`v`.""" + def inverse(u, v): + """The inverse of :data:`u` *mod* :data:`v`.""" - if v == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if v < 0: - raise ValueError("Modulus cannot be negative") + if v == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if v < 0: + raise ValueError("Modulus cannot be negative") - return pow(u, -1, v) + return pow(u, -1, v) else: - def inverse(u, v): - """The inverse of :data:`u` *mod* :data:`v`.""" - - if v == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if v < 0: - raise ValueError("Modulus cannot be negative") - - u3, v3 = u, v - u1, v1 = 1, 0 - while v3 > 0: - q = u3 // v3 - u1, v1 = v1, u1 - v1*q - u3, v3 = v3, u3 - v3*q - if u3 != 1: - raise ValueError("No inverse value can be computed") - while u1<0: - u1 = u1 + v - return u1 + def inverse(u, v): + """The inverse of :data:`u` *mod* :data:`v`.""" + + if v == 0: + raise ZeroDivisionError("Modulus cannot be zero") + if v < 0: + raise ValueError("Modulus cannot be negative") + + u3, v3 = u, v + u1, v1 = 1, 0 + while v3 > 0: + q = u3 // v3 + u1, v1 = v1, u1 - v1 * q + u3, v3 = v3, u3 - v3 * q + if u3 != 1: + raise ValueError("No inverse value can be computed") + while u1 < 0: + u1 = u1 + v + return u1 # Given a number of bits to generate and a random generation function, # find a prime number of the appropriate size. + def getPrime(N, randfunc=None): - """Return a random N-bit prime number. + """Return a random N-bit prime number. - N must be an integer larger than 1. - If randfunc is omitted, then :meth:`Random.get_random_bytes` is used. - """ - if randfunc is None: - randfunc = Random.get_random_bytes + N must be an integer larger than 1. + If randfunc is omitted, then :meth:`Random.get_random_bytes` is used. + """ + if randfunc is None: + randfunc = Random.get_random_bytes - if N < 2: - raise ValueError("N must be larger than 1") + if N < 2: + raise ValueError("N must be larger than 1") - while True: - number = getRandomNBitInteger(N, randfunc) | 1 - if isPrime(number, randfunc=randfunc): - break - return number + while True: + number = getRandomNBitInteger(N, randfunc) | 1 + if isPrime(number, randfunc=randfunc): + break + return number def _rabinMillerTest(n, rounds, randfunc=None): - """_rabinMillerTest(n:long, rounds:int, randfunc:callable):int - Tests if n is prime. - Returns 0 when n is definitely composite. - Returns 1 when n is probably prime. - Returns 2 when n is definitely prime. - - If randfunc is omitted, then Random.new().read is used. - - This function is for internal use only and may be renamed or removed in - the future. - """ - # check special cases (n==2, n even, n < 2) - if n < 3 or (n & 1) == 0: - return n == 2 - # n might be very large so it might be beneficial to precalculate n-1 - n_1 = n - 1 - # determine m and b so that 2**b * m = n - 1 and b maximal - b = 0 - m = n_1 - while (m & 1) == 0: - b += 1 - m >>= 1 - - tested = [] - # we need to do at most n-2 rounds. - for i in iter_range (min (rounds, n-2)): - # randomly choose a < n and make sure it hasn't been tested yet - a = getRandomRange (2, n, randfunc) - while a in tested: - a = getRandomRange (2, n, randfunc) - tested.append (a) - # do the rabin-miller test - z = pow (a, m, n) # (a**m) % n - if z == 1 or z == n_1: - continue - composite = 1 - for r in iter_range(b): - z = (z * z) % n - if z == 1: - return 0 - elif z == n_1: - composite = 0 - break - if composite: - return 0 - return 1 + """_rabinMillerTest(n:long, rounds:int, randfunc:callable):int + Tests if n is prime. + Returns 0 when n is definitely composite. + Returns 1 when n is probably prime. + Returns 2 when n is definitely prime. + + If randfunc is omitted, then Random.new().read is used. + + This function is for internal use only and may be renamed or removed in + the future. + """ + # check special cases (n==2, n even, n < 2) + if n < 3 or (n & 1) == 0: + return n == 2 + # n might be very large so it might be beneficial to precalculate n-1 + n_1 = n - 1 + # determine m and b so that 2**b * m = n - 1 and b maximal + b = 0 + m = n_1 + while (m & 1) == 0: + b += 1 + m >>= 1 + + tested = [] + # we need to do at most n-2 rounds. + for i in iter_range(min(rounds, n - 2)): + # randomly choose a < n and make sure it hasn't been tested yet + a = getRandomRange(2, n, randfunc) + while a in tested: + a = getRandomRange(2, n, randfunc) + tested.append(a) + # do the rabin-miller test + z = pow(a, m, n) # (a**m) % n + if z == 1 or z == n_1: + continue + composite = 1 + for r in iter_range(b): + z = (z * z) % n + if z == 1: + return 0 + elif z == n_1: + composite = 0 + break + if composite: + return 0 + return 1 + def getStrongPrime(N, e=0, false_positive_prob=1e-6, randfunc=None): - r""" - Return a random strong *N*-bit prime number. - In this context, *p* is a strong prime if *p-1* and *p+1* have at - least one large prime factor. - - Args: - N (integer): the exact length of the strong prime. - It must be a multiple of 128 and > 512. - e (integer): if provided, the returned prime (minus 1) - will be coprime to *e* and thus suitable for RSA where - *e* is the public exponent. - false_positive_prob (float): - The statistical probability for the result not to be actually a - prime. It defaults to 10\ :sup:`-6`. - Note that the real probability of a false-positive is far less. This is - just the mathematically provable limit. - randfunc (callable): - A function that takes a parameter *N* and that returns - a random byte string of such length. - If omitted, :func:`Cryptodome.Random.get_random_bytes` is used. - Return: - The new strong prime. - - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. - """ - - # This function was implemented following the - # instructions found in the paper: - # "FAST GENERATION OF RANDOM, STRONG RSA PRIMES" - # by Robert D. Silverman - # RSA Laboratories - # May 17, 1997 - # which by the time of writing could be freely downloaded here: - # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf - - if randfunc is None: - randfunc = Random.get_random_bytes - - # Use the accelerator if available - if _fastmath is not None: - return _fastmath.getStrongPrime(long(N), long(e), false_positive_prob, - randfunc) - - if (N < 512) or ((N % 128) != 0): - raise ValueError ("bits must be multiple of 128 and > 512") - - rabin_miller_rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4))) - - # calculate range for X - # lower_bound = sqrt(2) * 2^{511 + 128*x} - # upper_bound = 2^{512 + 128*x} - 1 - x = (N - 512) >> 7 - # We need to approximate the sqrt(2) in the lower_bound by an integer - # expression because floating point math overflows with these numbers - lower_bound = (14142135623730950489 * (2 ** (511 + 128*x))) // 10000000000000000000 - upper_bound = (1 << (512 + 128*x)) - 1 - # Randomly choose X in calculated range - X = getRandomRange (lower_bound, upper_bound, randfunc) - - # generate p1 and p2 - p = [0, 0] - for i in (0, 1): - # randomly choose 101-bit y - y = getRandomNBitInteger (101, randfunc) - # initialize the field for sieving - field = [0] * 5 * len (sieve_base) - # sieve the field - for prime in sieve_base: - offset = y % prime - for j in iter_range((prime - offset) % prime, len (field), prime): - field[j] = 1 - - # look for suitable p[i] starting at y - result = 0 - for j in range(len(field)): - composite = field[j] - # look for next canidate - if composite: - continue - tmp = y + j - result = _rabinMillerTest (tmp, rabin_miller_rounds) - if result > 0: - p[i] = tmp - break - if result == 0: - raise RuntimeError ("Couln't find prime in field. " - "Developer: Increase field_size") - - # Calculate R - # R = (p2^{-1} mod p1) * p2 - (p1^{-1} mod p2) * p1 - tmp1 = inverse (p[1], p[0]) * p[1] # (p2^-1 mod p1)*p2 - tmp2 = inverse (p[0], p[1]) * p[0] # (p1^-1 mod p2)*p1 - R = tmp1 - tmp2 # (p2^-1 mod p1)*p2 - (p1^-1 mod p2)*p1 - - # search for final prime number starting by Y0 - # Y0 = X + (R - X mod p1p2) - increment = p[0] * p[1] - X = X + (R - (X % increment)) - while 1: - is_possible_prime = 1 - # first check candidate against sieve_base - for prime in sieve_base: - if (X % prime) == 0: - is_possible_prime = 0 - break - # if e is given make sure that e and X-1 are coprime - # this is not necessarily a strong prime criterion but useful when - # creating them for RSA where the p-1 and q-1 should be coprime to - # the public exponent e - if e and is_possible_prime: - if e & 1: - if GCD(e, X-1) != 1: - is_possible_prime = 0 - else: - if GCD(e, (X-1) // 2) != 1: - is_possible_prime = 0 - - # do some Rabin-Miller-Tests - if is_possible_prime: - result = _rabinMillerTest (X, rabin_miller_rounds) - if result > 0: - break - X += increment + r""" + Return a random strong *N*-bit prime number. + In this context, *p* is a strong prime if *p-1* and *p+1* have at + least one large prime factor. + + Args: + N (integer): the exact length of the strong prime. + It must be a multiple of 128 and > 512. + e (integer): if provided, the returned prime (minus 1) + will be coprime to *e* and thus suitable for RSA where + *e* is the public exponent. + false_positive_prob (float): + The statistical probability for the result not to be actually a + prime. It defaults to 10\ :sup:`-6`. + Note that the real probability of a false-positive is far less. This is + just the mathematically provable limit. + randfunc (callable): + A function that takes a parameter *N* and that returns + a random byte string of such length. + If omitted, :func:`Cryptodome.Random.get_random_bytes` is used. + Return: + The new strong prime. + + .. deprecated:: 3.0 + This function is for internal use only and may be renamed or removed in + the future. + """ + + # This function was implemented following the + # instructions found in the paper: + # "FAST GENERATION OF RANDOM, STRONG RSA PRIMES" + # by Robert D. Silverman + # RSA Laboratories + # May 17, 1997 + # which by the time of writing could be freely downloaded here: + # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf + + if randfunc is None: + randfunc = Random.get_random_bytes + + # Use the accelerator if available + if _fastmath is not None: + return _fastmath.getStrongPrime( + long(N), + long(e), + false_positive_prob, + randfunc, + ) + + if (N < 512) or ((N % 128) != 0): + raise ValueError("bits must be multiple of 128 and > 512") + + rabin_miller_rounds = int(math.ceil(-math.log(false_positive_prob) / math.log(4))) + + # calculate range for X + # lower_bound = sqrt(2) * 2^{511 + 128*x} + # upper_bound = 2^{512 + 128*x} - 1 + x = (N - 512) >> 7 + # We need to approximate the sqrt(2) in the lower_bound by an integer + # expression because floating point math overflows with these numbers + lower_bound = (14142135623730950489 * (2 ** (511 + 128 * x))) // 10000000000000000000 + upper_bound = (1 << (512 + 128 * x)) - 1 + # Randomly choose X in calculated range + X = getRandomRange(lower_bound, upper_bound, randfunc) + + # generate p1 and p2 + p = [0, 0] + for i in (0, 1): + # randomly choose 101-bit y + y = getRandomNBitInteger(101, randfunc) + # initialize the field for sieving + field = [0] * 5 * len(sieve_base) + # sieve the field + for prime in sieve_base: + offset = y % prime + for j in iter_range((prime - offset) % prime, len(field), prime): + field[j] = 1 + + # look for suitable p[i] starting at y + result = 0 + for j in range(len(field)): + composite = field[j] + # look for next canidate + if composite: + continue + tmp = y + j + result = _rabinMillerTest(tmp, rabin_miller_rounds) + if result > 0: + p[i] = tmp + break + if result == 0: + raise RuntimeError( + "Couln't find prime in field. Developer: Increase field_size", + ) + + # Calculate R + # R = (p2^{-1} mod p1) * p2 - (p1^{-1} mod p2) * p1 + tmp1 = inverse(p[1], p[0]) * p[1] # (p2^-1 mod p1)*p2 + tmp2 = inverse(p[0], p[1]) * p[0] # (p1^-1 mod p2)*p1 + R = tmp1 - tmp2 # (p2^-1 mod p1)*p2 - (p1^-1 mod p2)*p1 + + # search for final prime number starting by Y0 + # Y0 = X + (R - X mod p1p2) + increment = p[0] * p[1] + X = X + (R - (X % increment)) + while 1: + is_possible_prime = 1 + # first check candidate against sieve_base + for prime in sieve_base: + if (X % prime) == 0: + is_possible_prime = 0 + break + # if e is given make sure that e and X-1 are coprime + # this is not necessarily a strong prime criterion but useful when + # creating them for RSA where the p-1 and q-1 should be coprime to + # the public exponent e + if e and is_possible_prime: + if e & 1: + if GCD(e, X - 1) != 1: + is_possible_prime = 0 + else: + if GCD(e, (X - 1) // 2) != 1: + is_possible_prime = 0 + + # do some Rabin-Miller-Tests + if is_possible_prime: + result = _rabinMillerTest(X, rabin_miller_rounds) + if result > 0: + break + X += increment # abort when X has more bits than requested # TODO: maybe we shouldn't abort but rather start over. - if X >= 1 << N: - raise RuntimeError ("Couln't find prime in field. " - "Developer: Increase field_size") - return X + if X >= 1 << N: + raise RuntimeError( + "Couln't find prime in field. Developer: Increase field_size", + ) + return X + def isPrime(N, false_positive_prob=1e-6, randfunc=None): - r"""Test if a number *N* is a prime. + r"""Test if a number *N* is a prime. - Args: - false_positive_prob (float): - The statistical probability for the result not to be actually a - prime. It defaults to 10\ :sup:`-6`. - Note that the real probability of a false-positive is far less. - This is just the mathematically provable limit. - randfunc (callable): - A function that takes a parameter *N* and that returns - a random byte string of such length. - If omitted, :func:`Cryptodome.Random.get_random_bytes` is used. + Args: + false_positive_prob (float): + The statistical probability for the result not to be actually a + prime. It defaults to 10\ :sup:`-6`. + Note that the real probability of a false-positive is far less. + This is just the mathematically provable limit. + randfunc (callable): + A function that takes a parameter *N* and that returns + a random byte string of such length. + If omitted, :func:`Cryptodome.Random.get_random_bytes` is used. - Return: - `True` if the input is indeed prime. - """ + Return: + `True` if the input is indeed prime. + """ - if randfunc is None: - randfunc = Random.get_random_bytes + if randfunc is None: + randfunc = Random.get_random_bytes - if _fastmath is not None: - return _fastmath.isPrime(long(N), false_positive_prob, randfunc) + if _fastmath is not None: + return _fastmath.isPrime(long(N), false_positive_prob, randfunc) - if N < 3 or N & 1 == 0: - return N == 2 - for p in sieve_base: - if N == p: - return True - if N % p == 0: - return False + if N < 3 or N & 1 == 0: + return N == 2 + for p in sieve_base: + if N == p: + return True + if N % p == 0: + return False - rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4))) - return bool(_rabinMillerTest(N, rounds, randfunc)) + rounds = int(math.ceil(-math.log(false_positive_prob) / math.log(4))) + return bool(_rabinMillerTest(N, rounds, randfunc)) # Improved conversion functions contributed by Barry Warsaw, after # careful benchmarking -import struct def long_to_bytes(n, blocksize=0): - """Convert a positive integer to a byte string using big endian encoding. + """Convert a positive integer to a byte string using big endian encoding. - If :data:`blocksize` is absent or zero, the byte string will - be of minimal length. + If :data:`blocksize` is absent or zero, the byte string will + be of minimal length. - Otherwise, the length of the byte string is guaranteed to be a multiple - of :data:`blocksize`. If necessary, zeroes (``\\x00``) are added at the left. + Otherwise, the length of the byte string is guaranteed to be a multiple + of :data:`blocksize`. If necessary, zeroes (``\\x00``) are added at the left. - .. note:: - In Python 3, if you are sure that :data:`n` can fit into - :data:`blocksize` bytes, you can simply use the native method instead:: + .. note:: + In Python 3, if you are sure that :data:`n` can fit into + :data:`blocksize` bytes, you can simply use the native method instead:: - >>> n.to_bytes(blocksize, 'big') + >>> n.to_bytes(blocksize, 'big') - For instance:: + For instance:: - >>> n = 80 - >>> n.to_bytes(2, 'big') - b'\\x00P' + >>> n = 80 + >>> n.to_bytes(2, 'big') + b'\\x00P' - However, and unlike this ``long_to_bytes()`` function, - an ``OverflowError`` exception is raised if :data:`n` does not fit. - """ + However, and unlike this ``long_to_bytes()`` function, + an ``OverflowError`` exception is raised if :data:`n` does not fit. + """ - if n < 0 or blocksize < 0: - raise ValueError("Values must be non-negative") + if n < 0 or blocksize < 0: + raise ValueError("Values must be non-negative") - result = [] - pack = struct.pack + result = [] + pack = struct.pack - # Fill the first block independently from the value of n - bsr = blocksize - while bsr >= 8: - result.insert(0, pack('>Q', n & 0xFFFFFFFFFFFFFFFF)) - n = n >> 64 - bsr -= 8 + # Fill the first block independently from the value of n + bsr = blocksize + while bsr >= 8: + result.insert(0, pack(">Q", n & 0xFFFFFFFFFFFFFFFF)) + n = n >> 64 + bsr -= 8 - while bsr >= 4: - result.insert(0, pack('>I', n & 0xFFFFFFFF)) - n = n >> 32 - bsr -= 4 + while bsr >= 4: + result.insert(0, pack(">I", n & 0xFFFFFFFF)) + n = n >> 32 + bsr -= 4 - while bsr > 0: - result.insert(0, pack('>B', n & 0xFF)) - n = n >> 8 - bsr -= 1 + while bsr > 0: + result.insert(0, pack(">B", n & 0xFF)) + n = n >> 8 + bsr -= 1 - if n == 0: - if len(result) == 0: - bresult = b'\x00' - else: - bresult = b''.join(result) - else: - # The encoded number exceeds the block size - while n > 0: - result.insert(0, pack('>Q', n & 0xFFFFFFFFFFFFFFFF)) - n = n >> 64 - result[0] = result[0].lstrip(b'\x00') - bresult = b''.join(result) - # bresult has minimum length here - if blocksize > 0: - target_len = ((len(bresult) - 1) // blocksize + 1) * blocksize - bresult = b'\x00' * (target_len - len(bresult)) + bresult + if n == 0: + if len(result) == 0: + bresult = b"\x00" + else: + bresult = b"".join(result) + else: + # The encoded number exceeds the block size + while n > 0: + result.insert(0, pack(">Q", n & 0xFFFFFFFFFFFFFFFF)) + n = n >> 64 + result[0] = result[0].lstrip(b"\x00") + bresult = b"".join(result) + # bresult has minimum length here + if blocksize > 0: + target_len = ((len(bresult) - 1) // blocksize + 1) * blocksize + bresult = b"\x00" * (target_len - len(bresult)) + bresult - return bresult + return bresult def bytes_to_long(s): - """Convert a byte string to a long integer (big endian). + """Convert a byte string to a long integer (big endian). - In Python 3.2+, use the native method instead:: + In Python 3.2+, use the native method instead:: - >>> int.from_bytes(s, 'big') + >>> int.from_bytes(s, 'big') - For instance:: + For instance:: - >>> int.from_bytes(b'\x00P', 'big') - 80 + >>> int.from_bytes(b'\x00P', 'big') + 80 - This is (essentially) the inverse of :func:`long_to_bytes`. - """ - acc = 0 + This is (essentially) the inverse of :func:`long_to_bytes`. + """ + acc = 0 - unpack = struct.unpack + unpack = struct.unpack - # Up to Python 2.7.4, struct.unpack can't work with bytearrays nor - # memoryviews - if sys.version_info[0:3] < (2, 7, 4): - if isinstance(s, bytearray): - s = bytes(s) - elif isinstance(s, memoryview): - s = s.tobytes() + # Up to Python 2.7.4, struct.unpack can't work with bytearrays nor + # memoryviews + if sys.version_info[0:3] < (2, 7, 4): + if isinstance(s, bytearray): + s = bytes(s) + elif isinstance(s, memoryview): + s = s.tobytes() - length = len(s) - if length % 4: - extra = (4 - length % 4) - s = b'\x00' * extra + s - length = length + extra - for i in range(0, length, 4): - acc = (acc << 32) + unpack('>I', s[i:i+4])[0] - return acc + length = len(s) + if length % 4: + extra = 4 - length % 4 + s = b"\x00" * extra + s + length = length + extra + for i in range(0, length, 4): + acc = (acc << 32) + unpack(">I", s[i : i + 4])[0] + return acc # For backwards compatibility... import warnings + + def long2str(n, blocksize=0): - warnings.warn("long2str() has been replaced by long_to_bytes()") - return long_to_bytes(n, blocksize) + warnings.warn("long2str() has been replaced by long_to_bytes()") + return long_to_bytes(n, blocksize) + + def str2long(s): - warnings.warn("str2long() has been replaced by bytes_to_long()") - return bytes_to_long(s) + warnings.warn("str2long() has been replaced by bytes_to_long()") + return bytes_to_long(s) # The first 10000 primes used for checking primality. # This should be enough to eliminate most of the odd # numbers before needing to do a Rabin-Miller test at all. sieve_base = ( - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, - 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, - 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, - 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, - 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, - 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, - 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, - 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, - 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, - 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, - 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, - 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, - 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, - 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, - 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, - 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, - 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, - 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, - 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, - 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, - 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, - 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, - 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, - 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, - 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, - 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, - 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, - 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, - 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, - 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, - 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, - 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, - 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, - 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, - 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, - 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, - 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, - 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, - 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, - 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, - 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, - 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, - 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, - 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, - 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, - 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, - 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, - 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, - 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, - 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, - 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, - 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, - 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, - 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, - 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, - 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, - 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, - 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, - 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, - 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, - 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, - 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, - 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, - 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, - 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, - 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, - 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, - 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, - 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, - 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, - 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, - 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, - 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, - 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, - 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, - 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, - 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, - 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, - 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, - 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, - 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, - 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, - 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, - 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, - 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, - 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, - 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, - 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, - 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, - 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, - 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, - 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, - 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, - 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, - 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, - 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, - 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, - 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, - 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, - 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, - 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, - 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, - 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, - 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, - 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, - 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, - 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, - 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, - 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, - 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, - 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, - 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, - 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, - 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, - 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, - 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, - 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, - 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, - 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, - 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, - 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, - 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, - 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, - 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, - 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, - 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, - 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, - 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, - 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, - 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, - 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, - 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, - 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, - 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, - 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, - 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, - 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, - 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, - 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, - 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, - 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, - 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, - 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, - 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, - 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, - 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, - 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, - 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, - 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, - 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, - 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, - 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, - 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, - 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, - 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, - 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, - 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, - 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, - 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, - 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, - 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, - 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, - 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, - 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, - 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, - 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, - 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, - 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, - 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, - 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, - 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, - 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, - 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, - 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, - 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, - 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, - 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, - 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, - 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, - 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, - 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, - 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, - 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, - 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, - 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, - 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, - 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, - 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, - 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, - 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, - 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, - 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, - 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, - 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, - 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, - 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, - 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, - 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, - 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, - 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, - 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, - 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, - 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, - 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, - 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, - 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, - 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, - 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, - 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, - 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, - 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, - 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, - 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, - 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, - 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, - 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, - 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, - 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, - 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, - 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, - 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, - 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, - 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, - 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, - 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, - 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, - 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, - 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, - 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, - 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, - 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, - 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, - 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, - 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, - 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, - 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, - 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, - 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, - 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, - 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, - 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, - 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, - 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, - 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, - 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, - 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, - 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, - 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, - 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, - 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, - 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, - 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, - 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, - 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, - 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, - 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, - 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, - 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, - 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, - 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, - 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, - 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, - 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, - 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, - 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, - 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, - 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, - 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, - 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, - 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, - 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, - 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, - 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, - 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, - 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, - 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, - 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, - 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, - 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, - 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, - 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, - 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, - 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, - 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, - 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, - 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, - 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, - 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, - 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, - 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, - 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, - 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, - 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, - 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, - 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, - 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, - 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, - 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, - 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, - 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, - 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, - 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, - 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, - 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, - 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, - 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, - 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, - 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, - 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, - 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, - 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, - 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, - 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, - 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, - 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, - 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, - 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, - 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, - 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, - 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, - 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, - 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, - 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, - 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, - 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, - 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, - 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, - 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, - 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, - 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, - 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, - 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, - 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, - 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, - 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, - 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, - 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, - 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, - 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, - 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, - 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, - 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, - 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, - 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, - 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, - 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, - 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, - 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, - 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, - 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, - 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, - 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, - 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, - 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, - 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, - 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, - 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, - 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, - 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, - 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, - 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, - 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, - 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, - 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, - 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, - 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, - 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, - 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, - 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, - 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, - 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, - 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, - 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, - 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, - 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, - 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, - 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, - 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, - 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, - 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, - 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, - 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, - 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, - 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, - 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, - 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, - 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, - 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, - 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, - 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, - 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, - 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, - 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, - 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, - 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, - 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, - 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, - 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, - 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, - 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, - 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, - 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, - 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, - 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, - 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, - 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, - 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, - 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, - 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, - 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, - 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, - 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, - 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, - 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, - 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, - 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, - 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, - 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, - 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, - 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, - 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, - 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, - 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, - 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, - 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, - 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, - 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, - 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, - 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, - 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, - 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, - 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, - 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, - 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, - 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, - 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, - 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, - 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, - 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, - 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, - 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, - 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, - 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, - 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, - 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, - 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, - 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, - 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, - 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, - 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, - 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, - 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, - 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, - 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, - 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, - 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, - 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, - 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, - 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, - 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, - 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, - 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, - 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, - 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, - 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, - 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, - 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, - 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, - 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, - 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, - 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, - 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, - 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, - 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, - 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, - 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, - 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, - 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, - 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, - 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, - 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, - 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, - 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, - 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, - 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, - 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, - 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, - 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, - 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, - 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, - 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, - 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, - 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, - 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, - 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, - 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, - 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, - 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, - 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, - 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, - 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, - 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, - 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, - 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, - 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, - 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, - 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, - 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, - 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, - 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, - 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, - 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, - 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, - 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, - 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, - 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, - 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, - 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, - 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, - 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, - 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, - 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, - 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, - 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, - 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, - 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, - 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, - 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, - 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, - 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, - 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, - 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, - 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, - 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, - 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, - 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, - 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, - 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, - 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, - 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, - 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, - 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, - 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, - 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, - 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, - 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, - 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, - 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, - 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, - 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, - 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, - 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, - 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, - 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, - 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, - 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, - 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, - 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, - 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, - 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, - 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, - 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, - 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, - 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, - 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, - 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, - 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, - 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, - 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, - 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, - 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, - 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, - 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, - 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, - 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, - 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, - 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, - 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, - 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, - 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, - 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, - 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, - 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, - 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, - 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, - 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, - 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, - 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, - 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, - 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, - 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, - 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, - 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, - 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, - 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, - 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, - 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, - 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, - 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, - 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, - 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, - 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, - 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, - 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, - 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, - 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, - 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, - 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, - 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, - 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, - 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, - 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, - 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, - 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, - 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, - 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, - 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, - 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, - 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, - 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, - 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, - 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, - 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, - 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, - 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, - 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, - 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, - 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, - 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, - 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, - 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, - 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, - 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, - 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, - 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, - 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, - 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, - 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, - 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, - 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, - 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, - 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581, - 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, - 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761, - 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867, - 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983, - 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103, - 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239, - 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377, - 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499, - 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593, - 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, - 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841, - 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943, - 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049, - 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153, - 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231, - 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369, - 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453, - 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547, - 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, - 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763, - 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867, - 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961, - 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087, - 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213, - 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371, - 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489, - 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597, - 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, - 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819, - 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917, - 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061, - 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191, - 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263, - 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403, - 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493, - 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691, - 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, - 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929, - 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039, - 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139, - 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223, - 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321, - 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451, - 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549, - 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657, - 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, - 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901, - 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981, - 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089, - 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209, - 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327, - 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389, - 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473, - 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593, - 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, - 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843, - 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933, - 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031, - 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109, - 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229, - 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341, - 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481, - 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617, - 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, - 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823, - 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923, - 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013, - 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127, - 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303, - 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417, - 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529, - 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613, - 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, - 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859, - 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973, - 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099, - 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197, - 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297, - 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411, - 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521, - 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611, - 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, - 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843, - 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929, - 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079, - 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209, - 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307, - 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401, - 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533, - 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619, - 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, - 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821, - 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979, - 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081, - 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207, - 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303, - 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441, - 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541, - 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667, - 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, - 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907, - 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023, - 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153, - 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261, - 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351, - 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477, - 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551, - 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641, - 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, - 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839, - 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977, - 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101, - 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193, - 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311, - 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479, - 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571, - 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697, - 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, - 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901, - 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063, - 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181, - 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283, - 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393, - 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531, - 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621, - 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699, - 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, - 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939, - 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051, - 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173, - 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263, - 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369, - 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513, - 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629, - 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713, - 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, - 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923, - 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023, - 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101, - 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223, - 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349, - 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463, - 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569, - 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689, - 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, - 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929, - 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009, - 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139, - 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219, - 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339, - 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469, - 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559, - 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651, - 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, - 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891, - 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047, - 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177, - 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267, - 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399, - 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471, - 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609, - 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719, - 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, - 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987, - 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127, - 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221, - 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319, - 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437, - 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521, - 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659, - 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761, - 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, - 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027, - 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121, - 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237, - 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363, - 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469, - 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601, - 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691, - 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829, - 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, - 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111, - 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197, - 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291, - 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371, - 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477, - 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587, - 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743, - 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861, - 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, - 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119, - 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223, - 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323, - 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473, - 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553, - 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641, - 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721, - 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853, - 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, - 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079, - 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259, - 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411, - 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547, - 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667, - 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801, - 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873, - 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003, - 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, - 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209, - 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317, - 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431, - 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527, - 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627, - 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759, - 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849, - 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963, - 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, - 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149, - 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239, - 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373, - 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481, - 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617, - 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709, - 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847, - 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977, - 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, - 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193, - 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303, - 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411, - 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529, - 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673, - 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807, - 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939, - 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033, - 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, - 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243, - 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363, - 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431, - 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567, - 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669, - 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753, - 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849, - 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951, - 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, - 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179, - 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281, - 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383, - 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497, - 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607, - 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787, - 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911, - 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997, - 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, - 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253, - 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349, - 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447, - 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559, - 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687, - 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793, - 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903, - 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021, - 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, - 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231, - 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317, - 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441, - 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539, - 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633, - 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773, - 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873, - 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971, - 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, - 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223, - 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331, - 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461, - 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581, - 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731, - 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799, - 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931, - 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021, - 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, - 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303, - 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429, - 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549, - 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649, - 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813, - 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883, - 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011, - 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179, - 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, - 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411, - 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507, - 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639, - 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737, - 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873, - 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947, - 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053, - 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139, - 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, - 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397, - 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529, - 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643, - 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733, - 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839, - 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, - 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109, -100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237, -100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361, -100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469, -100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549, -100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699, -100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823, -100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957, -100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089, -101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173, -101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281, -101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383, -101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501, -101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599, -101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719, -101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833, -101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929, -101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023, -102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107, -102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217, -102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317, -102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451, -102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551, -102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667, -102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811, -102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931, -102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079, -103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217, -103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387, -103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483, -103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591, -103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703, -103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867, -103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981, -103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059, -104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173, -104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297, -104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399, -104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543, -104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659, -104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, + 2, + 3, + 5, + 7, + 11, + 13, + 17, + 19, + 23, + 29, + 31, + 37, + 41, + 43, + 47, + 53, + 59, + 61, + 67, + 71, + 73, + 79, + 83, + 89, + 97, + 101, + 103, + 107, + 109, + 113, + 127, + 131, + 137, + 139, + 149, + 151, + 157, + 163, + 167, + 173, + 179, + 181, + 191, + 193, + 197, + 199, + 211, + 223, + 227, + 229, + 233, + 239, + 241, + 251, + 257, + 263, + 269, + 271, + 277, + 281, + 283, + 293, + 307, + 311, + 313, + 317, + 331, + 337, + 347, + 349, + 353, + 359, + 367, + 373, + 379, + 383, + 389, + 397, + 401, + 409, + 419, + 421, + 431, + 433, + 439, + 443, + 449, + 457, + 461, + 463, + 467, + 479, + 487, + 491, + 499, + 503, + 509, + 521, + 523, + 541, + 547, + 557, + 563, + 569, + 571, + 577, + 587, + 593, + 599, + 601, + 607, + 613, + 617, + 619, + 631, + 641, + 643, + 647, + 653, + 659, + 661, + 673, + 677, + 683, + 691, + 701, + 709, + 719, + 727, + 733, + 739, + 743, + 751, + 757, + 761, + 769, + 773, + 787, + 797, + 809, + 811, + 821, + 823, + 827, + 829, + 839, + 853, + 857, + 859, + 863, + 877, + 881, + 883, + 887, + 907, + 911, + 919, + 929, + 937, + 941, + 947, + 953, + 967, + 971, + 977, + 983, + 991, + 997, + 1009, + 1013, + 1019, + 1021, + 1031, + 1033, + 1039, + 1049, + 1051, + 1061, + 1063, + 1069, + 1087, + 1091, + 1093, + 1097, + 1103, + 1109, + 1117, + 1123, + 1129, + 1151, + 1153, + 1163, + 1171, + 1181, + 1187, + 1193, + 1201, + 1213, + 1217, + 1223, + 1229, + 1231, + 1237, + 1249, + 1259, + 1277, + 1279, + 1283, + 1289, + 1291, + 1297, + 1301, + 1303, + 1307, + 1319, + 1321, + 1327, + 1361, + 1367, + 1373, + 1381, + 1399, + 1409, + 1423, + 1427, + 1429, + 1433, + 1439, + 1447, + 1451, + 1453, + 1459, + 1471, + 1481, + 1483, + 1487, + 1489, + 1493, + 1499, + 1511, + 1523, + 1531, + 1543, + 1549, + 1553, + 1559, + 1567, + 1571, + 1579, + 1583, + 1597, + 1601, + 1607, + 1609, + 1613, + 1619, + 1621, + 1627, + 1637, + 1657, + 1663, + 1667, + 1669, + 1693, + 1697, + 1699, + 1709, + 1721, + 1723, + 1733, + 1741, + 1747, + 1753, + 1759, + 1777, + 1783, + 1787, + 1789, + 1801, + 1811, + 1823, + 1831, + 1847, + 1861, + 1867, + 1871, + 1873, + 1877, + 1879, + 1889, + 1901, + 1907, + 1913, + 1931, + 1933, + 1949, + 1951, + 1973, + 1979, + 1987, + 1993, + 1997, + 1999, + 2003, + 2011, + 2017, + 2027, + 2029, + 2039, + 2053, + 2063, + 2069, + 2081, + 2083, + 2087, + 2089, + 2099, + 2111, + 2113, + 2129, + 2131, + 2137, + 2141, + 2143, + 2153, + 2161, + 2179, + 2203, + 2207, + 2213, + 2221, + 2237, + 2239, + 2243, + 2251, + 2267, + 2269, + 2273, + 2281, + 2287, + 2293, + 2297, + 2309, + 2311, + 2333, + 2339, + 2341, + 2347, + 2351, + 2357, + 2371, + 2377, + 2381, + 2383, + 2389, + 2393, + 2399, + 2411, + 2417, + 2423, + 2437, + 2441, + 2447, + 2459, + 2467, + 2473, + 2477, + 2503, + 2521, + 2531, + 2539, + 2543, + 2549, + 2551, + 2557, + 2579, + 2591, + 2593, + 2609, + 2617, + 2621, + 2633, + 2647, + 2657, + 2659, + 2663, + 2671, + 2677, + 2683, + 2687, + 2689, + 2693, + 2699, + 2707, + 2711, + 2713, + 2719, + 2729, + 2731, + 2741, + 2749, + 2753, + 2767, + 2777, + 2789, + 2791, + 2797, + 2801, + 2803, + 2819, + 2833, + 2837, + 2843, + 2851, + 2857, + 2861, + 2879, + 2887, + 2897, + 2903, + 2909, + 2917, + 2927, + 2939, + 2953, + 2957, + 2963, + 2969, + 2971, + 2999, + 3001, + 3011, + 3019, + 3023, + 3037, + 3041, + 3049, + 3061, + 3067, + 3079, + 3083, + 3089, + 3109, + 3119, + 3121, + 3137, + 3163, + 3167, + 3169, + 3181, + 3187, + 3191, + 3203, + 3209, + 3217, + 3221, + 3229, + 3251, + 3253, + 3257, + 3259, + 3271, + 3299, + 3301, + 3307, + 3313, + 3319, + 3323, + 3329, + 3331, + 3343, + 3347, + 3359, + 3361, + 3371, + 3373, + 3389, + 3391, + 3407, + 3413, + 3433, + 3449, + 3457, + 3461, + 3463, + 3467, + 3469, + 3491, + 3499, + 3511, + 3517, + 3527, + 3529, + 3533, + 3539, + 3541, + 3547, + 3557, + 3559, + 3571, + 3581, + 3583, + 3593, + 3607, + 3613, + 3617, + 3623, + 3631, + 3637, + 3643, + 3659, + 3671, + 3673, + 3677, + 3691, + 3697, + 3701, + 3709, + 3719, + 3727, + 3733, + 3739, + 3761, + 3767, + 3769, + 3779, + 3793, + 3797, + 3803, + 3821, + 3823, + 3833, + 3847, + 3851, + 3853, + 3863, + 3877, + 3881, + 3889, + 3907, + 3911, + 3917, + 3919, + 3923, + 3929, + 3931, + 3943, + 3947, + 3967, + 3989, + 4001, + 4003, + 4007, + 4013, + 4019, + 4021, + 4027, + 4049, + 4051, + 4057, + 4073, + 4079, + 4091, + 4093, + 4099, + 4111, + 4127, + 4129, + 4133, + 4139, + 4153, + 4157, + 4159, + 4177, + 4201, + 4211, + 4217, + 4219, + 4229, + 4231, + 4241, + 4243, + 4253, + 4259, + 4261, + 4271, + 4273, + 4283, + 4289, + 4297, + 4327, + 4337, + 4339, + 4349, + 4357, + 4363, + 4373, + 4391, + 4397, + 4409, + 4421, + 4423, + 4441, + 4447, + 4451, + 4457, + 4463, + 4481, + 4483, + 4493, + 4507, + 4513, + 4517, + 4519, + 4523, + 4547, + 4549, + 4561, + 4567, + 4583, + 4591, + 4597, + 4603, + 4621, + 4637, + 4639, + 4643, + 4649, + 4651, + 4657, + 4663, + 4673, + 4679, + 4691, + 4703, + 4721, + 4723, + 4729, + 4733, + 4751, + 4759, + 4783, + 4787, + 4789, + 4793, + 4799, + 4801, + 4813, + 4817, + 4831, + 4861, + 4871, + 4877, + 4889, + 4903, + 4909, + 4919, + 4931, + 4933, + 4937, + 4943, + 4951, + 4957, + 4967, + 4969, + 4973, + 4987, + 4993, + 4999, + 5003, + 5009, + 5011, + 5021, + 5023, + 5039, + 5051, + 5059, + 5077, + 5081, + 5087, + 5099, + 5101, + 5107, + 5113, + 5119, + 5147, + 5153, + 5167, + 5171, + 5179, + 5189, + 5197, + 5209, + 5227, + 5231, + 5233, + 5237, + 5261, + 5273, + 5279, + 5281, + 5297, + 5303, + 5309, + 5323, + 5333, + 5347, + 5351, + 5381, + 5387, + 5393, + 5399, + 5407, + 5413, + 5417, + 5419, + 5431, + 5437, + 5441, + 5443, + 5449, + 5471, + 5477, + 5479, + 5483, + 5501, + 5503, + 5507, + 5519, + 5521, + 5527, + 5531, + 5557, + 5563, + 5569, + 5573, + 5581, + 5591, + 5623, + 5639, + 5641, + 5647, + 5651, + 5653, + 5657, + 5659, + 5669, + 5683, + 5689, + 5693, + 5701, + 5711, + 5717, + 5737, + 5741, + 5743, + 5749, + 5779, + 5783, + 5791, + 5801, + 5807, + 5813, + 5821, + 5827, + 5839, + 5843, + 5849, + 5851, + 5857, + 5861, + 5867, + 5869, + 5879, + 5881, + 5897, + 5903, + 5923, + 5927, + 5939, + 5953, + 5981, + 5987, + 6007, + 6011, + 6029, + 6037, + 6043, + 6047, + 6053, + 6067, + 6073, + 6079, + 6089, + 6091, + 6101, + 6113, + 6121, + 6131, + 6133, + 6143, + 6151, + 6163, + 6173, + 6197, + 6199, + 6203, + 6211, + 6217, + 6221, + 6229, + 6247, + 6257, + 6263, + 6269, + 6271, + 6277, + 6287, + 6299, + 6301, + 6311, + 6317, + 6323, + 6329, + 6337, + 6343, + 6353, + 6359, + 6361, + 6367, + 6373, + 6379, + 6389, + 6397, + 6421, + 6427, + 6449, + 6451, + 6469, + 6473, + 6481, + 6491, + 6521, + 6529, + 6547, + 6551, + 6553, + 6563, + 6569, + 6571, + 6577, + 6581, + 6599, + 6607, + 6619, + 6637, + 6653, + 6659, + 6661, + 6673, + 6679, + 6689, + 6691, + 6701, + 6703, + 6709, + 6719, + 6733, + 6737, + 6761, + 6763, + 6779, + 6781, + 6791, + 6793, + 6803, + 6823, + 6827, + 6829, + 6833, + 6841, + 6857, + 6863, + 6869, + 6871, + 6883, + 6899, + 6907, + 6911, + 6917, + 6947, + 6949, + 6959, + 6961, + 6967, + 6971, + 6977, + 6983, + 6991, + 6997, + 7001, + 7013, + 7019, + 7027, + 7039, + 7043, + 7057, + 7069, + 7079, + 7103, + 7109, + 7121, + 7127, + 7129, + 7151, + 7159, + 7177, + 7187, + 7193, + 7207, + 7211, + 7213, + 7219, + 7229, + 7237, + 7243, + 7247, + 7253, + 7283, + 7297, + 7307, + 7309, + 7321, + 7331, + 7333, + 7349, + 7351, + 7369, + 7393, + 7411, + 7417, + 7433, + 7451, + 7457, + 7459, + 7477, + 7481, + 7487, + 7489, + 7499, + 7507, + 7517, + 7523, + 7529, + 7537, + 7541, + 7547, + 7549, + 7559, + 7561, + 7573, + 7577, + 7583, + 7589, + 7591, + 7603, + 7607, + 7621, + 7639, + 7643, + 7649, + 7669, + 7673, + 7681, + 7687, + 7691, + 7699, + 7703, + 7717, + 7723, + 7727, + 7741, + 7753, + 7757, + 7759, + 7789, + 7793, + 7817, + 7823, + 7829, + 7841, + 7853, + 7867, + 7873, + 7877, + 7879, + 7883, + 7901, + 7907, + 7919, + 7927, + 7933, + 7937, + 7949, + 7951, + 7963, + 7993, + 8009, + 8011, + 8017, + 8039, + 8053, + 8059, + 8069, + 8081, + 8087, + 8089, + 8093, + 8101, + 8111, + 8117, + 8123, + 8147, + 8161, + 8167, + 8171, + 8179, + 8191, + 8209, + 8219, + 8221, + 8231, + 8233, + 8237, + 8243, + 8263, + 8269, + 8273, + 8287, + 8291, + 8293, + 8297, + 8311, + 8317, + 8329, + 8353, + 8363, + 8369, + 8377, + 8387, + 8389, + 8419, + 8423, + 8429, + 8431, + 8443, + 8447, + 8461, + 8467, + 8501, + 8513, + 8521, + 8527, + 8537, + 8539, + 8543, + 8563, + 8573, + 8581, + 8597, + 8599, + 8609, + 8623, + 8627, + 8629, + 8641, + 8647, + 8663, + 8669, + 8677, + 8681, + 8689, + 8693, + 8699, + 8707, + 8713, + 8719, + 8731, + 8737, + 8741, + 8747, + 8753, + 8761, + 8779, + 8783, + 8803, + 8807, + 8819, + 8821, + 8831, + 8837, + 8839, + 8849, + 8861, + 8863, + 8867, + 8887, + 8893, + 8923, + 8929, + 8933, + 8941, + 8951, + 8963, + 8969, + 8971, + 8999, + 9001, + 9007, + 9011, + 9013, + 9029, + 9041, + 9043, + 9049, + 9059, + 9067, + 9091, + 9103, + 9109, + 9127, + 9133, + 9137, + 9151, + 9157, + 9161, + 9173, + 9181, + 9187, + 9199, + 9203, + 9209, + 9221, + 9227, + 9239, + 9241, + 9257, + 9277, + 9281, + 9283, + 9293, + 9311, + 9319, + 9323, + 9337, + 9341, + 9343, + 9349, + 9371, + 9377, + 9391, + 9397, + 9403, + 9413, + 9419, + 9421, + 9431, + 9433, + 9437, + 9439, + 9461, + 9463, + 9467, + 9473, + 9479, + 9491, + 9497, + 9511, + 9521, + 9533, + 9539, + 9547, + 9551, + 9587, + 9601, + 9613, + 9619, + 9623, + 9629, + 9631, + 9643, + 9649, + 9661, + 9677, + 9679, + 9689, + 9697, + 9719, + 9721, + 9733, + 9739, + 9743, + 9749, + 9767, + 9769, + 9781, + 9787, + 9791, + 9803, + 9811, + 9817, + 9829, + 9833, + 9839, + 9851, + 9857, + 9859, + 9871, + 9883, + 9887, + 9901, + 9907, + 9923, + 9929, + 9931, + 9941, + 9949, + 9967, + 9973, + 10007, + 10009, + 10037, + 10039, + 10061, + 10067, + 10069, + 10079, + 10091, + 10093, + 10099, + 10103, + 10111, + 10133, + 10139, + 10141, + 10151, + 10159, + 10163, + 10169, + 10177, + 10181, + 10193, + 10211, + 10223, + 10243, + 10247, + 10253, + 10259, + 10267, + 10271, + 10273, + 10289, + 10301, + 10303, + 10313, + 10321, + 10331, + 10333, + 10337, + 10343, + 10357, + 10369, + 10391, + 10399, + 10427, + 10429, + 10433, + 10453, + 10457, + 10459, + 10463, + 10477, + 10487, + 10499, + 10501, + 10513, + 10529, + 10531, + 10559, + 10567, + 10589, + 10597, + 10601, + 10607, + 10613, + 10627, + 10631, + 10639, + 10651, + 10657, + 10663, + 10667, + 10687, + 10691, + 10709, + 10711, + 10723, + 10729, + 10733, + 10739, + 10753, + 10771, + 10781, + 10789, + 10799, + 10831, + 10837, + 10847, + 10853, + 10859, + 10861, + 10867, + 10883, + 10889, + 10891, + 10903, + 10909, + 10937, + 10939, + 10949, + 10957, + 10973, + 10979, + 10987, + 10993, + 11003, + 11027, + 11047, + 11057, + 11059, + 11069, + 11071, + 11083, + 11087, + 11093, + 11113, + 11117, + 11119, + 11131, + 11149, + 11159, + 11161, + 11171, + 11173, + 11177, + 11197, + 11213, + 11239, + 11243, + 11251, + 11257, + 11261, + 11273, + 11279, + 11287, + 11299, + 11311, + 11317, + 11321, + 11329, + 11351, + 11353, + 11369, + 11383, + 11393, + 11399, + 11411, + 11423, + 11437, + 11443, + 11447, + 11467, + 11471, + 11483, + 11489, + 11491, + 11497, + 11503, + 11519, + 11527, + 11549, + 11551, + 11579, + 11587, + 11593, + 11597, + 11617, + 11621, + 11633, + 11657, + 11677, + 11681, + 11689, + 11699, + 11701, + 11717, + 11719, + 11731, + 11743, + 11777, + 11779, + 11783, + 11789, + 11801, + 11807, + 11813, + 11821, + 11827, + 11831, + 11833, + 11839, + 11863, + 11867, + 11887, + 11897, + 11903, + 11909, + 11923, + 11927, + 11933, + 11939, + 11941, + 11953, + 11959, + 11969, + 11971, + 11981, + 11987, + 12007, + 12011, + 12037, + 12041, + 12043, + 12049, + 12071, + 12073, + 12097, + 12101, + 12107, + 12109, + 12113, + 12119, + 12143, + 12149, + 12157, + 12161, + 12163, + 12197, + 12203, + 12211, + 12227, + 12239, + 12241, + 12251, + 12253, + 12263, + 12269, + 12277, + 12281, + 12289, + 12301, + 12323, + 12329, + 12343, + 12347, + 12373, + 12377, + 12379, + 12391, + 12401, + 12409, + 12413, + 12421, + 12433, + 12437, + 12451, + 12457, + 12473, + 12479, + 12487, + 12491, + 12497, + 12503, + 12511, + 12517, + 12527, + 12539, + 12541, + 12547, + 12553, + 12569, + 12577, + 12583, + 12589, + 12601, + 12611, + 12613, + 12619, + 12637, + 12641, + 12647, + 12653, + 12659, + 12671, + 12689, + 12697, + 12703, + 12713, + 12721, + 12739, + 12743, + 12757, + 12763, + 12781, + 12791, + 12799, + 12809, + 12821, + 12823, + 12829, + 12841, + 12853, + 12889, + 12893, + 12899, + 12907, + 12911, + 12917, + 12919, + 12923, + 12941, + 12953, + 12959, + 12967, + 12973, + 12979, + 12983, + 13001, + 13003, + 13007, + 13009, + 13033, + 13037, + 13043, + 13049, + 13063, + 13093, + 13099, + 13103, + 13109, + 13121, + 13127, + 13147, + 13151, + 13159, + 13163, + 13171, + 13177, + 13183, + 13187, + 13217, + 13219, + 13229, + 13241, + 13249, + 13259, + 13267, + 13291, + 13297, + 13309, + 13313, + 13327, + 13331, + 13337, + 13339, + 13367, + 13381, + 13397, + 13399, + 13411, + 13417, + 13421, + 13441, + 13451, + 13457, + 13463, + 13469, + 13477, + 13487, + 13499, + 13513, + 13523, + 13537, + 13553, + 13567, + 13577, + 13591, + 13597, + 13613, + 13619, + 13627, + 13633, + 13649, + 13669, + 13679, + 13681, + 13687, + 13691, + 13693, + 13697, + 13709, + 13711, + 13721, + 13723, + 13729, + 13751, + 13757, + 13759, + 13763, + 13781, + 13789, + 13799, + 13807, + 13829, + 13831, + 13841, + 13859, + 13873, + 13877, + 13879, + 13883, + 13901, + 13903, + 13907, + 13913, + 13921, + 13931, + 13933, + 13963, + 13967, + 13997, + 13999, + 14009, + 14011, + 14029, + 14033, + 14051, + 14057, + 14071, + 14081, + 14083, + 14087, + 14107, + 14143, + 14149, + 14153, + 14159, + 14173, + 14177, + 14197, + 14207, + 14221, + 14243, + 14249, + 14251, + 14281, + 14293, + 14303, + 14321, + 14323, + 14327, + 14341, + 14347, + 14369, + 14387, + 14389, + 14401, + 14407, + 14411, + 14419, + 14423, + 14431, + 14437, + 14447, + 14449, + 14461, + 14479, + 14489, + 14503, + 14519, + 14533, + 14537, + 14543, + 14549, + 14551, + 14557, + 14561, + 14563, + 14591, + 14593, + 14621, + 14627, + 14629, + 14633, + 14639, + 14653, + 14657, + 14669, + 14683, + 14699, + 14713, + 14717, + 14723, + 14731, + 14737, + 14741, + 14747, + 14753, + 14759, + 14767, + 14771, + 14779, + 14783, + 14797, + 14813, + 14821, + 14827, + 14831, + 14843, + 14851, + 14867, + 14869, + 14879, + 14887, + 14891, + 14897, + 14923, + 14929, + 14939, + 14947, + 14951, + 14957, + 14969, + 14983, + 15013, + 15017, + 15031, + 15053, + 15061, + 15073, + 15077, + 15083, + 15091, + 15101, + 15107, + 15121, + 15131, + 15137, + 15139, + 15149, + 15161, + 15173, + 15187, + 15193, + 15199, + 15217, + 15227, + 15233, + 15241, + 15259, + 15263, + 15269, + 15271, + 15277, + 15287, + 15289, + 15299, + 15307, + 15313, + 15319, + 15329, + 15331, + 15349, + 15359, + 15361, + 15373, + 15377, + 15383, + 15391, + 15401, + 15413, + 15427, + 15439, + 15443, + 15451, + 15461, + 15467, + 15473, + 15493, + 15497, + 15511, + 15527, + 15541, + 15551, + 15559, + 15569, + 15581, + 15583, + 15601, + 15607, + 15619, + 15629, + 15641, + 15643, + 15647, + 15649, + 15661, + 15667, + 15671, + 15679, + 15683, + 15727, + 15731, + 15733, + 15737, + 15739, + 15749, + 15761, + 15767, + 15773, + 15787, + 15791, + 15797, + 15803, + 15809, + 15817, + 15823, + 15859, + 15877, + 15881, + 15887, + 15889, + 15901, + 15907, + 15913, + 15919, + 15923, + 15937, + 15959, + 15971, + 15973, + 15991, + 16001, + 16007, + 16033, + 16057, + 16061, + 16063, + 16067, + 16069, + 16073, + 16087, + 16091, + 16097, + 16103, + 16111, + 16127, + 16139, + 16141, + 16183, + 16187, + 16189, + 16193, + 16217, + 16223, + 16229, + 16231, + 16249, + 16253, + 16267, + 16273, + 16301, + 16319, + 16333, + 16339, + 16349, + 16361, + 16363, + 16369, + 16381, + 16411, + 16417, + 16421, + 16427, + 16433, + 16447, + 16451, + 16453, + 16477, + 16481, + 16487, + 16493, + 16519, + 16529, + 16547, + 16553, + 16561, + 16567, + 16573, + 16603, + 16607, + 16619, + 16631, + 16633, + 16649, + 16651, + 16657, + 16661, + 16673, + 16691, + 16693, + 16699, + 16703, + 16729, + 16741, + 16747, + 16759, + 16763, + 16787, + 16811, + 16823, + 16829, + 16831, + 16843, + 16871, + 16879, + 16883, + 16889, + 16901, + 16903, + 16921, + 16927, + 16931, + 16937, + 16943, + 16963, + 16979, + 16981, + 16987, + 16993, + 17011, + 17021, + 17027, + 17029, + 17033, + 17041, + 17047, + 17053, + 17077, + 17093, + 17099, + 17107, + 17117, + 17123, + 17137, + 17159, + 17167, + 17183, + 17189, + 17191, + 17203, + 17207, + 17209, + 17231, + 17239, + 17257, + 17291, + 17293, + 17299, + 17317, + 17321, + 17327, + 17333, + 17341, + 17351, + 17359, + 17377, + 17383, + 17387, + 17389, + 17393, + 17401, + 17417, + 17419, + 17431, + 17443, + 17449, + 17467, + 17471, + 17477, + 17483, + 17489, + 17491, + 17497, + 17509, + 17519, + 17539, + 17551, + 17569, + 17573, + 17579, + 17581, + 17597, + 17599, + 17609, + 17623, + 17627, + 17657, + 17659, + 17669, + 17681, + 17683, + 17707, + 17713, + 17729, + 17737, + 17747, + 17749, + 17761, + 17783, + 17789, + 17791, + 17807, + 17827, + 17837, + 17839, + 17851, + 17863, + 17881, + 17891, + 17903, + 17909, + 17911, + 17921, + 17923, + 17929, + 17939, + 17957, + 17959, + 17971, + 17977, + 17981, + 17987, + 17989, + 18013, + 18041, + 18043, + 18047, + 18049, + 18059, + 18061, + 18077, + 18089, + 18097, + 18119, + 18121, + 18127, + 18131, + 18133, + 18143, + 18149, + 18169, + 18181, + 18191, + 18199, + 18211, + 18217, + 18223, + 18229, + 18233, + 18251, + 18253, + 18257, + 18269, + 18287, + 18289, + 18301, + 18307, + 18311, + 18313, + 18329, + 18341, + 18353, + 18367, + 18371, + 18379, + 18397, + 18401, + 18413, + 18427, + 18433, + 18439, + 18443, + 18451, + 18457, + 18461, + 18481, + 18493, + 18503, + 18517, + 18521, + 18523, + 18539, + 18541, + 18553, + 18583, + 18587, + 18593, + 18617, + 18637, + 18661, + 18671, + 18679, + 18691, + 18701, + 18713, + 18719, + 18731, + 18743, + 18749, + 18757, + 18773, + 18787, + 18793, + 18797, + 18803, + 18839, + 18859, + 18869, + 18899, + 18911, + 18913, + 18917, + 18919, + 18947, + 18959, + 18973, + 18979, + 19001, + 19009, + 19013, + 19031, + 19037, + 19051, + 19069, + 19073, + 19079, + 19081, + 19087, + 19121, + 19139, + 19141, + 19157, + 19163, + 19181, + 19183, + 19207, + 19211, + 19213, + 19219, + 19231, + 19237, + 19249, + 19259, + 19267, + 19273, + 19289, + 19301, + 19309, + 19319, + 19333, + 19373, + 19379, + 19381, + 19387, + 19391, + 19403, + 19417, + 19421, + 19423, + 19427, + 19429, + 19433, + 19441, + 19447, + 19457, + 19463, + 19469, + 19471, + 19477, + 19483, + 19489, + 19501, + 19507, + 19531, + 19541, + 19543, + 19553, + 19559, + 19571, + 19577, + 19583, + 19597, + 19603, + 19609, + 19661, + 19681, + 19687, + 19697, + 19699, + 19709, + 19717, + 19727, + 19739, + 19751, + 19753, + 19759, + 19763, + 19777, + 19793, + 19801, + 19813, + 19819, + 19841, + 19843, + 19853, + 19861, + 19867, + 19889, + 19891, + 19913, + 19919, + 19927, + 19937, + 19949, + 19961, + 19963, + 19973, + 19979, + 19991, + 19993, + 19997, + 20011, + 20021, + 20023, + 20029, + 20047, + 20051, + 20063, + 20071, + 20089, + 20101, + 20107, + 20113, + 20117, + 20123, + 20129, + 20143, + 20147, + 20149, + 20161, + 20173, + 20177, + 20183, + 20201, + 20219, + 20231, + 20233, + 20249, + 20261, + 20269, + 20287, + 20297, + 20323, + 20327, + 20333, + 20341, + 20347, + 20353, + 20357, + 20359, + 20369, + 20389, + 20393, + 20399, + 20407, + 20411, + 20431, + 20441, + 20443, + 20477, + 20479, + 20483, + 20507, + 20509, + 20521, + 20533, + 20543, + 20549, + 20551, + 20563, + 20593, + 20599, + 20611, + 20627, + 20639, + 20641, + 20663, + 20681, + 20693, + 20707, + 20717, + 20719, + 20731, + 20743, + 20747, + 20749, + 20753, + 20759, + 20771, + 20773, + 20789, + 20807, + 20809, + 20849, + 20857, + 20873, + 20879, + 20887, + 20897, + 20899, + 20903, + 20921, + 20929, + 20939, + 20947, + 20959, + 20963, + 20981, + 20983, + 21001, + 21011, + 21013, + 21017, + 21019, + 21023, + 21031, + 21059, + 21061, + 21067, + 21089, + 21101, + 21107, + 21121, + 21139, + 21143, + 21149, + 21157, + 21163, + 21169, + 21179, + 21187, + 21191, + 21193, + 21211, + 21221, + 21227, + 21247, + 21269, + 21277, + 21283, + 21313, + 21317, + 21319, + 21323, + 21341, + 21347, + 21377, + 21379, + 21383, + 21391, + 21397, + 21401, + 21407, + 21419, + 21433, + 21467, + 21481, + 21487, + 21491, + 21493, + 21499, + 21503, + 21517, + 21521, + 21523, + 21529, + 21557, + 21559, + 21563, + 21569, + 21577, + 21587, + 21589, + 21599, + 21601, + 21611, + 21613, + 21617, + 21647, + 21649, + 21661, + 21673, + 21683, + 21701, + 21713, + 21727, + 21737, + 21739, + 21751, + 21757, + 21767, + 21773, + 21787, + 21799, + 21803, + 21817, + 21821, + 21839, + 21841, + 21851, + 21859, + 21863, + 21871, + 21881, + 21893, + 21911, + 21929, + 21937, + 21943, + 21961, + 21977, + 21991, + 21997, + 22003, + 22013, + 22027, + 22031, + 22037, + 22039, + 22051, + 22063, + 22067, + 22073, + 22079, + 22091, + 22093, + 22109, + 22111, + 22123, + 22129, + 22133, + 22147, + 22153, + 22157, + 22159, + 22171, + 22189, + 22193, + 22229, + 22247, + 22259, + 22271, + 22273, + 22277, + 22279, + 22283, + 22291, + 22303, + 22307, + 22343, + 22349, + 22367, + 22369, + 22381, + 22391, + 22397, + 22409, + 22433, + 22441, + 22447, + 22453, + 22469, + 22481, + 22483, + 22501, + 22511, + 22531, + 22541, + 22543, + 22549, + 22567, + 22571, + 22573, + 22613, + 22619, + 22621, + 22637, + 22639, + 22643, + 22651, + 22669, + 22679, + 22691, + 22697, + 22699, + 22709, + 22717, + 22721, + 22727, + 22739, + 22741, + 22751, + 22769, + 22777, + 22783, + 22787, + 22807, + 22811, + 22817, + 22853, + 22859, + 22861, + 22871, + 22877, + 22901, + 22907, + 22921, + 22937, + 22943, + 22961, + 22963, + 22973, + 22993, + 23003, + 23011, + 23017, + 23021, + 23027, + 23029, + 23039, + 23041, + 23053, + 23057, + 23059, + 23063, + 23071, + 23081, + 23087, + 23099, + 23117, + 23131, + 23143, + 23159, + 23167, + 23173, + 23189, + 23197, + 23201, + 23203, + 23209, + 23227, + 23251, + 23269, + 23279, + 23291, + 23293, + 23297, + 23311, + 23321, + 23327, + 23333, + 23339, + 23357, + 23369, + 23371, + 23399, + 23417, + 23431, + 23447, + 23459, + 23473, + 23497, + 23509, + 23531, + 23537, + 23539, + 23549, + 23557, + 23561, + 23563, + 23567, + 23581, + 23593, + 23599, + 23603, + 23609, + 23623, + 23627, + 23629, + 23633, + 23663, + 23669, + 23671, + 23677, + 23687, + 23689, + 23719, + 23741, + 23743, + 23747, + 23753, + 23761, + 23767, + 23773, + 23789, + 23801, + 23813, + 23819, + 23827, + 23831, + 23833, + 23857, + 23869, + 23873, + 23879, + 23887, + 23893, + 23899, + 23909, + 23911, + 23917, + 23929, + 23957, + 23971, + 23977, + 23981, + 23993, + 24001, + 24007, + 24019, + 24023, + 24029, + 24043, + 24049, + 24061, + 24071, + 24077, + 24083, + 24091, + 24097, + 24103, + 24107, + 24109, + 24113, + 24121, + 24133, + 24137, + 24151, + 24169, + 24179, + 24181, + 24197, + 24203, + 24223, + 24229, + 24239, + 24247, + 24251, + 24281, + 24317, + 24329, + 24337, + 24359, + 24371, + 24373, + 24379, + 24391, + 24407, + 24413, + 24419, + 24421, + 24439, + 24443, + 24469, + 24473, + 24481, + 24499, + 24509, + 24517, + 24527, + 24533, + 24547, + 24551, + 24571, + 24593, + 24611, + 24623, + 24631, + 24659, + 24671, + 24677, + 24683, + 24691, + 24697, + 24709, + 24733, + 24749, + 24763, + 24767, + 24781, + 24793, + 24799, + 24809, + 24821, + 24841, + 24847, + 24851, + 24859, + 24877, + 24889, + 24907, + 24917, + 24919, + 24923, + 24943, + 24953, + 24967, + 24971, + 24977, + 24979, + 24989, + 25013, + 25031, + 25033, + 25037, + 25057, + 25073, + 25087, + 25097, + 25111, + 25117, + 25121, + 25127, + 25147, + 25153, + 25163, + 25169, + 25171, + 25183, + 25189, + 25219, + 25229, + 25237, + 25243, + 25247, + 25253, + 25261, + 25301, + 25303, + 25307, + 25309, + 25321, + 25339, + 25343, + 25349, + 25357, + 25367, + 25373, + 25391, + 25409, + 25411, + 25423, + 25439, + 25447, + 25453, + 25457, + 25463, + 25469, + 25471, + 25523, + 25537, + 25541, + 25561, + 25577, + 25579, + 25583, + 25589, + 25601, + 25603, + 25609, + 25621, + 25633, + 25639, + 25643, + 25657, + 25667, + 25673, + 25679, + 25693, + 25703, + 25717, + 25733, + 25741, + 25747, + 25759, + 25763, + 25771, + 25793, + 25799, + 25801, + 25819, + 25841, + 25847, + 25849, + 25867, + 25873, + 25889, + 25903, + 25913, + 25919, + 25931, + 25933, + 25939, + 25943, + 25951, + 25969, + 25981, + 25997, + 25999, + 26003, + 26017, + 26021, + 26029, + 26041, + 26053, + 26083, + 26099, + 26107, + 26111, + 26113, + 26119, + 26141, + 26153, + 26161, + 26171, + 26177, + 26183, + 26189, + 26203, + 26209, + 26227, + 26237, + 26249, + 26251, + 26261, + 26263, + 26267, + 26293, + 26297, + 26309, + 26317, + 26321, + 26339, + 26347, + 26357, + 26371, + 26387, + 26393, + 26399, + 26407, + 26417, + 26423, + 26431, + 26437, + 26449, + 26459, + 26479, + 26489, + 26497, + 26501, + 26513, + 26539, + 26557, + 26561, + 26573, + 26591, + 26597, + 26627, + 26633, + 26641, + 26647, + 26669, + 26681, + 26683, + 26687, + 26693, + 26699, + 26701, + 26711, + 26713, + 26717, + 26723, + 26729, + 26731, + 26737, + 26759, + 26777, + 26783, + 26801, + 26813, + 26821, + 26833, + 26839, + 26849, + 26861, + 26863, + 26879, + 26881, + 26891, + 26893, + 26903, + 26921, + 26927, + 26947, + 26951, + 26953, + 26959, + 26981, + 26987, + 26993, + 27011, + 27017, + 27031, + 27043, + 27059, + 27061, + 27067, + 27073, + 27077, + 27091, + 27103, + 27107, + 27109, + 27127, + 27143, + 27179, + 27191, + 27197, + 27211, + 27239, + 27241, + 27253, + 27259, + 27271, + 27277, + 27281, + 27283, + 27299, + 27329, + 27337, + 27361, + 27367, + 27397, + 27407, + 27409, + 27427, + 27431, + 27437, + 27449, + 27457, + 27479, + 27481, + 27487, + 27509, + 27527, + 27529, + 27539, + 27541, + 27551, + 27581, + 27583, + 27611, + 27617, + 27631, + 27647, + 27653, + 27673, + 27689, + 27691, + 27697, + 27701, + 27733, + 27737, + 27739, + 27743, + 27749, + 27751, + 27763, + 27767, + 27773, + 27779, + 27791, + 27793, + 27799, + 27803, + 27809, + 27817, + 27823, + 27827, + 27847, + 27851, + 27883, + 27893, + 27901, + 27917, + 27919, + 27941, + 27943, + 27947, + 27953, + 27961, + 27967, + 27983, + 27997, + 28001, + 28019, + 28027, + 28031, + 28051, + 28057, + 28069, + 28081, + 28087, + 28097, + 28099, + 28109, + 28111, + 28123, + 28151, + 28163, + 28181, + 28183, + 28201, + 28211, + 28219, + 28229, + 28277, + 28279, + 28283, + 28289, + 28297, + 28307, + 28309, + 28319, + 28349, + 28351, + 28387, + 28393, + 28403, + 28409, + 28411, + 28429, + 28433, + 28439, + 28447, + 28463, + 28477, + 28493, + 28499, + 28513, + 28517, + 28537, + 28541, + 28547, + 28549, + 28559, + 28571, + 28573, + 28579, + 28591, + 28597, + 28603, + 28607, + 28619, + 28621, + 28627, + 28631, + 28643, + 28649, + 28657, + 28661, + 28663, + 28669, + 28687, + 28697, + 28703, + 28711, + 28723, + 28729, + 28751, + 28753, + 28759, + 28771, + 28789, + 28793, + 28807, + 28813, + 28817, + 28837, + 28843, + 28859, + 28867, + 28871, + 28879, + 28901, + 28909, + 28921, + 28927, + 28933, + 28949, + 28961, + 28979, + 29009, + 29017, + 29021, + 29023, + 29027, + 29033, + 29059, + 29063, + 29077, + 29101, + 29123, + 29129, + 29131, + 29137, + 29147, + 29153, + 29167, + 29173, + 29179, + 29191, + 29201, + 29207, + 29209, + 29221, + 29231, + 29243, + 29251, + 29269, + 29287, + 29297, + 29303, + 29311, + 29327, + 29333, + 29339, + 29347, + 29363, + 29383, + 29387, + 29389, + 29399, + 29401, + 29411, + 29423, + 29429, + 29437, + 29443, + 29453, + 29473, + 29483, + 29501, + 29527, + 29531, + 29537, + 29567, + 29569, + 29573, + 29581, + 29587, + 29599, + 29611, + 29629, + 29633, + 29641, + 29663, + 29669, + 29671, + 29683, + 29717, + 29723, + 29741, + 29753, + 29759, + 29761, + 29789, + 29803, + 29819, + 29833, + 29837, + 29851, + 29863, + 29867, + 29873, + 29879, + 29881, + 29917, + 29921, + 29927, + 29947, + 29959, + 29983, + 29989, + 30011, + 30013, + 30029, + 30047, + 30059, + 30071, + 30089, + 30091, + 30097, + 30103, + 30109, + 30113, + 30119, + 30133, + 30137, + 30139, + 30161, + 30169, + 30181, + 30187, + 30197, + 30203, + 30211, + 30223, + 30241, + 30253, + 30259, + 30269, + 30271, + 30293, + 30307, + 30313, + 30319, + 30323, + 30341, + 30347, + 30367, + 30389, + 30391, + 30403, + 30427, + 30431, + 30449, + 30467, + 30469, + 30491, + 30493, + 30497, + 30509, + 30517, + 30529, + 30539, + 30553, + 30557, + 30559, + 30577, + 30593, + 30631, + 30637, + 30643, + 30649, + 30661, + 30671, + 30677, + 30689, + 30697, + 30703, + 30707, + 30713, + 30727, + 30757, + 30763, + 30773, + 30781, + 30803, + 30809, + 30817, + 30829, + 30839, + 30841, + 30851, + 30853, + 30859, + 30869, + 30871, + 30881, + 30893, + 30911, + 30931, + 30937, + 30941, + 30949, + 30971, + 30977, + 30983, + 31013, + 31019, + 31033, + 31039, + 31051, + 31063, + 31069, + 31079, + 31081, + 31091, + 31121, + 31123, + 31139, + 31147, + 31151, + 31153, + 31159, + 31177, + 31181, + 31183, + 31189, + 31193, + 31219, + 31223, + 31231, + 31237, + 31247, + 31249, + 31253, + 31259, + 31267, + 31271, + 31277, + 31307, + 31319, + 31321, + 31327, + 31333, + 31337, + 31357, + 31379, + 31387, + 31391, + 31393, + 31397, + 31469, + 31477, + 31481, + 31489, + 31511, + 31513, + 31517, + 31531, + 31541, + 31543, + 31547, + 31567, + 31573, + 31583, + 31601, + 31607, + 31627, + 31643, + 31649, + 31657, + 31663, + 31667, + 31687, + 31699, + 31721, + 31723, + 31727, + 31729, + 31741, + 31751, + 31769, + 31771, + 31793, + 31799, + 31817, + 31847, + 31849, + 31859, + 31873, + 31883, + 31891, + 31907, + 31957, + 31963, + 31973, + 31981, + 31991, + 32003, + 32009, + 32027, + 32029, + 32051, + 32057, + 32059, + 32063, + 32069, + 32077, + 32083, + 32089, + 32099, + 32117, + 32119, + 32141, + 32143, + 32159, + 32173, + 32183, + 32189, + 32191, + 32203, + 32213, + 32233, + 32237, + 32251, + 32257, + 32261, + 32297, + 32299, + 32303, + 32309, + 32321, + 32323, + 32327, + 32341, + 32353, + 32359, + 32363, + 32369, + 32371, + 32377, + 32381, + 32401, + 32411, + 32413, + 32423, + 32429, + 32441, + 32443, + 32467, + 32479, + 32491, + 32497, + 32503, + 32507, + 32531, + 32533, + 32537, + 32561, + 32563, + 32569, + 32573, + 32579, + 32587, + 32603, + 32609, + 32611, + 32621, + 32633, + 32647, + 32653, + 32687, + 32693, + 32707, + 32713, + 32717, + 32719, + 32749, + 32771, + 32779, + 32783, + 32789, + 32797, + 32801, + 32803, + 32831, + 32833, + 32839, + 32843, + 32869, + 32887, + 32909, + 32911, + 32917, + 32933, + 32939, + 32941, + 32957, + 32969, + 32971, + 32983, + 32987, + 32993, + 32999, + 33013, + 33023, + 33029, + 33037, + 33049, + 33053, + 33071, + 33073, + 33083, + 33091, + 33107, + 33113, + 33119, + 33149, + 33151, + 33161, + 33179, + 33181, + 33191, + 33199, + 33203, + 33211, + 33223, + 33247, + 33287, + 33289, + 33301, + 33311, + 33317, + 33329, + 33331, + 33343, + 33347, + 33349, + 33353, + 33359, + 33377, + 33391, + 33403, + 33409, + 33413, + 33427, + 33457, + 33461, + 33469, + 33479, + 33487, + 33493, + 33503, + 33521, + 33529, + 33533, + 33547, + 33563, + 33569, + 33577, + 33581, + 33587, + 33589, + 33599, + 33601, + 33613, + 33617, + 33619, + 33623, + 33629, + 33637, + 33641, + 33647, + 33679, + 33703, + 33713, + 33721, + 33739, + 33749, + 33751, + 33757, + 33767, + 33769, + 33773, + 33791, + 33797, + 33809, + 33811, + 33827, + 33829, + 33851, + 33857, + 33863, + 33871, + 33889, + 33893, + 33911, + 33923, + 33931, + 33937, + 33941, + 33961, + 33967, + 33997, + 34019, + 34031, + 34033, + 34039, + 34057, + 34061, + 34123, + 34127, + 34129, + 34141, + 34147, + 34157, + 34159, + 34171, + 34183, + 34211, + 34213, + 34217, + 34231, + 34253, + 34259, + 34261, + 34267, + 34273, + 34283, + 34297, + 34301, + 34303, + 34313, + 34319, + 34327, + 34337, + 34351, + 34361, + 34367, + 34369, + 34381, + 34403, + 34421, + 34429, + 34439, + 34457, + 34469, + 34471, + 34483, + 34487, + 34499, + 34501, + 34511, + 34513, + 34519, + 34537, + 34543, + 34549, + 34583, + 34589, + 34591, + 34603, + 34607, + 34613, + 34631, + 34649, + 34651, + 34667, + 34673, + 34679, + 34687, + 34693, + 34703, + 34721, + 34729, + 34739, + 34747, + 34757, + 34759, + 34763, + 34781, + 34807, + 34819, + 34841, + 34843, + 34847, + 34849, + 34871, + 34877, + 34883, + 34897, + 34913, + 34919, + 34939, + 34949, + 34961, + 34963, + 34981, + 35023, + 35027, + 35051, + 35053, + 35059, + 35069, + 35081, + 35083, + 35089, + 35099, + 35107, + 35111, + 35117, + 35129, + 35141, + 35149, + 35153, + 35159, + 35171, + 35201, + 35221, + 35227, + 35251, + 35257, + 35267, + 35279, + 35281, + 35291, + 35311, + 35317, + 35323, + 35327, + 35339, + 35353, + 35363, + 35381, + 35393, + 35401, + 35407, + 35419, + 35423, + 35437, + 35447, + 35449, + 35461, + 35491, + 35507, + 35509, + 35521, + 35527, + 35531, + 35533, + 35537, + 35543, + 35569, + 35573, + 35591, + 35593, + 35597, + 35603, + 35617, + 35671, + 35677, + 35729, + 35731, + 35747, + 35753, + 35759, + 35771, + 35797, + 35801, + 35803, + 35809, + 35831, + 35837, + 35839, + 35851, + 35863, + 35869, + 35879, + 35897, + 35899, + 35911, + 35923, + 35933, + 35951, + 35963, + 35969, + 35977, + 35983, + 35993, + 35999, + 36007, + 36011, + 36013, + 36017, + 36037, + 36061, + 36067, + 36073, + 36083, + 36097, + 36107, + 36109, + 36131, + 36137, + 36151, + 36161, + 36187, + 36191, + 36209, + 36217, + 36229, + 36241, + 36251, + 36263, + 36269, + 36277, + 36293, + 36299, + 36307, + 36313, + 36319, + 36341, + 36343, + 36353, + 36373, + 36383, + 36389, + 36433, + 36451, + 36457, + 36467, + 36469, + 36473, + 36479, + 36493, + 36497, + 36523, + 36527, + 36529, + 36541, + 36551, + 36559, + 36563, + 36571, + 36583, + 36587, + 36599, + 36607, + 36629, + 36637, + 36643, + 36653, + 36671, + 36677, + 36683, + 36691, + 36697, + 36709, + 36713, + 36721, + 36739, + 36749, + 36761, + 36767, + 36779, + 36781, + 36787, + 36791, + 36793, + 36809, + 36821, + 36833, + 36847, + 36857, + 36871, + 36877, + 36887, + 36899, + 36901, + 36913, + 36919, + 36923, + 36929, + 36931, + 36943, + 36947, + 36973, + 36979, + 36997, + 37003, + 37013, + 37019, + 37021, + 37039, + 37049, + 37057, + 37061, + 37087, + 37097, + 37117, + 37123, + 37139, + 37159, + 37171, + 37181, + 37189, + 37199, + 37201, + 37217, + 37223, + 37243, + 37253, + 37273, + 37277, + 37307, + 37309, + 37313, + 37321, + 37337, + 37339, + 37357, + 37361, + 37363, + 37369, + 37379, + 37397, + 37409, + 37423, + 37441, + 37447, + 37463, + 37483, + 37489, + 37493, + 37501, + 37507, + 37511, + 37517, + 37529, + 37537, + 37547, + 37549, + 37561, + 37567, + 37571, + 37573, + 37579, + 37589, + 37591, + 37607, + 37619, + 37633, + 37643, + 37649, + 37657, + 37663, + 37691, + 37693, + 37699, + 37717, + 37747, + 37781, + 37783, + 37799, + 37811, + 37813, + 37831, + 37847, + 37853, + 37861, + 37871, + 37879, + 37889, + 37897, + 37907, + 37951, + 37957, + 37963, + 37967, + 37987, + 37991, + 37993, + 37997, + 38011, + 38039, + 38047, + 38053, + 38069, + 38083, + 38113, + 38119, + 38149, + 38153, + 38167, + 38177, + 38183, + 38189, + 38197, + 38201, + 38219, + 38231, + 38237, + 38239, + 38261, + 38273, + 38281, + 38287, + 38299, + 38303, + 38317, + 38321, + 38327, + 38329, + 38333, + 38351, + 38371, + 38377, + 38393, + 38431, + 38447, + 38449, + 38453, + 38459, + 38461, + 38501, + 38543, + 38557, + 38561, + 38567, + 38569, + 38593, + 38603, + 38609, + 38611, + 38629, + 38639, + 38651, + 38653, + 38669, + 38671, + 38677, + 38693, + 38699, + 38707, + 38711, + 38713, + 38723, + 38729, + 38737, + 38747, + 38749, + 38767, + 38783, + 38791, + 38803, + 38821, + 38833, + 38839, + 38851, + 38861, + 38867, + 38873, + 38891, + 38903, + 38917, + 38921, + 38923, + 38933, + 38953, + 38959, + 38971, + 38977, + 38993, + 39019, + 39023, + 39041, + 39043, + 39047, + 39079, + 39089, + 39097, + 39103, + 39107, + 39113, + 39119, + 39133, + 39139, + 39157, + 39161, + 39163, + 39181, + 39191, + 39199, + 39209, + 39217, + 39227, + 39229, + 39233, + 39239, + 39241, + 39251, + 39293, + 39301, + 39313, + 39317, + 39323, + 39341, + 39343, + 39359, + 39367, + 39371, + 39373, + 39383, + 39397, + 39409, + 39419, + 39439, + 39443, + 39451, + 39461, + 39499, + 39503, + 39509, + 39511, + 39521, + 39541, + 39551, + 39563, + 39569, + 39581, + 39607, + 39619, + 39623, + 39631, + 39659, + 39667, + 39671, + 39679, + 39703, + 39709, + 39719, + 39727, + 39733, + 39749, + 39761, + 39769, + 39779, + 39791, + 39799, + 39821, + 39827, + 39829, + 39839, + 39841, + 39847, + 39857, + 39863, + 39869, + 39877, + 39883, + 39887, + 39901, + 39929, + 39937, + 39953, + 39971, + 39979, + 39983, + 39989, + 40009, + 40013, + 40031, + 40037, + 40039, + 40063, + 40087, + 40093, + 40099, + 40111, + 40123, + 40127, + 40129, + 40151, + 40153, + 40163, + 40169, + 40177, + 40189, + 40193, + 40213, + 40231, + 40237, + 40241, + 40253, + 40277, + 40283, + 40289, + 40343, + 40351, + 40357, + 40361, + 40387, + 40423, + 40427, + 40429, + 40433, + 40459, + 40471, + 40483, + 40487, + 40493, + 40499, + 40507, + 40519, + 40529, + 40531, + 40543, + 40559, + 40577, + 40583, + 40591, + 40597, + 40609, + 40627, + 40637, + 40639, + 40693, + 40697, + 40699, + 40709, + 40739, + 40751, + 40759, + 40763, + 40771, + 40787, + 40801, + 40813, + 40819, + 40823, + 40829, + 40841, + 40847, + 40849, + 40853, + 40867, + 40879, + 40883, + 40897, + 40903, + 40927, + 40933, + 40939, + 40949, + 40961, + 40973, + 40993, + 41011, + 41017, + 41023, + 41039, + 41047, + 41051, + 41057, + 41077, + 41081, + 41113, + 41117, + 41131, + 41141, + 41143, + 41149, + 41161, + 41177, + 41179, + 41183, + 41189, + 41201, + 41203, + 41213, + 41221, + 41227, + 41231, + 41233, + 41243, + 41257, + 41263, + 41269, + 41281, + 41299, + 41333, + 41341, + 41351, + 41357, + 41381, + 41387, + 41389, + 41399, + 41411, + 41413, + 41443, + 41453, + 41467, + 41479, + 41491, + 41507, + 41513, + 41519, + 41521, + 41539, + 41543, + 41549, + 41579, + 41593, + 41597, + 41603, + 41609, + 41611, + 41617, + 41621, + 41627, + 41641, + 41647, + 41651, + 41659, + 41669, + 41681, + 41687, + 41719, + 41729, + 41737, + 41759, + 41761, + 41771, + 41777, + 41801, + 41809, + 41813, + 41843, + 41849, + 41851, + 41863, + 41879, + 41887, + 41893, + 41897, + 41903, + 41911, + 41927, + 41941, + 41947, + 41953, + 41957, + 41959, + 41969, + 41981, + 41983, + 41999, + 42013, + 42017, + 42019, + 42023, + 42043, + 42061, + 42071, + 42073, + 42083, + 42089, + 42101, + 42131, + 42139, + 42157, + 42169, + 42179, + 42181, + 42187, + 42193, + 42197, + 42209, + 42221, + 42223, + 42227, + 42239, + 42257, + 42281, + 42283, + 42293, + 42299, + 42307, + 42323, + 42331, + 42337, + 42349, + 42359, + 42373, + 42379, + 42391, + 42397, + 42403, + 42407, + 42409, + 42433, + 42437, + 42443, + 42451, + 42457, + 42461, + 42463, + 42467, + 42473, + 42487, + 42491, + 42499, + 42509, + 42533, + 42557, + 42569, + 42571, + 42577, + 42589, + 42611, + 42641, + 42643, + 42649, + 42667, + 42677, + 42683, + 42689, + 42697, + 42701, + 42703, + 42709, + 42719, + 42727, + 42737, + 42743, + 42751, + 42767, + 42773, + 42787, + 42793, + 42797, + 42821, + 42829, + 42839, + 42841, + 42853, + 42859, + 42863, + 42899, + 42901, + 42923, + 42929, + 42937, + 42943, + 42953, + 42961, + 42967, + 42979, + 42989, + 43003, + 43013, + 43019, + 43037, + 43049, + 43051, + 43063, + 43067, + 43093, + 43103, + 43117, + 43133, + 43151, + 43159, + 43177, + 43189, + 43201, + 43207, + 43223, + 43237, + 43261, + 43271, + 43283, + 43291, + 43313, + 43319, + 43321, + 43331, + 43391, + 43397, + 43399, + 43403, + 43411, + 43427, + 43441, + 43451, + 43457, + 43481, + 43487, + 43499, + 43517, + 43541, + 43543, + 43573, + 43577, + 43579, + 43591, + 43597, + 43607, + 43609, + 43613, + 43627, + 43633, + 43649, + 43651, + 43661, + 43669, + 43691, + 43711, + 43717, + 43721, + 43753, + 43759, + 43777, + 43781, + 43783, + 43787, + 43789, + 43793, + 43801, + 43853, + 43867, + 43889, + 43891, + 43913, + 43933, + 43943, + 43951, + 43961, + 43963, + 43969, + 43973, + 43987, + 43991, + 43997, + 44017, + 44021, + 44027, + 44029, + 44041, + 44053, + 44059, + 44071, + 44087, + 44089, + 44101, + 44111, + 44119, + 44123, + 44129, + 44131, + 44159, + 44171, + 44179, + 44189, + 44201, + 44203, + 44207, + 44221, + 44249, + 44257, + 44263, + 44267, + 44269, + 44273, + 44279, + 44281, + 44293, + 44351, + 44357, + 44371, + 44381, + 44383, + 44389, + 44417, + 44449, + 44453, + 44483, + 44491, + 44497, + 44501, + 44507, + 44519, + 44531, + 44533, + 44537, + 44543, + 44549, + 44563, + 44579, + 44587, + 44617, + 44621, + 44623, + 44633, + 44641, + 44647, + 44651, + 44657, + 44683, + 44687, + 44699, + 44701, + 44711, + 44729, + 44741, + 44753, + 44771, + 44773, + 44777, + 44789, + 44797, + 44809, + 44819, + 44839, + 44843, + 44851, + 44867, + 44879, + 44887, + 44893, + 44909, + 44917, + 44927, + 44939, + 44953, + 44959, + 44963, + 44971, + 44983, + 44987, + 45007, + 45013, + 45053, + 45061, + 45077, + 45083, + 45119, + 45121, + 45127, + 45131, + 45137, + 45139, + 45161, + 45179, + 45181, + 45191, + 45197, + 45233, + 45247, + 45259, + 45263, + 45281, + 45289, + 45293, + 45307, + 45317, + 45319, + 45329, + 45337, + 45341, + 45343, + 45361, + 45377, + 45389, + 45403, + 45413, + 45427, + 45433, + 45439, + 45481, + 45491, + 45497, + 45503, + 45523, + 45533, + 45541, + 45553, + 45557, + 45569, + 45587, + 45589, + 45599, + 45613, + 45631, + 45641, + 45659, + 45667, + 45673, + 45677, + 45691, + 45697, + 45707, + 45737, + 45751, + 45757, + 45763, + 45767, + 45779, + 45817, + 45821, + 45823, + 45827, + 45833, + 45841, + 45853, + 45863, + 45869, + 45887, + 45893, + 45943, + 45949, + 45953, + 45959, + 45971, + 45979, + 45989, + 46021, + 46027, + 46049, + 46051, + 46061, + 46073, + 46091, + 46093, + 46099, + 46103, + 46133, + 46141, + 46147, + 46153, + 46171, + 46181, + 46183, + 46187, + 46199, + 46219, + 46229, + 46237, + 46261, + 46271, + 46273, + 46279, + 46301, + 46307, + 46309, + 46327, + 46337, + 46349, + 46351, + 46381, + 46399, + 46411, + 46439, + 46441, + 46447, + 46451, + 46457, + 46471, + 46477, + 46489, + 46499, + 46507, + 46511, + 46523, + 46549, + 46559, + 46567, + 46573, + 46589, + 46591, + 46601, + 46619, + 46633, + 46639, + 46643, + 46649, + 46663, + 46679, + 46681, + 46687, + 46691, + 46703, + 46723, + 46727, + 46747, + 46751, + 46757, + 46769, + 46771, + 46807, + 46811, + 46817, + 46819, + 46829, + 46831, + 46853, + 46861, + 46867, + 46877, + 46889, + 46901, + 46919, + 46933, + 46957, + 46993, + 46997, + 47017, + 47041, + 47051, + 47057, + 47059, + 47087, + 47093, + 47111, + 47119, + 47123, + 47129, + 47137, + 47143, + 47147, + 47149, + 47161, + 47189, + 47207, + 47221, + 47237, + 47251, + 47269, + 47279, + 47287, + 47293, + 47297, + 47303, + 47309, + 47317, + 47339, + 47351, + 47353, + 47363, + 47381, + 47387, + 47389, + 47407, + 47417, + 47419, + 47431, + 47441, + 47459, + 47491, + 47497, + 47501, + 47507, + 47513, + 47521, + 47527, + 47533, + 47543, + 47563, + 47569, + 47581, + 47591, + 47599, + 47609, + 47623, + 47629, + 47639, + 47653, + 47657, + 47659, + 47681, + 47699, + 47701, + 47711, + 47713, + 47717, + 47737, + 47741, + 47743, + 47777, + 47779, + 47791, + 47797, + 47807, + 47809, + 47819, + 47837, + 47843, + 47857, + 47869, + 47881, + 47903, + 47911, + 47917, + 47933, + 47939, + 47947, + 47951, + 47963, + 47969, + 47977, + 47981, + 48017, + 48023, + 48029, + 48049, + 48073, + 48079, + 48091, + 48109, + 48119, + 48121, + 48131, + 48157, + 48163, + 48179, + 48187, + 48193, + 48197, + 48221, + 48239, + 48247, + 48259, + 48271, + 48281, + 48299, + 48311, + 48313, + 48337, + 48341, + 48353, + 48371, + 48383, + 48397, + 48407, + 48409, + 48413, + 48437, + 48449, + 48463, + 48473, + 48479, + 48481, + 48487, + 48491, + 48497, + 48523, + 48527, + 48533, + 48539, + 48541, + 48563, + 48571, + 48589, + 48593, + 48611, + 48619, + 48623, + 48647, + 48649, + 48661, + 48673, + 48677, + 48679, + 48731, + 48733, + 48751, + 48757, + 48761, + 48767, + 48779, + 48781, + 48787, + 48799, + 48809, + 48817, + 48821, + 48823, + 48847, + 48857, + 48859, + 48869, + 48871, + 48883, + 48889, + 48907, + 48947, + 48953, + 48973, + 48989, + 48991, + 49003, + 49009, + 49019, + 49031, + 49033, + 49037, + 49043, + 49057, + 49069, + 49081, + 49103, + 49109, + 49117, + 49121, + 49123, + 49139, + 49157, + 49169, + 49171, + 49177, + 49193, + 49199, + 49201, + 49207, + 49211, + 49223, + 49253, + 49261, + 49277, + 49279, + 49297, + 49307, + 49331, + 49333, + 49339, + 49363, + 49367, + 49369, + 49391, + 49393, + 49409, + 49411, + 49417, + 49429, + 49433, + 49451, + 49459, + 49463, + 49477, + 49481, + 49499, + 49523, + 49529, + 49531, + 49537, + 49547, + 49549, + 49559, + 49597, + 49603, + 49613, + 49627, + 49633, + 49639, + 49663, + 49667, + 49669, + 49681, + 49697, + 49711, + 49727, + 49739, + 49741, + 49747, + 49757, + 49783, + 49787, + 49789, + 49801, + 49807, + 49811, + 49823, + 49831, + 49843, + 49853, + 49871, + 49877, + 49891, + 49919, + 49921, + 49927, + 49937, + 49939, + 49943, + 49957, + 49991, + 49993, + 49999, + 50021, + 50023, + 50033, + 50047, + 50051, + 50053, + 50069, + 50077, + 50087, + 50093, + 50101, + 50111, + 50119, + 50123, + 50129, + 50131, + 50147, + 50153, + 50159, + 50177, + 50207, + 50221, + 50227, + 50231, + 50261, + 50263, + 50273, + 50287, + 50291, + 50311, + 50321, + 50329, + 50333, + 50341, + 50359, + 50363, + 50377, + 50383, + 50387, + 50411, + 50417, + 50423, + 50441, + 50459, + 50461, + 50497, + 50503, + 50513, + 50527, + 50539, + 50543, + 50549, + 50551, + 50581, + 50587, + 50591, + 50593, + 50599, + 50627, + 50647, + 50651, + 50671, + 50683, + 50707, + 50723, + 50741, + 50753, + 50767, + 50773, + 50777, + 50789, + 50821, + 50833, + 50839, + 50849, + 50857, + 50867, + 50873, + 50891, + 50893, + 50909, + 50923, + 50929, + 50951, + 50957, + 50969, + 50971, + 50989, + 50993, + 51001, + 51031, + 51043, + 51047, + 51059, + 51061, + 51071, + 51109, + 51131, + 51133, + 51137, + 51151, + 51157, + 51169, + 51193, + 51197, + 51199, + 51203, + 51217, + 51229, + 51239, + 51241, + 51257, + 51263, + 51283, + 51287, + 51307, + 51329, + 51341, + 51343, + 51347, + 51349, + 51361, + 51383, + 51407, + 51413, + 51419, + 51421, + 51427, + 51431, + 51437, + 51439, + 51449, + 51461, + 51473, + 51479, + 51481, + 51487, + 51503, + 51511, + 51517, + 51521, + 51539, + 51551, + 51563, + 51577, + 51581, + 51593, + 51599, + 51607, + 51613, + 51631, + 51637, + 51647, + 51659, + 51673, + 51679, + 51683, + 51691, + 51713, + 51719, + 51721, + 51749, + 51767, + 51769, + 51787, + 51797, + 51803, + 51817, + 51827, + 51829, + 51839, + 51853, + 51859, + 51869, + 51871, + 51893, + 51899, + 51907, + 51913, + 51929, + 51941, + 51949, + 51971, + 51973, + 51977, + 51991, + 52009, + 52021, + 52027, + 52051, + 52057, + 52067, + 52069, + 52081, + 52103, + 52121, + 52127, + 52147, + 52153, + 52163, + 52177, + 52181, + 52183, + 52189, + 52201, + 52223, + 52237, + 52249, + 52253, + 52259, + 52267, + 52289, + 52291, + 52301, + 52313, + 52321, + 52361, + 52363, + 52369, + 52379, + 52387, + 52391, + 52433, + 52453, + 52457, + 52489, + 52501, + 52511, + 52517, + 52529, + 52541, + 52543, + 52553, + 52561, + 52567, + 52571, + 52579, + 52583, + 52609, + 52627, + 52631, + 52639, + 52667, + 52673, + 52691, + 52697, + 52709, + 52711, + 52721, + 52727, + 52733, + 52747, + 52757, + 52769, + 52783, + 52807, + 52813, + 52817, + 52837, + 52859, + 52861, + 52879, + 52883, + 52889, + 52901, + 52903, + 52919, + 52937, + 52951, + 52957, + 52963, + 52967, + 52973, + 52981, + 52999, + 53003, + 53017, + 53047, + 53051, + 53069, + 53077, + 53087, + 53089, + 53093, + 53101, + 53113, + 53117, + 53129, + 53147, + 53149, + 53161, + 53171, + 53173, + 53189, + 53197, + 53201, + 53231, + 53233, + 53239, + 53267, + 53269, + 53279, + 53281, + 53299, + 53309, + 53323, + 53327, + 53353, + 53359, + 53377, + 53381, + 53401, + 53407, + 53411, + 53419, + 53437, + 53441, + 53453, + 53479, + 53503, + 53507, + 53527, + 53549, + 53551, + 53569, + 53591, + 53593, + 53597, + 53609, + 53611, + 53617, + 53623, + 53629, + 53633, + 53639, + 53653, + 53657, + 53681, + 53693, + 53699, + 53717, + 53719, + 53731, + 53759, + 53773, + 53777, + 53783, + 53791, + 53813, + 53819, + 53831, + 53849, + 53857, + 53861, + 53881, + 53887, + 53891, + 53897, + 53899, + 53917, + 53923, + 53927, + 53939, + 53951, + 53959, + 53987, + 53993, + 54001, + 54011, + 54013, + 54037, + 54049, + 54059, + 54083, + 54091, + 54101, + 54121, + 54133, + 54139, + 54151, + 54163, + 54167, + 54181, + 54193, + 54217, + 54251, + 54269, + 54277, + 54287, + 54293, + 54311, + 54319, + 54323, + 54331, + 54347, + 54361, + 54367, + 54371, + 54377, + 54401, + 54403, + 54409, + 54413, + 54419, + 54421, + 54437, + 54443, + 54449, + 54469, + 54493, + 54497, + 54499, + 54503, + 54517, + 54521, + 54539, + 54541, + 54547, + 54559, + 54563, + 54577, + 54581, + 54583, + 54601, + 54617, + 54623, + 54629, + 54631, + 54647, + 54667, + 54673, + 54679, + 54709, + 54713, + 54721, + 54727, + 54751, + 54767, + 54773, + 54779, + 54787, + 54799, + 54829, + 54833, + 54851, + 54869, + 54877, + 54881, + 54907, + 54917, + 54919, + 54941, + 54949, + 54959, + 54973, + 54979, + 54983, + 55001, + 55009, + 55021, + 55049, + 55051, + 55057, + 55061, + 55073, + 55079, + 55103, + 55109, + 55117, + 55127, + 55147, + 55163, + 55171, + 55201, + 55207, + 55213, + 55217, + 55219, + 55229, + 55243, + 55249, + 55259, + 55291, + 55313, + 55331, + 55333, + 55337, + 55339, + 55343, + 55351, + 55373, + 55381, + 55399, + 55411, + 55439, + 55441, + 55457, + 55469, + 55487, + 55501, + 55511, + 55529, + 55541, + 55547, + 55579, + 55589, + 55603, + 55609, + 55619, + 55621, + 55631, + 55633, + 55639, + 55661, + 55663, + 55667, + 55673, + 55681, + 55691, + 55697, + 55711, + 55717, + 55721, + 55733, + 55763, + 55787, + 55793, + 55799, + 55807, + 55813, + 55817, + 55819, + 55823, + 55829, + 55837, + 55843, + 55849, + 55871, + 55889, + 55897, + 55901, + 55903, + 55921, + 55927, + 55931, + 55933, + 55949, + 55967, + 55987, + 55997, + 56003, + 56009, + 56039, + 56041, + 56053, + 56081, + 56087, + 56093, + 56099, + 56101, + 56113, + 56123, + 56131, + 56149, + 56167, + 56171, + 56179, + 56197, + 56207, + 56209, + 56237, + 56239, + 56249, + 56263, + 56267, + 56269, + 56299, + 56311, + 56333, + 56359, + 56369, + 56377, + 56383, + 56393, + 56401, + 56417, + 56431, + 56437, + 56443, + 56453, + 56467, + 56473, + 56477, + 56479, + 56489, + 56501, + 56503, + 56509, + 56519, + 56527, + 56531, + 56533, + 56543, + 56569, + 56591, + 56597, + 56599, + 56611, + 56629, + 56633, + 56659, + 56663, + 56671, + 56681, + 56687, + 56701, + 56711, + 56713, + 56731, + 56737, + 56747, + 56767, + 56773, + 56779, + 56783, + 56807, + 56809, + 56813, + 56821, + 56827, + 56843, + 56857, + 56873, + 56891, + 56893, + 56897, + 56909, + 56911, + 56921, + 56923, + 56929, + 56941, + 56951, + 56957, + 56963, + 56983, + 56989, + 56993, + 56999, + 57037, + 57041, + 57047, + 57059, + 57073, + 57077, + 57089, + 57097, + 57107, + 57119, + 57131, + 57139, + 57143, + 57149, + 57163, + 57173, + 57179, + 57191, + 57193, + 57203, + 57221, + 57223, + 57241, + 57251, + 57259, + 57269, + 57271, + 57283, + 57287, + 57301, + 57329, + 57331, + 57347, + 57349, + 57367, + 57373, + 57383, + 57389, + 57397, + 57413, + 57427, + 57457, + 57467, + 57487, + 57493, + 57503, + 57527, + 57529, + 57557, + 57559, + 57571, + 57587, + 57593, + 57601, + 57637, + 57641, + 57649, + 57653, + 57667, + 57679, + 57689, + 57697, + 57709, + 57713, + 57719, + 57727, + 57731, + 57737, + 57751, + 57773, + 57781, + 57787, + 57791, + 57793, + 57803, + 57809, + 57829, + 57839, + 57847, + 57853, + 57859, + 57881, + 57899, + 57901, + 57917, + 57923, + 57943, + 57947, + 57973, + 57977, + 57991, + 58013, + 58027, + 58031, + 58043, + 58049, + 58057, + 58061, + 58067, + 58073, + 58099, + 58109, + 58111, + 58129, + 58147, + 58151, + 58153, + 58169, + 58171, + 58189, + 58193, + 58199, + 58207, + 58211, + 58217, + 58229, + 58231, + 58237, + 58243, + 58271, + 58309, + 58313, + 58321, + 58337, + 58363, + 58367, + 58369, + 58379, + 58391, + 58393, + 58403, + 58411, + 58417, + 58427, + 58439, + 58441, + 58451, + 58453, + 58477, + 58481, + 58511, + 58537, + 58543, + 58549, + 58567, + 58573, + 58579, + 58601, + 58603, + 58613, + 58631, + 58657, + 58661, + 58679, + 58687, + 58693, + 58699, + 58711, + 58727, + 58733, + 58741, + 58757, + 58763, + 58771, + 58787, + 58789, + 58831, + 58889, + 58897, + 58901, + 58907, + 58909, + 58913, + 58921, + 58937, + 58943, + 58963, + 58967, + 58979, + 58991, + 58997, + 59009, + 59011, + 59021, + 59023, + 59029, + 59051, + 59053, + 59063, + 59069, + 59077, + 59083, + 59093, + 59107, + 59113, + 59119, + 59123, + 59141, + 59149, + 59159, + 59167, + 59183, + 59197, + 59207, + 59209, + 59219, + 59221, + 59233, + 59239, + 59243, + 59263, + 59273, + 59281, + 59333, + 59341, + 59351, + 59357, + 59359, + 59369, + 59377, + 59387, + 59393, + 59399, + 59407, + 59417, + 59419, + 59441, + 59443, + 59447, + 59453, + 59467, + 59471, + 59473, + 59497, + 59509, + 59513, + 59539, + 59557, + 59561, + 59567, + 59581, + 59611, + 59617, + 59621, + 59627, + 59629, + 59651, + 59659, + 59663, + 59669, + 59671, + 59693, + 59699, + 59707, + 59723, + 59729, + 59743, + 59747, + 59753, + 59771, + 59779, + 59791, + 59797, + 59809, + 59833, + 59863, + 59879, + 59887, + 59921, + 59929, + 59951, + 59957, + 59971, + 59981, + 59999, + 60013, + 60017, + 60029, + 60037, + 60041, + 60077, + 60083, + 60089, + 60091, + 60101, + 60103, + 60107, + 60127, + 60133, + 60139, + 60149, + 60161, + 60167, + 60169, + 60209, + 60217, + 60223, + 60251, + 60257, + 60259, + 60271, + 60289, + 60293, + 60317, + 60331, + 60337, + 60343, + 60353, + 60373, + 60383, + 60397, + 60413, + 60427, + 60443, + 60449, + 60457, + 60493, + 60497, + 60509, + 60521, + 60527, + 60539, + 60589, + 60601, + 60607, + 60611, + 60617, + 60623, + 60631, + 60637, + 60647, + 60649, + 60659, + 60661, + 60679, + 60689, + 60703, + 60719, + 60727, + 60733, + 60737, + 60757, + 60761, + 60763, + 60773, + 60779, + 60793, + 60811, + 60821, + 60859, + 60869, + 60887, + 60889, + 60899, + 60901, + 60913, + 60917, + 60919, + 60923, + 60937, + 60943, + 60953, + 60961, + 61001, + 61007, + 61027, + 61031, + 61043, + 61051, + 61057, + 61091, + 61099, + 61121, + 61129, + 61141, + 61151, + 61153, + 61169, + 61211, + 61223, + 61231, + 61253, + 61261, + 61283, + 61291, + 61297, + 61331, + 61333, + 61339, + 61343, + 61357, + 61363, + 61379, + 61381, + 61403, + 61409, + 61417, + 61441, + 61463, + 61469, + 61471, + 61483, + 61487, + 61493, + 61507, + 61511, + 61519, + 61543, + 61547, + 61553, + 61559, + 61561, + 61583, + 61603, + 61609, + 61613, + 61627, + 61631, + 61637, + 61643, + 61651, + 61657, + 61667, + 61673, + 61681, + 61687, + 61703, + 61717, + 61723, + 61729, + 61751, + 61757, + 61781, + 61813, + 61819, + 61837, + 61843, + 61861, + 61871, + 61879, + 61909, + 61927, + 61933, + 61949, + 61961, + 61967, + 61979, + 61981, + 61987, + 61991, + 62003, + 62011, + 62017, + 62039, + 62047, + 62053, + 62057, + 62071, + 62081, + 62099, + 62119, + 62129, + 62131, + 62137, + 62141, + 62143, + 62171, + 62189, + 62191, + 62201, + 62207, + 62213, + 62219, + 62233, + 62273, + 62297, + 62299, + 62303, + 62311, + 62323, + 62327, + 62347, + 62351, + 62383, + 62401, + 62417, + 62423, + 62459, + 62467, + 62473, + 62477, + 62483, + 62497, + 62501, + 62507, + 62533, + 62539, + 62549, + 62563, + 62581, + 62591, + 62597, + 62603, + 62617, + 62627, + 62633, + 62639, + 62653, + 62659, + 62683, + 62687, + 62701, + 62723, + 62731, + 62743, + 62753, + 62761, + 62773, + 62791, + 62801, + 62819, + 62827, + 62851, + 62861, + 62869, + 62873, + 62897, + 62903, + 62921, + 62927, + 62929, + 62939, + 62969, + 62971, + 62981, + 62983, + 62987, + 62989, + 63029, + 63031, + 63059, + 63067, + 63073, + 63079, + 63097, + 63103, + 63113, + 63127, + 63131, + 63149, + 63179, + 63197, + 63199, + 63211, + 63241, + 63247, + 63277, + 63281, + 63299, + 63311, + 63313, + 63317, + 63331, + 63337, + 63347, + 63353, + 63361, + 63367, + 63377, + 63389, + 63391, + 63397, + 63409, + 63419, + 63421, + 63439, + 63443, + 63463, + 63467, + 63473, + 63487, + 63493, + 63499, + 63521, + 63527, + 63533, + 63541, + 63559, + 63577, + 63587, + 63589, + 63599, + 63601, + 63607, + 63611, + 63617, + 63629, + 63647, + 63649, + 63659, + 63667, + 63671, + 63689, + 63691, + 63697, + 63703, + 63709, + 63719, + 63727, + 63737, + 63743, + 63761, + 63773, + 63781, + 63793, + 63799, + 63803, + 63809, + 63823, + 63839, + 63841, + 63853, + 63857, + 63863, + 63901, + 63907, + 63913, + 63929, + 63949, + 63977, + 63997, + 64007, + 64013, + 64019, + 64033, + 64037, + 64063, + 64067, + 64081, + 64091, + 64109, + 64123, + 64151, + 64153, + 64157, + 64171, + 64187, + 64189, + 64217, + 64223, + 64231, + 64237, + 64271, + 64279, + 64283, + 64301, + 64303, + 64319, + 64327, + 64333, + 64373, + 64381, + 64399, + 64403, + 64433, + 64439, + 64451, + 64453, + 64483, + 64489, + 64499, + 64513, + 64553, + 64567, + 64577, + 64579, + 64591, + 64601, + 64609, + 64613, + 64621, + 64627, + 64633, + 64661, + 64663, + 64667, + 64679, + 64693, + 64709, + 64717, + 64747, + 64763, + 64781, + 64783, + 64793, + 64811, + 64817, + 64849, + 64853, + 64871, + 64877, + 64879, + 64891, + 64901, + 64919, + 64921, + 64927, + 64937, + 64951, + 64969, + 64997, + 65003, + 65011, + 65027, + 65029, + 65033, + 65053, + 65063, + 65071, + 65089, + 65099, + 65101, + 65111, + 65119, + 65123, + 65129, + 65141, + 65147, + 65167, + 65171, + 65173, + 65179, + 65183, + 65203, + 65213, + 65239, + 65257, + 65267, + 65269, + 65287, + 65293, + 65309, + 65323, + 65327, + 65353, + 65357, + 65371, + 65381, + 65393, + 65407, + 65413, + 65419, + 65423, + 65437, + 65447, + 65449, + 65479, + 65497, + 65519, + 65521, + 65537, + 65539, + 65543, + 65551, + 65557, + 65563, + 65579, + 65581, + 65587, + 65599, + 65609, + 65617, + 65629, + 65633, + 65647, + 65651, + 65657, + 65677, + 65687, + 65699, + 65701, + 65707, + 65713, + 65717, + 65719, + 65729, + 65731, + 65761, + 65777, + 65789, + 65809, + 65827, + 65831, + 65837, + 65839, + 65843, + 65851, + 65867, + 65881, + 65899, + 65921, + 65927, + 65929, + 65951, + 65957, + 65963, + 65981, + 65983, + 65993, + 66029, + 66037, + 66041, + 66047, + 66067, + 66071, + 66083, + 66089, + 66103, + 66107, + 66109, + 66137, + 66161, + 66169, + 66173, + 66179, + 66191, + 66221, + 66239, + 66271, + 66293, + 66301, + 66337, + 66343, + 66347, + 66359, + 66361, + 66373, + 66377, + 66383, + 66403, + 66413, + 66431, + 66449, + 66457, + 66463, + 66467, + 66491, + 66499, + 66509, + 66523, + 66529, + 66533, + 66541, + 66553, + 66569, + 66571, + 66587, + 66593, + 66601, + 66617, + 66629, + 66643, + 66653, + 66683, + 66697, + 66701, + 66713, + 66721, + 66733, + 66739, + 66749, + 66751, + 66763, + 66791, + 66797, + 66809, + 66821, + 66841, + 66851, + 66853, + 66863, + 66877, + 66883, + 66889, + 66919, + 66923, + 66931, + 66943, + 66947, + 66949, + 66959, + 66973, + 66977, + 67003, + 67021, + 67033, + 67043, + 67049, + 67057, + 67061, + 67073, + 67079, + 67103, + 67121, + 67129, + 67139, + 67141, + 67153, + 67157, + 67169, + 67181, + 67187, + 67189, + 67211, + 67213, + 67217, + 67219, + 67231, + 67247, + 67261, + 67271, + 67273, + 67289, + 67307, + 67339, + 67343, + 67349, + 67369, + 67391, + 67399, + 67409, + 67411, + 67421, + 67427, + 67429, + 67433, + 67447, + 67453, + 67477, + 67481, + 67489, + 67493, + 67499, + 67511, + 67523, + 67531, + 67537, + 67547, + 67559, + 67567, + 67577, + 67579, + 67589, + 67601, + 67607, + 67619, + 67631, + 67651, + 67679, + 67699, + 67709, + 67723, + 67733, + 67741, + 67751, + 67757, + 67759, + 67763, + 67777, + 67783, + 67789, + 67801, + 67807, + 67819, + 67829, + 67843, + 67853, + 67867, + 67883, + 67891, + 67901, + 67927, + 67931, + 67933, + 67939, + 67943, + 67957, + 67961, + 67967, + 67979, + 67987, + 67993, + 68023, + 68041, + 68053, + 68059, + 68071, + 68087, + 68099, + 68111, + 68113, + 68141, + 68147, + 68161, + 68171, + 68207, + 68209, + 68213, + 68219, + 68227, + 68239, + 68261, + 68279, + 68281, + 68311, + 68329, + 68351, + 68371, + 68389, + 68399, + 68437, + 68443, + 68447, + 68449, + 68473, + 68477, + 68483, + 68489, + 68491, + 68501, + 68507, + 68521, + 68531, + 68539, + 68543, + 68567, + 68581, + 68597, + 68611, + 68633, + 68639, + 68659, + 68669, + 68683, + 68687, + 68699, + 68711, + 68713, + 68729, + 68737, + 68743, + 68749, + 68767, + 68771, + 68777, + 68791, + 68813, + 68819, + 68821, + 68863, + 68879, + 68881, + 68891, + 68897, + 68899, + 68903, + 68909, + 68917, + 68927, + 68947, + 68963, + 68993, + 69001, + 69011, + 69019, + 69029, + 69031, + 69061, + 69067, + 69073, + 69109, + 69119, + 69127, + 69143, + 69149, + 69151, + 69163, + 69191, + 69193, + 69197, + 69203, + 69221, + 69233, + 69239, + 69247, + 69257, + 69259, + 69263, + 69313, + 69317, + 69337, + 69341, + 69371, + 69379, + 69383, + 69389, + 69401, + 69403, + 69427, + 69431, + 69439, + 69457, + 69463, + 69467, + 69473, + 69481, + 69491, + 69493, + 69497, + 69499, + 69539, + 69557, + 69593, + 69623, + 69653, + 69661, + 69677, + 69691, + 69697, + 69709, + 69737, + 69739, + 69761, + 69763, + 69767, + 69779, + 69809, + 69821, + 69827, + 69829, + 69833, + 69847, + 69857, + 69859, + 69877, + 69899, + 69911, + 69929, + 69931, + 69941, + 69959, + 69991, + 69997, + 70001, + 70003, + 70009, + 70019, + 70039, + 70051, + 70061, + 70067, + 70079, + 70099, + 70111, + 70117, + 70121, + 70123, + 70139, + 70141, + 70157, + 70163, + 70177, + 70181, + 70183, + 70199, + 70201, + 70207, + 70223, + 70229, + 70237, + 70241, + 70249, + 70271, + 70289, + 70297, + 70309, + 70313, + 70321, + 70327, + 70351, + 70373, + 70379, + 70381, + 70393, + 70423, + 70429, + 70439, + 70451, + 70457, + 70459, + 70481, + 70487, + 70489, + 70501, + 70507, + 70529, + 70537, + 70549, + 70571, + 70573, + 70583, + 70589, + 70607, + 70619, + 70621, + 70627, + 70639, + 70657, + 70663, + 70667, + 70687, + 70709, + 70717, + 70729, + 70753, + 70769, + 70783, + 70793, + 70823, + 70841, + 70843, + 70849, + 70853, + 70867, + 70877, + 70879, + 70891, + 70901, + 70913, + 70919, + 70921, + 70937, + 70949, + 70951, + 70957, + 70969, + 70979, + 70981, + 70991, + 70997, + 70999, + 71011, + 71023, + 71039, + 71059, + 71069, + 71081, + 71089, + 71119, + 71129, + 71143, + 71147, + 71153, + 71161, + 71167, + 71171, + 71191, + 71209, + 71233, + 71237, + 71249, + 71257, + 71261, + 71263, + 71287, + 71293, + 71317, + 71327, + 71329, + 71333, + 71339, + 71341, + 71347, + 71353, + 71359, + 71363, + 71387, + 71389, + 71399, + 71411, + 71413, + 71419, + 71429, + 71437, + 71443, + 71453, + 71471, + 71473, + 71479, + 71483, + 71503, + 71527, + 71537, + 71549, + 71551, + 71563, + 71569, + 71593, + 71597, + 71633, + 71647, + 71663, + 71671, + 71693, + 71699, + 71707, + 71711, + 71713, + 71719, + 71741, + 71761, + 71777, + 71789, + 71807, + 71809, + 71821, + 71837, + 71843, + 71849, + 71861, + 71867, + 71879, + 71881, + 71887, + 71899, + 71909, + 71917, + 71933, + 71941, + 71947, + 71963, + 71971, + 71983, + 71987, + 71993, + 71999, + 72019, + 72031, + 72043, + 72047, + 72053, + 72073, + 72077, + 72089, + 72091, + 72101, + 72103, + 72109, + 72139, + 72161, + 72167, + 72169, + 72173, + 72211, + 72221, + 72223, + 72227, + 72229, + 72251, + 72253, + 72269, + 72271, + 72277, + 72287, + 72307, + 72313, + 72337, + 72341, + 72353, + 72367, + 72379, + 72383, + 72421, + 72431, + 72461, + 72467, + 72469, + 72481, + 72493, + 72497, + 72503, + 72533, + 72547, + 72551, + 72559, + 72577, + 72613, + 72617, + 72623, + 72643, + 72647, + 72649, + 72661, + 72671, + 72673, + 72679, + 72689, + 72701, + 72707, + 72719, + 72727, + 72733, + 72739, + 72763, + 72767, + 72797, + 72817, + 72823, + 72859, + 72869, + 72871, + 72883, + 72889, + 72893, + 72901, + 72907, + 72911, + 72923, + 72931, + 72937, + 72949, + 72953, + 72959, + 72973, + 72977, + 72997, + 73009, + 73013, + 73019, + 73037, + 73039, + 73043, + 73061, + 73063, + 73079, + 73091, + 73121, + 73127, + 73133, + 73141, + 73181, + 73189, + 73237, + 73243, + 73259, + 73277, + 73291, + 73303, + 73309, + 73327, + 73331, + 73351, + 73361, + 73363, + 73369, + 73379, + 73387, + 73417, + 73421, + 73433, + 73453, + 73459, + 73471, + 73477, + 73483, + 73517, + 73523, + 73529, + 73547, + 73553, + 73561, + 73571, + 73583, + 73589, + 73597, + 73607, + 73609, + 73613, + 73637, + 73643, + 73651, + 73673, + 73679, + 73681, + 73693, + 73699, + 73709, + 73721, + 73727, + 73751, + 73757, + 73771, + 73783, + 73819, + 73823, + 73847, + 73849, + 73859, + 73867, + 73877, + 73883, + 73897, + 73907, + 73939, + 73943, + 73951, + 73961, + 73973, + 73999, + 74017, + 74021, + 74027, + 74047, + 74051, + 74071, + 74077, + 74093, + 74099, + 74101, + 74131, + 74143, + 74149, + 74159, + 74161, + 74167, + 74177, + 74189, + 74197, + 74201, + 74203, + 74209, + 74219, + 74231, + 74257, + 74279, + 74287, + 74293, + 74297, + 74311, + 74317, + 74323, + 74353, + 74357, + 74363, + 74377, + 74381, + 74383, + 74411, + 74413, + 74419, + 74441, + 74449, + 74453, + 74471, + 74489, + 74507, + 74509, + 74521, + 74527, + 74531, + 74551, + 74561, + 74567, + 74573, + 74587, + 74597, + 74609, + 74611, + 74623, + 74653, + 74687, + 74699, + 74707, + 74713, + 74717, + 74719, + 74729, + 74731, + 74747, + 74759, + 74761, + 74771, + 74779, + 74797, + 74821, + 74827, + 74831, + 74843, + 74857, + 74861, + 74869, + 74873, + 74887, + 74891, + 74897, + 74903, + 74923, + 74929, + 74933, + 74941, + 74959, + 75011, + 75013, + 75017, + 75029, + 75037, + 75041, + 75079, + 75083, + 75109, + 75133, + 75149, + 75161, + 75167, + 75169, + 75181, + 75193, + 75209, + 75211, + 75217, + 75223, + 75227, + 75239, + 75253, + 75269, + 75277, + 75289, + 75307, + 75323, + 75329, + 75337, + 75347, + 75353, + 75367, + 75377, + 75389, + 75391, + 75401, + 75403, + 75407, + 75431, + 75437, + 75479, + 75503, + 75511, + 75521, + 75527, + 75533, + 75539, + 75541, + 75553, + 75557, + 75571, + 75577, + 75583, + 75611, + 75617, + 75619, + 75629, + 75641, + 75653, + 75659, + 75679, + 75683, + 75689, + 75703, + 75707, + 75709, + 75721, + 75731, + 75743, + 75767, + 75773, + 75781, + 75787, + 75793, + 75797, + 75821, + 75833, + 75853, + 75869, + 75883, + 75913, + 75931, + 75937, + 75941, + 75967, + 75979, + 75983, + 75989, + 75991, + 75997, + 76001, + 76003, + 76031, + 76039, + 76079, + 76081, + 76091, + 76099, + 76103, + 76123, + 76129, + 76147, + 76157, + 76159, + 76163, + 76207, + 76213, + 76231, + 76243, + 76249, + 76253, + 76259, + 76261, + 76283, + 76289, + 76303, + 76333, + 76343, + 76367, + 76369, + 76379, + 76387, + 76403, + 76421, + 76423, + 76441, + 76463, + 76471, + 76481, + 76487, + 76493, + 76507, + 76511, + 76519, + 76537, + 76541, + 76543, + 76561, + 76579, + 76597, + 76603, + 76607, + 76631, + 76649, + 76651, + 76667, + 76673, + 76679, + 76697, + 76717, + 76733, + 76753, + 76757, + 76771, + 76777, + 76781, + 76801, + 76819, + 76829, + 76831, + 76837, + 76847, + 76871, + 76873, + 76883, + 76907, + 76913, + 76919, + 76943, + 76949, + 76961, + 76963, + 76991, + 77003, + 77017, + 77023, + 77029, + 77041, + 77047, + 77069, + 77081, + 77093, + 77101, + 77137, + 77141, + 77153, + 77167, + 77171, + 77191, + 77201, + 77213, + 77237, + 77239, + 77243, + 77249, + 77261, + 77263, + 77267, + 77269, + 77279, + 77291, + 77317, + 77323, + 77339, + 77347, + 77351, + 77359, + 77369, + 77377, + 77383, + 77417, + 77419, + 77431, + 77447, + 77471, + 77477, + 77479, + 77489, + 77491, + 77509, + 77513, + 77521, + 77527, + 77543, + 77549, + 77551, + 77557, + 77563, + 77569, + 77573, + 77587, + 77591, + 77611, + 77617, + 77621, + 77641, + 77647, + 77659, + 77681, + 77687, + 77689, + 77699, + 77711, + 77713, + 77719, + 77723, + 77731, + 77743, + 77747, + 77761, + 77773, + 77783, + 77797, + 77801, + 77813, + 77839, + 77849, + 77863, + 77867, + 77893, + 77899, + 77929, + 77933, + 77951, + 77969, + 77977, + 77983, + 77999, + 78007, + 78017, + 78031, + 78041, + 78049, + 78059, + 78079, + 78101, + 78121, + 78137, + 78139, + 78157, + 78163, + 78167, + 78173, + 78179, + 78191, + 78193, + 78203, + 78229, + 78233, + 78241, + 78259, + 78277, + 78283, + 78301, + 78307, + 78311, + 78317, + 78341, + 78347, + 78367, + 78401, + 78427, + 78437, + 78439, + 78467, + 78479, + 78487, + 78497, + 78509, + 78511, + 78517, + 78539, + 78541, + 78553, + 78569, + 78571, + 78577, + 78583, + 78593, + 78607, + 78623, + 78643, + 78649, + 78653, + 78691, + 78697, + 78707, + 78713, + 78721, + 78737, + 78779, + 78781, + 78787, + 78791, + 78797, + 78803, + 78809, + 78823, + 78839, + 78853, + 78857, + 78877, + 78887, + 78889, + 78893, + 78901, + 78919, + 78929, + 78941, + 78977, + 78979, + 78989, + 79031, + 79039, + 79043, + 79063, + 79087, + 79103, + 79111, + 79133, + 79139, + 79147, + 79151, + 79153, + 79159, + 79181, + 79187, + 79193, + 79201, + 79229, + 79231, + 79241, + 79259, + 79273, + 79279, + 79283, + 79301, + 79309, + 79319, + 79333, + 79337, + 79349, + 79357, + 79367, + 79379, + 79393, + 79397, + 79399, + 79411, + 79423, + 79427, + 79433, + 79451, + 79481, + 79493, + 79531, + 79537, + 79549, + 79559, + 79561, + 79579, + 79589, + 79601, + 79609, + 79613, + 79621, + 79627, + 79631, + 79633, + 79657, + 79669, + 79687, + 79691, + 79693, + 79697, + 79699, + 79757, + 79769, + 79777, + 79801, + 79811, + 79813, + 79817, + 79823, + 79829, + 79841, + 79843, + 79847, + 79861, + 79867, + 79873, + 79889, + 79901, + 79903, + 79907, + 79939, + 79943, + 79967, + 79973, + 79979, + 79987, + 79997, + 79999, + 80021, + 80039, + 80051, + 80071, + 80077, + 80107, + 80111, + 80141, + 80147, + 80149, + 80153, + 80167, + 80173, + 80177, + 80191, + 80207, + 80209, + 80221, + 80231, + 80233, + 80239, + 80251, + 80263, + 80273, + 80279, + 80287, + 80309, + 80317, + 80329, + 80341, + 80347, + 80363, + 80369, + 80387, + 80407, + 80429, + 80447, + 80449, + 80471, + 80473, + 80489, + 80491, + 80513, + 80527, + 80537, + 80557, + 80567, + 80599, + 80603, + 80611, + 80621, + 80627, + 80629, + 80651, + 80657, + 80669, + 80671, + 80677, + 80681, + 80683, + 80687, + 80701, + 80713, + 80737, + 80747, + 80749, + 80761, + 80777, + 80779, + 80783, + 80789, + 80803, + 80809, + 80819, + 80831, + 80833, + 80849, + 80863, + 80897, + 80909, + 80911, + 80917, + 80923, + 80929, + 80933, + 80953, + 80963, + 80989, + 81001, + 81013, + 81017, + 81019, + 81023, + 81031, + 81041, + 81043, + 81047, + 81049, + 81071, + 81077, + 81083, + 81097, + 81101, + 81119, + 81131, + 81157, + 81163, + 81173, + 81181, + 81197, + 81199, + 81203, + 81223, + 81233, + 81239, + 81281, + 81283, + 81293, + 81299, + 81307, + 81331, + 81343, + 81349, + 81353, + 81359, + 81371, + 81373, + 81401, + 81409, + 81421, + 81439, + 81457, + 81463, + 81509, + 81517, + 81527, + 81533, + 81547, + 81551, + 81553, + 81559, + 81563, + 81569, + 81611, + 81619, + 81629, + 81637, + 81647, + 81649, + 81667, + 81671, + 81677, + 81689, + 81701, + 81703, + 81707, + 81727, + 81737, + 81749, + 81761, + 81769, + 81773, + 81799, + 81817, + 81839, + 81847, + 81853, + 81869, + 81883, + 81899, + 81901, + 81919, + 81929, + 81931, + 81937, + 81943, + 81953, + 81967, + 81971, + 81973, + 82003, + 82007, + 82009, + 82013, + 82021, + 82031, + 82037, + 82039, + 82051, + 82067, + 82073, + 82129, + 82139, + 82141, + 82153, + 82163, + 82171, + 82183, + 82189, + 82193, + 82207, + 82217, + 82219, + 82223, + 82231, + 82237, + 82241, + 82261, + 82267, + 82279, + 82301, + 82307, + 82339, + 82349, + 82351, + 82361, + 82373, + 82387, + 82393, + 82421, + 82457, + 82463, + 82469, + 82471, + 82483, + 82487, + 82493, + 82499, + 82507, + 82529, + 82531, + 82549, + 82559, + 82561, + 82567, + 82571, + 82591, + 82601, + 82609, + 82613, + 82619, + 82633, + 82651, + 82657, + 82699, + 82721, + 82723, + 82727, + 82729, + 82757, + 82759, + 82763, + 82781, + 82787, + 82793, + 82799, + 82811, + 82813, + 82837, + 82847, + 82883, + 82889, + 82891, + 82903, + 82913, + 82939, + 82963, + 82981, + 82997, + 83003, + 83009, + 83023, + 83047, + 83059, + 83063, + 83071, + 83077, + 83089, + 83093, + 83101, + 83117, + 83137, + 83177, + 83203, + 83207, + 83219, + 83221, + 83227, + 83231, + 83233, + 83243, + 83257, + 83267, + 83269, + 83273, + 83299, + 83311, + 83339, + 83341, + 83357, + 83383, + 83389, + 83399, + 83401, + 83407, + 83417, + 83423, + 83431, + 83437, + 83443, + 83449, + 83459, + 83471, + 83477, + 83497, + 83537, + 83557, + 83561, + 83563, + 83579, + 83591, + 83597, + 83609, + 83617, + 83621, + 83639, + 83641, + 83653, + 83663, + 83689, + 83701, + 83717, + 83719, + 83737, + 83761, + 83773, + 83777, + 83791, + 83813, + 83833, + 83843, + 83857, + 83869, + 83873, + 83891, + 83903, + 83911, + 83921, + 83933, + 83939, + 83969, + 83983, + 83987, + 84011, + 84017, + 84047, + 84053, + 84059, + 84061, + 84067, + 84089, + 84121, + 84127, + 84131, + 84137, + 84143, + 84163, + 84179, + 84181, + 84191, + 84199, + 84211, + 84221, + 84223, + 84229, + 84239, + 84247, + 84263, + 84299, + 84307, + 84313, + 84317, + 84319, + 84347, + 84349, + 84377, + 84389, + 84391, + 84401, + 84407, + 84421, + 84431, + 84437, + 84443, + 84449, + 84457, + 84463, + 84467, + 84481, + 84499, + 84503, + 84509, + 84521, + 84523, + 84533, + 84551, + 84559, + 84589, + 84629, + 84631, + 84649, + 84653, + 84659, + 84673, + 84691, + 84697, + 84701, + 84713, + 84719, + 84731, + 84737, + 84751, + 84761, + 84787, + 84793, + 84809, + 84811, + 84827, + 84857, + 84859, + 84869, + 84871, + 84913, + 84919, + 84947, + 84961, + 84967, + 84977, + 84979, + 84991, + 85009, + 85021, + 85027, + 85037, + 85049, + 85061, + 85081, + 85087, + 85091, + 85093, + 85103, + 85109, + 85121, + 85133, + 85147, + 85159, + 85193, + 85199, + 85201, + 85213, + 85223, + 85229, + 85237, + 85243, + 85247, + 85259, + 85297, + 85303, + 85313, + 85331, + 85333, + 85361, + 85363, + 85369, + 85381, + 85411, + 85427, + 85429, + 85439, + 85447, + 85451, + 85453, + 85469, + 85487, + 85513, + 85517, + 85523, + 85531, + 85549, + 85571, + 85577, + 85597, + 85601, + 85607, + 85619, + 85621, + 85627, + 85639, + 85643, + 85661, + 85667, + 85669, + 85691, + 85703, + 85711, + 85717, + 85733, + 85751, + 85781, + 85793, + 85817, + 85819, + 85829, + 85831, + 85837, + 85843, + 85847, + 85853, + 85889, + 85903, + 85909, + 85931, + 85933, + 85991, + 85999, + 86011, + 86017, + 86027, + 86029, + 86069, + 86077, + 86083, + 86111, + 86113, + 86117, + 86131, + 86137, + 86143, + 86161, + 86171, + 86179, + 86183, + 86197, + 86201, + 86209, + 86239, + 86243, + 86249, + 86257, + 86263, + 86269, + 86287, + 86291, + 86293, + 86297, + 86311, + 86323, + 86341, + 86351, + 86353, + 86357, + 86369, + 86371, + 86381, + 86389, + 86399, + 86413, + 86423, + 86441, + 86453, + 86461, + 86467, + 86477, + 86491, + 86501, + 86509, + 86531, + 86533, + 86539, + 86561, + 86573, + 86579, + 86587, + 86599, + 86627, + 86629, + 86677, + 86689, + 86693, + 86711, + 86719, + 86729, + 86743, + 86753, + 86767, + 86771, + 86783, + 86813, + 86837, + 86843, + 86851, + 86857, + 86861, + 86869, + 86923, + 86927, + 86929, + 86939, + 86951, + 86959, + 86969, + 86981, + 86993, + 87011, + 87013, + 87037, + 87041, + 87049, + 87071, + 87083, + 87103, + 87107, + 87119, + 87121, + 87133, + 87149, + 87151, + 87179, + 87181, + 87187, + 87211, + 87221, + 87223, + 87251, + 87253, + 87257, + 87277, + 87281, + 87293, + 87299, + 87313, + 87317, + 87323, + 87337, + 87359, + 87383, + 87403, + 87407, + 87421, + 87427, + 87433, + 87443, + 87473, + 87481, + 87491, + 87509, + 87511, + 87517, + 87523, + 87539, + 87541, + 87547, + 87553, + 87557, + 87559, + 87583, + 87587, + 87589, + 87613, + 87623, + 87629, + 87631, + 87641, + 87643, + 87649, + 87671, + 87679, + 87683, + 87691, + 87697, + 87701, + 87719, + 87721, + 87739, + 87743, + 87751, + 87767, + 87793, + 87797, + 87803, + 87811, + 87833, + 87853, + 87869, + 87877, + 87881, + 87887, + 87911, + 87917, + 87931, + 87943, + 87959, + 87961, + 87973, + 87977, + 87991, + 88001, + 88003, + 88007, + 88019, + 88037, + 88069, + 88079, + 88093, + 88117, + 88129, + 88169, + 88177, + 88211, + 88223, + 88237, + 88241, + 88259, + 88261, + 88289, + 88301, + 88321, + 88327, + 88337, + 88339, + 88379, + 88397, + 88411, + 88423, + 88427, + 88463, + 88469, + 88471, + 88493, + 88499, + 88513, + 88523, + 88547, + 88589, + 88591, + 88607, + 88609, + 88643, + 88651, + 88657, + 88661, + 88663, + 88667, + 88681, + 88721, + 88729, + 88741, + 88747, + 88771, + 88789, + 88793, + 88799, + 88801, + 88807, + 88811, + 88813, + 88817, + 88819, + 88843, + 88853, + 88861, + 88867, + 88873, + 88883, + 88897, + 88903, + 88919, + 88937, + 88951, + 88969, + 88993, + 88997, + 89003, + 89009, + 89017, + 89021, + 89041, + 89051, + 89057, + 89069, + 89071, + 89083, + 89087, + 89101, + 89107, + 89113, + 89119, + 89123, + 89137, + 89153, + 89189, + 89203, + 89209, + 89213, + 89227, + 89231, + 89237, + 89261, + 89269, + 89273, + 89293, + 89303, + 89317, + 89329, + 89363, + 89371, + 89381, + 89387, + 89393, + 89399, + 89413, + 89417, + 89431, + 89443, + 89449, + 89459, + 89477, + 89491, + 89501, + 89513, + 89519, + 89521, + 89527, + 89533, + 89561, + 89563, + 89567, + 89591, + 89597, + 89599, + 89603, + 89611, + 89627, + 89633, + 89653, + 89657, + 89659, + 89669, + 89671, + 89681, + 89689, + 89753, + 89759, + 89767, + 89779, + 89783, + 89797, + 89809, + 89819, + 89821, + 89833, + 89839, + 89849, + 89867, + 89891, + 89897, + 89899, + 89909, + 89917, + 89923, + 89939, + 89959, + 89963, + 89977, + 89983, + 89989, + 90001, + 90007, + 90011, + 90017, + 90019, + 90023, + 90031, + 90053, + 90059, + 90067, + 90071, + 90073, + 90089, + 90107, + 90121, + 90127, + 90149, + 90163, + 90173, + 90187, + 90191, + 90197, + 90199, + 90203, + 90217, + 90227, + 90239, + 90247, + 90263, + 90271, + 90281, + 90289, + 90313, + 90353, + 90359, + 90371, + 90373, + 90379, + 90397, + 90401, + 90403, + 90407, + 90437, + 90439, + 90469, + 90473, + 90481, + 90499, + 90511, + 90523, + 90527, + 90529, + 90533, + 90547, + 90583, + 90599, + 90617, + 90619, + 90631, + 90641, + 90647, + 90659, + 90677, + 90679, + 90697, + 90703, + 90709, + 90731, + 90749, + 90787, + 90793, + 90803, + 90821, + 90823, + 90833, + 90841, + 90847, + 90863, + 90887, + 90901, + 90907, + 90911, + 90917, + 90931, + 90947, + 90971, + 90977, + 90989, + 90997, + 91009, + 91019, + 91033, + 91079, + 91081, + 91097, + 91099, + 91121, + 91127, + 91129, + 91139, + 91141, + 91151, + 91153, + 91159, + 91163, + 91183, + 91193, + 91199, + 91229, + 91237, + 91243, + 91249, + 91253, + 91283, + 91291, + 91297, + 91303, + 91309, + 91331, + 91367, + 91369, + 91373, + 91381, + 91387, + 91393, + 91397, + 91411, + 91423, + 91433, + 91453, + 91457, + 91459, + 91463, + 91493, + 91499, + 91513, + 91529, + 91541, + 91571, + 91573, + 91577, + 91583, + 91591, + 91621, + 91631, + 91639, + 91673, + 91691, + 91703, + 91711, + 91733, + 91753, + 91757, + 91771, + 91781, + 91801, + 91807, + 91811, + 91813, + 91823, + 91837, + 91841, + 91867, + 91873, + 91909, + 91921, + 91939, + 91943, + 91951, + 91957, + 91961, + 91967, + 91969, + 91997, + 92003, + 92009, + 92033, + 92041, + 92051, + 92077, + 92083, + 92107, + 92111, + 92119, + 92143, + 92153, + 92173, + 92177, + 92179, + 92189, + 92203, + 92219, + 92221, + 92227, + 92233, + 92237, + 92243, + 92251, + 92269, + 92297, + 92311, + 92317, + 92333, + 92347, + 92353, + 92357, + 92363, + 92369, + 92377, + 92381, + 92383, + 92387, + 92399, + 92401, + 92413, + 92419, + 92431, + 92459, + 92461, + 92467, + 92479, + 92489, + 92503, + 92507, + 92551, + 92557, + 92567, + 92569, + 92581, + 92593, + 92623, + 92627, + 92639, + 92641, + 92647, + 92657, + 92669, + 92671, + 92681, + 92683, + 92693, + 92699, + 92707, + 92717, + 92723, + 92737, + 92753, + 92761, + 92767, + 92779, + 92789, + 92791, + 92801, + 92809, + 92821, + 92831, + 92849, + 92857, + 92861, + 92863, + 92867, + 92893, + 92899, + 92921, + 92927, + 92941, + 92951, + 92957, + 92959, + 92987, + 92993, + 93001, + 93047, + 93053, + 93059, + 93077, + 93083, + 93089, + 93097, + 93103, + 93113, + 93131, + 93133, + 93139, + 93151, + 93169, + 93179, + 93187, + 93199, + 93229, + 93239, + 93241, + 93251, + 93253, + 93257, + 93263, + 93281, + 93283, + 93287, + 93307, + 93319, + 93323, + 93329, + 93337, + 93371, + 93377, + 93383, + 93407, + 93419, + 93427, + 93463, + 93479, + 93481, + 93487, + 93491, + 93493, + 93497, + 93503, + 93523, + 93529, + 93553, + 93557, + 93559, + 93563, + 93581, + 93601, + 93607, + 93629, + 93637, + 93683, + 93701, + 93703, + 93719, + 93739, + 93761, + 93763, + 93787, + 93809, + 93811, + 93827, + 93851, + 93871, + 93887, + 93889, + 93893, + 93901, + 93911, + 93913, + 93923, + 93937, + 93941, + 93949, + 93967, + 93971, + 93979, + 93983, + 93997, + 94007, + 94009, + 94033, + 94049, + 94057, + 94063, + 94079, + 94099, + 94109, + 94111, + 94117, + 94121, + 94151, + 94153, + 94169, + 94201, + 94207, + 94219, + 94229, + 94253, + 94261, + 94273, + 94291, + 94307, + 94309, + 94321, + 94327, + 94331, + 94343, + 94349, + 94351, + 94379, + 94397, + 94399, + 94421, + 94427, + 94433, + 94439, + 94441, + 94447, + 94463, + 94477, + 94483, + 94513, + 94529, + 94531, + 94541, + 94543, + 94547, + 94559, + 94561, + 94573, + 94583, + 94597, + 94603, + 94613, + 94621, + 94649, + 94651, + 94687, + 94693, + 94709, + 94723, + 94727, + 94747, + 94771, + 94777, + 94781, + 94789, + 94793, + 94811, + 94819, + 94823, + 94837, + 94841, + 94847, + 94849, + 94873, + 94889, + 94903, + 94907, + 94933, + 94949, + 94951, + 94961, + 94993, + 94999, + 95003, + 95009, + 95021, + 95027, + 95063, + 95071, + 95083, + 95087, + 95089, + 95093, + 95101, + 95107, + 95111, + 95131, + 95143, + 95153, + 95177, + 95189, + 95191, + 95203, + 95213, + 95219, + 95231, + 95233, + 95239, + 95257, + 95261, + 95267, + 95273, + 95279, + 95287, + 95311, + 95317, + 95327, + 95339, + 95369, + 95383, + 95393, + 95401, + 95413, + 95419, + 95429, + 95441, + 95443, + 95461, + 95467, + 95471, + 95479, + 95483, + 95507, + 95527, + 95531, + 95539, + 95549, + 95561, + 95569, + 95581, + 95597, + 95603, + 95617, + 95621, + 95629, + 95633, + 95651, + 95701, + 95707, + 95713, + 95717, + 95723, + 95731, + 95737, + 95747, + 95773, + 95783, + 95789, + 95791, + 95801, + 95803, + 95813, + 95819, + 95857, + 95869, + 95873, + 95881, + 95891, + 95911, + 95917, + 95923, + 95929, + 95947, + 95957, + 95959, + 95971, + 95987, + 95989, + 96001, + 96013, + 96017, + 96043, + 96053, + 96059, + 96079, + 96097, + 96137, + 96149, + 96157, + 96167, + 96179, + 96181, + 96199, + 96211, + 96221, + 96223, + 96233, + 96259, + 96263, + 96269, + 96281, + 96289, + 96293, + 96323, + 96329, + 96331, + 96337, + 96353, + 96377, + 96401, + 96419, + 96431, + 96443, + 96451, + 96457, + 96461, + 96469, + 96479, + 96487, + 96493, + 96497, + 96517, + 96527, + 96553, + 96557, + 96581, + 96587, + 96589, + 96601, + 96643, + 96661, + 96667, + 96671, + 96697, + 96703, + 96731, + 96737, + 96739, + 96749, + 96757, + 96763, + 96769, + 96779, + 96787, + 96797, + 96799, + 96821, + 96823, + 96827, + 96847, + 96851, + 96857, + 96893, + 96907, + 96911, + 96931, + 96953, + 96959, + 96973, + 96979, + 96989, + 96997, + 97001, + 97003, + 97007, + 97021, + 97039, + 97073, + 97081, + 97103, + 97117, + 97127, + 97151, + 97157, + 97159, + 97169, + 97171, + 97177, + 97187, + 97213, + 97231, + 97241, + 97259, + 97283, + 97301, + 97303, + 97327, + 97367, + 97369, + 97373, + 97379, + 97381, + 97387, + 97397, + 97423, + 97429, + 97441, + 97453, + 97459, + 97463, + 97499, + 97501, + 97511, + 97523, + 97547, + 97549, + 97553, + 97561, + 97571, + 97577, + 97579, + 97583, + 97607, + 97609, + 97613, + 97649, + 97651, + 97673, + 97687, + 97711, + 97729, + 97771, + 97777, + 97787, + 97789, + 97813, + 97829, + 97841, + 97843, + 97847, + 97849, + 97859, + 97861, + 97871, + 97879, + 97883, + 97919, + 97927, + 97931, + 97943, + 97961, + 97967, + 97973, + 97987, + 98009, + 98011, + 98017, + 98041, + 98047, + 98057, + 98081, + 98101, + 98123, + 98129, + 98143, + 98179, + 98207, + 98213, + 98221, + 98227, + 98251, + 98257, + 98269, + 98297, + 98299, + 98317, + 98321, + 98323, + 98327, + 98347, + 98369, + 98377, + 98387, + 98389, + 98407, + 98411, + 98419, + 98429, + 98443, + 98453, + 98459, + 98467, + 98473, + 98479, + 98491, + 98507, + 98519, + 98533, + 98543, + 98561, + 98563, + 98573, + 98597, + 98621, + 98627, + 98639, + 98641, + 98663, + 98669, + 98689, + 98711, + 98713, + 98717, + 98729, + 98731, + 98737, + 98773, + 98779, + 98801, + 98807, + 98809, + 98837, + 98849, + 98867, + 98869, + 98873, + 98887, + 98893, + 98897, + 98899, + 98909, + 98911, + 98927, + 98929, + 98939, + 98947, + 98953, + 98963, + 98981, + 98993, + 98999, + 99013, + 99017, + 99023, + 99041, + 99053, + 99079, + 99083, + 99089, + 99103, + 99109, + 99119, + 99131, + 99133, + 99137, + 99139, + 99149, + 99173, + 99181, + 99191, + 99223, + 99233, + 99241, + 99251, + 99257, + 99259, + 99277, + 99289, + 99317, + 99347, + 99349, + 99367, + 99371, + 99377, + 99391, + 99397, + 99401, + 99409, + 99431, + 99439, + 99469, + 99487, + 99497, + 99523, + 99527, + 99529, + 99551, + 99559, + 99563, + 99571, + 99577, + 99581, + 99607, + 99611, + 99623, + 99643, + 99661, + 99667, + 99679, + 99689, + 99707, + 99709, + 99713, + 99719, + 99721, + 99733, + 99761, + 99767, + 99787, + 99793, + 99809, + 99817, + 99823, + 99829, + 99833, + 99839, + 99859, + 99871, + 99877, + 99881, + 99901, + 99907, + 99923, + 99929, + 99961, + 99971, + 99989, + 99991, + 100003, + 100019, + 100043, + 100049, + 100057, + 100069, + 100103, + 100109, + 100129, + 100151, + 100153, + 100169, + 100183, + 100189, + 100193, + 100207, + 100213, + 100237, + 100267, + 100271, + 100279, + 100291, + 100297, + 100313, + 100333, + 100343, + 100357, + 100361, + 100363, + 100379, + 100391, + 100393, + 100403, + 100411, + 100417, + 100447, + 100459, + 100469, + 100483, + 100493, + 100501, + 100511, + 100517, + 100519, + 100523, + 100537, + 100547, + 100549, + 100559, + 100591, + 100609, + 100613, + 100621, + 100649, + 100669, + 100673, + 100693, + 100699, + 100703, + 100733, + 100741, + 100747, + 100769, + 100787, + 100799, + 100801, + 100811, + 100823, + 100829, + 100847, + 100853, + 100907, + 100913, + 100927, + 100931, + 100937, + 100943, + 100957, + 100981, + 100987, + 100999, + 101009, + 101021, + 101027, + 101051, + 101063, + 101081, + 101089, + 101107, + 101111, + 101113, + 101117, + 101119, + 101141, + 101149, + 101159, + 101161, + 101173, + 101183, + 101197, + 101203, + 101207, + 101209, + 101221, + 101267, + 101273, + 101279, + 101281, + 101287, + 101293, + 101323, + 101333, + 101341, + 101347, + 101359, + 101363, + 101377, + 101383, + 101399, + 101411, + 101419, + 101429, + 101449, + 101467, + 101477, + 101483, + 101489, + 101501, + 101503, + 101513, + 101527, + 101531, + 101533, + 101537, + 101561, + 101573, + 101581, + 101599, + 101603, + 101611, + 101627, + 101641, + 101653, + 101663, + 101681, + 101693, + 101701, + 101719, + 101723, + 101737, + 101741, + 101747, + 101749, + 101771, + 101789, + 101797, + 101807, + 101833, + 101837, + 101839, + 101863, + 101869, + 101873, + 101879, + 101891, + 101917, + 101921, + 101929, + 101939, + 101957, + 101963, + 101977, + 101987, + 101999, + 102001, + 102013, + 102019, + 102023, + 102031, + 102043, + 102059, + 102061, + 102071, + 102077, + 102079, + 102101, + 102103, + 102107, + 102121, + 102139, + 102149, + 102161, + 102181, + 102191, + 102197, + 102199, + 102203, + 102217, + 102229, + 102233, + 102241, + 102251, + 102253, + 102259, + 102293, + 102299, + 102301, + 102317, + 102329, + 102337, + 102359, + 102367, + 102397, + 102407, + 102409, + 102433, + 102437, + 102451, + 102461, + 102481, + 102497, + 102499, + 102503, + 102523, + 102533, + 102539, + 102547, + 102551, + 102559, + 102563, + 102587, + 102593, + 102607, + 102611, + 102643, + 102647, + 102653, + 102667, + 102673, + 102677, + 102679, + 102701, + 102761, + 102763, + 102769, + 102793, + 102797, + 102811, + 102829, + 102841, + 102859, + 102871, + 102877, + 102881, + 102911, + 102913, + 102929, + 102931, + 102953, + 102967, + 102983, + 103001, + 103007, + 103043, + 103049, + 103067, + 103069, + 103079, + 103087, + 103091, + 103093, + 103099, + 103123, + 103141, + 103171, + 103177, + 103183, + 103217, + 103231, + 103237, + 103289, + 103291, + 103307, + 103319, + 103333, + 103349, + 103357, + 103387, + 103391, + 103393, + 103399, + 103409, + 103421, + 103423, + 103451, + 103457, + 103471, + 103483, + 103511, + 103529, + 103549, + 103553, + 103561, + 103567, + 103573, + 103577, + 103583, + 103591, + 103613, + 103619, + 103643, + 103651, + 103657, + 103669, + 103681, + 103687, + 103699, + 103703, + 103723, + 103769, + 103787, + 103801, + 103811, + 103813, + 103837, + 103841, + 103843, + 103867, + 103889, + 103903, + 103913, + 103919, + 103951, + 103963, + 103967, + 103969, + 103979, + 103981, + 103991, + 103993, + 103997, + 104003, + 104009, + 104021, + 104033, + 104047, + 104053, + 104059, + 104087, + 104089, + 104107, + 104113, + 104119, + 104123, + 104147, + 104149, + 104161, + 104173, + 104179, + 104183, + 104207, + 104231, + 104233, + 104239, + 104243, + 104281, + 104287, + 104297, + 104309, + 104311, + 104323, + 104327, + 104347, + 104369, + 104381, + 104383, + 104393, + 104399, + 104417, + 104459, + 104471, + 104473, + 104479, + 104491, + 104513, + 104527, + 104537, + 104543, + 104549, + 104551, + 104561, + 104579, + 104593, + 104597, + 104623, + 104639, + 104651, + 104659, + 104677, + 104681, + 104683, + 104693, + 104701, + 104707, + 104711, + 104717, + 104723, + 104729, ) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/number.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/number.pyi index f8680bf8..fbb063e1 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/number.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/number.pyi @@ -1,19 +1,25 @@ from typing import List, Optional, Callable - def ceil_div(n: int, d: int) -> int: ... -def size (N: int) -> int: ... -def getRandomInteger(N: int, randfunc: Optional[Callable]=None) -> int: ... -def getRandomRange(a: int, b: int, randfunc: Optional[Callable]=None) -> int: ... -def getRandomNBitInteger(N: int, randfunc: Optional[Callable]=None) -> int: ... -def GCD(x: int,y: int) -> int: ... +def size(N: int) -> int: ... +def getRandomInteger(N: int, randfunc: Optional[Callable] = None) -> int: ... +def getRandomRange(a: int, b: int, randfunc: Optional[Callable] = None) -> int: ... +def getRandomNBitInteger(N: int, randfunc: Optional[Callable] = None) -> int: ... +def GCD(x: int, y: int) -> int: ... def inverse(u: int, v: int) -> int: ... -def getPrime(N: int, randfunc: Optional[Callable]=None) -> int: ... -def getStrongPrime(N: int, e: Optional[int]=0, false_positive_prob: Optional[float]=1e-6, randfunc: Optional[Callable]=None) -> int: ... -def isPrime(N: int, false_positive_prob: Optional[float]=1e-6, randfunc: Optional[Callable]=None) -> bool: ... -def long_to_bytes(n: int, blocksize: Optional[int]=0) -> bytes: ... +def getPrime(N: int, randfunc: Optional[Callable] = None) -> int: ... +def getStrongPrime( + N: int, + e: Optional[int] = 0, + false_positive_prob: Optional[float] = 1e-6, + randfunc: Optional[Callable] = None, +) -> int: ... +def isPrime( + N: int, false_positive_prob: Optional[float] = 1e-6, randfunc: Optional[Callable] = None +) -> bool: ... +def long_to_bytes(n: int, blocksize: Optional[int] = 0) -> bytes: ... def bytes_to_long(s: bytes) -> int: ... -def long2str(n: int, blocksize: Optional[int]=0) -> bytes: ... +def long2str(n: int, blocksize: Optional[int] = 0) -> bytes: ... def str2long(s: bytes) -> int: ... sieve_base: List[int] diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/py3compat.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/py3compat.py index 3294b66b..592861d3 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/py3compat.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/py3compat.py @@ -63,123 +63,129 @@ if sys.version_info[0] == 2: - def b(s): - return s - def bchr(s): - return chr(s) - def bstr(s): - return str(s) - def bord(s): - return ord(s) - def tobytes(s, encoding="latin-1"): - if isinstance(s, unicode): - return s.encode(encoding) - elif isinstance(s, str): - return s - elif isinstance(s, bytearray): - return bytes(s) - elif isinstance(s, memoryview): - return s.tobytes() - else: - return ''.join(s) - def tostr(bs): - return bs - def byte_string(s): - return isinstance(s, str) - - # In Python 2, a memoryview does not support concatenation - def concat_buffers(a, b): - if isinstance(a, memoryview): - a = a.tobytes() - if isinstance(b, memoryview): - b = b.tobytes() - return a + b - - from StringIO import StringIO - BytesIO = StringIO - - from sys import maxint - - iter_range = xrange - - def is_native_int(x): - return isinstance(x, (int, long)) - - def is_string(x): - return isinstance(x, basestring) - - def is_bytes(x): - return isinstance(x, str) or \ - isinstance(x, bytearray) or \ - isinstance(x, memoryview) - - ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()}) - - FileNotFoundError = IOError + + def b(s): + return s + + def bchr(s): + return chr(s) + + def bstr(s): + return str(s) + + def bord(s): + return ord(s) + + def tobytes(s, encoding="latin-1"): + if isinstance(s, unicode): + return s.encode(encoding) + elif isinstance(s, str): + return s + elif isinstance(s, bytearray): + return bytes(s) + elif isinstance(s, memoryview): + return s.tobytes() + else: + return "".join(s) + + def tostr(bs): + return bs + + def byte_string(s): + return isinstance(s, str) + + # In Python 2, a memoryview does not support concatenation + def concat_buffers(a, b): + if isinstance(a, memoryview): + a = a.tobytes() + if isinstance(b, memoryview): + b = b.tobytes() + return a + b + + from StringIO import StringIO + + BytesIO = StringIO + + iter_range = xrange + + def is_native_int(x): + return isinstance(x, (int, long)) + + def is_string(x): + return isinstance(x, basestring) + + def is_bytes(x): + return isinstance(x, str) or isinstance(x, bytearray) or isinstance(x, memoryview) + + ABC = abc.ABCMeta("ABC", (object,), {"__slots__": ()}) + + FileNotFoundError = IOError else: - def b(s): - return s.encode("latin-1") # utf-8 would cause some side-effects we don't want - def bchr(s): - return bytes([s]) - def bstr(s): - if isinstance(s,str): - return bytes(s,"latin-1") - else: - return bytes(s) - def bord(s): - return s - def tobytes(s, encoding="latin-1"): - if isinstance(s, bytes): - return s - elif isinstance(s, bytearray): - return bytes(s) - elif isinstance(s,str): - return s.encode(encoding) - elif isinstance(s, memoryview): - return s.tobytes() - else: - return bytes([s]) - def tostr(bs): - return bs.decode("latin-1") - def byte_string(s): - return isinstance(s, bytes) - - def concat_buffers(a, b): - return a + b - - from io import BytesIO - from io import StringIO - from sys import maxsize as maxint - - iter_range = range - - def is_native_int(x): - return isinstance(x, int) - - def is_string(x): - return isinstance(x, str) - - def is_bytes(x): - return isinstance(x, bytes) or \ - isinstance(x, bytearray) or \ - isinstance(x, memoryview) - - from abc import ABC - - FileNotFoundError = FileNotFoundError + + def b(s): + return s.encode("latin-1") # utf-8 would cause some side-effects we don't want + + def bchr(s): + return bytes([s]) + + def bstr(s): + if isinstance(s, str): + return bytes(s, "latin-1") + else: + return bytes(s) + + def bord(s): + return s + + def tobytes(s, encoding="latin-1"): + if isinstance(s, bytes): + return s + elif isinstance(s, bytearray): + return bytes(s) + elif isinstance(s, str): + return s.encode(encoding) + elif isinstance(s, memoryview): + return s.tobytes() + else: + return bytes([s]) + + def tostr(bs): + return bs.decode("latin-1") + + def byte_string(s): + return isinstance(s, bytes) + + def concat_buffers(a, b): + return a + b + + from io import StringIO + + iter_range = range + + def is_native_int(x): + return isinstance(x, int) + + def is_string(x): + return isinstance(x, str) + + def is_bytes(x): + return isinstance(x, bytes) or isinstance(x, bytearray) or isinstance(x, memoryview) + + FileNotFoundError = FileNotFoundError def _copy_bytes(start, end, seq): - """Return an immutable copy of a sequence (byte string, byte array, memoryview) - in a certain interval [start:seq]""" - - if isinstance(seq, memoryview): - return seq[start:end].tobytes() - elif isinstance(seq, bytearray): - return bytes(seq[start:end]) - else: - return seq[start:end] + """Return an immutable copy of a sequence (byte string, byte array, memoryview) + in a certain interval [start:seq]""" + + if isinstance(seq, memoryview): + return seq[start:end].tobytes() + elif isinstance(seq, bytearray): + return bytes(seq[start:end]) + else: + return seq[start:end] + del sys del abc diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/py3compat.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/py3compat.pyi index 74e04a2b..0a2e1375 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/py3compat.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/py3compat.pyi @@ -10,24 +10,20 @@ def bord(s: bytes) -> int: ... def tobytes(s: Union[bytes, str]) -> bytes: ... def tostr(b: bytes) -> str: ... def bytestring(x: Any) -> bool: ... - def is_native_int(s: Any) -> bool: ... def is_string(x: Any) -> bool: ... def is_bytes(x: Any) -> bool: ... - def BytesIO(b: bytes) -> IO[bytes]: ... def StringIO(s: str) -> IO[str]: ... if sys.version_info[0] == 2: - from sys import maxint - iter_range = xrange + iter_range = xrange else: - from sys import maxsize as maxint - iter_range = range + iter_range = range class FileNotFoundError: - def __init__(self, err: int, msg: str, filename: str) -> None: - pass + def __init__(self, err: int, msg: str, filename: str) -> None: + pass def _copy_bytes(start: Optional[int], end: Optional[int], seq: Buffer) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/strxor.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/strxor.py index 6b161552..a6d03499 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/strxor.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/strxor.py @@ -28,13 +28,18 @@ # POSSIBILITY OF SUCH DAMAGE. # =================================================================== -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t, - create_string_buffer, get_raw_buffer, - c_uint8_ptr, is_writeable_buffer) +from Cryptodome.Util._raw_api import ( + load_pycryptodome_raw_lib, + c_size_t, + create_string_buffer, + get_raw_buffer, + c_uint8_ptr, + is_writeable_buffer, +) _raw_strxor = load_pycryptodome_raw_lib( - "Cryptodome.Util._strxor", - """ + "Cryptodome.Util._strxor", + """ void strxor(const uint8_t *in1, const uint8_t *in2, uint8_t *out, size_t len); @@ -42,105 +47,111 @@ uint8_t c, uint8_t *out, size_t len); - """) + """, +) def strxor(term1, term2, output=None): - """From two byte strings of equal length, - create a third one which is the byte-by-byte XOR of the two. - - Args: - term1 (bytes/bytearray/memoryview): - The first byte string to XOR. - term2 (bytes/bytearray/memoryview): - The second byte string to XOR. - output (bytearray/memoryview): - The location where the result will be written to. - It must have the same length as ``term1`` and ``term2``. - If ``None``, the result is returned. - :Return: - If ``output`` is ``None``, a new byte string with the result. - Otherwise ``None``. - - .. note:: - ``term1`` and ``term2`` must have the same length. - """ - - if len(term1) != len(term2): - raise ValueError("Only byte strings of equal length can be xored") - - if output is None: - result = create_string_buffer(len(term1)) - else: - # Note: output may overlap with either input - result = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(term1) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(term1)) - - _raw_strxor.strxor(c_uint8_ptr(term1), - c_uint8_ptr(term2), - c_uint8_ptr(result), - c_size_t(len(term1))) - - if output is None: - return get_raw_buffer(result) - else: - return None + """From two byte strings of equal length, + create a third one which is the byte-by-byte XOR of the two. + + Args: + term1 (bytes/bytearray/memoryview): + The first byte string to XOR. + term2 (bytes/bytearray/memoryview): + The second byte string to XOR. + output (bytearray/memoryview): + The location where the result will be written to. + It must have the same length as ``term1`` and ``term2``. + If ``None``, the result is returned. + :Return: + If ``output`` is ``None``, a new byte string with the result. + Otherwise ``None``. + + .. note:: + ``term1`` and ``term2`` must have the same length. + """ + + if len(term1) != len(term2): + raise ValueError("Only byte strings of equal length can be xored") + + if output is None: + result = create_string_buffer(len(term1)) + else: + # Note: output may overlap with either input + result = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(term1) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(term1), + ) + + _raw_strxor.strxor( + c_uint8_ptr(term1), + c_uint8_ptr(term2), + c_uint8_ptr(result), + c_size_t(len(term1)), + ) + + if output is None: + return get_raw_buffer(result) + else: + return None def strxor_c(term, c, output=None): - """From a byte string, create a second one of equal length - where each byte is XOR-red with the same value. - - Args: - term(bytes/bytearray/memoryview): - The byte string to XOR. - c (int): - Every byte in the string will be XOR-ed with this value. - It must be between 0 and 255 (included). - output (None or bytearray/memoryview): - The location where the result will be written to. - It must have the same length as ``term``. - If ``None``, the result is returned. - - Return: - If ``output`` is ``None``, a new ``bytes`` string with the result. - Otherwise ``None``. - """ - - if not 0 <= c < 256: - raise ValueError("c must be in range(256)") - - if output is None: - result = create_string_buffer(len(term)) - else: - # Note: output may overlap with either input - result = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(term) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(term)) - - _raw_strxor.strxor_c(c_uint8_ptr(term), - c, - c_uint8_ptr(result), - c_size_t(len(term)) - ) - - if output is None: - return get_raw_buffer(result) - else: - return None + """From a byte string, create a second one of equal length + where each byte is XOR-red with the same value. + + Args: + term(bytes/bytearray/memoryview): + The byte string to XOR. + c (int): + Every byte in the string will be XOR-ed with this value. + It must be between 0 and 255 (included). + output (None or bytearray/memoryview): + The location where the result will be written to. + It must have the same length as ``term``. + If ``None``, the result is returned. + + Return: + If ``output`` is ``None``, a new ``bytes`` string with the result. + Otherwise ``None``. + """ + + if not 0 <= c < 256: + raise ValueError("c must be in range(256)") + + if output is None: + result = create_string_buffer(len(term)) + else: + # Note: output may overlap with either input + result = output + + if not is_writeable_buffer(output): + raise TypeError("output must be a bytearray or a writeable memoryview") + + if len(term) != len(output): + raise ValueError( + "output must have the same length as the input (%d bytes)" % len(term), + ) + + _raw_strxor.strxor_c( + c_uint8_ptr(term), + c, + c_uint8_ptr(result), + c_size_t(len(term)), + ) + + if output is None: + return get_raw_buffer(result) + else: + return None def _strxor_direct(term1, term2, result): - """Very fast XOR - check conditions!""" - _raw_strxor.strxor(term1, term2, result, c_size_t(len(term1))) + """Very fast XOR - check conditions!""" + _raw_strxor.strxor(term1, term2, result, c_size_t(len(term1))) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/strxor.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/strxor.pyi index ca896f3b..d1cbcd82 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/strxor.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/Util/strxor.pyi @@ -2,5 +2,5 @@ from typing import Union, Optional Buffer = Union[bytes, bytearray, memoryview] -def strxor(term1: bytes, term2: bytes, output: Optional[Buffer]=...) -> bytes: ... -def strxor_c(term: bytes, c: int, output: Optional[Buffer]=...) -> bytes: ... +def strxor(term1: bytes, term2: bytes, output: Optional[Buffer] = ...) -> bytes: ... +def strxor_c(term: bytes, c: int, output: Optional[Buffer] = ...) -> bytes: ... diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/__init__.py b/addon/globalPlugins/remoteClient/lib64/Cryptodome/__init__.py index 1fc2db90..46857578 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/__init__.py +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/__init__.py @@ -1,6 +1,14 @@ -__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util', 'Signature', - 'IO', 'Math'] +__all__ = [ + "Cipher", + "Hash", + "Protocol", + "PublicKey", + "Util", + "Signature", + "IO", + "Math", +] -version_info = (3, 23, '0') +version_info = (3, 23, "0") __version__ = ".".join([str(x) for x in version_info]) diff --git a/addon/globalPlugins/remoteClient/lib64/Cryptodome/__init__.pyi b/addon/globalPlugins/remoteClient/lib64/Cryptodome/__init__.pyi index bc73446d..9fb3d057 100644 --- a/addon/globalPlugins/remoteClient/lib64/Cryptodome/__init__.pyi +++ b/addon/globalPlugins/remoteClient/lib64/Cryptodome/__init__.pyi @@ -1,4 +1,4 @@ from typing import Tuple, Union -version_info : Tuple[int, int, Union[int, str]] -__version__ : str +version_info: Tuple[int, int, Union[int, str]] +__version__: str diff --git a/addon/globalPlugins/remoteClient/nvda_patcher.py b/addon/globalPlugins/remoteClient/nvda_patcher.py index 2349c871..440950f7 100755 --- a/addon/globalPlugins/remoteClient/nvda_patcher.py +++ b/addon/globalPlugins/remoteClient/nvda_patcher.py @@ -177,7 +177,12 @@ def beep(self, hz, length, left=50, right=50): def handle_decide_beep(self, hz, length, left=50, right=50, isSpeechBeepCommand=False): self.call_callbacks( - "beep", hz=hz, length=length, left=left, right=right, isSpeechBeepCommand=isSpeechBeepCommand + "beep", + hz=hz, + length=length, + left=left, + right=right, + isSpeechBeepCommand=isSpeechBeepCommand, ) return True diff --git a/addon/globalPlugins/remoteClient/server.py b/addon/globalPlugins/remoteClient/server.py index beab7979..fb98274e 100755 --- a/addon/globalPlugins/remoteClient/server.py +++ b/addon/globalPlugins/remoteClient/server.py @@ -30,10 +30,14 @@ def __init__(self, port, password, bind_host="", bind_host6="[::]", UPNP=False): self.invalid_join_attempts: dict[str, InvalidJoinAttempt] = {} self.running = False self.server_socket = self.create_server_socket( - socket.AF_INET, socket.SOCK_STREAM, bind_addr=(bind_host, self.port) + socket.AF_INET, + socket.SOCK_STREAM, + bind_addr=(bind_host, self.port), ) self.server_socket6 = self.create_server_socket( - socket.AF_INET6, socket.SOCK_STREAM, bind_addr=(bind_host6, self.port) + socket.AF_INET6, + socket.SOCK_STREAM, + bind_addr=(bind_host6, self.port), ) self.upnp = None if UPNP: @@ -61,7 +65,10 @@ def run(self): log.info("TeleNVDA direct connection server started") while self.running: r, w, e = select.select( - self.client_sockets + [self.server_socket, self.server_socket6], [], self.client_sockets, 60 + self.client_sockets + [self.server_socket, self.server_socket6], + [], + self.client_sockets, + 60, ) if not self.running: break @@ -73,7 +80,13 @@ def run(self): if time.monotonic() - self.last_ping_time >= self.PING_TIME: if self.upnp: self.upnp.addportmapping( - self.port, "TCP", self.upnp.lanaddr, self.port, "TeleNVDA", "", 3600 + self.port, + "TCP", + self.upnp.lanaddr, + self.port, + "TeleNVDA", + "", + 3600, ) for client in self.clients.values(): if client.authenticated: diff --git a/addon/globalPlugins/remoteClient/session.py b/addon/globalPlugins/remoteClient/session.py index 47f29e47..a7da7fdc 100755 --- a/addon/globalPlugins/remoteClient/session.py +++ b/addon/globalPlugins/remoteClient/session.py @@ -1,325 +1,360 @@ -import sys -import os -import globalVars -from .transport import TransportEvents -from . import connection_info -import gui -import speech -import ui -import braille -import buildVersion -from logHandler import log -from . import configuration -from . import nvda_patcher -from . import RelayTransport -from collections import defaultdict -from . import connection_info -from . import cues -import hashlib -import addonHandler -try: - addonHandler.initTranslation() -except addonHandler.AddonError: - log.warning( - "Unable to initialise translations. This may be because the addon is running from NVDA scratchpad." - ) -if not ( - buildVersion.version_year >= 2021 or - (buildVersion.version_year == 2020 and buildVersion.version_major >= 2) -): - # NVDA versions newer than 2020.2 have a _CancellableSpeechCommand which should be ignored by TeleNVDA - # For older versions, we create a dummy command that won't cause existing commands to be ignored. - class _DummyCommand(speech.commands.SpeechCommand): pass - speech.commands._CancellableSpeechCommand = _DummyCommand - - -EXCLUDED_SPEECH_COMMANDS = ( - speech.commands.BaseCallbackCommand, - # _CancellableSpeechCommands are not designed to be reported and are used internally by NVDA. (#230) - speech.commands._CancellableSpeechCommand, -) - -class RemoteSession: - - def __init__(self, local_machine, transport: RelayTransport): - self.local_machine = local_machine - self.patcher = None - self.transport = transport - self.transport.callback_manager.register_callback('msg_version_mismatch', self.handle_version_mismatch) - self.transport.callback_manager.register_callback('msg_motd', self.handle_motd) - self.client_count = 1 - - def handle_version_mismatch(self, **kwargs): - #translators: Message for version mismatch - message = _("""The version of the relay server which you have connected to is not compatible with this version of the Remote Client. -Please either use a different server or upgrade your version of the addon.""") - ui.message(message) - self.transport.close() - - def handle_motd(self, motd: str, force_display=False, **kwargs): - displayOnce = configuration.get_config()['ui']['display_motd_once'] - if (force_display and not displayOnce) or self.should_display_motd(motd): - gui.messageBox(parent=gui.mainFrame, caption=_("Message of the Day"), message=motd) - - def should_display_motd(self, motd: str): - conf = configuration.get_config() - host, port = self.transport.address - host = host.lower() - address = '{host}:{port}'.format(host=host, port=port) - motdBytes = motd.encode('utf-8', errors='surrogatepass') - hashed = hashlib.sha1(motdBytes).hexdigest() - current = conf['seen_motds'].get(address, "") - if current == hashed: - return False - conf['seen_motds'][address] = hashed - conf.write() - return True - -class SlaveSession(RemoteSession): - """Session that runs on the slave and manages state.""" - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.transport.callback_manager.register_callback('msg_client_joined', self.handle_client_connected) - self.transport.callback_manager.register_callback('msg_client_left', self.handle_client_disconnected) - self.transport.callback_manager.register_callback('msg_key', self.local_machine.send_key) - self.masters = defaultdict(dict) - self.master_display_sizes = [] - - self.transport.callback_manager.register_callback('msg_index', self.recv_index) - self.transport.callback_manager.register_callback(TransportEvents.CLOSING, self.handle_transport_closing) - self.patcher = nvda_patcher.NVDASlavePatcher() - self.patch_callbacks_added = False - self.transport.callback_manager.register_callback('msg_channel_joined', self.handle_channel_joined) - self.transport.callback_manager.register_callback('msg_set_clipboard_text', self.local_machine.set_clipboard_text) - self.transport.callback_manager.register_callback('msg_file_transfer', self.local_machine.file_transfer) - self.transport.callback_manager.register_callback('msg_set_braille_info', self.handle_braille_info) - self.transport.callback_manager.register_callback('msg_set_display_size', self.set_display_size) - if buildVersion.version_year >= 2023 and buildVersion.version_year < 2025: - braille.filter_displaySize.register(self.local_machine.handle_filter_displaySize) - if buildVersion.version_year >= 2025: - braille.filter_displayDimensions.register(self.local_machine.handle_filter_displayDimensions) - self.transport.callback_manager.register_callback('msg_braille_input', self.local_machine.braille_input) - self.transport.callback_manager.register_callback('msg_send_SAS', self.local_machine.send_SAS) - - - def get_connection_info(self): - hostname, port = self.transport.address - key = self.transport.channel - encryption_key = self.transport.encryption_key - return connection_info.ConnectionInfo(hostname=hostname, port=port, key=key, mode='slave', encryption_key=encryption_key) - - def handle_client_connected(self, client=None, **kwargs): - self.patcher.patch() - if not self.patch_callbacks_added: - self.add_patch_callbacks() - self.patch_callbacks_added = True - cues.client_connected() - if client['connection_type'] == 'master': - self.masters[client['id']]['active'] = True - self.client_count += 1 - - def handle_channel_joined(self, channel=None, clients=None, origin=None, **kwargs): - if clients is None: - clients = [] - for client in clients: - self.handle_client_connected(client) - self.client_count = len(clients)+1 - - def handle_transport_closing(self): - self.patcher.unpatch() - if self.patch_callbacks_added: - self.remove_patch_callbacks() - self.patch_callbacks_added = False - - def handle_transport_disconnected(self): - cues.client_connected() - self.patcher.unpatch() - - def handle_client_disconnected(self, client=None, **kwargs): - cues.client_disconnected() - if client['connection_type'] == 'master': - del self.masters[client['id']] - if not self.masters: - self.patcher.unpatch() - self.client_count -= 1 - - def set_display_size(self, sizes=None, **kwargs): - self.master_display_sizes = sizes if sizes else [info.get("braille_numCells", 0) for info in self.masters.values()] - self.local_machine.set_braille_display_size(self.master_display_sizes) - - def handle_braille_info(self, name=None, numCells=0, origin=None, **kwargs): - if not self.masters.get(origin): - return - self.masters[origin]['braille_name'] = name - self.masters[origin]['braille_numCells'] = numCells - self.set_display_size() - - def _get_patcher_callbacks(self): - return ( - ('speak', self.speak), - ('beep', self.beep), - ('wave', self.playWaveFile), - ('cancel_speech', self.cancel_speech), - ('pause_speech', self.pause_speech), - ('display', self.display), - ('set_display', self.set_display_size) - ) - - def add_patch_callbacks(self): - patcher_callbacks = self._get_patcher_callbacks() - for event, callback in patcher_callbacks: - self.patcher.register_callback(event, callback) - - def remove_patch_callbacks(self): - patcher_callbacks = self._get_patcher_callbacks() - for event, callback in patcher_callbacks: - self.patcher.unregister_callback(event, callback) - - def _filterUnsupportedSpeechCommands(self, speechSequence): - return list([ - item for item in speechSequence - if not isinstance(item, EXCLUDED_SPEECH_COMMANDS) - ]) - - def speak(self, speechSequence, priority): - self.transport.send( - type="speak", - sequence=self._filterUnsupportedSpeechCommands(speechSequence), - priority=priority - ) - - def cancel_speech(self): - self.transport.send(type="cancel") - - def pause_speech(self, switch): - self.transport.send(type="pause_speech", switch=switch) - - def beep(self, hz, length, left=50, right=50, **kwargs): - self.transport.send(type='tone', hz=hz, length=length, left=left, right=right, **kwargs) - - def playWaveFile(self, **kwargs): - """This machine played a sound, send it to Master machine""" - kwargs.update({ - # nvWave.playWaveFile should always be asynchronous when called from TeleNVDA, so always send 'True' - # Version 2.2 requires 'async' keyword. - 'async': True, - # Version 2.3 onwards. Not currently used, but matches arguments for nvWave.playWaveFile. - # Including it allows for forward compatibility if requirements change. - 'asynchronous': True, - 'fileName': kwargs['fileName'].replace(globalVars.appArgs.configPath, "%configpath%").replace(sys.prefix if hasattr(sys, 'frozen') else os.path.dirname(sys.modules['__main__'].__file__), "%appdir%"), - }) - self.transport.send(type='wave', **kwargs) - - def display(self, cells): - # Only send braille data when there are controlling machines with a braille display - if self.has_braille_masters(): - self.transport.send(type="display", cells=cells) - - def has_braille_masters(self): - return bool([i for i in self.master_display_sizes if i>0]) - - def recv_index(self, index=None, **kwargs): - pass # speech index approach changed in 2019.3 - -class MasterSession(RemoteSession): - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.slaves = defaultdict(dict) - self.patcher = nvda_patcher.NVDAMasterPatcher() - self.patch_callbacks_added = False - self.transport.callback_manager.register_callback('msg_speak', self.local_machine.speak) - self.transport.callback_manager.register_callback('msg_cancel', self.local_machine.cancel_speech) - self.transport.callback_manager.register_callback('msg_pause_speech', self.local_machine.pause_speech) - self.transport.callback_manager.register_callback('msg_tone', self.local_machine.beep) - self.transport.callback_manager.register_callback('msg_wave', self.handle_play_wave) - self.transport.callback_manager.register_callback('msg_display', self.local_machine.display) - self.transport.callback_manager.register_callback('msg_nvda_not_connected', self.handle_nvda_not_connected) - self.transport.callback_manager.register_callback('msg_client_joined', self.handle_client_connected) - self.transport.callback_manager.register_callback('msg_client_left', self.handle_client_disconnected) - self.transport.callback_manager.register_callback('msg_channel_joined', self.handle_channel_joined) - self.transport.callback_manager.register_callback('msg_set_clipboard_text', self.local_machine.set_clipboard_text) - self.transport.callback_manager.register_callback('msg_file_transfer', self.local_machine.file_transfer) - self.transport.callback_manager.register_callback('msg_send_braille_info', self.send_braille_info) - self.transport.callback_manager.register_callback(TransportEvents.CONNECTED, self.handle_connected) - self.transport.callback_manager.register_callback(TransportEvents.DISCONNECTED, self.handle_disconnected) - - def handle_play_wave(self, **kwargs): - """Receive instruction to play a 'wave' from the slave machine - This method handles translation (between versions of TeleNVDA) of arguments required for 'msg_wave' - """ - # Note: - # Version 2.2 will send only 'async' in kwargs - # Version 2.3 will send 'asynchronous' and 'async' in kwargs - if "fileName" not in kwargs: - log.error("'fileName' missing from kwargs.") - return - fileName = kwargs.pop("fileName") - if "%appdir%" in fileName: - fileName = fileName.replace("%appdir%", sys.prefix if hasattr(sys, 'frozen') else os.path.dirname(sys.modules['__main__'].__file__)) - if "%configpath%" in fileName: - fileName = fileName.replace("%configpath%", globalVars.appArgs.configPath) - self.local_machine.play_wave(fileName=fileName) - - def get_connection_info(self): - hostname, port = self.transport.address - key = self.transport.channel - encryption_key = self.transport.encryption_key - return connection_info.ConnectionInfo(hostname=hostname, port=port, key=key, mode='master', encryption_key=encryption_key) - - def handle_nvda_not_connected(self): - speech.cancelSpeech() - ui.message(_("Remote NVDA not connected.")) - - def handle_connected(self): - # speech index approach changed in 2019.3 - pass # nothing to do - - def handle_disconnected(self): - # speech index approach changed in 2019.3 - pass # nothing to do - - def handle_channel_joined(self, channel=None, clients=None, origin=None, **kwargs): - if clients is None: - clients = [] - for client in clients: - self.handle_client_connected(client) - self.client_count = len(clients)+1 - - def handle_client_connected(self, client=None, **kwargs): - self.patcher.patch() - if not self.patch_callbacks_added: - self.add_patch_callbacks() - self.patch_callbacks_added = True - self.send_braille_info() - cues.client_connected() - self.client_count += 1 - - def handle_client_disconnected(self, client=None, **kwargs): - self.patcher.unpatch() - if self.patch_callbacks_added: - self.remove_patch_callbacks() - self.patch_callbacks_added = False - cues.client_disconnected() - self.client_count -= 1 - - def send_braille_info(self, display=None, displaySize=None, **kwargs): - if display is None: - display = braille.handler.display - if displaySize is None: - displaySize = braille.handler.displaySize - self.transport.send(type="set_braille_info", name=display.name, numCells=displaySize) - - def braille_input(self,**kwargs): - self.transport.send(type="braille_input", **kwargs) - - def add_patch_callbacks(self): - patcher_callbacks = (('braille_input', self.braille_input), ('set_display', self.send_braille_info)) - for event, callback in patcher_callbacks: - self.patcher.register_callback(event, callback) - - def remove_patch_callbacks(self): - patcher_callbacks = (('braille_input', self.braille_input), ('set_display', self.send_braille_info)) - for event, callback in patcher_callbacks: - self.patcher.unregister_callback(event, callback) +import sys +import os +import globalVars +from .transport import TransportEvents +from . import connection_info +import gui +import speech +import ui +import braille +import buildVersion +from logHandler import log +from . import configuration +from . import nvda_patcher +from . import RelayTransport +from collections import defaultdict +from . import cues +import hashlib +import addonHandler + +try: + addonHandler.initTranslation() +except addonHandler.AddonError: + log.warning( + "Unable to initialise translations. This may be because the addon is running from NVDA scratchpad.", + ) +if not ( + buildVersion.version_year >= 2021 + or (buildVersion.version_year == 2020 and buildVersion.version_major >= 2) +): + # NVDA versions newer than 2020.2 have a _CancellableSpeechCommand which should be ignored by TeleNVDA + # For older versions, we create a dummy command that won't cause existing commands to be ignored. + class _DummyCommand(speech.commands.SpeechCommand): + pass + + speech.commands._CancellableSpeechCommand = _DummyCommand + + +EXCLUDED_SPEECH_COMMANDS = ( + speech.commands.BaseCallbackCommand, + # _CancellableSpeechCommands are not designed to be reported and are used internally by NVDA. (#230) + speech.commands._CancellableSpeechCommand, +) + + +class RemoteSession: + def __init__(self, local_machine, transport: RelayTransport): + self.local_machine = local_machine + self.patcher = None + self.transport = transport + self.transport.callback_manager.register_callback( + "msg_version_mismatch", self.handle_version_mismatch + ) + self.transport.callback_manager.register_callback("msg_motd", self.handle_motd) + self.client_count = 1 + + def handle_version_mismatch(self, **kwargs): + # translators: Message for version mismatch + message = _("""The version of the relay server which you have connected to is not compatible with this version of the Remote Client. +Please either use a different server or upgrade your version of the addon.""") + ui.message(message) + self.transport.close() + + def handle_motd(self, motd: str, force_display=False, **kwargs): + displayOnce = configuration.get_config()["ui"]["display_motd_once"] + if (force_display and not displayOnce) or self.should_display_motd(motd): + gui.messageBox(parent=gui.mainFrame, caption=_("Message of the Day"), message=motd) + + def should_display_motd(self, motd: str): + conf = configuration.get_config() + host, port = self.transport.address + host = host.lower() + address = "{host}:{port}".format(host=host, port=port) + motdBytes = motd.encode("utf-8", errors="surrogatepass") + hashed = hashlib.sha1(motdBytes).hexdigest() + current = conf["seen_motds"].get(address, "") + if current == hashed: + return False + conf["seen_motds"][address] = hashed + conf.write() + return True + + +class SlaveSession(RemoteSession): + """Session that runs on the slave and manages state.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.transport.callback_manager.register_callback("msg_client_joined", self.handle_client_connected) + self.transport.callback_manager.register_callback("msg_client_left", self.handle_client_disconnected) + self.transport.callback_manager.register_callback("msg_key", self.local_machine.send_key) + self.masters = defaultdict(dict) + self.master_display_sizes = [] + + self.transport.callback_manager.register_callback("msg_index", self.recv_index) + self.transport.callback_manager.register_callback( + TransportEvents.CLOSING, self.handle_transport_closing + ) + self.patcher = nvda_patcher.NVDASlavePatcher() + self.patch_callbacks_added = False + self.transport.callback_manager.register_callback("msg_channel_joined", self.handle_channel_joined) + self.transport.callback_manager.register_callback( + "msg_set_clipboard_text", self.local_machine.set_clipboard_text + ) + self.transport.callback_manager.register_callback( + "msg_file_transfer", self.local_machine.file_transfer + ) + self.transport.callback_manager.register_callback("msg_set_braille_info", self.handle_braille_info) + self.transport.callback_manager.register_callback("msg_set_display_size", self.set_display_size) + if buildVersion.version_year >= 2023 and buildVersion.version_year < 2025: + braille.filter_displaySize.register(self.local_machine.handle_filter_displaySize) + if buildVersion.version_year >= 2025: + braille.filter_displayDimensions.register(self.local_machine.handle_filter_displayDimensions) + self.transport.callback_manager.register_callback( + "msg_braille_input", self.local_machine.braille_input + ) + self.transport.callback_manager.register_callback("msg_send_SAS", self.local_machine.send_SAS) + + def get_connection_info(self): + hostname, port = self.transport.address + key = self.transport.channel + encryption_key = self.transport.encryption_key + return connection_info.ConnectionInfo( + hostname=hostname, port=port, key=key, mode="slave", encryption_key=encryption_key + ) + + def handle_client_connected(self, client=None, **kwargs): + self.patcher.patch() + if not self.patch_callbacks_added: + self.add_patch_callbacks() + self.patch_callbacks_added = True + cues.client_connected() + if client["connection_type"] == "master": + self.masters[client["id"]]["active"] = True + self.client_count += 1 + + def handle_channel_joined(self, channel=None, clients=None, origin=None, **kwargs): + if clients is None: + clients = [] + for client in clients: + self.handle_client_connected(client) + self.client_count = len(clients) + 1 + + def handle_transport_closing(self): + self.patcher.unpatch() + if self.patch_callbacks_added: + self.remove_patch_callbacks() + self.patch_callbacks_added = False + + def handle_transport_disconnected(self): + cues.client_connected() + self.patcher.unpatch() + + def handle_client_disconnected(self, client=None, **kwargs): + cues.client_disconnected() + if client["connection_type"] == "master": + del self.masters[client["id"]] + if not self.masters: + self.patcher.unpatch() + self.client_count -= 1 + + def set_display_size(self, sizes=None, **kwargs): + self.master_display_sizes = ( + sizes if sizes else [info.get("braille_numCells", 0) for info in self.masters.values()] + ) + self.local_machine.set_braille_display_size(self.master_display_sizes) + + def handle_braille_info(self, name=None, numCells=0, origin=None, **kwargs): + if not self.masters.get(origin): + return + self.masters[origin]["braille_name"] = name + self.masters[origin]["braille_numCells"] = numCells + self.set_display_size() + + def _get_patcher_callbacks(self): + return ( + ("speak", self.speak), + ("beep", self.beep), + ("wave", self.playWaveFile), + ("cancel_speech", self.cancel_speech), + ("pause_speech", self.pause_speech), + ("display", self.display), + ("set_display", self.set_display_size), + ) + + def add_patch_callbacks(self): + patcher_callbacks = self._get_patcher_callbacks() + for event, callback in patcher_callbacks: + self.patcher.register_callback(event, callback) + + def remove_patch_callbacks(self): + patcher_callbacks = self._get_patcher_callbacks() + for event, callback in patcher_callbacks: + self.patcher.unregister_callback(event, callback) + + def _filterUnsupportedSpeechCommands(self, speechSequence): + return list([item for item in speechSequence if not isinstance(item, EXCLUDED_SPEECH_COMMANDS)]) + + def speak(self, speechSequence, priority): + self.transport.send( + type="speak", + sequence=self._filterUnsupportedSpeechCommands(speechSequence), + priority=priority, + ) + + def cancel_speech(self): + self.transport.send(type="cancel") + + def pause_speech(self, switch): + self.transport.send(type="pause_speech", switch=switch) + + def beep(self, hz, length, left=50, right=50, **kwargs): + self.transport.send(type="tone", hz=hz, length=length, left=left, right=right, **kwargs) + + def playWaveFile(self, **kwargs): + """This machine played a sound, send it to Master machine""" + kwargs.update( + { + # nvWave.playWaveFile should always be asynchronous when called from TeleNVDA, so always send 'True' + # Version 2.2 requires 'async' keyword. + "async": True, + # Version 2.3 onwards. Not currently used, but matches arguments for nvWave.playWaveFile. + # Including it allows for forward compatibility if requirements change. + "asynchronous": True, + "fileName": kwargs["fileName"] + .replace(globalVars.appArgs.configPath, "%configpath%") + .replace( + sys.prefix + if hasattr(sys, "frozen") + else os.path.dirname(sys.modules["__main__"].__file__), + "%appdir%", + ), + } + ) + self.transport.send(type="wave", **kwargs) + + def display(self, cells): + # Only send braille data when there are controlling machines with a braille display + if self.has_braille_masters(): + self.transport.send(type="display", cells=cells) + + def has_braille_masters(self): + return bool([i for i in self.master_display_sizes if i > 0]) + + def recv_index(self, index=None, **kwargs): + pass # speech index approach changed in 2019.3 + + +class MasterSession(RemoteSession): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.slaves = defaultdict(dict) + self.patcher = nvda_patcher.NVDAMasterPatcher() + self.patch_callbacks_added = False + self.transport.callback_manager.register_callback("msg_speak", self.local_machine.speak) + self.transport.callback_manager.register_callback("msg_cancel", self.local_machine.cancel_speech) + self.transport.callback_manager.register_callback("msg_pause_speech", self.local_machine.pause_speech) + self.transport.callback_manager.register_callback("msg_tone", self.local_machine.beep) + self.transport.callback_manager.register_callback("msg_wave", self.handle_play_wave) + self.transport.callback_manager.register_callback("msg_display", self.local_machine.display) + self.transport.callback_manager.register_callback( + "msg_nvda_not_connected", self.handle_nvda_not_connected + ) + self.transport.callback_manager.register_callback("msg_client_joined", self.handle_client_connected) + self.transport.callback_manager.register_callback("msg_client_left", self.handle_client_disconnected) + self.transport.callback_manager.register_callback("msg_channel_joined", self.handle_channel_joined) + self.transport.callback_manager.register_callback( + "msg_set_clipboard_text", self.local_machine.set_clipboard_text + ) + self.transport.callback_manager.register_callback( + "msg_file_transfer", self.local_machine.file_transfer + ) + self.transport.callback_manager.register_callback("msg_send_braille_info", self.send_braille_info) + self.transport.callback_manager.register_callback(TransportEvents.CONNECTED, self.handle_connected) + self.transport.callback_manager.register_callback( + TransportEvents.DISCONNECTED, self.handle_disconnected + ) + + def handle_play_wave(self, **kwargs): + """Receive instruction to play a 'wave' from the slave machine + This method handles translation (between versions of TeleNVDA) of arguments required for 'msg_wave' + """ + # Note: + # Version 2.2 will send only 'async' in kwargs + # Version 2.3 will send 'asynchronous' and 'async' in kwargs + if "fileName" not in kwargs: + log.error("'fileName' missing from kwargs.") + return + fileName = kwargs.pop("fileName") + if "%appdir%" in fileName: + fileName = fileName.replace( + "%appdir%", + sys.prefix if hasattr(sys, "frozen") else os.path.dirname(sys.modules["__main__"].__file__), + ) + if "%configpath%" in fileName: + fileName = fileName.replace("%configpath%", globalVars.appArgs.configPath) + self.local_machine.play_wave(fileName=fileName) + + def get_connection_info(self): + hostname, port = self.transport.address + key = self.transport.channel + encryption_key = self.transport.encryption_key + return connection_info.ConnectionInfo( + hostname=hostname, port=port, key=key, mode="master", encryption_key=encryption_key + ) + + def handle_nvda_not_connected(self): + speech.cancelSpeech() + ui.message(_("Remote NVDA not connected.")) + + def handle_connected(self): + # speech index approach changed in 2019.3 + pass # nothing to do + + def handle_disconnected(self): + # speech index approach changed in 2019.3 + pass # nothing to do + + def handle_channel_joined(self, channel=None, clients=None, origin=None, **kwargs): + if clients is None: + clients = [] + for client in clients: + self.handle_client_connected(client) + self.client_count = len(clients) + 1 + + def handle_client_connected(self, client=None, **kwargs): + self.patcher.patch() + if not self.patch_callbacks_added: + self.add_patch_callbacks() + self.patch_callbacks_added = True + self.send_braille_info() + cues.client_connected() + self.client_count += 1 + + def handle_client_disconnected(self, client=None, **kwargs): + self.patcher.unpatch() + if self.patch_callbacks_added: + self.remove_patch_callbacks() + self.patch_callbacks_added = False + cues.client_disconnected() + self.client_count -= 1 + + def send_braille_info(self, display=None, displaySize=None, **kwargs): + if display is None: + display = braille.handler.display + if displaySize is None: + displaySize = braille.handler.displaySize + self.transport.send(type="set_braille_info", name=display.name, numCells=displaySize) + + def braille_input(self, **kwargs): + self.transport.send(type="braille_input", **kwargs) + + def add_patch_callbacks(self): + patcher_callbacks = (("braille_input", self.braille_input), ("set_display", self.send_braille_info)) + for event, callback in patcher_callbacks: + self.patcher.register_callback(event, callback) + + def remove_patch_callbacks(self): + patcher_callbacks = (("braille_input", self.braille_input), ("set_display", self.send_braille_info)) + for event, callback in patcher_callbacks: + self.patcher.unregister_callback(event, callback) diff --git a/addon/globalPlugins/remoteClient/transport.py b/addon/globalPlugins/remoteClient/transport.py index 7db837dd..5c4d0679 100755 --- a/addon/globalPlugins/remoteClient/transport.py +++ b/addon/globalPlugins/remoteClient/transport.py @@ -1,295 +1,355 @@ -import threading -import os -import sys -import buildVersion -import time -import queue -import ssl -import socket -import select -import hashlib -import base64 -from collections import defaultdict -from typing import Tuple -from logging import getLogger -log = getLogger('transport') -from . import callback_manager -from . import configuration -from .socket_utils import SERVER_PORT, address_to_hostport, hostport_to_address -from enum import Enum -sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), "lib64" if buildVersion.version_year >= 2026 else "lib32")) -from Cryptodome.Cipher import AES -sys.path.remove(sys.path[-1]) - -PROTOCOL_VERSION: int = 2 -EXCLUDED_FROM_ENCRYPTION: list[str] = ["join", "protocol_version", "encrypted", "channel_joined", "motd", "nvda_not_connected", "client_left", "ping", "error", "client_joined", "generate_key"] - -class TransportEvents(Enum): - CONNECTED = 'transport_connected' - CERTIFICATE_AUTHENTICATION_FAILED = 'certificate_authentication_failed' - CONNECTION_FAILED = 'transport_connection_failed' - CLOSING = 'transport_closing' - DISCONNECTED = 'transport_disconnected' - - -class Transport: - connected: bool - successful_connects: int - callback_manager: callback_manager.CallbackManager - connect_event: threading.Event - - def __init__(self, serializer): - self.serializer = serializer - self.callback_manager = callback_manager.CallbackManager() - self.connected = False - self.successful_connects = 0 - self.connected_event = threading.Event() - - def transport_connected(self): - self.successful_connects += 1 - self.connected = True - self.connected_event.set() - self.callback_manager.call_callbacks(TransportEvents.CONNECTED) - -class TCPTransport(Transport): - buffer: bytes - closed: bool - queue: queue.Queue - insecure: bool - server_sock_lock: threading.Lock - - def __init__(self, serializer, address: Tuple[str, int], timeout: int=0, insecure: bool=False, encryption_key: str=''): - super().__init__(serializer=serializer) - self.closed = False - #Buffer to hold partially received data - self.buffer = B'' - self.queue = queue.Queue() - self.address = address - self.server_sock = None - # Reading/writing from an SSL socket is not thread safe. - # See https://bugs.python.org/issue41597#msg375692 - # Guard access to the socket with a lock. - self.server_sock_lock = threading.Lock() - self.queue_thread = None - self.timeout = timeout - self.reconnector_thread = ConnectorThread(self) - self.insecure=insecure - self.encryption_key = encryption_key - self.encryption_hash=hashlib.sha256(encryption_key.encode("utf-8")).digest() if encryption_key else None - self.send_alpn = True - - def run(self): - self.closed = False - try: - self.server_sock = self.create_outbound_socket(*self.address, insecure=self.insecure) - self.server_sock.connect(self.address) - except ssl.SSLCertVerificationError as ex: - fingerprint=None - try: - tmp_con = self.create_outbound_socket(*self.address, insecure = True) - tmp_con.connect(self.address) - certBin = tmp_con.getpeercert(True) - tmp_con.close() - fingerprint = hashlib.sha256(certBin).hexdigest().lower() - except Exception: pass - config = configuration.get_config() - if hostport_to_address(self.address) in config['trusted_certs'] and config['trusted_certs'][hostport_to_address(self.address)]==fingerprint: - self.insecure=True - return self.run() - self.last_fail_fingerprint = fingerprint - self.callback_manager.call_callbacks(TransportEvents.CERTIFICATE_AUTHENTICATION_FAILED) - raise - except ssl.SSLError: - if self.send_alpn: - self.send_alpn = False - return self.run() - else: - self.callback_manager.call_callbacks(TransportEvents.CONNECTION_FAILED) - raise - except Exception: - self.callback_manager.call_callbacks(TransportEvents.CONNECTION_FAILED) - raise - self.transport_connected() - self.queue_thread = threading.Thread(target=self.send_queue) - self.queue_thread.daemon = True - self.queue_thread.start() - while self.server_sock is not None: - try: - readers, writers, error = select.select([self.server_sock], [], [self.server_sock]) - except socket.error: - self.buffer = b'' - break - if self.server_sock in error: - self.buffer = b"" - break - if self.server_sock in readers: - try: - self.handle_server_data() - except socket.error: - self.buffer = b'' - break - self.connected = False - self.connected_event.clear() - self.callback_manager.call_callbacks(TransportEvents.DISCONNECTED) - self._disconnect() - - def create_outbound_socket(self, host, port, insecure=False): - if host.lower().endswith(".onion"): - server_sock = socket.socket(socket.AF_INET) - else: - address = socket.getaddrinfo(host, port)[0] - server_sock = socket.socket(*address[:3]) - if self.timeout: - server_sock.settimeout(self.timeout) - server_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - server_sock.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 60000, 2000)) - ctx = (ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)) - if self.send_alpn: - ctx.set_alpn_protocols(['nvdaremote/2.0']) - ctx.minimum_version = ssl.TLSVersion.TLSv1_2 - if insecure: - ctx.check_hostname = False - ctx.verify_mode = ssl.CERT_NONE - ctx.load_default_certs() - server_sock = ctx.wrap_socket(sock=server_sock, server_hostname=host) - return server_sock - - def getpeercert(self, binary_form=False): - if self.server_sock is None: return None - return self.server_sock.getpeercert(binary_form) - - def handle_server_data(self): - # This approach may be problematic: - # See also server.py handle_data in class Client. - buffSize = 16384 - with self.server_sock_lock: - # select operates on the raw socket. Even though it said there was data to - # read, that might be SSL data which might not result in actual data for - # us. Therefore, do a non-blocking read so SSL doesn't try to wait for - # more data for us. - # We don't make the socket non-blocking earlier because then we'd have to - # handle retries during the SSL handshake. - # See https://stackoverflow.com/questions/3187565/select-and-ssl-in-python - # and https://docs.python.org/3/library/ssl.html#notes-on-non-blocking-sockets - self.server_sock.setblocking(False) - try: - data = self.buffer + self.server_sock.recv(buffSize) - except ssl.SSLWantReadError: - # There's no data for us. - return - finally: - self.server_sock.setblocking(True) - self.buffer = b'' - if not data: - self._disconnect() - return - if b'\n' not in data: - self.buffer += data - return - while b'\n' in data: - line, sep, data = data.partition(b'\n') - self.parse(line) - self.buffer += data - - def parse(self, line, isDecrypted=False): - obj = self.serializer.deserialize(line) - if 'type' not in obj: - return - if self.encryption_hash is not None and not isDecrypted and obj['type'] not in EXCLUDED_FROM_ENCRYPTION: - return - if obj['type']=='encrypted' and self.encryption_hash is not None: - cipher = AES.new(self.encryption_hash, AES.MODE_GCM, nonce=base64.b64decode(obj['nonce'].encode("utf-8"))) - try: - decrypted_data = cipher.decrypt_and_verify(base64.b64decode(obj['data'].encode("utf-8")), base64.b64decode(obj['tag'].encode("utf-8"))) - return self.parse(decrypted_data, isDecrypted=True) - except: - return - callback = "msg_"+obj['type'] - del obj['type'] - self.callback_manager.call_callbacks(callback, **obj) - - def send_queue(self): - while True: - item = self.queue.get() - if item is None: - return - try: - with self.server_sock_lock: - self.server_sock.sendall(item) - except socket.error: - return - - def send(self, type, **kwargs): - obj = self.serializer.serialize(type=type, **kwargs) - if self.encryption_hash is not None and type not in EXCLUDED_FROM_ENCRYPTION: - cipher = AES.new(self.encryption_hash, AES.MODE_GCM) - nonce = base64.b64encode(cipher.nonce).decode() - data, tag = cipher.encrypt_and_digest(obj) - data = base64.b64encode(data).decode() - tag = base64.b64encode(tag).decode() - return self.send(type='encrypted', nonce=nonce, data=data, tag=tag) - if self.connected: - self.queue.put(obj) - - def _disconnect(self): - """Disconnect the transport due to an error, without closing the connector thread.""" - if self.queue_thread is not None: - self.queue.put(None) - self.queue_thread.join() - self.queue_thread = None - clear_queue(self.queue) - if self.server_sock: - self.server_sock.close() - self.server_sock = None - - def close(self): - self.callback_manager.call_callbacks(TransportEvents.CLOSING) - self.reconnector_thread.running = False - self._disconnect() - self.closed = True - self.reconnector_thread = ConnectorThread(self) - -class RelayTransport(TCPTransport): - - def __init__(self, serializer, address, timeout=0, channel=None, connection_type=None, protocol_version=PROTOCOL_VERSION, insecure=False, encryption_key=None): - super().__init__(address=address, serializer=serializer, timeout=timeout, insecure=insecure, encryption_key=encryption_key) - log.info("Connecting to %s channel %s" % (address, channel)) - self.channel = channel - self.connection_type = connection_type - self.protocol_version = protocol_version - self.callback_manager.register_callback(TransportEvents.CONNECTED, self.on_connected) - - def on_connected(self): - self.send('protocol_version', version=self.protocol_version) - if self.channel is not None: - self.send('join', channel=self.channel, connection_type=self.connection_type) - else: - self.send('generate_key') - -class ConnectorThread(threading.Thread): - - def __init__(self, connector, connect_delay=5): - super().__init__() - self.connect_delay = connect_delay - self.running = True - self.connector = connector - self.name = self.name + "_connector_loop" - self.daemon = True - - def run(self): - while self.running: - try: - self.connector.run() - except socket.error: - time.sleep(self.connect_delay) - continue - else: - time.sleep(self.connect_delay) - log.info("Ending control connector thread %s" % self.name) - -def clear_queue(queue): - try: - while True: - queue.get_nowait() - except Exception: - pass +import threading +import os +import sys +import buildVersion +import time +import queue +import ssl +import socket +import select +import hashlib +import base64 +from typing import Tuple +from logging import getLogger + +log = getLogger("transport") +from . import callback_manager +from . import configuration +from .socket_utils import hostport_to_address +from enum import Enum + +sys.path.append( + os.path.join( + os.path.abspath(os.path.dirname(__file__)), "lib64" if buildVersion.version_year >= 2026 else "lib32" + ) +) +from Cryptodome.Cipher import AES + +sys.path.remove(sys.path[-1]) + +PROTOCOL_VERSION: int = 2 +EXCLUDED_FROM_ENCRYPTION: list[str] = [ + "join", + "protocol_version", + "encrypted", + "channel_joined", + "motd", + "nvda_not_connected", + "client_left", + "ping", + "error", + "client_joined", + "generate_key", +] + + +class TransportEvents(Enum): + CONNECTED = "transport_connected" + CERTIFICATE_AUTHENTICATION_FAILED = "certificate_authentication_failed" + CONNECTION_FAILED = "transport_connection_failed" + CLOSING = "transport_closing" + DISCONNECTED = "transport_disconnected" + + +class Transport: + connected: bool + successful_connects: int + callback_manager: callback_manager.CallbackManager + connect_event: threading.Event + + def __init__(self, serializer): + self.serializer = serializer + self.callback_manager = callback_manager.CallbackManager() + self.connected = False + self.successful_connects = 0 + self.connected_event = threading.Event() + + def transport_connected(self): + self.successful_connects += 1 + self.connected = True + self.connected_event.set() + self.callback_manager.call_callbacks(TransportEvents.CONNECTED) + + +class TCPTransport(Transport): + buffer: bytes + closed: bool + queue: queue.Queue + insecure: bool + server_sock_lock: threading.Lock + + def __init__( + self, + serializer, + address: Tuple[str, int], + timeout: int = 0, + insecure: bool = False, + encryption_key: str = "", + ): + super().__init__(serializer=serializer) + self.closed = False + # Buffer to hold partially received data + self.buffer = b"" + self.queue = queue.Queue() + self.address = address + self.server_sock = None + # Reading/writing from an SSL socket is not thread safe. + # See https://bugs.python.org/issue41597#msg375692 + # Guard access to the socket with a lock. + self.server_sock_lock = threading.Lock() + self.queue_thread = None + self.timeout = timeout + self.reconnector_thread = ConnectorThread(self) + self.insecure = insecure + self.encryption_key = encryption_key + self.encryption_hash = ( + hashlib.sha256(encryption_key.encode("utf-8")).digest() if encryption_key else None + ) + self.send_alpn = True + + def run(self): + self.closed = False + try: + self.server_sock = self.create_outbound_socket(*self.address, insecure=self.insecure) + self.server_sock.connect(self.address) + except ssl.SSLCertVerificationError: + fingerprint = None + try: + tmp_con = self.create_outbound_socket(*self.address, insecure=True) + tmp_con.connect(self.address) + certBin = tmp_con.getpeercert(True) + tmp_con.close() + fingerprint = hashlib.sha256(certBin).hexdigest().lower() + except Exception: + pass + config = configuration.get_config() + if ( + hostport_to_address(self.address) in config["trusted_certs"] + and config["trusted_certs"][hostport_to_address(self.address)] == fingerprint + ): + self.insecure = True + return self.run() + self.last_fail_fingerprint = fingerprint + self.callback_manager.call_callbacks(TransportEvents.CERTIFICATE_AUTHENTICATION_FAILED) + raise + except ssl.SSLError: + if self.send_alpn: + self.send_alpn = False + return self.run() + else: + self.callback_manager.call_callbacks(TransportEvents.CONNECTION_FAILED) + raise + except Exception: + self.callback_manager.call_callbacks(TransportEvents.CONNECTION_FAILED) + raise + self.transport_connected() + self.queue_thread = threading.Thread(target=self.send_queue) + self.queue_thread.daemon = True + self.queue_thread.start() + while self.server_sock is not None: + try: + readers, writers, error = select.select([self.server_sock], [], [self.server_sock]) + except socket.error: + self.buffer = b"" + break + if self.server_sock in error: + self.buffer = b"" + break + if self.server_sock in readers: + try: + self.handle_server_data() + except socket.error: + self.buffer = b"" + break + self.connected = False + self.connected_event.clear() + self.callback_manager.call_callbacks(TransportEvents.DISCONNECTED) + self._disconnect() + + def create_outbound_socket(self, host, port, insecure=False): + if host.lower().endswith(".onion"): + server_sock = socket.socket(socket.AF_INET) + else: + address = socket.getaddrinfo(host, port)[0] + server_sock = socket.socket(*address[:3]) + if self.timeout: + server_sock.settimeout(self.timeout) + server_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + server_sock.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 60000, 2000)) + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + if self.send_alpn: + ctx.set_alpn_protocols(["nvdaremote/2.0"]) + ctx.minimum_version = ssl.TLSVersion.TLSv1_2 + if insecure: + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + ctx.load_default_certs() + server_sock = ctx.wrap_socket(sock=server_sock, server_hostname=host) + return server_sock + + def getpeercert(self, binary_form=False): + if self.server_sock is None: + return None + return self.server_sock.getpeercert(binary_form) + + def handle_server_data(self): + # This approach may be problematic: + # See also server.py handle_data in class Client. + buffSize = 16384 + with self.server_sock_lock: + # select operates on the raw socket. Even though it said there was data to + # read, that might be SSL data which might not result in actual data for + # us. Therefore, do a non-blocking read so SSL doesn't try to wait for + # more data for us. + # We don't make the socket non-blocking earlier because then we'd have to + # handle retries during the SSL handshake. + # See https://stackoverflow.com/questions/3187565/select-and-ssl-in-python + # and https://docs.python.org/3/library/ssl.html#notes-on-non-blocking-sockets + self.server_sock.setblocking(False) + try: + data = self.buffer + self.server_sock.recv(buffSize) + except ssl.SSLWantReadError: + # There's no data for us. + return + finally: + self.server_sock.setblocking(True) + self.buffer = b"" + if not data: + self._disconnect() + return + if b"\n" not in data: + self.buffer += data + return + while b"\n" in data: + line, sep, data = data.partition(b"\n") + self.parse(line) + self.buffer += data + + def parse(self, line, isDecrypted=False): + obj = self.serializer.deserialize(line) + if "type" not in obj: + return + if ( + self.encryption_hash is not None + and not isDecrypted + and obj["type"] not in EXCLUDED_FROM_ENCRYPTION + ): + return + if obj["type"] == "encrypted" and self.encryption_hash is not None: + cipher = AES.new( + self.encryption_hash, AES.MODE_GCM, nonce=base64.b64decode(obj["nonce"].encode("utf-8")) + ) + try: + decrypted_data = cipher.decrypt_and_verify( + base64.b64decode(obj["data"].encode("utf-8")), + base64.b64decode(obj["tag"].encode("utf-8")), + ) + return self.parse(decrypted_data, isDecrypted=True) + except: + return + callback = "msg_" + obj["type"] + del obj["type"] + self.callback_manager.call_callbacks(callback, **obj) + + def send_queue(self): + while True: + item = self.queue.get() + if item is None: + return + try: + with self.server_sock_lock: + self.server_sock.sendall(item) + except socket.error: + return + + def send(self, type, **kwargs): + obj = self.serializer.serialize(type=type, **kwargs) + if self.encryption_hash is not None and type not in EXCLUDED_FROM_ENCRYPTION: + cipher = AES.new(self.encryption_hash, AES.MODE_GCM) + nonce = base64.b64encode(cipher.nonce).decode() + data, tag = cipher.encrypt_and_digest(obj) + data = base64.b64encode(data).decode() + tag = base64.b64encode(tag).decode() + return self.send(type="encrypted", nonce=nonce, data=data, tag=tag) + if self.connected: + self.queue.put(obj) + + def _disconnect(self): + """Disconnect the transport due to an error, without closing the connector thread.""" + if self.queue_thread is not None: + self.queue.put(None) + self.queue_thread.join() + self.queue_thread = None + clear_queue(self.queue) + if self.server_sock: + self.server_sock.close() + self.server_sock = None + + def close(self): + self.callback_manager.call_callbacks(TransportEvents.CLOSING) + self.reconnector_thread.running = False + self._disconnect() + self.closed = True + self.reconnector_thread = ConnectorThread(self) + + +class RelayTransport(TCPTransport): + def __init__( + self, + serializer, + address, + timeout=0, + channel=None, + connection_type=None, + protocol_version=PROTOCOL_VERSION, + insecure=False, + encryption_key=None, + ): + super().__init__( + address=address, + serializer=serializer, + timeout=timeout, + insecure=insecure, + encryption_key=encryption_key, + ) + log.info("Connecting to %s channel %s" % (address, channel)) + self.channel = channel + self.connection_type = connection_type + self.protocol_version = protocol_version + self.callback_manager.register_callback(TransportEvents.CONNECTED, self.on_connected) + + def on_connected(self): + self.send("protocol_version", version=self.protocol_version) + if self.channel is not None: + self.send("join", channel=self.channel, connection_type=self.connection_type) + else: + self.send("generate_key") + + +class ConnectorThread(threading.Thread): + def __init__(self, connector, connect_delay=5): + super().__init__() + self.connect_delay = connect_delay + self.running = True + self.connector = connector + self.name = self.name + "_connector_loop" + self.daemon = True + + def run(self): + while self.running: + try: + self.connector.run() + except socket.error: + time.sleep(self.connect_delay) + continue + else: + time.sleep(self.connect_delay) + log.info("Ending control connector thread %s" % self.name) + + +def clear_queue(queue): + try: + while True: + queue.get_nowait() + except Exception: + pass diff --git a/addon/installTasks.py b/addon/installTasks.py index c6544504..9f581f41 100644 --- a/addon/installTasks.py +++ b/addon/installTasks.py @@ -14,7 +14,7 @@ def onInstall(): result = gui.messageBox( # Translators: message asking the user wether NVDA Remote whould be disabled or not _( - "NVDA Remote has been detected on your NVDA installation. In order for TeleNVDA to work without conflicts, NVDA Remote must be disabled. Otherwise, TeleNVDA will refuse to work. Would you like to disable NVDA Remote now?" + "NVDA Remote has been detected on your NVDA installation. In order for TeleNVDA to work without conflicts, NVDA Remote must be disabled. Otherwise, TeleNVDA will refuse to work. Would you like to disable NVDA Remote now?", ), # Translators: question title _("Running NVDA Remote detected"),