mirror of https://github.com/pyodide/pyodide.git
224 lines
6.7 KiB
Python
224 lines
6.7 KiB
Python
from hypothesis import HealthCheck, given, settings
|
|
from hypothesis.strategies import binary, integers
|
|
from pyodide_test_runner import run_in_pyodide
|
|
from pyodide_test_runner.fixture import selenium_context_manager
|
|
|
|
|
|
@run_in_pyodide(packages=["cryptography"])
|
|
def test_cryptography():
|
|
import base64
|
|
|
|
from cryptography.fernet import Fernet, MultiFernet
|
|
|
|
f1 = Fernet(base64.urlsafe_b64encode(b"\x00" * 32))
|
|
f2 = Fernet(base64.urlsafe_b64encode(b"\x01" * 32))
|
|
f = MultiFernet([f1, f2])
|
|
|
|
assert f1.decrypt(f.encrypt(b"abc")) == b"abc"
|
|
|
|
|
|
@run_in_pyodide(packages=["cryptography", "pytest"])
|
|
def test_der_reader_basic():
|
|
import pytest
|
|
from cryptography.hazmat._der import DERReader
|
|
|
|
reader = DERReader(b"123456789")
|
|
assert reader.read_byte() == ord(b"1")
|
|
assert reader.read_bytes(1).tobytes() == b"2"
|
|
assert reader.read_bytes(4).tobytes() == b"3456"
|
|
|
|
with pytest.raises(ValueError):
|
|
reader.read_bytes(4)
|
|
|
|
assert reader.read_bytes(3).tobytes() == b"789"
|
|
|
|
# The input is now empty.
|
|
with pytest.raises(ValueError):
|
|
reader.read_bytes(1)
|
|
with pytest.raises(ValueError):
|
|
reader.read_byte()
|
|
|
|
|
|
@run_in_pyodide(packages=["cryptography", "pytest"])
|
|
def test_der():
|
|
import pytest
|
|
from cryptography.hazmat._der import (
|
|
INTEGER,
|
|
NULL,
|
|
OCTET_STRING,
|
|
SEQUENCE,
|
|
DERReader,
|
|
encode_der,
|
|
encode_der_integer,
|
|
)
|
|
|
|
# This input is the following structure, using
|
|
# https://github.com/google/der-ascii
|
|
#
|
|
# SEQUENCE {
|
|
# SEQUENCE {
|
|
# NULL {}
|
|
# INTEGER { 42 }
|
|
# OCTET_STRING { "hello" }
|
|
# }
|
|
# }
|
|
der = b"\x30\x0e\x30\x0c\x05\x00\x02\x01\x2a\x04\x05\x68\x65\x6c\x6c\x6f"
|
|
reader = DERReader(der)
|
|
with pytest.raises(ValueError):
|
|
reader.check_empty()
|
|
|
|
with pytest.raises(ValueError):
|
|
with reader:
|
|
pass
|
|
|
|
with pytest.raises(ZeroDivisionError):
|
|
with DERReader(der):
|
|
raise ZeroDivisionError
|
|
|
|
# Parse the outer element.
|
|
outer = reader.read_element(SEQUENCE) # type: ignore[unreachable]
|
|
reader.check_empty()
|
|
assert outer.data.tobytes() == der[2:]
|
|
|
|
# Parse the outer element with read_any_element.
|
|
reader = DERReader(der)
|
|
tag, outer2 = reader.read_any_element()
|
|
reader.check_empty()
|
|
assert tag == SEQUENCE
|
|
assert outer2.data.tobytes() == der[2:]
|
|
|
|
# Parse the outer element with read_single_element.
|
|
outer3 = DERReader(der).read_single_element(SEQUENCE)
|
|
assert outer3.data.tobytes() == der[2:]
|
|
|
|
# read_single_element rejects trailing data.
|
|
with pytest.raises(ValueError):
|
|
DERReader(der + der).read_single_element(SEQUENCE)
|
|
|
|
# Continue parsing the structure.
|
|
inner = outer.read_element(SEQUENCE)
|
|
outer.check_empty()
|
|
|
|
# Parsing a missing optional element should work.
|
|
assert inner.read_optional_element(INTEGER) is None
|
|
|
|
null = inner.read_element(NULL)
|
|
null.check_empty()
|
|
|
|
# Parsing a present optional element should work.
|
|
integer = inner.read_optional_element(INTEGER)
|
|
assert integer.as_integer() == 42
|
|
|
|
octet_string = inner.read_element(OCTET_STRING)
|
|
assert octet_string.data.tobytes() == b"hello"
|
|
|
|
# Parsing a missing optional element should work when the input is empty.
|
|
inner.check_empty()
|
|
assert inner.read_optional_element(INTEGER) is None
|
|
|
|
# Re-encode the same structure.
|
|
der2 = encode_der(
|
|
SEQUENCE,
|
|
encode_der(
|
|
SEQUENCE,
|
|
encode_der(NULL),
|
|
encode_der(INTEGER, encode_der_integer(42)),
|
|
encode_der(OCTET_STRING, b"hello"),
|
|
),
|
|
)
|
|
assert der2 == der
|
|
|
|
|
|
@run_in_pyodide(packages=["cryptography"])
|
|
def test_der_lengths():
|
|
|
|
from cryptography.hazmat._der import OCTET_STRING, DERReader, encode_der
|
|
|
|
for [length, header] in [
|
|
# Single-byte lengths.
|
|
(0, b"\x04\x00"),
|
|
(1, b"\x04\x01"),
|
|
(2, b"\x04\x02"),
|
|
(127, b"\x04\x7f"),
|
|
# Long-form lengths.
|
|
(128, b"\x04\x81\x80"),
|
|
(129, b"\x04\x81\x81"),
|
|
(255, b"\x04\x81\xff"),
|
|
(0x100, b"\x04\x82\x01\x00"),
|
|
(0x101, b"\x04\x82\x01\x01"),
|
|
(0xFFFF, b"\x04\x82\xff\xff"),
|
|
(0x10000, b"\x04\x83\x01\x00\x00"),
|
|
]:
|
|
body = length * b"a"
|
|
der = header + body
|
|
|
|
reader = DERReader(der)
|
|
element = reader.read_element(OCTET_STRING)
|
|
reader.check_empty()
|
|
assert element.data.tobytes() == body
|
|
|
|
assert encode_der(OCTET_STRING, body) == der
|
|
|
|
|
|
@settings(suppress_health_check=[HealthCheck.too_slow], deadline=None)
|
|
@given(data=binary())
|
|
def test_fernet(selenium_module_scope, data):
|
|
sbytes = list(data)
|
|
with selenium_context_manager(selenium_module_scope) as selenium:
|
|
selenium.load_package("cryptography")
|
|
selenium.run(
|
|
f"""
|
|
from cryptography.fernet import Fernet
|
|
data = bytes({sbytes})
|
|
f = Fernet(Fernet.generate_key())
|
|
ct = f.encrypt(data)
|
|
assert f.decrypt(ct) == data
|
|
"""
|
|
)
|
|
|
|
|
|
@settings(suppress_health_check=[HealthCheck.too_slow], deadline=None)
|
|
@given(block_size=integers(min_value=1, max_value=255), data=binary())
|
|
def test_pkcs7(selenium_module_scope, block_size, data):
|
|
sbytes = list(data)
|
|
with selenium_context_manager(selenium_module_scope) as selenium:
|
|
selenium.load_package("cryptography")
|
|
selenium.run(
|
|
f"""
|
|
from cryptography.hazmat.primitives.padding import ANSIX923, PKCS7
|
|
block_size = {block_size}
|
|
data = bytes({sbytes})
|
|
# Generate in [1, 31] so we can easily get block_size in bits by
|
|
# multiplying by 8.
|
|
p = PKCS7(block_size=block_size * 8)
|
|
padder = p.padder()
|
|
unpadder = p.unpadder()
|
|
|
|
padded = padder.update(data) + padder.finalize()
|
|
|
|
assert unpadder.update(padded) + unpadder.finalize() == data
|
|
"""
|
|
)
|
|
|
|
|
|
@settings(suppress_health_check=[HealthCheck.too_slow], deadline=None)
|
|
@given(block_size=integers(min_value=1, max_value=255), data=binary())
|
|
def test_ansix923(selenium_module_scope, block_size, data):
|
|
sbytes = list(data)
|
|
with selenium_context_manager(selenium_module_scope) as selenium:
|
|
selenium.load_package("cryptography")
|
|
selenium.run(
|
|
f"""
|
|
from cryptography.hazmat.primitives.padding import ANSIX923, PKCS7
|
|
block_size = {block_size}
|
|
data = bytes({sbytes})
|
|
a = ANSIX923(block_size=block_size * 8)
|
|
padder = a.padder()
|
|
unpadder = a.unpadder()
|
|
|
|
padded = padder.update(data) + padder.finalize()
|
|
|
|
assert unpadder.update(padded) + unpadder.finalize() == data
|
|
"""
|
|
)
|