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