AtlatestRepositorysigil-crypto

sigil-crypto / tree / test / vectorsgen-ed25519-vectors.sh

1#!/bin/sh
2# Generate test/test-ed25519-vectors.sgl from test/vectors/ed25519-cases.txt.
3#
4# ed25519-cases.txt lines: "<label> <pk-hex> <sig-hex> <msg-hex|-> <expected>"
5# rfc8032-* RFC 8032 section 7.1 (Ed25519), expected valid
6# wycheproof-* C2SP/wycheproof testvectors_v1/ed25519_test.json
7# (commit 5722833ca004983abd1a91bcb6c24596d50ac0f9)
8# crafted-* crafted by the adversarial review: crafted-mixed-order-r is an
9# honest key (seed 00..1f) and R = rB + T8 (T8 of order 8), which
10# passes the cofactored equation and fails libsodium's cofactorless
11# one: the second shape of the documented divergence.
12# speccheck-* novifinancial/ed25519-speccheck cases.json
13# (commit 5e4bfc4542293286e9ad3cb2b805badee00503de), whose
14# expected column is "?": filled in below.
16# speccheck expectations are libsodium's (what the minisign tool uses):
17# reject 0-2 (small-order A or R), accept 3, reject 6-7 (S >= L) and 8-11
18# (non-canonical R or A). Cases 4 and 5 are the documented divergence:
19# they need a public key with a small-order component and pass the
20# cofactored equation (RFC 8032 section 5.1.7), which sigil-crypto checks,
21# but fail libsodium's cofactorless one. Measured by test/differential/run.sh.
22set -eu
23DIR=$(cd "$(dirname "$0")" && pwd)
24OUT="$DIR/../test-ed25519-vectors.sgl"
25awk '
26BEGIN {
27 spec["0"]="invalid"; spec["1"]="invalid"; spec["2"]="invalid"; spec["3"]="valid";
28 spec["4"]="valid"; spec["5"]="valid"; spec["6"]="invalid"; spec["7"]="invalid";
29 spec["8"]="invalid"; spec["9"]="invalid"; spec["10"]="invalid"; spec["11"]="invalid";
30 print ";;; GENERATED by test/vectors/gen-ed25519-vectors.sh from"
31 print ";;; test/vectors/ed25519-cases.txt. Do not edit by hand."
32 print ";;;"
33 print ";;; Every case runs through ed25519-verify. A valid case must return #t;"
34 print ";;; an invalid one must return #f, or raise when the key or signature has the"
35 print ";;; wrong length (the API raises on wrong lengths; nothing else may raise)."
36 print ""
37 print "(import (sigil test) (sigil crypto) (sigil math))"
38 print ""
39 print "(define (hex->bv s)"
40 print " (if (string=? s \"-\")"
41 print " (make-bytevector 0 0)"
42 print " (let* ((n (quotient (string-length s) 2))"
43 print " (bv (make-bytevector n 0)))"
44 print " (let loop ((i 0))"
45 print " (if (< i n)"
46 print " (begin"
47 print " (bytevector-u8-set! bv i (string->number (substring s (* 2 i) (+ 2 (* 2 i))) 16))"
48 print " (loop (+ i 1)))"
49 print " bv)))))"
50 print ""
51 print ";; #t, #f, or the symbol raised when the call raises."
52 print ";; Hex is decoded outside the guard: only ed25519-verify may raise."
53 print "(define (verdict pk sig msg)"
54 print " (let ((pk (hex->bv pk)) (sig (hex->bv sig)) (msg (hex->bv msg)))"
55 print " (guard (e (#t (quote raised)))"
56 print " (ed25519-verify pk msg sig))))"
57 print ""
58 print "(test-group \"ed25519 vectors\""
60NF != 5 { printf "REFUSING: line %d has %d fields, not 5: %s\n", NR, NF, $1 > "/dev/stderr"; bad = 1; exit 1 }
62 label=$1; pk=$2; sig=$3; msg=$4; want_result=$5
63 if (label ~ /^speccheck-/) { k=label; sub(/^speccheck-/, "", k); want_result=spec[k] }
64 if (want_result == "valid") want="(assert-eq #t (verdict \"" pk "\" \"" sig "\" \"" msg "\"))"
65 else if (length(pk) == 64 && length(sig) == 128) want="(assert-eq #f (verdict \"" pk "\" \"" sig "\" \"" msg "\"))"
66 else want="(assert-eq (quote raised) (verdict \"" pk "\" \"" sig "\" \"" msg "\"))"
67 printf " (test \"%s %s\"\n %s)\n", label, want_result, want
68 n++
70END { if (bad) exit 1; print " )"; print ""; printf ";;; %d cases\n", n }
71' "$DIR/ed25519-cases.txt" > "$OUT.tmp"
72mv "$OUT.tmp" "$OUT"
73echo "wrote $OUT"