@@ -907,9 +907,60 @@ async fn sudo_challenge_handler(
907907 ) ;
908908 }
909909
910- // Note: We don't verify sudo signature here - the P2P network validates
911- // ChallengeUpdate messages. The validator that broadcasts will sign with
912- // its key, and other validators verify against SUDO_KEY when they receive it.
910+ // Verify the signature
911+ let signature_bytes = match hex:: decode ( & request. signature ) {
912+ Ok ( s) => s,
913+ Err ( _) => {
914+ return (
915+ StatusCode :: BAD_REQUEST ,
916+ Json ( serde_json:: json!( {
917+ "success" : false ,
918+ "message" : "Invalid signature format"
919+ } ) ) ,
920+ ) ;
921+ }
922+ } ;
923+
924+ // Check signature length
925+ if signature_bytes. len ( ) != 64 {
926+ return (
927+ StatusCode :: UNAUTHORIZED ,
928+ Json ( serde_json:: json!( {
929+ "success" : false ,
930+ "message" : "Invalid signature length"
931+ } ) ) ,
932+ ) ;
933+ }
934+
935+ // Verify signature is from sudo key
936+ let message = format ! (
937+ "sudo:{}:{}:{}" ,
938+ request. action, request. challenge_id, request. timestamp
939+ ) ;
940+
941+ let signature = match sp_core:: sr25519:: Signature :: try_from ( signature_bytes. as_slice ( ) ) {
942+ Ok ( sig) => sig,
943+ Err ( _) => {
944+ return (
945+ StatusCode :: UNAUTHORIZED ,
946+ Json ( serde_json:: json!( {
947+ "success" : false ,
948+ "message" : "Invalid signature format"
949+ } ) ) ,
950+ ) ;
951+ }
952+ } ;
953+
954+ let sudo_public = sp_core:: sr25519:: Public :: from_raw ( SUDO_KEY_BYTES ) ;
955+ if !sp_core:: sr25519:: Pair :: verify ( & signature, message. as_bytes ( ) , & sudo_public) {
956+ return (
957+ StatusCode :: UNAUTHORIZED ,
958+ Json ( serde_json:: json!( {
959+ "success" : false ,
960+ "message" : "Invalid signature - not from sudo key"
961+ } ) ) ,
962+ ) ;
963+ }
913964
914965 info ! (
915966 action = %request. action,
0 commit comments