Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: verify canister signature #3

Merged
merged 3 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,16 +189,18 @@ The [canister_sig_util](https://github.com/dfinity/internet-identity/tree/releas

## Roadmap

- [x] on the canister, periodically fetch the [JSON Web Key Sets (JWKS)](https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-key-sets) from Auth0 using the [HTTPS outcalls](https://internetcomputer.org/docs/current/references/https-outcalls-how-it-works/) and [Timers](https://internetcomputer.org/docs/current/developer-docs/smart-contracts/advanced-features/periodic-tasks/) features.
- [x] On the canister, periodically fetch the [JSON Web Key Sets (JWKS)](https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-key-sets) from Auth0 using the [HTTPS outcalls](https://internetcomputer.org/docs/current/references/https-outcalls-how-it-works/) and [Timers](https://internetcomputer.org/docs/current/developer-docs/smart-contracts/advanced-features/periodic-tasks/) features.

Right now, the JWKS are fetched at build time by the [build-canister.sh](./scripts/build-canister.sh) script, stored in `data/jwks.json` and imported in the canister as raw bytes at compile time ([source](https://github.com/ilbertt/ic-react-native-jwt-auth/blob/882539addd4e0e35fe1f1756701296f1ff085239/src/ic_backend/src/id_token.rs#L12)).

Fetching the JWKS at runtime is needed because [JWK](https://datatracker.ietf.org/doc/html/rfc7517)s on Auth0 may rotate.

Related issue: https://github.com/ilbertt/ic-react-native-jwt-auth/issues/1.
- [x] tests (integration)
- [x] Integration tests

Related PR: https://github.com/ilbertt/ic-react-native-jwt-auth/pull/2.
Related PRs:
- https://github.com/ilbertt/ic-react-native-jwt-auth/pull/2
- https://github.com/ilbertt/ic-react-native-jwt-auth/pull/3

## License

Expand Down
3 changes: 2 additions & 1 deletion src/ic_backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ candid.workspace = true
ic-cdk = "0.13"
ic-cdk-timers = "0.7"
ic-stable-structures = "0.6"
ic-certified-map = "0.4"
ic-certification = "2.5"
canister_sig_util = { git = "https://github.com/dfinity/internet-identity", tag = "release-2024-04-05" }

serde.workspace = true
Expand All @@ -34,3 +34,4 @@ pocket-ic = "2.2"
jwt-simple = "0.12"
ic-agent = "0.34"
ring = "0.17"
ic-representation-independent-hash = "2.5"
39 changes: 9 additions & 30 deletions src/ic_backend/src/delegation.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::collections::HashMap;

use candid::Principal;
use canister_sig_util::{
delegation_signature_msg, hash_bytes,
signature_map::{SignatureMap, LABEL_SIG},
CanisterSigPublicKey,
};
Expand All @@ -10,10 +9,10 @@ use ic_backend_types::{
UserSub,
};
use ic_cdk::{api::set_certified_data, id};
use ic_certified_map::{labeled_hash, Hash};
use ic_certification::{labeled_hash, Hash};
use serde_bytes::ByteBuf;

use crate::{hash, state};
use crate::state;

pub async fn prepare_delegation(
user_sub: &UserSub,
Expand All @@ -37,11 +36,7 @@ pub fn get_delegation(
expiration: Timestamp,
) -> GetDelegationResponse {
state::signature_map(|sigs| {
let message_hash = delegation_signature_msg_hash(&Delegation {
pubkey: session_key.clone(),
expiration,
targets: None,
});
let message_hash = delegation_signature_msg_hash(&session_key, expiration);
match sigs.get_signature_as_cbor(&calculate_seed(user_sub), message_hash, None) {
Ok(signature) => GetDelegationResponse::SignedDelegation(SignedDelegation {
delegation: Delegation {
Expand Down Expand Up @@ -73,7 +68,7 @@ fn calculate_seed(user_sub: &UserSub) -> Hash {
blob.push(user_sub_blob.len() as u8);
blob.extend(user_sub_blob);

hash::hash_bytes(blob)
hash_bytes(blob)
}

fn update_root_hash() {
Expand All @@ -83,21 +78,9 @@ fn update_root_hash() {
})
}

fn delegation_signature_msg_hash(d: &Delegation) -> Hash {
use hash::Value;

let mut m = HashMap::new();
m.insert("pubkey", Value::Bytes(d.pubkey.as_slice()));
m.insert("expiration", Value::U64(d.expiration));
if let Some(targets) = d.targets.as_ref() {
let mut arr = Vec::with_capacity(targets.len());
for t in targets.iter() {
arr.push(Value::Bytes(t.as_ref()));
}
m.insert("targets", Value::Array(arr));
}
let map_hash = hash::hash_of_map(m);
hash::hash_with_domain(b"ic-request-auth-delegation", &map_hash)
fn delegation_signature_msg_hash(pubkey: &PublicKey, expiration: Timestamp) -> Hash {
let msg = delegation_signature_msg(pubkey, expiration, None);
hash_bytes(msg)
}

fn add_delegation_signature(
Expand All @@ -106,11 +89,7 @@ fn add_delegation_signature(
seed: &[u8],
expiration: Timestamp,
) {
let msg_hash = delegation_signature_msg_hash(&Delegation {
pubkey: pk,
expiration,
targets: None,
});
let msg_hash = delegation_signature_msg_hash(&pk, expiration);
sigs.add_signature(seed, msg_hash);
}

Expand Down
Loading