#!/bin/bash # otp_roundtrip_test.sh — end-to-end test of otp_encrypt / otp_decrypt verbs. # # Sends framed JSON-RPC requests to nsigner --listen stdio and checks the # round-trip: plaintext -> otp_encrypt -> otp_decrypt -> recovered plaintext. # # Usage: ./tools/otp_roundtrip_test.sh set -euo pipefail NSIGNER="./build/nsigner" PAD_DIR="/media/user/Music/pads" PAD_SPEC="333e9902db839d9d" MNEMONIC_FILE=".test_mnemonic" if [ ! -x "$NSIGNER" ]; then echo "ERROR: $NSIGNER not found. Run 'make dev' first." exit 1 fi # Helper: send a framed JSON-RPC request to nsigner stdio and print the response. # Framing: 4-byte big-endian length prefix + JSON payload. send_request() { local json="$1" local len=${#json} # 4-byte big-endian length printf '\\x%02x\\x%02x\\x%02x\\x%02x' \ $(( (len >> 24) & 0xff )) $(( (len >> 16) & 0xff )) \ $(( (len >> 8) & 0xff )) $(( len & 0xff )) printf '%s' "$json" } # Build the plaintext base64. "Hello, OTP world!" -> base64 PLAINTEXT_B64=$(printf 'Hello, OTP world!' | base64) echo "Plaintext base64: $PLAINTEXT_B64" # Build the encrypt request ENCRYPT_REQ=$(cat </dev/null \ | tail -1 ) echo "Encrypt response: $RESPONSE" # Extract the ciphertext field (rough parse — look for "ciphertext":"...") CIPHERTEXT=$(echo "$RESPONSE" | sed -n 's/.*"ciphertext":"\([^"]*\)".*/\1/p') if [ -z "$CIPHERTEXT" ]; then echo "ERROR: no ciphertext in response" exit 1 fi echo "Ciphertext (first 80 chars): ${CIPHERTEXT:0:80}..." # Build the decrypt request — the ciphertext is the ASCII armor (with newlines # escaped as \n in JSON). We need to properly JSON-escape it. # Use python to do the JSON encoding safely. DECRYPT_REQ=$(python3 -c " import json, sys ct = sys.argv[1] print(json.dumps({'id':'2','method':'otp_decrypt','params':[ct,{'encoding':'ascii'}]})) " "$CIPHERTEXT") echo "=== Sending otp_decrypt ===" RESPONSE2=$( (printf '\\x00\\x00\\x00\\x%02x' ${#DECRYPT_REQ}; printf '%s' "$DECRYPT_REQ") | \ (exec 3<"$MNEMONIC_FILE"; "$NSIGNER" --listen stdio --mnemonic-fd 3 \ --otp-pad-dir "$PAD_DIR" --otp-pad "$PAD_SPEC" --otp-allow-blkback --allow-all) 2>/dev/null \ | tail -1 ) echo "Decrypt response: $RESPONSE2" # Extract and decode the recovered plaintext RECOVERED_B64=$(echo "$RESPONSE2" | sed -n 's/.*"plaintext":"\([^"]*\)".*/\1/p') if [ -z "$RECOVERED_B64" ]; then echo "ERROR: no plaintext in decrypt response" exit 1 fi RECOVERED=$(echo "$RECOVERED_B64" | base64 -d 2>/dev/null) echo "Recovered plaintext: $RECOVERED" if [ "$RECOVERED" = "Hello, OTP world!" ]; then echo "" echo "=== ROUND-TRIP SUCCESS ===" exit 0 else echo "" echo "=== ROUND-TRIP FAILED ===" echo "Expected: Hello, OTP world!" echo "Got: $RECOVERED" exit 1 fi