Skip to main content

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

signer
KeyIdentifier
required
Identifier of the key that created the signature
timestamp
TimeStamp
required
Timestamp when the signature was created
content_hash
DigestIdentifier
required
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.
content
&T
required
The content to sign (must implement HashId trait)
keys
&KeyPair
required
The key pair to use for signing
derivator
DigestDerivator
required
The digest algorithm to use for hashing (e.g., Blake3_256)
Returns: A Result containing the Signature or a SubjectError. Process:
  1. Creates a signer identifier from the public key
  2. Generates a timestamp
  3. Hashes the content and timestamp together using Borsh serialization
  4. Signs the hash with the secret key
  5. 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.
content
&T
required
The content to sign
private_key
String
required
Hexadecimal-encoded Ed25519 private key
derivator
DigestDerivator
required
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.
content
&T
required
The content to sign
private_key
String
required
Hexadecimal-encoded Secp256k1 private key
derivator
DigestDerivator
required
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.
content
&T
required
The content to verify against the signature
Returns: Ok(()) if verification succeeds, otherwise a SubjectError. Process:
  1. Hashes the content with the stored timestamp
  2. Verifies the signature using the signer’s public key
  3. 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

content
T
required
The data being signed (flattened in JSON serialization)
signature
Signature
required
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.

Build docs developers (and LLMs) love