forked from trent_larson/crowd-funder-for-time-pwa
feat(scripts): Add DID visibility check script
Adds dids_seen.sh script to check DID visibility permissions in endorser.ch system. Key features: - JWT creation and signing using ES256K-R - DID visibility checking via API - Environment variable and .env file support - Debug logging with DEBUG=1 flag - Command line argument parsing for specific DID checks - Secure key handling with temporary files - Pretty-printed JSON output Security: - Uses secure temporary files with cleanup - Validates DER signature format - Handles key material securely - Supports environment variable configuration
This commit is contained in:
186
test-scripts/dids_seen.sh
Executable file
186
test-scripts/dids_seen.sh
Executable file
@@ -0,0 +1,186 @@
|
||||
#!/bin/bash
|
||||
# DID Visibility Check Script
|
||||
# @author Matthew Raymer
|
||||
#
|
||||
# This script checks visibility permissions for DIDs within the endorser.ch system.
|
||||
# It creates a signed JWT using admin credentials and queries the visibility API.
|
||||
#
|
||||
# Features:
|
||||
# - JWT creation and signing using ES256K-R
|
||||
# - DID visibility checking
|
||||
# - Environment variable support
|
||||
# - Debug logging
|
||||
# - Command line argument parsing
|
||||
#
|
||||
# Usage:
|
||||
# ./dids_seen.sh [-d did_to_check]
|
||||
# DEBUG=1 ./dids_seen.sh # For debug output
|
||||
#
|
||||
# Environment Variables:
|
||||
# ADMIN_DID - Admin DID for authorization
|
||||
# ADMIN_PRIVATE_KEY - Private key for signing
|
||||
# ENDORSER_API_URL - API endpoint (defaults to test)
|
||||
# DEBUG - Enable debug logging when set to 1
|
||||
|
||||
# Add debug logging function
|
||||
debug_log() {
|
||||
if [ "${DEBUG:-0}" = "1" ]; then
|
||||
echo "DEBUG: $*" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
# -d: Specific DID to check visibility for
|
||||
CHECK_DID=""
|
||||
while getopts "d:" opt; do
|
||||
case $opt in
|
||||
d) CHECK_DID="$OPTARG" ;;
|
||||
\?) echo "Usage: $0 [-d did_to_check]" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Load environment variables from .env file if present
|
||||
# Supports:
|
||||
# - ADMIN_DID
|
||||
# - ADMIN_PRIVATE_KEY
|
||||
# - ENDORSER_API_URL
|
||||
if [ -f .env ]; then
|
||||
export $(cat .env | grep -v '^#' | xargs)
|
||||
fi
|
||||
|
||||
# Default values for required parameters
|
||||
ADMIN_DID=${ADMIN_DID:-"did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F"}
|
||||
ADMIN_PRIVATE_KEY=${ADMIN_PRIVATE_KEY:-"2b6472c026ec2aa2c4235c994a63868fc9212d18b58f6cbfe861b52e71330f5b"}
|
||||
API_URL=${ENDORSER_API_URL:-"https://test-api.endorser.ch/api/report/whichDidsICanSee"}
|
||||
|
||||
# Create JWT payload with:
|
||||
# - Issuer (iss)
|
||||
# - Subject (sub)
|
||||
# - Issued At (iat)
|
||||
# - Expiration (exp)
|
||||
now=$(date +%s)
|
||||
exp=$((now + 86400)) # 24 hours from now
|
||||
|
||||
payload=$(jq -n \
|
||||
--arg iss "$ADMIN_DID" \
|
||||
--arg sub "$ADMIN_DID" \
|
||||
--arg iat "$now" \
|
||||
--arg exp "$exp" \
|
||||
'{
|
||||
iss: $iss,
|
||||
sub: $sub,
|
||||
iat: ($iat | tonumber),
|
||||
exp: ($exp | tonumber)
|
||||
}')
|
||||
|
||||
# Base64url encode header and payload
|
||||
# Header specifies ES256K-R algorithm for Ethereum compatibility
|
||||
header='{"alg":"ES256K-R","typ":"JWT"}'
|
||||
header_b64=$(echo -n "$header" | base64 -w 0 | tr '/+' '_-' | tr -d '=')
|
||||
payload_b64=$(echo -n "$payload" | base64 -w 0 | tr '/+' '_-' | tr -d '=')
|
||||
|
||||
# Create message to sign (header.payload)
|
||||
message="$header_b64.$payload_b64"
|
||||
|
||||
# Create temporary directory for key operations
|
||||
# Uses trap to ensure cleanup on exit
|
||||
TMPDIR=$(mktemp -d)
|
||||
trap 'rm -rf "$TMPDIR"' EXIT
|
||||
|
||||
# Create private key PEM file
|
||||
# Converts raw private key to PEM format for OpenSSL
|
||||
echo "-----BEGIN EC PRIVATE KEY-----" > "$TMPDIR/private.pem"
|
||||
(
|
||||
echo "302e0201010420" # Private key header
|
||||
echo -n "$ADMIN_PRIVATE_KEY" # Private key bytes
|
||||
echo "a00706052b8104000a" # secp256k1 OID
|
||||
) | xxd -r -p | base64 >> "$TMPDIR/private.pem"
|
||||
echo "-----END EC PRIVATE KEY-----" >> "$TMPDIR/private.pem"
|
||||
|
||||
# Write message to file for signing
|
||||
echo -n "$message" > "$TMPDIR/message.txt"
|
||||
|
||||
# Sign message and get DER format signature
|
||||
openssl dgst -sha256 -sign "$TMPDIR/private.pem" "$TMPDIR/message.txt" > "$TMPDIR/signature.der"
|
||||
|
||||
# Convert DER signature to hex
|
||||
der_sig=$(xxd -p -c 256 "$TMPDIR/signature.der")
|
||||
|
||||
# Parse DER structure
|
||||
# Extracts R and S values from signature
|
||||
if [[ $der_sig =~ ^30([0-9a-f]{2})02([0-9a-f]{2})([0-9a-f]*)02([0-9a-f]{2})([0-9a-f]*)$ ]]; then
|
||||
r_len="${BASH_REMATCH[2]}"
|
||||
r_val="${BASH_REMATCH[3]}"
|
||||
s_len="${BASH_REMATCH[4]}"
|
||||
s_val="${BASH_REMATCH[5]}"
|
||||
|
||||
# Convert lengths to decimal
|
||||
r_len_dec=$((16#$r_len))
|
||||
s_len_dec=$((16#$s_len))
|
||||
|
||||
# Handle R value padding
|
||||
if [ $r_len_dec -gt 32 ]; then
|
||||
r_val=${r_val: -64} # Take last 32 bytes
|
||||
elif [ $r_len_dec -lt 32 ]; then
|
||||
r_val=$(printf "%064s" "$r_val" | tr ' ' '0') # Left pad
|
||||
fi
|
||||
|
||||
# Handle S value padding
|
||||
if [ $s_len_dec -gt 32 ]; then
|
||||
s_val=${s_val: -64} # Take last 32 bytes
|
||||
elif [ $s_len_dec -lt 32 ]; then
|
||||
s_val=$(printf "%064s" "$s_val" | tr ' ' '0') # Left pad
|
||||
fi
|
||||
|
||||
# Create final signature
|
||||
concat_sig="${r_val}${s_val}"
|
||||
|
||||
# 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")
|
||||
|
||||
# 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
|
||||
else
|
||||
echo "❌ DID $CHECK_DID is not in the list"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Show full list of visible DIDs
|
||||
echo "$response" | jq '.' --indent 2
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Error: Could not find valid recovery bit"
|
||||
exit 1
|
||||
else
|
||||
echo "Error: Invalid DER signature format"
|
||||
echo "DER: $der_sig"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user