forked from trent_larson/crowd-funder-for-time-pwa
fix: Implement proper JWT signing in test claim generator
- Add ES256K signature generation for test claims - Fix signature format to match endorser.ch requirements - Remove dependency on did_generator.sh for signing - Improve JWT creation with proper header and payload structure The changes fix JWT verification issues by: 1. Implementing proper DER to R+S signature conversion 2. Handling secp256k1 private key formatting correctly 3. Using correct base64url encoding for JWT components 4. Adding proper issuer field to JWT payload
This commit is contained in:
117
test-scripts/generate-test-claim.sh
Executable file
117
test-scripts/generate-test-claim.sh
Executable file
@@ -0,0 +1,117 @@
|
||||
#!/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
|
||||
|
||||
# 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
|
||||
|
||||
# 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"
|
||||
|
||||
# Write message to file
|
||||
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 R+S format
|
||||
der_sig=$(xxd -p -c 256 "$tmpdir/signature.der")
|
||||
|
||||
# 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]}"
|
||||
|
||||
# Remove leading zeros
|
||||
r_val=${r_val#"00"}
|
||||
s_val=${s_val#"00"}
|
||||
|
||||
# Pad to 64 chars
|
||||
r_val=$(printf "%064s" "$r_val" | tr ' ' '0')
|
||||
s_val=$(printf "%064s" "$s_val" | tr ' ' '0')
|
||||
|
||||
# Take last 64 chars if longer
|
||||
r_val=${r_val:(-64)}
|
||||
s_val=${s_val:(-64)}
|
||||
|
||||
# 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
|
||||
}
|
||||
|
||||
# Create a test claim payload
|
||||
create_claim_payload() {
|
||||
local issuer_did="$1"
|
||||
local subject_did="$2"
|
||||
|
||||
# Create registration claim with issuer as agent
|
||||
cat << EOF
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "TestClaim",
|
||||
"agent": { "did": "$issuer_did" },
|
||||
"participant": { "did": "$subject_did" },
|
||||
"object": "test.endorser.ch"
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# Create and sign JWT
|
||||
create_jwt() {
|
||||
local claim="$1"
|
||||
local issuer_did="$2"
|
||||
local private_key="$3"
|
||||
|
||||
# Create header and payload
|
||||
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\"}"
|
||||
|
||||
# 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
|
||||
local signature=$(sign_message "$message" "$private_key")
|
||||
|
||||
# Return complete JWT
|
||||
echo "$message.$signature"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
echo "Generating test claim..."
|
||||
|
||||
# Create claim payload
|
||||
claim=$(create_claim_payload "$ISSUER_DID" "$CONTACT1_DID")
|
||||
echo "Claim payload:"
|
||||
echo "$claim" | jq '.'
|
||||
|
||||
# Create and sign JWT
|
||||
echo "Generating signed JWT..."
|
||||
jwt=$(create_jwt "$claim" "$ISSUER_DID" "$ISSUER_KEY")
|
||||
|
||||
echo -e "\nGenerated JWT: ${jwt:0:50}..."
|
||||
echo "$jwt" # Output just the JWT for piping
|
||||
Reference in New Issue
Block a user