Browse Source

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
pull/127/head
Matthew Raymer 1 week ago
parent
commit
bc971056e1
  1. 59
      test-scripts/check-did.sh
  2. 152
      test-scripts/generate-test-claim.sh
  3. 29
      test-scripts/run-deeplink-tests.sh

59
test-scripts/check-did.sh

@ -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

152
test-scripts/generate-test-claim.sh

@ -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")
# Output just the JWT for piping
echo "$jwt"
echo -e "\nGenerated JWT: ${jwt:0:50}..."
echo "$jwt" # Output just the JWT for piping
# Register the claim
register_claim "$jwt"

29
test-scripts/run-deeplink-tests.sh

@ -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"

Loading…
Cancel
Save