otp_std/secret/
encoding.rs

1//! Secret encoding and decoding.
2
3use base32::Alphabet;
4use miette::Diagnostic;
5use thiserror::Error;
6
7use crate::macros::errors;
8
9/// Represents errors that can occur when secret decoding fails.
10#[derive(Debug, Error, Diagnostic)]
11#[error("failed to decode `{secret}` secret")]
12#[diagnostic(code(otp_std::secret::encoding), help("make sure the secret is valid"))]
13pub struct Error {
14    /// The encoded secret that could not be decoded.
15    pub secret: String,
16}
17
18impl Error {
19    /// Constructs [`Self`].
20    pub const fn new(secret: String) -> Self {
21        Self { secret }
22    }
23}
24
25/// The alphabet used for encoding and decoding OTP secrets.
26pub const ALPHABET: Alphabet = Alphabet::Rfc4648 { padding: false };
27
28/// Encodes the given secret.
29pub fn encode<S: AsRef<[u8]>>(secret: S) -> String {
30    base32::encode(ALPHABET, secret.as_ref())
31}
32
33errors! {
34    Type = Error,
35    Hack = $,
36    error => new(secret => to_owned),
37}
38
39/// Decodes the given secret.
40///
41/// # Errors
42///
43/// Returns [`struct@Error`] if the secret could not be decoded.
44pub fn decode<S: AsRef<str>>(secret: S) -> Result<Vec<u8>, Error> {
45    fn decode_inner(secret: &str) -> Result<Vec<u8>, Error> {
46        base32::decode(ALPHABET, secret).ok_or_else(|| error!(secret))
47    }
48
49    decode_inner(secret.as_ref())
50}