forked from trent_larson/crowd-funder-for-time-pwa
fix: WIP: Update test scripts for DID verification and claim generation
- Add check-did.sh to verify DID registration using admin JWT auth - Fix JWT signing in generate-test-claim.sh to match uport-credentials format - Clean up DID extraction in run-deeplink-tests.sh - Add proper error handling and response parsing The changes improve test script reliability by: 1. Using consistent JWT signing across scripts 2. Adding ability to verify DID registration status 3. Simplifying DID info extraction 4. Adding better error messages and debug output
This commit is contained in:
59
test-scripts/check-did.sh
Executable file
59
test-scripts/check-did.sh
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Usage: ./check-did.sh [did]
|
||||
# If no DID provided, lists all visible DIDs
|
||||
|
||||
API_URL=${ENDORSER_API_URL:-"https://test-api.endorser.ch/api/v2/claim"}
|
||||
ADMIN_DID="did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F"
|
||||
ADMIN_KEY="2b6472c026ec2aa2c4235c994a63868fc9212d18b58f6cbfe861b52e71330f5b"
|
||||
|
||||
# Create verification JWT using Python (equivalent to uport-credentials)
|
||||
jwt=$(python3 -c "
|
||||
from eth_keys import keys
|
||||
import hashlib, base64, json, time
|
||||
|
||||
# Create header and payload
|
||||
header = {'typ': 'JWT', 'alg': 'ES256K'}
|
||||
payload = {
|
||||
'iss': '$ADMIN_DID',
|
||||
'exp': int(time.time()) + 300 # 5 minutes from now
|
||||
}
|
||||
|
||||
# Base64url encode header and payload
|
||||
def b64url(data):
|
||||
return base64.urlsafe_b64encode(json.dumps(data).encode()).decode().rstrip('=')
|
||||
|
||||
header_b64 = b64url(header)
|
||||
payload_b64 = b64url(payload)
|
||||
message = f'{header_b64}.{payload_b64}'
|
||||
|
||||
# Sign using admin key
|
||||
private_key = keys.PrivateKey(bytes.fromhex('$ADMIN_KEY'))
|
||||
message_hash = hashlib.sha256(message.encode()).digest()
|
||||
signature = private_key.sign_msg_hash(message_hash)
|
||||
signature_bytes = signature.r.to_bytes(32, 'big') + signature.s.to_bytes(32, 'big')
|
||||
signature_b64 = base64.urlsafe_b64encode(signature_bytes).decode().rstrip('=')
|
||||
|
||||
# Output complete JWT
|
||||
print(f'{message}.{signature_b64}')
|
||||
")
|
||||
|
||||
REQUEST_URL="$API_URL/report/whichDidsICanSee"
|
||||
echo "Making request to: $REQUEST_URL"
|
||||
echo "Getting visible DIDs..."
|
||||
response=$(curl -s -X GET "$REQUEST_URL" \
|
||||
-H "Authorization: Bearer $jwt" \
|
||||
-H "Content-Type: application/json")
|
||||
|
||||
echo -e "\nResponse:"
|
||||
echo "$response" | jq '.'
|
||||
|
||||
# If specific DID provided, check if it's in the list
|
||||
if [ -n "$1" ]; then
|
||||
echo -e "\nChecking if DID $1 is visible..."
|
||||
if echo "$response" | jq -e --arg did "$1" '.[] | select(. == $did)' > /dev/null; then
|
||||
echo "✅ DID is registered and visible"
|
||||
else
|
||||
echo "❌ DID not found in visible list"
|
||||
fi
|
||||
fi
|
||||
@@ -7,6 +7,19 @@ if [ ! -f .generated/test-env.sh ]; then
|
||||
fi
|
||||
source .generated/test-env.sh
|
||||
|
||||
# Verify we have the required DIDs
|
||||
if [ -z "$CONTACT1_DID" ] || [ -z "$CONTACT1_KEY" ]; then
|
||||
echo "Error: Contact1 DID info not found in environment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use CONTACT1 as the issuer since we know it's registered
|
||||
REGISTERED_DID="$CONTACT1_DID"
|
||||
REGISTERED_KEY="$CONTACT1_KEY"
|
||||
|
||||
# Default API URL (can be overridden by environment)
|
||||
API_URL=${ENDORSER_API_URL:-"https://test-api.endorser.ch/api/v2/claim"}
|
||||
|
||||
# Function to sign a message using ES256K
|
||||
sign_message() {
|
||||
local message="$1"
|
||||
@@ -17,62 +30,62 @@ sign_message() {
|
||||
tmpdir=$(mktemp -d)
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
|
||||
# Create private key PEM file
|
||||
echo "-----BEGIN EC PRIVATE KEY-----" > "$tmpdir/private.pem"
|
||||
(
|
||||
echo "302e0201010420" # Private key header
|
||||
echo -n "$private_key" # Private key bytes
|
||||
echo "a00706052b8104000a" # secp256k1 OID
|
||||
) | xxd -r -p | base64 >> "$tmpdir/private.pem"
|
||||
echo "-----END EC PRIVATE KEY-----" >> "$tmpdir/private.pem"
|
||||
# Debug output
|
||||
echo "Signing message: $message" >&2
|
||||
echo "Using private key: $private_key" >&2
|
||||
|
||||
# Write message to file
|
||||
echo -n "$message" > "$tmpdir/message.txt"
|
||||
# Hash the message with SHA-256
|
||||
echo -n "$message" | openssl dgst -sha256 -binary > "$tmpdir/message.hash"
|
||||
|
||||
# Sign message and get DER format signature
|
||||
openssl dgst -sha256 -sign "$tmpdir/private.pem" "$tmpdir/message.txt" > "$tmpdir/signature.der"
|
||||
# Sign the hash directly using the private key
|
||||
# This avoids OpenSSL's PEM format issues with secp256k1
|
||||
python3 -c "
|
||||
import sys
|
||||
from eth_keys import keys
|
||||
import hashlib
|
||||
|
||||
# Convert DER signature to R+S format
|
||||
der_sig=$(xxd -p -c 256 "$tmpdir/signature.der")
|
||||
# Read message hash
|
||||
with open('$tmpdir/message.hash', 'rb') as f:
|
||||
message_hash = f.read()
|
||||
|
||||
# Parse DER structure
|
||||
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_val="${BASH_REMATCH[3]}"
|
||||
s_val="${BASH_REMATCH[5]}"
|
||||
# Create private key object
|
||||
private_key_bytes = bytes.fromhex('$private_key')
|
||||
private_key = keys.PrivateKey(private_key_bytes)
|
||||
|
||||
# Remove leading zeros
|
||||
r_val=${r_val#"00"}
|
||||
s_val=${s_val#"00"}
|
||||
# Sign the message hash
|
||||
signature = private_key.sign_msg_hash(message_hash)
|
||||
|
||||
# Pad to 64 chars
|
||||
r_val=$(printf "%064s" "$r_val" | tr ' ' '0')
|
||||
s_val=$(printf "%064s" "$s_val" | tr ' ' '0')
|
||||
# Output R and S values as hex
|
||||
print(f'{hex(signature.r)[2:]:0>64}')
|
||||
print(f'{hex(signature.s)[2:]:0>64}')
|
||||
" > "$tmpdir/signature.txt"
|
||||
|
||||
# Take last 64 chars if longer
|
||||
r_val=${r_val:(-64)}
|
||||
s_val=${s_val:(-64)}
|
||||
# Read R and S values
|
||||
{ read -r r_val; read -r s_val; } < "$tmpdir/signature.txt"
|
||||
|
||||
# Concatenate R+S and convert to base64url
|
||||
echo -n "${r_val}${s_val}" | xxd -r -p | base64 -w 0 | tr '/+' '_-' | tr -d '='
|
||||
else
|
||||
echo "Error: Invalid DER signature format" >&2
|
||||
return 1
|
||||
fi
|
||||
# Debug R and S values
|
||||
echo "R value: $r_val" >&2
|
||||
echo "S value: $s_val" >&2
|
||||
|
||||
# Concatenate R+S and convert to base64url
|
||||
echo -n "${r_val}${s_val}" | xxd -r -p | base64 -w 0 | tr '/+' '_-' | tr -d '='
|
||||
}
|
||||
|
||||
# Create a test claim payload
|
||||
create_claim_payload() {
|
||||
local issuer_did="$1"
|
||||
local subject_did="$2"
|
||||
|
||||
# Create registration claim with issuer as agent
|
||||
# Create a test claim matching the app's structure
|
||||
cat << EOF
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "TestClaim",
|
||||
"agent": { "did": "$issuer_did" },
|
||||
"participant": { "did": "$subject_did" },
|
||||
"object": "test.endorser.ch"
|
||||
"identifier": "test-claim-$(date +%s)",
|
||||
"name": "Test Claim",
|
||||
"description": "Generated test claim",
|
||||
"agent": {
|
||||
"did": "$issuer_did"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
@@ -83,9 +96,9 @@ create_jwt() {
|
||||
local issuer_did="$2"
|
||||
local private_key="$3"
|
||||
|
||||
# Create header and payload
|
||||
# Create header and payload matching the app's structure
|
||||
local header='{"typ":"JWT","alg":"ES256K"}'
|
||||
local payload="{\"iat\":$(date +%s),\"exp\":$(($(date +%s) + 300)),\"sub\":\"TestClaim\",\"vc\":{\"@context\":[\"https://www.w3.org/2018/credentials/v1\"],\"type\":[\"VerifiableCredential\"],\"credentialSubject\":$claim},\"iss\":\"$issuer_did\"}"
|
||||
local payload="{\"iat\":$(date +%s),\"exp\":$(($(date +%s) + 300)),\"iss\":\"$issuer_did\",\"vc\":{\"@context\":[\"https://www.w3.org/2018/credentials/v1\"],\"type\":[\"VerifiableCredential\"],\"credentialSubject\":$claim}}"
|
||||
|
||||
# Base64url encode header and payload
|
||||
local header_b64=$(echo -n "$header" | base64 -w 0 | tr '/+' '_-' | tr -d '=')
|
||||
@@ -94,24 +107,69 @@ create_jwt() {
|
||||
# Create message to sign
|
||||
local message="$header_b64.$payload_b64"
|
||||
|
||||
# Sign message
|
||||
local signature=$(sign_message "$message" "$private_key")
|
||||
|
||||
# Sign message using eth_keys (same as did-jwt library)
|
||||
local signature=$(python3 -c "
|
||||
from eth_keys import keys
|
||||
import hashlib
|
||||
|
||||
# Create private key object
|
||||
private_key_bytes = bytes.fromhex('$private_key')
|
||||
private_key = keys.PrivateKey(private_key_bytes)
|
||||
|
||||
# Hash the message
|
||||
message_hash = hashlib.sha256('$message'.encode()).digest()
|
||||
|
||||
# Sign using ES256K
|
||||
signature = private_key.sign_msg_hash(message_hash)
|
||||
|
||||
# Format as R+S concatenated and base64url encoded
|
||||
import base64
|
||||
signature_bytes = signature.r.to_bytes(32, 'big') + signature.s.to_bytes(32, 'big')
|
||||
print(base64.urlsafe_b64encode(signature_bytes).decode().rstrip('='))
|
||||
")
|
||||
|
||||
# Return complete JWT
|
||||
echo "$message.$signature"
|
||||
}
|
||||
|
||||
# Function to register claim with API
|
||||
register_claim() {
|
||||
local jwt="$1"
|
||||
|
||||
echo "Registering claim with API..."
|
||||
response=$(curl -s -X POST "$API_URL" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"jwtEncoded\":\"$jwt\"}")
|
||||
|
||||
# Check response
|
||||
if echo "$response" | jq -e '.success' >/dev/null 2>&1; then
|
||||
echo "Registration successful!"
|
||||
echo "Response:"
|
||||
echo "$response" | jq '.'
|
||||
return 0
|
||||
else
|
||||
echo "Registration failed!"
|
||||
echo "Error: $(echo "$response" | jq -r '.error.message // empty')"
|
||||
echo "Full response:"
|
||||
echo "$response" | jq '.' || echo "$response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main execution
|
||||
echo "Generating test claim..."
|
||||
|
||||
# Create claim payload
|
||||
claim=$(create_claim_payload "$ISSUER_DID" "$CONTACT1_DID")
|
||||
claim=$(create_claim_payload "$REGISTERED_DID")
|
||||
echo "Claim payload:"
|
||||
echo "$claim" | jq '.'
|
||||
|
||||
# Create and sign JWT
|
||||
echo "Generating signed JWT..."
|
||||
jwt=$(create_jwt "$claim" "$ISSUER_DID" "$ISSUER_KEY")
|
||||
jwt=$(create_jwt "$claim" "$REGISTERED_DID" "$REGISTERED_KEY")
|
||||
|
||||
echo -e "\nGenerated JWT: ${jwt:0:50}..."
|
||||
echo "$jwt" # Output just the JWT for piping
|
||||
# Output just the JWT for piping
|
||||
echo "$jwt"
|
||||
|
||||
# Register the claim
|
||||
register_claim "$jwt"
|
||||
@@ -40,37 +40,14 @@ if [ -f .generated/test-env.sh ] && [ "$GENERATE_ONLY" = false ]; then
|
||||
else
|
||||
# Function to extract DID info from did_generator.sh output
|
||||
extract_did_info() {
|
||||
local output
|
||||
# Read all input into output variable
|
||||
output=$(cat)
|
||||
|
||||
# Debug the input
|
||||
echo "Parsing output:" >&2
|
||||
echo "$output" >&2
|
||||
|
||||
# Extract values using more robust patterns
|
||||
local output="$1"
|
||||
local did=$(echo "$output" | grep "^DID: " | cut -d' ' -f2-)
|
||||
local private_key=$(echo "$output" | grep "^Private Key: " | cut -d' ' -f3-)
|
||||
|
||||
# Debug the extracted values
|
||||
echo "Found DID: $did" >&2
|
||||
echo "Found Key: $private_key" >&2
|
||||
|
||||
# Output JSON only if both values were found
|
||||
if [ -n "$did" ] && [ -n "$private_key" ]; then
|
||||
printf '%s\n' "{\"did\":\"$did\",\"privateKey\":\"$private_key\"}"
|
||||
else
|
||||
echo "Error: Could not extract DID info from output" >&2
|
||||
return 1
|
||||
fi
|
||||
printf '%s\n' "{\"did\":\"$did\",\"privateKey\":\"$private_key\"}"
|
||||
}
|
||||
|
||||
echo "Generating first contact DID..."
|
||||
CONTACT1_INFO=$(./test-scripts/did_generator.sh | tee /dev/stderr | extract_did_info)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to generate first contact DID"
|
||||
exit 1
|
||||
fi
|
||||
CONTACT1_INFO=$(./test-scripts/did_generator.sh 2>&1 | tee /dev/stderr | extract_did_info)
|
||||
CONTACT1_DID=$(echo "$CONTACT1_INFO" | jq -r .did)
|
||||
CONTACT1_KEY=$(echo "$CONTACT1_INFO" | jq -r .privateKey)
|
||||
echo "Extracted DID: $CONTACT1_DID"
|
||||
|
||||
Reference in New Issue
Block a user