FullChain Public Keys
A FullChain Public Key in SARE combines both signature and encryption public keys into a single, exportable structure. It is used to verify signatures and encrypt data for the holder of the corresponding master key.
Structure
The full chain contains two main components:
#![allow(unused)] fn main() { #[derive(Serialize, Deserialize, Clone)] pub struct FullChainPublicKeyFormat { pub signature_public_key: SignaturePublicKeyFormat, pub encryption_public_key: EncryptionPublicKeyFormat, } }
Signature Public Key (SignaturePublicKeyFormat
)
- Combines classical elliptic-curve (EC) and post-quantum (PQ) algorithms:
#![allow(unused)] fn main() { pub struct SignaturePublicKeyFormat { pub ec_algorithm: ECAlgorithm, pub pq_algorithm: PQAlgorithm, pub ec_public_key: Vec<u8>, pub pq_public_key: Vec<u8>, } }
- Both EC and PQ signatures must verify successfully for a message to be trusted.
Encryption Public Key (EncryptionPublicKeyFormat
)
- Combines Diffie-Hellman (DH) and hybrid KEM algorithms:
#![allow(unused)] fn main() { pub struct EncryptionPublicKeyFormat { pub dh_algorithm: DHAlgorithm, pub kem_algorithm: KEMAlgorithm, pub dh_public_key: Vec<u8>, pub kem_public_key: Vec<u8>, } }
- Used for hybrid KEM-based key agreement to encrypt secrets for this key holder.
Export Formats
BSON
- The full chain can be encoded as BSON:
{
"signature_public_key": {
"ec_algorithm": "EC_ALGO",
"pq_algorithm": "PQ_ALGO",
"ec_public_key": "<bytes>",
"pq_public_key": "<bytes>"
},
"encryption_public_key": {
"dh_algorithm": "DH_ALGO",
"kem_algorithm": "KEM_ALGO",
"dh_public_key": "<bytes>",
"kem_public_key": "<bytes>"
}
}
PEM
- Encoded as a standard PEM block:
-----BEGIN SARE FULLCHAIN PUBLIC KEY-----
<base64-encoded BSON>
-----END SARE FULLCHAIN PUBLIC KEY-----
Fingerprint
The fingerprint uniquely identifies a full chain public key and is derived deterministically from all contained public key components.
#![allow(unused)] fn main() { impl FullChainPublicKeyFormat { pub fn calculate_fingerprint(&self) -> [u8; 32] { let mut hasher = Sha256::new(); // EC signature component hasher.update(self.signature_public_key.ec_algorithm.to_string().as_bytes()); hasher.update(&self.signature_public_key.ec_public_key); // PQ signature component hasher.update(self.signature_public_key.pq_algorithm.to_string().as_bytes()); hasher.update(&self.signature_public_key.pq_public_key); // DH encryption component hasher.update(self.encryption_public_key.dh_algorithm.to_string().as_bytes()); hasher.update(&self.encryption_public_key.dh_public_key); // KEM encryption component hasher.update(self.encryption_public_key.kem_algorithm.to_string().as_bytes()); hasher.update(&self.encryption_public_key.kem_public_key); let fingerprint: [u8; 32] = hasher.finalize().into(); fingerprint } } }
Notes:
-
Uses SHA-256 over all algorithm identifiers and public key bytes.
-
Ensures unique identification of each full chain public key.
-
Safe to share publicly, as it contains only public information.