Files
crowd-funder-from-jason/test-scripts/did_generator.sh
Matthew Raymer a4279fab34 feat: Add environment variable support for DID registration
- Bash implementation of DID creation-registration
- Move admin credentials to .env file for better security
- Add .env.example with default values
- Add dotenv support to TypeScript, Python and Bash implementations
- Update dependencies to include dotenv packages
- Fix JWT signature format in Bash implementation
- Add DER signature parsing for ES256K in Bash script

The admin DID and private key can now be configured via environment
variables, with fallback to default values if not set. This allows
for easier testing and deployment across different environments.
2025-03-04 06:27:20 +00:00

189 lines
5.9 KiB
Bash
Executable File

#!/bin/bash
# Check for required commands
for cmd in openssl xxd jq curl base64; do
if ! command -v $cmd &> /dev/null; then
echo "Error: $cmd is not installed. Please install it first."
echo "On Arch Linux: sudo pacman -S $cmd"
exit 1
fi
done
# Load environment variables
if [ -f .env ]; then
export $(cat .env | grep -v '^#' | xargs)
fi
# Default values
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/v2/claim"}
# Function to generate a new keypair
generate_keypair() {
echo "Generating new keypair..."
# Create a temporary directory for key operations
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
# Generate private key
openssl ecparam -name secp256k1 -genkey -noout > "$TMPDIR/private.pem"
# Extract raw private key
PRIVATE_KEY=$(openssl ec -in "$TMPDIR/private.pem" -text -noout 2>/dev/null | \
grep priv -A 3 | tail -n +2 | \
tr -d '\n[:space:]:' | \
sed 's/^00//')
# Generate public key (compressed format)
PUBLIC_KEY=$(openssl ec -in "$TMPDIR/private.pem" -pubout -outform DER 2>/dev/null | \
tail -c 65 | \
xxd -p -c 65 | \
sed 's/^04/02/')
# Generate Ethereum address
ADDRESS=$(echo -n "$PUBLIC_KEY" | \
xxd -r -p | \
openssl dgst -sha3-256 -binary | \
tail -c 20 | \
xxd -p)
# Create DID
DID="did:ethr:0x$ADDRESS"
echo "Generated DID Details:"
echo "----------------------"
echo "DID: $DID"
echo "Address: 0x$ADDRESS"
echo "Private Key: $PRIVATE_KEY"
echo "Public Key: $PUBLIC_KEY"
# Export variables for other functions
export DID PRIVATE_KEY PUBLIC_KEY ADDRESS
return 0
}
# Function to hex_to_dec
hex_to_dec() {
printf "%d" "0x$1"
}
# Function to create and sign JWT
create_jwt() {
local now=$(date +%s)
local exp=$((now + 300))
# Create header (compact JSON)
local header='{"typ":"JWT","alg":"ES256K"}'
# Create registration claim (compact JSON)
local claim="{\"iat\":$now,\"exp\":$exp,\"sub\":\"RegisterAction\",\"vc\":{\"@context\":[\"https://www.w3.org/2018/credentials/v1\"],\"type\":[\"VerifiableCredential\"],\"credentialSubject\":{\"@context\":\"https://schema.org\",\"@type\":\"RegisterAction\",\"agent\":{\"did\":\"$ADMIN_DID\"},\"participant\":{\"did\":\"$DID\"},\"object\":\"endorser.ch\"}},\"iss\":\"$ADMIN_DID\"}"
# Base64url encode header and claim
header_b64=$(echo -n "$header" | base64 -w 0 | tr '/+' '_-' | tr -d '=')
claim_b64=$(echo -n "$claim" | base64 -w 0 | tr '/+' '_-' | tr -d '=')
# Create message to sign
message="$header_b64.$claim_b64"
# Create temporary directory for key operations
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 "$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
echo -n "$message" > "$TMPDIR/message.txt"
# Sign message and get DER format signature
openssl dgst -sha256 -sign "$TMPDIR/private.pem" "$TMPDIR/message.txt" 2>/dev/null > "$TMPDIR/signature.der"
# Convert DER signature to R+S format
der_sig=$(xxd -p -c 256 "$TMPDIR/signature.der")
# Debug the full DER signature
echo "Debug - Full DER signature:"
echo "$der_sig"
# Parse DER structure - more robust version
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
seq_len="${BASH_REMATCH[1]}"
r_len="${BASH_REMATCH[2]}"
r_val="${BASH_REMATCH[3]}"
s_len="${BASH_REMATCH[4]}"
s_val="${BASH_REMATCH[5]}"
echo "Debug - DER parsing:"
echo "Sequence length: $seq_len"
echo "R length: $r_len"
echo "R value: $r_val"
echo "S length: $s_len"
echo "S value: $s_val"
# Remove leading zeros if present
r_val=${r_val#"00"}
s_val=${s_val#"00"}
# Pad R and S to 32 bytes each
r_val=$(printf "%064s" "$r_val" | tr ' ' '0')
s_val=$(printf "%064s" "$s_val" | tr ' ' '0')
# Concatenate R+S and convert to base64url
signature=$(echo -n "${r_val}${s_val}" | xxd -r -p | base64 -w 0 | tr '/+' '_-' | tr -d '=')
else
echo "Error: Invalid DER signature format"
echo "DER: $der_sig"
return 1
fi
# Create final JWT
JWT="$message.$signature"
echo -e "\nCreated JWT: ${JWT:0:50}..."
export JWT
return 0
}
# Function to register DID
register_did() {
echo "Attempting registration..."
# Create request body
body="{\"jwtEncoded\":\"$JWT\"}"
# Send registration request
response=$(curl -s -X POST "$API_URL" \
-H "Content-Type: application/json" \
-d "$body")
# Check response
if echo "$response" | jq -e '.success' >/dev/null 2>&1; then
echo "Registration successful!"
echo "Response:"
echo "$response" | jq '.'
else
echo "Registration failed!"
echo "Error: $(echo "$response" | jq -r '.error.message // empty')"
echo "Full response:"
echo "$response" | jq '.' || echo "$response"
fi
}
# Main execution
echo "Starting DID Generation..."
echo "Using admin DID: $ADMIN_DID"
echo "API URL: $API_URL"
generate_keypair && \
create_jwt && \
register_did
exit $?