-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathckd_verification.rs
More file actions
131 lines (110 loc) · 4.73 KB
/
Copy pathckd_verification.rs
File metadata and controls
131 lines (110 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use crate::common::{
CKD_PV_VERIFICATION_PORT_SEED, CKD_VERIFICATION_PORT_SEED, must_get_bls_public_key,
must_get_domain, must_setup_cluster,
};
use anyhow::Context;
use blstrs::{G1Projective, G2Projective, Scalar};
use group::Group as _;
use group::ff::Field as _;
use near_account_id::AccountId;
use near_mpc_contract_interface::types::kdf::derive_app_id;
use near_mpc_contract_interface::types::{
Bls12381G1PublicKey, Bls12381G2PublicKey, CKDAppPublicKey, CKDAppPublicKeyPV, Protocol,
};
use rand::SeedableRng;
use threshold_signatures::confidential_key_derivation::{
CKDOutput, VerifyingKey, ciphersuite::verify_signature,
};
// derivation_path sent by send_ckd_request
const DERIVATION_PATH: &str = "test";
fn verify_ckd(
account_id: &AccountId,
path: &str,
mpc_public_key: &Bls12381G2PublicKey,
private_key: Scalar,
big_y: &Bls12381G1PublicKey,
big_c: &Bls12381G1PublicKey,
) -> anyhow::Result<bool> {
let big_y = G1Projective::try_from(big_y).context("invalid big_y G1 point")?;
let big_c = G1Projective::try_from(big_c).context("invalid big_c G1 point")?;
let mpc_pk = G2Projective::try_from(mpc_public_key).context("invalid MPC G2 key")?;
let mpc_vk = VerifyingKey::new(mpc_pk);
let confidential_key = CKDOutput::new(big_y, big_c).unmask(private_key);
let app_id = derive_app_id(account_id, path);
Ok(verify_signature(&mpc_vk, app_id.as_ref(), &confidential_key).is_ok())
}
/// Verify that a CKD response (AppPublicKey variant) is mathematically correct.
#[tokio::test]
#[expect(non_snake_case)]
async fn ckd_response__passes_cryptographic_verification() {
// given
let (cluster, running) = must_setup_cluster(CKD_VERIFICATION_PORT_SEED, |_| {}).await;
let bls_domain = must_get_domain(&running, Protocol::ConfidentialKeyDerivation);
let mpc_pk = must_get_bls_public_key(&running, bls_domain.id);
let user = cluster.default_user_account().clone();
let mut rng = rand::rngs::StdRng::seed_from_u64(1);
let private_key = Scalar::random(&mut rng);
let app_public_key = CKDAppPublicKey::AppPublicKey(Bls12381G1PublicKey::from(
&(G1Projective::generator() * private_key),
));
// when
let outcome = cluster
.send_ckd_request(bls_domain.id, app_public_key, &user)
.await
.expect("CKD request transaction failed");
// then
assert!(
outcome.is_success(),
"CKD request failed: {:?}",
outcome.failure_message()
);
let response: serde_json::Value = outcome.json().expect("failed to deserialize CKD response");
let big_y: Bls12381G1PublicKey =
serde_json::from_value(response["big_y"].clone()).expect("failed to parse big_y");
let big_c: Bls12381G1PublicKey =
serde_json::from_value(response["big_c"].clone()).expect("failed to parse big_c");
assert!(
verify_ckd(&user, DERIVATION_PATH, &mpc_pk, private_key, &big_y, &big_c)
.expect("verify_ckd failed"),
"CKD response failed cryptographic verification"
);
}
/// Verify that a CKD response (publicly verifiable AppPublicKeyPV variant) is mathematically correct.
#[tokio::test]
#[expect(non_snake_case)]
async fn ckd_pv_response__passes_cryptographic_verification() {
// given
let (cluster, running) = must_setup_cluster(CKD_PV_VERIFICATION_PORT_SEED, |_| {}).await;
let bls_domain = must_get_domain(&running, Protocol::ConfidentialKeyDerivation);
let mpc_pk = must_get_bls_public_key(&running, bls_domain.id);
let user = cluster.default_user_account().clone();
let mut rng = rand::rngs::StdRng::seed_from_u64(2);
let private_key = Scalar::random(&mut rng);
let pk1 = G1Projective::generator() * private_key;
let pk2 = G2Projective::generator() * private_key;
let app_public_key = CKDAppPublicKey::AppPublicKeyPV(CKDAppPublicKeyPV {
pk1: Bls12381G1PublicKey::from(&pk1),
pk2: Bls12381G2PublicKey::from(&pk2),
});
// when
let outcome = cluster
.send_ckd_request(bls_domain.id, app_public_key, &user)
.await
.expect("CKD PV request transaction failed");
// then
assert!(
outcome.is_success(),
"CKD PV request failed: {:?}",
outcome.failure_message()
);
let response: serde_json::Value = outcome.json().expect("failed to deserialize CKD response");
let big_y: Bls12381G1PublicKey =
serde_json::from_value(response["big_y"].clone()).expect("failed to parse big_y");
let big_c: Bls12381G1PublicKey =
serde_json::from_value(response["big_c"].clone()).expect("failed to parse big_c");
assert!(
verify_ckd(&user, DERIVATION_PATH, &mpc_pk, private_key, &big_y, &big_c)
.expect("verify_ckd failed"),
"CKD PV response failed cryptographic verification"
);
}