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) : PublicKey
Calculate the DER-encoded public key for the given canister and seed
public func selfAuthenticatingPrincipal(publicKey : PublicKey) : Principal
Derive a self-authenticating principal from a public key
public func signature(cert : Blob, witness : MerkleTree.Witness) : Signature
Encode 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) : Signature
Generate 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() : Nat
Number 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();
};