@@ -183,6 +183,55 @@ pub trait KeyManager {
183183}
184184
185185impl Agent {
186+ /// Sign raw bytes and return the base64-encoded signature.
187+ ///
188+ /// This is the byte-level equivalent of `sign_string`. Used by
189+ /// the email signing module where the payload is binary.
190+ pub fn sign_bytes ( & mut self , data : & [ u8 ] ) -> Result < Vec < u8 > , Box < dyn std:: error:: Error > > {
191+ let config = self . config . as_ref ( ) . ok_or (
192+ "Byte signing failed: agent configuration not initialized." ,
193+ ) ?;
194+ let key_algorithm = config. get_key_algorithm ( ) . map_err ( |e| {
195+ format ! ( "Byte signing failed: could not determine signing algorithm: {}" , e)
196+ } ) ?;
197+
198+ let binding = self . get_private_key ( ) . map_err ( |e| {
199+ format ! ( "Byte signing failed: private key not loaded: {}" , e)
200+ } ) ?;
201+
202+ let is_ephemeral = self . is_ephemeral ( ) ;
203+ let has_key_store = self . get_key_store ( ) . is_some ( ) ;
204+ let stored_algo = self . get_key_algorithm ( ) . cloned ( ) ;
205+ let ( key_bytes, ks_box) : ( Vec < u8 > , Box < dyn KeyStore > ) = if is_ephemeral {
206+ let raw = binding. expose_secret ( ) . clone ( ) ;
207+ let ks: Box < dyn KeyStore > = if has_key_store {
208+ let algo = stored_algo. as_deref ( ) . unwrap_or ( "pq2025" ) ;
209+ Box :: new ( crate :: keystore:: InMemoryKeyStore :: new ( algo) )
210+ } else {
211+ Box :: new ( FsEncryptedStore )
212+ } ;
213+ ( raw, ks)
214+ } else {
215+ let decrypted =
216+ crate :: crypt:: aes_encrypt:: decrypt_private_key_secure ( binding. expose_secret ( ) )
217+ . map_err ( |e| {
218+ format ! ( "Byte signing failed: could not decrypt private key: {}" , e)
219+ } ) ?;
220+ (
221+ decrypted. as_slice ( ) . to_vec ( ) ,
222+ Box :: new ( FsEncryptedStore ) as Box < dyn KeyStore > ,
223+ )
224+ } ;
225+
226+ let sig_bytes = ks_box
227+ . sign_detached ( & key_bytes, data, & key_algorithm)
228+ . map_err ( |e| {
229+ format ! ( "Byte signing failed: cryptographic signing operation failed: {}" , e)
230+ } ) ?;
231+
232+ Ok ( sig_bytes)
233+ }
234+
186235 /// Generate keys using a specific KeyStore implementation.
187236 /// For ephemeral agents, uses set_keys_raw (no AES encryption).
188237 /// For persistent agents, uses set_keys (AES-encrypts private key).
0 commit comments