Download cryptography/Test_Cryptography.py from PythonSTB/pypi312: direct link, hf CLI and curl.
- Browser
- Download file 18.5 kB
-
https://huggingface.co/PythonSTB/pypi312/resolve/7d29bbe9757e514b3838e3538ff1b410882a641a/cryptography/Test_Cryptography.py
- Command line
-
hf download hf://PythonSTB/pypi312@7d29bbe9757e514b3838e3538ff1b410882a641a/cryptography/Test_Cryptography.py
-
curl -L -o Test_Cryptography.py https://huggingface.co/PythonSTB/pypi312/resolve/7d29bbe9757e514b3838e3538ff1b410882a641a/cryptography/Test_Cryptography.py
18.5 kB
| """ | |
| On-device verification for the cross-compiled cryptography + cffi wheels. | |
| Run after installing: | |
| pip install pycparser-2.22-py2.py3-none-any.whl | |
| pip install cffi-2.1.1-cp312-cp312-android_24_<ABI>.whl | |
| pip install cryptography-50.0.0-cp312-abi3-android_24_<ABI>.whl | |
| Usage: | |
| python test_crypto_on_device.py [--quick] | |
| Exit code 0 = everything required PASSed. | |
| Sections marked [SKIP] are features the bundled OpenSSL 3.2.1 does not | |
| provide (e.g. post-quantum ML-KEM/ML-DSA) and are informational only. | |
| Generated by RIMI | |
| """ | |
| import sys | |
| import traceback | |
| RESULTS = [] | |
| def test(name, fn): | |
| try: | |
| fn() | |
| RESULTS.append((name, "PASS", None)) | |
| except NotImplementedError as exc: | |
| RESULTS.append((name, "SKIP", str(exc))) | |
| except Exception as exc: | |
| RESULTS.append((name, "FAIL", "%s: %s" % (type(exc).__name__, exc))) | |
| print(" ! %s -> %s: %s" % (name, type(exc).__name__, exc)) | |
| def section(title): | |
| print("=" * 60) | |
| print(title) | |
| print("=" * 60) | |
| # --------------------------------------------------------------------------- | |
| # 1. cryptography import surface | |
| # --------------------------------------------------------------------------- | |
| def imports_core(): | |
| import cryptography | |
| assert cryptography.__version__ == "50.0.0", cryptography.__version__ | |
| import cryptography.hazmat.bindings._rust # noqa: F401 (the .so extension) | |
| import cryptography.exceptions # noqa: F401 | |
| import cryptography.utils # noqa: F401 | |
| import cryptography.fernet # noqa: F401 | |
| import cryptography.cobblestone # noqa: F401 | |
| def imports_bindings(): | |
| import cryptography.hazmat.backends.openssl.backend # noqa: F401 | |
| import cryptography.hazmat.bindings.openssl._conditional # noqa: F401 | |
| import cryptography.hazmat.bindings.openssl.binding # noqa: F401 | |
| import cryptography.hazmat.bindings._rust # noqa: F401 | |
| def imports_primitives(): | |
| import cryptography.hazmat.primitives.hashes # noqa: F401 | |
| import cryptography.hazmat.primitives.hmac # noqa: F401 | |
| import cryptography.hazmat.primitives.cmac # noqa: F401 | |
| import cryptography.hazmat.primitives.ciphers # noqa: F401 | |
| import cryptography.hazmat.primitives.ciphers.aead # noqa: F401 | |
| import cryptography.hazmat.primitives.padding # noqa: F401 | |
| import cryptography.hazmat.primitives.constant_time # noqa: F401 | |
| import cryptography.hazmat.primitives.keywrap # noqa: F401 | |
| import cryptography.hazmat.primitives.poly1305 # noqa: F401 | |
| import cryptography.hazmat.primitives.hpke # noqa: F401 | |
| import cryptography.hazmat.primitives.kdf.hkdf # noqa: F401 | |
| import cryptography.hazmat.primitives.kdf.pbkdf2 # noqa: F401 | |
| import cryptography.hazmat.primitives.kdf.scrypt # noqa: F401 | |
| import cryptography.hazmat.primitives.kdf.kbkdf # noqa: F401 | |
| import cryptography.hazmat.primitives.kdf.concatkdf # noqa: F401 | |
| import cryptography.hazmat.primitives.kdf.x963kdf # noqa: F401 | |
| import cryptography.hazmat.primitives.serialization # noqa: F401 | |
| import cryptography.hazmat.primitives.serialization.pkcs7 # noqa: F401 | |
| import cryptography.hazmat.primitives.serialization.pkcs12 # noqa: F401 | |
| import cryptography.hazmat.primitives.serialization.ssh # noqa: F401 | |
| import cryptography.hazmat.primitives.twofactor.hotp # noqa: F401 | |
| import cryptography.hazmat.primitives.twofactor.totp # noqa: F401 | |
| def imports_asymmetric(): | |
| import cryptography.hazmat.primitives.asymmetric.rsa # noqa: F401 | |
| import cryptography.hazmat.primitives.asymmetric.ec # noqa: F401 | |
| import cryptography.hazmat.primitives.asymmetric.dsa # noqa: F401 | |
| import cryptography.hazmat.primitives.asymmetric.dh # noqa: F401 | |
| import cryptography.hazmat.primitives.asymmetric.ed25519 # noqa: F401 | |
| import cryptography.hazmat.primitives.asymmetric.ed448 # noqa: F401 | |
| import cryptography.hazmat.primitives.asymmetric.x25519 # noqa: F401 | |
| import cryptography.hazmat.primitives.asymmetric.x448 # noqa: F401 | |
| import cryptography.hazmat.primitives.asymmetric.padding # noqa: F401 | |
| import cryptography.hazmat.primitives.asymmetric.utils # noqa: F401 | |
| def imports_x509(): | |
| import cryptography.x509 # noqa: F401 | |
| import cryptography.x509.base # noqa: F401 | |
| import cryptography.x509.extensions # noqa: F401 | |
| import cryptography.x509.general_name # noqa: F401 | |
| import cryptography.x509.name # noqa: F401 | |
| import cryptography.x509.ocsp # noqa: F401 | |
| import cryptography.x509.oid # noqa: F401 | |
| import cryptography.x509.verification # noqa: F401 | |
| import cryptography.x509.certificate_transparency # noqa: F401 | |
| # --------------------------------------------------------------------------- | |
| # 2. hashes / hmac / cmac | |
| # --------------------------------------------------------------------------- | |
| def hashes(): | |
| from cryptography.hazmat.primitives import hashes | |
| d = hashes.Hash(hashes.SHA256()) | |
| d.update(b"hello cryptography") | |
| assert d.finalize().hex() == ( | |
| "a301dc0ba3af7e81df0d99b6b37c4ffca866cb2ee44058bb76158db3b59d02b9" | |
| ), "SHA256 mismatch" | |
| def sha512(): | |
| from cryptography.hazmat.primitives import hashes | |
| d = hashes.Hash(hashes.SHA512()) | |
| d.update(b"abc") | |
| h = d.finalize().hex() | |
| assert h.startswith("ddaf35a193617aba"), "SHA512 mismatch" | |
| def sha3_and_blake2(): | |
| from cryptography.hazmat.primitives import hashes | |
| for cls in (hashes.SHA3_256, hashes.SHA3_512): | |
| d = hashes.Hash(cls()) | |
| d.update(b"data") | |
| assert len(d.finalize()) == d.algorithm.digest_size | |
| d = hashes.Hash(hashes.BLAKE2b(digest_size=64)) | |
| d.update(b"data") | |
| assert len(d.finalize()) == 64 | |
| d = hashes.Hash(hashes.SHA256()) | |
| d.update(b"x") | |
| assert len(d.finalize()) == 32 | |
| def hmac_(): | |
| from cryptography.hazmat.primitives import hashes, hmac | |
| h = hmac.HMAC(b"key", hashes.SHA256()) | |
| h.update(b"message") | |
| assert len(h.finalize()) == 32 | |
| def cmac(): | |
| from cryptography.hazmat.primitives import cmac | |
| from cryptography.hazmat.primitives.ciphers import algorithms | |
| c = cmac.CMAC(algorithms.AES(b"0" * 16)) | |
| c.update(b"msg") | |
| assert len(c.finalize()) == 16 | |
| # --------------------------------------------------------------------------- | |
| # 3. symmetric ciphers | |
| # --------------------------------------------------------------------------- | |
| def aes_gcm(): | |
| from cryptography.hazmat.primitives.ciphers.aead import AESGCM | |
| key = bytes(range(32)) | |
| nonce = b"123456789012" | |
| ct = AESGCM(key).encrypt(nonce, b"secret message", b"aad") | |
| pt = AESGCM(key).decrypt(nonce, ct, b"aad") | |
| assert pt == b"secret message" | |
| def aes_cbc(): | |
| from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes | |
| cipher = Cipher(algorithms.AES(b"0" * 16), modes.CBC(b"0" * 16)) | |
| enc = cipher.encryptor() | |
| ct = enc.update(b"0123456789abcdef") + enc.finalize() | |
| cipher2 = Cipher(algorithms.AES(b"0" * 16), modes.CBC(b"0" * 16)) | |
| dec = cipher2.decryptor() | |
| assert dec.update(ct) + dec.finalize() == b"0123456789abcdef" | |
| def chacha20_poly1305(): | |
| from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 | |
| key = bytes(range(32)) | |
| nonce = b"123456789012" | |
| ct = ChaCha20Poly1305(key).encrypt(nonce, b"hello", None) | |
| assert ChaCha20Poly1305(key).decrypt(nonce, ct, None) == b"hello" | |
| def padding_(): | |
| from cryptography.hazmat.primitives import padding | |
| p = padding.PKCS7(128).padder() | |
| data = p.update(b"1234") + p.finalize() | |
| u = padding.PKCS7(128).unpadder() | |
| assert u.update(data) + u.finalize() == b"1234" | |
| def keywrap_(): | |
| from cryptography.hazmat.primitives.keywrap import aes_key_wrap, aes_key_unwrap | |
| kek = b"0" * 16 | |
| wrapped = aes_key_wrap(kek, b"1" * 24) | |
| assert aes_key_unwrap(kek, wrapped) == b"1" * 24 | |
| # --------------------------------------------------------------------------- | |
| # 4. asymmetric | |
| # --------------------------------------------------------------------------- | |
| def rsa_sign_verify(): | |
| from cryptography.hazmat.primitives import hashes, serialization | |
| from cryptography.hazmat.primitives.asymmetric import padding, rsa | |
| key = rsa.generate_private_key(public_exponent=65537, key_size=2048) | |
| sig = key.sign(b"data", padding.PKCS1v15(), hashes.SHA256()) | |
| key.public_key().verify(sig, b"data", padding.PKCS1v15(), hashes.SHA256()) | |
| pub_pem = key.public_key().public_bytes( | |
| serialization.Encoding.PEM, | |
| serialization.PublicFormat.SubjectPublicKeyInfo, | |
| ) | |
| loaded = serialization.load_pem_public_key(pub_pem) | |
| loaded.verify(sig, b"data", padding.PKCS1v15(), hashes.SHA256()) | |
| priv_pem = key.private_bytes( | |
| serialization.Encoding.PEM, | |
| serialization.PrivateFormat.PKCS8, | |
| serialization.NoEncryption(), | |
| ) | |
| assert serialization.load_pem_private_key(priv_pem, None) is not None | |
| def rsa_oaep(): | |
| from cryptography.hazmat.primitives import hashes | |
| from cryptography.hazmat.primitives.asymmetric import padding, rsa | |
| key = rsa.generate_private_key(public_exponent=65537, key_size=2048) | |
| ct = key.public_key().encrypt( | |
| b"top secret", padding.OAEP(mgf=padding.MGF1(hashes.SHA256()), | |
| algorithm=hashes.SHA256(), label=None) | |
| ) | |
| assert key.decrypt(ct, padding.OAEP(mgf=padding.MGF1(hashes.SHA256()), | |
| algorithm=hashes.SHA256(), | |
| label=None)) == b"top secret" | |
| def ec_(): | |
| from cryptography.hazmat.primitives import hashes | |
| from cryptography.hazmat.primitives.asymmetric import ec | |
| key = ec.generate_private_key(ec.SECP256R1()) | |
| sig = key.sign(b"msg", ec.ECDSA(hashes.SHA256())) | |
| key.public_key().verify(sig, b"msg", ec.ECDSA(hashes.SHA256())) | |
| def ed25519_(): | |
| from cryptography.hazmat.primitives.asymmetric import ed25519 | |
| key = ed25519.Ed25519PrivateKey.generate() | |
| sig = key.sign(b"msg") | |
| key.public_key().verify(sig, b"msg") | |
| def ed448_(): | |
| from cryptography.hazmat.primitives.asymmetric import ed448 | |
| key = ed448.Ed448PrivateKey.generate() | |
| sig = key.sign(b"msg") | |
| key.public_key().verify(sig, b"msg") | |
| def x25519_(): | |
| from cryptography.hazmat.primitives.asymmetric import x25519 | |
| a = x25519.X25519PrivateKey.generate() | |
| b = x25519.X25519PrivateKey.generate() | |
| sa = a.exchange(b.public_key()) | |
| sb = b.exchange(a.public_key()) | |
| assert sa == sb | |
| def x448_(): | |
| from cryptography.hazmat.primitives.asymmetric import x448 | |
| a = x448.X448PrivateKey.generate() | |
| b = x448.X448PrivateKey.generate() | |
| assert a.exchange(b.public_key()) == b.exchange(a.public_key()) | |
| def dh_(): | |
| from cryptography.hazmat.primitives.asymmetric import dh | |
| params = dh.generate_parameters(generator=2, key_size=2048) | |
| a = params.generate_private_key() | |
| b = params.generate_private_key() | |
| assert a.exchange(b.public_key()) == b.exchange(a.public_key()) | |
| def dsa_(): | |
| from cryptography.hazmat.primitives import hashes | |
| from cryptography.hazmat.primitives.asymmetric import dsa | |
| key = dsa.generate_private_key(key_size=2048) | |
| sig = key.sign(b"m", hashes.SHA256()) | |
| key.public_key().verify(sig, b"m", hashes.SHA256()) | |
| # --------------------------------------------------------------------------- | |
| # 5. KDF / password hashing | |
| # --------------------------------------------------------------------------- | |
| def hkdf_(): | |
| from cryptography.hazmat.primitives import hashes | |
| from cryptography.hazmat.primitives.kdf.hkdf import HKDF | |
| k = HKDF(algorithm=hashes.SHA256(), length=32, salt=None, info=b"i").derive(b"pw") | |
| assert len(k) == 32 | |
| def pbkdf2_(): | |
| from cryptography.hazmat.primitives import hashes | |
| from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC | |
| k = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=b"s", iterations=1000).derive(b"pw") | |
| assert len(k) == 32 | |
| def scrypt_(): | |
| from cryptography.hazmat.primitives.kdf.scrypt import Scrypt | |
| k = Scrypt(salt=b"salt", length=32, n=2**14, r=8, p=1).derive(b"pw") | |
| assert len(k) == 32 | |
| # --------------------------------------------------------------------------- | |
| # 6. x509 | |
| # --------------------------------------------------------------------------- | |
| def x509_selfsigned(): | |
| import datetime | |
| from cryptography import x509 | |
| from cryptography.hazmat.primitives import hashes, serialization | |
| from cryptography.hazmat.primitives.asymmetric import ec | |
| from cryptography.x509.oid import NameOID | |
| key = ec.generate_private_key(ec.SECP256R1()) | |
| name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "test")]) | |
| now = datetime.datetime.now(datetime.timezone.utc) | |
| cert = ( | |
| x509.CertificateBuilder() | |
| .subject_name(name) | |
| .issuer_name(name) | |
| .public_key(key.public_key()) | |
| .serial_number(x509.random_serial_number()) | |
| .not_valid_before(now - datetime.timedelta(days=1)) | |
| .not_valid_after(now + datetime.timedelta(days=1)) | |
| .add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True) | |
| .sign(key, hashes.SHA256()) | |
| ) | |
| pem = cert.public_bytes(serialization.Encoding.PEM) | |
| loaded = x509.load_pem_x509_certificate(pem) | |
| assert loaded.subject == name | |
| loaded.public_key().verify( | |
| cert.signature, cert.tbs_certificate_bytes, | |
| ec.ECDSA(hashes.SHA256()), | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # 7. fernet | |
| # --------------------------------------------------------------------------- | |
| def fernet_(): | |
| from cryptography.fernet import Fernet | |
| f = Fernet(Fernet.generate_key()) | |
| t = f.encrypt(b"payload") | |
| assert f.decrypt(t) == b"payload" | |
| # --------------------------------------------------------------------------- | |
| # 8. cffi | |
| # --------------------------------------------------------------------------- | |
| def cffi_import(): | |
| import _cffi_backend | |
| import cffi | |
| assert cffi.__version__ == "2.1.1", cffi.__version__ | |
| # backend version must match the cffi package version | |
| assert getattr(_cffi_backend, "__version__", None) in (None, "2.1.1") | |
| def _open_libc(ffi): | |
| import ctypes.util | |
| for name in ("libc.so", "libc.so.6", "c"): | |
| try: | |
| return ffi.dlopen(name) | |
| except OSError: | |
| continue | |
| found = ctypes.util.find_library("c") | |
| if found: | |
| return ffi.dlopen(found) | |
| raise NotImplementedError("no libc available on this platform") | |
| def cffi_libc_call(): | |
| import cffi | |
| ffi = cffi.FFI() | |
| ffi.cdef("size_t strlen(const char *s);") | |
| lib = _open_libc(ffi) | |
| s = ffi.new("char[]", b"android-cffi") | |
| n = lib.strlen(s) | |
| assert n == 12, n | |
| def cffi_abi_mode(): | |
| import cffi | |
| ffi = cffi.FFI() | |
| ffi.cdef("int abs(int x);") | |
| lib = _open_libc(ffi) | |
| assert lib.abs(-5) == 5 | |
| def cffi_struct(): | |
| import cffi | |
| ffi = cffi.FFI() | |
| ffi.cdef( | |
| "typedef struct { int x; int y; } point_t; " | |
| "point_t make_point(int x, int y);" | |
| ) | |
| # use ABI mode call into a trivial function we link ourselves via ctypes-free | |
| # path is not available, so just validate the type machinery and FFI().new() | |
| p = ffi.new("point_t*") | |
| p.x = 3 | |
| p.y = 4 | |
| assert p.x == 3 and p.y == 4 | |
| def cffi_callback(): | |
| import cffi | |
| ffi = cffi.FFI() | |
| ffi.cdef("typedef int (*cb_t)(int);") | |
| calls = [] | |
| cb = ffi.callback("int(int)", lambda n: (calls.append(n), n + 1)[1]) | |
| assert cb(10) == 11 | |
| assert calls == [10] | |
| # --------------------------------------------------------------------------- | |
| def main(): | |
| quick = "--quick" in sys.argv | |
| section("1. cryptography imports (full surface)") | |
| test("import core (version + _rust.so + fernet)", imports_core) | |
| test("import bindings/backends", imports_bindings) | |
| test("import primitives", imports_primitives) | |
| test("import asymmetric", imports_asymmetric) | |
| test("import x509", imports_x509) | |
| section("2. hashes / hmac / cmac") | |
| test("SHA256", hashes) | |
| test("SHA512", sha512) | |
| test("SHA3 / BLAKE2", sha3_and_blake2) | |
| test("HMAC", hmac_) | |
| test("CMAC", cmac) | |
| section("3. symmetric ciphers") | |
| test("AES-GCM", aes_gcm) | |
| test("AES-CBC", aes_cbc) | |
| test("ChaCha20-Poly1305", chacha20_poly1305) | |
| test("PKCS7 padding", padding_) | |
| test("AES keywrap", keywrap_) | |
| section("4. asymmetric") | |
| test("RSA sign/verify + PEM roundtrip", rsa_sign_verify) | |
| test("RSA-OAEP", rsa_oaep) | |
| test("EC P-256", ec_) | |
| test("Ed25519", ed25519_) | |
| test("Ed448", ed448_) | |
| test("X25519 key exchange", x25519_) | |
| test("X448 key exchange", x448_) | |
| test("DH", dh_) | |
| test("DSA", dsa_) | |
| section("5. KDF") | |
| test("HKDF", hkdf_) | |
| test("PBKDF2", pbkdf2_) | |
| test("scrypt", scrypt_) | |
| section("6. X.509") | |
| test("self-signed cert build+parse+verify", x509_selfsigned) | |
| section("7. Fernet") | |
| test("Fernet encrypt/decrypt", fernet_) | |
| section("8. cffi") | |
| test("cffi import (backend version match)", cffi_import) | |
| test("cffi dlopen libc + strlen", cffi_libc_call) | |
| test("cffi ABI mode abs()", cffi_abi_mode) | |
| test("cffi struct", cffi_struct) | |
| test("cffi callback", cffi_callback) | |
| print() | |
| print("=" * 60) | |
| print("SUMMARY") | |
| print("=" * 60) | |
| fails = 0 | |
| skips = 0 | |
| for name, status, why in RESULTS: | |
| mark = " OK" if status == "PASS" else (" SKIP" if status == "SKIP" else "FAIL") | |
| print("%s %s" % (mark, name)) | |
| if why: | |
| print(" -> %s" % why) | |
| if status == "FAIL": | |
| fails += 1 | |
| elif status == "SKIP": | |
| skips += 1 | |
| print() | |
| passed = len(RESULTS) - fails - skips | |
| print("passed=%d skipped=%d failed=%d" % (passed, skips, fails)) | |
| if fails: | |
| print("RESULT: FAILED") | |
| elif skips and not quick: | |
| print("RESULT: PASSED (with informational skips)") | |
| else: | |
| print("RESULT: PASSED") | |
| sys.exit(1 if fails else 0) | |
| if __name__ == "__main__": | |
| main() | |