1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
//! Cryptographic signing of data.
//!
//! # Purpose
//!
//! This module defines the [`Signer`] trait, which abstracts the process of
//! producing cryptographic signatures over arbitrary byte slices. In a
//! version control system, signatures are typically used to attest to the
//! authenticity and integrity of [`Commit`](crate::Commit) and
//! [`Tag`](crate::Tag) objects, allowing users to verify that an object was
//! indeed created by the claimed author.
//!
//! # Design Rationale
//!
//! Signing is separated into a trait for several reasons:
//!
//! - **Algorithm agnosticism**: Different deployments may choose different
//! signature schemes (Ed25519, RSA, ECDSA, etc.). The trait contract only
//! requires that a signer transforms bytes into a signature, so the rest
//! of the system remains independent of the specific algorithm.
//! - **Testability**: Dummy or deterministic signers can be injected in unit
//! tests, avoiding the need for actual private keys or hardware signing
//! modules.
//! - **Stateful signing**: The trait method takes `&mut self` because signing
//! often requires mutable internal state. For example, hardware security
//! modules may maintain session state, or deterministic nonce generation
//! may need a counter to prevent reuse.
//! - **Flexible output**: The signature is returned as a `Vec<u8>` because
//! different algorithms produce signatures of varying lengths. Returning a
//! byte vector keeps the trait fully generic.
//!
//! # Why `&mut self`?
//!
//! The [`Signer::sign`] method takes `&mut self` rather than `&self`. This
//! design choice reflects the fact that signing often involves mutable
//! internal state:
//!
//! - Cryptographic libraries may use a stateful random number generator or
//! a nonce counter that must be advanced after each signature.
//! - Hardware security modules may maintain session keys that change over
//! time.
//! - Some algorithms require precomputation caches that are built lazily.
//!
//! Using `&mut self` ensures that implementations can safely manage such
//! state without interior mutability or synchronization overhead.
//!
//! # Error Handling
//!
//! The signing operation may fail for various reasons, including:
//!
//! - A missing or invalid private key.
//! - Hardware module unavailability.
//! - Algorithm-specific constraints (e.g., message too long for RSA).
//!
//! The trait therefore returns [`Result<Vec<u8>, VctrlError>`], allowing
//! implementations to report failures through the crate's unified error type.
//! The most common error variant is
//! [`VctrlError::Other`](crate::VctrlError::Other), which can carry a
//! descriptive message.
//!
//! # Internal Mechanism
//!
//! A typical implementation will:
//!
//! 1. Access the private key or signing context stored in `self`.
//! 2. Feed the provided `data` into the signature algorithm.
//! 3. Return the resulting signature as a byte vector.
//!
//! The exact steps depend on the algorithm, but the trait ensures that the
//! interface remains consistent across all backends.
//!
//! # Examples
//!
//! A simple deterministic signer that returns the data itself as the
//! signature:
//!
//! ```
//! use libvctrl_handler::{Signer, VctrlError};
//!
//! struct IdentitySigner;
//!
//! impl Signer for IdentitySigner {
//! fn sign(&mut self, data: &[u8]) -> Result<Vec<u8>, VctrlError> {
//! Ok(data.to_vec())
//! }
//! }
//!
//! let mut signer = IdentitySigner;
//! let signature = signer.sign(b"hello").unwrap();
//! assert_eq!(signature, b"hello");
//! ```
use crateVctrlError;
/// Defines the interface for signing data cryptographically.
///
/// # Purpose
///
/// A `Signer` produces a cryptographic signature over a byte slice, typically
/// to attest to the authenticity of a [`Commit`](crate::Commit) or
/// [`Tag`](crate::Tag). The trait is intentionally minimal: it only specifies
/// the signing operation itself, leaving algorithm selection and key
/// management to the implementation.
///
/// # Design Rationale
///
/// The trait returns a `Vec<u8>` to remain agnostic to the underlying
/// signature algorithm (e.g., Ed25519, RSA, ECDSA). The input is a `&[u8]`
/// slice, allowing the caller to sign any serialized object or raw bytes
/// without requiring a specific type. The method takes `&mut self` because
/// signing often involves stateful operations (nonce generation, session
/// keys, or hardware module sessions).
///
/// # Why Not a Generic Input?
///
/// The input is a plain byte slice rather than a generic type to keep the
/// trait simple and avoid imposing serialization requirements on the data
/// being signed. Callers are responsible for converting their objects to
/// bytes (e.g., using an [`Encoder`](crate::Encoder)) before calling
/// [`sign`](Signer::sign).
///
/// # Why `Result<Vec<u8>>`?
///
/// Signing is fallible because the private key may be missing, the hardware
/// module may be unavailable, or the algorithm may reject the input length.
/// The return type captures both success (as a byte vector) and failure (as
/// a [`VctrlError`]).
///
/// # How It Works Internally
///
/// An implementation receives the raw bytes and returns a signature. It is
/// responsible for:
///
/// - Accessing the private key or signing context.
/// - Applying the signature algorithm.
/// - Returning the signature bytes in the algorithm's native encoding.
///
/// # Examples
///
/// A dummy signer that signs by simply copying the input:
///
/// ```
/// use libvctrl_handler::{Signer, VctrlError};
///
/// struct DummySigner;
///
/// impl Signer for DummySigner {
/// fn sign(&mut self, data: &[u8]) -> Result<Vec<u8>, VctrlError> {
/// Ok(data.to_vec())
/// }
/// }
///
/// let mut signer = DummySigner;
/// let sig = signer.sign(b"msg").unwrap();
/// assert_eq!(sig, b"msg");
/// ```