Skip to content

Commit 5987ea9

Browse files
authored
Merge branch 'main' into tore/chore/fix-to-rc25
2 parents 15b9651 + 2b3e583 commit 5987ea9

File tree

16 files changed

+204
-92
lines changed

16 files changed

+204
-92
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core-client/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,7 @@ fn check_ext_pt_signature(
901901
external_handles: Vec<Vec<u8>>,
902902
domain: Eip712Domain,
903903
kms_addrs: &[alloy_primitives::Address],
904+
extra_data: Vec<u8>,
904905
) -> anyhow::Result<()> {
905906
// convert received data into proper format for EIP-712 verification
906907
if external_sig.len() != 65 {
@@ -918,7 +919,7 @@ fn check_ext_pt_signature(
918919
tracing::debug!("PTs: {:?}", plaintexts);
919920
tracing::debug!("ext. handles: {:?}", external_handles);
920921

921-
let hash = compute_pt_message_hash(external_handles, plaintexts, domain);
922+
let hash = compute_pt_message_hash(external_handles, plaintexts, domain, extra_data);
922923

923924
let addr = sig.recover_address_from_prehash(&hash)?;
924925
tracing::info!("recovered address: {}", addr);
@@ -942,11 +943,12 @@ fn check_external_decryption_signature(
942943
for response in responses {
943944
let payload = response.payload.as_ref().unwrap();
944945
check_ext_pt_signature(
945-
payload.external_signature(),
946+
response.external_signature(),
946947
&payload.plaintexts,
947948
external_handles.to_owned(),
948949
domain.clone(),
949950
kms_addrs,
951+
vec![],
950952
)?;
951953

952954
for (idx, pt) in payload.plaintexts.iter().enumerate() {

core/grpc/proto/kms.v1.proto

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ message PublicDecryptionRequest {
223223

224224
// The EIP712 domain used for signing the response.
225225
Eip712DomainMsg domain = 4;
226+
227+
// Extra data from the gateway.
228+
bytes extra_data = 5;
226229
}
227230

228231
// KMS-internal Public Decryption Response Payload, containing meta data, plaintexts
@@ -234,27 +237,29 @@ message PublicDecryptionResponsePayload {
234237
// trusted keys.
235238
// TODO should be renamed to make it clear it is the server's key
236239
bytes verification_key = 1;
237-
// Digest of the request validated.
238-
// Needed to ensure that the response is for the expected request.
239-
// THIS IS DEPRECATED AND KMS WILL LEAVE THIS FIELD EMPTY,
240-
// instead, we will use request_id to specify the link.
241-
bytes digest = 2 [deprecated=true];
240+
242241
// A list of plaintexts, as little endian byte arrays. One for each
243242
// ciphertext.
244-
repeated TypedPlaintext plaintexts = 3;
245-
// the signature on external_decryption_result for the external recipient
246-
// (e.g. using EIP712 for fhevm)
247-
optional bytes external_signature = 4;
243+
repeated TypedPlaintext plaintexts = 2;
244+
248245
// Request ID of the request that this response corresponds to.
249-
RequestId request_id = 5;
246+
RequestId request_id = 3;
250247
}
251248

252249
// KMS-internal Public Decryption Response
253250
message PublicDecryptionResponse {
254251
// Signature of the serialization of [PublicDecryptionResponsePayload].
255252
bytes signature = 1;
253+
254+
// the signature on external_decryption_result for the external recipient
255+
// (e.g. using EIP712 for fhevm)
256+
optional bytes external_signature = 2;
257+
256258
// The payload that is signed
257-
PublicDecryptionResponsePayload payload = 2;
259+
PublicDecryptionResponsePayload payload = 3;
260+
261+
// Extra data used in the EIP712 signature - external_signature.
262+
bytes extra_data = 4;
258263
}
259264

260265
// Eip712 domain information.
@@ -289,38 +294,51 @@ message UserDecryptionRequest {
289294

290295
// The user's EIP712 domain. This MUST be present. Furthermore, the `verifying_contract` MUST be set and be distinct from `client_address`.
291296
Eip712DomainMsg domain = 6;
297+
298+
// Extra data from the gateway.
299+
bytes extra_data = 7;
292300
}
293301

294302
message UserDecryptionResponse {
295303
bytes signature = 1;
304+
296305
// This is the external signature created from the Eip712 domain
297306
// on the structure, where userDecryptedShare is bc2wrap::serialize(&payload)
298307
// struct UserDecryptResponseVerification {
299308
// bytes publicKey;
300309
// uint256[] ctHandles;
301-
// bytes userDecryptedShare;
310+
// bytes userDecryptedShare; // serialization of payload
311+
// bytes extraData;
302312
// }
303313
bytes external_signature = 2;
314+
304315
// The actual [UserDecryptionResponsePayload].
305316
UserDecryptionResponsePayload payload = 3;
317+
318+
// Extra data used in the EIP712 signature - external_signature.
319+
bytes extra_data = 4;
306320
}
307321

308322
message UserDecryptionResponsePayload {
309323
// The server's signature verification key, Encoded using SEC1.
310324
// Needed to validate the response, but MUST also be linked to a list of
311325
// trusted keys.
312326
bytes verification_key = 1;
327+
313328
// This is needed to ensure the response corresponds to the request.
314329
// It is the digest of UserDecryptionLinker hashed using EIP712
315330
// under the given domain in the request.
316331
bytes digest = 2;
332+
317333
// The resulting signcrypted ciphertexts, each ciphertext
318334
// must be decrypted and then reconstructed with the other shares
319335
// to produce the final plaintext.
320336
repeated TypedSigncryptedCiphertext signcrypted_ciphertexts = 3;
337+
321338
// The ID of the MPC party doing the user decryption. Used for polynomial
322339
// reconstruction.
323340
uint32 party_id = 4;
341+
324342
// The degree of the sharing scheme used.
325343
uint32 degree = 5;
326344
}

core/grpc/src/rpc_types.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ alloy_sol_types::sol! {
4141
bytes publicKey;
4242
bytes32[] ctHandles;
4343
bytes userDecryptedShare;
44+
bytes extraData;
4445
}
4546
}
4647

@@ -61,6 +62,7 @@ alloy_sol_types::sol! {
6162
struct PublicDecryptVerification {
6263
bytes32[] ctHandles;
6364
bytes decryptedResult;
65+
bytes extraData;
6466
}
6567
}
6668

@@ -1080,6 +1082,7 @@ mod tests {
10801082
client_address: client_address.to_checksum(None),
10811083
enc_key: vec![],
10821084
domain: None,
1085+
extra_data: vec![],
10831086
};
10841087
assert!(req
10851088
.compute_link_checked()
@@ -1097,6 +1100,7 @@ mod tests {
10971100
client_address: client_address.to_checksum(None),
10981101
enc_key: vec![],
10991102
domain: Some(domain.clone()),
1103+
extra_data: vec![],
11001104
};
11011105
assert!(req
11021106
.compute_link_checked()
@@ -1117,6 +1121,7 @@ mod tests {
11171121
client_address: client_address.to_checksum(None),
11181122
enc_key: vec![],
11191123
domain: Some(bad_domain),
1124+
extra_data: vec![],
11201125
};
11211126

11221127
assert!(req
@@ -1135,6 +1140,7 @@ mod tests {
11351140
client_address: client_address.to_checksum(None),
11361141
enc_key: vec![],
11371142
domain: Some(domain.clone()),
1143+
extra_data: vec![],
11381144
};
11391145
assert!(req.compute_link_checked().is_ok());
11401146
}

core/service/src/client/js_api.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ struct UserDecryptionResponseHex {
380380
// NOTE: this is the external signature
381381
signature: String,
382382
payload: Option<String>,
383+
extra_data: Option<String>,
383384
}
384385

385386
#[cfg(feature = "wasm_tests")]
@@ -392,6 +393,7 @@ fn resp_to_js(agg_resp: Vec<UserDecryptionResponse>) -> JsValue {
392393
Some(inner) => Some(hex::encode(serialize(&inner).unwrap())),
393394
None => None,
394395
},
396+
extra_data: Some(hex::encode(&resp.extra_data)),
395397
};
396398
out.push(r);
397399
}
@@ -421,6 +423,10 @@ fn js_to_resp(json: JsValue) -> anyhow::Result<Vec<UserDecryptionResponse>> {
421423
}
422424
None => None,
423425
},
426+
extra_data: match hex_resp.extra_data {
427+
Some(inner) => hex::decode(&inner)?,
428+
None => vec![],
429+
},
424430
});
425431
}
426432
Ok(out)
@@ -473,7 +479,8 @@ fn js_to_resp(json: JsValue) -> anyhow::Result<Vec<UserDecryptionResponse>> {
473479
/// [
474480
/// {
475481
/// signature: '69e7e040cab157aa819015b321c012dccb1545ffefd325b359b492653f0347517e28e66c572cdc299e259024329859ff9fcb0096e1ce072af0b6e1ca1fe25ec6',
476-
/// payload: '0100000029...'
482+
/// payload: '0100000029...',
483+
/// extra_data: '01234...',
477484
/// }
478485
/// ]
479486
/// ```

core/service/src/client/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@ impl Client {
767767
key_id: Some((*key_id).into()),
768768
domain: Some(domain_msg),
769769
request_id: Some((*request_id).into()),
770+
extra_data: vec![],
770771
};
771772
Ok(req)
772773
}
@@ -824,6 +825,7 @@ impl Client {
824825
typed_ciphertexts,
825826
key_id: Some((*key_id).into()),
826827
domain: Some(domain_msg),
828+
extra_data: vec![],
827829
},
828830
UnifiedPublicEncKey::MlKem512(enc_pk),
829831
UnifiedPrivateEncKey::MlKem512(enc_sk),
@@ -872,6 +874,7 @@ impl Client {
872874
typed_ciphertexts,
873875
key_id: Some((*key_id).into()),
874876
domain: Some(domain_msg),
877+
extra_data: vec![],
875878
},
876879
UnifiedPublicEncKey::MlKem1024(enc_pk),
877880
UnifiedPrivateEncKey::MlKem1024(enc_sk),

core/service/src/engine/base.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,10 @@ pub(crate) fn compute_external_user_decrypt_signature(
439439
payload: &UserDecryptionResponsePayload,
440440
eip712_domain: &Eip712Domain,
441441
user_pk: &UnifiedPublicEncKey,
442+
extra_data: Vec<u8>,
442443
) -> anyhow::Result<Vec<u8>> {
443-
let message_hash = compute_user_decrypt_message_hash(payload, eip712_domain, user_pk)?;
444+
let message_hash =
445+
compute_user_decrypt_message_hash(payload, eip712_domain, user_pk, extra_data)?;
444446

445447
let signer = PrivateKeySigner::from_signing_key(server_sk.sk().clone());
446448
let signer_address = signer.address();
@@ -462,9 +464,10 @@ pub(crate) fn compute_external_pt_signature(
462464
server_sk: &PrivateSigKey,
463465
ext_handles_bytes: Vec<Vec<u8>>,
464466
pts: &[TypedPlaintext],
467+
extra_data: Vec<u8>,
465468
eip712_domain: Eip712Domain,
466469
) -> Vec<u8> {
467-
let message_hash = compute_pt_message_hash(ext_handles_bytes, pts, eip712_domain);
470+
let message_hash = compute_pt_message_hash(ext_handles_bytes, pts, eip712_domain, extra_data);
468471

469472
let signer = PrivateKeySigner::from_signing_key(server_sk.sk().clone());
470473
let signer_address = signer.address();
@@ -715,6 +718,7 @@ pub fn compute_pt_message_hash(
715718
ext_handles_bytes: Vec<Vec<u8>>,
716719
pts: &[TypedPlaintext],
717720
eip712_domain: Eip712Domain,
721+
extra_data: Vec<u8>,
718722
) -> B256 {
719723
// convert external_handles back to U256 to be signed
720724
#[allow(clippy::useless_conversion)]
@@ -730,6 +734,7 @@ pub fn compute_pt_message_hash(
730734
let message = PublicDecryptVerification {
731735
ctHandles: external_handles,
732736
decryptedResult: pt_bytes,
737+
extraData: extra_data.into(),
733738
};
734739

735740
let message_hash = message.eip712_signing_hash(&eip712_domain);
@@ -749,14 +754,14 @@ pub type KeyGenCallValues = HashMap<PubDataType, SignedPubDataHandleInternal>;
749754

750755
// Values that need to be stored temporarily as part of an async decryption call.
751756
// Represents the request ID of the request and the result of the decryption (a batch of plaintests),
752-
// as well as an external signature on the batch.
757+
// an external signature on the batch and any extra data.
753758
#[cfg(feature = "non-wasm")]
754-
pub type PubDecCallValues = (RequestId, Vec<TypedPlaintext>, Vec<u8>);
759+
pub type PubDecCallValues = (RequestId, Vec<TypedPlaintext>, Vec<u8>, Vec<u8>);
755760

756761
// Values that need to be stored temporarily as part of an async user decryption call.
757-
// Represents UserDecryptionResponsePayload, external_handles, external_signature.
762+
// Represents UserDecryptionResponsePayload, external_handles, external_signature and extra_data.
758763
#[cfg(feature = "non-wasm")]
759-
pub type UserDecryptCallValues = (UserDecryptionResponsePayload, Vec<u8>);
764+
pub type UserDecryptCallValues = (UserDecryptionResponsePayload, Vec<u8>, Vec<u8>);
760765

761766
/// Helper method which takes a [KeyGenCallValues] and returns
762767
/// [HashMap<String, SignedPubDataHandle>] by applying the [ToString] function on [PubDataType] for each element in the map.

core/service/src/engine/centralized/central_kms.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ pub async fn async_user_decrypt<
527527
server_verf_key: Vec<u8>,
528528
domain: &alloy_sol_types::Eip712Domain,
529529
metric_tags: Vec<(&'static str, String)>,
530+
extra_data: Vec<u8>,
530531
) -> anyhow::Result<(UserDecryptionResponsePayload, Vec<u8>)> {
531532
use observability::{
532533
metrics,
@@ -582,8 +583,13 @@ pub async fn async_user_decrypt<
582583
degree: 0, // In the centralized KMS, the degree is always 0 since result is a constant
583584
};
584585

585-
let external_signature =
586-
compute_external_user_decrypt_signature(sig_key, &payload, domain, client_enc_key)?;
586+
let external_signature = compute_external_user_decrypt_signature(
587+
sig_key,
588+
&payload,
589+
domain,
590+
client_enc_key,
591+
extra_data,
592+
)?;
587593

588594
Ok((payload, external_signature))
589595
}

0 commit comments

Comments
 (0)