@@ -1073,4 +1073,88 @@ mod tests {
1073
1073
1074
1074
assert_error_matches ! ( CertificateVerifierError :: CertificateHashUnmatch , error)
1075
1075
}
1076
+
1077
+ #[ tokio:: test]
1078
+ async fn verify_certificate_chain_fails_when_adversarial_with_registered_signer_forgery_through_protocol_parameters (
1079
+ ) {
1080
+ // Create an adversarial certificate with a forged multi signature:
1081
+ // - with the valid signed message
1082
+ // - with the valid aggregate verification key (valid stake distribution)
1083
+ // - by a legit adversarial registered signer in the signing stake distribution
1084
+ // - with adversarial protocol parameters (phi_f = 1.0, i.e. all lotteries are won by the adversarial signer and quorum is reached)
1085
+ fn forge_certificate (
1086
+ certificate : Certificate ,
1087
+ context : & CertificateChainBuilderContext ,
1088
+ ) -> Certificate {
1089
+ assert_ne ! (
1090
+ 1.0 , certificate. metadata. protocol_parameters. phi_f,
1091
+ "Adversarial protocol parameters phi_f should be different from 1.0"
1092
+ ) ;
1093
+ let fixture = context. fixture ;
1094
+ let signed_message = certificate. signed_message . to_owned ( ) ;
1095
+ let mut forged_certificate = certificate;
1096
+ let mut forged_protocol_parameters = fixture. protocol_parameters ( ) ;
1097
+ forged_protocol_parameters. phi_f = 1.0 ;
1098
+ let forged_single_signatures = fixture
1099
+ . signers_fixture ( )
1100
+ . iter ( )
1101
+ . take ( 1 )
1102
+ . filter_map ( |s| {
1103
+ let s_adversary = s
1104
+ . to_owned ( )
1105
+ . try_new_with_protocol_parameters ( forged_protocol_parameters. clone ( ) )
1106
+ . unwrap ( ) ;
1107
+ let signature = s_adversary. protocol_signer . sign ( signed_message. as_bytes ( ) ) ;
1108
+
1109
+ signature
1110
+ } )
1111
+ . collect :: < Vec < _ > > ( ) ;
1112
+ let forged_clerk = ProtocolClerk :: from_registration (
1113
+ & forged_protocol_parameters. clone ( ) . into ( ) ,
1114
+ & fixture. signers_fixture ( ) [ 0 ] . protocol_closed_key_registration ,
1115
+ ) ;
1116
+ let forged_multi_signature = forged_clerk
1117
+ . aggregate ( & forged_single_signatures, signed_message. as_bytes ( ) )
1118
+ . unwrap ( ) ;
1119
+ forged_certificate. signature = CertificateSignature :: MultiSignature (
1120
+ forged_certificate. signed_entity_type ( ) ,
1121
+ forged_multi_signature. into ( ) ,
1122
+ ) ;
1123
+ forged_certificate. metadata . protocol_parameters = forged_protocol_parameters;
1124
+
1125
+ forged_certificate
1126
+ }
1127
+
1128
+ let ( total_certificates, certificates_per_epoch) = ( 7 , 2 ) ;
1129
+ let ( fake_certificates, genesis_verifier) = CertificateChainBuilder :: new ( )
1130
+ . with_total_certificates ( total_certificates)
1131
+ . with_certificates_per_epoch ( certificates_per_epoch)
1132
+ . with_standard_certificate_processor ( & |certificate, context| {
1133
+ if context. is_last_certificate ( ) {
1134
+ forge_certificate ( certificate, context)
1135
+ } else {
1136
+ certificate
1137
+ }
1138
+ } )
1139
+ . build ( ) ;
1140
+ let certificate_to_verify = fake_certificates[ 0 ] . clone ( ) ;
1141
+ let mock_container = MockDependencyInjector :: new ( ) ;
1142
+ let mut verifier = mock_container. build_certificate_verifier ( ) ;
1143
+ verifier. certificate_retriever = Arc :: new ( FakeCertificaterRetriever :: from_certificates (
1144
+ & fake_certificates,
1145
+ ) ) ;
1146
+
1147
+ let error = verifier
1148
+ . verify_certificate (
1149
+ & certificate_to_verify,
1150
+ & genesis_verifier. to_verification_key ( ) ,
1151
+ )
1152
+ . await
1153
+ . expect_err ( "verify_certificate_chain should fail" ) ;
1154
+
1155
+ assert_error_matches ! (
1156
+ CertificateVerifierError :: CertificateChainProtocolParametersUnmatch ,
1157
+ error
1158
+ )
1159
+ }
1076
1160
}
0 commit comments