#!/bin/bash # generate-proof.sh - Generate OpenTimestamp proof for a git commit # Usage: generate-proof.sh [output-file] set -e COMMIT_HASH="${1:-}" OUTPUT_FILE="${2:-.ots/proof.ots}" if [ -z "$COMMIT_HASH" ]; then echo "Error: commit hash required" >&2 echo "Usage: $0 [output-file]" >&2 exit 1 fi # Ensure .ots directory exists mkdir -p "$(dirname "$OUTPUT_FILE")" # Function to generate proof using ots CLI generate_with_ots_cli() { local hash="$1" local output="$2" # Create a temporary file with the hash (convert hex to binary) local temp_file=$(mktemp) local temp_ots="${temp_file}.ots" # Use python3 for hex to binary conversion (more portable than xxd) python3 -c "import sys; sys.stdout.buffer.write(bytes.fromhex('$hash'))" > "$temp_file" # Generate timestamp - ots creates .ots file alongside the original ots stamp "$temp_file" # Move the generated .ots file to the desired location if [ -f "$temp_ots" ]; then mkdir -p "$(dirname "$output")" mv "$temp_ots" "$output" echo "Generated proof with ots CLI: $output" else echo "Error: ots did not generate proof file" >&2 rm -f "$temp_file" exit 1 fi # Cleanup rm -f "$temp_file" } # Function to generate proof using opentimestamps-nodejs generate_with_node() { local hash="$1" local output="$2" # Use nodejs opentimestamps library # This requires @opentimestamps/ots to be installed globally node -e " const ots = require('@opentimestamps/ots'); const fs = require('fs'); const crypto = require('crypto'); const hash = '$hash'; const output = '$output'; // Convert hex hash to buffer const hashBuffer = Buffer.from(hash, 'hex'); // Create timestamp ots.Timestamp.hash(hashBuffer).then(timestamp => { // In a real implementation, this would contact the calendar server // For now, we create a minimal proof structure console.log('Warning: nodejs fallback creates local proof only'); console.log('Install ots CLI for full functionality: https://github.com/opentimestamps/opentimestamps-client'); // Create a simple proof file (this is a placeholder - real impl needs calendar) const proof = { hash: hash, timestamp: new Date().toISOString(), status: 'pending' }; fs.writeFileSync(output, JSON.stringify(proof, null, 2)); console.log('Generated local proof: ' + output); }).catch(err => { console.error('Error generating timestamp:', err); process.exit(1); }); " } # Check if ots CLI is available if command -v ots &> /dev/null; then echo "Using ots CLI..." generate_with_ots_cli "$COMMIT_HASH" "$OUTPUT_FILE" elif command -v node &> /dev/null && node -e "require('@opentimestamps/ots')" &> /dev/null; then echo "Using opentimestamps-nodejs fallback..." generate_with_node "$COMMIT_HASH" "$OUTPUT_FILE" else echo "Error: Neither ots CLI nor @opentimestamps/ots node package found" >&2 echo "Install one of:" >&2 echo " - ots CLI: https://github.com/opentimestamps/opentimestamps-client" >&2 echo " - Node package: npm install -g @opentimestamps/ots" >&2 exit 1 fi # Append previous commit hash to the proof file for chaining if [ -f "$OUTPUT_FILE" ]; then PREV_COMMIT=$(git rev-parse HEAD^1 2>/dev/null || echo "") if [ -n "$PREV_COMMIT" ]; then echo "" >> "$OUTPUT_FILE" echo "# Previous commit: $PREV_COMMIT" >> "$OUTPUT_FILE" fi fi echo "Proof generated for commit: $COMMIT_HASH"