From 9edb3a255cbd725c52470d5c06b40f31666860fc Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 4 Mar 2025 13:30:10 +0000 Subject: [PATCH] feat: enhance DID visibility management - Add automatic visibility request when DID not found - Add rich documentation for script usage and features - Improve error handling and user feedback - Add visual indicators for success/failure - Add HTTPS for API endpoints - Add proper exit codes for different scenarios - Add detailed debug logging throughout - Add file header documentation This enhances the DID visibility script by adding automatic visibility requests when a DID is not found, along with better documentation, error handling and user feedback. --- test-scripts/dids_seen.sh | 168 ++++++++++++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 35 deletions(-) diff --git a/test-scripts/dids_seen.sh b/test-scripts/dids_seen.sh index 138e0e8..508d7e8 100755 --- a/test-scripts/dids_seen.sh +++ b/test-scripts/dids_seen.sh @@ -22,7 +22,7 @@ # ENDORSER_API_URL - API endpoint (defaults to test) # DEBUG - Enable debug logging when set to 1 -# Add debug logging function +# Enhanced debug logging debug_log() { if [ "${DEBUG:-0}" = "1" ]; then echo "DEBUG: $*" >&2 @@ -71,7 +71,7 @@ payload=$(jq -n \ sub: $sub, iat: ($iat | tonumber), exp: ($exp | tonumber) - }') + }') # Base64url encode header and payload # Header specifies ES256K-R algorithm for Ethereum compatibility @@ -82,6 +82,15 @@ payload_b64=$(echo -n "$payload" | base64 -w 0 | tr '/+' '_-' | tr -d '=') # Create message to sign (header.payload) message="$header_b64.$payload_b64" +# Add debug points +debug_log "Creating JWT with:" +debug_log "ADMIN_DID: $ADMIN_DID" +debug_log "API_URL: $API_URL" +debug_log "Payload: $payload" +debug_log "Header base64: $header_b64" +debug_log "Payload base64: $payload_b64" +debug_log "Message to sign: $message" + # Create temporary directory for key operations # Uses trap to ensure cleanup on exit TMPDIR=$(mktemp -d) @@ -114,6 +123,10 @@ if [[ $der_sig =~ ^30([0-9a-f]{2})02([0-9a-f]{2})([0-9a-f]*)02([0-9a-f]{2})([0-9 s_len="${BASH_REMATCH[4]}" s_val="${BASH_REMATCH[5]}" + debug_log "Raw signature values:" + debug_log " R (${#r_val} chars): $r_val" + debug_log " S (${#s_val} chars): $s_val" + # Convert lengths to decimal r_len_dec=$((16#$r_len)) s_len_dec=$((16#$s_len)) @@ -132,49 +145,134 @@ if [[ $der_sig =~ ^30([0-9a-f]{2})02([0-9a-f]{2})([0-9a-f]*)02([0-9a-f]{2})([0-9 s_val=$(printf "%064s" "$s_val" | tr ' ' '0') # Left pad fi + # Ensure both values are exactly 64 characters + r_val=$(printf "%064s" "$r_val" | tr ' ' '0') + s_val=$(printf "%064s" "$s_val" | tr ' ' '0') + + debug_log "Normalized values:" + debug_log " R (${#r_val} chars): $r_val" + debug_log " S (${#s_val} chars): $s_val" + # Create final signature concat_sig="${r_val}${s_val}" + # Debug the DER parsing + debug_log "DER Signature Analysis:" + debug_log " Full DER: $der_sig" + debug_log " Sequence length: ${BASH_REMATCH[1]}" + debug_log " R length: $r_len ($r_len_dec bytes)" + debug_log " S length: $s_len ($s_len_dec bytes)" + + # Debug signature components + debug_log "Signature components:" + debug_log " R value: $r_val (length: ${#r_val})" + debug_log " S value: $s_val (length: ${#s_val})" + debug_log " Concatenated: $concat_sig (length: ${#concat_sig})" + + # Try both normal and high-S value signatures + s_val_alt="" + if [ $s_len_dec -gt 32 ]; then + # Store alternative S value + s_val_alt="$s_val" + # Calculate N - s for high-S values + n="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" + # Use Python for hex math to avoid bc issues + normalized_s=$(python3 -c " + n = int('$n', 16) + s = int('${s_val}', 16) + result = hex(n - s)[2:].zfill(64) + print(result.lower()) + " 2>/dev/null || echo "ERROR") + if [ "$normalized_s" = "ERROR" ]; then + debug_log " Failed to normalize S value" + # Keep original s_val if normalization fails + s_val_alt="" + else + s_val=$(printf "%064s" "$normalized_s" | tr ' ' '0' | tr '[:upper:]' '[:lower:]') + debug_log " Normalized S value: $s_val" + fi + fi + # Calculate recovery bit (v) # Try each possible recovery value (0-3) until we find one that works for v in {0..3}; do - recovery_sig=$(printf "%s%02x" "$concat_sig" "$v") - debug_log "Trying recovery bit $v: $recovery_sig" - - # Convert to base64url - signature=$(echo -n "$recovery_sig" | xxd -r -p | base64 -w 0 | tr '/+' '_-' | tr -d '=') - - # Create JWT with this signature - JWT="$message.$signature" - - # Test the JWT against the API - response=$(curl -s -X GET "$API_URL" \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $JWT") + # Try both S values if we have an alternative + s_values=("$s_val") + if [ -n "$s_val_alt" ]; then + s_values+=("$s_val_alt") + fi - # Check if the JWT worked - if ! echo "$response" | grep -q "JWT_VERIFY_FAILED"; then - echo "JWT Token:" - echo "$JWT" - echo - echo "Export command:" - echo "export TOKEN='$JWT'" - echo - if [ -n "$CHECK_DID" ]; then - # Check if specific DID is in the list - if echo "$response" | jq -e --arg did "$CHECK_DID" 'contains([$did])' > /dev/null; then - echo "✅ DID $CHECK_DID is in the list" - exit 0 + for current_s in "${s_values[@]}"; do + concat_sig="${r_val}${current_s}" + debug_log "Trying with S value: $current_s" + + recovery_sig=$(printf "%s%02x" "$concat_sig" "$v") + debug_log "Recovery attempt $v:" + debug_log " Concatenated signature: $concat_sig" + debug_log " Recovery signature: $recovery_sig" + debug_log " Recovery signature length: ${#recovery_sig}" + + # Ensure signature is exactly 65 bytes (130 hex chars) + if [ ${#recovery_sig} -ne 130 ]; then + debug_log " Invalid signature length: ${#recovery_sig}, expected 130" + continue + fi + + # Convert hex to binary, then to base64url + signature=$(echo -n "$recovery_sig" | xxd -r -p 2>/dev/null | base64 -w 0 | tr '/+' '_-' | tr -d '=') + debug_log " Base64URL signature: $signature" + + # Create JWT with this signature + JWT="$message.$signature" + debug_log " Testing JWT: $JWT" + + # Test the JWT against the API + response=$(curl -s -X GET "$API_URL" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $JWT") + debug_log " API Response: $response" + + # Check if the JWT worked + if ! echo "$response" | grep -q "JWT.*failed"; then + echo "JWT Token:" + echo "$JWT" + debug_log "Success with v=$v and S=${current_s:0:8}..." + echo + echo "Export command:" + echo "export TOKEN='$JWT'" + echo + if [ -n "$CHECK_DID" ]; then + # Check if specific DID is in the list + if echo "$response" | jq -e --arg did "$CHECK_DID" 'contains([$did])' > /dev/null; then + echo "✅ DID $CHECK_DID is in the list" + exit 0 + else + echo "❌ DID $CHECK_DID is not in the list" + echo "Attempting to add visibility..." + + # Request visibility + visibility_response=$(curl -s -X POST \ + 'http://test-api.endorser.ch/api/report/canSeeMe' \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d "{\"did\": \"$CHECK_DID\"}") + + if echo "$visibility_response" | grep -q "error"; then + echo "❌ Failed to add visibility:" + echo "$visibility_response" | jq '.' --indent 2 + exit 1 + else + echo "✅ Successfully requested visibility. Please try checking again." + exit 0 + fi + fi else - echo "❌ DID $CHECK_DID is not in the list" - exit 1 + # Show full list of visible DIDs + echo "$response" | jq '.' --indent 2 fi - else - # Show full list of visible DIDs - echo "$response" | jq '.' --indent 2 + exit 0 fi - exit 0 - fi + done done echo "Error: Could not find valid recovery bit"