Add prototype encrypted CAS blobs
This commit is contained in:
parent
6e04e786c2
commit
533ffc8c2a
8 changed files with 382 additions and 6 deletions
|
|
@ -4509,6 +4509,48 @@ pub fn handle_request(
|
|||
size_bytes: info.size_bytes,
|
||||
})
|
||||
}
|
||||
ControlRequest::CasAddPrivate { resource, path } => {
|
||||
ensure_resource_exists(&store, &resource)?;
|
||||
let secret = store.latest_resource_secret(&resource)?.ok_or_else(|| {
|
||||
NodeError::IrohPeer(format!(
|
||||
"resource {resource} has no active resource secret; run geth secret create {resource}"
|
||||
))
|
||||
})?;
|
||||
let plaintext = std::fs::read(&path)?;
|
||||
let plaintext_hash = geth_cas::hash_bytes(&plaintext);
|
||||
let nonce = geth_crypto::blake3_hex(
|
||||
format!(
|
||||
"{}\0{}\0{}\0{}",
|
||||
resource,
|
||||
secret.secret_id,
|
||||
secret.epoch,
|
||||
geth_store::now_ms()
|
||||
)
|
||||
.as_bytes(),
|
||||
);
|
||||
let encrypted = geth_cas::encrypt_private_blob(
|
||||
&resource,
|
||||
&secret.secret_id,
|
||||
secret.epoch,
|
||||
&nonce,
|
||||
&plaintext,
|
||||
)?;
|
||||
let cas = LocalCas::new(node.paths.cas_dir());
|
||||
let info = cas.add_bytes(&encrypted)?;
|
||||
store.record_cas_object(
|
||||
info.hash.as_str(),
|
||||
info.size_bytes,
|
||||
&info.path.to_string_lossy(),
|
||||
)?;
|
||||
Ok(ControlResponse::CasPrivateAdded {
|
||||
resource,
|
||||
epoch: secret.epoch,
|
||||
plaintext_hash,
|
||||
encrypted_hash: info.hash,
|
||||
size_bytes: info.size_bytes,
|
||||
note: "stored prototype encrypted private blob envelope; no forward secrecy or post-compromise security is claimed".to_owned(),
|
||||
})
|
||||
}
|
||||
ControlRequest::CasGet { hash, out } => {
|
||||
let cas = LocalCas::new(node.paths.cas_dir());
|
||||
let size_bytes = cas.get_to_path(&hash, &out)?;
|
||||
|
|
@ -4518,6 +4560,51 @@ pub fn handle_request(
|
|||
size_bytes,
|
||||
})
|
||||
}
|
||||
ControlRequest::CasGetPrivate {
|
||||
resource,
|
||||
hash,
|
||||
out,
|
||||
} => {
|
||||
ensure_resource_exists(&store, &resource)?;
|
||||
let cas = LocalCas::new(node.paths.cas_dir());
|
||||
let encrypted = cas.read_bytes(&hash)?;
|
||||
let secrets = store
|
||||
.list_resource_secrets()?
|
||||
.into_iter()
|
||||
.filter(|secret| secret.resource_id == resource)
|
||||
.collect::<Vec<_>>();
|
||||
if secrets.is_empty() {
|
||||
return Err(NodeError::IrohPeer(format!(
|
||||
"resource {resource} has no resource secrets; cannot decrypt private blob"
|
||||
)));
|
||||
}
|
||||
let mut plaintext = None;
|
||||
for secret in secrets {
|
||||
if let Ok(bytes) =
|
||||
geth_cas::decrypt_private_blob(&resource, &secret.secret_id, &encrypted)
|
||||
{
|
||||
plaintext = Some(bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let plaintext = plaintext.ok_or_else(|| {
|
||||
NodeError::IrohPeer(format!(
|
||||
"no local resource secret epoch could decrypt private blob {hash}"
|
||||
))
|
||||
})?;
|
||||
if let Some(parent) = out.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
std::fs::write(&out, &plaintext)?;
|
||||
Ok(ControlResponse::CasPrivateGot {
|
||||
resource,
|
||||
hash,
|
||||
plaintext_hash: geth_cas::hash_bytes(&plaintext),
|
||||
out,
|
||||
size_bytes: plaintext.len() as u64,
|
||||
note: "decrypted prototype private blob envelope with the latest local resource secret epoch".to_owned(),
|
||||
})
|
||||
}
|
||||
ControlRequest::CasHash { path } => Ok(ControlResponse::CasHash {
|
||||
hash: hash_path(&path)?,
|
||||
}),
|
||||
|
|
|
|||
Loading…
Reference in a new issue