Browse Source
- 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.pull/127/head
7 changed files with 227 additions and 15 deletions
@ -0,0 +1,6 @@ |
|||
# Admin DID credentials |
|||
ADMIN_DID=did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F |
|||
ADMIN_PRIVATE_KEY=2b6472c026ec2aa2c4235c994a63868fc9212d18b58f6cbfe861b52e71330f5b |
|||
|
|||
# API Configuration |
|||
ENDORSER_API_URL=https://test-api.endorser.ch/api/v2/claim |
@ -0,0 +1,189 @@ |
|||
#!/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 $? |
Loading…
Reference in new issue