1use anyhow::Result;
2
3use serde::{Deserialize, Serialize};
4use serde_json::{json, Value};
5
6use sha2::{Digest, Sha224, Sha256, Sha384, Sha512};
7use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
8
9use ed25519_dalek::{
10 ExpandedSecretKey, Keypair, PublicKey, SecretKey, Signature as EdDSASignature, Verifier,
11};
12use rand::rngs::OsRng;
13
14use crate::schemas::signature::SignatureAlgorithm;
15use crate::serde_utils::{bytes_to_hex, hex_to_bytes};
16use crate::Error;
17
18#[derive(Clone, Debug, Deserialize, Serialize, Default)]
19#[serde(rename_all = "kebab-case")]
20pub enum HashAlgorithm {
21 Sha224,
22 Sha256,
23 Sha384,
24 #[default]
25 Sha512,
26 Sha3_224,
27 Sha3_256,
28 Sha3_384,
29 Sha3_512,
30}
31
32#[derive(Clone, Debug, Deserialize, Serialize, Default)]
33pub enum EncryptionAlgorithm {
34 #[default]
35 EdDSA,
36 EdDSAOpenPGP,
37}
38
39#[derive(Deserialize, Serialize, Debug, Clone)]
40pub struct Key {
41 algorithm: EncryptionAlgorithm,
42 #[serde(serialize_with = "bytes_to_hex", deserialize_with = "hex_to_bytes")]
43 key: Vec<u8>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 parameters: Option<Value>,
46}
47
48impl From<[u8; 32]> for Key {
49 fn from(value: [u8; 32]) -> Self {
50 Self {
51 algorithm: EncryptionAlgorithm::EdDSA,
52 parameters: Some(json!({ "scheme": "Ed25519" })),
53 key: value.into(),
54 }
55 }
56}
57
58pub struct KeyPair {
59 pub public_key: Key,
60 pub private_key: Key,
61}
62
63pub fn create_key_pair() -> KeyPair {
64 let mut csprng = OsRng {};
65 let keypair = Keypair::generate(&mut csprng);
66 KeyPair {
67 public_key: keypair.public.to_bytes().into(),
68 private_key: keypair.secret.to_bytes().into(),
69 }
70}
71
72pub fn create_default_hash(value: &Value) -> Result<Vec<u8>, Error> {
73 create_hash(value, &HashAlgorithm::default())
74}
75
76pub fn create_hash(value: &Value, hash_algorithm: &HashAlgorithm) -> Result<Vec<u8>, Error> {
77 serde_json_canonicalizer::to_vec(value)
78 .map(|canonical_json| create_digest(canonical_json, hash_algorithm))
79 .map_err(|e| Error::JcsSerializationError(e.to_string()))
80}
81
82fn create_digest(input: impl AsRef<[u8]>, hash_algorithm: &HashAlgorithm) -> Vec<u8> {
83 match hash_algorithm {
85 HashAlgorithm::Sha224 => Sha224::digest(input).into_iter().collect(),
86 HashAlgorithm::Sha256 => Sha256::digest(input).into_iter().collect(),
87 HashAlgorithm::Sha384 => Sha384::digest(input).into_iter().collect(),
88 HashAlgorithm::Sha512 => Sha512::digest(input).into_iter().collect(),
89 HashAlgorithm::Sha3_224 => Sha3_224::digest(input).into_iter().collect(),
90 HashAlgorithm::Sha3_256 => Sha3_256::digest(input).into_iter().collect(),
91 HashAlgorithm::Sha3_384 => Sha3_384::digest(input).into_iter().collect(),
92 HashAlgorithm::Sha3_512 => Sha3_512::digest(input).into_iter().collect(),
93 }
94}
95
96pub fn sign_json(value: &Value, private_key: &Key) -> Result<(SignatureAlgorithm, Vec<u8>)> {
97 let canonical_json = serde_json_canonicalizer::to_vec(value)?;
98 let secret_key = SecretKey::from_bytes(&private_key.key)?;
99 let signature_value = sign_bytes(canonical_json, &secret_key);
100 let algorithm = SignatureAlgorithm::default();
101 Ok((algorithm, signature_value))
102}
103
104fn sign_bytes(bytes: impl AsRef<[u8]>, secret_key: &SecretKey) -> Vec<u8> {
105 let expanded_secret_key = ExpandedSecretKey::from(secret_key);
106 let public_key = PublicKey::from(secret_key);
107 let signature_value = expanded_secret_key.sign(bytes.as_ref(), &public_key);
108 signature_value.to_bytes().into()
109}
110
111pub fn verify_signature_json(
112 value: &Value,
113 signature_algorithm: &EncryptionAlgorithm,
114 signature_value: impl AsRef<[u8]>,
115 public_key: &Key,
116) -> Result<(), Error> {
117 let canonical_json = serde_json_canonicalizer::to_vec(value)
118 .map_err(|e| Error::JcsSerializationError(e.to_string()))?;
119 let eddsa_signature = EdDSASignature::from_bytes(signature_value.as_ref())
120 .map_err(|_| Error::InvalidSignatureValue)?;
121 let public_key = PublicKey::from_bytes(&public_key.key).map_err(|_| Error::InvalidPublicKey)?;
122 match signature_algorithm {
123 EncryptionAlgorithm::EdDSA => verify_bytes(canonical_json, &eddsa_signature, &public_key),
124 EncryptionAlgorithm::EdDSAOpenPGP => {
125 verify_bytes_openpgp(canonical_json, &eddsa_signature, &public_key)
126 }
127 }
128}
129
130fn verify_bytes_openpgp(
134 bytes: impl AsRef<[u8]>,
135 signature: &EdDSASignature,
136 public_key: &PublicKey,
137) -> Result<(), Error> {
138 let bytes_hash = create_digest(bytes, &HashAlgorithm::Sha512);
139 verify_bytes(bytes_hash, signature, public_key)
140}
141
142fn verify_bytes(
143 bytes: impl AsRef<[u8]>,
144 signature: &EdDSASignature,
145 public_key: &PublicKey,
146) -> Result<(), Error> {
147 public_key
148 .verify(bytes.as_ref(), signature)
149 .map_err(|_| Error::InvalidSignature)
150}