diff --git a/.github/workflows/move.yml b/.github/workflows/move.yml new file mode 100644 index 00000000000000..62d4f8f67734e1 --- /dev/null +++ b/.github/workflows/move.yml @@ -0,0 +1,15 @@ +name: Move + +on: + push: + branches: [ ] + pull_request: + branches: [ ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 00000000000000..97f73f3d57d558 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,22 @@ +name: Rust + +on: + push: + branches: [ ] + pull_request: + branches: [ ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/aptos-move/aptos-vm/src/natives.rs b/aptos-move/aptos-vm/src/natives.rs index 1ff10bb7da49b8..5073ffa4cebd23 100644 --- a/aptos-move/aptos-vm/src/natives.rs +++ b/aptos-move/aptos-vm/src/natives.rs @@ -202,10 +202,10 @@ pub fn assert_no_test_natives(err_msg: &str) { || module_name.as_str() == "multi_ed25519" && func_name.as_str() == "generate_keys_internal" || module_name.as_str() == "multi_ed25519" && func_name.as_str() == "sign_internal" - || module_name.as_str() == "bls12381" + || module_name.as_str() == "ed25519" && func_name.as_str() == "generate_keys_internal" - || module_name.as_str() == "bls12381" && func_name.as_str() == "sign_internal" - || module_name.as_str() == "bls12381" + || module_name.as_str() == "ed25519" && func_name.as_str() == "sign_internal" + || module_name.as_str() == "ed25519" && func_name.as_str() == "generate_proof_of_possession_internal" || module_name.as_str() == "event" && func_name.as_str() == "emitted_events_internal") diff --git a/aptos-move/e2e-move-tests/src/stake.rs b/aptos-move/e2e-move-tests/src/stake.rs index 566e94023ad49c..2f2af49f05d79c 100644 --- a/aptos-move/e2e-move-tests/src/stake.rs +++ b/aptos-move/e2e-move-tests/src/stake.rs @@ -3,7 +3,7 @@ use crate::harness::MoveHarness; use aptos_cached_packages::aptos_stdlib; -use aptos_crypto::{bls12381, PrivateKey, Uniform}; +use aptos_crypto::{ed25519, PrivateKey, Uniform}; use aptos_language_e2e_tests::account::Account; use aptos_types::{ account_address::AccountAddress, account_config::CORE_CODE_ADDRESS, @@ -76,18 +76,11 @@ pub fn rotate_consensus_key( account: &Account, pool_address: AccountAddress, ) -> TransactionStatus { - let consensus_key = bls12381::PrivateKey::generate_for_testing(); + let consensus_key = ed25519::PrivateKey::generate_for_testing(); let consensus_pubkey = consensus_key.public_key().to_bytes().to_vec(); - let proof_of_possession = bls12381::ProofOfPossession::create(&consensus_key) - .to_bytes() - .to_vec(); harness.run_transaction_payload( account, - aptos_stdlib::stake_rotate_consensus_key( - pool_address, - consensus_pubkey, - proof_of_possession, - ), + aptos_stdlib::stake_rotate_consensus_key(pool_address, consensus_pubkey), ) } diff --git a/aptos-move/e2e-move-tests/src/tests/gas.rs b/aptos-move/e2e-move-tests/src/tests/gas.rs index 3b542a2614c97a..627588d07d8f20 100644 --- a/aptos-move/e2e-move-tests/src/tests/gas.rs +++ b/aptos-move/e2e-move-tests/src/tests/gas.rs @@ -12,7 +12,7 @@ use crate::{ MoveHarness, }; use aptos_cached_packages::{aptos_stdlib, aptos_token_sdk_builder}; -use aptos_crypto::{bls12381, PrivateKey, Uniform}; +use aptos_crypto::{ed25519, PrivateKey, Uniform}; use aptos_gas_profiling::TransactionGasLog; use aptos_types::{ account_address::{default_stake_pool_address, AccountAddress}, @@ -145,20 +145,13 @@ fn test_gas() { ), ); let pool_address = default_stake_pool_address(account_1_address, account_2_address); - let consensus_key = bls12381::PrivateKey::generate_for_testing(); + let consensus_key = ed25519::PrivateKey::generate_for_testing(); let consensus_pubkey = consensus_key.public_key().to_bytes().to_vec(); - let proof_of_possession = bls12381::ProofOfPossession::create(&consensus_key) - .to_bytes() - .to_vec(); run( &mut harness, "RotateConsensusKey", account_2, - aptos_stdlib::stake_rotate_consensus_key( - pool_address, - consensus_pubkey, - proof_of_possession, - ), + aptos_stdlib::stake_rotate_consensus_key(pool_address, consensus_pubkey), ); run( &mut harness, diff --git a/aptos-move/framework/aptos-framework/doc/genesis.md b/aptos-move/framework/aptos-framework/doc/genesis.md index b942bf5f86e5fe..ac9224a7cf553f 100644 --- a/aptos-move/framework/aptos-framework/doc/genesis.md +++ b/aptos-move/framework/aptos-framework/doc/genesis.md @@ -779,7 +779,6 @@ encoded in a single BCS byte array. operator, pool_address, validator.consensus_pubkey, - validator.proof_of_possession, ); stake::update_network_and_fullnode_addresses( operator, diff --git a/aptos-move/framework/aptos-framework/doc/stake.md b/aptos-move/framework/aptos-framework/doc/stake.md index 3474162b538baa..3152a55531eb36 100644 --- a/aptos-move/framework/aptos-framework/doc/stake.md +++ b/aptos-move/framework/aptos-framework/doc/stake.md @@ -149,7 +149,6 @@ or if their stake drops below the min required, they would get removed at the en
use 0x1::account;
 use 0x1::aptos_coin;
-use 0x1::bls12381;
 use 0x1::coin;
 use 0x1::error;
 use 0x1::event;
@@ -1959,7 +1958,7 @@ to set later.
 Initialize the validator account and give ownership to the signing account.
 
 
-
public entry fun initialize_validator(account: &signer, consensus_pubkey: vector<u8>, proof_of_possession: vector<u8>, network_addresses: vector<u8>, fullnode_addresses: vector<u8>)
+
public entry fun initialize_validator(account: &signer, consensus_pubkey: vector<u8>, network_addresses: vector<u8>, fullnode_addresses: vector<u8>)
 
@@ -1971,17 +1970,10 @@ Initialize the validator account and give ownership to the signing account.
public entry fun initialize_validator(
     account: &signer,
     consensus_pubkey: vector<u8>,
-    proof_of_possession: vector<u8>,
     network_addresses: vector<u8>,
     fullnode_addresses: vector<u8>,
 ) acquires AllowedValidators {
     // Checks the public key has a valid proof-of-possession to prevent rogue-key attacks.
-    let pubkey_from_pop = &mut bls12381::public_key_from_bytes_with_pop(
-        consensus_pubkey,
-        &proof_of_possession_from_bytes(proof_of_possession)
-    );
-    assert!(option::is_some(pubkey_from_pop), error::invalid_argument(EINVALID_PUBLIC_KEY));
-
     initialize_owner(account);
     move_to(account, ValidatorConfig {
         consensus_pubkey,
@@ -2417,7 +2409,7 @@ Move amount of coins from pending_inactive to active.
 
 
 
-
fun rotate_consensus_key_internal(operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>, proof_of_possession: vector<u8>, genesis: bool)
+
fun rotate_consensus_key_internal(operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>, genesis: bool)
 
@@ -2430,7 +2422,6 @@ Move amount of coins from pending_inactive to active. operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>, - proof_of_possession: vector<u8>, genesis: bool, ) acquires StakePool, ValidatorConfig { assert_stake_pool_exists(pool_address); @@ -2441,16 +2432,6 @@ Move amount of coins from pending_inactive to active. let validator_info = borrow_global_mut<ValidatorConfig>(pool_address); let old_consensus_pubkey = validator_info.consensus_pubkey; // Checks the public key has a valid proof-of-possession to prevent rogue-key attacks. - if (!genesis) { - let pubkey_from_pop = &mut bls12381::public_key_from_bytes_with_pop( - new_consensus_pubkey, - &proof_of_possession_from_bytes(proof_of_possession) - ); - assert!(option::is_some(pubkey_from_pop), error::invalid_argument(EINVALID_PUBLIC_KEY)); - } else { - let pubkey = &mut bls12381::public_key_from_bytes(new_consensus_pubkey); - assert!(option::is_some(pubkey), error::invalid_argument(EINVALID_PUBLIC_KEY)); - }; validator_info.consensus_pubkey = new_consensus_pubkey; event::emit_event( @@ -2477,7 +2458,7 @@ does not verify proof of possession only for genesis -
public(friend) fun rotate_consensus_key_genesis(operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>, proof_of_poseesion: vector<u8>)
+
public(friend) fun rotate_consensus_key_genesis(operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>)
 
@@ -2490,9 +2471,8 @@ only for genesis operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>, - proof_of_poseesion: vector<u8>, ) acquires StakePool, ValidatorConfig { - rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, proof_of_poseesion, true); + rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, true); }
@@ -2507,7 +2487,7 @@ only for genesis Rotate the consensus key of the validator, it'll take effect in next epoch. -
public entry fun rotate_consensus_key(operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>, proof_of_possession: vector<u8>)
+
public entry fun rotate_consensus_key(operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>)
 
@@ -2520,9 +2500,8 @@ Rotate the consensus key of the validator, it'll take effect in next epoch. operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>, - proof_of_possession: vector<u8>, ) acquires StakePool, ValidatorConfig { - rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, proof_of_possession, false); + rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, false); }
@@ -3982,17 +3961,16 @@ Returns validator's next epoch voting power, including pending_active, active, a ### Function `initialize_validator` -
public entry fun initialize_validator(account: &signer, consensus_pubkey: vector<u8>, proof_of_possession: vector<u8>, network_addresses: vector<u8>, fullnode_addresses: vector<u8>)
+
public entry fun initialize_validator(account: &signer, consensus_pubkey: vector<u8>, network_addresses: vector<u8>, fullnode_addresses: vector<u8>)
 
-
let pubkey_from_pop = bls12381::spec_public_key_from_bytes_with_pop(
+
let pubkey_from_pop = ed25519::spec_public_key_validate_internal(
     consensus_pubkey,
-    proof_of_possession_from_bytes(proof_of_possession)
 );
-aborts_if !option::spec_is_some(pubkey_from_pop);
+aborts_if !pubkey_from_pop;
 let addr = signer::address_of(account);
 let post_addr = signer::address_of(account);
 let allowed = global<AllowedValidators>(@aptos_framework);
@@ -4157,7 +4135,7 @@ Returns validator's next epoch voting power, including pending_active, active, a
 ### Function `rotate_consensus_key`
 
 
-
public entry fun rotate_consensus_key(operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>, proof_of_possession: vector<u8>)
+
public entry fun rotate_consensus_key(operator: &signer, pool_address: address, new_consensus_pubkey: vector<u8>)
 
@@ -4168,11 +4146,10 @@ Returns validator's next epoch voting power, including pending_active, active, a aborts_if !exists<StakePool>(pool_address); aborts_if signer::address_of(operator) != pre_stake_pool.operator_address; aborts_if !exists<ValidatorConfig>(pool_address); -let pubkey_from_pop = bls12381::spec_public_key_from_bytes_with_pop( +let pubkey_from_pop = ed25519::spec_public_key_validate_internal( new_consensus_pubkey, - proof_of_possession_from_bytes(proof_of_possession) ); -aborts_if !option::spec_is_some(pubkey_from_pop); +aborts_if !pubkey_from_pop; modifies global<ValidatorConfig>(pool_address); include StakedValueNochange; ensures validator_info.consensus_pubkey == new_consensus_pubkey; @@ -4922,74 +4899,4 @@ Returns validator's next epoch voting power, including pending_active, active, a
- - - - - -
schema ResourceRequirement {
-    requires exists<AptosCoinCapabilities>(@aptos_framework);
-    requires exists<ValidatorPerformance>(@aptos_framework);
-    requires exists<ValidatorSet>(@aptos_framework);
-    requires exists<StakingConfig>(@aptos_framework);
-    requires exists<StakingRewardsConfig>(@aptos_framework) || !features::spec_periodical_reward_rate_decrease_enabled();
-    requires exists<timestamp::CurrentTimeMicroseconds>(@aptos_framework);
-    requires exists<ValidatorFees>(@aptos_framework);
-}
-
- - - - - - - -
fun spec_get_reward_rate_1(config: StakingConfig): num {
-   if (features::spec_periodical_reward_rate_decrease_enabled()) {
-       let epoch_rewards_rate = global<staking_config::StakingRewardsConfig>(@aptos_framework).rewards_rate;
-       if (epoch_rewards_rate.value == 0) {
-           0
-       } else {
-           let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate);
-           let denominator = if (denominator_0 > MAX_U64) {
-               MAX_U64
-           } else {
-               denominator_0
-           };
-           let nominator = aptos_std::fixed_point64::spec_multiply_u128(denominator, epoch_rewards_rate);
-           nominator
-       }
-   } else {
-           config.rewards_rate
-   }
-}
-
- - - - - - - -
fun spec_get_reward_rate_2(config: StakingConfig): num {
-   if (features::spec_periodical_reward_rate_decrease_enabled()) {
-       let epoch_rewards_rate = global<staking_config::StakingRewardsConfig>(@aptos_framework).rewards_rate;
-       if (epoch_rewards_rate.value == 0) {
-           1
-       } else {
-           let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate);
-           let denominator = if (denominator_0 > MAX_U64) {
-               MAX_U64
-           } else {
-               denominator_0
-           };
-           denominator
-       }
-   } else {
-           config.rewards_rate_denominator
-   }
-}
-
- - [move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/aptos-framework/sources/genesis.move b/aptos-move/framework/aptos-framework/sources/genesis.move index 58c6e01c7d89e5..8cf494eb372952 100644 --- a/aptos-move/framework/aptos-framework/sources/genesis.move +++ b/aptos-move/framework/aptos-framework/sources/genesis.move @@ -365,7 +365,6 @@ module aptos_framework::genesis { operator, pool_address, validator.consensus_pubkey, - validator.proof_of_possession, ); stake::update_network_and_fullnode_addresses( operator, diff --git a/aptos-move/framework/aptos-framework/sources/stake.move b/aptos-move/framework/aptos-framework/sources/stake.move index 1df14c8d29635a..fd14dd339169d2 100644 --- a/aptos-move/framework/aptos-framework/sources/stake.move +++ b/aptos-move/framework/aptos-framework/sources/stake.move @@ -23,7 +23,7 @@ module aptos_framework::stake { use std::option::{Self, Option}; use std::signer; use std::vector; - use aptos_std::bls12381; + use aptos_std::ed25519; use aptos_std::math64::min; use aptos_std::table::{Self, Table}; use aptos_framework::aptos_coin::AptosCoin; @@ -494,17 +494,10 @@ module aptos_framework::stake { public entry fun initialize_validator( account: &signer, consensus_pubkey: vector, - proof_of_possession: vector, network_addresses: vector, fullnode_addresses: vector, ) acquires AllowedValidators { // Checks the public key has a valid proof-of-possession to prevent rogue-key attacks. - let pubkey_from_pop = &mut bls12381::public_key_from_bytes_with_pop( - consensus_pubkey, - &proof_of_possession_from_bytes(proof_of_possession) - ); - assert!(option::is_some(pubkey_from_pop), error::invalid_argument(EINVALID_PUBLIC_KEY)); - initialize_owner(account); move_to(account, ValidatorConfig { consensus_pubkey, @@ -693,7 +686,6 @@ module aptos_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, - proof_of_possession: vector, genesis: bool, ) acquires StakePool, ValidatorConfig { assert_stake_pool_exists(pool_address); @@ -704,16 +696,6 @@ module aptos_framework::stake { let validator_info = borrow_global_mut(pool_address); let old_consensus_pubkey = validator_info.consensus_pubkey; // Checks the public key has a valid proof-of-possession to prevent rogue-key attacks. - if (!genesis) { - let pubkey_from_pop = &mut bls12381::public_key_from_bytes_with_pop( - new_consensus_pubkey, - &proof_of_possession_from_bytes(proof_of_possession) - ); - assert!(option::is_some(pubkey_from_pop), error::invalid_argument(EINVALID_PUBLIC_KEY)); - } else { - let pubkey = &mut bls12381::public_key_from_bytes(new_consensus_pubkey); - assert!(option::is_some(pubkey), error::invalid_argument(EINVALID_PUBLIC_KEY)); - }; validator_info.consensus_pubkey = new_consensus_pubkey; event::emit_event( @@ -733,9 +715,8 @@ module aptos_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, - proof_of_poseesion: vector, ) acquires StakePool, ValidatorConfig { - rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, proof_of_poseesion, true); + rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, true); } /// Rotate the consensus key of the validator, it'll take effect in next epoch. @@ -743,9 +724,8 @@ module aptos_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, - proof_of_possession: vector, ) acquires StakePool, ValidatorConfig { - rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, proof_of_possession, false); + rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, false); } /// Update the network and full node addresses of the validator. This only takes effect in the next epoch. @@ -1388,7 +1368,6 @@ module aptos_framework::stake { #[test_only] use aptos_framework::aptos_coin; - use aptos_std::bls12381::proof_of_possession_from_bytes; #[test_only] use aptos_std::fixed_point64; @@ -1405,15 +1384,13 @@ module aptos_framework::stake { #[test_only] public fun join_validator_set_for_test( - pk: &bls12381::PublicKey, - pop: &bls12381::ProofOfPossession, + pk: &ed25519::ValidatedPublicKey, operator: &signer, pool_address: address, should_end_epoch: bool, ) acquires AptosCoinCapabilities, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { - let pk_bytes = bls12381::public_key_to_bytes(pk); - let pop_bytes = bls12381::proof_of_possession_to_bytes(pop); - rotate_consensus_key(operator, pool_address, pk_bytes, pop_bytes); + let pk_bytes = ed25519::validated_public_key_to_bytes(pk); + rotate_consensus_key(operator, pool_address, pk_bytes); join_validator_set(operator, pool_address); if (should_end_epoch) { end_epoch(); @@ -1484,8 +1461,7 @@ module aptos_framework::stake { #[test_only] public fun initialize_test_validator( - public_key: &bls12381::PublicKey, - proof_of_possession: &bls12381::ProofOfPossession, + public_key: &ed25519::UnvalidatedPublicKey, validator: &signer, amount: u64, should_join_validator_set: bool, @@ -1496,9 +1472,8 @@ module aptos_framework::stake { account::create_account_for_test(validator_address); }; - let pk_bytes = bls12381::public_key_to_bytes(public_key); - let pop_bytes = bls12381::proof_of_possession_to_bytes(proof_of_possession); - initialize_validator(validator, pk_bytes, pop_bytes, vector::empty(), vector::empty()); + let pk_bytes = ed25519::unvalidated_public_key_to_bytes(public_key); + initialize_validator(validator, pk_bytes, vector::empty(), vector::empty()); if (amount > 0) { mint_and_add_stake(validator, amount); @@ -1516,7 +1491,7 @@ module aptos_framework::stake { public fun create_validator_set( aptos_framework: &signer, active_validator_addresses: vector
, - public_keys: vector, + public_keys: vector, ) { let active_validators = vector::empty(); let i = 0; @@ -1527,7 +1502,7 @@ module aptos_framework::stake { addr: *validator_address, voting_power: 0, config: ValidatorConfig { - consensus_pubkey: bls12381::public_key_to_bytes(pk), + consensus_pubkey: ed25519::validated_public_key_to_bytes(pk), network_addresses: b"", fullnode_addresses: b"", validator_index: 0, @@ -1574,11 +1549,10 @@ module aptos_framework::stake { } #[test_only] - public fun generate_identity(): (bls12381::SecretKey, bls12381::PublicKey, bls12381::ProofOfPossession) { - let (sk, pkpop) = bls12381::generate_keys(); - let pop = bls12381::generate_proof_of_possession(&sk); - let unvalidated_pk = bls12381::public_key_with_pop_to_normal(&pkpop); - (sk, unvalidated_pk, pop) + public fun generate_identity(): (ed25519::SecretKey, ed25519::UnvalidatedPublicKey) { + let (sk, pkpop) = ed25519::generate_keys(); + let unvalidated_pk = ed25519::public_key_to_unvalidated(&pkpop); + (sk, unvalidated_pk) } #[test(aptos_framework = @aptos_framework, validator = @0x123)] @@ -1588,8 +1562,8 @@ module aptos_framework::stake { validator: &signer, ) acquires AllowedValidators, AptosCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(aptos_framework); - let (_sk, pk, pop) = generate_identity(); - initialize_test_validator(&pk, &pop, validator, 100, false, false); + let (_sk, pk) = generate_identity(); + initialize_test_validator(&pk, validator, 100, false, false); // Add more stake to exceed max. This should fail. mint_and_add_stake(validator, 9901); diff --git a/aptos-move/framework/aptos-framework/sources/stake.spec.move b/aptos-move/framework/aptos-framework/sources/stake.spec.move index 64e229f81bd227..9018ea92127898 100644 --- a/aptos-move/framework/aptos-framework/sources/stake.spec.move +++ b/aptos-move/framework/aptos-framework/sources/stake.spec.move @@ -104,15 +104,13 @@ spec aptos_framework::stake { spec initialize_validator( account: &signer, consensus_pubkey: vector, - proof_of_possession: vector, network_addresses: vector, fullnode_addresses: vector, ){ - let pubkey_from_pop = bls12381::spec_public_key_from_bytes_with_pop( + let pubkey_from_pop = ed25519::spec_public_key_validate_internal( consensus_pubkey, - proof_of_possession_from_bytes(proof_of_possession) ); - aborts_if !option::spec_is_some(pubkey_from_pop); + aborts_if !pubkey_from_pop; let addr = signer::address_of(account); let post_addr = signer::address_of(account); let allowed = global(@aptos_framework); @@ -357,18 +355,16 @@ spec aptos_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, - proof_of_possession: vector, ) { let pre_stake_pool = global(pool_address); let post validator_info = global(pool_address); aborts_if !exists(pool_address); aborts_if signer::address_of(operator) != pre_stake_pool.operator_address; aborts_if !exists(pool_address); - let pubkey_from_pop = bls12381::spec_public_key_from_bytes_with_pop( + let pubkey_from_pop = ed25519::spec_public_key_validate_internal( new_consensus_pubkey, - proof_of_possession_from_bytes(proof_of_possession) ); - aborts_if !option::spec_is_some(pubkey_from_pop); + aborts_if !pubkey_from_pop; modifies global(pool_address); include StakedValueNochange; diff --git a/aptos-move/framework/aptos-stdlib/doc/ed25519.md b/aptos-move/framework/aptos-stdlib/doc/ed25519.md index ed3bb72bd34fec..68fe0b4704df36 100644 --- a/aptos-move/framework/aptos-stdlib/doc/ed25519.md +++ b/aptos-move/framework/aptos-stdlib/doc/ed25519.md @@ -175,32 +175,32 @@ A purported Ed25519 signature that can be verified via signature_verify_st ## Constants - + -The size of a serialized public key, in bytes. +Wrong number of bytes were given as input when deserializing an Ed25519 public key. -
const PUBLIC_KEY_NUM_BYTES: u64 = 32;
+
const E_WRONG_PUBKEY_SIZE: u64 = 1;
 
- + -Wrong number of bytes were given as input when deserializing an Ed25519 public key. +Wrong number of bytes were given as input when deserializing an Ed25519 signature. -
const E_WRONG_PUBKEY_SIZE: u64 = 1;
+
const E_WRONG_SIGNATURE_SIZE: u64 = 2;
 
- + -Wrong number of bytes were given as input when deserializing an Ed25519 signature. +The size of a serialized public key, in bytes. -
const E_WRONG_SIGNATURE_SIZE: u64 = 2;
+
const PUBLIC_KEY_NUM_BYTES: u64 = 32;
 
diff --git a/aptos-move/framework/aptos-stdlib/doc/overview.md b/aptos-move/framework/aptos-stdlib/doc/overview.md index 6176385db1d977..25ff7563d13dca 100644 --- a/aptos-move/framework/aptos-stdlib/doc/overview.md +++ b/aptos-move/framework/aptos-stdlib/doc/overview.md @@ -15,8 +15,6 @@ This is the reference documentation of the Aptos standard library. - [`0x1::any`](any.md#0x1_any) - [`0x1::aptos_hash`](hash.md#0x1_aptos_hash) - [`0x1::big_vector`](big_vector.md#0x1_big_vector) -- [`0x1::bls12381`](bls12381.md#0x1_bls12381) -- [`0x1::bls12381_algebra`](bls12381_algebra.md#0x1_bls12381_algebra) - [`0x1::bn254_algebra`](bn254_algebra.md#0x1_bn254_algebra) - [`0x1::capability`](capability.md#0x1_capability) - [`0x1::comparator`](comparator.md#0x1_comparator) diff --git a/aptos-move/framework/aptos-stdlib/sources/cryptography/bls12381.move b/aptos-move/framework/aptos-stdlib/sources/cryptography/bls12381.move deleted file mode 100644 index de7d05ad8b18b7..00000000000000 --- a/aptos-move/framework/aptos-stdlib/sources/cryptography/bls12381.move +++ /dev/null @@ -1,985 +0,0 @@ -/// Contains functions for: -/// -/// The minimum-pubkey-size variant of [Boneh-Lynn-Shacham (BLS) signatures](https://en.wikipedia.org/wiki/BLS_digital_signature), -/// where public keys are BLS12-381 elliptic-curve points in $\mathbb{G}_1$ and signatures are in $\mathbb{G}_2$, -/// as per the [IETF BLS draft standard](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature#section-2.1). - -module aptos_std::bls12381 { - use std::option::{Self, Option}; - #[test_only] - use std::error::invalid_argument; - - /// The signature size, in bytes - const SIGNATURE_SIZE: u64 = 96; - - /// The public key size, in bytes - const PUBLIC_KEY_NUM_BYTES: u64 = 48; - - /// The caller was supposed to input one or more public keys. - const EZERO_PUBKEYS: u64 = 1; - - /// One of the given inputs has the wrong size.s - const EWRONG_SIZE: u64 = 2; - - /// The number of signers does not match the number of messages to be signed. - const E_NUM_SIGNERS_MUST_EQ_NUM_MESSAGES: u64 = 3; - - // TODO: Performance would increase if structs in this module are implemented natively via handles (similar to Table and - // RistrettoPoint). This will avoid unnecessary (de)serialization. We would need to allow storage of these structs too. - - #[test_only] - struct SecretKey has copy, drop { - bytes: vector, - } - - /// A *validated* public key that: - /// (1) is a point in the prime-order subgroup of the BLS12-381 elliptic curve, and - /// (2) is not the identity point - /// - /// This struct can be used to verify a normal (non-aggregated) signature. - /// - /// This struct can be combined with a ProofOfPossession struct in order to create a PublicKeyWithPop struct, which - /// can be used to verify a multisignature. - struct PublicKey has copy, drop, store { - bytes: vector - } - - /// A proof-of-possession (PoP). - /// Given such a struct and a PublicKey struct, one can construct a PublicKeyWithPoP (see below). - struct ProofOfPossession has copy, drop, store { - bytes: vector - } - - /// A *validated* public key that had a successfully-verified proof-of-possession (PoP). - /// - /// A vector of these structs can be either: - /// (1) used to verify an aggregate signature - /// (2) aggregated with other PublicKeyWithPoP structs into an AggrPublicKeysWithPoP, which in turn can be used - /// to verify a multisignature - struct PublicKeyWithPoP has copy, drop, store { - bytes: vector - } - - /// An aggregation of public keys with verified PoPs, which can be used to verify multisignatures. - struct AggrPublicKeysWithPoP has copy, drop, store { - bytes: vector - } - - /// A BLS signature. This can be either a: - /// (1) normal (non-aggregated) signature - /// (2) signature share (for a multisignature or aggregate signature) - struct Signature has copy, drop, store { - bytes: vector - } - - /// An aggregation of BLS signatures. This can be either a: - /// (4) aggregated signature (i.e., an aggregation of signatures s_i, each on a message m_i) - /// (3) multisignature (i.e., an aggregation of signatures s_i, each on the same message m) - /// - /// We distinguish between a Signature type and a AggrOrMultiSignature type to prevent developers from interchangeably - /// calling `verify_multisignature` and `verify_signature_share` to verify both multisignatures and signature shares, - /// which could create problems down the line. - struct AggrOrMultiSignature has copy, drop, store { - bytes: vector - } - - /// Creates a new public key from a sequence of bytes. - public fun public_key_from_bytes(bytes: vector): Option { - if (validate_pubkey_internal(bytes)) { - option::some(PublicKey { - bytes - }) - } else { - option::none() - } - } - - /// Serializes a public key into 48 bytes. - public fun public_key_to_bytes(pk: &PublicKey): vector { - pk.bytes - } - - /// Creates a new proof-of-possession (PoP) which can be later used to create a PublicKeyWithPoP struct, - public fun proof_of_possession_from_bytes(bytes: vector): ProofOfPossession { - ProofOfPossession { - bytes - } - } - - /// Serializes the signature into 96 bytes. - public fun proof_of_possession_to_bytes(pop: &ProofOfPossession): vector { - pop.bytes - } - - /// Creates a PoP'd public key from a normal public key and a corresponding proof-of-possession. - public fun public_key_from_bytes_with_pop(pk_bytes: vector, pop: &ProofOfPossession): Option { - if (verify_proof_of_possession_internal(pk_bytes, pop.bytes)) { - option::some(PublicKeyWithPoP { - bytes: pk_bytes - }) - } else { - option::none() - } - } - - /// Creates a normal public key from a PoP'd public key. - public fun public_key_with_pop_to_normal(pkpop: &PublicKeyWithPoP): PublicKey { - PublicKey { - bytes: pkpop.bytes - } - } - - /// Serializes a PoP'd public key into 48 bytes. - public fun public_key_with_pop_to_bytes(pk: &PublicKeyWithPoP): vector { - pk.bytes - } - - /// Creates a new signature from a sequence of bytes. Does not check the signature for prime-order subgroup - /// membership since that is done implicitly during verification. - public fun signature_from_bytes(bytes: vector): Signature { - Signature { - bytes - } - } - - /// Serializes the signature into 96 bytes. - public fun signature_to_bytes(sig: &Signature): vector { - sig.bytes - } - - /// Checks that the group element that defines a signature is in the prime-order subgroup. - /// This check is implicitly performed when verifying any signature via this module, but we expose this functionality - /// in case it might be useful for applications to easily dismiss invalid signatures early on. - public fun signature_subgroup_check(signature: &Signature): bool { - signature_subgroup_check_internal(signature.bytes) - } - - /// Given a vector of public keys with verified PoPs, combines them into an *aggregated* public key which can be used - /// to verify multisignatures using `verify_multisignature` and aggregate signatures using `verify_aggregate_signature`. - /// Aborts if no public keys are given as input. - public fun aggregate_pubkeys(public_keys: vector): AggrPublicKeysWithPoP { - let (bytes, success) = aggregate_pubkeys_internal(public_keys); - assert!(success, std::error::invalid_argument(EZERO_PUBKEYS)); - - AggrPublicKeysWithPoP { - bytes - } - } - - /// Serializes an aggregate public key into 48 bytes. - public fun aggregate_pubkey_to_bytes(apk: &AggrPublicKeysWithPoP): vector { - apk.bytes - } - - /// Aggregates the input signatures into an aggregate-or-multi-signature structure, which can be later verified via - /// `verify_aggregate_signature` or `verify_multisignature`. Returns `None` if zero signatures are given as input - /// or if some of the signatures are not valid group elements. - public fun aggregate_signatures(signatures: vector): Option { - let (bytes, success) = aggregate_signatures_internal(signatures); - if (success) { - option::some( - AggrOrMultiSignature { - bytes - } - ) - } else { - option::none() - } - } - - /// Serializes an aggregate-or-multi-signature into 96 bytes. - public fun aggr_or_multi_signature_to_bytes(sig: &AggrOrMultiSignature): vector { - sig.bytes - } - - /// Deserializes an aggregate-or-multi-signature from 96 bytes. - public fun aggr_or_multi_signature_from_bytes(bytes: vector): AggrOrMultiSignature { - assert!(std::vector::length(&bytes) == SIGNATURE_SIZE, std::error::invalid_argument(EWRONG_SIZE)); - - AggrOrMultiSignature { - bytes - } - } - - - /// Checks that the group element that defines an aggregate-or-multi-signature is in the prime-order subgroup. - public fun aggr_or_multi_signature_subgroup_check(signature: &AggrOrMultiSignature): bool { - signature_subgroup_check_internal(signature.bytes) - } - - /// Verifies an aggregate signature, an aggregation of many signatures `s_i`, each on a different message `m_i`. - public fun verify_aggregate_signature( - aggr_sig: &AggrOrMultiSignature, - public_keys: vector, - messages: vector>, - ): bool { - verify_aggregate_signature_internal(aggr_sig.bytes, public_keys, messages) - } - - /// Verifies a multisignature: an aggregation of many signatures, each on the same message `m`. - public fun verify_multisignature( - multisig: &AggrOrMultiSignature, - aggr_public_key: &AggrPublicKeysWithPoP, - message: vector - ): bool { - verify_multisignature_internal(multisig.bytes, aggr_public_key.bytes, message) - } - - /// Verifies a normal, non-aggregated signature. - public fun verify_normal_signature( - signature: &Signature, - public_key: &PublicKey, - message: vector - ): bool { - verify_normal_signature_internal(signature.bytes, public_key.bytes, message) - } - - /// Verifies a signature share in the multisignature share or an aggregate signature share. - public fun verify_signature_share( - signature_share: &Signature, - public_key: &PublicKeyWithPoP, - message: vector - ): bool { - verify_signature_share_internal(signature_share.bytes, public_key.bytes, message) - } - - #[test_only] - /// Generates a BLS key-pair: a secret key with its corresponding public key. - public fun generate_keys(): (SecretKey, PublicKeyWithPoP) { - let (sk_bytes, pk_bytes) = generate_keys_internal(); - let sk = SecretKey { - bytes: sk_bytes - }; - let pkpop = PublicKeyWithPoP { - bytes: pk_bytes - }; - (sk, pkpop) - } - - #[test_only] - /// Generates a BLS signature for a message with a signing key. - public fun sign_arbitrary_bytes(signing_key: &SecretKey, message: vector): Signature { - Signature { - bytes: sign_internal(signing_key.bytes, message) - } - } - - #[test_only] - /// Generates a multi-signature for a message with multiple signing keys. - public fun multi_sign_arbitrary_bytes(signing_keys: &vector, message: vector): AggrOrMultiSignature { - let n = std::vector::length(signing_keys); - let sigs = vector[]; - let i: u64 = 0; - while (i < n) { - let sig = sign_arbitrary_bytes(std::vector::borrow(signing_keys, i), message); - std::vector::push_back(&mut sigs, sig); - i = i + 1; - }; - let multisig = aggregate_signatures(sigs); - option::extract(&mut multisig) - } - - #[test_only] - /// Generates an aggregated signature over all messages in messages, where signing_keys[i] signs messages[i]. - public fun aggr_sign_arbitrary_bytes(signing_keys: &vector, messages: &vector>): AggrOrMultiSignature { - let signing_key_count = std::vector::length(signing_keys); - let message_count = std::vector::length(messages); - assert!(signing_key_count == message_count, invalid_argument(E_NUM_SIGNERS_MUST_EQ_NUM_MESSAGES)); - let sigs = vector[]; - let i: u64 = 0; - while (i < signing_key_count) { - let sig = sign_arbitrary_bytes(std::vector::borrow(signing_keys, i), *std::vector::borrow(messages, i)); - std::vector::push_back(&mut sigs, sig); - i = i + 1; - }; - let aggr_sig = aggregate_signatures(sigs); - option::extract(&mut aggr_sig) - } - - #[test_only] - /// Returns a mauled copy of a byte array. - public fun maul_bytes(bytes: &vector): vector { - let new_bytes = *bytes; - let first_byte = std::vector::borrow_mut(&mut new_bytes, 0); - *first_byte = *first_byte ^ 0xff; - new_bytes - } - - #[test_only] - /// Returns a mauled copy of a normal signature. - public fun maul_signature(sig: &Signature): Signature { - Signature { - bytes: maul_bytes(&signature_to_bytes(sig)) - } - } - - #[test_only] - /// Returns a mauled copy of an aggregated signature or a multi-signature. - public fun maul_aggr_or_multi_signature(sig: &AggrOrMultiSignature): AggrOrMultiSignature { - AggrOrMultiSignature { - bytes: maul_bytes(&aggr_or_multi_signature_to_bytes(sig)) - } - } - - #[test_only] - /// Returns a mauled copy of a normal public key. - public fun maul_public_key(pk: &PublicKey): PublicKey { - PublicKey { - bytes: maul_bytes(&public_key_to_bytes(pk)) - } - } - - #[test_only] - /// Returns a mauled copy of a PoP'd public key. - public fun maul_public_key_with_pop(pk: &PublicKeyWithPoP): PublicKeyWithPoP { - PublicKeyWithPoP { - bytes: maul_bytes(&public_key_with_pop_to_bytes(pk)) - } - } - - #[test_only] - /// Returns a mauled copy of an aggregated public key. - public fun maul_aggregated_public_key(pk: &AggrPublicKeysWithPoP): AggrPublicKeysWithPoP { - AggrPublicKeysWithPoP { - bytes: maul_bytes(&aggregate_pubkey_to_bytes(pk)) - } - } - - #[test_only] - /// Returns a mauled copy of a proof-of-possession. - public fun maul_proof_of_possession(pop: &ProofOfPossession): ProofOfPossession { - ProofOfPossession { - bytes: maul_bytes(&proof_of_possession_to_bytes(pop)) - } - } - - - #[test_only] - /// Generates a proof-of-possession (PoP) for the public key associated with the secret key `sk`. - public fun generate_proof_of_possession(sk: &SecretKey): ProofOfPossession { - ProofOfPossession { - bytes: generate_proof_of_possession_internal(sk.bytes) - } - } - - // - // Native functions - // - - /// CRYPTOGRAPHY WARNING: This function assumes that the caller verified all public keys have a valid - /// proof-of-possesion (PoP) using `verify_proof_of_possession`. - /// - /// Given a vector of serialized public keys, combines them into an aggregated public key, returning `(bytes, true)`, - /// where `bytes` store the serialized public key. - /// Aborts if no public keys are given as input. - native fun aggregate_pubkeys_internal(public_keys: vector): (vector, bool); - - - /// CRYPTOGRAPHY WARNING: This function can be safely called without verifying that the input signatures are elements - /// of the prime-order subgroup of the BLS12-381 curve. - /// - /// Given a vector of serialized signatures, combines them into an aggregate signature, returning `(bytes, true)`, - /// where `bytes` store the serialized signature. - /// Does not check the input signatures nor the final aggregated signatures for prime-order subgroup membership. - /// Returns `(_, false)` if no signatures are given as input. - /// Does not abort. - native fun aggregate_signatures_internal(signatures: vector): (vector, bool); - - /// Return `true` if the bytes in `public_key` are a valid BLS12-381 public key: - /// (1) it is NOT the identity point, and - /// (2) it is a BLS12-381 elliptic curve point, and - /// (3) it is a prime-order point - /// Return `false` otherwise. - /// Does not abort. - native fun validate_pubkey_internal(public_key: vector): bool; - - /// Return `true` if the elliptic curve point serialized in `signature`: - /// (1) is NOT the identity point, and - /// (2) is a BLS12-381 elliptic curve point, and - /// (3) is a prime-order point - /// Return `false` otherwise. - /// Does not abort. - native fun signature_subgroup_check_internal(signature: vector): bool; - - /// CRYPTOGRAPHY WARNING: First, this function assumes all public keys have a valid proof-of-possesion (PoP). - /// This prevents both small-subgroup attacks and rogue-key attacks. Second, this function can be safely called - /// without verifying that the aggregate signature is in the prime-order subgroup of the BLS12-381 curve. - /// - /// Returns `true` if the aggregate signature `aggsig` on `messages` under `public_keys` verifies (where `messages[i]` - /// should be signed by `public_keys[i]`). - /// - /// Returns `false` if either: - /// - no public keys or messages are given as input, - /// - number of messages does not equal number of public keys - /// - `aggsig` (1) is the identity point, or (2) is NOT a BLS12-381 elliptic curve point, or (3) is NOT a - /// prime-order point - /// Does not abort. - native fun verify_aggregate_signature_internal( - aggsig: vector, - public_keys: vector, - messages: vector>, - ): bool; - - /// CRYPTOGRAPHY WARNING: This function assumes verified proofs-of-possesion (PoP) for the public keys used in - /// computing the aggregate public key. This prevents small-subgroup attacks and rogue-key attacks. - /// - /// Return `true` if the BLS `multisignature` on `message` verifies against the BLS aggregate public key `agg_public_key`. - /// Returns `false` otherwise. - /// Does not abort. - native fun verify_multisignature_internal( - multisignature: vector, - agg_public_key: vector, - message: vector - ): bool; - - /// CRYPTOGRAPHY WARNING: This function WILL check that the public key is a prime-order point, in order to prevent - /// library users from misusing the library by forgetting to validate public keys before giving them as arguments to - /// this function. - /// - /// Returns `true` if the `signature` on `message` verifies under `public key`. - /// Returns `false` otherwise. - /// Does not abort. - native fun verify_normal_signature_internal( - signature: vector, - public_key: vector, - message: vector - ): bool; - - /// Return `true` if the bytes in `public_key` are a valid bls12381 public key (as per `validate_pubkey`) - /// *and* this public key has a valid proof-of-possesion (PoP). - /// Return `false` otherwise. - /// Does not abort. - native fun verify_proof_of_possession_internal( - public_key: vector, - proof_of_possesion: vector - ): bool; - - /// CRYPTOGRAPHY WARNING: Assumes the public key has a valid proof-of-possesion (PoP). This prevents rogue-key - /// attacks later on during signature aggregation. - /// - /// Returns `true` if the `signature_share` on `message` verifies under `public key`. - /// Returns `false` otherwise, similar to `verify_multisignature`. - /// Does not abort. - native fun verify_signature_share_internal( - signature_share: vector, - public_key: vector, - message: vector - ): bool; - - #[test_only] - native fun generate_keys_internal(): (vector, vector); - - #[test_only] - native fun sign_internal(sk: vector, msg: vector): vector; - - #[test_only] - native fun generate_proof_of_possession_internal(sk: vector): vector; - - // - // Constants and helpers for tests - // - - /// Random signature generated by running `cargo test -- bls12381_sample_signature --nocapture --include-ignored` in `crates/aptos-crypto`. - /// The message signed is "Hello Aptos!" and the associated SK is 07416693b6b32c84abe45578728e2379f525729e5b94762435a31e65ecc728da. - const RANDOM_SIGNATURE: vector = x"a01a65854f987d3434149b7f08f70730e30b241984e8712bc2aca885d632aafced4c3f661209debb6b1c8601326623cc16ca2f6c9edc53b7b88b7435fb6b05ddece418d2c34dc6aca2f5a11a79e67774582c14084a01dcb7820e4cb4bad0ea8d"; - - /// Random signature generated by running `cargo test -- bls12381_sample_signature --nocapture --include-ignored` in `crates/aptos-crypto`. - /// The associated SK is 07416693b6b32c84abe45578728e2379f525729e5b94762435a31e65ecc728da. - const RANDOM_PK: vector = x"8a53e7ae5270e3e765cd8a4032c2e77c6f7e87a44ebb85bf28a4d7865565698f975346714262f9e47c6f3e0d5d951660"; - - // - // Tests - // - - #[test_only] - fun get_random_aggsig(): AggrOrMultiSignature { - assert!(signature_subgroup_check_internal(RANDOM_SIGNATURE), 1); - - AggrOrMultiSignature { bytes: RANDOM_SIGNATURE } - } - - #[test_only] - fun get_random_pk_with_pop(): PublicKeyWithPoP { - assert!(validate_pubkey_internal(RANDOM_PK), 1); - - PublicKeyWithPoP { - bytes: RANDOM_PK - } - } - - #[test] - fun test_pubkey_validation() { - // test low order points (in group for PK) - assert!(option::is_none(&public_key_from_bytes(x"ae3cd9403b69c20a0d455fd860e977fe6ee7140a7f091f26c860f2caccd3e0a7a7365798ac10df776675b3a67db8faa0")), 1); - assert!(option::is_none(&public_key_from_bytes(x"928d4862a40439a67fd76a9c7560e2ff159e770dcf688ff7b2dd165792541c88ee76c82eb77dd6e9e72c89cbf1a56a68")), 1); - assert!(option::is_some(&public_key_from_bytes(x"b3e4921277221e01ed71284be5e3045292b26c7f465a6fcdba53ee47edd39ec5160da3b229a73c75671024dcb36de091")), 1); - } - - #[test] - #[expected_failure(abort_code = 65537, location = Self)] - fun test_empty_pubkey_aggregation() { - // First, make sure if no inputs are given, the function returns None - // assert!(aggregate_pop_verified_pubkeys(vector::empty()) == option::none(), 1); - aggregate_pubkeys(std::vector::empty()); - } - - #[test] - fun test_pubkey_aggregation() { - // Second, try some test-cases generated by running the following command in `crates/aptos-crypto`: - // $ cargo test -- sample_aggregate_pk_and_multisig --nocapture --include-ignored - let pks = vector[ - PublicKeyWithPoP { bytes: x"92e201a806af246f805f460fbdc6fc90dd16a18d6accc236e85d3578671d6f6690dde22134d19596c58ce9d63252410a" }, - PublicKeyWithPoP { bytes: x"ab9df801c6f96ade1c0490c938c87d5bcc2e52ccb8768e1b5d14197c5e8bfa562783b96711b702dda411a1a9f08ebbfa" }, - PublicKeyWithPoP { bytes: x"b698c932cf7097d99c17bd6e9c9dc4eeba84278c621700a8f80ec726b1daa11e3ab55fc045b4dbadefbeef05c4182494" }, - PublicKeyWithPoP { bytes: x"934706a8b876d47a996d427e1526ce52c952d5ec0858d49cd262efb785b62b1972d06270b0a7adda1addc98433ad1843" }, - PublicKeyWithPoP { bytes: x"a4cd352daad3a0651c1998dfbaa7a748e08d248a54347544bfedd51a197e016bb6008e9b8e45a744e1a030cc3b27d2da" }, - ]; - - // agg_pks[i] = \sum_{j <= i} pk[j] - let agg_pks = vector[ - AggrPublicKeysWithPoP { bytes: x"92e201a806af246f805f460fbdc6fc90dd16a18d6accc236e85d3578671d6f6690dde22134d19596c58ce9d63252410a" }, - AggrPublicKeysWithPoP { bytes: x"b79ad47abb441d7eda9b220a626df2e4e4910738c5f777947f0213398ecafae044ec0c20d552d1348347e9abfcf3eca1" }, - AggrPublicKeysWithPoP { bytes: x"b5f5eb6153ab5388a1a76343d714e4a2dcf224c5d0722d1e8e90c6bcead05c573fffe986460bd4000645a655bf52bc60" }, - AggrPublicKeysWithPoP { bytes: x"b922006ec14c183572a8864c31dc6632dccffa9f9c86411796f8b1b5a93a2457762c8e2f5ef0a2303506c4bca9a4e0bf" }, - AggrPublicKeysWithPoP { bytes: x"b53df1cfee2168f59e5792e710bf22928dc0553e6531dae5c7656c0a66fc12cb82fbb04863938c953dc901a5a79cc0f3" }, - ]; - - let i = 0; - let accum_pk = std::vector::empty(); - while (i < std::vector::length(&pks)) { - std::vector::push_back(&mut accum_pk, *std::vector::borrow(&pks, i)); - - let apk = aggregate_pubkeys(accum_pk); - - // Make sure PKs were aggregated correctly - assert!(apk == *std::vector::borrow(&agg_pks, i), 1); - assert!(validate_pubkey_internal(apk.bytes), 1); - - i = i + 1; - }; - } - - #[test] - fun test_pubkey_validation_against_invalid_keys() { - let (_sk, pk) = generate_keys(); - let pk_bytes = public_key_with_pop_to_bytes(&pk); - assert!(option::is_some(&public_key_from_bytes(pk_bytes)), 1); - assert!(option::is_none(&public_key_from_bytes(maul_bytes(&pk_bytes))), 1); - } - - #[test] - fun test_signature_aggregation() { - // First, test empty aggregation - assert!(option::is_none(&mut aggregate_signatures(vector[])), 1); - - // Second, try some test-cases generated by running the following command in `crates/aptos-crypto`: - // $ cargo test -- sample_aggregate_sigs --nocapture --include-ignored - - // Signatures of each signer i - let sigs = vector[ - signature_from_bytes(x"a55ac2d64b4c1d141b15d876d3e54ad1eea07ee488e8287cce7cdf3eec551458ab5795ab196f8c112590346f7bc7c97e0053cd5be0f9bd74b93a87cd44458e98d125d6d5c6950ea5e62666beb34422ead79121f8cb0815dae41a986688d03eaf"), - signature_from_bytes(x"90a639a44491191c46379a843266c293de3a46197714ead2ad3886233dd5c2b608b6437fa32fbf9d218b20f1cbfa7970182663beb9c148e2e9412b148e16abf283ffa51b8a536c0e55d61b2e5c849edc49f636c0ef07cb99f125cbcf602e22bb"), - signature_from_bytes(x"9527d81aa15863ef3a3bf96bea6d58157d5063a93a6d0eb9d8b4f4bbda3b31142ec4586cb519da2cd7600941283d1bad061b5439703fd584295b44037a969876962ae1897dcc7cadf909d06faae213c4fef8e015dfb33ec109af02ab0c3f6833"), - signature_from_bytes(x"a54d264f5cab9654b1744232c4650c42b29adf2b19bd00bbdaf4a4d792ee4dfd40a1fe1b067f298bcfd8ae4fdc8250660a2848bd4a80d96585afccec5c6cfa617033dd7913c9acfdf98a72467e8a5155d4cad589a72d6665be7cb410aebc0068"), - signature_from_bytes(x"8d22876bdf73e6ad36ed98546018f6258cd47e45904b87c071e774a6ef4b07cac323258cb920b2fe2b07cca1f2b24bcb0a3194ec76f32edb92391ed2c39e1ada8919f8ea755c5e39873d33ff3a8f4fba21b1261c1ddb9d1688c2b40b77e355d1"), - ]; - - // multisigs[i] is a signature on "Hello, Aptoverse!" from signers 1 through i (inclusive) - let multisigs = vector[ - AggrOrMultiSignature { bytes: x"a55ac2d64b4c1d141b15d876d3e54ad1eea07ee488e8287cce7cdf3eec551458ab5795ab196f8c112590346f7bc7c97e0053cd5be0f9bd74b93a87cd44458e98d125d6d5c6950ea5e62666beb34422ead79121f8cb0815dae41a986688d03eaf" }, - AggrOrMultiSignature { bytes: x"8f1949a06b95c3cb62898d861f889350c0d2cb740da513bfa195aa0ab8fa006ea2efe004a7bbbd9bb363637a279aed20132efd0846f520e7ee0e8ed847a1c6969bb986ad2239bcc9af561b6c2aa6d3016e1c722146471f1e28313de189fe7ebc" }, - AggrOrMultiSignature { bytes: x"ab5ad42bb8f350f8a6b4ae897946a05dbe8f2b22db4f6c37eff6ff737aebd6c5d75bd1abdfc99345ac8ec38b9a449700026f98647752e1c99f69bb132340f063b8a989728e0a3d82a753740bf63e5d8f51e413ebd9a36f6acbe1407a00c4b3e7" }, - AggrOrMultiSignature { bytes: x"ae307a0d055d3ba55ad6ec7094adef27ed821bdcf735fb509ab2c20b80952732394bc67ea1fd8c26ea963540df7448f8102509f7b8c694e4d75f30a43c455f251b6b3fd8b580b9228ffeeb9039834927aacefccd3069bef4b847180d036971cf" }, - AggrOrMultiSignature { bytes: x"8284e4e3983f29cb45020c3e2d89066df2eae533a01cb6ca2c4d466b5e02dd22467f59640aa120db2b9cc49e931415c3097e3d54ff977fd9067b5bc6cfa1c885d9d8821aef20c028999a1d97e783ae049d8fa3d0bbac36ce4ca8e10e551d3461" }, - ]; - - let i = 0; - let accum_sigs = std::vector::empty(); - while (i < std::vector::length(&sigs)) { - std::vector::push_back(&mut accum_sigs, *std::vector::borrow(&sigs, i)); - - let multisig = option::extract(&mut aggregate_signatures(accum_sigs)); - - // Make sure sigs were aggregated correctly - assert!(multisig == *std::vector::borrow(&multisigs, i), 1); - assert!(signature_subgroup_check_internal(multisig.bytes), 1); - - i = i + 1; - }; - } - - #[test] - fun test_empty_signature_aggregation() { - assert!(option::is_none(&mut aggregate_signatures(vector[])), 1); - } - - #[test] - fun test_verify_multisig() { - // Second, try some test-cases generated by running the following command in `crates/aptos-crypto`: - // $ cargo test -- sample_aggregate_pk_and_multisig --nocapture --include-ignored - let pks = vector[ - PublicKeyWithPoP { bytes: x"92e201a806af246f805f460fbdc6fc90dd16a18d6accc236e85d3578671d6f6690dde22134d19596c58ce9d63252410a" }, - PublicKeyWithPoP { bytes: x"ab9df801c6f96ade1c0490c938c87d5bcc2e52ccb8768e1b5d14197c5e8bfa562783b96711b702dda411a1a9f08ebbfa" }, - PublicKeyWithPoP { bytes: x"b698c932cf7097d99c17bd6e9c9dc4eeba84278c621700a8f80ec726b1daa11e3ab55fc045b4dbadefbeef05c4182494" }, - PublicKeyWithPoP { bytes: x"934706a8b876d47a996d427e1526ce52c952d5ec0858d49cd262efb785b62b1972d06270b0a7adda1addc98433ad1843" }, - PublicKeyWithPoP { bytes: x"a4cd352daad3a0651c1998dfbaa7a748e08d248a54347544bfedd51a197e016bb6008e9b8e45a744e1a030cc3b27d2da" }, - ]; - - // agg_pks[i] = \sum_{j <= i} pk[j] - let agg_pks = vector[ - AggrPublicKeysWithPoP { bytes: x"92e201a806af246f805f460fbdc6fc90dd16a18d6accc236e85d3578671d6f6690dde22134d19596c58ce9d63252410a" }, - AggrPublicKeysWithPoP { bytes: x"b79ad47abb441d7eda9b220a626df2e4e4910738c5f777947f0213398ecafae044ec0c20d552d1348347e9abfcf3eca1" }, - AggrPublicKeysWithPoP { bytes: x"b5f5eb6153ab5388a1a76343d714e4a2dcf224c5d0722d1e8e90c6bcead05c573fffe986460bd4000645a655bf52bc60" }, - AggrPublicKeysWithPoP { bytes: x"b922006ec14c183572a8864c31dc6632dccffa9f9c86411796f8b1b5a93a2457762c8e2f5ef0a2303506c4bca9a4e0bf" }, - AggrPublicKeysWithPoP { bytes: x"b53df1cfee2168f59e5792e710bf22928dc0553e6531dae5c7656c0a66fc12cb82fbb04863938c953dc901a5a79cc0f3" }, - ]; - - // multisigs[i] is a signature on "Hello, Aptoverse!" under agg_pks[i] - let multisigs = vector[ - AggrOrMultiSignature { bytes: x"ade45c67bff09ae57e0575feb0be870f2d351ce078e8033d847615099366da1299c69497027b77badb226ff1708543cd062597030c3f1553e0aef6c17e7af5dd0de63c1e4f1f9da68c966ea6c1dcade2cdc646bd5e8bcd4773931021ec5be3fd" }, - AggrOrMultiSignature { bytes: x"964af3d83436f6a9a382f34590c0c14e4454dc1de536af205319ce1ed417b87a2374863d5df7b7d5ed900cf91dffa7a105d3f308831d698c0d74fb2259d4813434fb86425db0ded664ae8f85d02ec1d31734910317d4155cbf69017735900d4d" }, - AggrOrMultiSignature { bytes: x"b523a31813e771e55aa0fc99a48db716ecc1085f9899ccadb64e759ecb481a2fb1cdcc0b266f036695f941361de773081729311f6a1bca9d47393f5359c8c87dc34a91f5dae335590aacbff974076ad1f910dd81750553a72ccbcad3c8cc0f07" }, - AggrOrMultiSignature { bytes: x"a945f61699df58617d37530a85e67bd1181349678b89293951ed29d1fb7588b5c12ebb7917dfc9d674f3f4fde4d062740b85a5f4927f5a4f0091e46e1ac6e41bbd650a74dd49e91445339d741e3b10bdeb9bc8bba46833e0011ff91fa5c77bd2" }, - AggrOrMultiSignature { bytes: x"b627b2cfd8ae59dcf5e58cc6c230ae369985fd096e1bc3be38da5deafcbed7d939f07cccc75383539940c56c6b6453db193f563f5b6e4fe54915afd9e1baea40a297fa7eda74abbdcd4cc5c667d6db3b9bd265782f7693798894400f2beb4637" }, - ]; - - let i = 0; - let accum_pk = std::vector::empty(); - while (i < std::vector::length(&pks)) { - std::vector::push_back(&mut accum_pk, *std::vector::borrow(&pks, i)); - - let apk = aggregate_pubkeys(accum_pk); - - assert!(apk == *std::vector::borrow(&agg_pks, i), 1); - - assert!(verify_multisignature(std::vector::borrow(&multisigs, i), &apk, b"Hello, Aptoverse!"), 1); - - i = i + 1; - }; - } - - #[test] - fun test_verify_multisignature_randomized() { - let signer_count = 1; - let max_signer_count = 5; - let msg = b"hello world"; - while (signer_count <= max_signer_count) { - // Generate key pairs. - let signing_keys = vector[]; - let public_keys = vector[]; - let i = 0; - while (i < signer_count) { - let (sk, pk) = generate_keys(); - std::vector::push_back(&mut signing_keys, sk); - std::vector::push_back(&mut public_keys, pk); - i = i + 1; - }; - - // Generate multi-signature. - let aggr_pk = aggregate_pubkeys(public_keys); - let multisig = multi_sign_arbitrary_bytes(&signing_keys, msg); - - // Test signature verification. - assert!(verify_multisignature(&multisig, &aggr_pk, msg), 1); - assert!(!verify_multisignature(&maul_aggr_or_multi_signature(&multisig), &aggr_pk, msg), 1); - assert!(!verify_multisignature(&multisig, &maul_aggregated_public_key(&aggr_pk), msg), 1); - assert!(!verify_multisignature(&multisig, &aggr_pk, maul_bytes(&msg)), 1); - - // Also test signature aggregation. - let signatures = vector[]; - let i = 0; - while (i < signer_count) { - let sk = std::vector::borrow(&signing_keys, i); - let sig = sign_arbitrary_bytes(sk, msg); - std::vector::push_back(&mut signatures, sig); - i = i + 1; - }; - let aggregated_signature = option::extract(&mut aggregate_signatures(signatures)); - assert!(aggr_or_multi_signature_subgroup_check(&aggregated_signature), 1); - assert!(aggr_or_multi_signature_to_bytes(&aggregated_signature) == aggr_or_multi_signature_to_bytes(&multisig), 1); - - signer_count = signer_count + 1; - } - } - - #[test] - fun test_verify_aggsig() { - assert!(aggr_or_multi_signature_to_bytes(&aggr_or_multi_signature_from_bytes(RANDOM_SIGNATURE)) == RANDOM_SIGNATURE, 1); - - // First, make sure verification returns None when no inputs are given or |pks| != |msgs| - assert!(verify_aggregate_signature(&get_random_aggsig(), vector[], vector[]) == false, 1); - - assert!(verify_aggregate_signature( - &get_random_aggsig(), - vector[ get_random_pk_with_pop() ], - vector[]) == false, 1); - - assert!(verify_aggregate_signature( - &get_random_aggsig(), - vector[], - vector[ x"ab" ]) == false, 1); - - assert!(verify_aggregate_signature( - &get_random_aggsig(), - vector[ get_random_pk_with_pop() ], - vector[ - x"cd", x"ef" - ]) == false, 1); - - assert!(verify_aggregate_signature( - &get_random_aggsig(), - vector[ - get_random_pk_with_pop(), - get_random_pk_with_pop(), - get_random_pk_with_pop(), - ], - vector[ - x"cd", x"ef" - ]) == false, 1); - - // Second, try some test-cases generated by running the following command in `crates/aptos-crypto`: - // $ cargo test -- bls12381_sample_aggregate_pk_and_aggsig --nocapture --ignored - - // The signed messages are "Hello, Aptos !", where \in {1, ..., 5} - let msgs = vector[ - x"48656c6c6f2c204170746f73203121", - x"48656c6c6f2c204170746f73203221", - x"48656c6c6f2c204170746f73203321", - x"48656c6c6f2c204170746f73203421", - x"48656c6c6f2c204170746f73203521", - ]; - - // Public key of signer i - let pks = vector[ - PublicKeyWithPoP { bytes: x"b93d6aabb2b83e52f4b8bda43c24ea920bbced87a03ffc80f8f70c814a8b3f5d69fbb4e579ca76ee008d61365747dbc6" }, - PublicKeyWithPoP { bytes: x"b45648ceae3a983bcb816a96db599b5aef3b688c5753fa20ce36ac7a4f2c9ed792ab20af6604e85e42dab746398bb82c" }, - PublicKeyWithPoP { bytes: x"b3e4921277221e01ed71284be5e3045292b26c7f465a6fcdba53ee47edd39ec5160da3b229a73c75671024dcb36de091" }, - PublicKeyWithPoP { bytes: x"8463b8671c9775a7dbd98bf76d3deba90b5a90535fc87dc8c13506bb5c7bbd99be4d257e60c548140e1e30b107ff5822" }, - PublicKeyWithPoP { bytes: x"a79e3d0e9d04587a3b27d05efe5717da05fd93485dc47978c866dc70a01695c2efd247d1dd843a011a4b6b24079d7384" }, - ]; - - // aggsigs[i] = \sum_{j <= i} sigs[j], where sigs[j] is a signature on msgs[j] under pks[j] - let aggsigs = vector[ - AggrOrMultiSignature { bytes: x"a2bc8bdebe6215ba74b5b53c5ed2aa0c68221a4adf868989ccdcfb62bb0eecc6537def9ee686a7960169c5917d25e5220177ed1c5e95ecfd68c09694062e76efcb00759beac874e4f9a715fd144210883bf9bb272f156b0a1fa15d0e9460f01f" }, - AggrOrMultiSignature { bytes: x"a523aa3c3f1f1074d968ffecf017c7b93ae5243006bf0abd2e45c036ddbec99302984b650ebe5ba306cda4071d281ba50a99ef0e66c3957fab94163296f9d673fc58a36de4276f82bfb1d9180b591df93b5c2804d40dd68cf0f72cd92f86442e" }, - AggrOrMultiSignature { bytes: x"abed10f464de74769121fc09715e59a3ac96a5054a43a9d43cc890a2d4d332614c74c7fb4cceef6d25f85c65dee337330f062f89f23fec9ecf7ce3193fbba2c886630d753be6a4513a4634428904b767af2f230c5cadbcb53a451dd9c7d977f6" }, - AggrOrMultiSignature { bytes: x"8362871631ba822742a31209fa4abce6dc94b741ac4725995459da2951324b51efbbf6bc3ab4681e547ebfbadd80e0360dc078c04188198f0acea26c12645ace9107a4a23cf8db46abc7a402637f16a0477c72569fc9966fe804ef4dc0e5e758" }, - AggrOrMultiSignature { bytes: x"a44d967935fbe63a763ce2dd2b16981f967ecd31e20d3266eef5517530cdc233c8a18273b6d9fd7f61dd39178826e3f115df4e7b304f2de17373a95ea0c9a14293dcfd6f0ef416e06fa23f6a3c850d638e4d8f97ab4562ef55d49a96a50baa13" }, - ]; - - let i = 0; - let msg_subset = std::vector::empty>(); - let pk_subset = std::vector::empty(); - while (i < std::vector::length(&pks)) { - let aggsig = *std::vector::borrow(&aggsigs, i); - - std::vector::push_back(&mut pk_subset, *std::vector::borrow(&pks, i)); - std::vector::push_back(&mut msg_subset, *std::vector::borrow(&msgs, i)); - - assert!(verify_aggregate_signature(&aggsig, pk_subset, msg_subset), 1); - - i = i + 1; - }; - } - - #[test] - fun test_verify_aggregated_signature_randomized() { - let signer_count = 1; - let max_signer_count = 5; - while (signer_count <= max_signer_count) { - // Generate key pairs and messages. - let signing_keys = vector[]; - let public_keys = vector[]; - let messages: vector> = vector[]; - let i = 0; - while (i < signer_count) { - let (sk, pk) = generate_keys(); - std::vector::push_back(&mut signing_keys, sk); - std::vector::push_back(&mut public_keys, pk); - let msg: vector = vector[104, 101, 108, 108, 111, 32, 97, 112, 116, 111, 115, 32, 117, 115, 101, 114, 32, 48+(i as u8)]; //"hello aptos user {i}" - std::vector::push_back(&mut messages, msg); - i = i + 1; - }; - - // Maul messages and public keys. - let mauled_public_keys = vector[maul_public_key_with_pop(std::vector::borrow(&public_keys, 0))]; - let mauled_messages = vector[maul_bytes(std::vector::borrow(&messages, 0))]; - let i = 1; - while (i < signer_count) { - let pk = std::vector::borrow(&public_keys, i); - let msg = std::vector::borrow(&messages, i); - std::vector::push_back(&mut mauled_public_keys, *pk); - std::vector::push_back(&mut mauled_messages, *msg); - i = i + 1; - }; - - // Generate aggregated signature. - let aggrsig = aggr_sign_arbitrary_bytes(&signing_keys, &messages); - - // Test signature verification. - assert!(verify_aggregate_signature(&aggrsig, public_keys, messages), 1); - assert!(!verify_aggregate_signature(&maul_aggr_or_multi_signature(&aggrsig), public_keys, messages), 1); - assert!(!verify_aggregate_signature(&aggrsig, mauled_public_keys, messages), 1); - assert!(!verify_aggregate_signature(&aggrsig, public_keys, mauled_messages), 1); - - // Also test signature aggregation. - let signatures = vector[]; - let i = 0; - while (i < signer_count) { - let sk = std::vector::borrow(&signing_keys, i); - let msg = std::vector::borrow(&messages, i); - let sig = sign_arbitrary_bytes(sk, *msg); - std::vector::push_back(&mut signatures, sig); - i = i + 1; - }; - let aggrsig_another = option::extract(&mut aggregate_signatures(signatures)); - assert!(aggr_or_multi_signature_to_bytes(&aggrsig_another) == aggr_or_multi_signature_to_bytes(&aggrsig), 1); - - signer_count = signer_count + 1; - } - } - - #[test] - /// Tests verification of a random BLS signature created using sk = x"" - fun test_verify_normal_and_verify_sigshare() { - // Test case generated by running `cargo test -- bls12381_sample_signature --nocapture --include-ignored` in - // `crates/aptos-crypto` - // ============================================================================================================= - // SK: 077c8a56f26259215a4a245373ab6ddf328ac6e00e5ea38d8700efa361bdc58d - - let message = b"Hello Aptos!"; - - // First, test signatures that verify - let ok = verify_normal_signature( - &signature_from_bytes(x"b01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7"), - &option::extract(&mut public_key_from_bytes(x"94209a296b739577cb076d3bfb1ca8ee936f29b69b7dae436118c4dd1cc26fd43dcd16249476a006b8b949bf022a7858")), - message, - ); - assert!(ok == true, 1); - - let pk = option::extract(&mut public_key_from_bytes(x"94209a296b739577cb076d3bfb1ca8ee936f29b69b7dae436118c4dd1cc26fd43dcd16249476a006b8b949bf022a7858")); - let pk_with_pop = PublicKeyWithPoP { bytes: pk.bytes }; - - let ok = verify_signature_share( - &signature_from_bytes(x"b01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7"), - &pk_with_pop, - message, - ); - assert!(ok == true, 1); - - // Second, test signatures that do NOT verify - let sigs = vector[ - Signature { bytes: x"a01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7" }, - Signature { bytes: x"b01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7" }, - Signature { bytes: x"b01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7" }, - ]; - let pks = vector[ - x"94209a296b739577cb076d3bfb1ca8ee936f29b69b7dae436118c4dd1cc26fd43dcd16249476a006b8b949bf022a7858", - x"ae4851bb9e7782027437ed0e2c026dd63b77a972ddf4bd9f72bcc218e327986568317e3aa9f679c697a2cb7cebf992f3", - x"82ed7bb5528303a2e306775040a7309e0bd597b70d9949d8c6198a01a7be0b00079320ebfeaf7bbd5bfe86809940d252", - ]; - let messages = vector[ - b"Hello Aptos!", - b"Hello Aptos!", - b"Bello Aptos!", - ]; - - let i = 0; - while (i < std::vector::length(&pks)) { - let sig = std::vector::borrow(&sigs, i); - let pk = *std::vector::borrow(&pks, i); - let msg = *std::vector::borrow(&messages, i); - - let pk = option::extract(&mut public_key_from_bytes(pk)); - - let notok = verify_normal_signature( - sig, - &pk, - msg, - ); - assert!(notok == false, 1); - - let notok = verify_signature_share( - sig, - &PublicKeyWithPoP { bytes: pk.bytes }, - msg, - ); - assert!(notok == false, 1); - - i = i + 1; - } - } - - #[test] - fun test_verify_normal_signature_or_signature_share_randomized() { - let (sk, pkpop) = generate_keys(); - let pk = public_key_with_pop_to_normal(&pkpop); - - let msg = b"hello world"; - let sig = sign_arbitrary_bytes(&sk, msg); - assert!(verify_normal_signature(&sig, &pk, msg), 1); - assert!(!verify_normal_signature(&maul_signature(&sig), &pk, msg), 1); - assert!(!verify_normal_signature(&sig, &maul_public_key(&pk), msg), 1); - assert!(!verify_normal_signature(&sig, &pk, maul_bytes(&msg)), 1); - - assert!(verify_signature_share(&sig, &pkpop, msg), 1); - assert!(!verify_signature_share(&maul_signature(&sig), &pkpop, msg), 1); - assert!(!verify_signature_share(&sig, &maul_public_key_with_pop(&pkpop), msg), 1); - assert!(!verify_signature_share(&sig, &pkpop, maul_bytes(&msg)), 1); - } - - #[test] - /// Tests verification of random BLS proofs-of-possession (PoPs) - fun test_verify_pop() { - // Test case generated by running `cargo test -- sample_pop --nocapture --include-ignored` in `crates/aptos-crypto` - // ============================================================================================================= - - let pks = vector[ - x"808864c91ae7a9998b3f5ee71f447840864e56d79838e4785ff5126c51480198df3d972e1e0348c6da80d396983e42d7", - x"8843843c76d167c02842a214c21277bad0bfd83da467cb5cf2d3ee67b2dcc7221b9fafa6d430400164012580e0c34d27", - x"a23b524d4308d46e43ee8cbbf57f3e1c20c47061ad9c3f915212334ea6532451dd5c01d3d3ada6bea10fe180b2c3b450", - x"a2aaa3eae1df3fc36365491afa1da5181acbb03801afd1430f04bb3b3eb18036f8b756b3508e4caee04beff50d455d1c", - x"84985b7e983dbdaddfca1f0b7dad9660bb39fff660e329acec15f69ac48c75dfa5d2df9f0dc320e4e7b7658166e0ac1c", - ]; - - let pops = vector[ - proof_of_possession_from_bytes(x"ab42afff92510034bf1232a37a0d31bc8abfc17e7ead9170d2d100f6cf6c75ccdcfedbd31699a112b4464a06fd636f3f190595863677d660b4c5d922268ace421f9e86e3a054946ee34ce29e1f88c1a10f27587cf5ec528d65ba7c0dc4863364"), - proof_of_possession_from_bytes(x"a6da5f2bc17df70ce664cff3e3a3e09d17162e47e652032b9fedc0c772fd5a533583242cba12095602e422e579c5284b1735009332dbdd23430bbcf61cc506ae37e41ff9a1fc78f0bc0d99b6bc7bf74c8f567dfb59079a035842bdc5fa3a0464"), - proof_of_possession_from_bytes(x"b8eef236595e2eab34d3c1abdab65971f5cfa1988c731ef62bd63c9a9ad3dfc9259f4f183bfffbc8375a38ba62e1c41a11173209705996ce889859bcbb3ddd7faa3c4ea3d8778f30a9ff814fdcfea1fb163d745c54dfb4dcc5a8cee092ee0070"), - proof_of_possession_from_bytes(x"a03a12fab68ad59d85c15dd1528560eff2c89250070ad0654ba260fda4334da179811d2ecdaca57693f80e9ce977d62011e3b1ee7bb4f7e0eb9b349468dd758f10fc35d54e0d0b8536ca713a77a301944392a5c192b6adf2a79ae2b38912dc98"), - proof_of_possession_from_bytes(x"8899b294f3c066e6dfb59bc0843265a1ccd6afc8f0f38a074d45ded8799c39d25ee0376cd6d6153b0d4d2ff8655e578b140254f1287b9e9df4e2aecc5b049d8556a4ab07f574df68e46348fd78e5298b7913377cf5bb3cf4796bfc755902bfdd"), - ]; - - assert!(std::vector::length(&pks) == std::vector::length(&pops), 1); - - let i = 0; - while (i < std::vector::length(&pks)) { - let opt_pk = public_key_from_bytes_with_pop(*std::vector::borrow(&pks, i), std::vector::borrow(&pops, i)); - assert!(option::is_some(&opt_pk), 1); - - i = i + 1; - }; - - // assert first PK's PoP does not verify against modifed PK' = 0xa0 | PK[1:] - let opt_pk = public_key_from_bytes_with_pop( - x"a08864c91ae7a9998b3f5ee71f447840864e56d79838e4785ff5126c51480198df3d972e1e0348c6da80d396983e42d7", - &proof_of_possession_from_bytes(x"ab42afff92510034bf1232a37a0d31bc8abfc17e7ead9170d2d100f6cf6c75ccdcfedbd31699a112b4464a06fd636f3f190595863677d660b4c5d922268ace421f9e86e3a054946ee34ce29e1f88c1a10f27587cf5ec528d65ba7c0dc4863364")); - assert!(option::is_none(&opt_pk), 1); - - // assert first PK's PoP does not verify if modifed as pop' = 0xb0 | pop[1:] - let opt_pk = public_key_from_bytes_with_pop( - x"808864c91ae7a9998b3f5ee71f447840864e56d79838e4785ff5126c51480198df3d972e1e0348c6da80d396983e42d7", - &proof_of_possession_from_bytes(x"bb42afff92510034bf1232a37a0d31bc8abfc17e7ead9170d2d100f6cf6c75ccdcfedbd31699a112b4464a06fd636f3f190595863677d660b4c5d922268ace421f9e86e3a054946ee34ce29e1f88c1a10f27587cf5ec528d65ba7c0dc4863364")); - assert!(option::is_none(&opt_pk), 1); - } - - #[test] - fun test_verify_pop_randomized() { - let (sk, pk) = generate_keys(); - let pk_bytes = public_key_with_pop_to_bytes(&pk); - let pop = generate_proof_of_possession(&sk); - assert!(option::is_some(&public_key_from_bytes_with_pop(pk_bytes, &pop)), 1); - assert!(option::is_none(&public_key_from_bytes_with_pop(pk_bytes, &maul_proof_of_possession(&pop))), 1); - assert!(option::is_none(&public_key_from_bytes_with_pop(maul_bytes(&pk_bytes), &pop)), 1); - } -} diff --git a/aptos-move/framework/aptos-stdlib/sources/cryptography/bls12381.spec.move b/aptos-move/framework/aptos-stdlib/sources/cryptography/bls12381.spec.move deleted file mode 100644 index fcac18cf7ac7a3..00000000000000 --- a/aptos-move/framework/aptos-stdlib/sources/cryptography/bls12381.spec.move +++ /dev/null @@ -1,164 +0,0 @@ -spec aptos_std::bls12381 { - - spec public_key_from_bytes { - aborts_if false; - ensures spec_validate_pubkey_internal(bytes) ==> (std::option::spec_is_some(result) && std::option::spec_borrow(result).bytes == bytes); - ensures !spec_validate_pubkey_internal(bytes) ==> std::option::spec_is_none(result); - } - - spec public_key_from_bytes_with_pop { - pragma opaque; - aborts_if false; - ensures spec_verify_proof_of_possession_internal(pk_bytes, pop.bytes) ==> (std::option::spec_is_some(result) && std::option::spec_borrow(result).bytes == pk_bytes); - ensures !spec_verify_proof_of_possession_internal(pk_bytes, pop.bytes) ==> std::option::spec_is_none(result); - ensures [abstract] result == spec_public_key_from_bytes_with_pop(pk_bytes, pop); - } - - spec aggregate_pubkeys { - let bytes = spec_aggregate_pubkeys_internal_1(public_keys); - let success = spec_aggregate_pubkeys_internal_2(public_keys); - aborts_if !success; - ensures result.bytes == bytes; - } - - spec aggregate_pubkeys_internal { - pragma opaque; - aborts_if [abstract] false; //TODO: check the aborts_if condition in the native implementation - ensures result_1 == spec_aggregate_pubkeys_internal_1(public_keys); - ensures result_2 == spec_aggregate_pubkeys_internal_2(public_keys); - } - - spec aggregate_signatures { - aborts_if false; - let bytes = spec_aggregate_signatures_internal_1(signatures); - let success = spec_aggregate_signatures_internal_2(signatures); - ensures success ==> (std::option::spec_is_some(result) && std::option::spec_borrow(result).bytes == bytes); - ensures !success ==> std::option::spec_is_none(result); - } - - spec aggregate_signatures_internal { - pragma opaque; - aborts_if [abstract] false; - ensures result_1 == spec_aggregate_signatures_internal_1(signatures); - ensures result_2 == spec_aggregate_signatures_internal_2(signatures); - } - - spec aggr_or_multi_signature_from_bytes { - aborts_if len(bytes) != SIGNATURE_SIZE; - ensures result.bytes == bytes; - } - - spec validate_pubkey_internal { - pragma opaque; - aborts_if [abstract] false; - ensures result == spec_validate_pubkey_internal(public_key); - } - - spec aggr_or_multi_signature_subgroup_check { - aborts_if false; - ensures result == spec_signature_subgroup_check_internal(signature.bytes); - } - - spec signature_subgroup_check_internal { - pragma opaque; - aborts_if [abstract] false; - ensures result == spec_signature_subgroup_check_internal(signature); - } - - spec verify_aggregate_signature { - aborts_if false; - ensures result == spec_verify_aggregate_signature_internal(aggr_sig.bytes, public_keys, messages); - } - - spec verify_aggregate_signature_internal { - pragma opaque; - aborts_if [abstract] false; - ensures result == spec_verify_aggregate_signature_internal(aggsig, public_keys, messages); - } - - spec verify_multisignature { - aborts_if false; - ensures result == spec_verify_multisignature_internal(multisig.bytes, aggr_public_key.bytes, message); - } - - spec verify_multisignature_internal { - pragma opaque; - aborts_if [abstract] false; - ensures result == spec_verify_multisignature_internal(multisignature, agg_public_key, message); - } - - spec verify_normal_signature { - aborts_if false; - ensures result == spec_verify_normal_signature_internal(signature.bytes, public_key.bytes, message); - } - - spec verify_normal_signature_internal { - pragma opaque; - aborts_if [abstract] false; - ensures result == spec_verify_normal_signature_internal(signature, public_key, message); - } - - spec verify_proof_of_possession_internal { - pragma opaque; - aborts_if [abstract] false; - ensures result == spec_verify_proof_of_possession_internal(public_key, proof_of_possesion); - } - - spec verify_signature_share { - aborts_if false; - ensures result == spec_verify_signature_share_internal(signature_share.bytes, public_key.bytes, message); - } - - spec verify_signature_share_internal { - pragma opaque; - aborts_if [abstract] false; - ensures result == spec_verify_signature_share_internal(signature_share, public_key, message); - } - - /// # Helper functions - - spec fun spec_aggregate_pubkeys_internal_1(public_keys: vector): vector; - - spec fun spec_public_key_from_bytes_with_pop(pk_bytes: vector, pop: ProofOfPossession): Option; - - spec fun spec_aggregate_pubkeys_internal_2(public_keys: vector): bool; - - spec fun spec_aggregate_signatures_internal_1(signatures: vector): vector; - - spec fun spec_aggregate_signatures_internal_2(signatures: vector): bool; - - spec fun spec_validate_pubkey_internal(public_key: vector): bool; - - spec fun spec_signature_subgroup_check_internal(signature: vector): bool; - - spec fun spec_verify_aggregate_signature_internal( - aggsig: vector, - public_keys: vector, - messages: vector>, - ): bool; - - spec fun spec_verify_multisignature_internal( - multisignature: vector, - agg_public_key: vector, - message: vector - ): bool; - - spec fun spec_verify_normal_signature_internal( - signature: vector, - public_key: vector, - message: vector - ): bool; - - spec fun spec_verify_proof_of_possession_internal( - public_key: vector, - proof_of_possesion: vector - ): bool; - - spec fun spec_verify_signature_share_internal( - signature_share: vector, - public_key: vector, - message: vector - ): bool; - - -} diff --git a/aptos-move/framework/aptos-stdlib/sources/cryptography/bls12381_algebra.move b/aptos-move/framework/aptos-stdlib/sources/cryptography/bls12381_algebra.move deleted file mode 100644 index 5fb99beb93c1bd..00000000000000 --- a/aptos-move/framework/aptos-stdlib/sources/cryptography/bls12381_algebra.move +++ /dev/null @@ -1,802 +0,0 @@ -/// This module defines marker types, constants and test cases for working with BLS12-381 curves -/// using the generic API defined in `algebra.move`. -/// See https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11#name-bls-curves-for-the-128-bit- -/// for the full specification of BLS12-381 curves. -/// -/// Currently-supported BLS12-381 structures include `Fq12`, `Fr`, `G1`, `G2` and `Gt`, -/// along with their widely-used serialization formats, -/// the pairing between `G1`, `G2` and `Gt`, -/// and the hash-to-curve operations for `G1` and `G2` defined in https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16. -/// -/// Other unimplemented BLS12-381 structures and serialization formats are also listed here, -/// as they help define some of the currently supported structures. -/// Their implementation may also be added in the future. -/// -/// `Fq`: the finite field $F_q$ used in BLS12-381 curves with a prime order $q$ equal to -/// 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab. -/// -/// `FormatFqLsb`: a serialization format for `Fq` elements, -/// where an element is represented by a byte array `b[]` of size 48 with the least significant byte (LSB) coming first. -/// -/// `FormatFqMsb`: a serialization format for `Fq` elements, -/// where an element is represented by a byte array `b[]` of size 48 with the most significant byte (MSB) coming first. -/// -/// `Fq2`: the finite field $F_{q^2}$ used in BLS12-381 curves, -/// which is an extension field of `Fq`, constructed as $F_{q^2}=F_q[u]/(u^2+1)$. -/// -/// `FormatFq2LscLsb`: a serialization format for `Fq2` elements, -/// where an element in the form $(c_0+c_1\cdot u)$ is represented by a byte array `b[]` of size 96, -/// which is a concatenation of its coefficients serialized, with the least significant coefficient (LSC) coming first: -/// - `b[0..48]` is $c_0$ serialized using `FormatFqLsb`. -/// - `b[48..96]` is $c_1$ serialized using `FormatFqLsb`. -/// -/// `FormatFq2MscMsb`: a serialization format for `Fq2` elements, -/// where an element in the form $(c_0+c_1\cdot u)$ is represented by a byte array `b[]` of size 96, -/// which is a concatenation of its coefficients serialized, with the most significant coefficient (MSC) coming first: -/// - `b[0..48]` is $c_1$ serialized using `FormatFqLsb`. -/// - `b[48..96]` is $c_0$ serialized using `FormatFqLsb`. -/// -/// `Fq6`: the finite field $F_{q^6}$ used in BLS12-381 curves, -/// which is an extension field of `Fq2`, constructed as $F_{q^6}=F_{q^2}[v]/(v^3-u-1)$. -/// -/// `FormatFq6LscLsb`: a serialization scheme for `Fq6` elements, -/// where an element in the form $(c_0+c_1\cdot v+c_2\cdot v^2)$ is represented by a byte array `b[]` of size 288, -/// which is a concatenation of its coefficients serialized, with the least significant coefficient (LSC) coming first: -/// - `b[0..96]` is $c_0$ serialized using `FormatFq2LscLsb`. -/// - `b[96..192]` is $c_1$ serialized using `FormatFq2LscLsb`. -/// - `b[192..288]` is $c_2$ serialized using `FormatFq2LscLsb`. -/// -/// `G1Full`: a group constructed by the points on the BLS12-381 curve $E(F_q): y^2=x^3+4$ and the point at infinity, -/// under the elliptic curve point addition. -/// It contains the prime-order subgroup $G_1$ used in pairing. -/// -/// `G2Full`: a group constructed by the points on a curve $E'(F_{q^2}): y^2=x^3+4(u+1)$ and the point at infinity, -/// under the elliptic curve point addition. -/// It contains the prime-order subgroup $G_2$ used in pairing. -module aptos_std::bls12381_algebra { - // - // Marker types + serialization formats begin. - // - - /// The finite field $F_{q^12}$ used in BLS12-381 curves, - /// which is an extension field of `Fq6` (defined in the module documentation), constructed as $F_{q^12}=F_{q^6}[w]/(w^2-v)$. - struct Fq12 {} - - /// A serialization scheme for `Fq12` elements, - /// where an element $(c_0+c_1\cdot w)$ is represented by a byte array `b[]` of size 576, - /// which is a concatenation of its coefficients serialized, with the least significant coefficient (LSC) coming first. - /// - `b[0..288]` is $c_0$ serialized using `FormatFq6LscLsb` (defined in the module documentation). - /// - `b[288..576]` is $c_1$ serialized using `FormatFq6LscLsb`. - /// - /// NOTE: other implementation(s) using this format: ark-bls12-381-0.4.0. - struct FormatFq12LscLsb {} - - /// The group $G_1$ in BLS12-381-based pairing $G_1 \times G_2 \rightarrow G_t$. - /// It is a subgroup of `G1Full` (defined in the module documentation) with a prime order $r$ - /// equal to 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001. - /// (so `Fr` is the associated scalar field). - struct G1 {} - - /// A serialization scheme for `G1` elements derived from - /// https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html#name-zcash-serialization-format-. - /// - /// Below is the serialization procedure that takes a `G1` element `p` and outputs a byte array of size 96. - /// 1. Let `(x,y)` be the coordinates of `p` if `p` is on the curve, or `(0,0)` otherwise. - /// 1. Serialize `x` and `y` into `b_x[]` and `b_y[]` respectively using `FormatFqMsb` (defined in the module documentation). - /// 1. Concatenate `b_x[]` and `b_y[]` into `b[]`. - /// 1. If `p` is the point at infinity, set the infinity bit: `b[0]: = b[0] | 0x40`. - /// 1. Return `b[]`. - /// - /// Below is the deserialization procedure that takes a byte array `b[]` and outputs either a `G1` element or none. - /// 1. If the size of `b[]` is not 96, return none. - /// 1. Compute the compression flag as `b[0] & 0x80 != 0`. - /// 1. If the compression flag is true, return none. - /// 1. Compute the infinity flag as `b[0] & 0x40 != 0`. - /// 1. If the infinity flag is set, return the point at infinity. - /// 1. Deserialize `[b[0] & 0x1f, b[1], ..., b[47]]` to `x` using `FormatFqMsb`. If `x` is none, return none. - /// 1. Deserialize `[b[48], ..., b[95]]` to `y` using `FormatFqMsb`. If `y` is none, return none. - /// 1. Check if `(x,y)` is on curve `E`. If not, return none. - /// 1. Check if `(x,y)` is in the subgroup of order `r`. If not, return none. - /// 1. Return `(x,y)`. - /// - /// NOTE: other implementation(s) using this format: ark-bls12-381-0.4.0. - struct FormatG1Uncompr {} - - /// A serialization scheme for `G1` elements derived from - /// https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html#name-zcash-serialization-format-. - /// - /// Below is the serialization procedure that takes a `G1` element `p` and outputs a byte array of size 48. - /// 1. Let `(x,y)` be the coordinates of `p` if `p` is on the curve, or `(0,0)` otherwise. - /// 1. Serialize `x` into `b[]` using `FormatFqMsb` (defined in the module documentation). - /// 1. Set the compression bit: `b[0] := b[0] | 0x80`. - /// 1. If `p` is the point at infinity, set the infinity bit: `b[0]: = b[0] | 0x40`. - /// 1. If `y > -y`, set the lexicographical flag: `b[0] := b[0] | 0x20`. - /// 1. Return `b[]`. - /// - /// Below is the deserialization procedure that takes a byte array `b[]` and outputs either a `G1` element or none. - /// 1. If the size of `b[]` is not 48, return none. - /// 1. Compute the compression flag as `b[0] & 0x80 != 0`. - /// 1. If the compression flag is false, return none. - /// 1. Compute the infinity flag as `b[0] & 0x40 != 0`. - /// 1. If the infinity flag is set, return the point at infinity. - /// 1. Compute the lexicographical flag as `b[0] & 0x20 != 0`. - /// 1. Deserialize `[b[0] & 0x1f, b[1], ..., b[47]]` to `x` using `FormatFqMsb`. If `x` is none, return none. - /// 1. Solve the curve equation with `x` for `y`. If no such `y` exists, return none. - /// 1. Let `y'` be `max(y,-y)` if the lexicographical flag is set, or `min(y,-y)` otherwise. - /// 1. Check if `(x,y')` is in the subgroup of order `r`. If not, return none. - /// 1. Return `(x,y')`. - /// - /// NOTE: other implementation(s) using this format: ark-bls12-381-0.4.0. - struct FormatG1Compr {} - - /// The group $G_2$ in BLS12-381-based pairing $G_1 \times G_2 \rightarrow G_t$. - /// It is a subgroup of `G2Full` (defined in the module documentation) with a prime order $r$ equal to - /// 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001. - /// (so `Fr` is the scalar field). - struct G2 {} - - /// A serialization scheme for `G2` elements derived from - /// https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html#name-zcash-serialization-format-. - /// - /// Below is the serialization procedure that takes a `G2` element `p` and outputs a byte array of size 192. - /// 1. Let `(x,y)` be the coordinates of `p` if `p` is on the curve, or `(0,0)` otherwise. - /// 1. Serialize `x` and `y` into `b_x[]` and `b_y[]` respectively using `FormatFq2MscMsb` (defined in the module documentation). - /// 1. Concatenate `b_x[]` and `b_y[]` into `b[]`. - /// 1. If `p` is the point at infinity, set the infinity bit in `b[]`: `b[0]: = b[0] | 0x40`. - /// 1. Return `b[]`. - /// - /// Below is the deserialization procedure that takes a byte array `b[]` and outputs either a `G2` element or none. - /// 1. If the size of `b[]` is not 192, return none. - /// 1. Compute the compression flag as `b[0] & 0x80 != 0`. - /// 1. If the compression flag is true, return none. - /// 1. Compute the infinity flag as `b[0] & 0x40 != 0`. - /// 1. If the infinity flag is set, return the point at infinity. - /// 1. Deserialize `[b[0] & 0x1f, ..., b[95]]` to `x` using `FormatFq2MscMsb`. If `x` is none, return none. - /// 1. Deserialize `[b[96], ..., b[191]]` to `y` using `FormatFq2MscMsb`. If `y` is none, return none. - /// 1. Check if `(x,y)` is on the curve `E'`. If not, return none. - /// 1. Check if `(x,y)` is in the subgroup of order `r`. If not, return none. - /// 1. Return `(x,y)`. - /// - /// NOTE: other implementation(s) using this format: ark-bls12-381-0.4.0. - struct FormatG2Uncompr {} - - /// A serialization scheme for `G2` elements derived from - /// https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html#name-zcash-serialization-format-. - /// - /// Below is the serialization procedure that takes a `G2` element `p` and outputs a byte array of size 96. - /// 1. Let `(x,y)` be the coordinates of `p` if `p` is on the curve, or `(0,0)` otherwise. - /// 1. Serialize `x` into `b[]` using `FormatFq2MscMsb` (defined in the module documentation). - /// 1. Set the compression bit: `b[0] := b[0] | 0x80`. - /// 1. If `p` is the point at infinity, set the infinity bit: `b[0]: = b[0] | 0x40`. - /// 1. If `y > -y`, set the lexicographical flag: `b[0] := b[0] | 0x20`. - /// 1. Return `b[]`. - /// - /// Below is the deserialization procedure that takes a byte array `b[]` and outputs either a `G2` element or none. - /// 1. If the size of `b[]` is not 96, return none. - /// 1. Compute the compression flag as `b[0] & 0x80 != 0`. - /// 1. If the compression flag is false, return none. - /// 1. Compute the infinity flag as `b[0] & 0x40 != 0`. - /// 1. If the infinity flag is set, return the point at infinity. - /// 1. Compute the lexicographical flag as `b[0] & 0x20 != 0`. - /// 1. Deserialize `[b[0] & 0x1f, b[1], ..., b[95]]` to `x` using `FormatFq2MscMsb`. If `x` is none, return none. - /// 1. Solve the curve equation with `x` for `y`. If no such `y` exists, return none. - /// 1. Let `y'` be `max(y,-y)` if the lexicographical flag is set, or `min(y,-y)` otherwise. - /// 1. Check if `(x,y')` is in the subgroup of order `r`. If not, return none. - /// 1. Return `(x,y')`. - /// - /// NOTE: other implementation(s) using this format: ark-bls12-381-0.4.0. - struct FormatG2Compr {} - - /// The group $G_t$ in BLS12-381-based pairing $G_1 \times G_2 \rightarrow G_t$. - /// It is a multiplicative subgroup of `Fq12`, - /// with a prime order $r$ equal to 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001. - /// (so `Fr` is the scalar field). - /// The identity of `Gt` is 1. - struct Gt {} - - /// A serialization scheme for `Gt` elements. - /// - /// To serialize, it treats a `Gt` element `p` as an `Fq12` element and serialize it using `FormatFq12LscLsb`. - /// - /// To deserialize, it uses `FormatFq12LscLsb` to try deserializing to an `Fq12` element then test the membership in `Gt`. - /// - /// NOTE: other implementation(s) using this format: ark-bls12-381-0.4.0. - struct FormatGt {} - - /// The finite field $F_r$ that can be used as the scalar fields - /// associated with the groups $G_1$, $G_2$, $G_t$ in BLS12-381-based pairing. - struct Fr {} - - /// A serialization format for `Fr` elements, - /// where an element is represented by a byte array `b[]` of size 32 with the least significant byte (LSB) coming first. - /// - /// NOTE: other implementation(s) using this format: ark-bls12-381-0.4.0, blst-0.3.7. - struct FormatFrLsb {} - - /// A serialization scheme for `Fr` elements, - /// where an element is represented by a byte array `b[]` of size 32 with the most significant byte (MSB) coming first. - /// - /// NOTE: other implementation(s) using this format: ark-bls12-381-0.4.0, blst-0.3.7. - struct FormatFrMsb {} - - // - // (Marker types + serialization formats end here.) - // Hash-to-structure suites begin. - // - - /// The hash-to-curve suite `BLS12381G1_XMD:SHA-256_SSWU_RO_` that hashes a byte array into `G1` elements. - /// - /// Full specification is defined in https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#name-bls12-381-g1. - struct HashG1XmdSha256SswuRo {} - - /// The hash-to-curve suite `BLS12381G2_XMD:SHA-256_SSWU_RO_` that hashes a byte array into `G2` elements. - /// - /// Full specification is defined in https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#name-bls12-381-g2. - struct HashG2XmdSha256SswuRo {} - - // - // (Hash-to-structure suites end here.) - // Tests begin. - // - - #[test_only] - const FQ12_VAL_0_SERIALIZED: vector = x"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const FQ12_VAL_1_SERIALIZED: vector = x"010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const FQ12_VAL_7_SERIALIZED: vector = x"070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const FQ12_VAL_7_NEG_SERIALIZED: vector = x"a4aafffffffffeb9ffff53b1feffab1e24f6b0f6a0d23067bf1285f3844b7764d7ac4b43b6a71b4b9ae67f39ea11011a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const Q12_SERIALIZED: vector = x"1175f55da544c7625f8ccb1360e2b1d3ca40747811c8f5ed04440afe232b476c0215676aec05f2a44ac2da6b6d1b7cff075e7b2a587e0aab601a8d3db4f0d29906e5e4d0d78119f396d5a59f0f8d1ca8bca62540be6ab9c12d0ca00de1f311f106278d000e55a393c9766a74e0d08a298450f60d7e666575e3354bf14b8731f4e721c0c180a5ed55c2f8f51f815baecbf96b5fc717eb58ac161a27d1d5f2bdc1a079609b9d6449165b2466b32a01eac7992a1ea0cac2f223cde1d56f9bbccc67afe44621daf858df3fc0eb837818f3e42ab3e131ce4e492efa63c108e6ef91c29ed63b3045baebcb0ab8d203c7f558beaffccba31b12aca7f54b58d0c28340e4fdb3c7c94fe9c4fef9d640ff2fcff02f1748416cbed0981fbff49f0e39eaf8a30273e67ed851944d33d6a593ef5ddcd62da84568822a6045b633bf6a513b3cfe8f9de13e76f8dcbd915980dec205eab6a5c0c72dcebd9afff1d25509ddbf33f8e24131fbd74cda93336514340cf8036b66b09ed9e6a6ac37e22fb3ac407e321beae8cd9fe74c8aaeb4edaa9a7272848fc623f6fe835a2e647379f547fc5ec6371318a85bfa60009cb20ccbb8a467492988a87633c14c0324ba0d0c3e1798ed29c8494cea35023746da05e35d184b4a301d5b2238d665495c6318b5af8653758008952d06cb9e62487b196d64383c73c06d6e1cccdf9b3ce8f95679e7050d949004a55f4ccf95b2552880ae36d1f7e09504d2338316d87d14a064511a295d768113e301bdf9d4383a8be32192d3f2f3b2de14181c73839a7cb4af5301"; - - #[test_only] - fun rand_vector(num: u64): vector> { - let elements = vector[]; - while (num > 0) { - std::vector::push_back(&mut elements, rand_insecure()); - num = num - 1; - }; - elements - } - - #[test(fx = @std)] - fun test_fq12(fx: signer) { - enable_cryptography_algebra_natives(&fx); - - // Constants. - assert!(Q12_SERIALIZED == order(), 1); - - // Serialization/deserialization. - let val_0 = zero(); - let val_1 = one(); - assert!(FQ12_VAL_0_SERIALIZED == serialize(&val_0), 1); - assert!(FQ12_VAL_1_SERIALIZED == serialize(&val_1), 1); - let val_7 = from_u64(7); - let val_7_another = std::option::extract(&mut deserialize(&FQ12_VAL_7_SERIALIZED)); - assert!(eq(&val_7, &val_7_another), 1); - assert!(FQ12_VAL_7_SERIALIZED == serialize(&val_7), 1); - assert!(std::option::is_none(&deserialize(&x"ffff")), 1); - - // Negation. - let val_minus_7 = neg(&val_7); - assert!(FQ12_VAL_7_NEG_SERIALIZED == serialize(&val_minus_7), 1); - - // Addition. - let val_9 = from_u64(9); - let val_2 = from_u64(2); - assert!(eq(&val_2, &add(&val_minus_7, &val_9)), 1); - - // Subtraction. - assert!(eq(&val_9, &sub(&val_2, &val_minus_7)), 1); - - // Multiplication. - let val_63 = from_u64(63); - assert!(eq(&val_63, &mul(&val_7, &val_9)), 1); - - // division. - let val_0 = from_u64(0); - assert!(eq(&val_7, &std::option::extract(&mut div(&val_63, &val_9))), 1); - assert!(std::option::is_none(&div(&val_63, &val_0)), 1); - - // Inversion. - assert!(eq(&val_minus_7, &neg(&val_7)), 1); - assert!(std::option::is_none(&inv(&val_0)), 1); - - // Squaring. - let val_x = rand_insecure(); - assert!(eq(&mul(&val_x, &val_x), &sqr(&val_x)), 1); - - // Downcasting. - assert!(eq(&zero(), &std::option::extract(&mut downcast(&val_1))), 1); - } - - #[test_only] - const R_SERIALIZED: vector = x"01000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73"; - #[test_only] - const G1_INF_SERIALIZED_COMP: vector = x"c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const G1_INF_SERIALIZED_UNCOMP: vector = x"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const G1_GENERATOR_SERIALIZED_COMP: vector = x"97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"; - #[test_only] - const G1_GENERATOR_SERIALIZED_UNCOMP: vector = x"17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"; - #[test_only] - const G1_GENERATOR_MUL_BY_7_SERIALIZED_COMP: vector = x"b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7"; - #[test_only] - const G1_GENERATOR_MUL_BY_7_SERIALIZED_UNCOMP: vector = x"1928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7108dadbaa4b636445639d5ae3089b3c43a8a1d47818edd1839d7383959a41c10fdc66849cfa1b08c5a11ec7e28981a1c"; - #[test_only] - const G1_GENERATOR_MUL_BY_7_NEG_SERIALIZED_COMP: vector = x"9928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7"; - #[test_only] - const G1_GENERATOR_MUL_BY_7_NEG_SERIALIZED_UNCOMP: vector = x"1928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb70973642f94c9b055f4e1d20812c1f91329ed2e3d71f635a72d599a679d0cda1320e597b4e1b24f735fed1381d767908f"; - - #[test(fx = @std)] - fun test_g1affine(fx: signer) { - enable_cryptography_algebra_natives(&fx); - - // Constants. - assert!(R_SERIALIZED == order(), 1); - let point_at_infinity = zero(); - let generator = one(); - - // Serialization/deserialization. - assert!(G1_GENERATOR_SERIALIZED_UNCOMP == serialize(&generator), 1); - assert!(G1_GENERATOR_SERIALIZED_COMP == serialize(&generator), 1); - let generator_from_comp = std::option::extract(&mut deserialize(&G1_GENERATOR_SERIALIZED_COMP - )); - let generator_from_uncomp = std::option::extract(&mut deserialize(&G1_GENERATOR_SERIALIZED_UNCOMP - )); - assert!(eq(&generator, &generator_from_comp), 1); - assert!(eq(&generator, &generator_from_uncomp), 1); - - // Deserialization should fail if given a byte array of correct size but the value is not a member. - assert!(std::option::is_none(&deserialize(&x"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), 1); - - // Deserialization should fail if given a byte array of wrong size. - assert!(std::option::is_none(&deserialize(&x"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), 1); - - assert!( - G1_INF_SERIALIZED_UNCOMP == serialize(&point_at_infinity), 1); - assert!(G1_INF_SERIALIZED_COMP == serialize(&point_at_infinity), 1); - let inf_from_uncomp = std::option::extract(&mut deserialize(&G1_INF_SERIALIZED_UNCOMP - )); - let inf_from_comp = std::option::extract(&mut deserialize(&G1_INF_SERIALIZED_COMP - )); - assert!(eq(&point_at_infinity, &inf_from_comp), 1); - assert!(eq(&point_at_infinity, &inf_from_uncomp), 1); - - let point_7g_from_uncomp = std::option::extract(&mut deserialize(&G1_GENERATOR_MUL_BY_7_SERIALIZED_UNCOMP - )); - let point_7g_from_comp = std::option::extract(&mut deserialize(&G1_GENERATOR_MUL_BY_7_SERIALIZED_COMP - )); - assert!(eq(&point_7g_from_comp, &point_7g_from_uncomp), 1); - - // Deserialization should fail if given a point on the curve but off its prime-order subgroup, e.g., `(0,2)`. - assert!(std::option::is_none(&deserialize(&x"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002")), 1); - assert!(std::option::is_none(&deserialize(&x"800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")), 1); - - // Deserialization should fail if given a valid point in (Fq,Fq) but not on the curve. - assert!(std::option::is_none(&deserialize(&x"8959e137e0719bf872abb08411010f437a8955bd42f5ba20fca64361af58ce188b1adb96ef229698bb7860b79e24ba12000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")), 1); - - // Deserialization should fail if given an invalid point (x not in Fq). - assert!(std::option::is_none(&deserialize(&x"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa76e9853b35f5c9b2002d9e5833fd8f9ab4cd3934a4722a06f6055bfca720c91629811e2ecae7f0cf301b6d07898a90f")), 1); - assert!(std::option::is_none(&deserialize(&x"9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), 1); - - // Deserialization should fail if given a byte array of wrong size. - assert!(std::option::is_none(&deserialize(&x"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab")), 1); - assert!(std::option::is_none(&deserialize(&x"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab")), 1); - - // Scalar multiplication. - let scalar_7 = from_u64(7); - let point_7g_calc = scalar_mul(&generator, &scalar_7); - assert!(eq(&point_7g_calc, &point_7g_from_comp), 1); - assert!(G1_GENERATOR_MUL_BY_7_SERIALIZED_UNCOMP == serialize(&point_7g_calc), 1); - assert!(G1_GENERATOR_MUL_BY_7_SERIALIZED_COMP == serialize( &point_7g_calc), 1); - - // Multi-scalar multiplication. - let num_entries = 1; - while (num_entries < 10) { - let scalars = rand_vector(num_entries); - let elements = rand_vector(num_entries); - - let expected = zero(); - let i = 0; - while (i < num_entries) { - let element = std::vector::borrow(&elements, i); - let scalar = std::vector::borrow(&scalars, i); - expected = add(&expected, &scalar_mul(element, scalar)); - i = i + 1; - }; - - let actual = multi_scalar_mul(&elements, &scalars); - assert!(eq(&expected, &actual), 1); - - num_entries = num_entries + 1; - }; - - // Doubling. - let scalar_2 = from_u64(2); - let point_2g = scalar_mul(&generator, &scalar_2); - let point_double_g = double(&generator); - assert!(eq(&point_2g, &point_double_g), 1); - - // Negation. - let point_minus_7g_calc = neg(&point_7g_calc); - assert!(G1_GENERATOR_MUL_BY_7_NEG_SERIALIZED_COMP == serialize(&point_minus_7g_calc), 1); - assert!(G1_GENERATOR_MUL_BY_7_NEG_SERIALIZED_UNCOMP == serialize(&point_minus_7g_calc), 1); - - // Addition. - let scalar_9 = from_u64(9); - let point_9g = scalar_mul(&generator, &scalar_9); - let point_2g = scalar_mul(&generator, &scalar_2); - let point_2g_calc = add(&point_minus_7g_calc, &point_9g); - assert!(eq(&point_2g, &point_2g_calc), 1); - - // Subtraction. - assert!(eq(&point_9g, &sub(&point_2g, &point_minus_7g_calc)), 1); - - // Hash-to-group using suite `BLS12381G1_XMD:SHA-256_SSWU_RO_`. - // Test vectors source: https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-bls12381g1_xmdsha-256_sswu_ - let actual = hash_to(&b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_", &b""); - let expected = std::option::extract(&mut deserialize(&x"052926add2207b76ca4fa57a8734416c8dc95e24501772c814278700eed6d1e4e8cf62d9c09db0fac349612b759e79a108ba738453bfed09cb546dbb0783dbb3a5f1f566ed67bb6be0e8c67e2e81a4cc68ee29813bb7994998f3eae0c9c6a265")); - assert!(eq(&expected, &actual), 1); - let actual = hash_to(&b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_", &b"abcdef0123456789"); - let expected = std::option::extract(&mut deserialize(&x"11e0b079dea29a68f0383ee94fed1b940995272407e3bb916bbf268c263ddd57a6a27200a784cbc248e84f357ce82d9803a87ae2caf14e8ee52e51fa2ed8eefe80f02457004ba4d486d6aa1f517c0889501dc7413753f9599b099ebcbbd2d709")); - assert!(eq(&expected, &actual), 1); - } - - #[test_only] - const G2_INF_SERIALIZED_UNCOMP: vector = x"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const G2_INF_SERIALIZED_COMP: vector = x"c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const G2_GENERATOR_SERIALIZED_UNCOMP: vector = x"13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801"; - #[test_only] - const G2_GENERATOR_SERIALIZED_COMP: vector = x"93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8"; - #[test_only] - const G2_GENERATOR_MUL_BY_7_SERIALIZED_UNCOMP: vector = x"0d0273f6bf31ed37c3b8d68083ec3d8e20b5f2cc170fa24b9b5be35b34ed013f9a921f1cad1644d4bdb14674247234c8049cd1dbb2d2c3581e54c088135fef36505a6823d61b859437bfc79b617030dc8b40e32bad1fa85b9c0f368af6d38d3c05ecf93654b7a1885695aaeeb7caf41b0239dc45e1022be55d37111af2aecef87799638bec572de86a7437898efa702008b7ae4dbf802c17a6648842922c9467e460a71c88d393ee7af356da123a2f3619e80c3bdcc8e2b1da52f8cd9913ccdd"; - #[test_only] - const G2_GENERATOR_MUL_BY_7_SERIALIZED_COMP: vector = x"8d0273f6bf31ed37c3b8d68083ec3d8e20b5f2cc170fa24b9b5be35b34ed013f9a921f1cad1644d4bdb14674247234c8049cd1dbb2d2c3581e54c088135fef36505a6823d61b859437bfc79b617030dc8b40e32bad1fa85b9c0f368af6d38d3c"; - #[test_only] - const G2_GENERATOR_MUL_BY_7_NEG_SERIALIZED_UNCOMP: vector = x"0d0273f6bf31ed37c3b8d68083ec3d8e20b5f2cc170fa24b9b5be35b34ed013f9a921f1cad1644d4bdb14674247234c8049cd1dbb2d2c3581e54c088135fef36505a6823d61b859437bfc79b617030dc8b40e32bad1fa85b9c0f368af6d38d3c141418b3e4c84511f485fcc78b80b8bc623d6f3f1282e6da09f9c1860402272ba7129c72c4fcd2174f8ac87671053a8b1149639c79ffba82a4b71f73b11f186f8016a4686ab17ed0ec3d7bc6e476c6ee04c3f3c2d48b1d4ddfac073266ebddce"; - #[test_only] - const G2_GENERATOR_MUL_BY_7_NEG_SERIALIZED_COMP: vector = x"ad0273f6bf31ed37c3b8d68083ec3d8e20b5f2cc170fa24b9b5be35b34ed013f9a921f1cad1644d4bdb14674247234c8049cd1dbb2d2c3581e54c088135fef36505a6823d61b859437bfc79b617030dc8b40e32bad1fa85b9c0f368af6d38d3c"; - - #[test(fx = @std)] - fun test_g2affine(fx: signer) { - enable_cryptography_algebra_natives(&fx); - - // Special constants. - assert!(R_SERIALIZED == order(), 1); - let point_at_infinity = zero(); - let generator = one(); - - // Serialization/deserialization. - assert!(G2_GENERATOR_SERIALIZED_COMP == serialize(&generator), 1); - assert!(G2_GENERATOR_SERIALIZED_UNCOMP == serialize(&generator), 1); - let generator_from_uncomp = std::option::extract(&mut deserialize(&G2_GENERATOR_SERIALIZED_UNCOMP - )); - let generator_from_comp = std::option::extract(&mut deserialize(&G2_GENERATOR_SERIALIZED_COMP - )); - assert!(eq(&generator, &generator_from_comp), 1); - assert!(eq(&generator, &generator_from_uncomp), 1); - assert!(G2_INF_SERIALIZED_UNCOMP == serialize(&point_at_infinity), 1); - assert!(G2_INF_SERIALIZED_COMP == serialize(&point_at_infinity), 1); - let inf_from_uncomp = std::option::extract(&mut deserialize(&G2_INF_SERIALIZED_UNCOMP)); - let inf_from_comp = std::option::extract(&mut deserialize(&G2_INF_SERIALIZED_COMP)); - assert!(eq(&point_at_infinity, &inf_from_comp), 1); - assert!(eq(&point_at_infinity, &inf_from_uncomp), 1); - let point_7g_from_uncomp = std::option::extract(&mut deserialize(&G2_GENERATOR_MUL_BY_7_SERIALIZED_UNCOMP - )); - let point_7g_from_comp = std::option::extract(&mut deserialize(&G2_GENERATOR_MUL_BY_7_SERIALIZED_COMP - )); - assert!(eq(&point_7g_from_comp, &point_7g_from_uncomp), 1); - - // Deserialization should fail if given a point on the curve but not in the prime-order subgroup. - assert!(std::option::is_none(&deserialize(&x"f037d4ccd5ee751eba1c1fd4c7edbb76d2b04c3a1f3f554827cf37c3acbc2dbb7cdb320a2727c2462d6c55ca1f637707b96eeebc622c1dbe7c56c34f93887c8751b42bd04f29253a82251c192ef27ece373993b663f4360505299c5bd18c890ddd862a6308796bf47e2265073c1f7d81afd69f9497fc1403e2e97a866129b43b672295229c21116d4a99f3e5c2ae720a31f181dbed8a93e15f909c20cf69d11a8879adbbe6890740def19814e6d4ed23fb0dcbd79291655caf48b466ac9cae04")), 1); - assert!(std::option::is_none(&deserialize(&x"f037d4ccd5ee751eba1c1fd4c7edbb76d2b04c3a1f3f554827cf37c3acbc2dbb7cdb320a2727c2462d6c55ca1f637707b96eeebc622c1dbe7c56c34f93887c8751b42bd04f29253a82251c192ef27ece373993b663f4360505299c5bd18c890d")), 1); - - // Deserialization should fail if given a valid point in (Fq2,Fq2) but not on the curve. - assert!(std::option::is_none(&deserialize(&x"f037d4ccd5ee751eba1c1fd4c7edbb76d2b04c3a1f3f554827cf37c3acbc2dbb7cdb320a2727c2462d6c55ca1f637707b96eeebc622c1dbe7c56c34f93887c8751b42bd04f29253a82251c192ef27ece373993b663f4360505299c5bd18c890d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")), 1); - - // Deserialization should fail if given an invalid point (x not in Fq2). - assert!(std::option::is_none(&deserialize(&x"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd862a6308796bf47e2265073c1f7d81afd69f9497fc1403e2e97a866129b43b672295229c21116d4a99f3e5c2ae720a31f181dbed8a93e15f909c20cf69d11a8879adbbe6890740def19814e6d4ed23fb0dcbd79291655caf48b466ac9cae04")), 1); - assert!(std::option::is_none(&deserialize(&x"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), 1); - - // Deserialization should fail if given a byte array of wrong size. - assert!(std::option::is_none(&deserialize(&x"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab")), 1); - assert!(std::option::is_none(&deserialize(&x"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab")), 1); - - // Scalar multiplication. - let scalar_7 = from_u64(7); - let point_7g_calc = scalar_mul(&generator, &scalar_7); - assert!(eq(&point_7g_calc, &point_7g_from_comp), 1); - assert!(G2_GENERATOR_MUL_BY_7_SERIALIZED_UNCOMP == serialize(&point_7g_calc), 1); - assert!(G2_GENERATOR_MUL_BY_7_SERIALIZED_COMP == serialize(&point_7g_calc), 1); - - // Multi-scalar multiplication. - let num_entries = 1; - while (num_entries < 10) { - let scalars = rand_vector(num_entries); - let elements = rand_vector(num_entries); - - let expected = zero(); - let i = 0; - while (i < num_entries) { - let element = std::vector::borrow(&elements, i); - let scalar = std::vector::borrow(&scalars, i); - expected = add(&expected, &scalar_mul(element, scalar)); - i = i + 1; - }; - - let actual = multi_scalar_mul(&elements, &scalars); - assert!(eq(&expected, &actual), 1); - - num_entries = num_entries + 1; - }; - - // Doubling. - let scalar_2 = from_u64(2); - let point_2g = scalar_mul(&generator, &scalar_2); - let point_double_g = double(&generator); - assert!(eq(&point_2g, &point_double_g), 1); - - // Negation. - let point_minus_7g_calc = neg(&point_7g_calc); - assert!(G2_GENERATOR_MUL_BY_7_NEG_SERIALIZED_COMP == serialize(&point_minus_7g_calc), 1); - assert!(G2_GENERATOR_MUL_BY_7_NEG_SERIALIZED_UNCOMP == serialize(&point_minus_7g_calc), 1); - - // Addition. - let scalar_9 = from_u64(9); - let point_9g = scalar_mul(&generator, &scalar_9); - let point_2g = scalar_mul(&generator, &scalar_2); - let point_2g_calc = add(&point_minus_7g_calc, &point_9g); - assert!(eq(&point_2g, &point_2g_calc), 1); - - // Subtraction. - assert!(eq(&point_9g, &sub(&point_2g, &point_minus_7g_calc)), 1); - - // Hash-to-group using suite `BLS12381G2_XMD:SHA-256_SSWU_RO_`. - // Test vectors source: https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-bls12381g2_xmdsha-256_sswu_ - let actual = hash_to(&b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_", &b""); - let expected = std::option::extract(&mut deserialize(&x"05cb8437535e20ecffaef7752baddf98034139c38452458baeefab379ba13dff5bf5dd71b72418717047f5b0f37da03d0141ebfbdca40eb85b87142e130ab689c673cf60f1a3e98d69335266f30d9b8d4ac44c1038e9dcdd5393faf5c41fb78a12424ac32561493f3fe3c260708a12b7c620e7be00099a974e259ddc7d1f6395c3c811cdd19f1e8dbf3e9ecfdcbab8d60503921d7f6a12805e72940b963c0cf3471c7b2a524950ca195d11062ee75ec076daf2d4bc358c4b190c0c98064fdd92")); - assert!(eq(&expected, &actual), 1); - let actual = hash_to(&b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_", &b"abcdef0123456789"); - let expected = std::option::extract(&mut deserialize(&x"190d119345b94fbd15497bcba94ecf7db2cbfd1e1fe7da034d26cbba169fb3968288b3fafb265f9ebd380512a71c3f2c121982811d2491fde9ba7ed31ef9ca474f0e1501297f68c298e9f4c0028add35aea8bb83d53c08cfc007c1e005723cd00bb5e7572275c567462d91807de765611490205a941a5a6af3b1691bfe596c31225d3aabdf15faff860cb4ef17c7c3be05571a0f8d3c08d094576981f4a3b8eda0a8e771fcdcc8ecceaf1356a6acf17574518acb506e435b639353c2e14827c8")); - assert!(eq(&expected, &actual), 1); - } - - #[test_only] - const FQ12_ONE_SERIALIZED: vector = x"010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const GT_GENERATOR_SERIALIZED: vector = x"b68917caaa0543a808c53908f694d1b6e7b38de90ce9d83d505ca1ef1b442d2727d7d06831d8b2a7920afc71d8eb50120f17a0ea982a88591d9f43503e94a8f1abaf2e4589f65aafb7923c484540a868883432a5c60e75860b11e5465b1c9a08873ec29e844c1c888cb396933057ffdd541b03a5220eda16b2b3a6728ea678034ce39c6839f20397202d7c5c44bb68134f93193cec215031b17399577a1de5ff1f5b0666bdd8907c61a7651e4e79e0372951505a07fa73c25788db6eb8023519a5aa97b51f1cad1d43d8aabbff4dc319c79a58cafc035218747c2f75daf8f2fb7c00c44da85b129113173d4722f5b201b6b4454062e9ea8ba78c5ca3cadaf7238b47bace5ce561804ae16b8f4b63da4645b8457a93793cbd64a7254f150781019de87ee42682940f3e70a88683d512bb2c3fb7b2434da5dedbb2d0b3fb8487c84da0d5c315bdd69c46fb05d23763f2191aabd5d5c2e12a10b8f002ff681bfd1b2ee0bf619d80d2a795eb22f2aa7b85d5ffb671a70c94809f0dafc5b73ea2fb0657bae23373b4931bc9fa321e8848ef78894e987bff150d7d671aee30b3931ac8c50e0b3b0868effc38bf48cd24b4b811a2995ac2a09122bed9fd9fa0c510a87b10290836ad06c8203397b56a78e9a0c61c77e56ccb4f1bc3d3fcaea7550f3503efe30f2d24f00891cb45620605fcfaa4292687b3a7db7c1c0554a93579e889a121fd8f72649b2402996a084d2381c5043166673b3849e4fd1e7ee4af24aa8ed443f56dfd6b68ffde4435a92cd7a4ac3bc77e1ad0cb728606cf08bf6386e5410f"; - #[test_only] - const GT_GENERATOR_MUL_BY_7_SERIALIZED: vector = x"2041ea7b66c19680e2c0bb23245a71918753220b31f88a925aa9b1e192e7c188a0b365cb994b3ec5e809206117c6411242b940b10caa37ce734496b3b7c63578a0e3c076f9b31a7ca13a716262e0e4cda4ac994efb9e19893cbfe4d464b9210d099d808a08b3c4c3846e7529984899478639c4e6c46152ef49a04af9c8e6ff442d286c4613a3dac6a4bee4b40e1f6b030f2871dabe4223b250c3181ecd3bc6819004745aeb6bac567407f2b9c7d1978c45ee6712ae46930bc00638383f6696158bad488cbe7663d681c96c035481dbcf78e7a7fbaec3799163aa6914cef3365156bdc3e533a7c883d5974e3462ac6f19e3f9ce26800ae248a45c5f0dd3a48a185969224e6cd6af9a048241bdcac9800d94aeee970e08488fb961e36a769b6c185d185b4605dc9808517196bba9d00a3e37bca466c19187486db104ee03962d39fe473e276355618e44c965f05082bb027a7baa4bcc6d8c0775c1e8a481e77df36ddad91e75a982302937f543a11fe71922dcd4f46fe8f951f91cde412b359507f2b3b6df0374bfe55c9a126ad31ce254e67d64194d32d7955ec791c9555ea5a917fc47aba319e909de82da946eb36e12aff936708402228295db2712f2fc807c95092a86afd71220699df13e2d2fdf2857976cb1e605f72f1b2edabadba3ff05501221fe81333c13917c85d725ce92791e115eb0289a5d0b3330901bb8b0ed146abeb81381b7331f1c508fb14e057b05d8b0190a9e74a3d046dcd24e7ab747049945b3d8a120c4f6d88e67661b55573aa9b361367488a1ef7dffd967d64a1518"; - #[test_only] - const GT_GENERATOR_MUL_BY_7_NEG_SERIALIZED: vector = x"2041ea7b66c19680e2c0bb23245a71918753220b31f88a925aa9b1e192e7c188a0b365cb994b3ec5e809206117c6411242b940b10caa37ce734496b3b7c63578a0e3c076f9b31a7ca13a716262e0e4cda4ac994efb9e19893cbfe4d464b9210d099d808a08b3c4c3846e7529984899478639c4e6c46152ef49a04af9c8e6ff442d286c4613a3dac6a4bee4b40e1f6b030f2871dabe4223b250c3181ecd3bc6819004745aeb6bac567407f2b9c7d1978c45ee6712ae46930bc00638383f6696158bad488cbe7663d681c96c035481dbcf78e7a7fbaec3799163aa6914cef3365156bdc3e533a7c883d5974e3462ac6f19e3f9ce26800ae248a45c5f0dd3a48a185969224e6cd6af9a048241bdcac9800d94aeee970e08488fb961e36a769b6c184e92a4b9fa2366b1ae8ebdf5542fa1e0ec390c90df40a91e5261800581b5492bd9640d1c5352babc551d1a49998f4517312f55b4339272b28a3e6b0c7d182e2bb61bd7d72b29ae3696db8fafe32b904ab5d0764e46bf21f9a0c9a1f7bedc6b12b9f64820fc8b3fd4a26541472be3c9c93d784cdd53a059d1604bf3292fedd1babfb00398128e3241bc63a5a47b5e9207fcb0c88f7bfddc376a242c9f0c032ba28eec8670f1fa1d47567593b4571c983b8015df91cfa1241b7fb8a57e0e6e01145b98de017eccc2a66e83ced9d83119a505e552467838d35b8ce2f4d7cc9a894f6dee922f35f0e72b7e96f0879b0c8614d3f9e5f5618b5be9b82381628448641a8bb0fd1dffb16c70e6831d8d69f61f2a2ef9e90c421f7a5b1ce7a5d113c7eb01"; - - #[test(fx = @std)] - fun test_gt(fx: signer) { - enable_cryptography_algebra_natives(&fx); - - // Special constants. - assert!(R_SERIALIZED == order(), 1); - let identity = zero(); - let generator = one(); - - // Serialization/deserialization. - assert!(GT_GENERATOR_SERIALIZED == serialize(&generator), 1); - let generator_from_deser = std::option::extract(&mut deserialize(>_GENERATOR_SERIALIZED)); - assert!(eq(&generator, &generator_from_deser), 1); - assert!(FQ12_ONE_SERIALIZED == serialize(&identity), 1); - let identity_from_deser = std::option::extract(&mut deserialize(&FQ12_ONE_SERIALIZED)); - assert!(eq(&identity, &identity_from_deser), 1); - let element_7g_from_deser = std::option::extract(&mut deserialize(>_GENERATOR_MUL_BY_7_SERIALIZED - )); - assert!(std::option::is_none(&deserialize(&x"ffff")), 1); - - // Deserialization should fail if given an element in Fq12 but not in the prime-order subgroup. - assert!(std::option::is_none(&deserialize(&x"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")), 1); - - // Deserialization should fail if given a byte array of wrong size. - assert!(std::option::is_none(&deserialize(&x"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab")), 1); - - // Element scalar multiplication. - let scalar_7 = from_u64(7); - let element_7g_calc = scalar_mul(&generator, &scalar_7); - assert!(eq(&element_7g_calc, &element_7g_from_deser), 1); - assert!(GT_GENERATOR_MUL_BY_7_SERIALIZED == serialize(&element_7g_calc), 1); - - // Element negation. - let element_minus_7g_calc = neg(&element_7g_calc); - assert!(GT_GENERATOR_MUL_BY_7_NEG_SERIALIZED == serialize(&element_minus_7g_calc), 1); - - // Element addition. - let scalar_9 = from_u64(9); - let element_9g = scalar_mul(&generator, &scalar_9); - let scalar_2 = from_u64(2); - let element_2g = scalar_mul(&generator, &scalar_2); - let element_2g_calc = add(&element_minus_7g_calc, &element_9g); - assert!(eq(&element_2g, &element_2g_calc), 1); - - // Subtraction. - assert!(eq(&element_9g, &sub(&element_2g, &element_minus_7g_calc)), 1); - - // Upcasting to Fq12. - assert!(eq(&one(), &upcast(&identity)), 1); - } - - #[test_only] - use aptos_std::crypto_algebra::{zero, one, from_u64, eq, deserialize, serialize, neg, add, sub, mul, div, inv, rand_insecure, sqr, order, scalar_mul, multi_scalar_mul, double, hash_to, upcast, enable_cryptography_algebra_natives, pairing, multi_pairing, downcast, Element}; - - #[test_only] - const FR_VAL_0_SERIALIZED_LSB: vector = x"0000000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const FR_VAL_1_SERIALIZED_LSB: vector = x"0100000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const FR_VAL_7_SERIALIZED_LSB: vector = x"0700000000000000000000000000000000000000000000000000000000000000"; - #[test_only] - const FR_VAL_7_SERIALIZED_MSB: vector = x"0000000000000000000000000000000000000000000000000000000000000007"; - #[test_only] - const FR_VAL_7_NEG_SERIALIZED_LSB: vector = x"fafffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73"; - - #[test(fx = @std)] - fun test_fr(fx: signer) { - enable_cryptography_algebra_natives(&fx); - - // Constants. - assert!(R_SERIALIZED == order(), 1); - - // Serialization/deserialization. - let val_0 = zero(); - let val_1 = one(); - assert!(FR_VAL_0_SERIALIZED_LSB == serialize(&val_0), 1); - assert!(FR_VAL_1_SERIALIZED_LSB == serialize(&val_1), 1); - let val_7 = from_u64(7); - let val_7_2nd = std::option::extract(&mut deserialize(&FR_VAL_7_SERIALIZED_LSB)); - let val_7_3rd = std::option::extract(&mut deserialize(&FR_VAL_7_SERIALIZED_MSB)); - assert!(eq(&val_7, &val_7_2nd), 1); - assert!(eq(&val_7, &val_7_3rd), 1); - assert!(FR_VAL_7_SERIALIZED_LSB == serialize(&val_7), 1); - assert!(FR_VAL_7_SERIALIZED_MSB == serialize(&val_7), 1); - - // Deserialization should fail if given a byte array of right size but the value is not a member. - assert!(std::option::is_none(&deserialize(&x"01000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73")), 1); - assert!(std::option::is_none(&deserialize(&x"73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")), 1); - - // Deserialization should fail if given a byte array of wrong size. - assert!(std::option::is_none(&deserialize(&x"01000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed7300")), 1); - assert!(std::option::is_none(&deserialize(&x"0073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")), 1); - assert!(std::option::is_none(&deserialize(&x"ffff")), 1); - assert!(std::option::is_none(&deserialize(&x"ffff")), 1); - - // Negation. - let val_minus_7 = neg(&val_7); - assert!(FR_VAL_7_NEG_SERIALIZED_LSB == serialize(&val_minus_7), 1); - - // Addition. - let val_9 = from_u64(9); - let val_2 = from_u64(2); - assert!(eq(&val_2, &add(&val_minus_7, &val_9)), 1); - - // Subtraction. - assert!(eq(&val_9, &sub(&val_2, &val_minus_7)), 1); - - // Multiplication. - let val_63 = from_u64(63); - assert!(eq(&val_63, &mul(&val_7, &val_9)), 1); - - // division. - let val_0 = from_u64(0); - assert!(eq(&val_7, &std::option::extract(&mut div(&val_63, &val_9))), 1); - assert!(std::option::is_none(&div(&val_63, &val_0)), 1); - - // Inversion. - assert!(eq(&val_minus_7, &neg(&val_7)), 1); - assert!(std::option::is_none(&inv(&val_0)), 1); - - // Squaring. - let val_x = rand_insecure(); - assert!(eq(&mul(&val_x, &val_x), &sqr(&val_x)), 1); - } - - #[test(fx = @std)] - fun test_pairing(fx: signer) { - enable_cryptography_algebra_natives(&fx); - - // pairing(a*P,b*Q) == (a*b)*pairing(P,Q) - let element_p = rand_insecure(); - let element_q = rand_insecure(); - let a = rand_insecure(); - let b = rand_insecure(); - let gt_element = pairing(&scalar_mul(&element_p, &a), &scalar_mul(&element_q, &b)); - let gt_element_another = scalar_mul(&pairing(&element_p, &element_q), &mul(&a, &b)); - assert!(eq(>_element, >_element_another), 1); - } - - #[test(fx = @std)] - fun test_multi_pairing(fx: signer) { - enable_cryptography_algebra_natives(&fx); - - // Will compute e(a0*P0,b0*Q0)+e(a1*P1,b1*Q1)+e(a2*P2,b2*Q2). - let a0 = rand_insecure(); - let a1 = rand_insecure(); - let a2 = rand_insecure(); - let element_p0 = rand_insecure(); - let element_p1 = rand_insecure(); - let element_p2 = rand_insecure(); - let p0_a0 = scalar_mul(&element_p0, &a0); - let p1_a1 = scalar_mul(&element_p1, &a1); - let p2_a2 = scalar_mul(&element_p2, &a2); - let b0 = rand_insecure(); - let b1 = rand_insecure(); - let b2 = rand_insecure(); - let element_q0 = rand_insecure(); - let element_q1 = rand_insecure(); - let element_q2 = rand_insecure(); - let q0_b0 = scalar_mul(&element_q0, &b0); - let q1_b1 = scalar_mul(&element_q1, &b1); - let q2_b2 = scalar_mul(&element_q2, &b2); - - // Naive method. - let n0 = pairing(&p0_a0, &q0_b0); - let n1 = pairing(&p1_a1, &q1_b1); - let n2 = pairing(&p2_a2, &q2_b2); - let n = zero(); - n = add(&n, &n0); - n = add(&n, &n1); - n = add(&n, &n2); - - // Efficient API. - let m = multi_pairing(&vector[p0_a0, p1_a1, p2_a2], &vector[q0_b0, q1_b1, q2_b2]); - assert!(eq(&n, &m), 1); - } - - #[test(fx = @std)] - #[expected_failure(abort_code = 0x010002, location = aptos_std::crypto_algebra)] - fun test_multi_pairing_should_abort_when_sizes_mismatch(fx: signer) { - enable_cryptography_algebra_natives(&fx); - let g1_elements = vector[rand_insecure()]; - let g2_elements = vector[rand_insecure(), rand_insecure()]; - multi_pairing(&g1_elements, &g2_elements); - } - - #[test(fx = @std)] - #[expected_failure(abort_code = 0x010002, location = aptos_std::crypto_algebra)] - fun test_multi_scalar_mul_should_abort_when_sizes_mismatch(fx: signer) { - enable_cryptography_algebra_natives(&fx); - let elements = vector[rand_insecure()]; - let scalars = vector[rand_insecure(), rand_insecure()]; - multi_scalar_mul(&elements, &scalars); - } - - #[test_only] - /// The maximum number of `G1` elements that can be created in a transaction, - /// calculated by the current memory limit (1MB) and the in-mem G1 representation size (144 bytes per element). - const G1_NUM_MAX: u64 = 1048576 / 144; - - #[test(fx = @std)] - fun test_memory_limit(fx: signer) { - enable_cryptography_algebra_natives(&fx); - let remaining = G1_NUM_MAX; - while (remaining > 0) { - zero(); - remaining = remaining - 1; - } - } - - #[test(fx = @std)] - #[expected_failure(abort_code = 0x090003, location = std::crypto_algebra)] - fun test_memory_limit_exceeded_with_g1(fx: signer) { - enable_cryptography_algebra_natives(&fx); - let remaining = G1_NUM_MAX + 1; - while (remaining > 0) { - zero(); - remaining = remaining - 1; - } - } - - // - // (Tests end here.) - // -} diff --git a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs index 045a27c1a664a2..e425ba72f45bdd 100644 --- a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs +++ b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs @@ -636,7 +636,6 @@ pub enum EntryFunctionCall { /// Initialize the validator account and give ownership to the signing account. StakeInitializeValidator { consensus_pubkey: Vec, - proof_of_possession: Vec, network_addresses: Vec, fullnode_addresses: Vec, }, @@ -665,7 +664,6 @@ pub enum EntryFunctionCall { StakeRotateConsensusKey { pool_address: AccountAddress, new_consensus_pubkey: Vec, - proof_of_possession: Vec, }, /// Allows an owner to change the delegated voter of the stake pool. @@ -1291,25 +1289,18 @@ impl EntryFunctionCall { } => stake_initialize_stake_owner(initial_stake_amount, operator, voter), StakeInitializeValidator { consensus_pubkey, - proof_of_possession, network_addresses, fullnode_addresses, - } => stake_initialize_validator( - consensus_pubkey, - proof_of_possession, - network_addresses, - fullnode_addresses, - ), + } => { + stake_initialize_validator(consensus_pubkey, network_addresses, fullnode_addresses) + }, StakeJoinValidatorSet { pool_address } => stake_join_validator_set(pool_address), StakeLeaveValidatorSet { pool_address } => stake_leave_validator_set(pool_address), StakeReactivateStake { amount } => stake_reactivate_stake(amount), StakeRotateConsensusKey { pool_address, new_consensus_pubkey, - proof_of_possession, - } => { - stake_rotate_consensus_key(pool_address, new_consensus_pubkey, proof_of_possession) - }, + } => stake_rotate_consensus_key(pool_address, new_consensus_pubkey), StakeSetDelegatedVoter { new_voter } => stake_set_delegated_voter(new_voter), StakeSetOperator { new_operator } => stake_set_operator(new_operator), StakeUnlock { amount } => stake_unlock(amount), @@ -3146,7 +3137,6 @@ pub fn stake_initialize_stake_owner( /// Initialize the validator account and give ownership to the signing account. pub fn stake_initialize_validator( consensus_pubkey: Vec, - proof_of_possession: Vec, network_addresses: Vec, fullnode_addresses: Vec, ) -> TransactionPayload { @@ -3162,7 +3152,6 @@ pub fn stake_initialize_validator( vec![], vec![ bcs::to_bytes(&consensus_pubkey).unwrap(), - bcs::to_bytes(&proof_of_possession).unwrap(), bcs::to_bytes(&network_addresses).unwrap(), bcs::to_bytes(&fullnode_addresses).unwrap(), ], @@ -3226,7 +3215,6 @@ pub fn stake_reactivate_stake(amount: u64) -> TransactionPayload { pub fn stake_rotate_consensus_key( pool_address: AccountAddress, new_consensus_pubkey: Vec, - proof_of_possession: Vec, ) -> TransactionPayload { TransactionPayload::EntryFunction(EntryFunction::new( ModuleId::new( @@ -3241,7 +3229,6 @@ pub fn stake_rotate_consensus_key( vec![ bcs::to_bytes(&pool_address).unwrap(), bcs::to_bytes(&new_consensus_pubkey).unwrap(), - bcs::to_bytes(&proof_of_possession).unwrap(), ], )) } @@ -5047,9 +5034,8 @@ mod decoder { if let TransactionPayload::EntryFunction(script) = payload { Some(EntryFunctionCall::StakeInitializeValidator { consensus_pubkey: bcs::from_bytes(script.args().get(0)?).ok()?, - proof_of_possession: bcs::from_bytes(script.args().get(1)?).ok()?, - network_addresses: bcs::from_bytes(script.args().get(2)?).ok()?, - fullnode_addresses: bcs::from_bytes(script.args().get(3)?).ok()?, + network_addresses: bcs::from_bytes(script.args().get(1)?).ok()?, + fullnode_addresses: bcs::from_bytes(script.args().get(2)?).ok()?, }) } else { None @@ -5091,7 +5077,6 @@ mod decoder { Some(EntryFunctionCall::StakeRotateConsensusKey { pool_address: bcs::from_bytes(script.args().get(0)?).ok()?, new_consensus_pubkey: bcs::from_bytes(script.args().get(1)?).ok()?, - proof_of_possession: bcs::from_bytes(script.args().get(2)?).ok()?, }) } else { None diff --git a/aptos-move/framework/src/natives/cryptography/bls12381.rs b/aptos-move/framework/src/natives/cryptography/bls12381.rs deleted file mode 100644 index 891b7a51991f80..00000000000000 --- a/aptos-move/framework/src/natives/cryptography/bls12381.rs +++ /dev/null @@ -1,708 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use aptos_crypto::{bls12381, traits}; -#[cfg(feature = "testing")] -use aptos_crypto::{ - bls12381::{PrivateKey, ProofOfPossession, PublicKey}, - test_utils::KeyPair, - SigningKey, Uniform, -}; -use aptos_gas_schedule::gas_params::natives::aptos_framework::*; -use aptos_native_interface::{ - safely_pop_arg, safely_pop_vec_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, - SafeNativeResult, -}; -use move_binary_format::errors::PartialVMError; -use move_core_types::{ - gas_algebra::{InternalGas, InternalGasPerArg, InternalGasPerByte, NumArgs, NumBytes}, - vm_status::StatusCode, -}; -use move_vm_runtime::native_functions::NativeFunction; -use move_vm_types::{ - loaded_data::runtime_types::Type, - values::{Struct, Value}, -}; -#[cfg(feature = "testing")] -use rand_core::OsRng; -use smallvec::{smallvec, SmallVec}; -use std::{collections::VecDeque, convert::TryFrom}; - -/// Pops a `Vec` off the argument stack and converts it to a `Vec>` by reading the first -/// field of `T`, which is a `Vec` field named `bytes`. -fn pop_as_vec_of_vec_u8(arguments: &mut VecDeque) -> SafeNativeResult>> { - let structs = safely_pop_vec_arg!(arguments, Struct); - let mut v = Vec::with_capacity(structs.len()); - - for s in structs { - let field = s - .unpack()? - .next() - .ok_or_else(|| PartialVMError::new(StatusCode::INTERNAL_TYPE_ERROR))?; - - v.push(field.value_as::>()?); - } - - Ok(v) -} - -#[derive(Debug, Clone)] -pub struct GasParameters { - pub base: InternalGas, - - pub per_pubkey_deserialize: InternalGasPerArg, - pub per_pubkey_aggregate: InternalGasPerArg, - pub per_pubkey_subgroup_check: InternalGasPerArg, - - pub per_sig_deserialize: InternalGasPerArg, - pub per_sig_aggregate: InternalGasPerArg, - pub per_sig_subgroup_check: InternalGasPerArg, - - pub per_sig_verify: InternalGasPerArg, - pub per_pop_verify: InternalGasPerArg, - - pub per_pairing: InternalGasPerArg, // a size-n BLS aggregate signature requires n+1 pairings - - pub per_msg_hashing: InternalGasPerArg, - pub per_byte_hashing: InternalGasPerByte, // signature verification involves signing |msg| bytes -} - -/// Deserializes a vector of PK bytes into bls12381::PublicKey structs. -fn bls12381_deserialize_pks( - pks_serialized: Vec>, - context: &mut SafeNativeContext, -) -> SafeNativeResult> { - let mut pks = vec![]; - - for pk_bytes in pks_serialized { - let pk = match bls12381_deserialize_pk(pk_bytes, context)? { - Some(key) => key, - // If PK does not deserialize correctly, break early - None => break, - }; - - pks.push(pk); - } - - Ok(pks) -} - -/// Deserializes a sequence of bytes into bls12381::PublicKey struct. -fn bls12381_deserialize_pk( - pk_bytes: Vec, - context: &mut SafeNativeContext, -) -> SafeNativeResult> { - context.charge(BLS12381_PER_PUBKEY_DESERIALIZE * NumArgs::one())?; - - match bls12381::PublicKey::try_from(&pk_bytes[..]) { - Ok(key) => Ok(Some(key)), - // If PK does not deserialize correctly, return None - Err(_) => Ok(None), - } -} - -/// Deserializes a vector of signature bytes into bls12381::Signature structs. -fn bls12381_deserialize_sigs( - sigs_serialized: Vec>, - context: &mut SafeNativeContext, -) -> SafeNativeResult> { - let mut sigs = vec![]; - - for sig_bytes in sigs_serialized { - let sig = match bls12381_deserialize_sig(sig_bytes, context)? { - Some(sig) => sig, - // If sig does not deserialize correctly, break early - None => break, - }; - - sigs.push(sig); - } - - Ok(sigs) -} - -/// Deserializes a sequence of bytes into bls12381::Signature struct. -fn bls12381_deserialize_sig( - sig_bytes: Vec, - context: &mut SafeNativeContext, -) -> SafeNativeResult> { - context.charge(BLS12381_PER_SIG_DESERIALIZE * NumArgs::one())?; - - match bls12381::Signature::try_from(&sig_bytes[..]) { - Ok(sig) => Ok(Some(sig)), - // If PK does not deserialize correctly, return None - Err(_) => Ok(None), - } -} - -/// Deserializes a sequence of bytes into bls12381::Signature struct. -fn bls12381_deserialize_pop( - pop_bytes: Vec, - context: &mut SafeNativeContext, -) -> SafeNativeResult> { - context.charge(BLS12381_PER_SIG_DESERIALIZE * NumArgs::one())?; - - match bls12381::ProofOfPossession::try_from(&pop_bytes[..]) { - Ok(pop) => Ok(Some(pop)), - // If PK does not deserialize correctly, break early - Err(_) => Ok(None), - } -} - -/// Checks prime-order subgroup membership on a bls12381::PublicKey struct. -fn bls12381_pk_subgroub_check( - pk: &bls12381::PublicKey, - context: &mut SafeNativeContext, -) -> SafeNativeResult { - // NOTE(Gas): constant-time; around 39 microseconds on Apple M1 - context.charge(BLS12381_PER_PUBKEY_DESERIALIZE * NumArgs::one())?; - - Ok(pk.subgroup_check().is_ok()) -} - -/// Checks prime-order subgroup membership on a bls12381::Signature struct. -fn bls12381_sig_subgroub_check( - sig: &bls12381::Signature, - context: &mut SafeNativeContext, -) -> SafeNativeResult { - context.charge(BLS12381_PER_SIG_SUBGROUP_CHECK * NumArgs::one())?; - - Ok(sig.subgroup_check().is_ok()) -} - -/// Verifies a signature on an arbitrary message. -fn signature_verify( - sig: &S, - pk: &S::VerifyingKeyMaterial, - msg: Vec, - context: &mut SafeNativeContext, -) -> SafeNativeResult { - // NOTE(Gas): 2 bilinear pairings and a hash-to-curve - context.charge( - BLS12381_PER_SIG_VERIFY * NumArgs::one() - + BLS12381_PER_MSG_HASHING * NumArgs::one() - + BLS12381_PER_BYTE_HASHING * NumBytes::new(msg.len() as u64), - )?; - - Ok(sig.verify_arbitrary_msg(&msg[..], pk).is_ok()) -} - -/// This is a helper function called by our `bls12381_verify_*` functions for: -/// * normal (non-aggregated) signatures, -/// * signature shares (in the multisignature scheme & the aggregate signature scheme) -/// * multisignatures -/// -/// Gas cost: base_cost + per_pubkey_deserialize_cost -/// +? ( per_pubkey_subgroup_check_cost * check_pk_subgroup -/// +? ( per_sig_deserialize_cost -/// +? ( per_sig_verify_cost + per_msg_hashing_cost -/// + per_byte_hashing_cost * |msg| ) ) ) -/// -/// where +? indicates that the expression stops evaluating there if the previous gas-charging step -/// failed. -pub fn bls12381_verify_signature_helper( - context: &mut SafeNativeContext, - _ty_args: Vec, - mut arguments: VecDeque, - check_pk_subgroup: bool, -) -> SafeNativeResult> { - debug_assert!(_ty_args.is_empty()); - debug_assert!(arguments.len() == 3); - - context.charge(BLS12381_BASE)?; - - let msg_bytes = safely_pop_arg!(arguments, Vec); - let aggpk_bytes = safely_pop_arg!(arguments, Vec); - let multisig_bytes = safely_pop_arg!(arguments, Vec); - - let pk = match bls12381_deserialize_pk(aggpk_bytes, context)? { - Some(pk) => pk, - None => { - return Ok(smallvec![Value::bool(false)]); - }, - }; - - if check_pk_subgroup && !bls12381_pk_subgroub_check(&pk, context)? { - return Ok(smallvec![Value::bool(false)]); - } - - let sig = match bls12381_deserialize_sig(multisig_bytes, context)? { - Some(sig) => sig, - None => { - return Ok(smallvec![Value::bool(false)]); - }, - }; - - let verify_result = signature_verify(&sig, &pk, msg_bytes, context)?; - - Ok(smallvec![Value::bool(verify_result)]) -} - -/*************************************************************************************************** - * native fun bls12381_aggregate_pop_verified_pubkeys - * - * gas cost: base_cost + per_pubkey_deserialize_cost * min(num_validatable_pubkeys + 1, num_pubkeys) - * +? per_pubkey_aggregate_cost * num_pubkeys - * - * where +? indicates that the expression stops evaluating there if the previous gas-charging step - * failed, num_pubkeys is the # of public keys given as input, and num_validatable_pubkeys is the - * # of public keys that deserialize successfully. - * - * NOTE(ValidatablePK): We refer to the public keys that deserialize correctly as "validatable" - * above, since successful deserialization is not a sufficient criteria for the "validatability" - * of a PK: e.g., the PK could still be susceptible to small-subgroup attacks or rogue-key attacks. - * - * NOTE: If all PKs deserialize, then per_pubkey_deserialize_cost is charged num_pubkeys times. - * Otherwise, if only num_validatable_pubkeys deserialize correctly, an extra per_pubkey_deserialize_cost - * must be charged for the failed deserialization. - **************************************************************************************************/ -fn native_bls12381_aggregate_pubkeys( - context: &mut SafeNativeContext, - _ty_args: Vec, - mut arguments: VecDeque, -) -> SafeNativeResult> { - debug_assert!(_ty_args.is_empty()); - debug_assert!(arguments.len() == 1); - - // Parses a Vec> of all serialized public keys - let pks_bytes = pop_as_vec_of_vec_u8(&mut arguments)?; - let num_pks = pks_bytes.len(); - - context.charge(BLS12381_BASE)?; - - // If zero PKs were given as input, return None. - if pks_bytes.is_empty() { - return Ok(smallvec![Value::vector_u8(vec![]), Value::bool(false)]); - } - - let pks = bls12381_deserialize_pks(pks_bytes, context)?; - debug_assert!(pks.len() <= num_pks); - - // If not all PKs were successfully deserialized, return None and only charge for the actual work done - if pks.len() != num_pks { - return Ok(smallvec![Value::vector_u8(vec![]), Value::bool(false)]); - } - - // Aggregate the public keys (this will NOT subgroup-check the individual PKs) - // NOTE(Gas): |pks| elliptic curve additions - context.charge(BLS12381_PER_PUBKEY_AGGREGATE * NumArgs::new(num_pks as u64))?; - let aggpk = - match bls12381::PublicKey::aggregate(pks.iter().collect::>()) { - Ok(aggpk) => aggpk, - Err(_) => return Ok(smallvec![Value::vector_u8(vec![]), Value::bool(false)]), - }; - - Ok(smallvec![ - Value::vector_u8(aggpk.to_bytes().to_vec()), - Value::bool(true) - ]) -} - -/*************************************************************************************************** - * native fun bls12381_aggregate_signatures - * - * gas cost: base_cost + num_viable_sigs * per_sig_deserialize_cost - * +? num_sigs * per_sig_aggregate_cost - * - * where +? indicates that the expression stops evaluating there if the previous gas-charging step - * failed - * - * NOTE(ViableSig): We refer to the signatures that deserialize correctly as "viable" above, since - * successful deserialization is not a sufficient criteria for the "viability" of a signature: e.g., - * the signature might not verify under the desired (message, public key) pair, or the signature - * could lie in a small-order subgroup. - **************************************************************************************************/ -pub fn native_bls12381_aggregate_signatures( - context: &mut SafeNativeContext, - _ty_args: Vec, - mut arguments: VecDeque, -) -> SafeNativeResult> { - debug_assert!(_ty_args.is_empty()); - debug_assert!(arguments.len() == 1); - - // Parses a Vec> of all serialized signatures - let sigs_serialized = pop_as_vec_of_vec_u8(&mut arguments)?; - let num_sigs = sigs_serialized.len(); - - context.charge(BLS12381_BASE)?; - - // If zero signatures were given as input, return None. - if sigs_serialized.is_empty() { - return Ok(smallvec![Value::vector_u8(vec![]), Value::bool(false)]); - } - - let sigs = bls12381_deserialize_sigs(sigs_serialized, context)?; - - if sigs.len() != num_sigs { - return Ok(smallvec![Value::vector_u8(vec![]), Value::bool(false)]); - } - - // Aggregate the signatures (this will NOT group-check the individual signatures) - // NOTE(Gas): |sigs| elliptic curve additions - context.charge(BLS12381_PER_SIG_AGGREGATE * NumArgs::new(sigs.len() as u64))?; - let aggsig = match bls12381::Signature::aggregate(sigs) { - Ok(aggsig) => aggsig, - Err(_) => return Ok(smallvec![Value::vector_u8(vec![]), Value::bool(false)]), - }; - - Ok(smallvec![ - Value::vector_u8(aggsig.to_bytes().to_vec()), - Value::bool(true) - ]) -} - -/*************************************************************************************************** - * native fun bls12381_signature_subgroup_check - * - * gas cost: base_cost + per_sig_deserialize_cost +? per_sig_subgroup_check_cost - * - * where +? indicates that the expression stops evaluating there if the previous gas-charging step - * failed - **************************************************************************************************/ -pub fn native_bls12381_signature_subgroup_check( - context: &mut SafeNativeContext, - _ty_args: Vec, - mut arguments: VecDeque, -) -> SafeNativeResult> { - debug_assert!(_ty_args.is_empty()); - debug_assert!(arguments.len() == 1); - - context.charge(BLS12381_BASE)?; - - let sig_bytes = safely_pop_arg!(arguments, Vec); - - let sig = match bls12381_deserialize_sig(sig_bytes, context)? { - Some(key) => key, - None => return Ok(smallvec![Value::bool(false)]), - }; - - let valid = bls12381_sig_subgroub_check(&sig, context)?; - - Ok(smallvec![Value::bool(valid)]) -} - -/*************************************************************************************************** - * native fun bls12381_validate_pubkey - * - * gas cost: base_cost + per_pubkey_deserialize_cost +? per_pubkey_subgroup_check_cost - * - * where +? indicates that the expression stops evaluating there if the previous gas-charging step - * failed - **************************************************************************************************/ -fn native_bls12381_validate_pubkey( - context: &mut SafeNativeContext, - _ty_args: Vec, - mut arguments: VecDeque, -) -> SafeNativeResult> { - debug_assert!(_ty_args.is_empty()); - debug_assert!(arguments.len() == 1); - - context.charge(BLS12381_BASE)?; - - let pk_bytes = safely_pop_arg!(arguments, Vec); - - let pk = match bls12381_deserialize_pk(pk_bytes, context)? { - Some(key) => key, - None => return Ok(smallvec![Value::bool(false)]), - }; - - let valid = bls12381_pk_subgroub_check(&pk, context)?; - - Ok(smallvec![Value::bool(valid)]) -} - -/*************************************************************************************************** -* native fun native_bls12381_verify_aggregate_signature -* -* gas cost: base_cost + per_pubkey_deserialize_cost * min(num_validatable_pubkeys + 1, num_pubkeys) -* +? ( per_sig_deserialize_cost * min(num_viable_sigs + 1, num_sigs) -* +? ( per_pairing_cost + per_msg_hashing_cost ) * num_msgs -* + per_byte_hashing_cost * total_msg_bytes ) -* -* where: -* +? indicates the expression stops evaluating there if the previous gas-charging step failed, -* num_pubkeys is the # of public keys given as input, -* num_validatable_pubkeys is the # of public keys that deserialize successfully (i.e., "validatable"), -* num_sigs is the # of signatures given as input, -* num_viable_sigs is the # of signatures that deserialize successfully (i.e., "viable"), -* total_msg_bytes is the cumulative size in bytes of all messages. -* -* NOTE(ValidatablePK): We refer to the public keys that deserialize correctly as "validatable" -* above, since successful deserialization is not a sufficient criteria for the "validatability" -* of a PK: e.g., the PK could still be susceptible to small-subgroup attacks or rogue-key attacks. -* -* NOTE(ViableSig): We refer to the signatures that deserialize correctly as "viable" above, since -* successful deserialization is not a sufficient criteria for the "viability" of a signature: e.g., -* the signature might not verify under the desired (message, public key) pair, or the signature -* could lie in a small-order subgroup. - -* NOTE: If all PKs deserialize, then per_pubkey_deserialize_cost is charged num_pubkeys times. -* Otherwise, if only num_validatable_pubkeys deserialize correctly, an extra per_pubkey_deserialize_cost -* must be charged for the failed deserialization. We proceed similarly for per_sig_deserialize_cost. -**************************************************************************************************/ -pub fn native_bls12381_verify_aggregate_signature( - context: &mut SafeNativeContext, - _ty_args: Vec, - mut arguments: VecDeque, -) -> SafeNativeResult> { - debug_assert!(_ty_args.is_empty()); - debug_assert!(arguments.len() == 3); - - context.charge(BLS12381_BASE)?; - - // Parses a Vec> of all messages - let messages = safely_pop_vec_arg!(arguments, Vec); - // Parses a Vec> of all serialized public keys - let pks_serialized = pop_as_vec_of_vec_u8(&mut arguments)?; - let num_pks = pks_serialized.len(); - - // Parses the signature as a Vec - let aggsig_bytes = safely_pop_arg!(arguments, Vec); - - // Number of messages must match number of public keys - if pks_serialized.len() != messages.len() { - return Ok(smallvec![Value::bool(false)]); - } - - let pks = bls12381_deserialize_pks(pks_serialized, context)?; - debug_assert!(pks.len() <= num_pks); - - // If less PKs than expected were deserialized, return None. - if pks.len() != num_pks { - return Ok(smallvec![Value::bool(false)]); - } - - let aggsig = match bls12381_deserialize_sig(aggsig_bytes, context)? { - Some(aggsig) => aggsig, - None => return Ok(smallvec![Value::bool(false)]), - }; - - let msgs_refs = messages - .iter() - .map(|m| m.as_slice()) - .collect::>(); - let pks_refs = pks.iter().collect::>(); - - // The cost of verifying a size-n aggregate signatures involves n+1 parings and hashing all - // the messages to elliptic curve points (proportional to sum of all message lengths). - context.charge( - BLS12381_PER_PAIRING * NumArgs::new((messages.len() + 1) as u64) - + BLS12381_PER_MSG_HASHING * NumArgs::new(messages.len() as u64) - + BLS12381_PER_BYTE_HASHING - * messages.iter().fold(NumBytes::new(0), |sum, msg| { - sum + NumBytes::new(msg.len() as u64) - }), - )?; - - let verify_result = aggsig - .verify_aggregate_arbitrary_msg(&msgs_refs, &pks_refs) - .is_ok(); - - Ok(smallvec![Value::bool(verify_result)]) -} - -/*************************************************************************************************** - * native fun bls12381_verify_multisignature - * - * gas cost: base_cost + per_pubkey_deserialize_cost - * +? ( per_sig_deserialize_cost - * +? ( per_sig_verify_cost + per_msg_hashing_cost - * + per_byte_hashing_cost * |msg| ) ) - * - * where +? indicates that the expression stops evaluating there if the previous gas-charging step - * failed - **************************************************************************************************/ -pub fn native_bls12381_verify_multisignature( - context: &mut SafeNativeContext, - _ty_args: Vec, - arguments: VecDeque, -) -> SafeNativeResult> { - let check_pk_subgroup = false; - bls12381_verify_signature_helper(context, _ty_args, arguments, check_pk_subgroup) -} - -/*************************************************************************************************** - * native fun bls12381_verify_normal_signature - * - * gas cost: base_cost + per_pubkey_deserialize_cost - * +? ( per_sig_deserialize_cost - * +? ( per_pubkey_subgroup_check_cost - * +? ( per_sig_verify_cost + per_msg_hashing_cost - * + per_byte_hashing_cost * |msg| ) ) ) - * - * where +? indicates that the expression stops evaluating there if the previous gas-charging step - * failed - **************************************************************************************************/ -pub fn native_bls12381_verify_normal_signature( - context: &mut SafeNativeContext, - _ty_args: Vec, - arguments: VecDeque, -) -> SafeNativeResult> { - // For normal (non-aggregated) signatures, PK's typically don't come with PoPs and the caller - // might forget to check prime-order subgroup membership of the PK. Therefore, we always enforce - // it here. - let check_pk_subgroup = true; - bls12381_verify_signature_helper(context, _ty_args, arguments, check_pk_subgroup) -} - -/*************************************************************************************************** - * native fun bls12381_verify_proof_of_possession - * - * gas cost: base_cost + per_pubkey_deserialize_cost - * +? ( per_sig_deserialize_cost - * +? per_pop_verify_cost ) - * - * where +? indicates that the expression stops evaluating there if the previous gas-charging step - * failed - **************************************************************************************************/ -fn native_bls12381_verify_proof_of_possession( - context: &mut SafeNativeContext, - _ty_args: Vec, - mut arguments: VecDeque, -) -> SafeNativeResult> { - debug_assert!(_ty_args.is_empty()); - debug_assert!(arguments.len() == 2); - - context.charge(BLS12381_BASE)?; - - let pop_bytes = safely_pop_arg!(arguments, Vec); - let key_bytes = safely_pop_arg!(arguments, Vec); - - let pk = match bls12381_deserialize_pk(key_bytes, context)? { - Some(pk) => pk, - None => return Ok(smallvec![Value::bool(false)]), - }; - - let pop = match bls12381_deserialize_pop(pop_bytes, context)? { - Some(pop) => pop, - None => return Ok(smallvec![Value::bool(false)]), - }; - - // NOTE(Gas): 2 bilinear pairings and a hash-to-curve - context.charge(BLS12381_PER_POP_VERIFY * NumArgs::one())?; - let valid = pop.verify(&pk).is_ok(); - - Ok(smallvec![Value::bool(valid)]) -} - -/*************************************************************************************************** - * native fun bls12381_verify_signature_share - * - * gas cost: base_cost + per_pubkey_deserialize_cost - * +? ( per_sig_deserialize_cost - * +? ( per_sig_verify_cost + per_msg_hashing_cost - * + per_byte_hashing_cost * |msg| ) ) - * - * where +? indicates that the expression stops evaluating there if the previous gas-charging step - * failed - **************************************************************************************************/ -pub fn native_bls12381_verify_signature_share( - context: &mut SafeNativeContext, - _ty_args: Vec, - arguments: VecDeque, -) -> SafeNativeResult> { - // For signature shares, the caller is REQUIRED to check the PK's PoP, and thus the PK is in the - // prime-order subgroup. - let check_pk_subgroup = false; - bls12381_verify_signature_helper(context, _ty_args, arguments, check_pk_subgroup) -} - -#[cfg(feature = "testing")] -pub fn native_generate_keys( - _context: &mut SafeNativeContext, - _ty_args: Vec, - mut _arguments: VecDeque, -) -> SafeNativeResult> { - let key_pair = KeyPair::::generate(&mut OsRng); - Ok(smallvec![ - Value::vector_u8(key_pair.private_key.to_bytes()), - Value::vector_u8(key_pair.public_key.to_bytes()), - ]) -} - -#[cfg(feature = "testing")] -pub fn native_sign( - _context: &mut SafeNativeContext, - _ty_args: Vec, - mut arguments: VecDeque, -) -> SafeNativeResult> { - let msg = safely_pop_arg!(arguments, Vec); - let sk_bytes = safely_pop_arg!(arguments, Vec); - let sk = PrivateKey::try_from(sk_bytes.as_slice()).unwrap(); - let sig = sk.sign_arbitrary_message(msg.as_slice()); - Ok(smallvec![Value::vector_u8(sig.to_bytes()),]) -} - -#[cfg(feature = "testing")] -pub fn native_generate_proof_of_possession( - _context: &mut SafeNativeContext, - _ty_args: Vec, - mut arguments: VecDeque, -) -> SafeNativeResult> { - let sk_bytes = safely_pop_arg!(arguments, Vec); - let sk = PrivateKey::try_from(sk_bytes.as_slice()).unwrap(); - let pop = ProofOfPossession::create(&sk); - Ok(smallvec![Value::vector_u8(pop.to_bytes()),]) -} - -/*************************************************************************************************** - * module - * - **************************************************************************************************/ -pub fn make_all( - builder: &SafeNativeBuilder, -) -> impl Iterator + '_ { - let mut natives = vec![]; - - natives.extend([ - // BLS over BLS12-381 - ( - "aggregate_pubkeys_internal", - native_bls12381_aggregate_pubkeys as RawSafeNative, - ), - ( - "aggregate_signatures_internal", - native_bls12381_aggregate_signatures, - ), - ( - "signature_subgroup_check_internal", - native_bls12381_signature_subgroup_check, - ), - ("validate_pubkey_internal", native_bls12381_validate_pubkey), - ( - "verify_aggregate_signature_internal", - native_bls12381_verify_aggregate_signature, - ), - ( - "verify_multisignature_internal", - native_bls12381_verify_multisignature, - ), - ( - "verify_normal_signature_internal", - native_bls12381_verify_normal_signature, - ), - ( - "verify_proof_of_possession_internal", - native_bls12381_verify_proof_of_possession, - ), - ( - "verify_signature_share_internal", - native_bls12381_verify_signature_share, - ), - ]); - - #[cfg(feature = "testing")] - natives.append(&mut vec![ - ( - "generate_keys_internal", - native_generate_keys as RawSafeNative, - ), - ("sign_internal", native_sign), - ( - "generate_proof_of_possession_internal", - native_generate_proof_of_possession, - ), - ]); - - builder.make_named_natives(natives) -} diff --git a/aptos-move/framework/src/natives/cryptography/mod.rs b/aptos-move/framework/src/natives/cryptography/mod.rs index d16f05f35ee607..ea32c99a4683a7 100644 --- a/aptos-move/framework/src/natives/cryptography/mod.rs +++ b/aptos-move/framework/src/natives/cryptography/mod.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 pub mod algebra; -pub mod bls12381; pub mod bulletproofs; pub mod ed25519; mod helpers; diff --git a/aptos-move/framework/src/natives/mod.rs b/aptos-move/framework/src/natives/mod.rs index 408b9f660c11d8..54e6d1eb390d22 100644 --- a/aptos-move/framework/src/natives/mod.rs +++ b/aptos-move/framework/src/natives/mod.rs @@ -52,7 +52,6 @@ pub fn all_natives( add_natives_from_module!("crypto_algebra", cryptography::algebra::make_all(builder)); add_natives_from_module!("genesis", create_signer::make_all(builder)); add_natives_from_module!("multi_ed25519", multi_ed25519::make_all(builder)); - add_natives_from_module!("bls12381", cryptography::bls12381::make_all(builder)); add_natives_from_module!("secp256k1", cryptography::secp256k1::make_all(builder)); add_natives_from_module!("aptos_hash", hash::make_all(builder)); add_natives_from_module!( diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 31fa3486a4f22a..175fc6294763e4 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -8,7 +8,7 @@ mod genesis_context; use crate::genesis_context::GenesisStateView; use aptos_crypto::{ - bls12381, + ed25519, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, HashValue, PrivateKey, Uniform, }; @@ -798,10 +798,8 @@ pub struct Validator { /// Amount to stake for consensus. Also the intial amount minted to the owner account. pub stake_amount: u64, - /// bls12381 public key used to sign consensus messages. + /// ed25519 public key used to sign consensus messages. pub consensus_pubkey: Vec, - /// Proof of Possession of the consensus pubkey. - pub proof_of_possession: Vec, /// `NetworkAddress` for the validator. pub network_addresses: Vec, /// `NetworkAddress` for the validator's full node. @@ -810,7 +808,7 @@ pub struct Validator { pub struct TestValidator { pub key: Ed25519PrivateKey, - pub consensus_key: bls12381::PrivateKey, + pub consensus_key: ed25519::PrivateKey, pub data: Validator, } @@ -826,11 +824,8 @@ impl TestValidator { let key = Ed25519PrivateKey::generate(rng); let auth_key = AuthenticationKey::ed25519(&key.public_key()); let owner_address = auth_key.account_address(); - let consensus_key = bls12381::PrivateKey::generate(rng); + let consensus_key = ed25519::PrivateKey::generate(rng); let consensus_pubkey = consensus_key.public_key().to_bytes().to_vec(); - let proof_of_possession = bls12381::ProofOfPossession::create(&consensus_key) - .to_bytes() - .to_vec(); let network_address = [0u8; 0].to_vec(); let full_node_network_address = [0u8; 0].to_vec(); @@ -842,7 +837,6 @@ impl TestValidator { let data = Validator { owner_address, consensus_pubkey, - proof_of_possession, operator_address: owner_address, voter_address: owner_address, network_addresses: network_address, diff --git a/config/src/config/identity_config.rs b/config/src/config/identity_config.rs index 0d2142574d8340..01fe1297cbaf9a 100644 --- a/config/src/config/identity_config.rs +++ b/config/src/config/identity_config.rs @@ -3,7 +3,7 @@ use crate::{config::SecureBackend, keys::ConfigKey}; use aptos_crypto::{ - bls12381, + ed25519, ed25519::Ed25519PrivateKey, x25519::{self, PRIVATE_KEY_SIZE}, ValidCryptoMaterial, @@ -29,7 +29,7 @@ pub struct IdentityBlob { pub account_private_key: Option, /// Optional consensus key. Only used for validators #[serde(skip_serializing_if = "Option::is_none")] - pub consensus_private_key: Option, + pub consensus_private_key: Option, /// Network private key. Peer id is derived from this if account address is not present pub network_private_key: x25519::PrivateKey, } diff --git a/config/src/config/safety_rules_config.rs b/config/src/config/safety_rules_config.rs index e5e19db1c17e5d..ca675e3e15ee59 100644 --- a/config/src/config/safety_rules_config.rs +++ b/config/src/config/safety_rules_config.rs @@ -12,7 +12,7 @@ use crate::{ keys::ConfigKey, }; use anyhow::bail; -use aptos_crypto::{bls12381, Uniform}; +use aptos_crypto::{ed25519, Uniform}; use aptos_types::{chain_id::ChainId, network_address::NetworkAddress, waypoint::Waypoint, PeerId}; use rand::rngs::StdRng; use serde::{Deserialize, Serialize}; @@ -203,7 +203,7 @@ impl RemoteService { #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] pub struct SafetyRulesTestConfig { pub author: PeerId, - pub consensus_key: Option>, + pub consensus_key: Option>, pub waypoint: Option, } @@ -216,13 +216,13 @@ impl SafetyRulesTestConfig { } } - pub fn consensus_key(&mut self, key: bls12381::PrivateKey) { + pub fn consensus_key(&mut self, key: ed25519::PrivateKey) { self.consensus_key = Some(ConfigKey::new(key)); } pub fn random_consensus_key(&mut self, rng: &mut StdRng) { - let privkey = bls12381::PrivateKey::generate(rng); - self.consensus_key = Some(ConfigKey::::new(privkey)); + let privkey = ed25519::PrivateKey::generate(rng); + self.consensus_key = Some(ConfigKey::::new(privkey)); } } diff --git a/consensus/consensus-types/src/block.rs b/consensus/consensus-types/src/block.rs index 392eb2b277f5a5..0ea1d38b023a10 100644 --- a/consensus/consensus-types/src/block.rs +++ b/consensus/consensus-types/src/block.rs @@ -9,7 +9,7 @@ use crate::{ }; use anyhow::{bail, ensure, format_err}; use aptos_bitvec::BitVec; -use aptos_crypto::{bls12381, hash::CryptoHash, HashValue}; +use aptos_crypto::{ed25519, hash::CryptoHash, HashValue}; use aptos_infallible::duration_since_epoch; use aptos_types::{ account_address::AccountAddress, @@ -51,7 +51,7 @@ pub struct Block { block_data: BlockData, /// Signature that the hash of this block has been authored by the owner of the private key, /// this is only set within Proposal blocks - signature: Option, + signature: Option, } impl fmt::Debug for Block { @@ -128,7 +128,7 @@ impl Block { self.block_data.round() } - pub fn signature(&self) -> Option<&bls12381::Signature> { + pub fn signature(&self) -> Option<&ed25519::Signature> { self.signature.as_ref() } @@ -186,7 +186,7 @@ impl Block { pub fn new_for_testing( id: HashValue, block_data: BlockData, - signature: Option, + signature: Option, ) -> Self { Block { id, @@ -296,7 +296,7 @@ impl Block { pub fn new_proposal_from_block_data_and_signature( block_data: BlockData, - signature: bls12381::Signature, + signature: ed25519::Signature, ) -> Self { Block { id: block_data.hash(), @@ -509,7 +509,7 @@ impl<'de> Deserialize<'de> for Block { #[serde(rename = "Block")] struct BlockWithoutId { block_data: BlockData, - signature: Option, + signature: Option, } let BlockWithoutId { diff --git a/consensus/consensus-types/src/block_test_utils.rs b/consensus/consensus-types/src/block_test_utils.rs index 402af52c48d623..facd0049aaa3e3 100644 --- a/consensus/consensus-types/src/block_test_utils.rs +++ b/consensus/consensus-types/src/block_test_utils.rs @@ -11,7 +11,7 @@ use crate::{ vote_data::VoteData, }; use aptos_crypto::{ - bls12381, + ed25519, ed25519::Ed25519PrivateKey, hash::{CryptoHash, HashValue}, PrivateKey, Uniform, @@ -155,7 +155,7 @@ prop_compose! { /// vector fn block_forest_from_keys( depth: u32, - key_pairs: Vec, + key_pairs: Vec, ) -> impl Strategy { let leaf = leaf_strategy().prop_map(|block| vec![block]); // Note that having `expected_branch_size` of 1 seems to generate significantly larger trees @@ -170,7 +170,7 @@ fn block_forest_from_keys( pub fn block_forest_and_its_keys( quorum_size: usize, depth: u32, -) -> impl Strategy, LinearizedBlockForest)> { +) -> impl Strategy, LinearizedBlockForest)> { proptest::collection::vec(proptests::arb_signing_key(), quorum_size).prop_flat_map( move |private_key| { ( diff --git a/consensus/consensus-types/src/pipeline/commit_vote.rs b/consensus/consensus-types/src/pipeline/commit_vote.rs index a7ab26d07b271a..593f9c6097b206 100644 --- a/consensus/consensus-types/src/pipeline/commit_vote.rs +++ b/consensus/consensus-types/src/pipeline/commit_vote.rs @@ -4,7 +4,7 @@ use crate::common::{Author, Round}; use anyhow::Context; -use aptos_crypto::{bls12381, CryptoMaterialError}; +use aptos_crypto::{ed25519, CryptoMaterialError}; use aptos_short_hex_str::AsShortHexStr; use aptos_types::{ block_info::BlockInfo, ledger_info::LedgerInfo, validator_signer::ValidatorSigner, @@ -17,7 +17,7 @@ use std::fmt::{Debug, Display, Formatter}; pub struct CommitVote { author: Author, ledger_info: LedgerInfo, - signature: bls12381::Signature, + signature: ed25519::Signature, } // this is required by structured log @@ -57,7 +57,7 @@ impl CommitVote { pub fn new_with_signature( author: Author, ledger_info: LedgerInfo, - signature: bls12381::Signature, + signature: ed25519::Signature, ) -> Self { Self { author, @@ -77,7 +77,7 @@ impl CommitVote { } /// Return the signature of the vote - pub fn signature(&self) -> &bls12381::Signature { + pub fn signature(&self) -> &ed25519::Signature { &self.signature } diff --git a/consensus/consensus-types/src/proof_of_store.rs b/consensus/consensus-types/src/proof_of_store.rs index 08c5c53946d432..1e5a0cd8317e7d 100644 --- a/consensus/consensus-types/src/proof_of_store.rs +++ b/consensus/consensus-types/src/proof_of_store.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use anyhow::{bail, ensure, Context}; -use aptos_crypto::{bls12381, CryptoMaterialError, HashValue}; +use aptos_crypto::{ed25519, CryptoMaterialError, HashValue}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use aptos_types::{ aggregate_signature::AggregateSignature, validator_signer::ValidatorSigner, @@ -191,7 +191,7 @@ impl SignedBatchInfoMsg { pub struct SignedBatchInfo { info: BatchInfo, signer: PeerId, - signature: bls12381::Signature, + signature: ed25519::Signature, } impl SignedBatchInfo { @@ -237,7 +237,7 @@ impl SignedBatchInfo { Ok(validator.verify(self.signer, &self.info, &self.signature)?) } - pub fn signature(self) -> bls12381::Signature { + pub fn signature(self) -> ed25519::Signature { self.signature } diff --git a/consensus/consensus-types/src/timeout_2chain.rs b/consensus/consensus-types/src/timeout_2chain.rs index 9fc0ced6f3c50f..e69c7cc8e9d0c5 100644 --- a/consensus/consensus-types/src/timeout_2chain.rs +++ b/consensus/consensus-types/src/timeout_2chain.rs @@ -4,7 +4,7 @@ use crate::{common::Author, quorum_cert::QuorumCert}; use anyhow::ensure; -use aptos_crypto::{bls12381, CryptoMaterialError}; +use aptos_crypto::{ed25519, CryptoMaterialError}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use aptos_types::{ account_address::AccountAddress, @@ -60,7 +60,7 @@ impl TwoChainTimeout { pub fn sign( &self, signer: &ValidatorSigner, - ) -> Result { + ) -> Result { signer.sign(&self.signing_format()) } @@ -234,12 +234,7 @@ impl TwoChainTimeoutWithPartialSignatures { } /// Add a new timeout message from author, the timeout should already be verified in upper layer. - pub fn add( - &mut self, - author: Author, - timeout: TwoChainTimeout, - signature: bls12381::Signature, - ) { + pub fn add(&mut self, author: Author, timeout: TwoChainTimeout, signature: ed25519::Signature) { debug_assert_eq!( self.timeout.epoch(), timeout.epoch(), @@ -281,11 +276,11 @@ impl TwoChainTimeoutWithPartialSignatures { /// timeout aggregation. #[derive(Debug, Clone, Eq, PartialEq)] pub struct PartialSignaturesWithRound { - signatures: BTreeMap, + signatures: BTreeMap, } impl PartialSignaturesWithRound { - pub fn new(signatures: BTreeMap) -> Self { + pub fn new(signatures: BTreeMap) -> Self { Self { signatures } } @@ -293,7 +288,7 @@ impl PartialSignaturesWithRound { Self::new(BTreeMap::new()) } - pub fn signatures(&self) -> &BTreeMap { + pub fn signatures(&self) -> &BTreeMap { &self.signatures } @@ -302,7 +297,7 @@ impl PartialSignaturesWithRound { &mut self, validator: AccountAddress, round: Round, - signature: bls12381::Signature, + signature: ed25519::Signature, ) { self.signatures.insert(validator, (round, signature)); } @@ -316,7 +311,7 @@ impl PartialSignaturesWithRound { &mut self, validator: AccountAddress, round: Round, - signature: bls12381::Signature, + signature: ed25519::Signature, ) { self.signatures .entry(validator) @@ -397,7 +392,7 @@ mod tests { quorum_cert::QuorumCert, timeout_2chain::{TwoChainTimeout, TwoChainTimeoutWithPartialSignatures}, }; - use aptos_crypto::bls12381; + use aptos_crypto::ed25519; #[test] fn test_2chain_timeout_certificate() { @@ -465,7 +460,7 @@ mod tests { invalid_timeout_cert.signatures.replace_signature( signers[0].author(), 0, - bls12381::Signature::dummy_signature(), + ed25519::Signature::dummy_signature(), ); let invalid_tc_with_sig = invalid_timeout_cert diff --git a/consensus/consensus-types/src/vote.rs b/consensus/consensus-types/src/vote.rs index 8d5868a06c3b16..f5f463fcc91889 100644 --- a/consensus/consensus-types/src/vote.rs +++ b/consensus/consensus-types/src/vote.rs @@ -6,7 +6,7 @@ use crate::{ common::Author, quorum_cert::QuorumCert, timeout_2chain::TwoChainTimeout, vote_data::VoteData, }; use anyhow::{ensure, Context}; -use aptos_crypto::{bls12381, hash::CryptoHash, CryptoMaterialError}; +use aptos_crypto::{ed25519, hash::CryptoHash, CryptoMaterialError}; use aptos_short_hex_str::AsShortHexStr; use aptos_types::{ ledger_info::LedgerInfo, validator_signer::ValidatorSigner, @@ -28,9 +28,9 @@ pub struct Vote { /// LedgerInfo of a block that is going to be committed in case this vote gathers QC. ledger_info: LedgerInfo, /// Signature of the LedgerInfo - signature: bls12381::Signature, + signature: ed25519::Signature, /// The 2-chain timeout and corresponding signature. - two_chain_timeout: Option<(TwoChainTimeout, bls12381::Signature)>, + two_chain_timeout: Option<(TwoChainTimeout, ed25519::Signature)>, } // this is required by structured log @@ -77,7 +77,7 @@ impl Vote { vote_data: VoteData, author: Author, ledger_info: LedgerInfo, - signature: bls12381::Signature, + signature: ed25519::Signature, ) -> Self { Self { vote_data, @@ -89,7 +89,7 @@ impl Vote { } /// Add the 2-chain timeout and signature in the vote. - pub fn add_2chain_timeout(&mut self, timeout: TwoChainTimeout, signature: bls12381::Signature) { + pub fn add_2chain_timeout(&mut self, timeout: TwoChainTimeout, signature: ed25519::Signature) { self.two_chain_timeout = Some((timeout, signature)); } @@ -108,7 +108,7 @@ impl Vote { } /// Return the signature of the vote - pub fn signature(&self) -> &bls12381::Signature { + pub fn signature(&self) -> &ed25519::Signature { &self.signature } @@ -127,7 +127,7 @@ impl Vote { } /// Return the two chain timeout vote and signature. - pub fn two_chain_timeout(&self) -> Option<&(TwoChainTimeout, bls12381::Signature)> { + pub fn two_chain_timeout(&self) -> Option<&(TwoChainTimeout, ed25519::Signature)> { self.two_chain_timeout.as_ref() } diff --git a/consensus/safety-rules/src/fuzzing_utils.rs b/consensus/safety-rules/src/fuzzing_utils.rs index c6e2b505571b8d..b3eec904e98bb9 100644 --- a/consensus/safety-rules/src/fuzzing_utils.rs +++ b/consensus/safety-rules/src/fuzzing_utils.rs @@ -16,7 +16,7 @@ use aptos_consensus_types::{ vote_proposal::VoteProposal, }; use aptos_crypto::{ - bls12381, + ed25519, hash::{HashValue, TransactionAccumulatorHasher}, test_utils::TEST_SEED, traits::{SigningKey, Uniform}, @@ -68,7 +68,7 @@ prop_compose! { ) -> Block { let signature = if include_signature { let mut rng = StdRng::from_seed(TEST_SEED); - let private_key = bls12381::PrivateKey::generate(&mut rng); + let private_key = ed25519::PrivateKey::generate(&mut rng); let signature = private_key.sign(&block_data).unwrap(); Some(signature) } else { @@ -243,7 +243,7 @@ pub mod fuzzing { block_data::BlockData, timeout_2chain::TwoChainTimeout, vote::Vote, vote_proposal::VoteProposal, }; - use aptos_crypto::bls12381; + use aptos_crypto::ed25519; use aptos_types::epoch_change::EpochChangeProof; pub fn fuzz_initialize(proof: EpochChangeProof) -> Result<(), Error> { @@ -272,14 +272,14 @@ pub mod fuzzing { } } - pub fn fuzz_sign_proposal(block_data: &BlockData) -> Result { + pub fn fuzz_sign_proposal(block_data: &BlockData) -> Result { let mut safety_rules = test_utils::test_safety_rules(); safety_rules.sign_proposal(block_data) } pub fn fuzz_sign_timeout_with_qc( timeout: TwoChainTimeout, - ) -> Result { + ) -> Result { let mut safety_rules = test_utils::test_safety_rules(); safety_rules.sign_timeout_with_qc(&timeout, None) } diff --git a/consensus/safety-rules/src/local_client.rs b/consensus/safety-rules/src/local_client.rs index 7994ef7fbe8239..3bf7687dfa0d86 100644 --- a/consensus/safety-rules/src/local_client.rs +++ b/consensus/safety-rules/src/local_client.rs @@ -9,7 +9,7 @@ use aptos_consensus_types::{ vote::Vote, vote_proposal::VoteProposal, }; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; use aptos_infallible::RwLock; use aptos_types::{ epoch_change::EpochChangeProof, @@ -39,7 +39,7 @@ impl TSafetyRules for LocalClient { self.internal.write().initialize(proof) } - fn sign_proposal(&mut self, block_data: &BlockData) -> Result { + fn sign_proposal(&mut self, block_data: &BlockData) -> Result { self.internal.write().sign_proposal(block_data) } @@ -47,7 +47,7 @@ impl TSafetyRules for LocalClient { &mut self, timeout: &TwoChainTimeout, timeout_cert: Option<&TwoChainTimeoutCertificate>, - ) -> Result { + ) -> Result { self.internal .write() .sign_timeout_with_qc(timeout, timeout_cert) @@ -67,7 +67,7 @@ impl TSafetyRules for LocalClient { &mut self, ledger_info: LedgerInfoWithSignatures, new_ledger_info: LedgerInfo, - ) -> Result { + ) -> Result { self.internal .write() .sign_commit_vote(ledger_info, new_ledger_info) diff --git a/consensus/safety-rules/src/persistent_safety_storage.rs b/consensus/safety-rules/src/persistent_safety_storage.rs index b5823970402bf9..10ecb2725c84d4 100644 --- a/consensus/safety-rules/src/persistent_safety_storage.rs +++ b/consensus/safety-rules/src/persistent_safety_storage.rs @@ -8,7 +8,7 @@ use crate::{ Error, }; use aptos_consensus_types::{common::Author, safety_data::SafetyData}; -use aptos_crypto::{bls12381, PrivateKey}; +use aptos_crypto::{ed25519, PrivateKey}; use aptos_global_constants::{CONSENSUS_KEY, OWNER_ACCOUNT, SAFETY_DATA, WAYPOINT}; use aptos_logger::prelude::*; use aptos_secure_storage::{KVStorage, Storage}; @@ -34,7 +34,7 @@ impl PersistentSafetyStorage { pub fn initialize( mut internal_store: Storage, author: Author, - consensus_private_key: bls12381::PrivateKey, + consensus_private_key: ed25519::PrivateKey, waypoint: Waypoint, enable_cached_safety_data: bool, ) -> Self { @@ -64,7 +64,7 @@ impl PersistentSafetyStorage { fn initialize_keys_and_accounts( internal_store: &mut Storage, author: Author, - consensus_private_key: bls12381::PrivateKey, + consensus_private_key: ed25519::PrivateKey, ) -> Result<(), Error> { let result = internal_store.set(CONSENSUS_KEY, consensus_private_key); // Attempting to re-initialize existing storage. This can happen in environments like @@ -98,10 +98,10 @@ impl PersistentSafetyStorage { pub fn consensus_key_for_version( &self, - version: bls12381::PublicKey, - ) -> Result { + version: ed25519::PublicKey, + ) -> Result { let _timer = counters::start_timer("get", CONSENSUS_KEY); - let key: bls12381::PrivateKey = self.internal_store.get(CONSENSUS_KEY).map(|v| v.value)?; + let key: ed25519::PrivateKey = self.internal_store.get(CONSENSUS_KEY).map(|v| v.value)?; if key.public_key() != version { return Err(Error::SecureStorageMissingDataError(format!( "PrivateKey for {:?} not found", diff --git a/consensus/safety-rules/src/safety_rules.rs b/consensus/safety-rules/src/safety_rules.rs index 60b0b8cc27a055..78bb4c15e742cc 100644 --- a/consensus/safety-rules/src/safety_rules.rs +++ b/consensus/safety-rules/src/safety_rules.rs @@ -20,7 +20,7 @@ use aptos_consensus_types::{ vote_data::VoteData, vote_proposal::VoteProposal, }; -use aptos_crypto::{bls12381, hash::CryptoHash}; +use aptos_crypto::{ed25519, hash::CryptoHash}; use aptos_logger::prelude::*; use aptos_types::{ epoch_change::EpochChangeProof, @@ -80,7 +80,7 @@ impl SafetyRules { pub(crate) fn sign( &self, message: &T, - ) -> Result { + ) -> Result { let signer = self.signer()?; signer .sign(message) @@ -302,7 +302,7 @@ impl SafetyRules { fn guarded_sign_proposal( &mut self, block_data: &BlockData, - ) -> Result { + ) -> Result { self.signer()?; self.verify_author(block_data.author())?; @@ -329,7 +329,7 @@ impl SafetyRules { &mut self, ledger_info: LedgerInfoWithSignatures, new_ledger_info: LedgerInfo, - ) -> Result { + ) -> Result { self.signer()?; let old_ledger_info = ledger_info.ledger_info(); @@ -373,7 +373,7 @@ impl TSafetyRules for SafetyRules { run_and_log(cb, |log| log, LogEntry::Initialize) } - fn sign_proposal(&mut self, block_data: &BlockData) -> Result { + fn sign_proposal(&mut self, block_data: &BlockData) -> Result { let round = block_data.round(); let cb = || self.guarded_sign_proposal(block_data); run_and_log(cb, |log| log.round(round), LogEntry::SignProposal) @@ -383,7 +383,7 @@ impl TSafetyRules for SafetyRules { &mut self, timeout: &TwoChainTimeout, timeout_cert: Option<&TwoChainTimeoutCertificate>, - ) -> Result { + ) -> Result { let cb = || self.guarded_sign_timeout_with_qc(timeout, timeout_cert); run_and_log( cb, @@ -410,7 +410,7 @@ impl TSafetyRules for SafetyRules { &mut self, ledger_info: LedgerInfoWithSignatures, new_ledger_info: LedgerInfo, - ) -> Result { + ) -> Result { let cb = || self.guarded_sign_commit_vote(ledger_info, new_ledger_info); run_and_log(cb, |log| log, LogEntry::SignCommitVote) } diff --git a/consensus/safety-rules/src/safety_rules_2chain.rs b/consensus/safety-rules/src/safety_rules_2chain.rs index b3ac49c1fde749..53397b02e0fadd 100644 --- a/consensus/safety-rules/src/safety_rules_2chain.rs +++ b/consensus/safety-rules/src/safety_rules_2chain.rs @@ -10,7 +10,7 @@ use aptos_consensus_types::{ vote::Vote, vote_proposal::VoteProposal, }; -use aptos_crypto::{bls12381, hash::CryptoHash, HashValue}; +use aptos_crypto::{ed25519, hash::CryptoHash, HashValue}; use aptos_types::{block_info::BlockInfo, ledger_info::LedgerInfo}; /// 2-chain safety rules implementation @@ -19,7 +19,7 @@ impl SafetyRules { &mut self, timeout: &TwoChainTimeout, timeout_cert: Option<&TwoChainTimeoutCertificate>, - ) -> Result { + ) -> Result { self.signer()?; let mut safety_data = self.persistent_storage.safety_data()?; self.verify_epoch(timeout.epoch(), &safety_data)?; diff --git a/consensus/safety-rules/src/safety_rules_manager.rs b/consensus/safety-rules/src/safety_rules_manager.rs index c73664be47344a..5652f40b159e3b 100644 --- a/consensus/safety-rules/src/safety_rules_manager.rs +++ b/consensus/safety-rules/src/safety_rules_manager.rs @@ -13,7 +13,7 @@ use crate::{ }; use anyhow::anyhow; use aptos_config::config::{InitialSafetyRulesConfig, SafetyRulesConfig, SafetyRulesService}; -use aptos_crypto::bls12381::PrivateKey; +use aptos_crypto::ed25519::PrivateKey; use aptos_global_constants::CONSENSUS_KEY; use aptos_infallible::RwLock; use aptos_secure_storage::{KVStorage, Storage}; diff --git a/consensus/safety-rules/src/serializer.rs b/consensus/safety-rules/src/serializer.rs index 2cef5bce865ec1..8c877088c4db22 100644 --- a/consensus/safety-rules/src/serializer.rs +++ b/consensus/safety-rules/src/serializer.rs @@ -9,7 +9,7 @@ use aptos_consensus_types::{ vote::Vote, vote_proposal::VoteProposal, }; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; use aptos_infallible::RwLock; use aptos_types::{ epoch_change::EpochChangeProof, @@ -107,7 +107,7 @@ impl TSafetyRules for SerializerClient { serde_json::from_slice(&response)? } - fn sign_proposal(&mut self, block_data: &BlockData) -> Result { + fn sign_proposal(&mut self, block_data: &BlockData) -> Result { let _timer = counters::start_timer("external", LogEntry::SignProposal.as_str()); let response = self.request(SafetyRulesInput::SignProposal(Box::new(block_data.clone())))?; @@ -118,7 +118,7 @@ impl TSafetyRules for SerializerClient { &mut self, timeout: &TwoChainTimeout, timeout_cert: Option<&TwoChainTimeoutCertificate>, - ) -> Result { + ) -> Result { let _timer = counters::start_timer("external", LogEntry::SignTimeoutWithQC.as_str()); let response = self.request(SafetyRulesInput::SignTimeoutWithQC( Box::new(timeout.clone()), @@ -145,7 +145,7 @@ impl TSafetyRules for SerializerClient { &mut self, ledger_info: LedgerInfoWithSignatures, new_ledger_info: LedgerInfo, - ) -> Result { + ) -> Result { let _timer = counters::start_timer("external", LogEntry::SignCommitVote.as_str()); let response = self.request(SafetyRulesInput::SignCommitVote( Box::new(ledger_info), diff --git a/consensus/safety-rules/src/t_safety_rules.rs b/consensus/safety-rules/src/t_safety_rules.rs index 33cc1d59b204cc..56691920c52bdb 100644 --- a/consensus/safety-rules/src/t_safety_rules.rs +++ b/consensus/safety-rules/src/t_safety_rules.rs @@ -9,7 +9,7 @@ use aptos_consensus_types::{ vote::Vote, vote_proposal::VoteProposal, }; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; use aptos_types::{ epoch_change::EpochChangeProof, ledger_info::{LedgerInfo, LedgerInfoWithSignatures}, @@ -29,14 +29,14 @@ pub trait TSafetyRules { /// As the holder of the private key, SafetyRules also signs proposals or blocks. /// A Block is a signed BlockData along with some additional metadata. - fn sign_proposal(&mut self, block_data: &BlockData) -> Result; + fn sign_proposal(&mut self, block_data: &BlockData) -> Result; /// Sign the timeout together with highest qc for 2-chain protocol. fn sign_timeout_with_qc( &mut self, timeout: &TwoChainTimeout, timeout_cert: Option<&TwoChainTimeoutCertificate>, - ) -> Result; + ) -> Result; /// Attempts to vote for a given proposal following the 2-chain protocol. fn construct_and_sign_vote_two_chain( @@ -51,5 +51,5 @@ pub trait TSafetyRules { &mut self, ledger_info: LedgerInfoWithSignatures, new_ledger_info: LedgerInfo, - ) -> Result; + ) -> Result; } diff --git a/consensus/src/consensusdb/consensusdb_test.rs b/consensus/src/consensusdb/consensusdb_test.rs index ee29113093421f..94bebba0ba6735 100644 --- a/consensus/src/consensusdb/consensusdb_test.rs +++ b/consensus/src/consensusdb/consensusdb_test.rs @@ -8,7 +8,7 @@ use aptos_consensus_types::{ block::block_test_utils::certificate_for_genesis, common::{Author, Payload}, }; -use aptos_crypto::bls12381::Signature; +use aptos_crypto::ed25519::Signature; use aptos_temppath::TempPath; use aptos_types::aggregate_signature::AggregateSignature; use std::{collections::HashMap, hash::Hash}; diff --git a/consensus/src/dag/commit_signer.rs b/consensus/src/dag/commit_signer.rs index 6aa06d19d7ae34..e80e382ffec59a 100644 --- a/consensus/src/dag/commit_signer.rs +++ b/consensus/src/dag/commit_signer.rs @@ -1,7 +1,7 @@ // Copyright © Aptos Foundation use crate::pipeline::signing_phase::CommitSignerProvider; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; use aptos_types::validator_signer::ValidatorSigner; use std::sync::Arc; @@ -20,7 +20,7 @@ impl CommitSignerProvider for DagCommitSigner { &self, _ledger_info: aptos_types::ledger_info::LedgerInfoWithSignatures, new_ledger_info: aptos_types::ledger_info::LedgerInfo, - ) -> Result { + ) -> Result { let signature = self .signer .sign(&new_ledger_info) diff --git a/consensus/src/dag/types.rs b/consensus/src/dag/types.rs index 9963bdb89df238..11339884d2389d 100644 --- a/consensus/src/dag/types.rs +++ b/consensus/src/dag/types.rs @@ -13,7 +13,7 @@ use crate::{ use anyhow::{bail, ensure}; use aptos_consensus_types::common::{Author, Payload, Round}; use aptos_crypto::{ - bls12381::Signature, + ed25519::Signature, hash::{CryptoHash, CryptoHasher}, CryptoMaterialError, HashValue, }; diff --git a/consensus/src/liveness/leader_reputation_test.rs b/consensus/src/liveness/leader_reputation_test.rs index 89739eb208fa54..4fbaf5a56ace43 100644 --- a/consensus/src/liveness/leader_reputation_test.rs +++ b/consensus/src/liveness/leader_reputation_test.rs @@ -13,7 +13,7 @@ use crate::liveness::{ }; use aptos_bitvec::BitVec; use aptos_consensus_types::common::{Author, Round}; -use aptos_crypto::{bls12381, HashValue}; +use aptos_crypto::{ed25519, HashValue}; use aptos_infallible::Mutex; use aptos_keygen::KeyGen; use aptos_storage_interface::DbReader; @@ -646,7 +646,7 @@ fn test_extract_epoch_to_proposers_impl() { fn create_epoch_state( epoch: u64, authors: &[Author], - public_key: &bls12381::PublicKey, + public_key: &ed25519::PublicKey, ) -> EpochState { EpochState { epoch, @@ -659,8 +659,8 @@ fn test_extract_epoch_to_proposers_impl() { } } - let private_key = KeyGen::from_os_rng().generate_bls12381_private_key(); - let public_key = bls12381::PublicKey::from(&private_key); + let private_key = KeyGen::from_os_rng().generate_ed25519_private_key(); + let public_key = ed25519::PublicKey::from(&private_key); let authors: Vec = (0..7).map(|_| AccountAddress::random()).sorted().collect(); let epoch_states = (0..7) diff --git a/consensus/src/metrics_safety_rules.rs b/consensus/src/metrics_safety_rules.rs index d49d2dbf12465f..7a0f54b90e5408 100644 --- a/consensus/src/metrics_safety_rules.rs +++ b/consensus/src/metrics_safety_rules.rs @@ -12,7 +12,7 @@ use aptos_consensus_types::{ vote::Vote, vote_proposal::VoteProposal, }; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; use aptos_infallible::Mutex; use aptos_logger::prelude::info; use aptos_safety_rules::{ConsensusState, Error, TSafetyRules}; @@ -93,7 +93,7 @@ impl TSafetyRules for MetricsSafetyRules { monitor!("safety_rules", self.inner.initialize(proof)) } - fn sign_proposal(&mut self, block_data: &BlockData) -> Result { + fn sign_proposal(&mut self, block_data: &BlockData) -> Result { self.retry(|inner| monitor!("safety_rules", inner.sign_proposal(block_data))) } @@ -101,7 +101,7 @@ impl TSafetyRules for MetricsSafetyRules { &mut self, timeout: &TwoChainTimeout, timeout_cert: Option<&TwoChainTimeoutCertificate>, - ) -> Result { + ) -> Result { self.retry(|inner| { monitor!( "safety_rules", @@ -127,7 +127,7 @@ impl TSafetyRules for MetricsSafetyRules { &mut self, ledger_info: LedgerInfoWithSignatures, new_ledger_info: LedgerInfo, - ) -> Result { + ) -> Result { self.retry(|inner| { monitor!( "safety_rules", @@ -142,7 +142,7 @@ impl CommitSignerProvider for Mutex { &self, ledger_info: LedgerInfoWithSignatures, new_ledger_info: LedgerInfo, - ) -> Result { + ) -> Result { self.lock().sign_commit_vote(ledger_info, new_ledger_info) } } @@ -156,7 +156,7 @@ mod tests { vote::Vote, vote_proposal::VoteProposal, }; - use aptos_crypto::bls12381; + use aptos_crypto::ed25519; use aptos_safety_rules::{ConsensusState, Error, TSafetyRules}; use aptos_types::{ epoch_change::EpochChangeProof, @@ -207,7 +207,7 @@ mod tests { self.last_init_result.clone() } - fn sign_proposal(&mut self, _: &BlockData) -> Result { + fn sign_proposal(&mut self, _: &BlockData) -> Result { unimplemented!() } @@ -215,7 +215,7 @@ mod tests { &mut self, _: &TwoChainTimeout, _: Option<&TwoChainTimeoutCertificate>, - ) -> Result { + ) -> Result { unimplemented!() } @@ -231,7 +231,7 @@ mod tests { &mut self, _: LedgerInfoWithSignatures, _: LedgerInfo, - ) -> Result { + ) -> Result { unimplemented!() } } diff --git a/consensus/src/pipeline/buffer_item.rs b/consensus/src/pipeline/buffer_item.rs index d92d62eb71f99d..8f78c5bbf28336 100644 --- a/consensus/src/pipeline/buffer_item.rs +++ b/consensus/src/pipeline/buffer_item.rs @@ -7,7 +7,7 @@ use anyhow::anyhow; use aptos_consensus_types::{ common::Author, executed_block::ExecutedBlock, pipeline::commit_vote::CommitVote, }; -use aptos_crypto::{bls12381, HashValue}; +use aptos_crypto::{ed25519, HashValue}; use aptos_executor_types::ExecutorResult; use aptos_logger::prelude::*; use aptos_reliable_broadcast::DropGuard; @@ -228,7 +228,7 @@ impl BufferItem { } } - pub fn advance_to_signed(self, author: Author, signature: bls12381::Signature) -> Self { + pub fn advance_to_signed(self, author: Author, signature: ed25519::Signature) -> Self { match self { Self::Executed(executed_item) => { let ExecutedItem { diff --git a/consensus/src/pipeline/signing_phase.rs b/consensus/src/pipeline/signing_phase.rs index 8482b2c37fa720..58d084bad0dd94 100644 --- a/consensus/src/pipeline/signing_phase.rs +++ b/consensus/src/pipeline/signing_phase.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::pipeline::pipeline_phase::StatelessPipeline; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; use aptos_safety_rules::Error; use aptos_types::ledger_info::{LedgerInfo, LedgerInfoWithSignatures}; use async_trait::async_trait; @@ -43,11 +43,11 @@ pub trait CommitSignerProvider: Send + Sync { &self, ledger_info: LedgerInfoWithSignatures, new_ledger_info: LedgerInfo, - ) -> Result; + ) -> Result; } pub struct SigningResponse { - pub signature_result: Result, + pub signature_result: Result, pub commit_ledger_info: LedgerInfo, } diff --git a/consensus/src/quorum_store/proof_coordinator.rs b/consensus/src/quorum_store/proof_coordinator.rs index d0eab1129d3c6b..b0dad18db8176c 100644 --- a/consensus/src/quorum_store/proof_coordinator.rs +++ b/consensus/src/quorum_store/proof_coordinator.rs @@ -12,7 +12,7 @@ use crate::{ use aptos_consensus_types::proof_of_store::{ BatchInfo, ProofOfStore, SignedBatchInfo, SignedBatchInfoError, SignedBatchInfoMsg, }; -use aptos_crypto::{bls12381, HashValue}; +use aptos_crypto::{ed25519, HashValue}; use aptos_logger::prelude::*; use aptos_types::{ aggregate_signature::PartialSignatures, validator_verifier::ValidatorVerifier, PeerId, @@ -36,7 +36,7 @@ pub(crate) enum ProofCoordinatorCommand { struct IncrementalProofState { info: BatchInfo, - aggregated_signature: BTreeMap, + aggregated_signature: BTreeMap, aggregated_voting_power: u128, self_voted: bool, completed: bool, diff --git a/consensus/src/rand/rand_gen/types.rs b/consensus/src/rand/rand_gen/types.rs index f3d4009ce66f37..aafe6d97b1695a 100644 --- a/consensus/src/rand/rand_gen/types.rs +++ b/consensus/src/rand/rand_gen/types.rs @@ -3,7 +3,7 @@ use anyhow::ensure; use aptos_consensus_types::common::{Author, Round}; -use aptos_crypto::bls12381::Signature; +use aptos_crypto::ed25519::Signature; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use aptos_types::{ aggregate_signature::AggregateSignature, diff --git a/crates/aptos-crypto/Cargo.toml b/crates/aptos-crypto/Cargo.toml index 783984768a4d1e..b356a93220ad39 100644 --- a/crates/aptos-crypto/Cargo.toml +++ b/crates/aptos-crypto/Cargo.toml @@ -85,10 +85,6 @@ harness = false name = "ark_bn254" harness = false -[[bench]] -name = "bls12381" -harness = false - [[bench]] name = "bulletproofs" harness = false diff --git a/crates/aptos-crypto/benches/bls12381.rs b/crates/aptos-crypto/benches/bls12381.rs deleted file mode 100644 index 41b53977733918..00000000000000 --- a/crates/aptos-crypto/benches/bls12381.rs +++ /dev/null @@ -1,422 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -#[macro_use] -extern crate criterion; - -use aptos_crypto::{ - bls12381, - bls12381::ProofOfPossession, - test_utils::{random_keypairs, random_subset, KeyPair}, - traits::{Signature, SigningKey, Uniform}, - PrivateKey, -}; -use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; -use criterion::{ - measurement::Measurement, AxisScale, BatchSize, BenchmarkGroup, BenchmarkId, Criterion, - PlotConfiguration, Throughput, -}; -use rand::{distributions, rngs::ThreadRng, thread_rng, Rng}; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, CryptoHasher, BCSCryptoHash, Serialize, Deserialize)] -struct TestAptosCrypto(String); - -fn random_message(rng: &mut ThreadRng) -> TestAptosCrypto { - TestAptosCrypto( - rng.sample_iter(&distributions::Alphanumeric) - .take(256) - .map(char::from) - .collect::(), - ) -} - -fn bench_group(c: &mut Criterion) { - let mut group = c.benchmark_group("bls12381"); - - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - - group.sample_size(1000); - group.plot_config(plot_config); - - pk_deserialize(&mut group); - sig_deserialize(&mut group); - pk_subgroup_membership(&mut group); - sig_subgroup_membership(&mut group); - aggregate_one_sigshare(&mut group); - aggregate_one_pk(&mut group); - - pop_create(&mut group); - pop_create_with_pubkey(&mut group); - pop_verify(&mut group); - - sign(&mut group); - verify_signature_share(&mut group); - - let mut size = 128; - for _ in 1..=4 { - // Even single-threaded, this function has higher throughput that `aggregate_one_sigshare` - aggregate_sigshare(&mut group, size); - - // Even single-threaded, this function has higher throughput than `aggregate_one_pk`. Seems - // to be due to only making a single call to blst::PublicKey::from_aggregate (which calls a - // $pk_to_aff function) for the entire batch. - aggregate_pks(&mut group, size); - - verify_multisig(&mut group, size); - verify_aggsig(&mut group, size); - size *= 2; - } - - group.finish(); -} - -/// Benchmarks the time to deserialize a BLS12-381 point representing a PK in G1. (Does not test for -/// prime-order subgroup membership.) -fn pk_deserialize(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - g.throughput(Throughput::Elements(1)); - - g.bench_function("pk_deserialize", move |b| { - b.iter_with_setup( - || { - bls12381::PrivateKey::generate(&mut rng) - .public_key() - .to_bytes() - }, - |pk_bytes| bls12381::PublicKey::try_from(&pk_bytes[..]), - ) - }); -} - -/// Benchmarks the time to aggregate a BLS PK in G1. (Does not test for prime-order subgroup -/// membership.) -fn aggregate_one_pk(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - g.throughput(Throughput::Elements(1)); - - g.bench_function("aggregate_one_pk", move |b| { - b.iter_with_setup( - || { - ( - bls12381::PrivateKey::generate(&mut rng).public_key(), - bls12381::PrivateKey::generate(&mut rng).public_key(), - ) - }, - |(pk1, pk2)| { - bls12381::PublicKey::aggregate(vec![&pk1, &pk2]).unwrap(); - }, - ) - }); -} - -/// Benchmarks the time to deserialize a BLS12-381 point representing a signature in G2. (Does not test for -/// prime-order subgroup membership.) -fn sig_deserialize(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - g.throughput(Throughput::Elements(1)); - - g.bench_function("sig_deserialize", move |b| { - b.iter_with_setup( - || { - let sk = bls12381::PrivateKey::generate(&mut rng); - sk.sign(&TestAptosCrypto("Hello Aptos!".to_owned())) - .unwrap() - .to_bytes() - }, - |sig_bytes| bls12381::Signature::try_from(&sig_bytes[..]), - ) - }); -} - -/// Benchmarks the time to aggregate a BLS signature in G2. (Does not test for prime-order subgroup -/// membership.) -fn aggregate_one_sigshare(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - g.throughput(Throughput::Elements(1)); - - g.bench_function("aggregate_one_sigshare", move |b| { - b.iter_with_setup( - || { - ( - bls12381::PrivateKey::generate(&mut rng) - .sign(&TestAptosCrypto("Hello Aptos!".to_owned())) - .unwrap(), - bls12381::PrivateKey::generate(&mut rng) - .sign(&TestAptosCrypto("Hello Aptos!".to_owned())) - .unwrap(), - ) - }, - |(sig1, sig2)| { - bls12381::Signature::aggregate(vec![sig1, sig2]).unwrap(); - }, - ) - }); -} - -fn pk_subgroup_membership(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - g.throughput(Throughput::Elements(1)); - g.bench_function("pk_prime_order_subgroup_check", move |b| { - b.iter_with_setup( - || { - let kp = KeyPair::::generate(&mut rng); - kp.public_key - }, - |pk| pk.subgroup_check(), - ) - }); -} - -fn sig_subgroup_membership(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - g.throughput(Throughput::Elements(1)); - g.bench_function("sig_prime_order_subgroup_check", move |b| { - b.iter_with_setup( - || { - let kp = KeyPair::::generate(&mut rng); - - // Currently, there's no better way of sampling a group element here - kp.private_key - .sign(&TestAptosCrypto("Hello Aptos!".to_owned())) - .unwrap() - }, - |sig| sig.subgroup_check(), - ) - }); -} - -fn pop_create(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - let priv_key = bls12381::PrivateKey::generate(&mut rng); - - g.throughput(Throughput::Elements(1)); - g.bench_function("pop_create", move |b| { - b.iter(|| ProofOfPossession::create(&priv_key)) - }); -} - -fn pop_create_with_pubkey(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - let kp = KeyPair::::generate(&mut rng); - - g.throughput(Throughput::Elements(1)); - g.bench_function("pop_create_with_pubkey", move |b| { - b.iter(|| ProofOfPossession::create_with_pubkey(&kp.private_key, &kp.public_key)) - }); -} - -fn pop_verify(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - let kp = KeyPair::::generate(&mut rng); - let pop = ProofOfPossession::create_with_pubkey(&kp.private_key, &kp.public_key); - - g.throughput(Throughput::Elements(1)); - g.bench_function("pop_verify", move |b| { - b.iter(|| { - let result = pop.verify(&kp.public_key); - assert!(result.is_ok()); - }) - }); -} - -fn sign(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - let priv_key = bls12381::PrivateKey::generate(&mut rng); - let msg = random_message(&mut rng); - - g.throughput(Throughput::Elements(1)); - g.bench_function("sign", move |b| b.iter(|| priv_key.sign(&msg).unwrap())); -} - -fn verify_signature_share(g: &mut BenchmarkGroup) { - let mut rng = thread_rng(); - - let keypair = KeyPair::::generate(&mut rng); - let msg = random_message(&mut rng); - let sig = keypair.private_key.sign(&msg).unwrap(); - - g.throughput(Throughput::Elements(1)); - g.bench_function("verify_signature_share", move |b| { - b.iter(|| { - let result = sig.verify(&msg, &keypair.public_key); - assert!(result.is_ok()); - }) - }); -} - -fn aggregate_pks(g: &mut BenchmarkGroup, size: usize) { - let mut rng = thread_rng(); - - // pick a bunch of random keypairs - let key_pairs: Vec> = - random_keypairs(&mut rng, size); - - g.throughput(Throughput::Elements(size as u64)); - g.bench_with_input( - BenchmarkId::new("aggregate_pks", size), - &size, - |b, &_size| { - b.iter_batched( - || { - let mut pks = vec![]; - for kp in key_pairs.iter() { - pks.push(&kp.public_key); - } - - pks - }, - |pks| { - let result = bls12381::PublicKey::aggregate(pks); - assert!(result.is_ok()); - }, - BatchSize::SmallInput, - ); - }, - ); -} - -fn aggregate_sigshare(g: &mut BenchmarkGroup, size: usize) { - let mut rng = thread_rng(); - - // pick a bunch of random keypairs - let key_pairs: Vec> = - random_keypairs(&mut rng, size); - - g.throughput(Throughput::Elements(size as u64)); - g.bench_with_input( - BenchmarkId::new("aggregate_sigshare", size), - &size, - |b, &_size| { - // pick a random message to aggregate a multisignature on - let msg = random_message(&mut rng); - - b.iter_batched( - || { - // each signer computes a signature share on the random message - let mut sigshares = vec![]; - for kp in key_pairs.iter() { - sigshares.push(kp.private_key.sign(&msg).unwrap()); - } - sigshares - }, - |sigshares| { - let result = bls12381::Signature::aggregate(sigshares); - assert!(result.is_ok()); - }, - BatchSize::SmallInput, - ); - }, - ); -} - -/// Benchmarks the time to verify a multisignature from the perspective of a verifier who has the -/// public keys of `n` signers and receives a multisignature from `size` of them -fn verify_multisig(g: &mut BenchmarkGroup, size: usize) { - let mut rng = thread_rng(); - - // pick `n` random keypairs - let mut key_pairs = vec![]; - let n = size * 2; - - for _ in 0..n { - key_pairs.push(KeyPair::::generate(&mut rng)); - } - - g.throughput(Throughput::Elements(size as u64)); - g.bench_with_input( - BenchmarkId::new("verify_multisig", size), - &size, - |b, &size| { - // pick a random message to aggregate a multisignature on - let msg = random_message(&mut rng); - - b.iter_batched( - || { - // pick a random subset of signers - let subset = random_subset(&mut rng, n, size); - - // each of the selected signers computes a signature share on the random message - let mut sigshares = vec![]; - let mut pks = vec![]; - - for i in subset { - sigshares.push(key_pairs[i].private_key.sign(&msg).unwrap()); - pks.push(&key_pairs[i].public_key) - } - - let multisig = bls12381::Signature::aggregate(sigshares).unwrap(); - - (pks, multisig) - }, - |(pks, multisig)| { - let aggpk = bls12381::PublicKey::aggregate(pks).unwrap(); - - let result = multisig.verify(&msg, &aggpk); - - assert!(result.is_ok()); - }, - BatchSize::SmallInput, - ); - }, - ); -} - -/// Benchmarks the time to verify an aggregate signature from the perspective of a verifier who -/// receives an aggregate signature from `n` signers. -fn verify_aggsig(g: &mut BenchmarkGroup, n: usize) { - let mut rng = thread_rng(); - - // pick `n` random keypairs - let mut key_pairs = vec![]; - - for _ in 0..n { - key_pairs.push(KeyPair::::generate(&mut rng)); - } - - g.throughput(Throughput::Elements(n as u64)); - g.bench_with_input(BenchmarkId::new("verify_aggsig", n), &n, |b, &_n| { - b.iter_batched( - || { - // each of the signers computes a signature share on a random message - let mut sigshares = vec![]; - let mut pks = vec![]; - let mut msgs = vec![]; - - for kp in key_pairs.iter() { - msgs.push(random_message(&mut rng)); - sigshares.push(kp.private_key.sign(msgs.last().unwrap()).unwrap()); - pks.push(&kp.public_key) - } - - let aggsig = bls12381::Signature::aggregate(sigshares).unwrap(); - - (msgs, pks, aggsig) - }, - |(msgs, pks, aggsig)| { - let msgs_refs = msgs.iter().collect::>(); - - let result = aggsig.verify_aggregate(&msgs_refs, &pks); - - assert!(result.is_ok()); - }, - BatchSize::SmallInput, - ); - }); -} - -criterion_group!( - name = bls12381_benches; - config = Criterion::default(); //.measurement_time(Duration::from_secs(100)); - targets = bench_group); -criterion_main!(bls12381_benches); diff --git a/crates/aptos-crypto/benches/hash.rs b/crates/aptos-crypto/benches/hash.rs index e72ce1dd2716b3..c4d5b429cbe572 100644 --- a/crates/aptos-crypto/benches/hash.rs +++ b/crates/aptos-crypto/benches/hash.rs @@ -4,7 +4,7 @@ #[macro_use] extern crate criterion; -use aptos_crypto::{bls12381::DST_BLS_SIG_IN_G2_WITH_POP, test_utils::random_bytes}; +use aptos_crypto::test_utils::random_bytes; use blake2::{ digest::{Update, VariableOutput}, Blake2bVar, @@ -41,8 +41,6 @@ fn bench_group(c: &mut Criterion) { sha2_256(&mut group, n); sha2_512(&mut group, n); sha3_256(&mut group, n); - hash_to_g1(&mut group, n, DST_BLS_SIG_IN_G2_WITH_POP); - hash_to_g2(&mut group, n, DST_BLS_SIG_IN_G2_WITH_POP); keccak256(&mut group, n); blake2_blake2b_256(&mut group, n); blake2_rfc_blake2b_256(&mut group, n); diff --git a/crates/aptos-crypto/src/bls12381/bls12381_keys.rs b/crates/aptos-crypto/src/bls12381/bls12381_keys.rs deleted file mode 100644 index e6e95ed2bfeb71..00000000000000 --- a/crates/aptos-crypto/src/bls12381/bls12381_keys.rs +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -//! This module provides APIs for private keys and public keys used in Boneh-Lynn-Shacham (BLS) -//! aggregate signatures (including individual signatures and multisignatures) implemented on top of -//! Barreto-Lynn-Scott BLS12-381 elliptic curves (). -//! -//! The `PublicKey` struct is used to represent both the public key of an individual signer -//! as well as the aggregate public key of several signers. Before passing this struct as an -//! argument, the caller should *always* verify its proof-of-possession (PoP) via -//! `ProofOfPossession::verify`. -//! -//! The `PublicKey::aggregate` API assumes the caller has already verified -//! proofs-of-possession for all the given public keys and therefore all public keys are valid, -//! prime-order subgroup elements. -//! -//! In general, with the exception of `ProofOfPossession::verify` no library function should -//! be given a public key as argument without first verifying that public key's PoP. Note that -//! for aggregate public keys obtained via `PublicKey::aggregate` there is no PoP to verify, but -//! the security assumption will be that all public keys given as input to this function have had -//! their PoPs verified. - -use crate::{ - bls12381, bls12381::DST_BLS_SIG_IN_G2_WITH_POP, hash::CryptoHash, signing_message, traits, - CryptoMaterialError, Genesis, Length, Uniform, ValidCryptoMaterial, - ValidCryptoMaterialStringExt, VerifyingKey, -}; -use anyhow::{anyhow, Result}; -use aptos_crypto_derive::{DeserializeKey, SerializeKey, SilentDebug, SilentDisplay}; -use serde::Serialize; -use std::{convert::TryFrom, fmt}; - -#[derive(Clone, Eq, SerializeKey, DeserializeKey)] -/// A BLS12381 public key -pub struct PublicKey { - pub(crate) pubkey: blst::min_pk::PublicKey, - // NOTE: In order to minimize the size of this struct, we do not keep the PoP here. - // One reason for this is these PKs are stored in the root of the Merkle accumulator. -} - -#[derive(SerializeKey, DeserializeKey, SilentDebug, SilentDisplay)] -/// A BLS12381 private key -pub struct PrivateKey { - pub(crate) privkey: blst::min_pk::SecretKey, -} - -////////////////////////////////////////////////////// -// Implementation of public-and-private key structs // -////////////////////////////////////////////////////// - -impl PublicKey { - /// The length of a serialized PublicKey struct. - // NOTE: We have to hardcode this here because there is no library-defined constant. - pub const LENGTH: usize = 48; - - /// Serialize a PublicKey. - pub fn to_bytes(&self) -> [u8; Self::LENGTH] { - self.pubkey.to_bytes() - } - - /// Subgroup-checks the public key (i.e., verifies the public key is an element of the prime-order - /// subgroup and it is not the identity element). - /// - /// WARNING: Subgroup-checking is done implicitly when verifying the proof-of-possession (PoP) for - /// this public key in `ProofOfPossession::verify`, so this function should not be called - /// separately for most use-cases. We leave it here just in case. - pub fn subgroup_check(&self) -> Result<()> { - self.pubkey.validate().map_err(|e| anyhow!("{:?}", e)) - } - - /// Aggregates the public keys of several signers into an aggregate public key, which can be later - /// used to verify a multisig aggregated from those signers. - /// - /// WARNING: This function assumes all public keys have had their proofs-of-possession verified - /// and have thus been group-checked. - pub fn aggregate(pubkeys: Vec<&Self>) -> Result { - let blst_pubkeys: Vec<_> = pubkeys.iter().map(|pk| &pk.pubkey).collect(); - - // CRYPTONOTE(Alin): We assume the PKs have had their PoPs verified and thus have also been subgroup-checked - let aggpk = blst::min_pk::AggregatePublicKey::aggregate(&blst_pubkeys[..], false) - .map_err(|e| anyhow!("{:?}", e))?; - - Ok(PublicKey { - pubkey: aggpk.to_public_key(), - }) - } -} - -impl PrivateKey { - /// The length of a serialized PrivateKey struct. - // NOTE: We have to hardcode this here because there is no library-defined constant - pub const LENGTH: usize = 32; - - /// Serialize a PrivateKey. - pub fn to_bytes(&self) -> [u8; Self::LENGTH] { - self.privkey.to_bytes() - } -} - -/////////////////////// -// PrivateKey Traits // -/////////////////////// - -impl traits::PrivateKey for PrivateKey { - type PublicKeyMaterial = PublicKey; -} - -impl traits::SigningKey for PrivateKey { - type SignatureMaterial = bls12381::Signature; - type VerifyingKeyMaterial = PublicKey; - - fn sign( - &self, - message: &T, - ) -> Result { - Ok(bls12381::Signature { - sig: self - .privkey - .sign(&signing_message(message)?, DST_BLS_SIG_IN_G2_WITH_POP, &[]), - }) - } - - #[cfg(any(test, feature = "fuzzing"))] - fn sign_arbitrary_message(&self, message: &[u8]) -> bls12381::Signature { - bls12381::Signature { - sig: self.privkey.sign(message, DST_BLS_SIG_IN_G2_WITH_POP, &[]), - } - } -} - -impl traits::ValidCryptoMaterial for PrivateKey { - fn to_bytes(&self) -> Vec { - self.to_bytes().to_vec() - } -} - -impl Length for PrivateKey { - fn length(&self) -> usize { - Self::LENGTH - } -} - -impl TryFrom<&[u8]> for PrivateKey { - type Error = CryptoMaterialError; - - /// Deserializes a PrivateKey from a sequence of bytes. - fn try_from(bytes: &[u8]) -> std::result::Result { - Ok(Self { - privkey: blst::min_pk::SecretKey::from_bytes(bytes) - .map_err(|_| CryptoMaterialError::DeserializationError)?, - }) - } -} - -impl Uniform for PrivateKey { - fn generate(rng: &mut R) -> Self - where - R: ::rand::RngCore + ::rand::CryptoRng, - { - // CRYPTONOTE(Alin): This "initial key material (IKM)" is the randomness used inside key_gen - // below to pseudo-randomly derive the secret key via an HKDF - // (see ) - let mut ikm = [0u8; 32]; - rng.fill_bytes(&mut ikm); - let privkey = - blst::min_pk::SecretKey::key_gen(&ikm, &[]).expect("ikm length should be higher"); - Self { privkey } - } -} - -impl Genesis for PrivateKey { - fn genesis() -> Self { - let mut buf = [0u8; Self::LENGTH]; - buf[Self::LENGTH - 1] = 1; - Self::try_from(buf.as_ref()).unwrap() - } -} - -#[cfg(feature = "assert-private-keys-not-cloneable")] -static_assertions::assert_not_impl_any!(PrivateKey: Clone); - -#[cfg(any(test, feature = "cloneable-private-keys"))] -impl Clone for PrivateKey { - fn clone(&self) -> Self { - let serialized: &[u8] = &(self.to_bytes()); - PrivateKey::try_from(serialized).unwrap() - } -} - -////////////////////// -// PublicKey Traits // -////////////////////// - -impl From<&PrivateKey> for PublicKey { - fn from(private_key: &PrivateKey) -> Self { - Self { - pubkey: private_key.privkey.sk_to_pk(), - } - } -} - -impl traits::PublicKey for PublicKey { - type PrivateKeyMaterial = PrivateKey; -} - -impl VerifyingKey for PublicKey { - type SignatureMaterial = bls12381::Signature; - type SigningKeyMaterial = PrivateKey; -} - -impl ValidCryptoMaterial for PublicKey { - fn to_bytes(&self) -> Vec { - self.to_bytes().to_vec() - } -} - -impl Length for PublicKey { - fn length(&self) -> usize { - Self::LENGTH - } -} - -impl TryFrom<&[u8]> for PublicKey { - type Error = CryptoMaterialError; - - /// Deserializes a PublicKey from a sequence of bytes. - /// - /// WARNING: Does NOT subgroup-check the public key! Instead, the caller is responsible for - /// verifying the public key's proof-of-possession (PoP) via `ProofOfPossession::verify`, - /// which implicitly subgroup-checks the public key. - /// - /// NOTE: This function will only check that the PK is a point on the curve: - /// - `blst::min_pk::PublicKey::from_bytes(bytes)` calls `blst::min_pk::PublicKey::deserialize(bytes)`, - /// which calls `$pk_deser` in , - /// which is mapped to `blst_p1_deserialize` in - /// - `blst_p1_deserialize` eventually calls `POINTonE1_Deserialize_BE`, which checks - /// the point is on the curve: - fn try_from(bytes: &[u8]) -> std::result::Result { - Ok(Self { - pubkey: blst::min_pk::PublicKey::from_bytes(bytes) - .map_err(|_| CryptoMaterialError::DeserializationError)?, - }) - } -} - -impl std::hash::Hash for PublicKey { - fn hash(&self, state: &mut H) { - let encoded_pubkey = self.to_bytes(); - state.write(&encoded_pubkey); - } -} - -// PartialEq trait implementation is required by the std::hash::Hash trait implementation above -impl PartialEq for PublicKey { - fn eq(&self, other: &Self) -> bool { - self.to_bytes()[..] == other.to_bytes()[..] - } -} - -impl fmt::Debug for PublicKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", hex::encode(self.to_bytes())) - } -} - -impl fmt::Display for PublicKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", hex::encode(self.to_bytes())) - } -} - -#[cfg(any(test, feature = "fuzzing"))] -use crate::test_utils::KeyPair; -#[cfg(any(test, feature = "fuzzing"))] -use proptest::prelude::*; - -/// Produces a uniformly random BLS keypair from a seed -#[cfg(any(test, feature = "fuzzing"))] -pub fn keypair_strategy() -> impl Strategy> { - crate::test_utils::uniform_keypair_strategy::() -} - -#[cfg(any(test, feature = "fuzzing"))] -impl proptest::arbitrary::Arbitrary for PublicKey { - type Parameters = (); - type Strategy = BoxedStrategy; - - fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - crate::test_utils::uniform_keypair_strategy::() - .prop_map(|v| v.public_key) - .boxed() - } -} diff --git a/crates/aptos-crypto/src/bls12381/bls12381_pop.rs b/crates/aptos-crypto/src/bls12381/bls12381_pop.rs deleted file mode 100644 index 146984fad7259b..00000000000000 --- a/crates/aptos-crypto/src/bls12381/bls12381_pop.rs +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -//! This module provides APIs for _proofs-of-possesion (PoPs)_ used to prevent _rogue-key attacks_, -//! both for multisignatures and aggregate signatures. -//! -//! Rogue-key attacks were first introduced by Micali, Ohta and Reyzin [^MOR01] and PoPs were first -//! introduced by Ristenpart and Yilek [^RY07]. -//! -//! [^MOR01]: Accountable-Subgroup Multisignatures: Extended Abstract; by Micali, Silvio and Ohta, Kazuo and Reyzin, Leonid; in Proceedings of the 8th ACM Conference on Computer and Communications Security; 2001; -//! [^RY07]: The Power of Proofs-of-Possession: Securing Multiparty Signatures against Rogue-Key Attacks; by Ristenpart, Thomas and Yilek, Scott; in Advances in Cryptology - EUROCRYPT 2007; 2007 - -use crate::{ - bls12381::bls12381_keys::{PrivateKey, PublicKey}, - CryptoMaterialError, Length, ValidCryptoMaterial, ValidCryptoMaterialStringExt, -}; -use anyhow::{anyhow, Result}; -use aptos_crypto_derive::{DeserializeKey, SerializeKey}; -use blst::BLST_ERROR; -use std::{convert::TryFrom, fmt}; - -/// Domain separation tag (DST) for hashing a public key before computing its proof-of-possesion (PoP), -/// which is also just a signature. -pub const DST_BLS_POP_IN_G2: &[u8] = b"BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; - -#[derive(Clone, Eq, SerializeKey, DeserializeKey)] -/// A proof-of-possesion (PoP) of a BLS12381 private key. -/// This is just a BLS signature on the corresponding public key. -pub struct ProofOfPossession { - pub(crate) pop: blst::min_pk::Signature, -} - -impl ProofOfPossession { - /// The length of a serialized ProofOfPossession struct. - // NOTE: We have to hardcode this here because there is no library-defined constant - pub const LENGTH: usize = 96; - - /// Serialize a ProofOfPossession. - pub fn to_bytes(&self) -> [u8; Self::LENGTH] { - self.pop.to_bytes() - } - - /// Subgroup-check the PoP (i.e., verifies the PoP is a valid group element). - /// - /// WARNING: Subgroup-checking is done implicitly in `verify` below, so this function need not be called - /// separately for most use-cases, as it incurs a performance penalty. We leave it here just in case. - pub fn subgroup_check(&self) -> Result<()> { - self.pop.validate(true).map_err(|e| anyhow!("{:?}", e)) - } - - /// Verifies the proof-of-possesion (PoP) of the private key corresponding to the specified - /// BLS public key. Implicitly, subgroup checks the PoP and the specified public key, so - /// the caller is not responsible for doing it manually. - pub fn verify(&self, pk: &PublicKey) -> Result<()> { - // CRYPTONOTE(Alin): We call the signature verification function with pk_validate set to true - // since we do not necessarily trust the PK we deserialized over the network whose PoP we are - // verifying here. - let result = self.pop.verify( - true, - &pk.to_bytes(), - DST_BLS_POP_IN_G2, - &[], - &pk.pubkey, - true, - ); - if result == BLST_ERROR::BLST_SUCCESS { - Ok(()) - } else { - Err(anyhow!( - "Proof-of-possession (PoP) did NOT verify: {:?}", - result - )) - } - } - - /// Creates a proof-of-possesion (PoP) of the specified BLS private key. This function - /// inefficiently recomputes the public key from the private key. To avoid this, the caller can - /// use `create_with_pubkey` instead, which accepts the public key as a second input. - pub fn create(sk: &PrivateKey) -> ProofOfPossession { - // CRYPTONOTE(Alin): The standard does not detail how the PK should be serialized for hashing purposes; we just do the obvious. - let pk = PublicKey { - pubkey: sk.privkey.sk_to_pk(), - }; - - ProofOfPossession::create_with_pubkey(sk, &pk) - } - - /// Creates a proof-of-possesion (PoP) of the specified BLS private key. Takes the - /// corresponding public key as input, to avoid inefficiently recomputing it from the - /// private key. - /// - /// WARNING: Does not subgroup-check the PK, since this function will be typically called on - /// a freshly-generated key-pair or on a correctly-deserialized keypair. - pub fn create_with_pubkey(sk: &PrivateKey, pk: &PublicKey) -> ProofOfPossession { - // CRYPTONOTE(Alin): The standard does not detail how the PK should be serialized for hashing purposes; we just do the obvious. - let pk_bytes = pk.to_bytes(); - - // CRYPTONOTE(Alin): We hash with DST_BLS_POP_IN_G2 as per https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature#section-4.2.3 - ProofOfPossession { - pop: sk.privkey.sign(&pk_bytes, DST_BLS_POP_IN_G2, &[]), - } - } -} - -////////////////////////////// -// ProofOfPossession Traits // -////////////////////////////// - -impl ValidCryptoMaterial for ProofOfPossession { - fn to_bytes(&self) -> Vec { - self.to_bytes().to_vec() - } -} -impl Length for ProofOfPossession { - fn length(&self) -> usize { - Self::LENGTH - } -} - -impl PartialEq for ProofOfPossession { - fn eq(&self, other: &Self) -> bool { - self.pop.to_bytes() == other.to_bytes() - } -} - -impl TryFrom<&[u8]> for ProofOfPossession { - type Error = CryptoMaterialError; - - /// Deserializes a BLS PoP from a sequence of bytes. - /// - /// WARNING: Does NOT subgroup-check the PoP! This is done implicitly when verifying the PoP in - /// `ProofOfPossession::verify` - fn try_from(bytes: &[u8]) -> std::result::Result { - Ok(Self { - pop: blst::min_pk::Signature::from_bytes(bytes) - .map_err(|_| CryptoMaterialError::DeserializationError)?, - }) - } -} - -impl std::hash::Hash for ProofOfPossession { - fn hash(&self, state: &mut H) { - let encoded_signature = self.to_bytes(); - state.write(&encoded_signature); - } -} - -impl fmt::Debug for ProofOfPossession { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", hex::encode(self.to_bytes())) - } -} - -impl fmt::Display for ProofOfPossession { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", hex::encode(self.to_bytes())) - } -} diff --git a/crates/aptos-crypto/src/bls12381/bls12381_sigs.rs b/crates/aptos-crypto/src/bls12381/bls12381_sigs.rs deleted file mode 100644 index 833104279e6af6..00000000000000 --- a/crates/aptos-crypto/src/bls12381/bls12381_sigs.rs +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -//! This module provides APIs for aggregating and verifying Boneh-Lynn-Shacham (BLS) aggregate -//! signatures (including individual signatures and multisignatures), implemented on top of -//! Barreto-Lynn-Scott BLS12-381 elliptic curves (. -//! -//! The `Signature` struct is used to represent either a: -//! -//! 1. signature share from an individual signer -//! 2. multisignature on a single message from many signers -//! 3. aggregate signature on different messages from many signers -//! -//! The signature verification APIs in `Signature::verify`, `Signature::verify_arbitrary_msg`, -//! `Signature::verify_aggregate` and `Signature::verify_aggregate_arbitrary_msg` do NOT -//! assume the signature to be a valid group element and will implicitly "subgroup-check" it. This -//! makes the caller's job easier and, more importantly, makes the library safer to use. - -use crate::{ - bls12381::{ - bls12381_keys::{PrivateKey, PublicKey}, - DST_BLS_SIG_IN_G2_WITH_POP, - }, - hash::CryptoHash, - signing_message, traits, CryptoMaterialError, Length, ValidCryptoMaterial, - ValidCryptoMaterialStringExt, -}; -use anyhow::{anyhow, Result}; -use aptos_crypto_derive::{DeserializeKey, SerializeKey}; -use blst::BLST_ERROR; -use serde::Serialize; -use std::{convert::TryFrom, fmt}; - -#[derive(Clone, Eq, SerializeKey, DeserializeKey)] -/// Either (1) a BLS signature share from an individual signer, (2) a BLS multisignature or (3) a -/// BLS aggregate signature -pub struct Signature { - pub(crate) sig: blst::min_pk::Signature, -} - -//////////////////////////////////////// -// Implementation of Signature struct // -//////////////////////////////////////// - -impl Signature { - /// The length of a serialized Signature struct. - // NOTE: We have to hardcode this here because there is no library-defined constant - pub const LENGTH: usize = 96; - - /// Serialize a Signature. - pub fn to_bytes(&self) -> [u8; Self::LENGTH] { - self.sig.to_bytes() - } - - /// Subgroup-checks the signature (i.e., verifies the signature is a valid group element). - /// - /// WARNING: Subgroup-checking is done implicitly when verifying signatures via - /// `Signature::verify_arbitrary_msg`. Therefore, this function should not be called separately - /// for most use-cases. We leave it here just in case. - pub fn subgroup_check(&self) -> Result<()> { - self.sig.validate(true).map_err(|e| anyhow!("{:?}", e)) - } - - /// Optimistically-aggregate signatures shares into either (1) a multisignature or (2) an aggregate - /// signature. The individual signature shares could be adversarial. Nonetheless, for performance - /// reasons, we do not subgroup-check the signature shares here, since the verification of the - /// returned multi-or-aggregate signature includes such a subgroup check. As a result, adversarial - /// signature shares cannot lead to forgeries. - pub fn aggregate(sigs: Vec) -> Result { - let sigs: Vec<_> = sigs.iter().map(|s| &s.sig).collect(); - let agg_sig = blst::min_pk::AggregateSignature::aggregate(&sigs[..], false) - .map_err(|e| anyhow!("{:?}", e))?; - Ok(Signature { - sig: agg_sig.to_signature(), - }) - } - - /// Verifies an aggregate signature on the messages in `msgs` under the public keys in `pks`. - /// Specifically, verifies that each `msgs[i]` is signed under `pks[i]`. The messages in `msgs` - /// do *not* have to be all different, since we use proofs-of-possession (PoPs) to prevent rogue - /// key attacks. - /// - /// WARNING: This function assumes that the public keys have been subgroup-checked by the caller - /// implicitly when verifying their proof-of-possession (PoP) in `ProofOfPossession::verify`. - pub fn verify_aggregate_arbitrary_msg(&self, msgs: &[&[u8]], pks: &[&PublicKey]) -> Result<()> { - let pks = pks - .iter() - .map(|&pk| &pk.pubkey) - .collect::>(); - - let result = self - .sig - .aggregate_verify(true, msgs, DST_BLS_SIG_IN_G2_WITH_POP, &pks, false); - - if result == BLST_ERROR::BLST_SUCCESS { - Ok(()) - } else { - Err(anyhow!("{:?}", result)) - } - } - - /// Serializes the messages of type `T` to bytes and calls `Signature::verify_aggregate_arbitrary_msg`. - pub fn verify_aggregate( - &self, - msgs: &[&T], - pks: &[&PublicKey], - ) -> Result<()> { - let mut messages: Vec> = vec![]; - for message in msgs { - messages.push(signing_message(*message)?); - } - - let msgs_refs = messages - .iter() - .map(|m| m.as_slice()) - .collect::>(); - - self.verify_aggregate_arbitrary_msg(&msgs_refs, pks) - } - - /// Return a dummy signature for testing. - #[cfg(any(test, feature = "fuzzing"))] - pub fn dummy_signature() -> Self { - use crate::{Genesis, SigningKey}; - - let private_key = PrivateKey::genesis(); - - let msg = b"hello foo"; - private_key.sign_arbitrary_message(msg) - } -} - -/////////////////////////// -// SignatureShare Traits // -/////////////////////////// -impl traits::Signature for Signature { - type SigningKeyMaterial = PrivateKey; - type VerifyingKeyMaterial = PublicKey; - - /// Serializes the message of type `T` to bytes and calls `Signature::verify_arbitrary_msg`. - fn verify(&self, message: &T, public_key: &PublicKey) -> Result<()> { - self.verify_arbitrary_msg(&signing_message(message)?, public_key) - } - - /// Verifies a BLS signature share or multisignature. Does not assume the signature to be - /// subgroup-checked. (For verifying aggregate signatures on different messages, a different - /// `verify_aggregate_arbitray_msg` function can be used.) - /// - /// WARNING: This function does assume the public key has been subgroup-checked by the caller, - /// either (1) implicitly when verifying the public key's proof-of-possession (PoP) in - /// `ProofOfPossession::verify` or (2) via `Validatable::::validate()`. - fn verify_arbitrary_msg(&self, message: &[u8], public_key: &PublicKey) -> Result<()> { - let result = self.sig.verify( - true, - message, - DST_BLS_SIG_IN_G2_WITH_POP, - &[], - &public_key.pubkey, - false, - ); - if result == BLST_ERROR::BLST_SUCCESS { - Ok(()) - } else { - Err(anyhow!("{:?}", result)) - } - } - - fn to_bytes(&self) -> Vec { - self.to_bytes().to_vec() - } -} - -impl ValidCryptoMaterial for Signature { - fn to_bytes(&self) -> Vec { - self.to_bytes().to_vec() - } -} -impl Length for Signature { - fn length(&self) -> usize { - Self::LENGTH - } -} - -impl fmt::Debug for Signature { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", hex::encode(self.to_bytes())) - } -} - -impl fmt::Display for Signature { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", hex::encode(self.to_bytes())) - } -} - -impl TryFrom<&[u8]> for Signature { - type Error = CryptoMaterialError; - - /// Deserializes a Signature from a sequence of bytes. - /// - /// WARNING: Does NOT subgroup-check the signature! Instead, this will be done implicitly when - /// verifying the signature. - fn try_from(bytes: &[u8]) -> std::result::Result { - Ok(Self { - sig: blst::min_pk::Signature::from_bytes(bytes) - .map_err(|_| CryptoMaterialError::DeserializationError)?, - }) - } -} - -impl std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - let encoded_signature = self.to_bytes(); - state.write(&encoded_signature); - } -} - -// PartialEq trait implementation is required by the std::hash::Hash trait implementation above -impl PartialEq for Signature { - fn eq(&self, other: &Self) -> bool { - self.to_bytes()[..] == other.to_bytes()[..] - } -} diff --git a/crates/aptos-crypto/src/bls12381/bls12381_validatable.rs b/crates/aptos-crypto/src/bls12381/bls12381_validatable.rs deleted file mode 100644 index 7f444ff4173414..00000000000000 --- a/crates/aptos-crypto/src/bls12381/bls12381_validatable.rs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -//! This module implements the Validate trait for BLS12-381 public keys, which enables library users -//! to make sure public keys used for verifying normal (non-aggregated) signatures lie in the prime-order -//! subgroup of the BLS12-381 group. -//! -//! NOTE: For public keys used to verify multisignatures, aggregate signatures and signature shares, -//! library users need NOT rely on this `Validatable` wrapper and should instead verify -//! the proof-of-possession (PoP) of a public key, which implicitly guarantees the PK lies in the -//! prime-order subgroup. (See `bls12381_pop.rs` and `mod.rs` for details.) - -use crate::{bls12381::PublicKey, validatable::Validate, CryptoMaterialError, ValidCryptoMaterial}; -use anyhow::{anyhow, Result}; -use serde::{Deserialize, Serialize}; -use std::{convert::TryFrom, hash::Hash}; - -/// An unvalidated `PublicKey` -#[derive(Debug, Clone, Eq)] -pub struct UnvalidatedPublicKey(pub(crate) [u8; PublicKey::LENGTH]); - -impl UnvalidatedPublicKey { - /// Return key as bytes - pub fn to_bytes(&self) -> [u8; PublicKey::LENGTH] { - self.0 - } -} - -impl TryFrom<&[u8]> for UnvalidatedPublicKey { - type Error = CryptoMaterialError; - - /// Deserializes an UnvalidatedPublicKey from a sequence of bytes. - /// - /// WARNING: Does NOT do any checks whatsoever on these bytes beyond checking the length. - /// The returned `UnvalidatedPublicKey` can only be used to create a `Validatable::` - /// via `Validatable::::from_unvalidated`. - fn try_from(bytes: &[u8]) -> std::result::Result { - if bytes.len() != PublicKey::LENGTH { - Err(CryptoMaterialError::DeserializationError) - } else { - Ok(Self(<[u8; PublicKey::LENGTH]>::try_from(bytes).unwrap())) - } - } -} - -impl ValidCryptoMaterial for UnvalidatedPublicKey { - fn to_bytes(&self) -> Vec { - self.0.to_vec() - } -} - -impl Serialize for UnvalidatedPublicKey { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - if serializer.is_human_readable() { - let encoded = ::hex::encode(self.0); - serializer.serialize_str(&format!("0x{}", encoded)) - } else { - // See comment in deserialize_key. - serializer - .serialize_newtype_struct("PublicKey", serde_bytes::Bytes::new(self.0.as_ref())) - } - } -} - -impl<'de> Deserialize<'de> for UnvalidatedPublicKey { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - use serde::de::Error; - - if deserializer.is_human_readable() { - let encoded_key = ::deserialize(deserializer)?; - let bytes_out = ::hex::decode(&encoded_key[2..]).map_err(D::Error::custom)?; - <[u8; PublicKey::LENGTH]>::try_from(bytes_out.as_ref()) - .map(UnvalidatedPublicKey) - .map_err(D::Error::custom) - } else { - // In order to preserve the Serde data model and help analysis tools, - // make sure to wrap our value in a container with the same name - // as the original type. - #[derive(Deserialize)] - #[serde(rename = "PublicKey")] - struct Value<'a>(&'a [u8]); - - let value = Value::deserialize(deserializer)?; - <[u8; PublicKey::LENGTH]>::try_from(value.0) - .map(UnvalidatedPublicKey) - .map_err(D::Error::custom) - } - } -} - -impl Hash for UnvalidatedPublicKey { - fn hash(&self, state: &mut H) { - state.write(&self.0) - } -} - -impl PartialEq for UnvalidatedPublicKey { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl Validate for PublicKey { - type Unvalidated = UnvalidatedPublicKey; - - fn validate(unvalidated: &Self::Unvalidated) -> Result { - let pk = Self::try_from(unvalidated.0.as_ref())?; - - if pk.subgroup_check().is_err() { - return Err(anyhow!("{:?}", CryptoMaterialError::SmallSubgroupError)); - } - - Ok(pk) - } - - fn to_unvalidated(&self) -> Self::Unvalidated { - UnvalidatedPublicKey(self.to_bytes()) - } -} - -#[cfg(test)] -mod test { - use crate::{ - bls12381::{PrivateKey, PublicKey, UnvalidatedPublicKey}, - test_utils::uniform_keypair_strategy, - validatable::Validate, - }; - use proptest::{prop_assert_eq, proptest}; - use std::{ - collections::hash_map::DefaultHasher, - hash::{Hash, Hasher}, - }; - - proptest! { - #[test] - fn bls12381_validatable_pk( - keypair in uniform_keypair_strategy::() - ) { - let valid = keypair.public_key; - let unvalidated = valid.to_unvalidated(); - - prop_assert_eq!(&unvalidated, &UnvalidatedPublicKey(valid.to_bytes())); - prop_assert_eq!(&valid, &PublicKey::validate(&unvalidated).unwrap()); - - // Ensure Serialize and Deserialize are implemented the same - - // BCS - A non-human-readable format - { - let serialized_valid = bcs::to_bytes(&valid).unwrap(); - let serialized_unvalidated = bcs::to_bytes(&unvalidated).unwrap(); - prop_assert_eq!(&serialized_valid, &serialized_unvalidated); - - let deserialized_valid_from_unvalidated: PublicKey = bcs::from_bytes(&serialized_unvalidated).unwrap(); - let deserialized_unvalidated_from_valid: UnvalidatedPublicKey = bcs::from_bytes(&serialized_valid).unwrap(); - - prop_assert_eq!(&valid, &deserialized_valid_from_unvalidated); - prop_assert_eq!(&unvalidated, &deserialized_unvalidated_from_valid); - } - - // JSON A human-readable format - { - let serialized_valid = serde_json::to_string(&valid).unwrap(); - let serialized_unvalidated = serde_json::to_string(&unvalidated).unwrap(); - prop_assert_eq!(&serialized_valid, &serialized_unvalidated); - - let deserialized_valid_from_unvalidated: PublicKey = serde_json::from_str(&serialized_unvalidated).unwrap(); - let deserialized_unvalidated_from_valid: UnvalidatedPublicKey = serde_json::from_str(&serialized_valid).unwrap(); - - prop_assert_eq!(&valid, &deserialized_valid_from_unvalidated); - prop_assert_eq!(&unvalidated, &deserialized_unvalidated_from_valid); - } - - - // Ensure Hash is implemented the same - let valid_hash = { - let mut hasher = DefaultHasher::new(); - valid.hash(&mut hasher); - hasher.finish() - }; - - let unvalidated_hash = { - let mut hasher = DefaultHasher::new(); - unvalidated.hash(&mut hasher); - hasher.finish() - }; - - prop_assert_eq!(valid_hash, unvalidated_hash); - } - } -} diff --git a/crates/aptos-crypto/src/bls12381/mod.rs b/crates/aptos-crypto/src/bls12381/mod.rs deleted file mode 100644 index 47471652f34e35..00000000000000 --- a/crates/aptos-crypto/src/bls12381/mod.rs +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -//! This module provides APIs for Boneh-Lynn-Shacham (BLS) aggregate signatures, including -//! normal (non-aggregated) signatures and multisignatures, on top of Barreto-Lynn-Scott BLS12-381 -//! elliptic curves. This module wraps the [blst](https://github.com/supranational/blst) library. -//! -//! Our multisignature and aggregate signature implementations are described in [^BLS04], [^Bold03], -//! except we use the proof-of-possession (PoP) scheme from [^RY07] to prevent rogue-key attacks -//! [^MOR01] where malicious signers adversarially pick their public keys in order to forge a -//! multisignature or forge an aggregate signature. -//! -//! Our normal (non-aggregated) signatures implementation requires CAREFUL use by developers to -//! prevent small-subgroup attacks. Specifically, developers must always wrap `bls12381::PublicKey` -//! objects as `Validatable::` and access the public key via -//! `Validatable::::valid()`. We give an example below. -//! -//! We implement the `Minimal-pubkey-size` variant from the BLS IETF draft standard [^bls-ietf-draft], -//! which puts the signatures in the group $\mathbb{G}_2$ and the public keys in $\mathbb{G}_1$. The -//! reasoning behind this choice is to minimize public key size, since public keys are posted on the -//! blockchain. -//! -//! # Overview of normal Boneh-Lynn-Shacham (BLS) signatures -//! -//! In a _normal signature scheme_, we have a single _signer_ who generates its own key-pair: -//! a _private-key_ and a corresponding _public key_. The signer can produce a _signature_ on a -//! _message_ `m` using its private-key. Any _verifier_ who has the public key can check that -//! the signature on `m` was produced by the signer. -//! -//! # Overview of Boneh-Lynn-Shacham (BLS) multisignatures -//! -//! In a _multisignature scheme_, we have `n` signers. Each signer `i` has their own key-pair `(sk_i, pk_i)`. -//! Any subset of `k` signers can collaborate to produce a succinct _multisignature_ on the *same* -//! message `m`. -//! -//! Typically, the `k` signers first agree on the message `m` via some protocol (e.g., `m` is the -//! latest block header in a blockchain protocol). Then, each signer produces a _signature share_ `s_i` -//! on `m` using their own private key `sk_i`. After this, each signer `i` sends their signature -//! share `s_i` to an _aggregator_: a dedicated, untrusted party who is responsible for aggregating -//! the signature shares into the final multisignature. For example, one of the signers themselves -//! could be the aggregator. -//! -//! Lastly, the aggregator can proceed in two ways: -//! -//! 1. Pessimistically verify each signature share, discarding the invalid ones, and then aggregate -//! the final multisignature. -//! -//! 2. Optimistically aggregate all signature shares, but verify the final multisignature at the end -//! to ensure no bad signature shares were included. If the multisignature does not verify, -//! revert to the pessimistic mode (or consider other approaches [^LM07]). -//! -//! Either way, the end result (assuming some of the signature shares were valid) will be a valid -//! multisignature on `m` which can be verified against an _aggregate public key_ of the involved -//! signers. -//! -//! Specifically, any verifier who knows the public keys of the signers whose shares were aggregated -//! into the multisignature, can first compute an _aggregate public key_ as a function of these -//! public keys and then verify the multisignature under this aggregate public key. -//! -//! Extremely important for security is that the verifier first ensure these public keys came with -//! valid proofs-of-possession (PoPs). Otherwise, multisignatures can be forged via _rogue-key attacks_ -//! [^MOR01]. -//! -//! # Overview of Boneh-Lynn-Shacham (BLS) aggregate signatures -//! -//! In an _aggregate signature scheme_ any subset of `k` out of `n` signers can collaborate to produce -//! a succinct _aggregate signature_ over (potentially) different message. Specifically, such an -//! aggregate signature is a succinct representation of `k` normal signatures, where the `i`th signature -//! from the `i`th signer is on some message `m_i`. Importantly, `m_i` might differ from the other `k-1` messages -//! signed by the other signers. -//! -//! Note that an aggregate signature where all the signed messages `m_i` are the same is just a -//! multisignature. -//! -//! Just like in a multisignature scheme, in an aggregate signature scheme there is an _aggregator_ -//! who receives _signature shares_ `s_i` from each signer `i` on their *own* message `m_i` and -//! aggregates the valid signature shares into an aggregate signature. (In contrast, recall that, -//! in a multisignature scheme, every signer `i` signed the same message `m`.) -//! -//! Aggregation proceeds the same as in a multisignature scheme (see notes in previous section). -//! -//! # A note on subgroup checks -//! -//! This library was written so that users who know nothing about _small subgroup attacks_ [^LL97], [^BCM+15e] -//! need not worry about them, **as long as library users either**: -//! -//! 1. For normal (non-aggregated) signature verification, wrap `PublicKey` objects using -//! `Validatable` -//! -//! 2. For multisignature, aggregate signature and signature share verification, library users -//! always verify a public key's proof-of-possession (PoP)** before aggregating it with other PKs -//! and before verifying signature shares with it. -//! -//! Nonetheless, we still provide `subgroup_check` methods for the `PublicKey` and `Signature` structs, -//! in case manual verification of subgroup membership is ever needed. -//! -//! # A note on domain separation tags (DSTs) -//! -//! Internal to this wrapper's implementation (and to the underlying blst library) is the careful -//! use of domain separation tags (DSTs) as per the BLS IETF draft standard [^bls-ietf-draft]. -//! -//! Specifically, **when signing a message** `m`, instead of signing as `H(m)^sk`, where `sk` is the -//! secret key, the library actually signs as `H(sig_dst | m)^sk`, where `sig_dst` is a DST for -//! message signing. -//! -//! In contrast, **when computing a proof-of-possesion (PoP)**, instead of signing the public key as -//! `H(pk)^sk`, the library actually signs as `H(sig_pop | pk)^sk`, where `sig_pop` is a DST for -//! signatures used during PoP creation. -//! -//! This way, we can clearly separate the message spaces of these two use cases of the secret key `sk`. -//! -//! # How to use this module to create and verify normal (non-aggregated) signatures on a single message -//! -//! A typical use of the normal (non-aggregated) signature library would look as follows. -//! -//! For signers: -//! -//! ``` -//! use std::iter::zip; -//! use aptos_crypto::test_utils::{KeyPair, TestAptosCrypto}; -//! use aptos_crypto::{bls12381, Signature, SigningKey, Uniform}; -//! use aptos_crypto::bls12381::bls12381_keys::{PrivateKey, PublicKey}; -//! use aptos_crypto::bls12381::ProofOfPossession; -//! use aptos_crypto_derive::{CryptoHasher, BCSCryptoHash}; -//! use rand_core::OsRng; -//! use serde::{Serialize, Deserialize}; -//! -//! let mut rng = OsRng; -//! -//! // A signer locally generated their own BLS key-pair via: -//! let kp = KeyPair::::generate(&mut rng); -//! -//! // Any arbitrary struct can be signed as long as it is properly "derived" via: -//! // -//! // #[derive(CryptoHasher, BCSCryptoHash, Serialize, Deserialize)] -//! // struct Message(String); -//! // -//! // Here, we'll sign an existing testing struct from `crates/aptos-crypto/src/test_utils.rs`: -//! // -//! // #[derive(Debug, Serialize, Deserialize)] -//! // pub struct TestAptosCrypto(pub String); -//! -//! -//! // The signer computes a normal signature on a message. -//! let message = TestAptosCrypto("test".to_owned()); -//! let sig = kp.private_key.sign(&message).unwrap(); -//! ``` -//! -//! For verifiers: -//! -//! ``` -//! use std::convert::TryFrom; -//! use std::iter::zip; -//! use aptos_crypto::test_utils::{KeyPair, TestAptosCrypto}; -//! use aptos_crypto::{bls12381, Signature, SigningKey, Uniform}; -//! use aptos_crypto::bls12381::bls12381_keys::{PrivateKey, PublicKey}; -//! use aptos_crypto::bls12381::{ProofOfPossession, UnvalidatedPublicKey}; -//! use aptos_crypto_derive::{CryptoHasher, BCSCryptoHash}; -//! use rand_core::OsRng; -//! use serde::{Serialize, Deserialize}; -//! use aptos_crypto::validatable::Validatable; -//! -//! // NOTE: These were generated by running `cargo test -- doc_test --ignored --nocapture` in `crates/aptos-crypto/` -//! let sk_bytes = hex::decode("65e0c364e0cc27ae4e90cb28059677c36fd11b47cbbab48a9cca3c34e92eefbb").unwrap(); -//! let pk_bytes = hex::decode("99ad6adb0a8b9a8c44dbf643a3ad6d11ff1fe90138db857382a8fc202334e6f8842e04055a729e4a4ba5b08161e7abd6").unwrap(); -//! // signature on TestAptosCrypto("test".to_owned()) -//! let sig_bytes = hex::decode("b266e156091c1d621304861654bae748cb3534bef86eb6ca1d482148ba7b1e3530eca47790a98971f421fe2d55f9d9af047807b5698cf559441b81288a022812d58669fee2d30b4c7bd86706c6a2128fd5b0c44c4bc171ca6e9d4c89196cac85").unwrap(); -//! -//! // A verifier typically obtains the public key of the signer (somehow) and deserializes it -//! -//! /////////////////////////////////////////////////////////////////////////////////////////////// -//! // WARNING: Before relying on any public key to verify a signature, a verifier MUST first // -//! // validate it using the `Validatable::` wrapper as follows: // -//! /////////////////////////////////////////////////////////////////////////////////////////////// -//! -//! // First, construct an UnvalidatedPublicKey struct -//! let pk_unvalidated = UnvalidatedPublicKey::try_from(pk_bytes.as_slice()); -//! if pk_unvalidated.is_err() { -//! println!("ERROR: Could NOT deserialize unvalidated PK"); -//! return; -//! } -//! -//! // Second, construct a Validatable:: struct out of this UnvalidatedPublicKey struct -//! let pk_validatable = Validatable::::from_unvalidated(pk_unvalidated.unwrap()); -//! -//! // Third, call validate() on it to get a subgroup-checked PK back. -//! // -//! // IMPORTANT NOTE: The result of this validation will be cached in a OnceCell so subsequent calls -//! // to this function will return very fast. -//! // -//! let pk = pk_validatable.validate(); -//! -//! if pk.is_err() { -//! println!("ERROR: Public key was either accidentally-corrupted or maliciously-generated."); -//! println!("Specifically, the public key is NOT a prime-order point."); -//! println!("As a result, this public key CANNOT be relied upon to verify any signatures!"); -//! return; -//! } -//! -//! let pk = pk.unwrap(); -//! let message = TestAptosCrypto("test".to_owned()); -//! -//! // deserialize the signature on `message` and verify it -//! let sig = bls12381::Signature::try_from(sig_bytes.as_slice()); -//! if sig.is_err() { -//! println!("ERROR: Could NOT deserialize signature"); -//! return; -//! } -//! -//! // Any verifier who has the signer's public key can verify the `(message, sig)` pair as: -//! let sig = sig.unwrap(); -//! if sig.verify(&message, &pk).is_ok() { -//! println!("Signature verified successfully!"); -//! } else { -//! println!("Signature did NOT verify!"); -//! } -//! -//! // If the verification passed, then the verifier is certain that the signer signed `message` -//! ``` -//! -//! # How to use this module to aggregate and verify multisignatures -//! -//! A typical use of the multisignature library would look as follows: -//! -//! ``` -//! use std::iter::zip; -//! use aptos_crypto::test_utils::KeyPair; -//! use aptos_crypto::{bls12381, Signature, SigningKey, Uniform}; -//! use aptos_crypto::bls12381::bls12381_keys::{PrivateKey, PublicKey}; -//! use aptos_crypto::bls12381::ProofOfPossession; -//! use aptos_crypto_derive::{CryptoHasher, BCSCryptoHash}; -//! use rand_core::OsRng; -//! use serde::{Serialize, Deserialize}; -//! -//! // Each signer locally generates their own BLS key-pair with a proof-of-possesion (PoP). -//! // We simulate this here, by storing each signer's key-pair in a vector. -//! let mut rng = OsRng; -//! -//! let num_signers = 1000; -//! -//! let mut key_pairs = vec![]; -//! let mut pops = vec![]; -//! for _ in 0..num_signers { -//! let kp = KeyPair::::generate(&mut rng); -//! pops.push(ProofOfPossession::create_with_pubkey(&kp.private_key, &kp.public_key)); -//! // Alternatively, but slower, can choose not to provide the PK and have it computed inside -//! // pops.push(ProofOfPossession::create(&kp.private_key)); -//! key_pairs.push(kp); -//! } -//! -//! // Any arbitrary struct can be signed as long as it is properly "derived" -//! #[derive(CryptoHasher, BCSCryptoHash, Serialize, Deserialize)] -//! struct Message(String); -//! -//! // Each signer then computes a signature share on a message. Again, we simulate using a vector. -//! let mut sigshares = vec![]; -//! let message = Message("test".to_owned()); -//! for kp in key_pairs.iter() { -//! let sig = kp.private_key.sign(&message).unwrap(); -//! sigshares.push(sig); -//! } -//! -//! // Then, an aggregator receives some of these signature shares and will attempt to aggregate -//! // them in a multisig. This aggregator can proceed _optimistically_ as follows: -//! -//! // First, when the aggregator boots up, it must verify that each signer's public key has a valid -//! // proof-of-possession (PoP)! -//! -//! /////////////////////////////////////////////////////////////////////////////////////////////// -//! // WARNING: Before relying on a public key to verify a multisignature or a signature share // -//! // one must MUST first verify that public key's PoP // -//! // // -//! // The importance of this step cannot be overstated! // -//! // // -//! // Put differently, a public key with an unverified PoP cannot be used securely for any // -//! // signature verification. This is why the code below first verifies PoPs of all public keys // -//! // that are later used to verify the multisignature against. // -//! /////////////////////////////////////////////////////////////////////////////////////////////// -//! for i in 0..pops.len() { -//! assert!(pops[i].verify(&key_pairs[i].public_key).is_ok()); -//! } -//! -//! // Second, now that the aggregator trusts the set of public keys, it can safely aggregate -//! // signature shares _optimistically_ into a multisignature which hopefully verifies. In this -//! // example, we assume the aggregator receives a signature share from every third signer (for simplicity). -//! -//! // Here, we simulate the aggregator receiving some signature shares. -//! let mut sigshares_received = vec![]; -//! for sigshare in sigshares.into_iter().step_by(3) { -//! sigshares_received.push(sigshare); -//! } -//! -//! // Here, the aggregator aggregates the received signature shares into a multisignature. -//! let multisig = bls12381::Signature::aggregate(sigshares_received.clone()).unwrap(); -//! -//! // Third, the aggregator checks that the _optimistic_ aggregation from above succeeded by -//! // verifying the multisig. For this, the aggregator will need to know the public keys of the -//! // signers whose signature shares were aggregated, so that it can aggregate them. -//! let mut pubkeys_to_agg = vec![]; -//! for kp in key_pairs.iter().step_by(3) { -//! pubkeys_to_agg.push(&kp.public_key); -//! } -//! -//! let aggpk = PublicKey::aggregate(pubkeys_to_agg.clone()).unwrap(); -//! -//! // Lastly, the aggregator checks the aggregated multisig verifies successfully. -//! assert!(multisig.verify(&message, &aggpk).is_ok()); -//! -//! // If the multisig failed verification, the aggregator can individually verify each of the -//! // signature shares to identify which ones are invalid and exclude them. There are also optimized -//! // methods for identifying bad signature shares faster when their relative frequency is low [^LM07]. -//! // However, we will not implement these yet. -//! for (sigshare, pk) in zip(sigshares_received, pubkeys_to_agg) { -//! assert!(sigshare.verify(&message, &pk).is_ok()); -//! } -//! ``` -//! -//! # How to use this module to aggregate and verify aggregate signatures -//! -//! A typical use of the aggregate signature library would look as follows: -//! -//! ``` -//! use std::iter::zip; -//! use aptos_crypto::test_utils::KeyPair; -//! use aptos_crypto::{bls12381, Signature, SigningKey, Uniform}; -//! use aptos_crypto::bls12381::bls12381_keys::{PrivateKey, PublicKey}; -//! use aptos_crypto::bls12381::ProofOfPossession; -//! use aptos_crypto_derive::{CryptoHasher, BCSCryptoHash}; -//! use rand_core::OsRng; -//! use serde::{Serialize, Deserialize}; -//! -//! // Each signer locally generates their own BLS key-pair with a proof-of-possesion (PoP). -//! // We simulate this here, by storing each signer's key-pair in a vector. -//! let mut rng = OsRng; -//! -//! let num_signers = 1000; -//! -//! let mut key_pairs = vec![]; -//! let mut pops = vec![]; -//! for _ in 0..num_signers { -//! let kp = KeyPair::::generate(&mut rng); -//! pops.push(ProofOfPossession::create_with_pubkey(&kp.private_key, &kp.public_key)); -//! // Alternatively, but slower, can choose not to provide the PK and have it computed inside -//! // pops.push(ProofOfPossession::create(&kp.private_key)); -//! key_pairs.push(kp); -//! } -//! -//! // Any arbitrary struct can be signed as long as it is properly "derived" -//! #[derive(CryptoHasher, BCSCryptoHash, Serialize, Deserialize)] -//! struct Message(String, usize); -//! -//! // Each signer `i` then computes a signature share on its own message `m_i`, which might -//! // differ from other signer's message `m_j`. Again, we simulate this using a vector. -//! let mut sigshares = vec![]; -//! let mut messages = vec![]; -//! for i in 0..num_signers { -//! let message = Message("different message".to_owned(), i); -//! let sig = key_pairs[i].private_key.sign(&message).unwrap(); -//! -//! messages.push(message); -//! sigshares.push(sig); -//! } -//! -//! // Then, an aggregator receives some of these signature shares and will attempt to aggregate -//! // them in an aggregate signature. This aggregator can proceed _optimistically_ as follows: -//! -//! // First, when the aggregator boots up, it must verify that each signer's public key has a valid -//! // proof-of-possession (PoP)! -//! -//! /////////////////////////////////////////////////////////////////////////////////////////////// -//! // WARNING: Before relying on the public keys of the signers for verifying aggregate // -//! // signatures or signature shares, one MUST first verify *every* signer's PoP. // -//! // // -//! // The importance of this step cannot be overstated! // -//! // // -//! /////////////////////////////////////////////////////////////////////////////////////////////// -//! for i in 0..pops.len() { -//! assert!(pops[i].verify(&key_pairs[i].public_key).is_ok()); -//! } -//! -//! // Second, now that the aggregator trusts the set of public keys, it can safely aggregate -//! // signature shares _optimistically_ into an aggregate signature which hopefully verifies. In this -//! // example, we assume the aggregator receives a signature share from every signer (for simplicity). -//! -//! // Here, we simulate the aggregator receiving all signature shares. -//! let sigshares_received = sigshares; -//! -//! // Here, the aggregator aggregates the received signature shares into an aggregate signature. -//! let aggsig = bls12381::Signature::aggregate(sigshares_received.clone()).unwrap(); -//! -//! // Third, the aggregator checks that the _optimistic_ aggregation from above succeeded by -//! // verifying the aggregate signature. For this, the aggregator will need to know the public keys -//! // of the signers whose signature shares were aggregated. -//! let msgs_refs = messages.iter().map(|m| m).collect::>(); -//! let pks_refs = key_pairs.iter().map(|kp| &kp.public_key).collect::>(); -//! assert!(aggsig.verify_aggregate(&msgs_refs, &pks_refs).is_ok()); -//! -//! // If the aggregate signature failed verification, the aggregator can individually verify each -//! // of the signature shares to identify which ones are invalid and exclude them. There are also -//! // optimized methods for identifying bad signature shares faster when their relative frequency -//! // is low [^LM07]. However, we will not implement these yet. -//! for i in 0..num_signers { -//! let (msg, sigshare, pk) = (msgs_refs[i], &sigshares_received[i], pks_refs[i]); -//! assert!(sigshare.verify(msg, pk).is_ok()); -//! } -//! ``` -//! -//! References: -//! -//! [^bls-ietf-draft]: BLS Signatures; by D. Boneh, S. Gorbunov, R. Wahby, H. Wee, Z. Zhang; -//! [^Bold03]: Threshold Signatures, Multisignatures and Blind Signatures Based on the Gap-Diffie-Hellman-Group Signature Scheme; by Boldyreva, Alexandra; in PKC 2003; 2002 -//! [^BLS04]: Short Signatures from the Weil Pairing; by Boneh, Dan and Lynn, Ben and Shacham, Hovav; in Journal of Cryptology; 2004; -//! [^BCM+15e] Subgroup security in pairing-based cryptography; by Paulo S. L. M. Barreto and Craig Costello and Rafael Misoczki and Michael Naehrig and Geovandro C. C. F. Pereira and Gustavo Zanon; in Cryptology ePrint Archive, Paper 2015/247; 2015; -//! [^LL97] A key recovery attack on discrete log-based schemes using a prime order subgroup; by Lim, Chae Hoon and Lee, Pil Joong; in Advances in Cryptology --- CRYPTO '97; 1997 -//! [^LM07]: Finding Invalid Signatures in Pairing-Based Batches; by Law, Laurie and Matt, Brian J.; in Cryptography and Coding; 2007 -//! [^MOR01]: Accountable-Subgroup Multisignatures: Extended Abstract; by Micali, Silvio and Ohta, Kazuo and Reyzin, Leonid; in Proceedings of the 8th ACM Conference on Computer and Communications Security; 2001; -//! [^RY07]: The Power of Proofs-of-Possession: Securing Multiparty Signatures against Rogue-Key Attacks; by Ristenpart, Thomas and Yilek, Scott; in Advances in Cryptology - EUROCRYPT 2007; 2007 - -/// Domain separation tag (DST) for hashing a message before signing it. -pub const DST_BLS_SIG_IN_G2_WITH_POP: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; - -pub mod bls12381_keys; -pub mod bls12381_pop; -pub mod bls12381_sigs; -pub mod bls12381_validatable; - -pub use bls12381_keys::{PrivateKey, PublicKey}; -pub use bls12381_pop::ProofOfPossession; -pub use bls12381_sigs::Signature; -pub use bls12381_validatable::UnvalidatedPublicKey; diff --git a/crates/aptos-crypto/src/ed25519/ed25519_keys.rs b/crates/aptos-crypto/src/ed25519/ed25519_keys.rs index fc32132590f7e6..8b5f4c1c1818a7 100644 --- a/crates/aptos-crypto/src/ed25519/ed25519_keys.rs +++ b/crates/aptos-crypto/src/ed25519/ed25519_keys.rs @@ -125,6 +125,11 @@ impl Ed25519PublicKey { .ok_or(CryptoMaterialError::DeserializationError)?; Ed25519PublicKey::try_from(&ed_point.compress().as_bytes()[..]) } + + /// TODO + pub fn aggregate(_pub_keys: Vec<&Ed25519PublicKey>) -> anyhow::Result { + todo!() + } } /////////////////////// diff --git a/crates/aptos-crypto/src/ed25519/ed25519_sigs.rs b/crates/aptos-crypto/src/ed25519/ed25519_sigs.rs index 4c1d9438c83a09..fe563594daa586 100644 --- a/crates/aptos-crypto/src/ed25519/ed25519_sigs.rs +++ b/crates/aptos-crypto/src/ed25519/ed25519_sigs.rs @@ -83,6 +83,20 @@ impl Ed25519Signature { // As this stage S == L which implies a non canonical S. false } + + /// TODO + pub fn aggregate(_sigs: Vec) -> anyhow::Result { + todo!() + } + + /// TODO + pub fn verify_aggregate( + &self, + _messages: &[&T], + _x: &[&Ed25519PublicKey], + ) -> anyhow::Result<()> { + todo!() + } } ////////////////////// diff --git a/crates/aptos-crypto/src/lib.rs b/crates/aptos-crypto/src/lib.rs index fc88e542bbcfd1..b6e087be4bc98f 100644 --- a/crates/aptos-crypto/src/lib.rs +++ b/crates/aptos-crypto/src/lib.rs @@ -6,7 +6,7 @@ #![deny(missing_docs)] //! A library supplying various cryptographic primitives -pub mod bls12381; + pub mod bulletproofs; pub mod compat; pub mod ed25519; diff --git a/crates/aptos-crypto/src/traits.rs b/crates/aptos-crypto/src/traits.rs index 1a1ef205a7068f..8534e987b636a7 100644 --- a/crates/aptos-crypto/src/traits.rs +++ b/crates/aptos-crypto/src/traits.rs @@ -305,11 +305,6 @@ pub trait Genesis: PrivateKey { pub(crate) mod private { pub trait Sealed {} - impl Sealed for crate::bls12381::PrivateKey {} - impl Sealed for crate::bls12381::PublicKey {} - impl Sealed for crate::bls12381::Signature {} - impl Sealed for crate::bls12381::ProofOfPossession {} - impl Sealed for crate::ed25519::Ed25519PrivateKey {} impl Sealed for crate::ed25519::Ed25519PublicKey {} impl Sealed for crate::ed25519::Ed25519Signature {} diff --git a/crates/aptos-crypto/src/unit_tests/bls12381_test.rs b/crates/aptos-crypto/src/unit_tests/bls12381_test.rs deleted file mode 100644 index 2977c398b1c722..00000000000000 --- a/crates/aptos-crypto/src/unit_tests/bls12381_test.rs +++ /dev/null @@ -1,616 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::{ - bls12381, - bls12381::{PrivateKey, ProofOfPossession, PublicKey}, - test_utils::{random_subset, KeyPair, TestAptosCrypto}, - validatable::{Validatable, Validate}, - Signature, SigningKey, Uniform, -}; -use rand::{distributions::Alphanumeric, Rng}; -use rand_core::OsRng; -use std::{convert::TryFrom, iter::zip}; - -/// Tests that an individual signature share computed correctly on a message m passes verification on m. -/// Tests that a signature share computed on a different message m' fails verification on m. -/// Tests that a signature share fails verification under the wrong public key. -#[test] -fn bls12381_sigshare_verify() { - let mut rng = OsRng; - - let message = b"Hello world"; - let message_wrong = b"Wello Horld"; - - let key_pair = KeyPair::::generate(&mut rng); - let key_pair_wrong = KeyPair::::generate(&mut rng); - - let signature = key_pair.private_key.sign_arbitrary_message(message); - let signature_wrong = key_pair_wrong.private_key.sign_arbitrary_message(message); - - // sig on message under key_pair should verify - assert!(signature - .verify_arbitrary_msg(message, &key_pair.public_key) - .is_ok()); - - // sig_wrong on message under key_pair_wrong should verify - assert!(signature_wrong - .verify_arbitrary_msg(message, &key_pair_wrong.public_key) - .is_ok()); - - // sig on message under keypair should NOT verify under keypair_wrong - assert!(signature - .verify_arbitrary_msg(message, &key_pair_wrong.public_key) - .is_err()); - - // sig on message under keypair should NOT verify on message_wrong under key_pair - assert!(signature - .verify_arbitrary_msg(message_wrong, &key_pair.public_key) - .is_err()); - - // sig on message under keypair_wrong should NOT verify under key_pair - assert!(signature_wrong - .verify_arbitrary_msg(message, &key_pair.public_key) - .is_err()); -} - -/// Tests that a PoP for PK 1 verifies under PK 1. -/// Tests that a PoP for PK 1 does NOT verify under PK 2. -#[test] -fn bls12381_pop_verify() { - let mut rng = OsRng; - - let keypair1 = KeyPair::::generate(&mut rng); - - let keypair2 = KeyPair::::generate(&mut rng); - - // Valid PoP for SK 1 - let pop1 = ProofOfPossession::create_with_pubkey(&keypair1.private_key, &keypair1.public_key); - // Valid PoP for SK 2 - let pop2 = ProofOfPossession::create(&keypair2.private_key); - // Invalid PoP for SK 2 - let pop_bad = - ProofOfPossession::create_with_pubkey(&keypair1.private_key, &keypair2.public_key); - - // PoP for SK i should verify for PK i - assert!(pop1.verify(&keypair1.public_key).is_ok()); - assert!(pop2.verify(&keypair2.public_key).is_ok()); - - // PoP for SK 1 should not verify for PK 2 - assert!(pop1.verify(&keypair2.public_key).is_err()); - // Pop for SK 2 should not verify for PK 1 - assert!(pop2.verify(&keypair1.public_key).is_err()); - // Invalid PoP for SK 2 should not verify - assert!(pop_bad.verify(&keypair2.public_key).is_err()); -} - -/// Generates `num_signers` BLS key-pairs. -fn bls12381_keygen(num_signers: usize, mut rng: &mut OsRng) -> Vec> { - let mut key_pairs = vec![]; - for _ in 0..num_signers { - key_pairs.push(KeyPair::::generate(&mut rng)); - } - key_pairs -} - -/// Returns a 256-character unique string that can be signed by the BLS API. -fn random_message_for_signing(rng: &mut OsRng) -> TestAptosCrypto { - TestAptosCrypto( - rng.sample_iter(&Alphanumeric) - .take(256) - .map(char::from) - .collect::(), - ) -} - -/// Returns several 256-character unique strings that can be aggregate-signed by the BLS API. -fn random_messages_for_signing(rng: &mut OsRng, n: usize) -> Vec { - (0..n) - .map(|_| random_message_for_signing(rng)) - .collect::>() -} - -/// Tests that a multisignature on a message m aggregated from n/2 out of n signers verifies -/// correctly on m but fails verification on a different m'. -#[test] -fn bls12381_multisig_should_verify() { - let mut rng = OsRng; - - let message = random_message_for_signing(&mut rng); - let message_wrong = random_message_for_signing(&mut rng); - - let num_signers = 1000; - let key_pairs = bls12381_keygen(num_signers, &mut rng); - - let mut signatures = vec![]; - let mut pubkeys: Vec<&PublicKey> = vec![]; - - let good_step = 2; - for keys in key_pairs.iter().step_by(good_step) { - let signature = keys.private_key.sign(&message).unwrap(); - signatures.push(signature); - pubkeys.push(&keys.public_key); - } - - let multisig = bls12381::Signature::aggregate(signatures).unwrap(); - let aggpk = PublicKey::aggregate(pubkeys).unwrap(); - - // multisig should verify on the correct message under the correct aggregate PK - assert!(multisig.verify(&message, &aggpk).is_ok()); - - // multisig should not verify on an incorrect message under the correct aggregate PK - assert!(multisig.verify(&message_wrong, &aggpk).is_err()); -} - -/// Tests signature (de)serialization -#[test] -fn bls12381_serialize_sig() { - let mut rng = OsRng; - let message = b"Hello world"; - let key_pair = KeyPair::::generate(&mut rng); - let signature = key_pair.private_key.sign_arbitrary_message(message); - - let sig_bytes = signature.to_bytes(); - - let signature_deserialized = bls12381::Signature::try_from(&sig_bytes[..]).unwrap(); - - assert_eq!(signature, signature_deserialized); -} - -/// Tests that an aggregate signature on `n` different messages verifies correctly. -#[test] -fn bls12381_aggsig_should_verify() { - let mut rng = OsRng; - let num_signers = 1000; - - let messages = random_messages_for_signing(&mut rng, num_signers); - let messages_wrong = random_messages_for_signing(&mut rng, num_signers); - - let key_pairs = bls12381_keygen(num_signers, &mut rng); - - let mut signatures = vec![]; - let mut pubkeys: Vec<&PublicKey> = vec![]; - - for i in 0..num_signers { - let msg = &messages[i]; - let key = &key_pairs[i]; - - signatures.push(key.private_key.sign(msg).unwrap()); - pubkeys.push(&key.public_key); - } - - let aggsig = bls12381::Signature::aggregate(signatures).unwrap(); - - // aggsig should verify on the correct messages under the correct PKs - let msgs_refs = messages.iter().collect::>(); - assert!(aggsig.verify_aggregate(&msgs_refs, &pubkeys).is_ok()); - - // aggsig should NOT verify on incorrect messages under the correct PKs - let msgs_wrong_refs = messages_wrong.iter().collect::>(); - assert!(aggsig.verify_aggregate(&msgs_wrong_refs, &pubkeys).is_err()); -} - -/// Tests that an aggregate signature on 0 messages or PKs does NOT verify. -#[test] -fn bls12381_aggsig_zero_messages_or_pks_does_not_verify() { - let mut rng = OsRng; - - let message = random_message_for_signing(&mut rng); - - let key_pair = KeyPair::::generate(&mut rng); - - let aggsig = - bls12381::Signature::aggregate(vec![key_pair.private_key.sign(&message).unwrap()]).unwrap(); - - // aggsig should NOT verify on zero messages and zero PKs - let pubkeys: Vec<&PublicKey> = vec![]; - let messages = vec![]; - let msgs_refs = messages.iter().collect::>(); - assert!(aggsig.verify_aggregate(&msgs_refs, &pubkeys).is_err()); - - // aggsig should NOT verify on zero PKs - let pubkeys: Vec<&PublicKey> = vec![]; - let messages = vec![message]; - let msgs_refs = messages.iter().collect::>(); - assert!(aggsig.verify_aggregate(&msgs_refs, &pubkeys).is_err()); - - // aggsig should NOT verify on zero messages - let pubkeys: Vec<&PublicKey> = vec![&key_pair.public_key]; - let messages = vec![]; - let msgs_refs = messages.iter().collect::>(); - assert!(aggsig.verify_aggregate(&msgs_refs, &pubkeys).is_err()); -} - -/// Tests that a multisignature incorrectly aggregated from signature shares on different messages does -/// NOT verify. -#[test] -fn bls12381_multisig_wrong_messages_aggregated() { - let mut rng = OsRng; - - let message = random_message_for_signing(&mut rng); - let message_wrong = random_message_for_signing(&mut rng); - - let num_signers = 500; - let key_pairs = bls12381_keygen(num_signers, &mut rng); - assert_eq!(key_pairs.len(), num_signers); - - let mut signatures = vec![]; - let mut pubkeys: Vec<&PublicKey> = vec![]; - - for (i, key_pair) in key_pairs.iter().enumerate() { - let signature = if i % 2 == 0 { - key_pair.private_key.sign(&message).unwrap() - } else { - key_pair.private_key.sign(&message_wrong).unwrap() - }; - signatures.push(signature); - pubkeys.push(&key_pair.public_key); - } - - let multisig = bls12381::Signature::aggregate(signatures).unwrap(); - let aggpk = PublicKey::aggregate(pubkeys).unwrap(); - - // multisig should NOT verify on any of the messages, because it is actually not a multisig: - // i.e., it is not an aggregate signature on a single message - assert!(multisig.verify(&message, &aggpk).is_err()); - assert!(multisig.verify(&message_wrong, &aggpk).is_err()); -} - -/// Returns two different sets of signer IDs (i.e., numbers in 0..num_signers) -pub fn random_different_signer_sets( - rng: &mut OsRng, - num_signers: usize, - subset_size: usize, -) -> (Vec, Vec) { - let signers1 = random_subset(rng, num_signers, subset_size); - let mut signers2 = random_subset(rng, num_signers, subset_size); - - while signers1 == signers2 { - signers2 = random_subset(rng, num_signers, subset_size); - } - - (signers1, signers2) -} - -/// Tests that a multisig aggregated from a set of signers A does not verify under a public key -/// aggregated from a different set B of signers. -#[test] -fn bls12381_multisig_wrong_pks_aggregated() { - let mut rng = OsRng; - - let message1 = random_message_for_signing(&mut rng); - let message2 = random_message_for_signing(&mut rng); - - let num_signers = 1000; - let key_pairs = bls12381_keygen(num_signers, &mut rng); - assert_eq!(key_pairs.len(), num_signers); - - let (signers1, signers2) = random_different_signer_sets(&mut rng, num_signers, num_signers / 2); - - let mut signatures1 = vec![]; - let mut signatures2 = vec![]; - let mut pubkeys1 = vec![]; - let mut pubkeys2 = vec![]; - - for (i1, i2) in zip(signers1, signers2) { - signatures1.push(key_pairs[i1].private_key.sign(&message1).unwrap()); - signatures2.push(key_pairs[i2].private_key.sign(&message2).unwrap()); - - pubkeys1.push(&key_pairs[i1].public_key); - pubkeys2.push(&key_pairs[i2].public_key); - } - assert_ne!(signatures1.len(), 0); - assert_ne!(signatures2.len(), 0); - - let multisig1 = bls12381::Signature::aggregate(signatures1).unwrap(); - let multisig2 = bls12381::Signature::aggregate(signatures2).unwrap(); - let aggpk1 = PublicKey::aggregate(pubkeys1).unwrap(); - let aggpk2 = PublicKey::aggregate(pubkeys2).unwrap(); - - // first, make sure multisig1 (and multisig2) verify on message1 (and on message2) under aggpk1 (and aggpk2, respectively) - assert!(multisig1.verify(&message1, &aggpk1).is_ok()); - assert!(multisig2.verify(&message2, &aggpk2).is_ok()); - - // second, make sure multisig1 doesn't verify against multisig2's signer set (and viceversa) - assert!(multisig1.verify(&message1, &aggpk2).is_err()); - assert!(multisig2.verify(&message2, &aggpk1).is_err()); - - // ...and try swapping the messages too - assert!(multisig1.verify(&message2, &aggpk2).is_err()); - assert!(multisig2.verify(&message1, &aggpk1).is_err()); -} - -/// Tests that a randomly generated multisig does not verify under a randomly generated PK. -#[test] -fn bls12381_random_multisig_dont_verify_with_random_pk() { - let mut rng = OsRng; - - let message = random_message_for_signing(&mut rng); - let keypair = KeyPair::::generate(&mut rng); - let keypair_junk = KeyPair::::generate(&mut rng); - - let signature = keypair.private_key.sign(&message).unwrap(); - - assert!(signature.verify(&message, &keypair.public_key).is_ok()); - - assert!(signature - .verify(&message, &keypair_junk.public_key) - .is_err()); -} - -#[test] -fn bls12381_validatable_pk() { - let mut rng = OsRng; - - // Test that prime-order points pass the validate() call - let keypair = KeyPair::::generate(&mut rng); - let pk_bytes = keypair.public_key.to_bytes(); - - let validatable = Validatable::from_validated(keypair.public_key); - - assert!(validatable.validate().is_ok()); - assert_eq!(validatable.validate().unwrap().to_bytes(), pk_bytes); - - // Test that low-order points don't pass the validate() call - // - // Low-order points were sampled from bls12_381 crate (https://github.com/zkcrypto/bls12_381/blob/main/src/g1.rs) - // - The first point was convereted from projective to affine coordinates and serialized via `point.to_affine().to_compressed()`. - // - The second point was in affine coordinates and serialized via `a.to_compressed()`. - let low_order_points = [ - "ae3cd9403b69c20a0d455fd860e977fe6ee7140a7f091f26c860f2caccd3e0a7a7365798ac10df776675b3a67db8faa0", - "928d4862a40439a67fd76a9c7560e2ff159e770dcf688ff7b2dd165792541c88ee76c82eb77dd6e9e72c89cbf1a56a68", - ]; - - for p in low_order_points { - let point = hex::decode(p).unwrap(); - assert_eq!(point.len(), PublicKey::LENGTH); - - let pk = PublicKey::try_from(point.as_slice()).unwrap(); - - // First, make sure group_check() identifies this point as a low-order point - assert!(pk.subgroup_check().is_err()); - - // Second, make sure our Validatable implementation agrees with group_check - let validatable = Validatable::::from_unvalidated(pk.to_unvalidated()); - assert!(validatable.validate().is_err()); - } -} - -#[test] -#[ignore] -/// Not an actual test: only used to generate test cases for testing the BLS Move module in -/// aptos-move/framework/move-stdlib/sources/signer.move -fn bls12381_sample_pop() { - let mut rng = OsRng; - - let num = 5; - - let mut kps = vec![]; - - for _i in 1..=num { - kps.push(KeyPair::::generate(&mut rng)); - } - - println!("let pks = vector["); - for kp in &kps { - println!(" x\"{}\",", kp.public_key); - } - println!("];\n"); - - println!("let pops = vector["); - for kp in &kps { - println!(" x\"{}\",", ProofOfPossession::create(&kp.private_key)); - } - println!("];\n"); -} - -#[test] -#[ignore] -/// Not an actual test: only used to generate test cases for testing the BLS Move module in -/// aptos-move/framework/move-stdlib/sources/signer.move -/// For simplicity, we use `sign_arbitrary_message` to generate a signature directly on a -/// message `m` rather than on its hash derived using the `CryptoHasher` trait. This makes it easier -/// to verify the signature in our Move code, which uses `verify_arbitrary_message`. -fn bls12381_sample_signature() { - let mut rng = OsRng; - - let keypair = KeyPair::::generate(&mut rng); - let sk = keypair.private_key; - let pk = keypair.public_key; - - let message = b"Hello Aptos!"; - let signature = sk.sign_arbitrary_message(message); - - println!("SK: {}", hex::encode(sk.to_bytes())); - println!("PK: {}", hex::encode(pk.to_bytes())); - println!("Message: {}", std::str::from_utf8(message).unwrap()); - println!("Signature: {}", hex::encode(signature.to_bytes())); -} - -#[test] -/// Tests deserialization and verification of a signature generated for the Move submodule via -/// `bls12381_sample_signature` above. -fn bls12381_sample_signature_verifies() { - let pk = PublicKey::try_from( - hex::decode( - "94209a296b739577cb076d3bfb1ca8ee936f29b69b7dae436118c4dd1cc26fd43dcd16249476a006b8b949bf022a7858" - ).unwrap().as_slice() - ).unwrap(); - - let sig = bls12381::Signature::try_from( - hex::decode( - "b01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7" - ).unwrap().as_slice() - ).unwrap(); - - assert!(sig.verify_arbitrary_msg(b"Hello Aptos!", &pk).is_ok()); -} - -#[test] -#[ignore] -fn bls12381_sample_doc_test_for_normal_sigs() { - let mut rng = OsRng; - - // A signer locally generated their own BLS key-pair via: - let kp = KeyPair::::generate(&mut rng); - - // The signer computes a normal signature on a message. - let message = TestAptosCrypto("test".to_owned()); - let sig = kp.private_key.sign(&message).unwrap(); - - // Any verifier who has the signer's public key can verify the `(message, sig)` pair as: - assert!(sig.verify(&message, &kp.public_key).is_ok()); - - println!( - "let sk_bytes = hex::decode(\"{}\").unwrap();", - hex::encode(kp.private_key.to_bytes()) - ); - println!( - "let pk_bytes = hex::decode(\"{}\").unwrap();", - hex::encode(kp.public_key.to_bytes()) - ); - println!("// signature on TestAptosCrypto(\"test\".to_owned())"); - println!( - "let sig_bytes = hex::decode(\"{}\").unwrap();", - hex::encode(sig.to_bytes()) - ); -} - -#[test] -#[ignore] -/// Not an actual test: only used to generate test cases for testing the BLS Move module in -/// aptos-move/framework/move-stdlib/sources/signer.move -fn bls12381_sample_aggregate_pk_and_aggsig() { - let mut rng = OsRng; - - let num = 5; - let mut messages = vec![]; - - let mut pks = vec![]; - let mut sigs = vec![]; - let mut aggsigs = vec![]; - - for i in 1..=num { - let msg = format!("Hello, Aptos {}!", i); - let keypair = KeyPair::::generate(&mut rng); - - messages.push(msg); - pks.push(keypair.public_key); - sigs.push( - keypair - .private_key - .sign_arbitrary_message(messages.last().unwrap().as_bytes()), - ); - - aggsigs.push(bls12381::Signature::aggregate(sigs.clone()).unwrap()); - } - - println!( - "// The signed messages are \"Hello, Aptos !\", where \\in {{1, ..., {}}}", - num - ); - println!("let msgs = vector["); - for m in messages { - println!(" x\"{}\",", hex::encode(m.as_bytes())); - } - println!("];\n"); - - println!("// Public key of signer i"); - println!("let pks = vector["); - for pk in pks { - println!(" x\"{}\",", pk); - } - println!("];\n"); - - println!("// aggsigs[i] = \\sum_{{j <= i}} sigs[j], where sigs[j] is a signature on msgs[j] under pks[j]"); - println!("let aggsigs = vector["); - for multisig in aggsigs { - println!(" x\"{}\",", multisig); - } - println!("];"); -} - -#[test] -#[ignore] -/// Not an actual test: only used to generate test cases for testing the BLS Move module in -/// aptos-move/framework/move-stdlib/sources/signer.move -fn bls12381_sample_aggregate_pk_and_multisig() { - let mut rng = OsRng; - - let num = 5; - let message = b"Hello, Aptoverse!"; - - let mut pks = vec![]; - let mut agg_pks = vec![]; - let mut sigs = vec![]; - let mut multisigs = vec![]; - - for _i in 1..=num { - let keypair = KeyPair::::generate(&mut rng); - - pks.push(keypair.public_key); - sigs.push(keypair.private_key.sign_arbitrary_message(message)); - - multisigs.push(bls12381::Signature::aggregate(sigs.clone()).unwrap()); - - let pk_refs = pks.iter().collect::>(); - agg_pks.push(PublicKey::aggregate(pk_refs).unwrap()); - } - - println!("// Public keys for each signer i"); - println!("let pks = vector["); - for pk in pks { - println!(" x\"{}\",", pk); - } - println!("];\n"); - - println!("// agg_pks[i] = \\sum_{{j <= i}} pk[j] (i.e., the aggregation of all public keys from 0 to i, inclusive)"); - println!("let agg_pks = vector["); - for aggpk in agg_pks { - println!(" x\"{}\",", aggpk); - } - println!("];\n"); - - println!("// multisigs[i] is a signature on \"Hello, Aptoverse!\" under agg_pks[i]"); - println!("let multisigs = vector["); - for multisig in multisigs { - println!(" x\"{}\",", multisig); - } - println!("];"); -} - -#[test] -#[ignore] -/// Not an actual test: only used to generate test cases for testing the BLS Move module in -/// aptos-move/framework/move-stdlib/sources/signer.move -fn bls12381_sample_aggregate_sigs() { - let mut rng = OsRng; - - let num = 5; - let message = b"Hello, Aptoverse!"; - - let mut sigs = vec![]; - let mut multisigs = vec![]; - - for _i in 1..=num { - let keypair = KeyPair::::generate(&mut rng); - - sigs.push(keypair.private_key.sign_arbitrary_message(message)); - - multisigs.push(bls12381::Signature::aggregate(sigs.clone()).unwrap()); - } - - println!("// Signatures of each signer i"); - println!("let sigs = vector["); - for sig in sigs { - println!(" signature_from_bytes(x\"{}\"),", sig); - } - println!("];\n"); - - println!("// multisigs[i] is a signature on \"Hello, Aptoverse!\" from signers 1 through i (inclusive)"); - println!("let multisigs = vector["); - for multisig in multisigs { - println!(" AggrOrMultiSignature {{ bytes: x\"{}\" }},", multisig); - } - println!("];"); -} diff --git a/crates/aptos-crypto/src/unit_tests/mod.rs b/crates/aptos-crypto/src/unit_tests/mod.rs index 34cf3348c431fd..53d539ef28a72b 100644 --- a/crates/aptos-crypto/src/unit_tests/mod.rs +++ b/crates/aptos-crypto/src/unit_tests/mod.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 mod bcs_test; -mod bls12381_test; mod bulletproofs_test; mod compat_test; mod cross_test; diff --git a/crates/aptos-dkg/src/pvss/contribution.rs b/crates/aptos-dkg/src/pvss/contribution.rs index 66db50110c7e7e..6f003b182b3736 100644 --- a/crates/aptos-dkg/src/pvss/contribution.rs +++ b/crates/aptos-dkg/src/pvss/contribution.rs @@ -5,7 +5,7 @@ use crate::{ utils::HasMultiExp, }; use anyhow::bail; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use blstrs::Scalar; use group::Group; @@ -22,13 +22,13 @@ pub struct Contribution { pub aux: A, } -pub type SoK = (Player, Gr, bls12381::Signature, schnorr::PoK); +pub type SoK = (Player, Gr, ed25519::Signature, schnorr::PoK); pub fn batch_verify_soks( soks: &[SoK], pk_base: &Gr, pk: &Gr, - spks: &Vec, + spks: &Vec, aux: &Vec, tau: &Scalar, ) -> anyhow::Result<()> @@ -91,11 +91,11 @@ where let pks = spks .iter() .map(|pk| pk) - .collect::>(); - let sig = bls12381::Signature::aggregate( + .collect::>(); + let sig = ed25519::Signature::aggregate( soks.iter() .map(|(_, _, sig, _)| sig.clone()) - .collect::>(), + .collect::>(), )?; sig.verify_aggregate(&msgs_refs[..], &pks[..])?; diff --git a/crates/aptos-dkg/src/pvss/das/unweighted_protocol.rs b/crates/aptos-dkg/src/pvss/das/unweighted_protocol.rs index e83435a41e452e..4359a1f33aab4d 100644 --- a/crates/aptos-dkg/src/pvss/das/unweighted_protocol.rs +++ b/crates/aptos-dkg/src/pvss/das/unweighted_protocol.rs @@ -18,7 +18,7 @@ use crate::{ }, }; use anyhow::bail; -use aptos_crypto::{bls12381, CryptoMaterialError, Genesis, SigningKey, ValidCryptoMaterial}; +use aptos_crypto::{ed25519, CryptoMaterialError, Genesis, SigningKey, ValidCryptoMaterial}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use blstrs::{G1Projective, G2Projective, Gt}; use group::Group; @@ -78,8 +78,8 @@ impl traits::Transcript for Transcript { type InputSecret = pvss::input_secret::InputSecret; type PublicParameters = das::PublicParameters; type SecretSharingConfig = ThresholdConfig; - type SigningPubKey = bls12381::PublicKey; - type SigningSecretKey = bls12381::PrivateKey; + type SigningPubKey = ed25519::PublicKey; + type SigningSecretKey = ed25519::PrivateKey; fn scheme_name() -> String { DAS_SK_IN_G1.to_string() @@ -282,7 +282,7 @@ impl traits::Transcript for Transcript { where R: rand_core::RngCore + rand_core::CryptoRng, { - let sk = bls12381::PrivateKey::genesis(); + let sk = ed25519::PrivateKey::genesis(); Transcript { soks: vec![( sc.get_player(0), @@ -320,11 +320,11 @@ impl MalleableTranscript for Transcript { impl Transcript { pub fn sign_contribution( - sk: &bls12381::PrivateKey, + sk: &ed25519::PrivateKey, player: &Player, aux: &A, comm: &G2Projective, - ) -> bls12381::Signature { + ) -> ed25519::Signature { sk.sign(&Contribution:: { comm: *comm, player: *player, diff --git a/crates/aptos-dkg/src/pvss/das/weighted_protocol.rs b/crates/aptos-dkg/src/pvss/das/weighted_protocol.rs index aa52b91584f171..95f3c19b7e5f9f 100644 --- a/crates/aptos-dkg/src/pvss/das/weighted_protocol.rs +++ b/crates/aptos-dkg/src/pvss/das/weighted_protocol.rs @@ -19,7 +19,7 @@ use crate::{ }, }; use anyhow::bail; -use aptos_crypto::{bls12381, CryptoMaterialError, Genesis, SigningKey, ValidCryptoMaterial}; +use aptos_crypto::{ed25519, CryptoMaterialError, Genesis, SigningKey, ValidCryptoMaterial}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use blstrs::{pairing, G1Affine, G1Projective, G2Affine, G2Projective, Gt}; use group::{Curve, Group}; @@ -92,8 +92,8 @@ impl traits::Transcript for Transcript { type InputSecret = pvss::input_secret::InputSecret; type PublicParameters = das::PublicParameters; type SecretSharingConfig = WeightedConfig; - type SigningPubKey = bls12381::PublicKey; - type SigningSecretKey = bls12381::PrivateKey; + type SigningPubKey = ed25519::PublicKey; + type SigningSecretKey = ed25519::PrivateKey; fn scheme_name() -> String { WEIGHTED_DAS_SK_IN_G1.to_string() @@ -365,7 +365,7 @@ impl traits::Transcript for Transcript { R: rand_core::RngCore + rand_core::CryptoRng, { let W = sc.get_total_weight(); - let sk = bls12381::PrivateKey::genesis(); + let sk = ed25519::PrivateKey::genesis(); Transcript { soks: vec![( sc.get_player(0), @@ -513,11 +513,11 @@ impl MalleableTranscript for Transcript { impl Transcript { pub fn sign_contribution( - sk: &bls12381::PrivateKey, + sk: &ed25519::PrivateKey, player: &Player, aux: &A, comm: &G1Projective, - ) -> bls12381::Signature { + ) -> ed25519::Signature { sk.sign(&Contribution:: { comm: *comm, player: *player, diff --git a/crates/aptos-dkg/src/pvss/insecure_field/transcript.rs b/crates/aptos-dkg/src/pvss/insecure_field/transcript.rs index 28da3261b2da22..b241f5ac43098e 100644 --- a/crates/aptos-dkg/src/pvss/insecure_field/transcript.rs +++ b/crates/aptos-dkg/src/pvss/insecure_field/transcript.rs @@ -14,7 +14,7 @@ use crate::{ }, }; use anyhow::bail; -use aptos_crypto::{bls12381, CryptoMaterialError, ValidCryptoMaterial}; +use aptos_crypto::{ed25519, CryptoMaterialError, ValidCryptoMaterial}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use blstrs::{G2Projective, Scalar}; use rand::thread_rng; @@ -61,8 +61,8 @@ impl traits::Transcript for Transcript { type InputSecret = pvss::input_secret::InputSecret; type PublicParameters = das::PublicParameters; type SecretSharingConfig = ThresholdConfig; - type SigningPubKey = bls12381::PublicKey; - type SigningSecretKey = bls12381::PrivateKey; + type SigningPubKey = ed25519::PublicKey; + type SigningSecretKey = ed25519::PrivateKey; fn scheme_name() -> String { "insecure_field_pvss".to_string() diff --git a/crates/aptos-genesis/src/builder.rs b/crates/aptos-genesis/src/builder.rs index 2f9992df2358a6..88003866eb8700 100644 --- a/crates/aptos-genesis/src/builder.rs +++ b/crates/aptos-genesis/src/builder.rs @@ -18,7 +18,6 @@ use aptos_config::{ network_id::NetworkId, }; use aptos_crypto::{ - bls12381, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, PrivateKey, }; @@ -212,9 +211,6 @@ impl TryFrom<&ValidatorNodeConfig> for ValidatorConfiguration { voter_account_address: private_identity.account_address.into(), voter_account_public_key: private_identity.account_private_key.public_key(), consensus_public_key: Some(private_identity.consensus_private_key.public_key()), - proof_of_possession: Some(bls12381::ProofOfPossession::create( - &private_identity.consensus_private_key, - )), validator_network_public_key: Some( private_identity.validator_network_private_key.public_key(), ), diff --git a/crates/aptos-genesis/src/config.rs b/crates/aptos-genesis/src/config.rs index 28fdc92e85957a..37b49c5bb9c2cb 100644 --- a/crates/aptos-genesis/src/config.rs +++ b/crates/aptos-genesis/src/config.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_config::config::HANDSHAKE_VERSION; -use aptos_crypto::{bls12381, ed25519::Ed25519PublicKey, x25519}; +use aptos_crypto::{ed25519, ed25519::Ed25519PublicKey, x25519}; use aptos_types::{ account_address::{AccountAddress, AccountAddressWithChecks}, chain_id::ChainId, @@ -130,10 +130,7 @@ pub struct ValidatorConfiguration { pub voter_account_public_key: Ed25519PublicKey, /// Key used for signing in consensus #[serde(skip_serializing_if = "Option::is_none")] - pub consensus_public_key: Option, - /// Corresponding proof of possession of consensus public key - #[serde(skip_serializing_if = "Option::is_none")] - pub proof_of_possession: Option, + pub consensus_public_key: Option, /// Public key used for validator network identity (same as account address) #[serde(skip_serializing_if = "Option::is_none")] pub validator_network_public_key: Option, @@ -237,18 +234,12 @@ impl TryFrom for Validator { } else { vec![] }; - let proof_of_possession = if let Some(pop) = config.proof_of_possession { - pop.to_bytes().to_vec() - } else { - vec![] - }; Ok(Validator { owner_address, operator_address, voter_address, consensus_pubkey, - proof_of_possession, network_addresses: bcs::to_bytes(&validator_addresses).unwrap(), full_node_network_addresses: bcs::to_bytes(&full_node_addresses).unwrap(), stake_amount: config.stake_amount, @@ -345,8 +336,7 @@ pub struct OwnerConfiguration { pub struct OperatorConfiguration { pub operator_account_address: AccountAddressWithChecks, pub operator_account_public_key: Ed25519PublicKey, - pub consensus_public_key: bls12381::PublicKey, - pub consensus_proof_of_possession: bls12381::ProofOfPossession, + pub consensus_public_key: ed25519::PublicKey, pub validator_network_public_key: x25519::PublicKey, pub validator_host: HostAndPort, pub full_node_network_public_key: Option, @@ -585,9 +575,6 @@ impl TryFrom for Vec { if pool.validator.consensus_public_key.is_none() { errors.push(anyhow::anyhow!("Employee pool #{} is setup to join during genesis but missing a consensus public key", i)); } - if pool.validator.proof_of_possession.is_none() { - errors.push(anyhow::anyhow!("Employee pool #{} is setup to join during genesis but missing a proof of possession", i)); - } if pool.validator.validator_host.is_none() { errors.push(anyhow::anyhow!( "Employee pool #{} is setup to join during genesis but missing a validator host", diff --git a/crates/aptos-genesis/src/keys.rs b/crates/aptos-genesis/src/keys.rs index 26df4ffd425e2a..194a429ddbb6b7 100644 --- a/crates/aptos-genesis/src/keys.rs +++ b/crates/aptos-genesis/src/keys.rs @@ -3,7 +3,7 @@ use aptos_config::{config::IdentityBlob, keys::ConfigKey}; use aptos_crypto::{ - bls12381, + ed25519, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, x25519, PrivateKey, }; @@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize}; pub struct PrivateIdentity { pub account_address: AccountAddress, pub account_private_key: Ed25519PrivateKey, - pub consensus_private_key: bls12381::PrivateKey, + pub consensus_private_key: ed25519::PrivateKey, pub full_node_network_private_key: x25519::PrivateKey, pub validator_network_private_key: x25519::PrivateKey, } @@ -26,8 +26,7 @@ pub struct PrivateIdentity { pub struct PublicIdentity { pub account_address: AccountAddress, pub account_public_key: Ed25519PublicKey, - pub consensus_public_key: Option, - pub consensus_proof_of_possession: Option, + pub consensus_public_key: Option, pub full_node_network_public_key: Option, pub validator_network_public_key: Option, } @@ -37,7 +36,7 @@ pub fn generate_key_objects( keygen: &mut KeyGen, ) -> anyhow::Result<(IdentityBlob, IdentityBlob, PrivateIdentity, PublicIdentity)> { let account_key = ConfigKey::new(keygen.generate_ed25519_private_key()); - let consensus_key = ConfigKey::new(keygen.generate_bls12381_private_key()); + let consensus_key = ConfigKey::new(keygen.generate_ed25519_private_key()); let validator_network_key = ConfigKey::new(keygen.generate_x25519_private_key()?); let full_node_network_key = ConfigKey::new(keygen.generate_x25519_private_key()?); @@ -69,9 +68,6 @@ pub fn generate_key_objects( account_address, account_public_key: account_key.public_key(), consensus_public_key: Some(private_identity.consensus_private_key.public_key()), - consensus_proof_of_possession: Some(bls12381::ProofOfPossession::create( - &private_identity.consensus_private_key, - )), full_node_network_public_key: Some(full_node_network_key.public_key()), validator_network_public_key: Some(validator_network_key.public_key()), }; diff --git a/crates/aptos-jwk-consensus/src/epoch_manager.rs b/crates/aptos-jwk-consensus/src/epoch_manager.rs index d07ad2fd6b3e09..33d62221ae71c3 100644 --- a/crates/aptos-jwk-consensus/src/epoch_manager.rs +++ b/crates/aptos-jwk-consensus/src/epoch_manager.rs @@ -11,7 +11,7 @@ use anyhow::Result; use aptos_bounded_executor::BoundedExecutor; use aptos_channels::{aptos_channel, message_queues::QueueStyle}; use aptos_consensus_types::common::Author; -use aptos_crypto::bls12381::PrivateKey; +use aptos_crypto::ed25519::PrivateKey; use aptos_event_notifications::{ EventNotification, EventNotificationListener, ReconfigNotification, ReconfigNotificationListener, diff --git a/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs b/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs index 746508ce59a330..ac9856d35268bf 100644 --- a/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs +++ b/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs @@ -8,7 +8,7 @@ use crate::{ }; use anyhow::{anyhow, bail, Result}; use aptos_channels::{aptos_channel, message_queues::QueueStyle}; -use aptos_crypto::{bls12381::PrivateKey, SigningKey}; +use aptos_crypto::{ed25519::PrivateKey, SigningKey}; use aptos_logger::{debug, error, info}; use aptos_types::{ account_address::AccountAddress, diff --git a/crates/aptos-jwk-consensus/src/jwk_manager/tests.rs b/crates/aptos-jwk-consensus/src/jwk_manager/tests.rs index d113a71622b66d..319f2ef75c7645 100644 --- a/crates/aptos-jwk-consensus/src/jwk_manager/tests.rs +++ b/crates/aptos-jwk-consensus/src/jwk_manager/tests.rs @@ -9,7 +9,7 @@ use crate::{ use aptos_bitvec::BitVec; use aptos_channels::aptos_channel; use aptos_crypto::{ - bls12381::{PrivateKey, PublicKey, Signature}, + ed25519::{PrivateKey, PublicKey, Signature}, hash::CryptoHash, SigningKey, Uniform, }; diff --git a/crates/aptos-jwk-consensus/src/lib.rs b/crates/aptos-jwk-consensus/src/lib.rs index 2d23907e396dd6..f88e5a0b2f33a1 100644 --- a/crates/aptos-jwk-consensus/src/lib.rs +++ b/crates/aptos-jwk-consensus/src/lib.rs @@ -4,7 +4,7 @@ use crate::{ epoch_manager::EpochManager, network::NetworkTask, network_interface::JWKConsensusNetworkClient, types::JWKConsensusMsg, }; -use aptos_crypto::bls12381::PrivateKey; +use aptos_crypto::ed25519::PrivateKey; use aptos_event_notifications::{ DbBackedOnChainConfig, EventNotificationListener, ReconfigNotificationListener, }; diff --git a/crates/aptos-jwk-consensus/src/observation_aggregation/tests.rs b/crates/aptos-jwk-consensus/src/observation_aggregation/tests.rs index 07878fbc3a6547..5fc4d48b6b803b 100644 --- a/crates/aptos-jwk-consensus/src/observation_aggregation/tests.rs +++ b/crates/aptos-jwk-consensus/src/observation_aggregation/tests.rs @@ -4,7 +4,7 @@ use crate::{ observation_aggregation::ObservationAggregationState, types::{ObservedUpdate, ObservedUpdateResponse}, }; -use aptos_crypto::{bls12381, SigningKey, Uniform}; +use aptos_crypto::{ed25519, SigningKey, Uniform}; use aptos_reliable_broadcast::BroadcastStatus; use aptos_types::{ epoch_state::EpochState, @@ -25,11 +25,11 @@ fn test_observation_aggregation_state() { let addrs: Vec = (0..num_validators) .map(|_| AccountAddress::random()) .collect(); - let private_keys: Vec = (0..num_validators) - .map(|_| bls12381::PrivateKey::generate_for_testing()) + let private_keys: Vec = (0..num_validators) + .map(|_| ed25519::PrivateKey::generate_for_testing()) .collect(); - let public_keys: Vec = (0..num_validators) - .map(|i| bls12381::PublicKey::from(&private_keys[i])) + let public_keys: Vec = (0..num_validators) + .map(|i| ed25519::PublicKey::from(&private_keys[i])) .collect(); let voting_powers = [1, 1, 1, 6, 6]; // total voting power: 15, default threshold: 11 let validator_infos: Vec = (0..num_validators) diff --git a/crates/aptos-jwk-consensus/src/types.rs b/crates/aptos-jwk-consensus/src/types.rs index 31223ec4c746fd..74f4901875598f 100644 --- a/crates/aptos-jwk-consensus/src/types.rs +++ b/crates/aptos-jwk-consensus/src/types.rs @@ -1,6 +1,6 @@ // Copyright © Aptos Foundation -use aptos_crypto::bls12381::Signature; +use aptos_crypto::ed25519::Signature; use aptos_enum_conversion_derive::EnumConversion; use aptos_reliable_broadcast::RBMessage; use aptos_types::{ diff --git a/crates/aptos-keygen/src/lib.rs b/crates/aptos-keygen/src/lib.rs index d176b461c62e4f..4ad921f44e51d6 100644 --- a/crates/aptos-keygen/src/lib.rs +++ b/crates/aptos-keygen/src/lib.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_crypto::{ - bls12381, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, x25519, CryptoMaterialError, PrivateKey, Uniform, }; @@ -35,11 +34,6 @@ impl KeyGen { Ed25519PrivateKey::generate(&mut self.0) } - /// Generate a bls12381 private key. - pub fn generate_bls12381_private_key(&mut self) -> bls12381::PrivateKey { - bls12381::PrivateKey::generate(&mut self.0) - } - /// Generate an Ed25519 key pair. pub fn generate_ed25519_keypair(&mut self) -> (Ed25519PrivateKey, Ed25519PublicKey) { let private_key = self.generate_ed25519_private_key(); diff --git a/crates/aptos-telemetry-service/src/validator_cache.rs b/crates/aptos-telemetry-service/src/validator_cache.rs index 554e533d3b2d8c..53afae31d1a384 100644 --- a/crates/aptos-telemetry-service/src/validator_cache.rs +++ b/crates/aptos-telemetry-service/src/validator_cache.rs @@ -178,7 +178,7 @@ impl PeerSetCacheUpdater { mod tests { use super::PeerSetCacheUpdater; use aptos_crypto::{ - bls12381::{PrivateKey, PublicKey}, + ed25519::{PrivateKey, PublicKey}, test_utils::KeyPair, Uniform, }; diff --git a/crates/aptos/src/genesis/keys.rs b/crates/aptos/src/genesis/keys.rs index d4b619f6d04e5c..5bb0ebae7272a3 100644 --- a/crates/aptos/src/genesis/keys.rs +++ b/crates/aptos/src/genesis/keys.rs @@ -209,17 +209,6 @@ impl CliCommand<()> for SetValidatorConfiguration { ))); }; - let consensus_proof_of_possession = if let Some(consensus_proof_of_possession) = - operator_identity.consensus_proof_of_possession - { - consensus_proof_of_possession - } else { - return Err(CliError::CommandArgumentError(format!( - "Failed to read consensus proof of possession from public identity file {}", - operator_keys_file.display() - ))); - }; - // Only add the public key if there is a full node let full_node_network_public_key = if self.full_node_host.is_some() { operator_identity.full_node_network_public_key @@ -232,7 +221,6 @@ impl CliCommand<()> for SetValidatorConfiguration { operator_account_address: operator_identity.account_address.into(), operator_account_public_key: operator_identity.account_public_key.clone(), consensus_public_key, - consensus_proof_of_possession, validator_network_public_key, validator_host: self.validator_host, full_node_network_public_key, diff --git a/crates/aptos/src/genesis/mod.rs b/crates/aptos/src/genesis/mod.rs index 9c9155645175b1..0c19a7d43756c4 100644 --- a/crates/aptos/src/genesis/mod.rs +++ b/crates/aptos/src/genesis/mod.rs @@ -19,7 +19,7 @@ use crate::{ CliCommand, CliResult, }; use aptos_crypto::{ - bls12381, ed25519::ED25519_PUBLIC_KEY_LENGTH, x25519, ValidCryptoMaterial, + ed25519, ed25519::ED25519_PUBLIC_KEY_LENGTH, x25519, ValidCryptoMaterial, ValidCryptoMaterialStringExt, }; use aptos_genesis::{ @@ -198,7 +198,6 @@ pub fn fetch_mainnet_genesis_info(git_options: GitOptions) -> CliTypedResult CliTypedResult CliTypedResult, unique_accounts: &mut BTreeSet, unique_network_keys: &mut HashSet, - unique_consensus_keys: &mut HashSet, - unique_consensus_pops: &mut HashSet, + unique_consensus_keys: &mut HashSet, unique_hosts: &mut HashSet, seen_owners: &mut BTreeMap, is_pooled_validator: bool, @@ -747,22 +735,6 @@ fn validate_validators( ))); } - if validator.proof_of_possession.is_none() { - errors.push(CliError::UnexpectedError(format!( - "Validator {} does not have a consensus proof of possession, though it's joining during genesis", - name - ))); - } - if !unique_consensus_pops - .insert(validator.proof_of_possession.as_ref().unwrap().clone()) - { - errors.push(CliError::UnexpectedError(format!( - "Validator {} has a repeated a consensus proof of possessions {}", - name, - validator.proof_of_possession.as_ref().unwrap() - ))); - } - match ( validator.full_node_host.as_ref(), validator.full_node_network_public_key.as_ref(), @@ -832,12 +804,6 @@ fn validate_validators( name ))); } - if validator.proof_of_possession.is_some() { - errors.push(CliError::UnexpectedError(format!( - "Validator {} has a consensus proof of possession, but it is *NOT* joining during genesis", - name - ))); - } if validator.full_node_network_public_key.is_some() { errors.push(CliError::UnexpectedError(format!( "Validator {} has a full node public key, but it is *NOT* joining during genesis", diff --git a/crates/aptos/src/genesis/tests.rs b/crates/aptos/src/genesis/tests.rs index bb270e6ef85274..e67c37cccf5acc 100644 --- a/crates/aptos/src/genesis/tests.rs +++ b/crates/aptos/src/genesis/tests.rs @@ -382,7 +382,6 @@ async fn create_employee_vesting_accounts_file( voter_account_address: admin_identity.account_address.into(), voter_account_public_key: admin_identity.account_public_key, consensus_public_key: operator_identity.consensus_public_key, - proof_of_possession: operator_identity.consensus_proof_of_possession, validator_network_public_key: operator_identity.validator_network_public_key, validator_host: Some(HostAndPort::from_str("localhost:8080").unwrap()), full_node_network_public_key: operator_identity.full_node_network_public_key, @@ -400,7 +399,6 @@ async fn create_employee_vesting_accounts_file( voter_account_address: admin_identity.account_address.into(), voter_account_public_key: admin_identity.account_public_key, consensus_public_key: None, - proof_of_possession: None, validator_network_public_key: None, validator_host: None, full_node_network_public_key: None, diff --git a/crates/aptos/src/node/mod.rs b/crates/aptos/src/node/mod.rs index 83d32e501d0102..4a8d16c8b021cb 100644 --- a/crates/aptos/src/node/mod.rs +++ b/crates/aptos/src/node/mod.rs @@ -25,7 +25,7 @@ use aptos_backup_cli::{ utils::GlobalRestoreOpt, }; use aptos_cached_packages::aptos_stdlib; -use aptos_crypto::{bls12381, bls12381::PublicKey, x25519, ValidCryptoMaterialStringExt}; +use aptos_crypto::{ed25519, ed25519::PublicKey, x25519, ValidCryptoMaterialStringExt}; use aptos_genesis::config::{HostAndPort, OperatorConfiguration}; use aptos_logger::Level; use aptos_network_checker::args::{ @@ -136,21 +136,15 @@ pub struct ValidatorConsensusKeyArgs { /// Hex encoded Consensus public key /// /// The key should be a BLS12-381 public key - #[clap(long, value_parser = bls12381::PublicKey::from_encoded_string)] - pub(crate) consensus_public_key: Option, - - /// Hex encoded Consensus proof of possession - /// - /// The key should be a BLS12-381 proof of possession - #[clap(long, value_parser = bls12381::ProofOfPossession::from_encoded_string)] - pub(crate) proof_of_possession: Option, + #[clap(long, value_parser = ed25519::PublicKey::from_encoded_string)] + pub(crate) consensus_public_key: Option, } impl ValidatorConsensusKeyArgs { fn get_consensus_public_key<'a>( &'a self, operator_config: &'a Option, - ) -> CliTypedResult<&'a bls12381::PublicKey> { + ) -> CliTypedResult<&'a ed25519::PublicKey> { let consensus_public_key = if let Some(ref consensus_public_key) = self.consensus_public_key { consensus_public_key @@ -163,22 +157,6 @@ impl ValidatorConsensusKeyArgs { }; Ok(consensus_public_key) } - - fn get_consensus_proof_of_possession<'a>( - &'a self, - operator_config: &'a Option, - ) -> CliTypedResult<&'a bls12381::ProofOfPossession> { - let proof_of_possession = if let Some(ref proof_of_possession) = self.proof_of_possession { - proof_of_possession - } else if let Some(ref operator_config) = operator_config { - &operator_config.consensus_proof_of_possession - } else { - return Err(CliError::CommandArgumentError( - "Must provide either --operator-config-file or --proof-of-possession".to_string(), - )); - }; - Ok(proof_of_possession) - } } #[derive(Parser)] @@ -612,9 +590,6 @@ impl CliCommand for InitializeValidator { let consensus_public_key = self .validator_consensus_key_args .get_consensus_public_key(&operator_config)?; - let consensus_proof_of_possession = self - .validator_consensus_key_args - .get_consensus_proof_of_possession(&operator_config)?; let ( validator_network_public_key, full_node_network_public_key, @@ -640,7 +615,6 @@ impl CliCommand for InitializeValidator { self.txn_options .submit_transaction(aptos_stdlib::stake_initialize_validator( consensus_public_key.to_bytes().to_vec(), - consensus_proof_of_possession.to_bytes().to_vec(), // BCS encode, so that we can hide the original type bcs::to_bytes(&validator_network_addresses)?, bcs::to_bytes(&full_node_network_addresses)?, @@ -1072,14 +1046,10 @@ impl CliCommand for UpdateConsensusKey { let consensus_public_key = self .validator_consensus_key_args .get_consensus_public_key(&operator_config)?; - let consensus_proof_of_possession = self - .validator_consensus_key_args - .get_consensus_proof_of_possession(&operator_config)?; self.txn_options .submit_transaction(aptos_stdlib::stake_rotate_consensus_key( address, consensus_public_key.to_bytes().to_vec(), - consensus_proof_of_possession.to_bytes().to_vec(), )) .await .map(|inner| inner.into()) diff --git a/crates/aptos/src/op/key.rs b/crates/aptos/src/op/key.rs index 07a65a21db2da7..a68ad6ef78f485 100644 --- a/crates/aptos/src/op/key.rs +++ b/crates/aptos/src/op/key.rs @@ -15,9 +15,7 @@ use crate::{ CliCommand, CliResult, }; use aptos_config::config::{Peer, PeerRole}; -use aptos_crypto::{ - bls12381, ed25519, encoding_type::EncodingType, x25519, PrivateKey, ValidCryptoMaterial, -}; +use aptos_crypto::{ed25519, encoding_type::EncodingType, x25519, PrivateKey, ValidCryptoMaterial}; use aptos_genesis::config::HostAndPort; use aptos_types::account_address::{ create_multisig_account_address, from_identity_public_key, AccountAddress, @@ -255,8 +253,8 @@ impl CliCommand> for GenerateKey { return Ok(result_map); }, KeyType::Bls12381 => { - let private_key = keygen.generate_bls12381_private_key(); - self.save_params.save_bls_key(&private_key, "bls12381") + let private_key = keygen.generate_ed25519_private_key(); + self.save_params.save_key(&private_key, "ed25519") }, } } @@ -325,11 +323,6 @@ impl SaveKey { ) } - /// Public key file name - fn proof_of_possession_file(&self) -> CliTypedResult { - append_file_extension(self.file_options.output_file.as_path(), "pop") - } - /// Check if the key file exists already pub fn check_key_file(&self) -> CliTypedResult<()> { // Check if file already exists @@ -360,39 +353,4 @@ impl SaveKey { map.insert("PublicKey Path", public_key_file); Ok(map) } - - /// Saves a key to a file encoded in a string - pub fn save_bls_key( - self, - key: &bls12381::PrivateKey, - key_name: &'static str, - ) -> CliTypedResult> { - let encoded_private_key = self.encoding_options.encoding.encode_key(key_name, key)?; - let encoded_public_key = self - .encoding_options - .encoding - .encode_key(key_name, &key.public_key())?; - let encoded_proof_of_posession = self - .encoding_options - .encoding - .encode_key(key_name, &bls12381::ProofOfPossession::create(key))?; - - // Write private and public keys to files - let public_key_file = self.public_key_file()?; - let proof_of_possession_file = self.proof_of_possession_file()?; - self.file_options - .save_to_file_confidential(key_name, &encoded_private_key)?; - write_to_file(&public_key_file, key_name, &encoded_public_key)?; - write_to_file( - &proof_of_possession_file, - key_name, - &encoded_proof_of_posession, - )?; - - let mut map = HashMap::new(); - map.insert("PrivateKey Path", self.file_options.output_file); - map.insert("PublicKey Path", public_key_file); - map.insert("Proof of possession Path", proof_of_possession_file); - Ok(map) - } } diff --git a/crates/aptos/src/test/mod.rs b/crates/aptos/src/test/mod.rs index b6353852db1f3a..c7008c7371989f 100644 --- a/crates/aptos/src/test/mod.rs +++ b/crates/aptos/src/test/mod.rs @@ -46,7 +46,7 @@ use crate::{ }; use aptos_config::config::Peer; use aptos_crypto::{ - bls12381, + ed25519, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, x25519, PrivateKey, }; @@ -372,8 +372,7 @@ impl CliTestFramework { pub async fn initialize_validator( &self, index: usize, - consensus_public_key: bls12381::PublicKey, - proof_of_possession: bls12381::ProofOfPossession, + consensus_public_key: ed25519::PublicKey, validator_host: HostAndPort, validator_network_public_key: x25519::PublicKey, ) -> CliTypedResult { @@ -384,7 +383,6 @@ impl CliTestFramework { }, validator_consensus_key_args: ValidatorConsensusKeyArgs { consensus_public_key: Some(consensus_public_key), - proof_of_possession: Some(proof_of_possession), }, validator_network_addresses_args: ValidatorNetworkAddressesArgs { validator_host: Some(validator_host), @@ -515,8 +513,7 @@ impl CliTestFramework { &self, operator_index: usize, pool_index: Option, - consensus_public_key: bls12381::PublicKey, - proof_of_possession: bls12381::ProofOfPossession, + consensus_public_key: ed25519::PublicKey, ) -> CliTypedResult { UpdateConsensusKey { txn_options: self.transaction_options(operator_index, None), @@ -526,7 +523,6 @@ impl CliTestFramework { }, validator_consensus_key_args: ValidatorConsensusKeyArgs { consensus_public_key: Some(consensus_public_key), - proof_of_possession: Some(proof_of_possession), }, } .execute() diff --git a/dkg/src/dkg_manager/tests.rs b/dkg/src/dkg_manager/tests.rs index 8e48a6227df41b..eca7d30194c60f 100644 --- a/dkg/src/dkg_manager/tests.rs +++ b/dkg/src/dkg_manager/tests.rs @@ -8,7 +8,7 @@ use crate::{ DKGMessage, }; use aptos_crypto::{ - bls12381::{PrivateKey, PublicKey}, + ed25519::{PrivateKey, PublicKey}, Uniform, }; use aptos_infallible::RwLock; diff --git a/dkg/src/transcript_aggregation/tests.rs b/dkg/src/transcript_aggregation/tests.rs index eeb2e34dcfb50a..163c55034ba382 100644 --- a/dkg/src/transcript_aggregation/tests.rs +++ b/dkg/src/transcript_aggregation/tests.rs @@ -1,7 +1,7 @@ // Copyright © Aptos Foundation use crate::transcript_aggregation::TranscriptAggregationState; -use aptos_crypto::{bls12381::bls12381_keys, Uniform}; +use aptos_crypto::{ed25519, Uniform}; use aptos_reliable_broadcast::BroadcastStatus; use aptos_types::{ dkg::{ @@ -23,11 +23,11 @@ fn test_transcript_aggregation_state() { let addrs: Vec = (0..num_validators) .map(|_| AccountAddress::random()) .collect(); - let private_keys: Vec = (0..num_validators) - .map(|_| bls12381_keys::PrivateKey::generate_for_testing()) + let private_keys: Vec = (0..num_validators) + .map(|_| ed25519::PrivateKey::generate_for_testing()) .collect(); - let public_keys: Vec = (0..num_validators) - .map(|i| bls12381_keys::PublicKey::from(&private_keys[i])) + let public_keys: Vec = (0..num_validators) + .map(|i| ed25519::PublicKey::from(&private_keys[i])) .collect(); let voting_powers = [1, 1, 1, 6, 6]; // total voting power: 15, default threshold: 11 let validator_infos: Vec = (0..num_validators) diff --git a/network/discovery/src/validator_set.rs b/network/discovery/src/validator_set.rs index f6953f34ac780e..6f8305950ae1b6 100644 --- a/network/discovery/src/validator_set.rs +++ b/network/discovery/src/validator_set.rs @@ -156,7 +156,7 @@ mod tests { use crate::DiscoveryChangeListener; use aptos_channels::{aptos_channel, message_queues::QueueStyle}; use aptos_config::config::HANDSHAKE_VERSION; - use aptos_crypto::{bls12381, x25519::PrivateKey, PrivateKey as PK, Uniform}; + use aptos_crypto::{ed25519, x25519::PrivateKey, PrivateKey as PK, Uniform}; use aptos_event_notifications::ReconfigNotification; use aptos_types::{ network_address::NetworkAddress, @@ -177,7 +177,7 @@ mod tests { fn metric_if_key_mismatch() { aptos_logger::Logger::init_for_testing(); let runtime = Runtime::new().unwrap(); - let consensus_private_key = bls12381::PrivateKey::generate_for_testing(); + let consensus_private_key = ed25519::PrivateKey::generate_for_testing(); let consensus_pubkey = consensus_private_key.public_key(); let pubkey = test_pubkey([0u8; 32]); let different_pubkey = test_pubkey([1u8; 32]); @@ -237,7 +237,7 @@ mod tests { fn send_pubkey_update( peer_id: PeerId, - consensus_pubkey: bls12381::PublicKey, + consensus_pubkey: ed25519::PublicKey, pubkey: x25519::PublicKey, reconfig_tx: &mut aptos_channels::aptos_channel::Sender< (), diff --git a/testsuite/generate-format/src/api.rs b/testsuite/generate-format/src/api.rs index 6d229913415732..9211b7500fe122 100644 --- a/testsuite/generate-format/src/api.rs +++ b/testsuite/generate-format/src/api.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_crypto::{ - bls12381, + ed25519, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, hash::{CryptoHasher as _, TestOnlyHasher}, multi_ed25519::{MultiEd25519PublicKey, MultiEd25519Signature}, @@ -73,8 +73,8 @@ fn trace_crypto_values(tracer: &mut Tracer, samples: &mut Samples) -> Result<()> tracer.trace_value(samples, &secp256r1_ecdsa_public_key)?; tracer.trace_value(samples, &secp256r1_ecdsa_signature)?; - let bls12381_private_key = bls12381::PrivateKey::generate(&mut rng); - let bls12381_public_key = bls12381::PublicKey::from(&bls12381_private_key); + let bls12381_private_key = ed25519::PrivateKey::generate(&mut rng); + let bls12381_public_key = ed25519::PublicKey::from(&bls12381_private_key); let bls12381_signature = bls12381_private_key.sign(&message).unwrap(); tracer.trace_value(samples, &bls12381_private_key)?; tracer.trace_value(samples, &bls12381_public_key)?; diff --git a/testsuite/generate-format/src/aptos.rs b/testsuite/generate-format/src/aptos.rs index 3d0d4800cca2ac..3559388acd799d 100644 --- a/testsuite/generate-format/src/aptos.rs +++ b/testsuite/generate-format/src/aptos.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_crypto::{ - bls12381, + ed25519, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, hash::{CryptoHasher as _, TestOnlyHasher}, multi_ed25519::{MultiEd25519PublicKey, MultiEd25519Signature}, @@ -70,8 +70,8 @@ fn trace_crypto_values(tracer: &mut Tracer, samples: &mut Samples) -> Result<()> tracer.trace_value(samples, &secp256r1_ecdsa_public_key)?; tracer.trace_value(samples, &secp256r1_ecdsa_signature)?; - let bls12381_private_key = bls12381::PrivateKey::generate(&mut rng); - let bls12381_public_key = bls12381::PublicKey::from(&bls12381_private_key); + let bls12381_private_key = ed25519::PrivateKey::generate(&mut rng); + let bls12381_public_key = ed25519::PublicKey::from(&bls12381_private_key); let bls12381_signature = bls12381_private_key.sign(&message).unwrap(); tracer.trace_value(samples, &bls12381_private_key)?; tracer.trace_value(samples, &bls12381_public_key)?; diff --git a/testsuite/generate-format/src/consensus.rs b/testsuite/generate-format/src/consensus.rs index 0a36c8fc9f0994..9fd471accc219b 100644 --- a/testsuite/generate-format/src/consensus.rs +++ b/testsuite/generate-format/src/consensus.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_crypto::{ - bls12381, + ed25519, ed25519::Ed25519PrivateKey, multi_ed25519::{MultiEd25519PublicKey, MultiEd25519Signature}, secp256k1_ecdsa, secp256r1_ecdsa, @@ -46,7 +46,7 @@ fn trace_crypto_values(tracer: &mut Tracer, samples: &mut Samples) -> Result<()> let public_key = private_key.public_key(); let signature = private_key.sign(&message).unwrap(); - let bls_private_key = bls12381::PrivateKey::generate(&mut rng); + let bls_private_key = ed25519::PrivateKey::generate(&mut rng); let bls_public_key = bls_private_key.public_key(); let bls_signature = bls_private_key.sign(&message).unwrap(); diff --git a/testsuite/smoke-test/src/aptos_cli/validator.rs b/testsuite/smoke-test/src/aptos_cli/validator.rs index 31e030e99b1c0f..2bd73acb712e2b 100644 --- a/testsuite/smoke-test/src/aptos_cli/validator.rs +++ b/testsuite/smoke-test/src/aptos_cli/validator.rs @@ -16,7 +16,7 @@ use aptos::{ }; use aptos_bitvec::BitVec; use aptos_cached_packages::aptos_stdlib; -use aptos_crypto::{bls12381, ed25519::Ed25519PrivateKey, x25519, ValidCryptoMaterialStringExt}; +use aptos_crypto::{ed25519, ed25519::Ed25519PrivateKey, x25519, ValidCryptoMaterialStringExt}; use aptos_forge::{reconfig, wait_for_all_nodes_to_catchup, LocalSwarm, NodeExt, Swarm, SwarmExt}; use aptos_genesis::config::HostAndPort; use aptos_keygen::KeyGen; @@ -574,7 +574,6 @@ async fn test_large_total_stake() { cli.initialize_validator( validator_cli_index, keys.consensus_public_key(), - keys.consensus_proof_of_possession(), HostAndPort { host: dns_name("0.0.0.0"), port: 1234, @@ -969,7 +968,6 @@ async fn test_register_and_update_validator() { cli.initialize_validator( validator_cli_index, keys.consensus_public_key(), - keys.consensus_proof_of_possession(), HostAndPort { host: dns_name("0.0.0.0"), port, @@ -1079,7 +1077,6 @@ async fn test_join_and_leave_validator() { cli.initialize_validator( validator_cli_index, keys.consensus_public_key(), - keys.consensus_proof_of_possession(), HostAndPort { host: dns_name("0.0.0.0"), port, @@ -1335,7 +1332,6 @@ async fn test_owner_create_and_delegate_flow() { operator_cli_index, Some(owner_cli_index), operator_keys.consensus_public_key(), - operator_keys.consensus_proof_of_possession(), ) .await .unwrap(), @@ -1444,7 +1440,7 @@ fn dns_name(addr: &str) -> DnsName { pub struct ValidatorNodeKeys { account_private_key: Ed25519PrivateKey, network_private_key: x25519::PrivateKey, - consensus_private_key: bls12381::PrivateKey, + consensus_private_key: ed25519::PrivateKey, } impl ValidatorNodeKeys { @@ -1452,7 +1448,7 @@ impl ValidatorNodeKeys { Self { account_private_key: keygen.generate_ed25519_private_key(), network_private_key: keygen.generate_x25519_private_key().unwrap(), - consensus_private_key: keygen.generate_bls12381_private_key(), + consensus_private_key: keygen.generate_ed25519_private_key(), } } @@ -1460,12 +1456,8 @@ impl ValidatorNodeKeys { self.network_private_key.public_key() } - pub fn consensus_public_key(&self) -> bls12381::PublicKey { - bls12381::PublicKey::from(&self.consensus_private_key) - } - - pub fn consensus_proof_of_possession(&self) -> bls12381::ProofOfPossession { - bls12381::ProofOfPossession::create(&self.consensus_private_key) + pub fn consensus_public_key(&self) -> ed25519::PublicKey { + ed25519::PublicKey::from(&self.consensus_private_key) } } diff --git a/types/src/aggregate_signature.rs b/types/src/aggregate_signature.rs index 3202583b6252d0..c5d9c38a01399f 100644 --- a/types/src/aggregate_signature.rs +++ b/types/src/aggregate_signature.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_bitvec::BitVec; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use move_core_types::account_address::AccountAddress; use serde::{Deserialize, Serialize}; @@ -15,13 +15,13 @@ use std::collections::BTreeMap; #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, CryptoHasher, BCSCryptoHash)] pub struct AggregateSignature { validator_bitmask: BitVec, - sig: Option, + sig: Option, } impl AggregateSignature { pub fn new( validator_bitmask: BitVec, - aggregated_signature: Option, + aggregated_signature: Option, ) -> Self { Self { validator_bitmask, @@ -61,7 +61,7 @@ impl AggregateSignature { self.validator_bitmask.count_ones() as usize } - pub fn sig(&self) -> &Option { + pub fn sig(&self) -> &Option { &self.sig } } @@ -70,11 +70,11 @@ impl AggregateSignature { /// from different validators. It is only kept in memory and never sent through the network. #[derive(Clone, Debug, Deserialize, Eq, PartialEq)] pub struct PartialSignatures { - signatures: BTreeMap, + signatures: BTreeMap, } impl PartialSignatures { - pub fn new(signatures: BTreeMap) -> Self { + pub fn new(signatures: BTreeMap) -> Self { Self { signatures } } @@ -90,11 +90,11 @@ impl PartialSignatures { self.signatures.remove(&validator); } - pub fn add_signature(&mut self, validator: AccountAddress, signature: bls12381::Signature) { + pub fn add_signature(&mut self, validator: AccountAddress, signature: ed25519::Signature) { self.signatures.entry(validator).or_insert(signature); } - pub fn signatures(&self) -> &BTreeMap { + pub fn signatures(&self) -> &BTreeMap { &self.signatures } diff --git a/types/src/dkg/dummy_dkg/mod.rs b/types/src/dkg/dummy_dkg/mod.rs index eed07088221acf..8664685b89208a 100644 --- a/types/src/dkg/dummy_dkg/mod.rs +++ b/types/src/dkg/dummy_dkg/mod.rs @@ -2,7 +2,7 @@ use crate::dkg::{DKGSessionMetadata, DKGTrait}; use anyhow::{anyhow, ensure}; -use aptos_crypto::{bls12381, Uniform}; +use aptos_crypto::{ed25519, Uniform}; use rand::{CryptoRng, Rng, RngCore}; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, BTreeSet}; @@ -13,11 +13,11 @@ use std::collections::{BTreeMap, BTreeSet}; pub struct DummyDKG {} impl DKGTrait for DummyDKG { - type DealerPrivateKey = bls12381::PrivateKey; + type DealerPrivateKey = ed25519::PrivateKey; type DealtSecret = DummySecret; type DealtSecretShare = DummySecret; type InputSecret = DummySecret; - type NewValidatorDecryptKey = bls12381::PrivateKey; + type NewValidatorDecryptKey = ed25519::PrivateKey; type PublicParams = DKGSessionMetadata; type Transcript = DummyDKGTranscript; @@ -110,7 +110,7 @@ impl DKGTrait for DummyDKG { } fn generate_predictable_input_secret_for_testing( - dealer_sk: &bls12381::PrivateKey, + dealer_sk: &ed25519::PrivateKey, ) -> DummySecret { let bytes_8: [u8; 8] = dealer_sk.to_bytes()[0..8].try_into().unwrap(); DummySecret { diff --git a/types/src/dkg/dummy_dkg/tests.rs b/types/src/dkg/dummy_dkg/tests.rs index e1a91ea14e039e..b16047f510a565 100644 --- a/types/src/dkg/dummy_dkg/tests.rs +++ b/types/src/dkg/dummy_dkg/tests.rs @@ -7,15 +7,15 @@ use crate::{ }, validator_verifier::{ValidatorConsensusInfo, ValidatorConsensusInfoMoveStruct}, }; -use aptos_crypto::{bls12381, Uniform}; +use aptos_crypto::{ed25519, Uniform}; use move_core_types::account_address::AccountAddress; use rand::thread_rng; struct DealerState { addr: AccountAddress, voting_power: u64, - sk: bls12381::PrivateKey, - pk: bls12381::PublicKey, + sk: ed25519::PrivateKey, + pk: ed25519::PublicKey, input_secret: DummySecret, transcript: Option, } @@ -33,8 +33,8 @@ impl DealerState { struct NewValidatorState { addr: AccountAddress, voting_power: u64, - sk: bls12381::PrivateKey, - pk: bls12381::PublicKey, + sk: ed25519::PrivateKey, + pk: ed25519::PublicKey, secret_share: Option, } @@ -55,8 +55,8 @@ fn test_dummy_dkg_correctness() { // Initialize the current validator states. Also prepare their DKG input secrets. let mut dealer_states: Vec = (0..3) .map(|_| { - let sk = bls12381::PrivateKey::generate_for_testing(); - let pk = bls12381::PublicKey::from(&sk); + let sk = ed25519::PrivateKey::generate_for_testing(); + let pk = ed25519::PublicKey::from(&sk); let input_secret = DummySecret::generate_for_testing(); DealerState { addr: AccountAddress::random(), @@ -76,8 +76,8 @@ fn test_dummy_dkg_correctness() { // Initialize the next validator states. let mut new_validator_states: Vec = (0..4) .map(|_| { - let sk = bls12381::PrivateKey::generate_for_testing(); - let pk = bls12381::PublicKey::from(&sk); + let sk = ed25519::PrivateKey::generate_for_testing(); + let pk = ed25519::PublicKey::from(&sk); NewValidatorState { addr: AccountAddress::random(), voting_power: 2, diff --git a/types/src/ledger_info.rs b/types/src/ledger_info.rs index 47ce8c620b1d3c..855af8d52cdb43 100644 --- a/types/src/ledger_info.rs +++ b/types/src/ledger_info.rs @@ -12,7 +12,7 @@ use crate::{ transaction::Version, validator_verifier::{ValidatorVerifier, VerifyError}, }; -use aptos_crypto::{bls12381, hash::HashValue}; +use aptos_crypto::{ed25519, hash::HashValue}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; #[cfg(any(test, feature = "fuzzing"))] use proptest_derive::Arbitrary; @@ -336,11 +336,11 @@ impl LedgerInfoWithPartialSignatures { self.partial_sigs.remove_signature(validator); } - pub fn add_signature(&mut self, validator: AccountAddress, signature: bls12381::Signature) { + pub fn add_signature(&mut self, validator: AccountAddress, signature: ed25519::Signature) { self.partial_sigs.add_signature(validator, signature); } - pub fn signatures(&self) -> &BTreeMap { + pub fn signatures(&self) -> &BTreeMap { self.partial_sigs.signatures() } @@ -384,7 +384,7 @@ impl Arbitrary for LedgerInfoWithV0 { type Strategy = BoxedStrategy; fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - let dummy_signature = bls12381::Signature::dummy_signature(); + let dummy_signature = ed25519::Signature::dummy_signature(); (any::(), (1usize..100)) .prop_map(move |(ledger_info, num_validators)| { let (signers, verifier) = random_validator_verifier(num_validators, None, true); diff --git a/types/src/proptest_types.rs b/types/src/proptest_types.rs index ddc0ae23a9446a..34eedab0fd5273 100644 --- a/types/src/proptest_types.rs +++ b/types/src/proptest_types.rs @@ -36,7 +36,6 @@ use crate::{ write_set::{WriteOp, WriteSet, WriteSetMut}, }; use aptos_crypto::{ - bls12381::{self, bls12381_keys}, ed25519::{self, Ed25519PrivateKey, Ed25519PublicKey}, test_utils::KeyPair, traits::*, @@ -143,17 +142,14 @@ struct AccountInfo { address: AccountAddress, private_key: Ed25519PrivateKey, public_key: Ed25519PublicKey, - consensus_private_key: bls12381::PrivateKey, + consensus_private_key: ed25519::PrivateKey, sequence_number: u64, sent_event_handle: EventHandle, received_event_handle: EventHandle, } impl AccountInfo { - pub fn new( - private_key: Ed25519PrivateKey, - consensus_private_key: bls12381::PrivateKey, - ) -> Self { + pub fn new(private_key: Ed25519PrivateKey, consensus_private_key: ed25519::PrivateKey) -> Self { let public_key = private_key.public_key(); let address = account_address::from_public_key(&public_key); Self { @@ -180,7 +176,7 @@ pub struct AccountInfoUniverse { impl AccountInfoUniverse { fn new( account_private_keys: Vec, - consensus_private_keys: Vec, + consensus_private_keys: Vec, epoch: u64, round: Round, next_version: Version, @@ -262,10 +258,7 @@ impl Arbitrary for AccountInfoUniverse { fn arbitrary_with(num_accounts: Self::Parameters) -> Self::Strategy { vec( - ( - ed25519::keypair_strategy(), - bls12381_keys::keypair_strategy(), - ), + (ed25519::keypair_strategy(), ed25519::keypair_strategy()), num_accounts, ) .prop_map(|kps| { @@ -560,8 +553,8 @@ prop_compose! { fn arb_validator_for_ledger_info(ledger_info: LedgerInfo)( ledger_info in Just(ledger_info), account_keypair in ed25519::keypair_strategy(), - consensus_keypair in bls12381_keys::keypair_strategy(), - ) -> (AccountAddress, ValidatorConsensusInfo, bls12381::Signature) { + consensus_keypair in ed25519::keypair_strategy(), + ) -> (AccountAddress, ValidatorConsensusInfo, ed25519::Signature) { let signature = consensus_keypair.private_key.sign(&ledger_info).unwrap(); let address = account_address::from_public_key(&account_keypair.public_key); (address, ValidatorConsensusInfo::new(address, consensus_keypair.public_key, 1), signature) diff --git a/types/src/validator_config.rs b/types/src/validator_config.rs index d43f4bea237633..3e2354ee998dc6 100644 --- a/types/src/validator_config.rs +++ b/types/src/validator_config.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::network_address::NetworkAddress; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; use move_core_types::{ ident_str, identifier::IdentStr, @@ -35,7 +35,7 @@ impl MoveResource for ValidatorOperatorConfigResource {} #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] pub struct ValidatorConfig { - pub consensus_public_key: bls12381::PublicKey, + pub consensus_public_key: ed25519::PublicKey, /// This is an bcs serialized `Vec` pub validator_network_addresses: Vec, /// This is an bcs serialized `Vec` @@ -45,7 +45,7 @@ pub struct ValidatorConfig { impl ValidatorConfig { pub fn new( - consensus_public_key: bls12381::PublicKey, + consensus_public_key: ed25519::PublicKey, validator_network_addresses: Vec, fullnode_network_addresses: Vec, validator_index: u64, diff --git a/types/src/validator_info.rs b/types/src/validator_info.rs index 2f56486273edf4..01f5c7f3fd09d5 100644 --- a/types/src/validator_info.rs +++ b/types/src/validator_info.rs @@ -5,7 +5,7 @@ #[cfg(any(test, feature = "fuzzing"))] use crate::network_address::NetworkAddress; use crate::{account_address::AccountAddress, validator_config::ValidatorConfig}; -use aptos_crypto::bls12381; +use aptos_crypto::ed25519; #[cfg(any(test, feature = "fuzzing"))] use proptest_derive::Arbitrary; use serde::{Deserialize, Serialize}; @@ -55,7 +55,7 @@ impl ValidatorInfo { #[cfg(any(test, feature = "fuzzing"))] pub fn new_with_test_network_keys( account_address: AccountAddress, - consensus_public_key: bls12381::PublicKey, + consensus_public_key: ed25519::PublicKey, consensus_voting_power: u64, validator_index: u64, ) -> Self { @@ -81,7 +81,7 @@ impl ValidatorInfo { } /// Returns the key for validating signed messages from this validator - pub fn consensus_public_key(&self) -> &bls12381::PublicKey { + pub fn consensus_public_key(&self) -> &ed25519::PublicKey { &self.config.consensus_public_key } diff --git a/types/src/validator_signer.rs b/types/src/validator_signer.rs index 84140126547056..60c59a997d62ea 100644 --- a/types/src/validator_signer.rs +++ b/types/src/validator_signer.rs @@ -4,7 +4,7 @@ use crate::account_address::AccountAddress; use aptos_crypto::{ - bls12381, hash::CryptoHash, test_utils::TEST_SEED, CryptoMaterialError, PrivateKey, SigningKey, + ed25519, hash::CryptoHash, test_utils::TEST_SEED, CryptoMaterialError, PrivateKey, SigningKey, Uniform, }; use rand::{rngs::StdRng, SeedableRng}; @@ -18,11 +18,11 @@ use std::convert::TryFrom; #[cfg_attr(any(test, feature = "fuzzing"), derive(Clone))] pub struct ValidatorSigner { author: AccountAddress, - private_key: bls12381::PrivateKey, + private_key: ed25519::PrivateKey, } impl ValidatorSigner { - pub fn new(author: AccountAddress, private_key: bls12381::PrivateKey) -> Self { + pub fn new(author: AccountAddress, private_key: ed25519::PrivateKey) -> Self { ValidatorSigner { author, private_key, @@ -33,7 +33,7 @@ impl ValidatorSigner { pub fn sign( &self, message: &T, - ) -> Result { + ) -> Result { self.private_key.sign(message) } @@ -43,13 +43,13 @@ impl ValidatorSigner { } /// Returns the public key associated with this signer. - pub fn public_key(&self) -> bls12381::PublicKey { + pub fn public_key(&self) -> ed25519::PublicKey { self.private_key.public_key() } /// Returns the private key associated with this signer. Only available for testing purposes. #[cfg(any(test, feature = "fuzzing"))] - pub fn private_key(&self) -> &bls12381::PrivateKey { + pub fn private_key(&self) -> &ed25519::PrivateKey { &self.private_key } } @@ -63,7 +63,7 @@ impl ValidatorSigner { let mut rng = StdRng::from_seed(opt_rng_seed.into().unwrap_or(TEST_SEED)); Self::new( AccountAddress::random(), - bls12381::PrivateKey::generate(&mut rng), + ed25519::PrivateKey::generate(&mut rng), ) } @@ -72,7 +72,7 @@ impl ValidatorSigner { pub fn from_int(num: u8) -> Self { let mut address = [0; AccountAddress::LENGTH]; address[0] = num; - let private_key = bls12381::PrivateKey::generate_for_testing(); + let private_key = ed25519::PrivateKey::generate_for_testing(); Self::new(AccountAddress::try_from(&address[..]).unwrap(), private_key) } } @@ -84,17 +84,17 @@ pub mod proptests { use proptest::{prelude::*, sample, strategy::LazyJust}; #[allow(clippy::redundant_closure)] - pub fn arb_signing_key() -> impl Strategy { + pub fn arb_signing_key() -> impl Strategy { prop_oneof![ // The no_shrink here reflects that particular keypair choices out // of random options are irrelevant. - LazyJust::new(|| bls12381::PrivateKey::generate_for_testing()), - LazyJust::new(|| bls12381::PrivateKey::genesis()), + LazyJust::new(|| ed25519::PrivateKey::generate_for_testing()), + LazyJust::new(|| ed25519::PrivateKey::genesis()), ] } pub fn signer_strategy( - signing_key_strategy: impl Strategy, + signing_key_strategy: impl Strategy, ) -> impl Strategy { signing_key_strategy.prop_map(|signing_key| { ValidatorSigner::new( @@ -114,20 +114,20 @@ pub mod proptests { prop_oneof![ rand_signer(), LazyJust::new(|| { - let genesis_key = bls12381::PrivateKey::genesis(); + let genesis_key = ed25519::PrivateKey::genesis(); ValidatorSigner::new(AccountAddress::random(), genesis_key) }) ] } fn select_keypair( - keys: Vec, - ) -> impl Strategy { + keys: Vec, + ) -> impl Strategy { sample::select(keys) } pub fn mostly_in_keypair_pool( - keys: Vec, + keys: Vec, ) -> impl Strategy { prop::strategy::Union::new_weighted(vec![ (9, signer_strategy(select_keypair(keys)).boxed()), diff --git a/types/src/validator_verifier.rs b/types/src/validator_verifier.rs index f035e3bb0bf023..a13f7b695754b3 100644 --- a/types/src/validator_verifier.rs +++ b/types/src/validator_verifier.rs @@ -11,12 +11,7 @@ use crate::{ }; use anyhow::{ensure, Result}; use aptos_bitvec::BitVec; -use aptos_crypto::{ - bls12381, - bls12381::{bls12381_keys, PublicKey}, - hash::CryptoHash, - Signature, VerifyingKey, -}; +use aptos_crypto::{ed25519, ed25519::PublicKey, hash::CryptoHash, Signature, VerifyingKey}; use itertools::Itertools; #[cfg(any(test, feature = "fuzzing"))] use proptest_derive::Arbitrary; @@ -120,7 +115,7 @@ impl TryFrom for ValidatorConsensusInfo { pk_bytes, voting_power, } = value; - let public_key = bls12381_keys::PublicKey::try_from(pk_bytes.as_slice())?; + let public_key = PublicKey::try_from(pk_bytes.as_slice())?; Ok(Self::new(addr, public_key, voting_power)) } } @@ -225,7 +220,7 @@ impl ValidatorVerifier { &self, author: AccountAddress, message: &T, - signature: &bls12381::Signature, + signature: &ed25519::Signature, ) -> std::result::Result<(), VerifyError> { match self.get_public_key(&author) { Some(public_key) => public_key @@ -253,7 +248,7 @@ impl ValidatorVerifier { sigs.push(sig.clone()); } // Perform an optimistic aggregation of the signatures without verification. - let aggregated_sig = bls12381::Signature::aggregate(sigs) + let aggregated_sig = ed25519::Signature::aggregate(sigs) .map_err(|_| VerifyError::FailedToAggregateSignature)?; Ok(AggregateSignature::new(masks, Some(aggregated_sig)))