Skip to content

Commit

Permalink
feat: use hardcoded IC public key by default (#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericswanson-dfinity authored May 5, 2021
1 parent d0a17fc commit 95a0782
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 8 deletions.
17 changes: 10 additions & 7 deletions ic-agent/src/agent/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ use std::time::Duration;
const IC_REQUEST_DOMAIN_SEPARATOR: &[u8; 11] = b"\x0Aic-request";
const IC_STATE_ROOT_DOMAIN_SEPARATOR: &[u8; 14] = b"\x0Dic-state-root";

const IC_ROOT_KEY: &[u8; 133] = b"\x30\x81\x82\x30\x1d\x06\x0d\x2b\x06\x01\x04\x01\x82\xdc\x7c\x05\x03\x01\x02\x01\x06\x0c\x2b\x06\x01\x04\x01\x82\xdc\x7c\x05\x03\x02\x01\x03\x61\x00\x81\x4c\x0e\x6e\xc7\x1f\xab\x58\x3b\x08\xbd\x81\x37\x3c\x25\x5c\x3c\x37\x1b\x2e\x84\x86\x3c\x98\xa4\xf1\xe0\x8b\x74\x23\x5d\x14\xfb\x5d\x9c\x0c\xd5\x46\xd9\x68\x5f\x91\x3a\x0c\x0b\x2c\xc5\x34\x15\x83\xbf\x4b\x43\x92\xe4\x67\xdb\x96\xd6\x5b\x9b\xb4\xcb\x71\x71\x12\xf8\x47\x2e\x0d\x5a\x4d\x14\x50\x5f\xfd\x74\x84\xb0\x12\x91\x09\x1c\x5f\x87\xb9\x88\x83\x46\x3f\x98\x09\x1a\x0b\xaa\xae";

/// A facade that connects to a Replica and does requests. These requests can be of any type
/// (does not have to be HTTP). This trait is to inverse the control from the Agent over its
/// connection code, and to resolve any direct dependencies to tokio or HTTP code from this
Expand Down Expand Up @@ -184,7 +186,7 @@ impl Agent {
ingress_expiry_duration: config
.ingress_expiry_duration
.unwrap_or_else(|| Duration::from_secs(300)),
root_key: Arc::new(RwLock::new(None)),
root_key: Arc::new(RwLock::new(Some(IC_ROOT_KEY.to_vec()))),
transport: config
.transport
.ok_or_else(AgentError::MissingReplicaTransport)?,
Expand All @@ -196,13 +198,14 @@ impl Agent {
self.transport = Arc::new(transport);
}

/// Fetch the root key of the replica using its status end point, and update the agent's
/// root key. This only uses the agent's specific upstream replica, and does not ensure
/// the root key validity. In order to prevent any MITM attack, developers should try
/// to contact multiple replicas.
/// By default, the agent is configured to talk to the main Internet Computer, and verifies
/// responses using a hard-coded public key.
///
/// This function will instruct the agent to ask the endpoint for its public key, and use
/// that instead. This is required when talking to a local test instance, for example.
///
/// The root key is necessary for validating state and certificates sent by the replica.
/// By default, it is set to [None] and validating methods will return an error.
/// *Only use this when you are _not_ talking to the main Internet Computer, otherwise
/// you are prone to man-in-the-middle attacks! Do not call this function by default.*
pub async fn fetch_root_key(&self) -> Result<(), AgentError> {
let status = self.status().await?;
let root_key = status
Expand Down
4 changes: 4 additions & 0 deletions icx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ To get help, simply use `icx --help`.
To read a PEM file, you can pass it with the `--pem` argument. The PEM file must be a valid
key that can be used for the Internet Computer signing and validation.

### Root Key
For non-IC networks, pass --fetch-root-key to fetch the root key. When this argument is not present,
icx uses the hardcoded public key.

### Examples
To call the management canister's `create_canister` function, you can use the following:

Expand Down
8 changes: 7 additions & 1 deletion icx/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ struct Opts {
#[clap(default_value = "http://localhost:8000/")]
replica: String,

/// Set for non-IC networks: fetch the root key. If not passed, use real hardcoded key.
#[clap(long)]
fetch_root_key: bool,

/// An optional PEM file to read the identity from. If none is passed,
/// a random identity will be created.
#[clap(long)]
Expand Down Expand Up @@ -419,7 +423,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let result = match &opts.subcommand {
SubCommand::Update(_) => {
// We need to fetch the root key for updates.
agent.fetch_root_key().await?;
if opts.fetch_root_key {
agent.fetch_root_key().await?;
}

let mut builder = agent.update(&t.canister_id, &t.method_name);

Expand Down

1 comment on commit 95a0782

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 Netlify deployed agent-rust as production

https://agent-rust.netlify.app

Please sign in to comment.