From 751c5ce076de9b83660fd14913bd58b7c6c84e65 Mon Sep 17 00:00:00 2001 From: Elena Bardho Date: Wed, 8 Oct 2025 16:25:00 +0100 Subject: [PATCH 1/6] Update author-validate to be generic --- scripts/author-validate.sh | 112 +++++++++++++++++++++++++++++++------ 1 file changed, 95 insertions(+), 17 deletions(-) diff --git a/scripts/author-validate.sh b/scripts/author-validate.sh index 1d3bd6c..4e90da5 100755 --- a/scripts/author-validate.sh +++ b/scripts/author-validate.sh @@ -22,27 +22,82 @@ fi # Usage message usage() { - echo "Usage: $0 " + echo -e "${YELLOW}Usage: $0 [--public-key ]${NC}" + echo "" + echo -e "${CYAN}Verify metadata files with author witness using cardano-signer${NC}" + echo -e "Options:" + echo -e "${CYAN}If [public-key] is not provided, Intersect's public key will be used by default.${NC}" exit 1 } -# Check correct number of arguments -if [ "$#" -lt 1 ]; then +is_default_value_value=false + +# Parse command line arguments +input_path="" +options_list="" +public_key_file_path="" + +while [[ $# -gt 0 ]]; do + case $1 in + --public-key) + public_key_file_path="$2" + options_list+=" --public-key" + shift 2 + ;; + -h|--help) + usage + ;; + *) + if [ -z "$input_path" ]; then + input_path="$1" + shift + else + echo -e "${RED}Error: Unknown argument: $1${NC}" >&2 + usage + fi + ;; + esac +done + +# Check correct number of arguments using original argument count +if [ -z "$input_path" ]; then + echo -e "${RED}Error: Not enough arguments provided.${NC}" >&2 usage +elif [ -z "$public_key_file_path" ]; then + echo -e "${BLUE}You are checking with INTERSECT key ${NC}" >&2 + is_default_value=true +else + echo -e "${BLUE}You are checking with provided key ${NC}" >&2 fi -input_path="$1" - # Check if the key input file exists if [ ! -f "$input_path" ]; then echo -e "${RED}Error: JSON file '${YELLOW}$input_path${RED}' not found!${NC}" exit 1 fi +if [ ! -f "$public_key_file_path" ] && [[ $options_list == *"--public-key"* ]]; then + echo -e "${RED}Error: Public key file '${YELLOW}$public_key_file_path${RED}' not found!${NC}" + exit 1 +fi + +author_key="" + # Get Intersect author public key -echo -e "${CYAN}Fetching Intersect author public key from ${YELLOW}$INTERSECT_AUTHOR_PATH${NC}" -intersect_author_key=$(curl -s "$INTERSECT_AUTHOR_PATH" | jq -r '.publicKey') -echo -e " " +if [ ! -f "$public_key_file_path" ]; then + echo -e "${CYAN}Fetching Intersect author public key from ${YELLOW}$INTERSECT_AUTHOR_PATH${NC}" + author_key=$(curl -s "$INTERSECT_AUTHOR_PATH" | jq -r '.publicKey' | cut -c5-) + echo -e "Intersect author public key: ${YELLOW}$author_key${NC}" + echo -e " " +else + if [ -f "$public_key_file_path" ]; then + # If it's a file, read the public key from the file + author_key=$(cat "$public_key_file_path" | jq -r '.cborHex' | cut -c5-) + else + # Otherwise, treat the input as the public key string itself + author_key="$public_key_file_path" + fi +fi # Use cardano-signer to verify author witnesses # https://github.com/gitmachtl/cardano-signer?tab=readme-ov-file#verify-governance-metadata-and-the-authors-signatures @@ -64,26 +119,42 @@ verify_author_witness() { } # Give the user a warning if the author isn't Intersect -check_if_intersect_author() { +check_if_correct_author() { local file="$1" author_count=$(jq '.authors | length' "$file") # Iterate over all author pubkeys present for i in $(seq 0 $(($author_count - 1))); do - author_key=$(jq -r ".authors[$i].witness.publicKey" "$file") + file_author_key=$(jq -r ".authors[$i].witness.publicKey" "$file") + echo " " + echo -e "${BLUE}Checking author public key against expected public key ->${NC}" - if [ "$author_key" == "$intersect_author_key" ]; then - echo -e "${GREEN}Author public key matches Intersect's known public key.${NC}" + if [ "$file_author_key" == "$author_key" ]; then + if [ $default ]; then + echo -e "${GREEN}Author public key matches Intersect's known public key.${NC}" + else + echo -e "${GREEN}Author public key matches provided public key.${NC}" + fi else echo -e " " - echo -e "${RED}Warning: Author public key does NOT match Intersect's known public key.${NC}" - echo -e "Author public key: ${YELLOW}$author_key${NC}" - echo -e "Intersect's known public key: ${YELLOW}$intersect_author_key${NC}" + if [ "$is_default_value" = true ]; then + echo -e "${RED}Warning: Author public key does NOT match Intersect's known public key.${NC}" + else + echo -e "${RED}Warning: Author public key does NOT match the provided key.${NC}" + fi + echo -e "Author public key: ${YELLOW}$file_author_key${NC}" + echo -e "Expected public key: ${YELLOW}$author_key${NC}" fi echo -e " " done } +show_author_info() { + local file="$1" + author_details=$(jq -r '.authors[] | "Author Name: \(.name)\nPublic Key: \(.witness.publicKey)\nSignature: \(.witness.signature)\n"' "$file") + echo -e "$author_details" +} + if [ -d "$input_path" ]; then # If input is a directory: verify all .jsonld files shopt -s nullglob @@ -95,13 +166,20 @@ if [ -d "$input_path" ]; then fi # for each .jsonld file in the directory, go over it for file in "${jsonld_files[@]}"; do + echo -e "${BLUE} Verifying provided signature on file is valid:${NC}" verify_author_witness "$file" - check_if_intersect_author "$file" + if [ $is_default_value ]; then + check_if_correct_author "$file" + else + show_author_info "$file" + fi done elif [ -f "$input_path" ]; then # Input is a single file + echo -e "${BLUE}Verifyng provided signature on file is valid:${NC}" verify_author_witness "$input_path" - check_if_intersect_author "$input_path" + check_if_correct_author "$input_path" + else echo -e "${RED}Error: '${YELLOW}$input_path${RED}' is not a valid file or directory.${NC}" exit 1 From e233dd80306ce89bc299580b1f53104be6a59a11 Mon Sep 17 00:00:00 2001 From: Elena Bardho Date: Wed, 8 Oct 2025 16:30:55 +0100 Subject: [PATCH 2/6] Update author-validate --- scripts/author-validate.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/author-validate.sh b/scripts/author-validate.sh index 4e90da5..e955e0f 100755 --- a/scripts/author-validate.sh +++ b/scripts/author-validate.sh @@ -30,7 +30,7 @@ usage() { exit 1 } -is_default_value_value=false +is_default_value=false # Parse command line arguments input_path="" @@ -97,6 +97,8 @@ else # Otherwise, treat the input as the public key string itself author_key="$public_key_file_path" fi + echo -e "Provided author public key: ${YELLOW}$author_key${NC}" + echo -e " " fi # Use cardano-signer to verify author witnesses @@ -137,7 +139,7 @@ check_if_correct_author() { fi else echo -e " " - if [ "$is_default_value" = true ]; then + if [ $is_default_value ]; then echo -e "${RED}Warning: Author public key does NOT match Intersect's known public key.${NC}" else echo -e "${RED}Warning: Author public key does NOT match the provided key.${NC}" From 6c877db545198bd787d2d2f1a99609970cfa428c Mon Sep 17 00:00:00 2001 From: Elena Bardho Date: Wed, 8 Oct 2025 16:48:42 +0100 Subject: [PATCH 3/6] fix --- scripts/author-validate.sh | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/scripts/author-validate.sh b/scripts/author-validate.sh index e955e0f..0fe99eb 100755 --- a/scripts/author-validate.sh +++ b/scripts/author-validate.sh @@ -26,7 +26,7 @@ usage() { echo "" echo -e "${CYAN}Verify metadata files with author witness using cardano-signer${NC}" echo -e "Options:" - echo -e "${CYAN}If [public-key] is not provided, Intersect's public key will be used by default.${NC}" + echo -e " --public-key Specify the Cardano cli public key file path (default: ${YELLOW}Intersect's public key${NC})" exit 1 } @@ -86,7 +86,7 @@ author_key="" # Get Intersect author public key if [ ! -f "$public_key_file_path" ]; then echo -e "${CYAN}Fetching Intersect author public key from ${YELLOW}$INTERSECT_AUTHOR_PATH${NC}" - author_key=$(curl -s "$INTERSECT_AUTHOR_PATH" | jq -r '.publicKey' | cut -c5-) + author_key=$(curl -s "$INTERSECT_AUTHOR_PATH" | jq -r '.publicKey') echo -e "Intersect author public key: ${YELLOW}$author_key${NC}" echo -e " " else @@ -132,7 +132,7 @@ check_if_correct_author() { echo -e "${BLUE}Checking author public key against expected public key ->${NC}" if [ "$file_author_key" == "$author_key" ]; then - if [ $default ]; then + if [ $is_default_value ]; then echo -e "${GREEN}Author public key matches Intersect's known public key.${NC}" else echo -e "${GREEN}Author public key matches provided public key.${NC}" @@ -170,11 +170,7 @@ if [ -d "$input_path" ]; then for file in "${jsonld_files[@]}"; do echo -e "${BLUE} Verifying provided signature on file is valid:${NC}" verify_author_witness "$file" - if [ $is_default_value ]; then - check_if_correct_author "$file" - else - show_author_info "$file" - fi + check_if_correct_author "$file" done elif [ -f "$input_path" ]; then # Input is a single file From ab5926b2e2596500b8e6159fb656475aa1559c87 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Wed, 8 Oct 2025 17:08:59 +0100 Subject: [PATCH 4/6] tweaks on user messages --- scripts/author-validate.sh | 43 ++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/scripts/author-validate.sh b/scripts/author-validate.sh index 0fe99eb..3a0e790 100755 --- a/scripts/author-validate.sh +++ b/scripts/author-validate.sh @@ -59,17 +59,6 @@ while [[ $# -gt 0 ]]; do esac done -# Check correct number of arguments using original argument count -if [ -z "$input_path" ]; then - echo -e "${RED}Error: Not enough arguments provided.${NC}" >&2 - usage -elif [ -z "$public_key_file_path" ]; then - echo -e "${BLUE}You are checking with INTERSECT key ${NC}" >&2 - is_default_value=true -else - echo -e "${BLUE}You are checking with provided key ${NC}" >&2 -fi - # Check if the key input file exists if [ ! -f "$input_path" ]; then echo -e "${RED}Error: JSON file '${YELLOW}$input_path${RED}' not found!${NC}" @@ -83,12 +72,16 @@ fi author_key="" +echo -e " " +echo -e "${YELLOW}Validating the authors within given governance metadata${NC}" + # Get Intersect author public key if [ ! -f "$public_key_file_path" ]; then + echo -e " " + echo -e "${CYAN}No public key file provided, using Intersect's known public key${NC}" echo -e "${CYAN}Fetching Intersect author public key from ${YELLOW}$INTERSECT_AUTHOR_PATH${NC}" author_key=$(curl -s "$INTERSECT_AUTHOR_PATH" | jq -r '.publicKey') echo -e "Intersect author public key: ${YELLOW}$author_key${NC}" - echo -e " " else if [ -f "$public_key_file_path" ]; then # If it's a file, read the public key from the file @@ -105,13 +98,27 @@ fi # https://github.com/gitmachtl/cardano-signer?tab=readme-ov-file#verify-governance-metadata-and-the-authors-signatures verify_author_witness() { local file="$1" - local output - output=$(cardano-signer verify --cip100 \ + local raw_output + + raw_output=$(cardano-signer verify --cip100 \ --data-file "$file" \ - --json-extended | jq '{workMode, result, errorMsg, authors, canonizedHash, fileHash}') - - echo "$output" + --json-extended) + + # read exit code of last command + if [ $? -ne 0 ]; then + echo -e "${RED}Error: cardano-signer command failed while verifying file '${YELLOW}$file${RED}'.${NC}" >&2 + exit 1 + fi + local output + output=$(echo "$raw_output" | jq '{result, errorMsg, authors, canonizedHash, fileHash}') + + echo -e "${CYAN}Result: ${NC}$(echo "$output" | jq -r '.result')" + echo -e "${CYAN}Error Messages: ${NC}$(echo "$output" | jq -r '.errorMsg')" + echo -e "${CYAN}Authors: ${NC}$(echo "$output" | jq -r '.authors')" + echo -e "${CYAN}Canonized Hash: ${NC}$(echo "$output" | jq -r '.canonizedHash')" + echo -e "${CYAN}File Hash: ${NC}$(echo "$output" | jq -r '.fileHash')" + local result result=$(echo "$output" | jq -r '.result') if [ "$result" != "true" ]; then @@ -129,7 +136,7 @@ check_if_correct_author() { for i in $(seq 0 $(($author_count - 1))); do file_author_key=$(jq -r ".authors[$i].witness.publicKey" "$file") echo " " - echo -e "${BLUE}Checking author public key against expected public key ->${NC}" + echo -e "${BLUE}Checking author public key against expected public key${NC}" if [ "$file_author_key" == "$author_key" ]; then if [ $is_default_value ]; then From 480d7262165074657492eab7de247666e49f4ceb Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Wed, 8 Oct 2025 17:25:13 +0100 Subject: [PATCH 5/6] change to only check intersect key --- scripts/author-validate.sh | 73 +++++++++++++------------------------- 1 file changed, 24 insertions(+), 49 deletions(-) diff --git a/scripts/author-validate.sh b/scripts/author-validate.sh index 3a0e790..5a9f75e 100755 --- a/scripts/author-validate.sh +++ b/scripts/author-validate.sh @@ -3,8 +3,11 @@ ###################################################### # using permalink to reduce likelihood of breakage, or ability for it to change INTERSECT_AUTHOR_PATH="https://raw.githubusercontent.com/IntersectMBO/governance-actions/b1c5603fb306623e0261c234312eb7e011ac3d38/intersect-author.json" +CHECK_INTERSECT_AUTHOR="false" ###################################################### +set -euo pipefail + # Colors RED='\033[0;31m' GREEN='\033[0;32m' @@ -22,27 +25,23 @@ fi # Usage message usage() { - echo -e "${YELLOW}Usage: $0 [--public-key ]${NC}" + echo -e "${YELLOW}Usage: $0 [--check-intersect]${NC}" echo "" echo -e "${CYAN}Verify metadata files with author witness using cardano-signer${NC}" echo -e "Options:" - echo -e " --public-key Specify the Cardano cli public key file path (default: ${YELLOW}Intersect's public key${NC})" + echo -e " --check-intersect Compares author's to Intersect's known pub author key" exit 1 } -is_default_value=false - # Parse command line arguments input_path="" -options_list="" -public_key_file_path="" +check_intersect="$CHECK_INTERSECT_AUTHOR" while [[ $# -gt 0 ]]; do case $1 in - --public-key) - public_key_file_path="$2" - options_list+=" --public-key" - shift 2 + --check-intersect) + check_intersect="true" + shift ;; -h|--help) usage @@ -59,39 +58,25 @@ while [[ $# -gt 0 ]]; do esac done -# Check if the key input file exists +# Check if the metadata input file exists if [ ! -f "$input_path" ]; then echo -e "${RED}Error: JSON file '${YELLOW}$input_path${RED}' not found!${NC}" exit 1 fi -if [ ! -f "$public_key_file_path" ] && [[ $options_list == *"--public-key"* ]]; then - echo -e "${RED}Error: Public key file '${YELLOW}$public_key_file_path${RED}' not found!${NC}" - exit 1 -fi - -author_key="" - echo -e " " echo -e "${YELLOW}Validating the authors within given governance metadata${NC}" # Get Intersect author public key -if [ ! -f "$public_key_file_path" ]; then +if [ "$check_intersect" == "true" ]; then echo -e " " - echo -e "${CYAN}No public key file provided, using Intersect's known public key${NC}" + echo -e "${CYAN}Comparing author's public key to Intersect's known public key${NC}" echo -e "${CYAN}Fetching Intersect author public key from ${YELLOW}$INTERSECT_AUTHOR_PATH${NC}" author_key=$(curl -s "$INTERSECT_AUTHOR_PATH" | jq -r '.publicKey') echo -e "Intersect author public key: ${YELLOW}$author_key${NC}" else - if [ -f "$public_key_file_path" ]; then - # If it's a file, read the public key from the file - author_key=$(cat "$public_key_file_path" | jq -r '.cborHex' | cut -c5-) - else - # Otherwise, treat the input as the public key string itself - author_key="$public_key_file_path" - fi - echo -e "Provided author public key: ${YELLOW}$author_key${NC}" echo -e " " + echo -e "${CYAN}Not comparing author's against Intersect's known public key${NC}" fi # Use cardano-signer to verify author witnesses @@ -136,21 +121,13 @@ check_if_correct_author() { for i in $(seq 0 $(($author_count - 1))); do file_author_key=$(jq -r ".authors[$i].witness.publicKey" "$file") echo " " - echo -e "${BLUE}Checking author public key against expected public key${NC}" + echo -e "${CYAN}Checking author public key against expected public key${NC}" if [ "$file_author_key" == "$author_key" ]; then - if [ $is_default_value ]; then - echo -e "${GREEN}Author public key matches Intersect's known public key.${NC}" - else - echo -e "${GREEN}Author public key matches provided public key.${NC}" - fi + echo -e "${GREEN}Author public key matches Intersect's known public key.${NC}" else echo -e " " - if [ $is_default_value ]; then - echo -e "${RED}Warning: Author public key does NOT match Intersect's known public key.${NC}" - else - echo -e "${RED}Warning: Author public key does NOT match the provided key.${NC}" - fi + echo -e "${RED}Warning: Author public key does NOT match the Intersect key.${NC}" echo -e "Author public key: ${YELLOW}$file_author_key${NC}" echo -e "Expected public key: ${YELLOW}$author_key${NC}" fi @@ -158,12 +135,6 @@ check_if_correct_author() { done } -show_author_info() { - local file="$1" - author_details=$(jq -r '.authors[] | "Author Name: \(.name)\nPublic Key: \(.witness.publicKey)\nSignature: \(.witness.signature)\n"' "$file") - echo -e "$author_details" -} - if [ -d "$input_path" ]; then # If input is a directory: verify all .jsonld files shopt -s nullglob @@ -175,15 +146,19 @@ if [ -d "$input_path" ]; then fi # for each .jsonld file in the directory, go over it for file in "${jsonld_files[@]}"; do - echo -e "${BLUE} Verifying provided signature on file is valid:${NC}" + echo -e "${CYAN} Verifying provided signature on file is valid:${NC}" verify_author_witness "$file" - check_if_correct_author "$file" + if [ "$check_intersect" == "true" ]; then + check_if_correct_author "$file" + fi done elif [ -f "$input_path" ]; then # Input is a single file - echo -e "${BLUE}Verifyng provided signature on file is valid:${NC}" + echo -e "${CYAN}Verifying provided signature on file is valid:${NC}" verify_author_witness "$input_path" - check_if_correct_author "$input_path" + if [ "$check_intersect" == "true" ]; then + check_if_correct_author "$input_path" + fi else echo -e "${RED}Error: '${YELLOW}$input_path${RED}' is not a valid file or directory.${NC}" From 77a434fa5f835c6dc96e82bf6f42d2f025115ada Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Wed, 8 Oct 2025 17:40:14 +0100 Subject: [PATCH 6/6] redo logic around checking intersect pub keys --- scripts/author-validate.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/scripts/author-validate.sh b/scripts/author-validate.sh index 5a9f75e..0bacd3d 100755 --- a/scripts/author-validate.sh +++ b/scripts/author-validate.sh @@ -121,17 +121,24 @@ check_if_correct_author() { for i in $(seq 0 $(($author_count - 1))); do file_author_key=$(jq -r ".authors[$i].witness.publicKey" "$file") echo " " - echo -e "${CYAN}Checking author public key against expected public key${NC}" + echo -e "${CYAN}Checking author index $i public key against Intersect's keys${NC}" + # if author's public key matches Intersect's public key if [ "$file_author_key" == "$author_key" ]; then - echo -e "${GREEN}Author public key matches Intersect's known public key.${NC}" + # and if author name is intersect + if [ "$(jq -r ".authors[$i].name" "$file")" == "Intersect" ]; then + echo -e "${GREEN}Author pub key and name is correctly set to 'Intersect'.${NC}" + else + echo -e "${RED}Warning: Author name is NOT set to 'Intersect' but public key matches Intersect's key.${NC}" + echo -e "Author name: ${YELLOW}$(jq -r ".authors[$i].name" "$file")${NC}" + echo -e "Author public key: ${YELLOW}$file_author_key${NC}" + fi + else - echo -e " " - echo -e "${RED}Warning: Author public key does NOT match the Intersect key.${NC}" + echo -e "${RED}Warning: Author public key is not Intersect's key.${NC}" + echo -e "Author name: ${YELLOW}$(jq -r ".authors[$i].name" "$file")${NC}" echo -e "Author public key: ${YELLOW}$file_author_key${NC}" - echo -e "Expected public key: ${YELLOW}$author_key${NC}" fi - echo -e " " done }