* Flex-O Cross-Platform Signing System This document defines how Flex-O performs cryptographic signing across Linux, Windows, and macOS using a single interoperable workflow. ** Requirements - PKCS#7 / CMS signatures - RSA-4096 - DER output format (Windows/macOS native) - No Python crypto libraries - OS-native signing tooling * 1. Key and Certificate Creation (Universal) ** 1.1 Generate a private key (recommended: RSA-4096) #+begin_src bash openssl genrsa -out mykey.pem 4096 #+end_src ** 1.2 Generate an X.509 certificate #+begin_src bash openssl req -new -x509 -key mykey.pem -out mycert.pem -days 3650 -sha256 #+end_src Result: - mykey.pem → private key - mycert.pem → certificate (public key) * 2. Import Certificates into Each Platform ** 2.1 Linux No import required. Use PEM files directly. ** 2.2 Windows (PKCS#12 required) Create PKCS#12 bundle: #+begin_src bash openssl pkcs12 -export -out flexo.pfx -inkey mykey.pem -in mycert.pem #+end_src Import into user certificate store: #+begin_src bash certutil -user -p PASSWORD -importpfx flexo.pfx #+end_src ** 2.3 macOS (PKCS#12) #+begin_src bash openssl pkcs12 -export -out flexo.p12 -inkey mykey.pem -in mycert.pem #+end_src Import: #+begin_src bash security import flexo.p12 -k ~/Library/Keychains/login.keychain-db #+end_src * 3. Cross-Platform Signing Commands ** 3.1 Linux (OpenSSL CMS / DER) #+begin_src bash openssl cms -sign \ -binary \ -in data.txt \ -signer mycert.pem \ -inkey mykey.pem \ -outform DER \ -out signature.p7s #+end_src ** 3.2 Windows (certutil) #+begin_src bash certutil -sign data.txt signature.p7s #+end_src ** 3.3 macOS (`security cms`) #+begin_src bash security cms -S \ -N "Common Name of Cert" \ -i data.txt \ -o signature.p7s #+end_src All three platforms produce binary DER PKCS#7 signatures. * 4. Cross-Platform Verification ** 4.1 Linux (OpenSSL) #+begin_src bash openssl cms -verify \ -in signature.p7s \ -inform DER \ -content data.txt \ -CAfile mycert.pem \ -purpose any \ -out /dev/null #+end_src ** 4.2 Windows #+begin_src bash certutil -verify signature.p7s data.txt #+end_src ** 4.3 macOS #+begin_src bash security cms -D -i signature.p7s > verified.txt #+end_src * 5. Flex-O Signing Specification ** 5.1 Key Requirements - RSA-4096 - X.509 certificate - Valid for ≥ 10 years ** 5.2 Signature Format Requirements - PKCS#7/CMS - Binary DER form - Signing certificate must be embedded ** 5.3 Verification Requirements - Must work with OpenSSL CMS - No dependency on OS certificate stores - Must accept DER PKCS#7 signatures ** 5.4 Flex-O Signature Entity Schema Required fields: - signed_entity: FlexOID - signer_id: UUID - signature_data: base64(PKCS7 DER blob) - signature_type: "PKCS7-DER" - certificate_thumbprint: SHA-1 thumbprint - comment: optional ** 5.5 Security Assumptions - Flex-O never stores private keys - OS handles private key protection - Only public certificates embedded in signatures * 6. Refer to certificates ** Linux #+BEGIN_SRC python cert_ref = CertificateReference( platform="LINUX", identifier="/etc/flexo/certs/mycert.pem", private_key_path="$HOME/.flexo/mykey.pem", public_cert_path="/etc/flexo/certs/mycert.pem", ) backend = create_backend(cert_ref) signature_bytes = backend.sign(b"hello world") #+END_SRC ** Windows #+BEGIN_SRC python cert_ref = CertificateReference( platform="WINDOWS", identifier="E1A2B3C4D5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B", # Thumbprint ) backend = create_backend(cert_ref) signature_bytes = backend.sign(b"hello world") #+END_SRC ** MacOS #+BEGIN_SRC python cert_ref = CertificateReference( platform="MACOS", identifier="FlexOSigner", # Common Name (CN) public_cert_path="/Users/enno/certs/FlexOSigner.pem" ) backend = create_backend(cert_ref) signature_bytes = backend.sign(b"hello world") #+END_SRC * 8. Flex-O Signature Entity #+begin_src python @dataclass class Signature(FlexoEntity): ENTITY_TYPE = EntityType.OUTPUT signed_entity: Optional[FlexOID] = None signer_id: Optional[UUID] = None signature_data: str = "" # Base64 of PKCS#7 DER signature_type: str = "PKCS7-DER" certificate_thumbprint: str = "" comment: Optional[str] = None @property def text_seed(self) -> str: return f"{self.signed_entity}:{self.signer_id}:{self.certificate_thumbprint}" #+end_src