signstar_yubihsm2/
user.rs1use std::path::PathBuf;
4
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7use signstar_crypto::{passphrase::Passphrase, traits::UserWithPassphrase};
8use yubihsm::object::Id;
9
10#[derive(Debug)]
16#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
17pub struct FileBackedCredentials {
18 pub(crate) id: Id,
19 passphrase_file: PathBuf,
20}
21
22impl TryFrom<&FileBackedCredentials> for yubihsm::Credentials {
23 type Error = crate::Error;
24
25 fn try_from(value: &FileBackedCredentials) -> Result<Self, Self::Error> {
32 Ok(Self::from(&Credentials::try_from(value)?))
33 }
34}
35
36#[derive(Clone, Debug)]
41#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
42pub struct Credentials {
43 id: Id,
44 passphrase: Passphrase,
45}
46
47impl Credentials {
48 pub fn new(id: Id, passphrase: Passphrase) -> Self {
62 Self { id, passphrase }
63 }
64
65 pub fn id(&self) -> Id {
67 self.id
68 }
69}
70
71impl UserWithPassphrase for Credentials {
72 fn user(&self) -> String {
73 self.id.to_string()
74 }
75
76 fn passphrase(&self) -> &Passphrase {
77 &self.passphrase
78 }
79}
80
81impl From<&Credentials> for yubihsm::Credentials {
82 fn from(value: &Credentials) -> Self {
83 Self::from_password(value.id, value.passphrase.expose_borrowed().as_bytes())
84 }
85}
86
87impl TryFrom<&FileBackedCredentials> for Credentials {
88 type Error = crate::Error;
89
90 fn try_from(value: &FileBackedCredentials) -> Result<Self, Self::Error> {
97 Ok(Credentials::new(
98 value.id,
99 Passphrase::try_from(value.passphrase_file.as_path())?,
100 ))
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use std::io::Write;
107
108 use tempfile::{NamedTempFile, TempDir};
109 use testresult::TestResult;
110
111 use super::*;
112
113 #[test]
114 fn credentials_user_with_passphrase() -> TestResult {
115 let credentials = Credentials::new("1".parse()?, Passphrase::generate(None));
116 assert_eq!(credentials.user(), "1");
117 assert_eq!(
118 credentials.passphrase().expose_borrowed().len(),
119 Passphrase::DEFAULT_LENGTH
120 );
121
122 Ok(())
123 }
124
125 #[test]
127 fn yubihsm_credentials_try_from_file_backed_credentials_succeeds() -> TestResult {
128 let temp_file = {
129 let mut temp_file = NamedTempFile::new()?;
130 temp_file.write_all("passphrase".as_bytes())?;
131 temp_file
132 };
133 let file_backed_credentials = FileBackedCredentials {
134 id: "1".parse()?,
135 passphrase_file: temp_file.path().to_path_buf(),
136 };
137 let _creds = yubihsm::Credentials::try_from(&file_backed_credentials)?;
138
139 Ok(())
140 }
141
142 #[test]
145 fn yubihsm_credentials_try_from_file_backed_credentials_fails_on_dir() -> TestResult {
146 let temp_file = TempDir::new()?;
147 let file_backed_credentials = FileBackedCredentials {
148 id: "1".parse()?,
149 passphrase_file: temp_file.path().to_path_buf(),
150 };
151 assert!(yubihsm::Credentials::try_from(&file_backed_credentials).is_err());
152
153 Ok(())
154 }
155}