Skip to content

Commit

Permalink
add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
joyqvq committed Dec 3, 2024
1 parent 3abb8f1 commit bafe2f2
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 102 deletions.
6 changes: 2 additions & 4 deletions crates/sui-e2e-tests/tests/passkey_e2e_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use fastcrypto::traits::ToFromBytes;
use p256::pkcs8::DecodePublicKey;
use passkey_authenticator::{Authenticator, UserValidationMethod};
use passkey_authenticator::Authenticator;
use passkey_client::Client;
use passkey_types::{
ctap2::Aaguid,
Expand All @@ -16,13 +16,11 @@ use passkey_types::{
Bytes, Passkey,
};
use shared_crypto::intent::{Intent, IntentMessage};
use std::net::SocketAddr;
use sui_core::authority_client::AuthorityAPI;
use sui_macros::sim_test;
use sui_test_transaction_builder::TestTransactionBuilder;
use sui_types::crypto::Signature;
use sui_types::error::SuiError;
use sui_types::error::UserInputError;
use sui_types::error::{SuiError, SuiResult};
use sui_types::signature::GenericSignature;
use sui_types::transaction::Transaction;
use sui_types::{
Expand Down
69 changes: 33 additions & 36 deletions crates/sui-e2e-tests/tests/passkey_session_e2e_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
use fastcrypto::{
ed25519::Ed25519KeyPair,
secp256r1::Secp256r1KeyPair,
traits::{KeyPair, ToFromBytes},
};
use p256::pkcs8::DecodePublicKey;
use passkey_authenticator::{Authenticator, UserValidationMethod};
use passkey_authenticator::Authenticator;
use passkey_client::Client;
use passkey_types::{
ctap2::Aaguid,
Expand All @@ -20,11 +19,11 @@ use passkey_types::{
Bytes, Passkey,
};
use rand::{rngs::StdRng, SeedableRng};
use shared_crypto::intent::{Intent, IntentMessage, PersonalMessage};
use shared_crypto::intent::{Intent, IntentMessage};
use sui_macros::sim_test;
use sui_test_transaction_builder::TestTransactionBuilder;
use sui_types::error::SuiError;
use sui_types::error::UserInputError;
use sui_types::error::{SuiError, SuiResult};
use sui_types::signature::GenericSignature;
use sui_types::transaction::Transaction;
use sui_types::{
Expand All @@ -34,7 +33,7 @@ use sui_types::{
};
use sui_types::{
crypto::{get_key_pair, Signature},
passkey_session_authenticator::{PasskeySessionAuthenticator, RawPasskeySessionAuthenticator},
passkey_session_authenticator::RawPasskeySessionAuthenticator,
};
use test_cluster::TestCluster;
use test_cluster::TestClusterBuilder;
Expand Down Expand Up @@ -62,30 +61,24 @@ async fn make_passkey_session_tx(
};

let response =
create_credential_and_commit_ephemeral_pk(test_cluster, None, register_msg, false, false)
.await;
create_credential_and_commit_ephemeral_pk(test_cluster, None, register_msg).await;
let ephemeral_signature = Signature::new_secure(&response.intent_msg, &eph_kp);

let passkey_session_authenticator = RawPasskeySessionAuthenticator {
authenticator_data: response.authenticator_data,
client_data_json: response.client_data_json,
register_signature: if wrong_register_sig {
let mut fake_signature = response.user_sig_bytes.clone();
fake_signature[2] = fake_signature[2] + 1;
fake_signature[2] += 1;
Signature::from_bytes(&fake_signature).unwrap()
} else {
Signature::from_bytes(&response.user_sig_bytes).unwrap()
},
max_epoch,
ephemeral_signature: if wrong_ephemeral_sig {
let fake_kp = Secp256r1KeyPair::generate(&mut StdRng::from_seed([0u8; 32]));
let intent_msg = IntentMessage::new(
Intent::personal_message(),
PersonalMessage {
message: "random".as_bytes().to_vec(),
},
);
Signature::new_secure(&intent_msg, &fake_kp)
let mut fake_signature = ephemeral_signature.as_bytes().to_vec().clone();
fake_signature[2] += 1;
Signature::from_bytes(&fake_signature).unwrap()
} else {
ephemeral_signature
},
Expand All @@ -102,8 +95,6 @@ async fn create_credential_and_commit_ephemeral_pk(
test_cluster: &TestCluster,
sender: Option<SuiAddress>,
passkey_challenge: Vec<u8>,
change_intent: bool,
change_tx: bool,
) -> PasskeyResponse<TransactionData> {
// set up authenticator and client
let my_aaguid = Aaguid::new_empty();
Expand Down Expand Up @@ -158,7 +149,8 @@ async fn create_credential_and_commit_ephemeral_pk(
let prefix = if y.unwrap()[31] % 2 == 0 { 0x02 } else { 0x03 };
let mut pk_bytes = vec![prefix];
pk_bytes.extend_from_slice(x.unwrap());
let pk = PublicKey::try_from_bytes(SignatureScheme::PasskeyAuthenticator, &pk_bytes).unwrap();
let pk =
PublicKey::try_from_bytes(SignatureScheme::PasskeySessionAuthenticator, &pk_bytes).unwrap();

// Request a signature from passkey with challenge set to passkey_digest.
let credential_request = CredentialRequestOptions {
Expand Down Expand Up @@ -226,7 +218,7 @@ async fn test_passkey_session_feature_deny() {
let test_cluster = TestClusterBuilder::new().build().await;

let kp: Ed25519KeyPair = get_key_pair().1;
let max_epoch = 2 as u64;
let max_epoch = 2_u64;
let tx = make_passkey_session_tx(&test_cluster, kp, max_epoch, None, false, false).await;
let err = execute_tx(tx, &test_cluster).await.unwrap_err();
assert!(matches!(
Expand All @@ -246,8 +238,12 @@ async fn test_passkey_authenticator_scenarios() {
.build()
.await;

let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
config.set_zklogin_max_epoch_upper_bound_delta_for_testing(Some(1));
config
});
let kp = Ed25519KeyPair::generate(&mut StdRng::from_seed([0u8; 32]));
let max_epoch = 1 as u64;
let max_epoch = 1_u64;

// case 1: sign a tx with passkey ephemeral sig and register sig, passes
let tx = make_passkey_session_tx(&test_cluster, kp.copy(), max_epoch, None, false, false).await;
Expand Down Expand Up @@ -303,26 +299,27 @@ async fn test_passkey_authenticator_scenarios() {
// case 5: invalid ephemeral signature fails to verify.
let tx = make_passkey_session_tx(&test_cluster, kp.copy(), max_epoch, None, false, true).await;
let res = execute_tx(tx, &test_cluster).await;
println!("res: {:?}", res);
assert!(matches!(
res,
Err(SuiError::InvalidSignature { error }) if error == "Fails to verify ephemeral sig"
));
// // case 6: advance 2 epochs, the ephermal sig expires, fails to verify
// test_cluster.trigger_reconfiguration().await;
// test_cluster.trigger_reconfiguration().await;
// case 6: advance 2 epochs, the ephermal sig expires, fails to verify
test_cluster.trigger_reconfiguration().await;
test_cluster.trigger_reconfiguration().await;

// let tx = make_passkey_session_tx(&test_cluster, kp.copy(), max_epoch, None, false, false).await;
// let res = execute_tx(tx, &test_cluster).await;
// assert!(matches!(
// res,
// Err(SuiError::InvalidSignature { error }) if error == "Passkey session max epoch too large 2, current epoch 2, max accepted: 1"
// ));
// // case 4: max_epoch bound delta = 1, but max epoch - current epoch > 1, too large, fails
// let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
// config.set_passkey_session_max_epoch_upper_bound_delta_for_testing(Some(1));
// config
// });
let tx = make_passkey_session_tx(&test_cluster, kp.copy(), max_epoch, None, false, false).await;
let res = execute_tx(tx, &test_cluster).await;
assert!(matches!(
res,
Err(SuiError::InvalidSignature { error }) if error == "Passkey session expired at epoch 1, current epoch 2"
));
// case 4: max_epoch bound delta = 1, but max epoch (10) - current epoch (2) > 1, too large, fails
let tx = make_passkey_session_tx(&test_cluster, kp.copy(), 10, None, false, false).await;
let res = execute_tx(tx, &test_cluster).await;
assert!(matches!(
res,
Err(SuiError::InvalidSignature { error }) if error == "Passkey session max epoch too large 10, current epoch 2, max accepted: 3"
));
}

#[sim_test]
Expand Down
34 changes: 4 additions & 30 deletions crates/sui-e2e-tests/tests/passkey_util.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,13 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
use fastcrypto::traits::ToFromBytes;
use p256::pkcs8::DecodePublicKey;
use passkey_authenticator::{Authenticator, UserValidationMethod};
use passkey_client::Client;
use passkey_types::{
ctap2::Aaguid,
rand::random_vec,
webauthn::{
AttestationConveyancePreference, CredentialCreationOptions, CredentialRequestOptions,
PublicKeyCredentialCreationOptions, PublicKeyCredentialParameters,
PublicKeyCredentialRequestOptions, PublicKeyCredentialRpEntity, PublicKeyCredentialType,
PublicKeyCredentialUserEntity, UserVerificationRequirement,
},
Bytes, Passkey,
};
use shared_crypto::intent::{Intent, IntentMessage};
use passkey_authenticator::UserValidationMethod;
use shared_crypto::intent::IntentMessage;
use std::net::SocketAddr;
use sui_core::authority_client::AuthorityAPI;
use sui_macros::sim_test;
use sui_test_transaction_builder::TestTransactionBuilder;
use sui_types::crypto::Signature;
use sui_types::error::UserInputError;
use sui_types::error::{SuiError, SuiResult};
use sui_types::signature::GenericSignature;
use sui_types::base_types::SuiAddress;
use sui_types::error::SuiResult;
use sui_types::transaction::Transaction;
use sui_types::{
base_types::SuiAddress,
crypto::{PublicKey, SignatureScheme},
passkey_authenticator::{to_signing_message, PasskeyAuthenticator},
transaction::TransactionData,
};
use test_cluster::TestCluster;
use test_cluster::TestClusterBuilder;
use url::Url;

/// Helper struct to initialize passkey client.
pub struct MyUserValidationMethod {}
Expand Down
12 changes: 0 additions & 12 deletions crates/sui-protocol-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,6 @@ struct FeatureFlags {
#[serde(skip_serializing_if = "is_false")]
passkey_session_auth: bool,

// Set the upper bound allowed for max_epoch in passkey session signature.
#[serde(skip_serializing_if = "Option::is_none")]
passkey_session_max_epoch_upper_bound_delta: Option<u64>,

// Use AuthorityCapabilitiesV2
#[serde(skip_serializing_if = "is_false")]
authority_capabilities_v2: bool,
Expand Down Expand Up @@ -3142,14 +3138,6 @@ impl ProtocolConfig {
self.feature_flags.passkey_session_auth = val
}

pub fn set_passkey_session_max_epoch_upper_bound_delta_for_testing(
&mut self,
val: Option<u64>,
) {
self.feature_flags
.passkey_session_max_epoch_upper_bound_delta = val
}

pub fn set_consensus_distributed_vote_scoring_strategy_for_testing(&mut self, val: bool) {
self.feature_flags
.consensus_distributed_vote_scoring_strategy = val;
Expand Down
4 changes: 4 additions & 0 deletions crates/sui-rosetta/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,10 @@ impl From<SuiPublicKey> for PublicKey {
hex_bytes: Hex::from_bytes(&k.0),
curve_type: CurveType::Secp256r1,
},
SuiPublicKey::PasskeySession(k) => PublicKey {
hex_bytes: Hex::from_bytes(&k.0),
curve_type: CurveType::Secp256r1,
},
}
}
}
Expand Down
14 changes: 12 additions & 2 deletions crates/sui-types/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ pub enum PublicKey {
Secp256r1(Secp256r1PublicKeyAsBytes),
ZkLogin(ZkLoginPublicIdentifier),
Passkey(Secp256r1PublicKeyAsBytes),
PasskeySession(Secp256r1PublicKeyAsBytes),
}

/// A wrapper struct to retrofit in [enum PublicKey] for zkLogin.
Expand Down Expand Up @@ -294,6 +295,7 @@ impl AsRef<[u8]> for PublicKey {
PublicKey::Secp256r1(pk) => &pk.0,
PublicKey::ZkLogin(z) => &z.0,
PublicKey::Passkey(pk) => &pk.0,
PublicKey::PasskeySession(pk) => &pk.0,
}
}
}
Expand Down Expand Up @@ -331,6 +333,11 @@ impl EncodeDecodeBase64 for PublicKey {
FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
)?)?;
Ok(PublicKey::Passkey((&pk).into()))
} else if x == &SignatureScheme::PasskeySessionAuthenticator.flag() {
let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
)?)?;
Ok(PublicKey::PasskeySession((&pk).into()))
} else {
Err(FastCryptoError::InvalidInput)
}
Expand Down Expand Up @@ -359,8 +366,10 @@ impl PublicKey {
SignatureScheme::Secp256r1 => Ok(PublicKey::Secp256r1(
(&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
)),
SignatureScheme::PasskeyAuthenticator
| SignatureScheme::PasskeySessionAuthenticator => Ok(PublicKey::Passkey(
SignatureScheme::PasskeyAuthenticator => Ok(PublicKey::Passkey(
(&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
)),
SignatureScheme::PasskeySessionAuthenticator => Ok(PublicKey::PasskeySession(
(&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
)),
_ => Err(eyre!("Unsupported curve")),
Expand All @@ -374,6 +383,7 @@ impl PublicKey {
PublicKey::Secp256r1(_) => Secp256r1SuiSignature::SCHEME,
PublicKey::ZkLogin(_) => SignatureScheme::ZkLoginAuthenticator,
PublicKey::Passkey(_) => SignatureScheme::PasskeyAuthenticator,
PublicKey::PasskeySession(_) => SignatureScheme::PasskeySessionAuthenticator,
}
}

Expand Down
8 changes: 7 additions & 1 deletion crates/sui-types/src/passkey_session_authenticator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl Serialize for PasskeySessionAuthenticator {
impl PasskeySessionAuthenticator {
/// Returns the public key of the passkey authenticator.
pub fn get_pk(&self) -> SuiResult<PublicKey> {
Ok(PublicKey::Passkey((&self.passkey_pk).into()))
Ok(PublicKey::PasskeySession((&self.passkey_pk).into()))
}
}

Expand Down Expand Up @@ -200,6 +200,12 @@ impl AuthenticatorTrait for PasskeySessionAuthenticator {
) -> SuiResult {
// the checks here ensure that `current_epoch + passkey_session_max_epoch_upper_bound_delta >= self.max_epoch >= current_epoch`.
// 1. if the config for upper bound is set, ensure that the max epoch in signature is not larger than epoch + upper_bound.
println!(
"tktk max_epoch_upper_bound_delta: {:?}",
max_epoch_upper_bound_delta
);
println!("tktk self.max_epoch: {:?}", self.max_epoch);
println!("tktk epoch: {:?}", epoch);
if let Some(delta) = max_epoch_upper_bound_delta {
let max_epoch_upper_bound =
epoch.checked_add(delta).ok_or(SuiError::InvalidSignature {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,20 @@ use crate::{
error::SuiError,
object::Object,
signature::GenericSignature,
signature_verification::VerifiedDigestCache,
transaction::{TransactionData, TEST_ONLY_GAS_UNIT_FOR_TRANSFER},
};
use fastcrypto::ed25519::Ed25519KeyPair;
use std::sync::Arc;
use passkey_types::webauthn::{CredentialRequestOptions, PublicKeyCredentialRequestOptions};

use fastcrypto::traits::KeyPair;
use fastcrypto::traits::ToFromBytes;
use p256::pkcs8::DecodePublicKey;
use passkey_types::webauthn::CredentialCreationOptions;

use crate::passkey_authenticator::passkey_authenticator_test::make_credential_creation_option;
use passkey_authenticator::{Authenticator, UserValidationMethod};
use passkey_authenticator::Authenticator;
use passkey_client::Client;
use passkey_types::{
ctap2::Aaguid,
rand::random_vec,
webauthn::{
AttestationConveyancePreference, CredentialCreationOptions, CredentialRequestOptions,
PublicKeyCredentialCreationOptions, PublicKeyCredentialParameters,
PublicKeyCredentialRequestOptions, PublicKeyCredentialRpEntity, PublicKeyCredentialType,
PublicKeyCredentialUserEntity, UserVerificationRequirement,
},
Bytes, Passkey,
};
use rand::rngs::StdRng;
use rand::SeedableRng;
use shared_crypto::intent::PersonalMessage;
use passkey_types::{ctap2::Aaguid, webauthn::UserVerificationRequirement, Bytes, Passkey};
use shared_crypto::intent::{Intent, IntentMessage};
use url::Url;
/// Response with fields from passkey authentication.
Expand Down

0 comments on commit bafe2f2

Please sign in to comment.