forked from jsnbuchanan/crowd-funder-for-time-pwa
- 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
175 lines
4.8 KiB
Bash
Executable File
175 lines
4.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Source the environment with DIDs
|
|
if [ ! -f .generated/test-env.sh ]; then
|
|
echo "Error: No test environment found. Run run-deeplink-tests.sh first"
|
|
exit 1
|
|
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"
|
|
local private_key="$2"
|
|
local tmpdir
|
|
|
|
# Create temporary directory
|
|
tmpdir=$(mktemp -d)
|
|
trap 'rm -rf "$tmpdir"' EXIT
|
|
|
|
# Debug output
|
|
echo "Signing message: $message" >&2
|
|
echo "Using private key: $private_key" >&2
|
|
|
|
# Hash the message with SHA-256
|
|
echo -n "$message" | openssl dgst -sha256 -binary > "$tmpdir/message.hash"
|
|
|
|
# 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
|
|
|
|
# Read message hash
|
|
with open('$tmpdir/message.hash', 'rb') as f:
|
|
message_hash = f.read()
|
|
|
|
# Create private key object
|
|
private_key_bytes = bytes.fromhex('$private_key')
|
|
private_key = keys.PrivateKey(private_key_bytes)
|
|
|
|
# Sign the message hash
|
|
signature = private_key.sign_msg_hash(message_hash)
|
|
|
|
# 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"
|
|
|
|
# Read R and S values
|
|
{ read -r r_val; read -r s_val; } < "$tmpdir/signature.txt"
|
|
|
|
# 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"
|
|
|
|
# Create a test claim matching the app's structure
|
|
cat << EOF
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "TestClaim",
|
|
"identifier": "test-claim-$(date +%s)",
|
|
"name": "Test Claim",
|
|
"description": "Generated test claim",
|
|
"agent": {
|
|
"did": "$issuer_did"
|
|
}
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# Create and sign JWT
|
|
create_jwt() {
|
|
local claim="$1"
|
|
local issuer_did="$2"
|
|
local private_key="$3"
|
|
|
|
# Create header and payload matching the app's structure
|
|
local header='{"typ":"JWT","alg":"ES256K"}'
|
|
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 '=')
|
|
local payload_b64=$(echo -n "$payload" | base64 -w 0 | tr '/+' '_-' | tr -d '=')
|
|
|
|
# Create message to sign
|
|
local message="$header_b64.$payload_b64"
|
|
|
|
# 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 "$REGISTERED_DID")
|
|
echo "Claim payload:"
|
|
echo "$claim" | jq '.'
|
|
|
|
# Create and sign JWT
|
|
echo "Generating signed JWT..."
|
|
jwt=$(create_jwt "$claim" "$REGISTERED_DID" "$REGISTERED_KEY")
|
|
|
|
# Output just the JWT for piping
|
|
echo "$jwt"
|
|
|
|
# Register the claim
|
|
register_claim "$jwt" |