The most recent release of the replica software, which is scheduled to be rolled out to the Internet Computer blockchain network in the coming days, enables the checking of subnet delegations as part of canister signatures on requests. But what is a canister signature and why should you care?
What is a canister signature?
Canisters are smart contracts that run on the IC. As the state of a canister is known to all replicas of the subnet that hosts that canister, and one or more replicas may behave maliciously, there is no way for a canister to securely store cryptographic keys in their memory. The IC provides certified data – which on a high level can be thought of as a cryptographic signature created by the subnet – as a mechanism for a canister to authenticate data toward the outside world. A canister signature uses the certified-data mechanism available to canisters to define something that syntactically resembles a digital signature scheme that enables the canister to sign messages.
The IC accepts canister signatures for requests or delegations contained therein. This functionality is heavily used by Internet Identity (II): When a user decides to authenticate toward a given dapp using II, the II canister signs a delegation to a short-term cryptographic key in the user’s browser. This mechanism is what enables II to let users authenticate as the same principal from different devices without requiring the user to synchronize cryptographic keys.
Why is this feature important?
Until now, the IC accepted canister signatures on requests only if the issuing canister was hosted on the root subnet (often referred to as NNS subnet) – which means that canisters on other subnets could not make use of the same functionality. With this week’s upgrade, that restriction vanishes: Any canister on any subnet will be able to use the same functionality that powers Internet Identity!
Great to hear!
In particular, only now my Capture-the-ICP hacking challenge actually works, as in order to redeem the canister’s ICP, you have to construct such a canister signature.
I wonder how long until people build transferable neurons on top of this feature (or on top of ECDSA signatures, roughly the same thing)?
Could you explain how this canister signature differs functionally from the ECDSA threshold signature that powers the Bitcoin integration?
It seems like both kinds of signatures are signed by the subnet.
Regular canisters uses BLS threshold, which was not compatible with Bitcoin.
This is definitely exciting news, smart contracts have never been so innovative and powerful.
Can there be a demo tutorial for developers to learn? for example,
- how to deploy a canister on the mainnet, the src code for the canister?
- how to obtain the public key corresponding to its canister signature?
- how to make it sign a hash, how to obtain its signature?
- Then how to verify the signature anywhere based on the hash, signature, and public key? Include which curve to use (secp256k1 or bls_xxx)
The README at GitHub - nomeata/capture-the-ic-token: Hack the canister, get the token answers a few of these questions incidentally, although not quite tutorial style. The Internet Identity code is also a good example.
I don’t think we have use cases beyond these two yet, so there is no Canister Signature checking code besides one in the IC replica itself.
If you can read Haskell, then ic-hs/CanisterSig.hs at master · dfinity/ic-hs · GitHub is also another source to learn from.
As @JaMarco pointed out, the canister signatures are specific to the IC and based on BLS – whereas ECDSA signatures are a common standard widely used outside of the IC. On the flip side, signature generation in canister signatures will (probably) be faster and cheaper in terms of cycles – there is simply less protocol overhead.
There is no specific tutorial, unfortunately, and I don’t think we’ll have the capacity to build one soon. But beyond the links that @nomeata provided above, the code of II and the IC are open source, so you could have a look at:
Thanks, if I figure out the overall mechanism, I’ll try to write one
That’s great, thanks! If you hit any roadblocks, feel free to ask! Just tag me on the message to make sure I’ll get a notification – and I’m sure Joachim will be happy to help as well.
Thank you for rolling this feature out, been waiting for couple months.
Whoa! So if I’m reading this right, there’s a way now to build an on-chain authenticator / validator for sessions, as long as you have a “secure device” with you.
I’m thinking something along the lines of:
a) Initiate a new session from an “unsupported” device, just like the flow for II does now
b) go to my authenticator canister, and request a delegation
c) sign in to the authenticator with a valid II via a supported device
d) see the request, validate it (say some characters, or a series of pictures, whatever)
e) my “unsupported” device now has a proper delegation chain, and can sign requests as if coming from whatever Principal comes out of my II authentication to my own canister.
That would be huge for general adoption! Almost everybody has at least one “secure” device, but most have “normal” pcs without secure enclaves / tpu / etc for webauthn.
I’m curious: how do you plan to use this?
I think I need a picture and some
Pseudo code to really understand what is going on here. Can motoko access these signatures?
You can access the signatures through the CertifiedData API in Motoko. @nomeata has a post describing this in more detail. (Note that while the example canister does certified assets, canister signatures use the same type of tree and just encode a different tree structure.) And @matthewhammer also provided an example implementation.
At least, we can build an enhanced or alternative version of II, integrated with other unsupported login methods, like Email, social login, other supporting ED25519/Secp256k1 curve/signature wallet providers maybe?
For my personal interest, I would prefer to build solution for individuals, like person-controlled canister for private usage. For example, I may have a canister under control and that canister will authorize my other device to control my IoT equipments of my house. . Or more generally, to build solution for small group or company that can authorize their employee or customers.
I deployed ii and auth-client-demo locally,
- Registered an ii anchor number, which is 10000.
- When using a dapp(auth-client-demo), the front end is http://localhost:8080, and I generated a session key pair on the front end. Then call
prepare_delegation with the anchor number, frontend and sessionKey’s public key as parameters. ii After passing the detection of 10000 DeviceData and caller, update the sigs in State(in ii’s canister) and the certified data of the system.
- A dapp wants to make a update call, the front-end uses the session key to sign msg, and then the front-end calls
get_delegation also requires caller detection, but it doesn’t seem to require the fingerprint to obtain the device’s signature when initiating an update call. Then the result of
get_delegation has a more field: signature, which contains the system’s certified data and tree(delegation and asset’s info in ii canister). The certified data should be the node’s signature to the root hash of the system state tree. Does the ic have this signature code generation process?
prepare_delegation, there is no information related to the update call msg, so there is no signature for the msg in the certified data.The front-end sends the signature of the session key and the result of get_delegation to https://ic0.app, and the IC checks the two signatures?
I am not entirely sure about your goals. If you just want to use II as a client (which is what auth-client-demo should be doing), then the functions
get_delegation are only called from the II frontend. Are you trying to build an alternative frontend for the II canister?
If you want to understand the
get_delegation flow in more detail, I suggest you have a look at the Internet Identity specification.
My goal is to understand how the process works. I can understand ecdsa/bls signature and threshold signature. But Canister Signature I don’t understand it or how to use it. Can official team provide some low-level interfaces with better encapsulation?
This function is very helpful for developing IC naive apps, but unfortunately, it requires a little high.
If you want to have your canister issue a signature that can be verified outside of the IC, I would suggest waiting for the ECDSA feature that will be available soon (when we roll out Bitcoin integration to the mainnet). The signatures generated by that functionality will be compliant with widely used standards (which canister signatures are not, they exist only on the IC), and they will be easier to use.
The main use of canister signatures is for identity solutions such as Internet Identity or the project that @neeboo is working on. If you plan to build on that, I’d suggest starting from the Internet Identity source code.
I don’t think we will provide improved library support for canister signatures (both on the canister and the verification side) soon – the main reason is that we want to focus our engineering efforts on features such as ECDSA.