personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

link: port test_ca to solstone fork

+114
+114
tests/link/test_ca.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 4 + """CA generation, CSR signing, and attestation minting for the solstone fork.""" 5 + 6 + from __future__ import annotations 7 + 8 + import base64 9 + import json 10 + from pathlib import Path 11 + 12 + from cryptography import x509 13 + from cryptography.hazmat.primitives import hashes, serialization 14 + from cryptography.hazmat.primitives.asymmetric import ec 15 + from cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signature 16 + 17 + from think.link.ca import ( 18 + cert_fingerprint, 19 + generate_ca, 20 + load_ca, 21 + load_or_generate_ca, 22 + mint_attestation, 23 + sign_csr, 24 + ) 25 + 26 + 27 + def test_generate_and_reload(tmp_path: Path) -> None: 28 + ca_dir = tmp_path / "ca" 29 + generated = generate_ca(ca_dir) 30 + reloaded = load_ca(ca_dir) 31 + 32 + assert generated.fingerprint_sha256() == reloaded.fingerprint_sha256() 33 + assert (ca_dir / "cert.pem").exists() 34 + assert (ca_dir / "private.pem").exists() 35 + assert (ca_dir / "private.pem").stat().st_mode & 0o777 == 0o600 36 + 37 + 38 + def test_load_or_generate_is_idempotent(tmp_path: Path) -> None: 39 + ca_dir = tmp_path / "ca" 40 + 41 + first = load_or_generate_ca(ca_dir) 42 + second = load_or_generate_ca(ca_dir) 43 + 44 + assert first.fingerprint_sha256() == second.fingerprint_sha256() 45 + 46 + 47 + def test_sign_csr_produces_valid_cert_chained_to_ca(tmp_path: Path) -> None: 48 + ca = generate_ca(tmp_path / "ca") 49 + key = ec.generate_private_key(ec.SECP256R1()) 50 + csr = ( 51 + x509.CertificateSigningRequestBuilder() 52 + .subject_name( 53 + x509.Name([x509.NameAttribute(x509.NameOID.COMMON_NAME, "Jer's iPhone")]), 54 + ) 55 + .sign(key, hashes.SHA256()) 56 + ) 57 + csr_pem = csr.public_bytes(serialization.Encoding.PEM).decode("ascii") 58 + 59 + cert_pem, fp = sign_csr(ca, csr_pem, "Jer's iPhone") 60 + 61 + assert isinstance(cert_pem, str) 62 + assert isinstance(fp, str) 63 + assert fp.startswith("sha256:") 64 + assert len(fp) == 71 65 + 66 + cert = x509.load_pem_x509_certificate(cert_pem.encode("ascii")) 67 + assert cert.issuer == ca.cert.subject 68 + assert cert_fingerprint(cert_pem) == fp 69 + 70 + 71 + def test_attestation_signed_by_ca_verifies(tmp_path: Path) -> None: 72 + ca = generate_ca(tmp_path / "ca") 73 + instance_id = "deadbeef-dead-beef-dead-beefdeadbeef" 74 + device_fp = "sha256:" + "aa" * 32 75 + 76 + jwt = mint_attestation(ca, instance_id, device_fp, now=1_745_006_400) 77 + segments = jwt.split(".") 78 + 79 + assert len(segments) == 3 80 + header_b64, payload_b64, sig_b64 = segments 81 + 82 + header = json.loads(_b64_decode(header_b64)) 83 + payload = json.loads(_b64_decode(payload_b64)) 84 + raw_sig = _b64_decode(sig_b64) 85 + 86 + assert header == {"alg": "ES256", "typ": "home-attest"} 87 + assert payload["iss"] == f"home:{instance_id}" 88 + assert payload["aud"] == "spl-relay" 89 + assert payload["scope"] == "device.enroll" 90 + assert payload["instance_id"] == instance_id 91 + assert payload["device_fp"] == device_fp 92 + assert payload["iat"] == 1_745_006_400 93 + assert payload["exp"] == 1_745_006_640 94 + assert payload["exp"] - payload["iat"] == 240 95 + assert isinstance(payload["jti"], str) 96 + assert payload["jti"] 97 + 98 + assert len(raw_sig) == 64 99 + r = int.from_bytes(raw_sig[:32], "big") 100 + s = int.from_bytes(raw_sig[32:], "big") 101 + der_sig = encode_dss_signature(r, s) 102 + 103 + public_key = serialization.load_pem_public_key(ca.pubkey_spki_pem.encode("ascii")) 104 + assert isinstance(public_key, ec.EllipticCurvePublicKey) 105 + public_key.verify( 106 + der_sig, 107 + f"{header_b64}.{payload_b64}".encode("ascii"), 108 + ec.ECDSA(hashes.SHA256()), 109 + ) 110 + 111 + 112 + def _b64_decode(value: str) -> bytes: 113 + padding = "=" * (-len(value) % 4) 114 + return base64.urlsafe_b64decode(value + padding)