Overview
TAPLE Core uses self-describing identifiers based on different derivation schemes. Each identifier type includes both the derivation algorithm code and the material (key bytes, digest bytes, or signature bytes) encoded in a compact string format using base64.
DigestIdentifier
pub struct DigestIdentifier {
pub derivator: DigestDerivator,
pub digest: Vec<u8>,
}
A digest-based identifier representing the hash of some content. Used throughout TAPLE to uniquely identify events, subjects, and other data structures.
Fields
The hash algorithm used (e.g., Blake3_256, SHA-256, SHA-512)
The raw digest bytes produced by the hash function
Methods
new
pub fn new(derivator: DigestDerivator, digest: &[u8]) -> Self
Creates a new DigestIdentifier from a derivator and digest bytes.
The digest algorithm that produced the hash
Returns: A new DigestIdentifier.
from_serializable_borsh
pub fn from_serializable_borsh<T: BorshSerialize>(
serializable: T,
digest_derivator: DigestDerivator
) -> Result<Self, Error>
Creates a digest identifier by hashing a Borsh-serializable object.
Any type that implements BorshSerialize
The hash algorithm to use
Returns: A Result containing the DigestIdentifier or an error.
Process:
- Serializes the object using Borsh
- Hashes the serialized bytes using the specified derivator
- Creates a
DigestIdentifier with the hash
generate_with_blake3
pub fn generate_with_blake3<T: BorshSerialize>(
serializable: T,
) -> Result<Self, Error>
Convenience method that creates a digest identifier using Blake3-256 hashing.
Any type that implements BorshSerialize
Returns: A Result containing the DigestIdentifier with Blake3-256 derivator.
from_serializable
pub fn from_serializable<S: Serialize>(data: &S) -> Result<Self, Error>
Creates a digest identifier by hashing JSON-serializable data (uses Blake3-256).
Any type that implements Serialize
Returns: A Result containing the DigestIdentifier or an error.
String Representation
Digest identifiers are represented as base64-encoded strings with a prefix indicating the hash algorithm:
<derivator_code><base64_digest>
Example: JJNcubTZO2JMDUguqcXG5lbe0vFJfN-SOA1oUkGEcRLo (Blake3-256 digest)
Example
use taple_core::identifier::{DigestIdentifier, derive::digest::DigestDerivator};
use borsh::BorshSerialize;
use std::str::FromStr;
#[derive(BorshSerialize)]
struct Data {
field: String,
}
let data = Data {
field: "test".to_string(),
};
// Create from Borsh-serializable data
let digest_id = DigestIdentifier::from_serializable_borsh(
&data,
DigestDerivator::Blake3_256,
)?;
println!("Digest ID: {}", digest_id);
// Create from raw digest bytes
let bytes = vec![0u8; 32];
let digest_id2 = DigestIdentifier::new(DigestDerivator::Blake3_256, &bytes);
// Parse from string
let digest_str = "JJNcubTZO2JMDUguqcXG5lbe0vFJfN-SOA1oUkGEcRLo";
let parsed = DigestIdentifier::from_str(digest_str)?;
KeyIdentifier
pub struct KeyIdentifier {
pub public_key: Vec<u8>,
pub derivator: KeyDerivator,
}
A key-based identifier representing a cryptographic public key. Used to identify nodes, validators, and other entities in TAPLE.
Fields
The key algorithm (Ed25519 or Secp256k1)
Methods
new
pub fn new(derivator: KeyDerivator, pk: &[u8]) -> Self
Creates a new KeyIdentifier from a derivator and public key bytes.
The key algorithm (Ed25519 or Secp256k1)
Returns: A new KeyIdentifier.
to_signature_derivator
pub fn to_signature_derivator(&self) -> SignatureDerivator
Returns the corresponding signature derivator for this key type.
Returns: SignatureDerivator::Ed25519Sha512 for Ed25519 keys, or SignatureDerivator::ECDSAsecp256k1 for Secp256k1 keys.
verify
pub fn verify(&self, data: &[u8], signature: &SignatureIdentifier) -> Result<(), Error>
Verifies a signature against data using the public key.
signature
&SignatureIdentifier
required
The signature to verify
Returns: Ok(()) if verification succeeds, otherwise an error.
String Representation
Key identifiers are represented as base64-encoded strings with a prefix indicating the key algorithm:
<derivator_code><base64_public_key>
Example: EYS8MQAh_m740mHnjPMm9IgY9RGojzFak6ELaTsQQZx8 (Ed25519 public key)
Example
use taple_core::{
identifier::{KeyIdentifier, SignatureIdentifier, derive::KeyDerivator},
crypto::{Ed25519KeyPair, KeyGenerator, KeyMaterial, Payload, DSA},
};
use std::str::FromStr;
// Create from key pair
let key_pair = Ed25519KeyPair::new();
let key_id = KeyIdentifier::new(
KeyDerivator::Ed25519,
&key_pair.public_key_bytes(),
);
println!("Key ID: {}", key_id);
// Sign and verify
let message = b"Hello, TAPLE!";
let signature_bytes = key_pair.sign(Payload::Buffer(message.to_vec()))?;
let sig_derivator = key_id.to_signature_derivator();
let signature_id = SignatureIdentifier::new(sig_derivator, &signature_bytes);
key_id.verify(message, &signature_id)?;
// Parse from string
let key_str = "EYS8MQAh_m740mHnjPMm9IgY9RGojzFak6ELaTsQQZx8";
let parsed = KeyIdentifier::from_str(key_str)?;
SignatureIdentifier
pub struct SignatureIdentifier {
pub derivator: SignatureDerivator,
pub signature: Vec<u8>,
}
A signature-based identifier representing a cryptographic signature. Used to wrap signature bytes with their derivation algorithm.
Fields
derivator
SignatureDerivator
required
The signature algorithm (Ed25519Sha512 or ECDSAsecp256k1)
Methods
new
pub fn new(derivator: SignatureDerivator, signature: &[u8]) -> Self
Creates a new SignatureIdentifier from a derivator and signature bytes.
derivator
SignatureDerivator
required
The signature algorithm
Returns: A new SignatureIdentifier.
String Representation
Signature identifiers are represented as base64-encoded strings with a prefix indicating the signature algorithm:
<derivator_code><base64_signature>
Example: SETCkX4WX_KcMeLKdwrtN8DGD49z7gbPfYV0Ao8C-B_dcKRj-7TXmvLdKNHG27GDOvgCyWzFMMI23rw2sSssHjBQ (Ed25519 signature)
Example
use taple_core::identifier::{SignatureIdentifier, derive::signature::SignatureDerivator};
use std::str::FromStr;
// Create from signature bytes
let signature_bytes = vec![0u8; 64];
let sig_id = SignatureIdentifier::new(
SignatureDerivator::Ed25519Sha512,
&signature_bytes,
);
println!("Signature ID: {}", sig_id);
// Parse from string
let sig_str = "SETCkX4WX_KcMeLKdwrtN8DGD49z7gbPfYV0Ao8C-B_dcKRj-7TXmvLdKNHG27GDOvgCyWzFMMI23rw2sSssHjBQ";
let parsed = SignatureIdentifier::from_str(sig_str)?;
assert_eq!(parsed.derivator, SignatureDerivator::Ed25519Sha512);
Derivable Trait
All three identifier types implement the Derivable trait:
pub trait Derivable: FromStr<Err = Error> {
fn derivative(&self) -> Vec<u8>;
fn derivation_code(&self) -> String;
fn to_str(&self) -> String;
}
Methods
derivative
fn derivative(&self) -> Vec<u8>
Returns the raw bytes (digest, public key, or signature).
derivation_code
fn derivation_code(&self) -> String
Returns the derivator code as a string prefix.
to_str
fn to_str(&self) -> String
Converts the identifier to its string representation (code + base64 material).
Derivator Types
DigestDerivator
Supported hash algorithms:
Blake3_256 - Blake3 with 256-bit output (default)
Blake3_512 - Blake3 with 512-bit output
SHA2_256 - SHA-256
SHA2_512 - SHA-512
SHA3_256 - SHA3-256
SHA3_512 - SHA3-512
KeyDerivator
Supported key algorithms:
Ed25519 - Ed25519 curve (default)
Secp256k1 - Secp256k1 curve (Bitcoin/Ethereum)
SignatureDerivator
Supported signature algorithms:
Ed25519Sha512 - Ed25519 signatures
ECDSAsecp256k1 - ECDSA with secp256k1 curve
Serialization
All identifier types implement:
- Serde serialization as strings
- Borsh binary serialization
- Display for string formatting
- FromStr for parsing from strings
Example
use taple_core::identifier::KeyIdentifier;
use std::str::FromStr;
// Serialize to JSON (as string)
let json = serde_json::to_string(&key_id)?;
println!("{}", json); // Outputs: "EYS8MQAh_m740mHnjPMm9IgY9RGojzFak6ELaTsQQZx8"
// Deserialize from JSON
let restored: KeyIdentifier = serde_json::from_str(&json)?;
// Borsh serialization
let bytes = borsh::to_vec(&key_id)?;
let restored2: KeyIdentifier = borsh::from_slice(&bytes)?;
Common Operations
Creating Identifiers from Keys
use taple_core::{
crypto::{KeyPair, Ed25519KeyPair, KeyGenerator, KeyMaterial},
identifier::{KeyIdentifier, derive::KeyDerivator},
};
let key_pair = KeyPair::Ed25519(Ed25519KeyPair::new());
let key_id = KeyIdentifier::new(
key_pair.get_key_derivator(),
&key_pair.public_key_bytes(),
);
Hashing Content
use taple_core::identifier::{DigestIdentifier, derive::digest::DigestDerivator};
use borsh::BorshSerialize;
#[derive(BorshSerialize)]
struct Event {
data: Vec<u8>,
}
let event = Event { data: vec![1, 2, 3] };
let event_hash = DigestIdentifier::generate_with_blake3(&event)?;
Complete Signing Flow
use taple_core::{
crypto::{Ed25519KeyPair, KeyGenerator, KeyMaterial, Payload, DSA},
identifier::{
KeyIdentifier, SignatureIdentifier,
derive::{KeyDerivator, signature::SignatureDerivator},
},
};
// Create key pair and identifier
let key_pair = Ed25519KeyPair::new();
let signer_id = KeyIdentifier::new(
KeyDerivator::Ed25519,
&key_pair.public_key_bytes(),
);
// Sign data
let data = b"Important message";
let signature_bytes = key_pair.sign(Payload::Buffer(data.to_vec()))?;
// Create signature identifier
let signature_id = SignatureIdentifier::new(
signer_id.to_signature_derivator(),
&signature_bytes,
);
// Verify
signer_id.verify(data, &signature_id)?;