Internet Computer Canister Signatures
This modules allows canister to produce signatures according to the “Canister Signature scheme”.
public func publicKey(canister_id : Principal, seed : Seed) : PublicKeyCalculate the DER-encoded public key for the given canister and seed
public func selfAuthenticatingPrincipal(publicKey : PublicKey) : PrincipalDerive a self-authenticating principal from a public key
public func signature(cert : Blob, witness : MerkleTree.Witness) : SignatureEncode the system certificate and the canister's hash tree witness as a Canister Signature scheme signature (CBOR-encoded)
The witness must reveal the path ["sigs",seed, hash_of_msg_payload].
So for example in an update method run something like
let sig_payload_hash = h2("\0Aic-request", request_id);
let path : CertTree.Path = ["sig", h "", sig_payload_hash];
ct.put(path, "");
ct.setCertifiedData();and then in the query method obtain the witness and the signature using
let witness = ct.reveal(req_data.path);
let sig = CanisterSigs.signature(cert, witness);public func prepare(seed : Seed, plh : PayloadHash)Prepare a signature.
The second argument is the hashed paylaod, e.g.
let request_id = ReqData.hash(content);
let sig_payload_hash = h2("\0Aic-request", request_id);
csm.prepare("", sig_payload_hash);Also calls setCertifiedData() on the certified data for you.
public func fetch(seed : Seed, plh : PayloadHash) : SignatureGenerate the signature.
This only works in a query call, and will trap if no certificate is available.
public func prune()Drops expired signatures from the state tree.
This is automatically called from prepare, so usually
you do not need to call this.
public func pruneAll()Drops all signatures. Useful in the pre_upgrade hook, to keep things tidy else signatures may lurk there forever, if the CanisterSigManager forgets about them.
public func size() : NatNumber of unexpired signatures. Useful to inculde in metrics
The canister signature manager class provides a bit of convenience for keeping track of the prepare/fetch/delete cycle.
Instantiate it with access to your canister's CertTree.Ops, e.g.
stable let cert_store : CertTree.Store = CertTree.newStore();
let ct = CertTree.Ops(cert_store);
let csm = CanisterSigs.Manager(ct, null);Then in the update call, call prepare, and in the query call call fetch.
If your CertTree.Store is stable, it is recommended to prune all signatures in pre or
post-upgrade:
system func preupgrade() {
 csm.pruneAll();
};