CanisterSigs

Internet Computer Canister Signatures

This modules allows canister to produce signatures according to the “Canister Signature scheme”.

type PublicKey = Blob

type Seed = Blob

type Signature = Blob

type PayloadHash = Blob

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);

class Manager(ct : CertTree.Ops, expiry : ?Time.Time)

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();
};