You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

189 lines
5.9 KiB

#!/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 $?