Skip to main content

crypto/
state_signature.rs

1// SPDX-License-Identifier: Apache-2.0
2//! State-signature helpers that depend on crypto implementations.
3
4use objects::object::{ContentHash, StateSignature};
5
6use crate::{Signer, SignerError, verify_state_signature};
7
8/// Error type for state signature operations.
9#[derive(Debug, thiserror::Error)]
10pub enum StateSignatureError {
11    #[error("unsupported signature algorithm: {0}")]
12    UnsupportedAlgorithm(String),
13    #[error("invalid public key: {0}")]
14    InvalidPublicKey(String),
15    #[error("invalid signature: {0}")]
16    InvalidSignature(String),
17    #[error("hex decode error: {0}")]
18    Hex(#[from] hex::FromHexError),
19    #[error("signer error: {0}")]
20    Signer(#[from] SignerError),
21}
22
23pub fn state_signature_from_signer(
24    hash: &ContentHash,
25    signer: &dyn Signer,
26) -> Result<StateSignature, StateSignatureError> {
27    let signature = signer.sign(hash.as_bytes())?;
28
29    Ok(StateSignature {
30        algorithm: signer.algorithm().to_string(),
31        public_key: hex::encode(signer.public_key()),
32        signature: hex::encode(&signature),
33    })
34}
35
36pub fn verify_state_signature_bytes(
37    signature: &StateSignature,
38    hash: &ContentHash,
39) -> Result<(), StateSignatureError> {
40    let public_key = hex::decode(&signature.public_key)?;
41    let signature_bytes = hex::decode(&signature.signature)?;
42
43    verify_state_signature(hash, &signature.algorithm, &public_key, &signature_bytes)
44        .map_err(StateSignatureError::from)
45}
46
47pub fn public_key_bytes(signature: &StateSignature) -> Result<Vec<u8>, StateSignatureError> {
48    hex::decode(&signature.public_key).map_err(StateSignatureError::from)
49}
50
51pub fn signature_bytes(signature: &StateSignature) -> Result<Vec<u8>, StateSignatureError> {
52    hex::decode(&signature.signature).map_err(StateSignatureError::from)
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use crate::Ed25519Signer;
59
60    fn make_test_hash() -> ContentHash {
61        ContentHash::from_bytes([1u8; 32])
62    }
63
64    #[test]
65    fn test_sign_verify_ed25519() {
66        let signer = Ed25519Signer::generate().expect("generate key");
67        let hash = make_test_hash();
68
69        let sig = state_signature_from_signer(&hash, &signer).expect("sign state");
70        assert_eq!(sig.algorithm(), "ed25519");
71
72        verify_state_signature_bytes(&sig, &hash).expect("verify should not error");
73    }
74}