fidius_test/signing.rs
1// Copyright 2026 Colliery, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Deterministic signing fixtures for tests that exercise Fidius signature
16//! verification flows.
17//!
18//! These helpers are **not secure** — the signing keys are derived from a
19//! single byte seed. They exist so tests can sign and verify plugin dylibs
20//! without generating fresh random keys each run.
21
22use std::path::Path;
23
24use ed25519_dalek::{Signer, SigningKey, VerifyingKey};
25
26/// Deterministic Ed25519 keypair derived from `seed` repeated 32 times.
27///
28/// Use different seeds across tests that need distinct keys (e.g., to verify
29/// that a wrong-key signature is rejected).
30pub fn fixture_keypair_with_seed(seed: u8) -> (SigningKey, VerifyingKey) {
31 let signing = SigningKey::from_bytes(&[seed; 32]);
32 let verifying = signing.verifying_key();
33 (signing, verifying)
34}
35
36/// Convenience: [`fixture_keypair_with_seed(1)`](fixture_keypair_with_seed).
37pub fn fixture_keypair() -> (SigningKey, VerifyingKey) {
38 fixture_keypair_with_seed(1)
39}
40
41/// Sign a plugin dylib in place by writing a detached `.sig` file alongside it.
42///
43/// The signature file uses the same naming convention as `fidius sign` —
44/// appends `.sig` to the full filename (e.g., `foo.dylib` → `foo.dylib.sig`).
45pub fn sign_dylib(dylib: &Path, key: &SigningKey) -> std::io::Result<()> {
46 let bytes = std::fs::read(dylib)?;
47 let signature = key.sign(&bytes);
48 let sig_path = dylib.with_extension(format!(
49 "{}.sig",
50 dylib.extension().and_then(|e| e.to_str()).unwrap_or("")
51 ));
52 std::fs::write(sig_path, signature.to_bytes())?;
53 Ok(())
54}