fix(api): dont verify signature or DID during importRepo

This commit is contained in:
nelind
2026-06-10 23:33:36 +02:00
parent 80afd764d3
commit bfadc936c0
3 changed files with 22 additions and 99 deletions
+6 -75
View File
@@ -77,27 +77,6 @@ pub async fn import_repo(
blocks.len(),
root
);
let Some(root_block) = blocks.get(&root) else {
return Err(ApiError::InvalidRequest(
"Root block not found in CAR file".into(),
));
};
let commit_did: Did = match jacquard_repo::commit::Commit::from_cbor(root_block) {
Ok(commit) => commit
.did()
.as_str()
.parse()
.map_err(|_| ApiError::InvalidRequest("Commit contains invalid DID".into()))?,
Err(e) => {
return Err(ApiError::InvalidRequest(format!("Invalid commit: {}", e)));
}
};
if commit_did != *did {
return Err(ApiError::InvalidRepo(format!(
"CAR file is for DID {} but you are authenticated as {}",
commit_did, did
)));
}
let skip_verification = std::env::var("SKIP_IMPORT_VERIFICATION")
.ok()
.map(|v| v == "true" || v == "1")
@@ -108,11 +87,13 @@ pub async fn import_repo(
});
let is_migration = user.inbound_migration && user.deactivated_at.is_some();
if skip_verification {
warn!("Skipping all CAR verification for import (SKIP_IMPORT_VERIFICATION=true)");
} else if is_migration {
debug!("Verifying CAR file structure for migration (skipping signature verification)");
warn!("Skipping all CAR verification for repo import (SKIP_IMPORT_VERIFICATION=true)");
} else {
debug!(
"Verifying CAR file structure for repo import (skipping signature and DID verification)"
);
let verifier = CarVerifier::new();
match verifier.verify_car_structure_only(did, &root, &blocks) {
match verifier.verify_car_structure_only(&root, &blocks) {
Ok(verified) => {
debug!(
"CAR structure verification successful: rev={}, data_cid={}",
@@ -142,56 +123,6 @@ pub async fn import_repo(
)));
}
}
} else {
debug!("Verifying CAR file signature and structure for DID {}", did);
let verifier = CarVerifier::new();
match verifier.verify_car(did, &root, &blocks).await {
Ok(verified) => {
debug!(
"CAR verification successful: rev={}, data_cid={}",
verified.rev, verified.data_cid
);
}
Err(tranquil_pds::sync::verify::VerifyError::DidMismatch {
commit_did,
expected_did,
}) => {
return Err(ApiError::InvalidRepo(format!(
"CAR file is for DID {} but you are authenticated as {}",
commit_did, expected_did
)));
}
Err(tranquil_pds::sync::verify::VerifyError::InvalidSignature) => {
return Err(ApiError::InvalidRequest(
"CAR file commit signature verification failed".into(),
));
}
Err(tranquil_pds::sync::verify::VerifyError::DidResolutionFailed(msg)) => {
warn!("DID resolution failed during import verification: {}", msg);
return Err(ApiError::InvalidRequest(format!(
"Failed to verify DID: {}",
msg
)));
}
Err(tranquil_pds::sync::verify::VerifyError::NoSigningKey) => {
return Err(ApiError::InvalidRequest(
"DID document does not contain a signing key".into(),
));
}
Err(tranquil_pds::sync::verify::VerifyError::MstValidationFailed(msg)) => {
return Err(ApiError::InvalidRequest(format!(
"MST validation failed: {}",
msg
)));
}
Err(e) => {
error!("CAR verification error: {:?}", e);
return Err(ApiError::InvalidRequest(format!(
"CAR verification failed: {}",
e
)));
}
}
}
let max_blocks = tranquil_config::get().import.max_blocks as usize;
let _write_lock = state.repo_write_locks.lock(user_id).await;
+13 -15
View File
@@ -92,30 +92,20 @@ impl CarVerifier {
pub fn verify_car_structure_only(
&self,
expected_did: &Did,
root_cid: &Cid,
blocks: &HashMap<Cid, Bytes>,
) -> Result<VerifiedCar, VerifyError> {
) -> Result<StructureVerifiedCar, VerifyError> {
let root_block = blocks
.get(root_cid)
.ok_or_else(|| VerifyError::BlockNotFound(root_cid.to_string()))?;
let commit =
Commit::from_cbor(root_block).map_err(|e| VerifyError::InvalidCommit(e.to_string()))?;
let commit_did = commit.did().as_str();
if commit_did != expected_did.as_str() {
return Err(VerifyError::DidMismatch {
commit_did: commit_did.to_string(),
expected_did: expected_did.to_string(),
});
}
let commit_did = commit.did().to_string().into();
let data_cid = commit.data();
self.verify_mst_structure(data_cid, blocks)?;
debug!(
"MST structure verified for DID {} (signature verification skipped for migration)",
expected_did
);
Ok(VerifiedCar {
did: expected_did.clone(),
debug!("MST structure verified for commit: {:?}", commit);
Ok(StructureVerifiedCar {
did: commit_did,
rev: commit.rev().to_string(),
data_cid: *data_cid,
prev: commit.prev().cloned(),
@@ -289,6 +279,14 @@ impl CarVerifier {
}
}
#[derive(Debug, Clone)]
pub struct StructureVerifiedCar {
pub did: Did,
pub rev: String,
pub data_cid: Cid,
pub prev: Option<Cid>,
}
#[derive(Debug, Clone)]
pub struct VerifiedCar {
pub did: Did,
@@ -73,7 +73,7 @@ fn write_varint(buf: &mut Vec<u8>, mut value: u64) {
}
#[tokio::test]
async fn test_import_rejects_car_for_different_user() {
async fn test_import_doesnt_reject_car_for_different_user() {
let client = client();
let (token_a, _did_a) = create_account_and_login(&client).await;
let (_token_b, did_b) = create_account_and_login(&client).await;
@@ -99,15 +99,9 @@ async fn test_import_rejects_car_for_different_user() {
.send()
.await
.expect("Import failed");
assert_eq!(import_res.status(), StatusCode::FORBIDDEN);
assert_eq!(import_res.status(), StatusCode::OK);
let body: serde_json::Value = import_res.json().await.unwrap();
assert!(
body["error"] == "InvalidRepo"
|| body["error"] == "InvalidRequest"
|| body["error"] == "DidMismatch",
"Expected InvalidRepo, DidMismatch, or InvalidRequest error, got: {:?}",
body
);
assert!(body.is_object() && body.as_object().unwrap().is_empty());
}
#[tokio::test]