identity_kit/sd_jwt_vc/
hash.rs1use core::fmt;
4use core::str::FromStr;
5
6use serde::{Deserialize, Deserializer, Serialize, Serializer};
7use sha2::Digest as _;
8
9use super::SdJwtError;
10use crate::jose::base64url;
11
12#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
32#[non_exhaustive]
33pub enum HashAlgorithm {
34 #[default]
36 Sha256,
37 Sha384,
39 Sha512,
41}
42
43impl HashAlgorithm {
44 pub const CLAIM: &'static str = "_sd_alg";
46
47 pub const fn name(self) -> &'static str {
49 match self {
50 Self::Sha256 => "sha-256",
51 Self::Sha384 => "sha-384",
52 Self::Sha512 => "sha-512",
53 }
54 }
55
56 pub fn parse(name: &str) -> Result<Self, SdJwtError> {
62 match name {
63 "sha-256" => Ok(Self::Sha256),
64 "sha-384" => Ok(Self::Sha384),
65 "sha-512" => Ok(Self::Sha512),
66 _ => Err(SdJwtError::UnsupportedHashAlgorithm(name.to_owned())),
67 }
68 }
69
70 pub fn digest(self, data: &[u8]) -> String {
72 let digest = match self {
73 Self::Sha256 => sha2::Sha256::digest(data).to_vec(),
74 Self::Sha384 => sha2::Sha384::digest(data).to_vec(),
75 Self::Sha512 => sha2::Sha512::digest(data).to_vec(),
76 };
77 base64url::encode(&digest)
78 }
79}
80
81impl fmt::Display for HashAlgorithm {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 f.write_str(self.name())
84 }
85}
86
87impl FromStr for HashAlgorithm {
88 type Err = SdJwtError;
89
90 fn from_str(s: &str) -> Result<Self, Self::Err> {
91 Self::parse(s)
92 }
93}
94
95impl Serialize for HashAlgorithm {
96 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
97 serializer.serialize_str(self.name())
98 }
99}
100
101impl<'de> Deserialize<'de> for HashAlgorithm {
102 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
103 let name = String::deserialize(deserializer)?;
104 Self::parse(&name).map_err(serde::de::Error::custom)
105 }
106}