1#[cfg(feature = "gpg")]
2use sequoia_openpgp::{
3 cert::CertParser,
4 crypto::SessionKey,
5 parse::Parse,
6 policy::StandardPolicy,
7 serialize::stream::{Armorer, Encryptor, LiteralWriter, Message},
8 Cert, KeyHandle,
9};
10
11#[cfg(feature = "gpg")]
12use std::io::{Read, Write};
13
14use crate::crypto::CryptoKey;
15use crate::error::{GitCryptError, Result};
16
17pub struct GpgManager;
18
19impl GpgManager {
20 #[cfg(feature = "gpg")]
22 pub fn encrypt_key_for_recipient(
23 key: &CryptoKey,
24 recipient_fingerprint: &str,
25 ) -> Result<Vec<u8>> {
26 let p = &StandardPolicy::new();
27
28 let cert = Self::get_cert_from_keyring(recipient_fingerprint)?;
31
32 let recipients = cert
34 .keys()
35 .with_policy(p, None)
36 .supported()
37 .for_transport_encryption()
38 .map(|ka| ka.key())
39 .collect::<Vec<_>>();
40
41 if recipients.is_empty() {
42 return Err(GitCryptError::Gpg(
43 "No encryption-capable keys found for recipient".into(),
44 ));
45 }
46
47 let mut encrypted = Vec::new();
49 {
50 let message = Message::new(&mut encrypted);
51 let message = Armorer::new(message).build()
52 .map_err(|e| GitCryptError::Gpg(e.to_string()))?;
53 let message = Encryptor::for_recipients(message, recipients)
54 .build()
55 .map_err(|e| GitCryptError::Gpg(e.to_string()))?;
56 let mut message = LiteralWriter::new(message)
57 .build()
58 .map_err(|e| GitCryptError::Gpg(e.to_string()))?;
59
60 message.write_all(key.as_bytes())
61 .map_err(|e| GitCryptError::Gpg(e.to_string()))?;
62 message.finalize()
63 .map_err(|e| GitCryptError::Gpg(e.to_string()))?;
64 }
65
66 Ok(encrypted)
67 }
68
69 #[cfg(not(feature = "gpg"))]
71 pub fn encrypt_key_for_recipient(
72 _key: &CryptoKey,
73 _recipient_fingerprint: &str,
74 ) -> Result<Vec<u8>> {
75 Err(GitCryptError::Gpg(
76 "GPG support not enabled. Rebuild with --features gpg".into(),
77 ))
78 }
79
80 #[cfg(feature = "gpg")]
82 pub fn decrypt_key(encrypted_data: &[u8]) -> Result<CryptoKey> {
83 Err(GitCryptError::Gpg(
90 "GPG decryption requires private key access - to be implemented".into(),
91 ))
92 }
93
94 #[cfg(not(feature = "gpg"))]
96 pub fn decrypt_key(_encrypted_data: &[u8]) -> Result<CryptoKey> {
97 Err(GitCryptError::Gpg(
98 "GPG support not enabled. Rebuild with --features gpg".into(),
99 ))
100 }
101
102 #[cfg(feature = "gpg")]
104 fn get_cert_from_keyring(fingerprint: &str) -> Result<Cert> {
105 Err(GitCryptError::Gpg(
111 format!("Certificate lookup not yet implemented for: {}", fingerprint),
112 ))
113 }
114
115 #[cfg(feature = "gpg")]
117 pub fn list_keys() -> Result<Vec<String>> {
118 Err(GitCryptError::Gpg("Key listing not yet implemented".into()))
120 }
121
122 #[cfg(not(feature = "gpg"))]
124 pub fn list_keys() -> Result<Vec<String>> {
125 Err(GitCryptError::Gpg(
126 "GPG support not enabled. Rebuild with --features gpg".into(),
127 ))
128 }
129}