Overview
The signature module provides structures for creating and verifying digital signatures in TAPLE. It includes the Signature struct that contains signature metadata and the Signed<T> wrapper for signed data entities.
Signature Struct
pub struct Signature {
pub signer: KeyIdentifier,
pub timestamp: TimeStamp,
pub content_hash: DigestIdentifier,
pub value: SignatureIdentifier,
}
The Signature struct includes not only the signature itself but also metadata about the signing operation.
Fields
Identifier of the key that created the signature
Timestamp when the signature was created
Hash of the content that was signed (including timestamp)
value
SignatureIdentifier
required
The actual signature value
Methods
new
pub fn new<T: HashId>(
content: &T,
keys: &KeyPair,
derivator: DigestDerivator,
) -> Result<Self, SubjectError>
Creates a new signature for the given content using the provided key pair.
The content to sign (must implement HashId trait)
The key pair to use for signing
The digest algorithm to use for hashing (e.g., Blake3_256)
Returns: A Result containing the Signature or a SubjectError.
Process:
- Creates a signer identifier from the public key
- Generates a timestamp
- Hashes the content and timestamp together using Borsh serialization
- Signs the hash with the secret key
- Wraps the signature with metadata
new_from_pk_ed25519
pub fn new_from_pk_ed25519<T: HashId>(
content: &T,
private_key: String,
derivator: DigestDerivator
) -> Result<Self, SubjectError>
Creates a signature using an Ed25519 private key provided as a hex string.
Hexadecimal-encoded Ed25519 private key
The digest algorithm to use for hashing
Returns: A Result containing the Signature or a SubjectError.
new_from_pk_secp256k1
pub fn new_from_pk_secp256k1<T: HashId>(
content: &T,
private_key: String,
derivator: DigestDerivator
) -> Result<Self, SubjectError>
Creates a signature using a Secp256k1 private key provided as a hex string.
Hexadecimal-encoded Secp256k1 private key
The digest algorithm to use for hashing
Returns: A Result containing the Signature or a SubjectError.
verify
pub fn verify<T: HashId>(&self, content: &T) -> Result<(), SubjectError>
Verifies that the signature is valid for the given content.
The content to verify against the signature
Returns: Ok(()) if verification succeeds, otherwise a SubjectError.
Process:
- Hashes the content with the stored timestamp
- Verifies the signature using the signer’s public key
- Checks that the hash matches the stored content_hash
Example
use taple_core::{
commons::models::signature::Signature,
crypto::{KeyPair, Ed25519KeyPair, KeyGenerator},
identifier::derive::digest::DigestDerivator,
};
// Create content to sign
#[derive(BorshSerialize)]
struct MyData {
value: String,
}
let data = MyData {
value: "Important message".to_string(),
};
// Generate key pair
let key_pair = KeyPair::Ed25519(Ed25519KeyPair::new());
// Create signature
let signature = Signature::new(
&data,
&key_pair,
DigestDerivator::Blake3_256,
)?;
// Verify signature
signature.verify(&data)?;
// Access signature metadata
println!("Signer: {}", signature.signer);
println!("Timestamp: {:?}", signature.timestamp);
println!("Content hash: {}", signature.content_hash);
Example with Hex Private Key
use taple_core::commons::models::signature::Signature;
use taple_core::identifier::derive::digest::DigestDerivator;
// Sign with Ed25519 private key
let private_key = "a3f5e8c7d2b4a1e9f6c3b8d5a2e7f4c1b9d6e3a8f5c2b7d4e1a6f3c9b8d5e2a7";
let signature = Signature::new_from_pk_ed25519(
&data,
private_key.to_string(),
DigestDerivator::Blake3_256,
)?;
signature.verify(&data)?;
Signed Wrapper
pub struct Signed<T: BorshSerialize + BorshDeserialize + Clone> {
#[serde(flatten)]
pub content: T,
pub signature: Signature,
}
The Signed<T> struct is a generic wrapper that combines any serializable content with its signature. This is useful for representing signed data entities.
Fields
The data being signed (flattened in JSON serialization)
The signature accompanying the data
Type Constraints
The generic type T must implement:
BorshSerialize - For binary serialization
BorshDeserialize - For binary deserialization
Clone - For cloning the data
Example
use taple_core::commons::models::signature::{Signature, Signed};
use borsh::{BorshSerialize, BorshDeserialize};
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
struct Event {
event_type: String,
data: Vec<u8>,
}
let event = Event {
event_type: "StateChange".to_string(),
data: vec![1, 2, 3, 4],
};
// Create a signature for the event
let signature = Signature::new(
&event,
&key_pair,
DigestDerivator::Blake3_256,
)?;
// Create a signed event
let signed_event = Signed {
content: event,
signature,
};
// Serialize to JSON (content fields are flattened)
let json = serde_json::to_string_pretty(&signed_event)?;
println!("{}", json);
// Verify the signed content
signed_event.signature.verify(&signed_event.content)?;
Serialization
Both Signature and Signed<T> implement:
- Serde serialization/deserialization for JSON and other formats
- Borsh serialization/deserialization for efficient binary encoding
JSON Serialization Example
use taple_core::commons::models::signature::Signature;
// Serialize signature to JSON
let json = serde_json::to_string_pretty(&signature)?;
// Deserialize from JSON
let restored: Signature = serde_json::from_str(&json)?;
Borsh Serialization Example
use borsh::{BorshSerialize, BorshDeserialize};
// Serialize to binary
let bytes = signature.try_to_vec()?;
// Deserialize from binary
let restored = Signature::try_from_slice(&bytes)?;
Traits Implemented
The Signature struct implements:
Debug - For debugging output
Clone - For cloning signatures
Serialize/Deserialize - For Serde serialization
BorshSerialize/BorshDeserialize - For Borsh serialization
Eq/PartialEq - For equality comparison
PartialOrd - For ordering
Hash - For use in hash-based collections
KeyIdentifier
See the Identifiers documentation for details on key identifiers.
DigestIdentifier
See the Identifiers documentation for details on digest identifiers.
SignatureIdentifier
See the Identifiers documentation for details on signature identifiers.
TimeStamp
Represents the time when a signature was created. Used to prevent replay attacks and provide temporal context.