Add Ed25519, BLAKE2b-512 and (sigil crypto minisign)
(sigil crypto) gains ed25519-verify, ed25519-public-key, ed25519-sign and blake2b-512 on Monocypher. The verify core (native/ed25519-verify.c) adds RFC 8032's y < p rule and libsodium's small-order rejection to Monocypher's cofactored check. (sigil crypto minisign) parses minisign public keys and .minisig files and verifies ED and Ed signatures and the trusted-comment global signature, as minisign -V does.
On wasm32-wasi only the Monocypher half is built: Mbed TLS is skipped and every Mbed TLS native is a stub raising "not available on wasm".
Tests: RFC 8032, Wycheproof and ed25519-speccheck vectors; negatives built from valid signatures; minisign fixtures made by minisign 0.12, production registry.json under the registry root key and minisign's own release tarball; a libsodium differential (test/differential); a host, static musl and wasm32-wasi differential (test/wasm).
Version 0.16.7.
README.md | 66 ++-
RELEASES.md | 18 +
native/crypto.c | 68 ++-
native/ed25519-verify.c | 72 +++
native/ed25519-verify.h | 26 ++
native/ed25519.c | 195 +++++++++
native/ed25519.h | 16 +
package.sgl | 63 ++-
src/sigil/crypto.sgl | 79 +++-
src/sigil/crypto/minisign.sgl | 380 ++++++++++++++++
test/differential/ed25519-vs-libsodium.c | 232 ++++++++++
test/differential/run.sh | 25 ++
test/fixtures/minisign/SHA256SUMS.fixtures | 16 +
test/fixtures/minisign/a.pub | 2 +
test/fixtures/minisign/b.pub | 2 +
test/fixtures/minisign/binary.bin | Bin 0 -> 1024 bytes
test/fixtures/minisign/binary.bin.ED.minisig | 4 +
test/fixtures/minisign/binary.bin.Ed.minisig | 4 +
test/fixtures/minisign/empty.txt | 0
test/fixtures/minisign/empty.txt.ED.minisig | 4 +
test/fixtures/minisign/hello.txt | 1 +
test/fixtures/minisign/hello.txt.ED.minisig | 4 +
test/fixtures/minisign/hello.txt.Ed.minisig | 4 +
test/fixtures/minisign/hello.txt.keyb.minisig | 4 +
test/fixtures/minisign/hello.txt.unicode.minisig | 4 +
test/fixtures/minisign/make-fixtures.sh | 69 +++
test/fixtures/minisign/minisign-0.12.tar.gz | Bin 0 -> 21808 bytes
test/fixtures/minisign/minisign-0.12.tar.gz.minisig | 4 +
test/fixtures/minisign/registry.json | 16 +
test/fixtures/minisign/registry.json.minisig | 4 +
test/test-ed25519-vectors.sgl | 366 ++++++++++++++++
test/test-ed25519.sgl | 156 +++++++
test/test-minisign.sgl | 303 +++++++++++++
test/vectors/ed25519-cases.txt | 168 +++++++
test/vectors/gen-ed25519-vectors.sh | 65 +++
test/vectors/speccheck-cases.json | 1 +
test/vectors/wycheproof-ed25519_test.json | 3360 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
test/wasm/.gitignore | 4 +
test/wasm/gen-fixtures.sh | 41 ++
test/wasm/package.sgl | 69 +++
test/wasm/run-wasm-test.mjs | 346 +++++++++++++++
test/wasm/src/crypto-probe/fixtures.sgl | 34 ++
test/wasm/src/crypto-probe/main.sgl | 88 ++++
43 files changed, 6355 insertions(+), 28 deletions(-)README.mdmodified
Cryptographic primitives for [Sigil](https://codeberg.org/sigil/sigil).Hashing, message authentication, key derivation, base64 encoding, andHashing, message authentication, key derivation, Ed25519 signatures,minisign verification, base64 encoding, andcryptographically secure random bytes. Built on a vendored mbedTLS andusable independently of TLS.## Modules| Module | Purpose ||-----------------|-----------------------------------------------|| `(sigil crypto)`| SHA/HMAC/PBKDF2 hashes, base64, random bytes || Module | Purpose ||--------------------------|----------------------------------------------------------|| `(sigil crypto)` | SHA/HMAC/PBKDF2 hashes, Ed25519, BLAKE2b, base64, random || `(sigil crypto minisign)`| Parse and verify minisign public keys and signatures |## API summary| `base64-decode` | Base64 decoding to a string || `random-bytes` | Cryptographically secure random bytevector || `timing-safe-equal?` | Constant-time string comparison || `ed25519-verify` | Verify an Ed25519 (RFC 8032) signature || `ed25519-public-key` | Ed25519 public key from a 32-byte seed || `ed25519-sign` | Ed25519 signature with a 32-byte seed || `blake2b-512` | BLAKE2b digest (64 bytes) as a bytevector || `minisign-verify` | Verify a minisign signature; returns the trusted comment or #f || `minisign-verify-prehashed` | As `minisign-verify`, refusing legacy signatures (`minisign -V -H`) || `minisign-failure-reason` | #f when a signature verifies, else why it failed |## minisign without the minisign binary```scheme(import (sigil crypto minisign) (sigil fs))(define key (minisign-parse-public-key "RWRa9dPSUBFexBbLdzZIfuAmuCYL736UeHC7IbdAOIYpgGIyDmWRaQHY"))(define sig (minisign-parse-signature (read-file-bytes "registry.json.minisig")))(minisign-verify-prehashed key sig (read-file-bytes "registry.json")); => "registry=pkg.usesigil.org path=/v1/meta/registry.json seq=1 ts=..."; or #f when the file, signature or trusted comment has been altered```Checks the key id, the signature over the file (`ED`, prehashed withBLAKE2b-512, or legacy `Ed`) and the global signature over the trustedcomment, as `minisign -V` does. Verification is cofactored (RFC 8032section 5.1.7) and rejects small-order keys and R values; it agrees withlibsodium, which minisign uses, except for keys with a small-ordercomponent, which an honest minisign key never has.## WebAssemblyOn wasm32-wasi only the Monocypher half of the package is built:`ed25519-verify`, `ed25519-public-key`, `ed25519-sign`, `blake2b-512` and`(sigil crypto minisign)`. Every Mbed TLS-backed procedure raises"not available on wasm" there, because Mbed TLS does not build forwasm32-wasi yet. The browser build uses this same compiled Ed25519 ratherthan WebCrypto, so the API stays synchronous.## System prerequisitesPSK handshakes and early data remain disabled. The vendored version isMbed TLS 3.6.7; see `vendor/MBEDTLS.md` for upstream provenance.Ed25519 and BLAKE2b come from Monocypher 4.0.3, vendored unmodified under`vendor/monocypher/` (provenance and the reasons for choosing it in`vendor/MONOCYPHER.md`).## Dependencies- sigil-stdlibsigil test --report```Two further gates need tools the suite does not:```shtest/differential/run.sh # Ed25519 against libsodium (needs guix)node test/wasm/run-wasm-test.mjs # host, static musl and wasm32-wasi agree (needs guix, node)```The first build compiles ~108 mbedTLS translation units plus`native/crypto.c`. Subsequent builds hit the cache.`native/crypto.c`. Subsequent builds hit the cache. The minisignfixtures in `test/fixtures/minisign` are regenerated with`test/fixtures/minisign/make-fixtures.sh`.## UsageVendored mbedTLS (under `vendor/mbedtls/`) is distributed underApache-2.0 OR GPL-2.0-or-later. sigil-crypto's own sources areBSD-3-Clause. See `vendor/mbedtls/LICENSE` for the mbedTLS terms.Vendored Monocypher (under `vendor/monocypher/`) is dual-licensedBSD-2-Clause OR CC0-1.0; sigil-crypto uses it under BSD-2-Clause. See`vendor/monocypher/LICENCE.md`.RELEASES.mdadded
# sigil-crypto Releases## v0.16.7 — 2026-09-23Sigil can now check minisign signatures itself. `(sigil crypto)` gains Ed25519 (RFC 8032) and BLAKE2b-512, and the new `(sigil crypto minisign)` parses minisign public keys and `.minisig` files and verifies them the way `minisign -V` does, with no `minisign` binary on PATH. Both build for wasm32-wasi as well as native and static musl targets, so a browser build can verify a signed registry index with the same code as the CLI.## Changes- `ed25519-verify` checks an Ed25519 signature and returns `#t` or `#f`. It rejects non-canonical encodings, small-order keys and R values, and S values outside the group order, and checks the cofactored equation that RFC 8032 section 5.1.7 allows. It agrees with libsodium, which the minisign tool uses, on every RFC 8032, Wycheproof and ed25519-speccheck vector except speccheck cases 4 and 5, which need a public key with a small-order component and which an honest key never has.- `ed25519-public-key` and `ed25519-sign` derive a key and sign with a 32-byte seed; they come with the vendored implementation.- `blake2b-512` hashes a string or bytevector to 64 bytes.- `(sigil crypto minisign)`: `minisign-parse-public-key` (a `minisign.pub` file or the bare key line), `minisign-parse-signature`, and `minisign-verify` / `minisign-verify-prehashed`, which return the authenticated trusted comment or `#f`. `minisign-failure-reason` returns `#f` for a good signature and otherwise why it failed: `key-id-mismatch`, `legacy-refused`, `bad-signature` or `bad-trusted-comment-signature`. Both minisign formats verify: prehashed `ED` and legacy `Ed`.- Ed25519 and BLAKE2b come from Monocypher 4.0.3, vendored unmodified under `vendor/monocypher/` with its provenance in `vendor/MONOCYPHER.md`.- On wasm32-wasi only the Monocypher procedures and `(sigil crypto minisign)` are built. The Mbed TLS-backed procedures (hashes, HMAC, PBKDF2, ECDSA, ECDH, AES-GCM, base64, random bytes) raise "not available on wasm" there instead of being unbound. Before this release the package did not build for wasm32-wasi at all.## Upgrade notesNothing changes for existing callers on native targets.native/crypto.cmodified
* - Base64 encoding/decoding * - Cryptographically secure random number generation (CTR-DRBG) * * Note: Crypto is not available on Emscripten/WebAssembly builds. * Web applications should use the Web Crypto API via JavaScript interop. * Ed25519 and BLAKE2b-512 live in native/ed25519.c (vendored Monocypher) * and are registered into the same module on every target. * * On wasm (wasm32-wasi, and Emscripten) Mbed TLS is not built: it needs a * platform entropy source, sockets and a clock that the wasm build does not * provide yet (t-8c222f). There the module carries only the Monocypher * natives; every Mbed TLS-backed name is registered as a stub that raises * "not available on wasm" when called, so a program that uses one fails * with that message rather than an unbound variable. */#include <sigil/sigil.h>#ifdef __EMSCRIPTEN__/* * Stub implementation for Emscripten builds. * Crypto operations should use Web Crypto API in the browser. */#include "ed25519.h"#if defined(__EMSCRIPTEN__) || defined(__wasi__)/* Keep in step with the registrations in the native branch below. The wasm * harness (test/wasm/run-wasm-test.mjs) calls every (sigil crypto) export * that is not in its working set and fails if one is missing here. */static const char *const mbedtls_only_natives[] = { "sha1", "sha256", "sha256-bytes", "ripemd160", "hmac-sha256", "hmac-sha256-bytes", "hmac-sha512-bytes", "hmac-sha1", "pbkdf2-sha1", "pbkdf2-sha256", "pbkdf2-sha512", "base64-encode", "base64-decode", "random-bytes", "mpi-add", "mpi-sub", "mpi-mul", "mpi-div", "mpi-mod", "mpi-mod-add", "mpi-inv-mod", "mpi-cmp", "mpi-is-zero?", "mpi-shift-l", "mpi-shift-r", "ecdsa-p256-generate-keypair", "ecdsa-p256-sign", "ecdsa-p256-verify", "ecdh-p256-shared-secret", "aes-128-gcm-encrypt", "aes-128-gcm-decrypt", NULL};static Value native_unavailable_on_wasm(SigilVM *vm, int argc, Value *args){ (void)argc; (void)args; sigil__vm_error(vm, SIGIL_ERR_RUNTIME, "(sigil crypto): not available on wasm; this procedure " "needs Mbed TLS, which the wasm build does not include. " "On wasm only ed25519-verify, ed25519-public-key, " "ed25519-sign, blake2b-512 and (sigil crypto minisign) " "are available"); return SIGIL_UNDEFINED;}void sigil__init_sigil_crypto_module(SigilVM *vm){ (void)vm; /* Crypto module not available on web platform */ SigilModule *module = sigil_begin_module(vm, "(sigil crypto)"); if (!module) return; for (const char *const *name = mbedtls_only_natives; *name; name++) { sigil_module_register_native(vm, *name, native_unavailable_on_wasm, SIGIL_ARITY_VARIADIC, "Not available on wasm (needs Mbed TLS)"); sigil_module_export(vm, *name); } sigil_crypto_register_ed25519(vm); sigil_end_module(vm);}#else /* Native build */ SIGIL_ARITY_EXACT(5), "AES-128-GCM decrypt: returns plaintext or #f on auth fail"); /* Ed25519 and BLAKE2b-512 (Monocypher, native/ed25519.c) */ sigil_crypto_register_ed25519(vm); sigil_end_module(vm);}#undef REGISTER_AND_EXPORT#endif /* !__EMSCRIPTEN__ */#endif /* !(__EMSCRIPTEN__ || __wasi__) */native/ed25519-verify.cadded
/* * Ed25519 signature verification core for sigil-crypto. * * Pure C99 over the vendored Monocypher 4.0.3: no Sigil runtime, no * allocation, no platform calls. Kept apart from native/ed25519.c (the * Sigil natives) so it can be linked into a plain C harness and compared * against libsodium (test/differential/). */#include <string.h>#include "monocypher.h"#include "monocypher-ed25519.h"#include "ed25519-verify.h"/* * RFC 8032 section 5.1.3 step 1: the low 255 bits of an encoded point are * y, and "if the y-coordinate is >= p, decoding fails". p = 2^255 - 19, so * y >= p exactly when the encoding (sign bit masked) is one of * ed ff .. ff 7f, ee ff .. ff 7f, ..., ff ff .. ff 7f (little-endian). * Monocypher reduces y mod p instead, so this check is ours. */int sigil_crypto_ed25519_point_is_canonical(const unsigned char p[32]){ if ((p[31] & 0x7f) != 0x7f) return 1; for (int i = 30; i >= 1; i--) { if (p[i] != 0xff) return 1; } return p[0] < 0xed;}/* * True when the encoded point decodes and has order dividing 8. * * Uses Monocypher's public crypto_eddsa_check_equation, which returns 0 * exactly when the encodings decode and [8]([s]B - [h]A - R) is the * identity. With s = 0, h = 0 and A = the identity, that is [8](-R) = 0, * i.e. R has small order. No curve arithmetic is done here. * * RFC 8032 section 5.1.3 step 4 ("if x = 0 and x_0 = 1, decoding fails") * only concerns y = 1 and y = p - 1, the points of order 1 and 2; both are * rejected by this test, so step 4 needs no separate check. */int sigil_crypto_ed25519_has_small_order(const unsigned char p[32]){ static const unsigned char identity[32] = {1}; static const unsigned char zero[32] = {0}; unsigned char sig[64]; memcpy(sig, p, 32); memset(sig + 32, 0, 32); return crypto_eddsa_check_equation(sig, identity, zero) == 0;}int sigil_crypto_ed25519_verify(const unsigned char public_key[32], const unsigned char *message, size_t message_len, const unsigned char signature[64]){ /* Encodings first: A and R must be canonical and not of small order. * These are the checks libsodium's crypto_sign_verify_detached (which * minisign uses) makes before the equation. S < L is checked inside * crypto_ed25519_check. */ if (!sigil_crypto_ed25519_point_is_canonical(public_key) || !sigil_crypto_ed25519_point_is_canonical(signature)) return 0; if (sigil_crypto_ed25519_has_small_order(public_key) || sigil_crypto_ed25519_has_small_order(signature)) return 0; return crypto_ed25519_check(signature, public_key, message, message_len) == 0;}native/ed25519-verify.hadded
/* * Ed25519 verification core. See ed25519-verify.c. No Sigil dependency. */#ifndef SIGIL_CRYPTO_ED25519_VERIFY_H#define SIGIL_CRYPTO_ED25519_VERIFY_H#include <stddef.h>/* 1 when signature (R || S) is a valid RFC 8032 Ed25519 signature of * message under public_key, 0 otherwise. Non-canonical or small-order A * and R, and S >= L, are rejected. */int sigil_crypto_ed25519_verify(const unsigned char public_key[32], const unsigned char *message, size_t message_len, const unsigned char signature[64]);/* 1 when the 32-byte point encoding has y < p (RFC 8032 section 5.1.3 * step 1). Exposed for the differential harness's boundary tests. */int sigil_crypto_ed25519_point_is_canonical(const unsigned char p[32]);/* 1 when the encoding decodes to a point whose order divides 8. Exposed * for the differential harness, which checks it against the 8-torsion * points derived independently from the curve equation. */int sigil_crypto_ed25519_has_small_order(const unsigned char p[32]);#endifnative/ed25519.cadded
/* * Ed25519 (RFC 8032) and BLAKE2b-512 for (sigil crypto), backed by the * vendored Monocypher 4.0.3 (vendor/monocypher, see vendor/MONOCYPHER.md). * * This file has no platform dependencies: no allocation beyond the result * bytevector, no entropy, no clock. It is compiled on every target, * including wasm32-wasi, where the Mbed TLS half of the package is not. * * Natives registered into the (sigil crypto) module: * * ed25519-verify public-key message signature -> #t | #f * ed25519-public-key seed -> bytevector(32) * ed25519-sign seed message -> bytevector(64) * blake2b-512 data -> bytevector(64) * * GC discipline: every pointer into a Sigil string or bytevector is used * before the single allocation that builds the result, and never after it. */#include <sigil/sigil.h>#include <string.h>#include "monocypher.h"#include "monocypher-ed25519.h"#include "ed25519.h"#define ED25519_KEY_LEN 32#define ED25519_SIG_LEN 64#define BLAKE2B_512_LEN 64static int ed_read_bytes(SigilVM *vm, Value v, const char *what, const unsigned char **out_data, size_t *out_len){ if (sigil_is_string(v)) { SigilString *s = (SigilString *)sigil_as_ptr(v); *out_data = (const unsigned char *)s->data; *out_len = s->byte_length; return 1; } if (sigil_is_bytevector(v)) { SigilBytevector *bv = (SigilBytevector *)sigil_as_ptr(v); *out_data = bv->data; *out_len = bv->length; return 1; } (void)what; sigil__vm_error(vm, SIGIL_ERR_TYPE, "expected string or bytevector argument"); return 0;}static int ed_read_bv_exact(SigilVM *vm, Value v, size_t want, const char *type_msg, const char *length_msg, const unsigned char **out_data){ if (!sigil_is_bytevector(v)) { sigil__vm_error(vm, SIGIL_ERR_TYPE, type_msg); return 0; } SigilBytevector *bv = (SigilBytevector *)sigil_as_ptr(v); if (bv->length != want) { sigil__vm_error(vm, SIGIL_ERR_RUNTIME, length_msg); return 0; } *out_data = bv->data; return 1;}static Value ed_make_bytevector(SigilVM *vm, const unsigned char *data, size_t len){ Value result = sigil_make_bytevector(vm, len); if (sigil_is_bytevector(result)) { memcpy(sigil_bytevector_data(result), data, len); } return result;}/* * ed25519-verify public-key message signature -> #t | #f * * public-key: 32-byte bytevector. signature: 64-byte bytevector (R || S). * message: string (its UTF-8 bytes) or bytevector. Wrong types or lengths * raise; a well-formed signature that does not verify returns #f. */static Value native_ed25519_verify(SigilVM *vm, int argc, Value *args){ (void)argc; const unsigned char *pk, *msg, *sig; size_t msg_len; if (!ed_read_bv_exact(vm, args[0], ED25519_KEY_LEN, "ed25519-verify: public key must be a bytevector", "ed25519-verify: public key must be 32 bytes", &pk) || !ed_read_bytes(vm, args[1], "message", &msg, &msg_len) || !ed_read_bv_exact(vm, args[2], ED25519_SIG_LEN, "ed25519-verify: signature must be a bytevector", "ed25519-verify: signature must be 64 bytes", &sig)) { return SIGIL_UNDEFINED; } return sigil_crypto_ed25519_verify(pk, msg, msg_len, sig) ? SIGIL_TRUE : SIGIL_FALSE;}/* * ed25519-public-key seed -> bytevector(32) * * seed is the 32-byte RFC 8032 private key. Deterministic, no RNG. */static Value native_ed25519_public_key(SigilVM *vm, int argc, Value *args){ (void)argc; const unsigned char *seed_in; if (!ed_read_bv_exact(vm, args[0], ED25519_KEY_LEN, "ed25519-public-key: seed must be a bytevector", "ed25519-public-key: seed must be 32 bytes", &seed_in)) { return SIGIL_UNDEFINED; } /* crypto_ed25519_key_pair wipes the seed buffer it is given, so it * gets a copy, never the caller's bytevector. */ unsigned char seed[32], secret[64], pk[32]; memcpy(seed, seed_in, 32); crypto_ed25519_key_pair(secret, pk, seed); crypto_wipe(secret, sizeof secret); return ed_make_bytevector(vm, pk, sizeof pk);}/* * ed25519-sign seed message -> bytevector(64) * * Deterministic RFC 8032 signature with the 32-byte seed. Provided because * Monocypher implements it alongside verification; sigil-crypto's own use * is verification. */static Value native_ed25519_sign(SigilVM *vm, int argc, Value *args){ (void)argc; const unsigned char *seed_in, *msg; size_t msg_len; if (!ed_read_bv_exact(vm, args[0], ED25519_KEY_LEN, "ed25519-sign: seed must be a bytevector", "ed25519-sign: seed must be 32 bytes", &seed_in) || !ed_read_bytes(vm, args[1], "message", &msg, &msg_len)) { return SIGIL_UNDEFINED; } unsigned char seed[32], secret[64], pk[32], sig[64]; memcpy(seed, seed_in, 32); crypto_ed25519_key_pair(secret, pk, seed); crypto_ed25519_sign(sig, secret, msg, msg_len); crypto_wipe(secret, sizeof secret); /* msg is not touched after this allocation. */ return ed_make_bytevector(vm, sig, sizeof sig);}/* * blake2b-512 data -> bytevector(64) * * Unkeyed BLAKE2b with a 64-byte digest (RFC 7693), the hash minisign's * prehashed "ED" signatures sign. */static Value native_blake2b_512(SigilVM *vm, int argc, Value *args){ (void)argc; const unsigned char *data; size_t len; if (!ed_read_bytes(vm, args[0], "data", &data, &len)) { return SIGIL_UNDEFINED; } unsigned char hash[BLAKE2B_512_LEN]; crypto_blake2b(hash, sizeof hash, data, len); return ed_make_bytevector(vm, hash, sizeof hash);}void sigil_crypto_register_ed25519(SigilVM *vm){ sigil_module_register_native(vm, "ed25519-verify", native_ed25519_verify, SIGIL_ARITY_EXACT(3), "Verify an Ed25519 (RFC 8032) signature"); sigil_module_export(vm, "ed25519-verify"); sigil_module_register_native(vm, "ed25519-public-key", native_ed25519_public_key, SIGIL_ARITY_EXACT(1), "Ed25519 public key from a 32-byte seed"); sigil_module_export(vm, "ed25519-public-key"); sigil_module_register_native(vm, "ed25519-sign", native_ed25519_sign, SIGIL_ARITY_EXACT(2), "Ed25519 (RFC 8032) signature with a 32-byte seed"); sigil_module_export(vm, "ed25519-sign"); sigil_module_register_native(vm, "blake2b-512", native_blake2b_512, SIGIL_ARITY_EXACT(1), "BLAKE2b-512 digest (bytevector)"); sigil_module_export(vm, "blake2b-512");}native/ed25519.hadded
/* * Ed25519 and BLAKE2b-512 natives for (sigil crypto). See ed25519.c. */#ifndef SIGIL_CRYPTO_ED25519_H#define SIGIL_CRYPTO_ED25519_H#include <sigil/sigil.h>#include "ed25519-verify.h"/* Register ed25519-verify, ed25519-public-key, ed25519-sign and * blake2b-512 into the module currently being built. Call between * sigil_begin_module and sigil_end_module. */void sigil_crypto_register_ed25519(SigilVM *vm);#endifpackage.sglmodified
;;; - Base64 + base64url (RFC 4648 § 5) encoding/decoding;;; - Cryptographically secure random bytes;;;;;; and, using the vendored Monocypher (vendor/MONOCYPHER.md):;;; - Ed25519 (RFC 8032) verify, sign and public-key derivation;;; - BLAKE2b-512;;; - minisign public keys and signatures, (sigil crypto minisign);;;;;; This package vendors mbedTLS and can be used independently of TLS.;;;;;; On wasm targets only the Monocypher half is built: Mbed TLS needs an;;; entropy source, sockets and a clock that the wasm build does not provide;;; yet (t-8c222f), and the Mbed TLS-backed procedures raise "not available;;; on wasm" there.(package;; skip-on-wasm wraps a build step so it is a no-op on wasm/wasi targets.;; run-steps threads each step's return value as the ctx for the next step,;; so a skipped step must return ctx unchanged. Same shape as sigil-audio.(let ((skip-on-wasm (lambda (step) (lambda (ctx) (if (memq (target-os ctx) '(wasm wasi)) ctx (step ctx)))))) (package name: "sigil-crypto" version: "0.16.6" version: "0.16.7" sigil: "0.20" description: "Cryptographic functions for Sigil (SHA, HMAC, ECDSA, ECDH, AES-GCM, HKDF, base64, random)" description: "Cryptographic functions for Sigil (SHA, HMAC, ECDSA, ECDH, AES-GCM, HKDF, Ed25519, BLAKE2b, minisign, base64, random)" url: "https://codeberg.org/sigil/sigil-crypto" license: "BSD-3-Clause" authors: (list "David Wilson <david@daviwil.com>") (from-git url: "codeberg:sigil/sigil" package: "sigil-test" version: ">=0.21") (from-git url: "codeberg:sigil/sigil" package: "sigil-test-runner" version: ">=0.21")) ;; Native library definition ;; Native library definition. sigil-build reads c-sources as a "has native ;; code" test and for the include dirs; the build task below compiles the ;; real, target-dependent list. libraries: (list (library name: 'sigil-crypto c-sources: '("native/crypto.c" "native/ed25519.c" "native/ed25519-verify.c" "vendor/monocypher/src/monocypher.c" "vendor/monocypher/src/optional/monocypher-ed25519.c" "vendor/mbedtls/library/*.c") c-include-dirs: '("vendor/mbedtls/include" "vendor/mbedtls") "vendor/mbedtls" "vendor/monocypher/src" "vendor/monocypher/src/optional") c-flags: '("-DMBEDTLS_CONFIG_FILE=\"sigil_mbedtls_config.h\"") native-init: "sigil__init_sigil_crypto_module")) steps: (list ;; Compile mbedTLS library with our minimal config ;; Shared TLS 1.2/1.3 client configuration, including PSA prerequisites. (compile-c-sources ;; Not on wasm: three of its units #error there (t-8c222f). (skip-on-wasm (compile-c-sources sources: "vendor/mbedtls/library/*.c" include-dirs: '("vendor/mbedtls/include" "vendor/mbedtls") flags: '("-std=c99" "-Wall" "-Wno-unused-function" "-DMBEDTLS_CONFIG_FILE=\"sigil_mbedtls_config.h\"")) "-DMBEDTLS_CONFIG_FILE=\"sigil_mbedtls_config.h\""))) ;; Compile crypto.c ;; Compile vendored Monocypher (unmodified upstream 4.0.3) on every ;; target. Plain C99 with no platform calls. (compile-c-sources sources: '("vendor/monocypher/src/monocypher.c" "vendor/monocypher/src/optional/monocypher-ed25519.c") include-dirs: '("vendor/monocypher/src" "vendor/monocypher/src/optional") flags: '("-std=c99" "-Wall" "-Wextra")) ;; Compile crypto.c and ed25519.c ;; Flags go through with-sigil-c-flags so the build system injects ;; -I<sigil-lib>/include + -I<sigil-lib>/src. crypto.c's ;; #include <sigil/sigil.h> resolves via that auto-injection. (compile-c-sources sources: '("native/crypto.c") sources: '("native/crypto.c" "native/ed25519.c" "native/ed25519-verify.c") include-dirs: '("vendor/mbedtls/include" "vendor/mbedtls") "vendor/mbedtls" "vendor/monocypher/src" "vendor/monocypher/src/optional") flags: (with-sigil-c-flags '("-std=c99" "-Wall" "-Wextra" "-Wno-unused-parameter" ;; Compile Scheme module (compile-sigil-modules sources: "src/**/*.sgl"))))) sources: "src/**/*.sgl"))))))src/sigil/crypto.sglmodified
;;; (sigil crypto) - Cryptographic Functions;;;;;; Hashing, message authentication, key derivation, base64 encoding,;;; and cryptographically secure random bytes. Built on mbedTLS.;;; and cryptographically secure random bytes, built on Mbed TLS; and;;; Ed25519 (RFC 8032) and BLAKE2b-512, built on the vendored Monocypher.;;; minisign signatures are verified by (sigil crypto minisign).;;;;;; ```scheme;;; (import (sigil crypto));;; (base64-encode "hello") ; => "aGVsbG8=";;; (base64-decode "aGVsbG8=") ; => "hello";;; (random-bytes 16) ; => bytevector of 16 random bytes;;; (ed25519-verify pk msg sig) ; => #t or #f;;; (blake2b-512 "hello") ; => 64-byte bytevector;;; ```;;;;;; ## Targets;;;;;; Native builds (glibc and static musl) have everything. On wasm32-wasi;;; only the Monocypher procedures are built: `ed25519-verify`,;;; `ed25519-public-key`, `ed25519-sign` and `blake2b-512`, which is all;;; (sigil crypto minisign) needs. Mbed TLS needs an entropy source,;;; sockets and a clock that the wasm build does not provide yet, so every;;; Mbed TLS-backed procedure raises "not available on wasm" there instead;;; of being unbound. The Ed25519 API is synchronous on every target; the;;; browser build uses this compiled implementation, not WebCrypto.(define-library (sigil crypto) (export aes-128-gcm-decrypt hkdf-sha256-extract hkdf-sha256-expand hkdf-sha256) hkdf-sha256 ed25519-verify ed25519-public-key ed25519-sign blake2b-512) (import (sigil math)) -> (any-of bytevector? boolean?))) ;;; Verify an Ed25519 signature (RFC 8032, pure Ed25519). ;;; ;;; `public-key` is the 32-byte encoded public key, `signature` the ;;; 64-byte R || S, and `message` a string (its UTF-8 bytes) or a ;;; bytevector. Returns #t when the signature is valid and #f ;;; otherwise. A wrong argument type or length raises an error. ;;; ;;; Rejects non-canonical encodings of the key or of R, keys and R ;;; values of small order, and S >= L, as libsodium (and so minisign) ;;; does; checks the cofactored equation of RFC 8032 section 5.1.7. ;;; Cofactored verification is deliberate: RFC 8032 allows it and it ;;; agrees with batch verification. It accepts more than libsodium ;;; only when the key or R has a small-order component, which only the ;;; key holder can produce. ;;; Backed by the vendored Monocypher on every target, including wasm. ;;; The browser build deliberately uses this same compiled ;;; implementation rather than WebCrypto, to keep the API synchronous. ;;; ;;; ```scheme ;;; (ed25519-verify pk "message" sig) ; => #t or #f ;;; ``` (define-native (ed25519-verify public-key message signature) (: bytevector? (any-of string? bytevector?) bytevector? -> boolean?)) ;;; Derive the 32-byte Ed25519 public key from a 32-byte seed ;;; (the RFC 8032 private key). ;;; ;;; ```scheme ;;; (ed25519-public-key (random-bytes 32)) ; => 32-byte bytevector ;;; ``` (define-native (ed25519-public-key seed) (: bytevector? -> bytevector?)) ;;; Sign `message` (string or bytevector) with the 32-byte `seed`. ;;; Returns the deterministic 64-byte RFC 8032 signature. Provided ;;; because the vendored implementation includes it; this package's ;;; own use of Ed25519 is verification. ;;; ;;; ```scheme ;;; (ed25519-sign seed "message") ; => 64-byte bytevector ;;; ``` (define-native (ed25519-sign seed message) (: bytevector? (any-of string? bytevector?) -> bytevector?)) ;;; Compute the unkeyed BLAKE2b hash (RFC 7693) with a 64-byte digest. ;;; ;;; Accepts a string or bytevector. This is the hash minisign's ;;; prehashed signatures sign. Available on every target. ;;; ;;; ```scheme ;;; (bytevector-length (blake2b-512 "abc")) ; => 64 ;;; ``` (define-native (blake2b-512 data) (: (any-of string? bytevector?) -> bytevector?)) ;;; URL-safe base64 encoding (RFC 4648 § 5). ;;; ;;; Same alphabet as base64 but with `-` and `_` replacing `+`src/sigil/crypto/minisign.sgladded
;;; (sigil crypto minisign) - Verify minisign signatures natively;;;;;; Parses minisign public keys and `.minisig` signature files and verifies;;; them with (sigil crypto)'s Ed25519 and BLAKE2b-512, so no external;;; `minisign` binary is needed. Verification only; there is no signing.;;;;;; ```scheme;;; (import (sigil crypto minisign) (sigil fs));;;;;; (define key (minisign-parse-public-key;;; "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3"));;; (define sig (minisign-parse-signature;;; (read-file-bytes "SHA256SUMS.minisig")));;;;;; (minisign-verify key sig (read-file-bytes "SHA256SUMS"));;; ; => the trusted comment string when valid, #f otherwise;;; ```;;;;;; ## What is checked;;;;;; The same things `minisign -V` checks, in the same order:;;;;;; 1. The signature's key id equals the public key's key id.;;; 2. The signature over the file: `ED` (prehashed, minisign's default;;; since 0.10) is Ed25519 over BLAKE2b-512 of the file; `Ed` (legacy);;; is Ed25519 over the file itself. `minisign-verify-prehashed` refuses;;; `Ed`, like `minisign -V -H`.;;; 3. The global signature: Ed25519 over the 64 signature bytes followed;;; by the trusted comment's bytes. This is what makes the trusted;;; comment trusted.;;;;;; The trusted comment is only ever returned by a successful verification;;;; the parsed signature does not expose it, so an unverified comment;;; cannot be read by mistake.;;;;;; Ed25519 here accepts what RFC 8032 section 5.1.7 accepts (cofactored;;; equation, canonical encodings, S < L) and rejects small-order keys and;;; R values as libsodium does. Verification is cofactored, deliberately:;;; RFC 8032 allows it and it agrees with batch verification. It accepts;;; more than libsodium (which the minisign tool uses) only when the key or;;; R has a small-order component (ed25519-speccheck cases 4 and 5), which;;; only the key holder can produce and an honest minisign key never has.;;;;;; ## Parsing is strict;;;;;; Anything `minisign` would reject is rejected here, and a few things it;;; would tolerate are rejected too: base64 must be canonical (standard;;; alphabet, correct padding, zero pad bits), lines may end in LF or CRLF;;; but may not contain other CR or NUL bytes, and nothing but blank lines;;; may follow the fourth line of a signature file. Parse errors raise;;;; a well-formed signature that does not verify is not an error.;;;;;; ## Every target, including the browser;;;;;; This module and the natives under it build on native targets and on;;; wasm32-wasi. The browser build deliberately uses the same compiled;;; implementation rather than WebCrypto, to keep the API synchronous.;;; The consumer that makes this load-bearing is Slate running in the;;; browser and installing extension packages from the registry: there,;;; verifying the signed index is the security boundary, because a hash;;; check only proves the bytes match an index that an attacker could;;; have served too. Verification needs no entropy and no clock, so it;;; runs anywhere the module loads.(define-library (sigil crypto minisign) (export minisign-parse-public-key minisign-public-key? minisign-public-key-id minisign-public-key-bytes minisign-parse-signature minisign-signature? minisign-signature-algorithm minisign-signature-key-id minisign-failure-reason minisign-verify minisign-verify-prehashed) (import (sigil crypto) (sigil io) (sigil math) (sigil string) (sigil struct)) (begin ;; Parsed values. The constructors are not exported: a key or signature ;; can only come from the parsers below. (define-struct minisign-public-key (raw-key-id) ; 8-byte bytevector (raw-bytes)) ; 32-byte Ed25519 public key (define-struct minisign-signature (algorithm) ; 'prehashed ("ED") or 'legacy ("Ed") (raw-key-id) ; 8-byte bytevector (raw-bytes) ; 64-byte Ed25519 signature over the file (or its hash) (comment) ; trusted comment as a bytevector, NOT yet authenticated (global)) ; 64-byte Ed25519 signature over bytes || comment (define untrusted-prefix "untrusted comment: ") (define trusted-prefix "trusted comment: ") ;; minisign reads the trusted comment line with fgets into an 8192-byte ;; buffer (TRUSTEDCOMMENTMAXBYTES) and refuses a line that does not ;; fit with its newline and NUL: 8190 bytes including the prefix. (define max-trusted-line-bytes 8190) (define (fail what) (error (string-append "minisign: " what))) ;; --- bytes ----------------------------------------------------------- (define (->bytes x what) (cond ((bytevector? x) x) ((string? x) (string->utf8 x)) (else (fail (string-append what " must be a string or bytevector"))))) (define (bv-slice bv start end) (bytevector-copy bv start end)) (define (bv-equal? a b) (and (= (bytevector-length a) (bytevector-length b)) (let loop ((i 0)) (or (= i (bytevector-length a)) (and (= (bytevector-u8-ref a i) (bytevector-u8-ref b i)) (loop (+ i 1))))))) (define (bv-prefix? bv prefix-string) (let ((p (string->utf8 prefix-string))) (and (>= (bytevector-length bv) (bytevector-length p)) (bv-equal? (bv-slice bv 0 (bytevector-length p)) p)))) (define (bv-contains-byte? bv byte) (let loop ((i 0)) (and (< i (bytevector-length bv)) (or (= (bytevector-u8-ref bv i) byte) (loop (+ i 1)))))) ;; Split on LF. Each line loses one trailing CR. The piece after a ;; final LF is an empty line, which callers treat as blank. (define (split-lines bv) (let ((n (bytevector-length bv))) (let loop ((i 0) (start 0) (acc '())) (cond ((= i n) (reverse (cons (strip-cr (bv-slice bv start n)) acc))) ((= (bytevector-u8-ref bv i) 10) (loop (+ i 1) (+ i 1) (cons (strip-cr (bv-slice bv start i)) acc))) (else (loop (+ i 1) start acc)))))) (define (strip-cr line) (let ((n (bytevector-length line))) (if (and (> n 0) (= (bytevector-u8-ref line (- n 1)) 13)) (bv-slice line 0 (- n 1)) line))) (define (blank? line) (= (bytevector-length line) 0)) ;; list-tail is not bound in this Sigil's base library (measured); nth ;; is its list-ref twin, kept beside it. (define (nth lst k) (if (= k 0) (car lst) (nth (cdr lst) (- k 1)))) (define (drop lst k) (if (= k 0) lst (drop (cdr lst) (- k 1)))) ;; A line may not carry a CR (other than the stripped trailing one) ;; or a NUL: minisign's line handling truncates at both, so it would ;; not see the same bytes this parser sees. (define (check-line-bytes line what) (when (or (bv-contains-byte? line 13) (bv-contains-byte? line 0)) (fail (string-append what " contains a CR or NUL byte")))) ;; --- strict base64 --------------------------------------------------- (define (b64-value c) (cond ((and (>= c 65) (<= c 90)) (- c 65)) ; A-Z ((and (>= c 97) (<= c 122)) (+ 26 (- c 97))) ; a-z ((and (>= c 48) (<= c 57)) (+ 52 (- c 48))) ; 0-9 ((= c 43) 62) ; + ((= c 47) 63) ; / (else #f))) ;; Decode standard base64 that must be exactly `want` bytes long. ;; Refuses: a length that is not a multiple of 4, characters outside ;; the alphabet, padding anywhere but the end, the wrong amount of ;; padding for `want`, and non-zero pad bits. (define (base64-decode-exact line want what) (let* ((n (bytevector-length line)) (pad (cond ((and (>= n 2) (= (bytevector-u8-ref line (- n 1)) 61) (= (bytevector-u8-ref line (- n 2)) 61)) 2) ((and (>= n 1) (= (bytevector-u8-ref line (- n 1)) 61)) 1) (else 0))) (expected-pad (modulo (- 3 (modulo want 3)) 3)) (expected-len (* 4 (quotient (+ want 2) 3)))) (unless (and (= n expected-len) (= pad expected-pad)) (fail (string-append what " has the wrong base64 length"))) (let ((out (make-bytevector want 0)) (data-chars (- n pad))) (let loop ((i 0) (acc 0) (bits 0) (j 0)) (if (< i data-chars) (let ((v (b64-value (bytevector-u8-ref line i)))) (unless v (fail (string-append what " contains a character outside base64"))) (let ((acc (+ (* acc 64) v)) (bits (+ bits 6))) (if (>= bits 8) (let* ((shift (arithmetic-shift 1 (- bits 8))) (byte (quotient acc shift))) (bytevector-u8-set! out j byte) (loop (+ i 1) (- acc (* byte shift)) (- bits 8) (+ j 1))) (loop (+ i 1) acc bits j)))) (begin ;; Leftover bits are the pad bits; they must be zero. (unless (and (= j want) (= acc 0)) (fail (string-append what " has non-canonical base64 padding"))) out)))))) ;; --- public keys ----------------------------------------------------- ;;; Parse a minisign public key. ;;; ;;; `text` (string or bytevector) is either the contents of a ;;; `minisign.pub` file (an `untrusted comment:` line, then the key line) ;;; or the bare base64 key line, as given to `minisign -P`. Raises on ;;; anything else. (define (minisign-parse-public-key text) (let* ((lines (split-lines (->bytes text "public key"))) (content (filter-non-blank lines)) (key-line (cond ((and (= (length content) 2) (bv-prefix? (car content) "untrusted comment:")) (cadr content)) ((= (length content) 1) (car content)) (else (fail "public key must be one base64 line, optionally after an untrusted comment line"))))) (check-line-bytes key-line "public key") (let ((raw (base64-decode-exact key-line 42 "public key"))) (unless (and (= (bytevector-u8-ref raw 0) 69) ; E (= (bytevector-u8-ref raw 1) 100)) ; d (fail "public key algorithm is not Ed")) (minisign-public-key raw-key-id: (bv-slice raw 2 10) raw-bytes: (bv-slice raw 10 42))))) (define (filter-non-blank lines) (cond ((null? lines) '()) ((blank? (car lines)) (filter-non-blank (cdr lines))) (else (cons (car lines) (filter-non-blank (cdr lines)))))) ;;; The key id of a parsed public key, as a 16-digit upper-case hex ;;; string in the order `minisign` prints it. (define (minisign-public-key-id key) (key-id->hex (minisign-public-key-raw-key-id key))) ;; minisign prints the 8 key id bytes as a little-endian 64-bit number. (define (key-id->hex id) (let loop ((i 7) (acc '())) (if (< i 0) (apply string-append (reverse acc)) (let* ((b (bytevector-u8-ref id i)) (h (string-upcase (number->string b 16)))) (loop (- i 1) (cons (if (< b 16) (string-append "0" h) h) acc)))))) ;;; The raw 32-byte Ed25519 public key. (define (minisign-public-key-bytes key) (bytevector-copy (minisign-public-key-raw-bytes key))) ;; --- signatures ------------------------------------------------------ ;;; Parse the contents of a `.minisig` file (string or bytevector). ;;; ;;; Four lines: `untrusted comment: ...`, the base64 signature, `trusted ;;; comment: ...`, the base64 global signature. Raises when the file is ;;; malformed or uses an algorithm other than `ED` or `Ed`. (define (minisign-parse-signature text) (let* ((lines (split-lines (->bytes text "signature"))) (n (length lines))) (when (< n 4) (fail "signature file has fewer than four lines")) (let ((untrusted (nth lines 0)) (sig-line (nth lines 1)) (trusted-line (nth lines 2)) (global-line (nth lines 3))) (unless (null? (filter-non-blank (drop lines 4))) (fail "signature file has content after the global signature")) (unless (bv-prefix? untrusted untrusted-prefix) (fail "first line must start with \"untrusted comment: \"")) (unless (bv-prefix? trusted-line trusted-prefix) (fail "third line must start with \"trusted comment: \"")) (when (> (bytevector-length trusted-line) max-trusted-line-bytes) (fail "trusted comment is too long")) (check-line-bytes sig-line "signature") (check-line-bytes trusted-line "trusted comment") (check-line-bytes global-line "global signature") (let* ((raw (base64-decode-exact sig-line 74 "signature")) (a0 (bytevector-u8-ref raw 0)) (a1 (bytevector-u8-ref raw 1)) (algorithm (cond ((and (= a0 69) (= a1 68)) 'prehashed) ; "ED" ((and (= a0 69) (= a1 100)) 'legacy) ; "Ed" (else (fail "unsupported signature algorithm")))) (comment (bv-slice trusted-line (string-length trusted-prefix) (bytevector-length trusted-line)))) (minisign-signature algorithm: algorithm raw-key-id: (bv-slice raw 2 10) raw-bytes: (bv-slice raw 10 74) comment: comment global: (base64-decode-exact global-line 64 "global signature")))))) ;;; The key id the signature names, as `minisign-public-key-id` formats ;;; it. Read from the signature file, so it is not authenticated. (define (minisign-signature-key-id sig) (key-id->hex (minisign-signature-raw-key-id sig))) ;; --- verification ---------------------------------------------------- ;;; Check `sig` against `message` (string or bytevector) under `key`. ;;; ;;; Returns #f when the signature verifies, and otherwise a symbol naming ;;; the first check that failed. #f for success is deliberate: a caller ;;; who tests the result for truth by mistake then rejects every valid ;;; signature, which the first real use shows, rather than accepting ;;; every invalid one, which nothing shows. ;;; ;;; - `'key-id-mismatch`: the signature names a different key ;;; - `'legacy-refused`: `prehashed-only?` is true and the signature ;;; is a legacy `Ed` one ;;; - `'bad-signature`: the signature over the message is wrong ;;; - `'bad-trusted-comment-signature`: the message verifies but the ;;; trusted comment has been altered ;;; ;;; Most callers want `minisign-verify` or `minisign-verify-prehashed`, ;;; which return the authenticated trusted comment or #f. (define (minisign-failure-reason key sig message prehashed-only?) (unless (minisign-public-key? key) (fail "minisign-failure-reason: not a parsed public key")) (unless (minisign-signature? sig) (fail "minisign-failure-reason: not a parsed signature")) (let ((message (->bytes message "message")) (pk (minisign-public-key-raw-bytes key)) (sig-bytes (minisign-signature-raw-bytes sig))) (cond ((not (bv-equal? (minisign-public-key-raw-key-id key) (minisign-signature-raw-key-id sig))) 'key-id-mismatch) ((and prehashed-only? (eq? (minisign-signature-algorithm sig) 'legacy)) 'legacy-refused) ((not (ed25519-verify pk (if (eq? (minisign-signature-algorithm sig) 'prehashed) (blake2b-512 message) message) sig-bytes)) 'bad-signature) ((not (ed25519-verify pk (bytevector-append sig-bytes (minisign-signature-comment sig)) (minisign-signature-global sig))) 'bad-trusted-comment-signature) (else #f)))) ;;; Verify like `minisign -V`: accepts prehashed `ED` and legacy `Ed` ;;; signatures. Returns the authenticated trusted comment (a string) ;;; when everything verifies, and #f otherwise. (define (minisign-verify key sig message) (verified-comment key sig message #f)) ;;; Verify like `minisign -V -H`: as `minisign-verify`, but a legacy ;;; `Ed` signature is refused (#f). (define (minisign-verify-prehashed key sig message) (verified-comment key sig message #t)) (define (verified-comment key sig message prehashed-only?) (if (eq? #f (minisign-failure-reason key sig message prehashed-only?)) (utf8->string (minisign-signature-comment sig)) #f))))test/differential/ed25519-vs-libsodium.cadded
/* * Differential test: sigil-crypto's Ed25519 verify against libsodium's * crypto_sign_verify_detached, the verifier the minisign tool uses. * * Input (stdin): one case per line, "<label> <pk-hex> <sig-hex> <msg-hex>" * (msg-hex may be "-" for the empty message). For each case both verifiers * run and the verdicts are printed. Then a mutation phase signs random * messages with libsodium and flips single bits in the key, the signature * and the message, comparing verdicts on every mutant. * * Output ends with a summary line * SUMMARY cases=N agree=A expected-divergence=E disagree=D mutants=M ... * and the exit status is 0 only when N > 0, D = 0, E = 2 (speccheck 4 and * 5, see below), no mutant is accepted or disagrees, all 200 unmutated * signatures verify, and all 20 units (7 encoding boundaries, 10 small-order * encodings, 3 large-order controls) pass. * * Build and run: test/differential/run.sh */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sodium.h>#include "ed25519-verify.h"static int hexval(int c){ if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1;}/* Decode hex into out (capacity cap). Returns length, or -1. */static long unhex(const char *hex, unsigned char *out, size_t cap){ if (strcmp(hex, "-") == 0) return 0; size_t n = strlen(hex); if (n % 2 != 0 || n / 2 > cap) return -1; for (size_t i = 0; i < n / 2; i++) { int hi = hexval(hex[2 * i]), lo = hexval(hex[2 * i + 1]); if (hi < 0 || lo < 0) return -1; out[i] = (unsigned char)(hi * 16 + lo); } return (long)(n / 2);}static int sodium_verdict(const unsigned char *pk, const unsigned char *sig, const unsigned char *msg, size_t len){ return crypto_sign_verify_detached(sig, msg, len, pk) == 0;}int main(void){ if (sodium_init() < 0) { fprintf(stderr, "SETUP-FAILED: sodium_init\n"); return 2; } printf("libsodium %s\n", sodium_version_string()); static char line[1 << 20]; static unsigned char msg[1 << 19]; long cases = 0, agree = 0, disagree = 0, expected_diverged = 0; while (fgets(line, sizeof line, stdin)) { char label[256], pkh[256], sigh[512]; static char msgh[1 << 20]; if (line[0] == '#' || line[0] == '\n') continue; if (sscanf(line, "%255s %255s %511s %1048575s", label, pkh, sigh, msgh) != 4) { fprintf(stderr, "SETUP-FAILED: bad input line: %s", line); return 2; } unsigned char pk[32], sig[64]; long mlen; if (unhex(pkh, pk, 32) != 32 || unhex(sigh, sig, 64) != 64 || (mlen = unhex(msgh, msg, sizeof msg)) < 0) { /* Wrong-length keys or signatures are rejected by both APIs' * callers before verification; skip them visibly. */ printf("SKIP %s (not 32-byte key / 64-byte signature)\n", label); continue; } int ours = sigil_crypto_ed25519_verify(pk, msg, (size_t)mlen, sig); int theirs = sodium_verdict(pk, sig, msg, (size_t)mlen); cases++; /* The documented divergence: speccheck cases 4 and 5 need a public * key with a small-order component and pass the cofactored * equation (ours) but not libsodium's cofactorless one. They must * diverge in exactly that direction; anything else is a finding. */ int expected_divergence = strcmp(label, "speccheck-4") == 0 || strcmp(label, "speccheck-5") == 0; const char *tag; if (expected_divergence) { if (ours == 1 && theirs == 0) { expected_diverged++; tag = "EXPECTED-DIVERGENCE"; } else { disagree++; tag = "DIVERGENCE-CHANGED"; } } else if (ours == theirs) { agree++; tag = "AGREE"; } else { disagree++; tag = "DISAGREE"; } printf("%s %s ours=%d libsodium=%d\n", tag, label, ours, theirs); } /* Mutation phase: valid signatures from libsodium, one bit flipped. */ long mutants = 0, mutant_disagree = 0, valid_ok = 0; for (int round = 0; round < 200; round++) { unsigned char pk[32], sk[64], sig[64], m[97]; size_t mlen = (size_t)(round % (int)sizeof m); crypto_sign_keypair(pk, sk); randombytes_buf(m, sizeof m); crypto_sign_detached(sig, NULL, m, mlen, sk); if (sigil_crypto_ed25519_verify(pk, m, mlen, sig) && sodium_verdict(pk, sig, m, mlen)) { valid_ok++; } else { printf("DISAGREE unmutated round=%d\n", round); mutant_disagree++; } for (int bit = 0; bit < 8; bit++) { unsigned char p2[32], s2[64], m2[97]; memcpy(p2, pk, 32); memcpy(s2, sig, 64); memcpy(m2, m, sizeof m); int which = (round + bit) % 3; if (which == 0) { p2[randombytes_uniform(32)] ^= (unsigned char)(1u << bit); } else if (which == 1) { s2[randombytes_uniform(64)] ^= (unsigned char)(1u << bit); } else if (mlen > 0) { m2[randombytes_uniform((uint32_t)mlen)] ^= (unsigned char)(1u << bit); } else { s2[0] ^= 1; } int ours = sigil_crypto_ed25519_verify(p2, m2, mlen, s2); int theirs = sodium_verdict(p2, s2, m2, mlen); mutants++; if (ours != theirs || ours) { /* Any accepted mutant is a finding, agreeing or not. */ printf("MUTANT-%s round=%d bit=%d which=%d ours=%d libsodium=%d\n", ours == theirs ? "ACCEPTED" : "DISAGREE", round, bit, which, ours, theirs); mutant_disagree++; } } } /* Unit phase: the y < p encoding check at its boundaries. No signature * can reach this check alone (a y >= p encoding of a large-order point * has no known discrete log to sign with, and the small-order ones are * also caught by the small-order check), so it is tested directly. */ struct { const char *label; int want; unsigned char last; unsigned char first; int mid_ff; } bounds[] = { /* little-endian: first byte, 30 middle bytes, last byte */ { "y=p-1 (ec ff..ff 7f)", 1, 0x7f, 0xec, 1 }, { "y=p (ed ff..ff 7f)", 0, 0x7f, 0xed, 1 }, { "y=p+18 (ff ff..ff 7f)", 0, 0x7f, 0xff, 1 }, { "y=p, sign bit (ed ff..ff ff)", 0, 0xff, 0xed, 1 }, { "y=p-1, sign bit (ec ff..ff ff)",1, 0xff, 0xec, 1 }, { "y=0 (00..00)", 1, 0x00, 0x00, 0 }, { "y=2^254 (00..00 40)", 1, 0x40, 0x00, 0 }, }; long unit = 0, unit_bad = 0; for (size_t i = 0; i < sizeof bounds / sizeof bounds[0]; i++) { unsigned char p[32]; memset(p, bounds[i].mid_ff ? 0xff : 0x00, 32); p[0] = bounds[i].first; p[31] = bounds[i].last; int got = sigil_crypto_ed25519_point_is_canonical(p); unit++; if (got != bounds[i].want) unit_bad++; printf("%s canonical(%s) = %d, want %d\n", got == bounds[i].want ? "UNIT-OK" : "UNIT-BAD", bounds[i].label, got, bounds[i].want); } /* Unit phase: the small-order test against the 8-torsion subgroup, * derived independently (Python, RFC 8032 section 6 arithmetic: [L]P * for random points P until 8 distinct points appear). Also the two * non-canonical encodings of torsion points (y = p, y = p + 1) and * large-order controls that must NOT be flagged. */ static const char *const torsion[] = { "0000000000000000000000000000000000000000000000000000000000000000", /* 4 */ "0000000000000000000000000000000000000000000000000000000000000080", /* 4 */ "0100000000000000000000000000000000000000000000000000000000000000", /* 1 */ "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", /* 8 */ "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", /* 8 */ "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", /* 8 */ "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", /* 8 */ "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", /* 2 */ "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", /* y=p (0) */ "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", /* y=p+1 (1) */ }; static const char *const large_order[] = { "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", /* RFC 8032 T1 */ "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", /* RFC 8032 T2 */ "5866666666666666666666666666666666666666666666666666666666666666", /* base point */ }; for (size_t i = 0; i < sizeof torsion / sizeof torsion[0]; i++) { unsigned char p[32]; unhex(torsion[i], p, 32); int got = sigil_crypto_ed25519_has_small_order(p); unit++; if (got != 1) unit_bad++; printf("%s small-order(%s) = %d, want 1\n", got == 1 ? "UNIT-OK" : "UNIT-BAD", torsion[i], got); } for (size_t i = 0; i < sizeof large_order / sizeof large_order[0]; i++) { unsigned char p[32]; unhex(large_order[i], p, 32); int got = sigil_crypto_ed25519_has_small_order(p); unit++; if (got != 0) unit_bad++; printf("%s small-order(%s) = %d, want 0\n", got == 0 ? "UNIT-OK" : "UNIT-BAD", large_order[i], got); } printf("SUMMARY cases=%ld agree=%ld expected-divergence=%ld disagree=%ld mutants=%ld " "mutant-disagree=%ld valid-ok=%ld unit=%ld unit-bad=%ld\n", cases, agree, expected_diverged, disagree, mutants, mutant_disagree, valid_ok, unit, unit_bad); return (cases > 0 && disagree == 0 && expected_diverged == 2 && mutant_disagree == 0 && valid_ok == 200 && unit == 20 && unit_bad == 0) ? 0 : 1;}test/differential/run.shadded
#!/bin/sh# Differential gate: sigil-crypto's Ed25519 verify core against libsodium# (what the minisign tool verifies with), over RFC 8032, Wycheproof and# ed25519-speccheck vectors plus 1,600 single-bit mutants.## Needs guix (for gcc-toolchain + libsodium). Run from the repo root:# test/differential/run.sh# Exit 0 only when every case and mutant agrees; see the SUMMARY line.set -euROOT=$(cd "$(dirname "$0")/../.." && pwd)OUT=$(mktemp -d)trap 'rm -rf "$OUT"' EXITguix shell gcc-toolchain libsodium pkg-config -- sh -c ' set -eu gcc -std=c99 -O2 -Wall -Wextra \ -I"$1/native" -I"$1/vendor/monocypher/src" -I"$1/vendor/monocypher/src/optional" \ "$1/test/differential/ed25519-vs-libsodium.c" \ "$1/native/ed25519-verify.c" \ "$1/vendor/monocypher/src/monocypher.c" \ "$1/vendor/monocypher/src/optional/monocypher-ed25519.c" \ $(pkg-config --cflags --libs libsodium) -o "$2/diff"' sh "$ROOT" "$OUT"# Input lines are "<label> <pk> <sig> <msg> <expected>"; the harness reads# the first four fields."$OUT/diff" < "$ROOT/test/vectors/ed25519-cases.txt"test/fixtures/minisign/SHA256SUMS.fixturesadded
dd29f07c6d5bc0f20c537730d3ceb1b428aeb68da3f414b15e0153096a63010c a.pub584d5cbcbd670d1665637e92cbc9d4355cb8e4a15a9257d30f62fd7a656c6077 b.pube3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 empty.txtd2e6b126d73e31b47434966470187c19c1875e08d36f869fe666753e714414ea hello.txt785b0751fc2c53dc14a4ce3d800e69ef9ce1009eb327ccf458afe09c242c26c9 binary.bine1084688607a8358e8713f65d62793d4c70656277bb8a417caae77e04ff460ab binary.bin.ED.minisig9a6fe11e0b9b5e230ae4475a141ddf7ba4afa9f0108d30526a642f3a1a821a21 binary.bin.Ed.minisigb1ffb765f93dd346afad1f8c2ea4cf3870b5fa0b88fd4d6ddabb6243d484c7da empty.txt.ED.minisig3201ca35d18f0c9b8a21a280a12f017ba3842d6ca8ab3ecd80d025847ec498d8 hello.txt.ED.minisig71dc5d67dae8a7a6acf28a4b9a70cc91a43a0584da03d4dfed161b084a78cf2e hello.txt.Ed.minisigdb2cd82e57408f28bd78a1cc31a14011bd68f75ea89e484d40aea02f31683cdf hello.txt.keyb.minisigd151631a336ef2cdbbabc84d09e7dba0220ff9fd8b0d5ddb276d5aa090c0a4ed hello.txt.unicode.minisigdd286956a4c8fd832e9d0654c2bd8bd4b1d0035987e65c42445b3850c1f2cc7e minisign-0.12.tar.gz.minisige7fbb737645ee2b0a79cbf94429f903d914db8895339dd6f25debb12c888eef4 registry.json.minisigdda48047824314698331702a12d8d50dd1f167a399e098d663ed08975bd93a09 registry.json677e3dd52f559992c72be932d958587b5f731a1a295bcee37be878ed3f585926 minisign-0.12.tar.gztest/fixtures/minisign/a.pubadded
untrusted comment: minisign public key 14EB3FB290B96204RWQEYrmQsj/rFOITx6WOfk1JVuOslJV7zwvh6mM3NCDJHhsYfllcASAMtest/fixtures/minisign/b.pubadded
untrusted comment: minisign public key C18A2BC89C1116E4RWTkFhGcyCuKwcaayKgqBhF4tXBbxLlYd5YzwRAJiE1+UBN/VjsO6emttest/fixtures/minisign/binary.binbinary
Binary. Not rendered here.
test/fixtures/minisign/binary.bin.ED.minisigadded
untrusted comment: signature from minisign secret keyRUQEYrmQsj/rFLV7uZuuDOZndblCG1t7hvSAp+7svcm5Co8ImUnUR26/Fd0zDaO+Up+0NRSeLDlZz7o2iKFmm2KSOPih/Yii+Qc=trusted comment: sigil-crypto fixture: binaryx23O9YaUJcbmAAOoRf5zSoRGj8gvl3fjEV5nMtlCqz8iGuD2c0NeVb+tcos90vMIkjOv7HIlDDlrS3+Mg0iaCA==test/fixtures/minisign/binary.bin.Ed.minisigadded
untrusted comment: signature from minisign secret keyRWQEYrmQsj/rFFPr+gm0F6fTajvcnJ9sw6dyLAO2+87zdqgeB7KE9pUJh6olqYNPztjXBCw2/c8mXZ8YW0G1daRCoAUrOsBeGgU=trusted comment: sigil-crypto fixture: binary legacyqMXYd3ygQ9Tntxg7BvGgVFPgxBCdhiUueRkuSnhhdm93BSVxu3nOoedYHm48FMkJPHz+sVTp+qiBaaz2EMxCAg==test/fixtures/minisign/empty.txtadded
No content change.
test/fixtures/minisign/empty.txt.ED.minisigadded
untrusted comment: signature from minisign secret keyRUQEYrmQsj/rFOXiTiZAjZxEAUtoox3cvNRemTMRSVgsxBDK2T2WdaR2IES7oXUHKIDEA65st42VuIuN0Re0QeCrAqDDpHbhbA0=trusted comment: sigil-crypto fixture: empty fileL0fWkEvuUd3D+vi8i1e3y3qeRNFGHMo39R5LD3GnvNhCnd/oG4wpTB3Vo4M/myiZK+5PvkK4QawsF0j8bcjLCQ==test/fixtures/minisign/hello.txtadded
hello, minisigntest/fixtures/minisign/hello.txt.ED.minisigadded
untrusted comment: signature from minisign secret keyRUQEYrmQsj/rFGAyTtKQ+4xZK+0g3fTMxrwdwVx7Zjj99HA7wtkILpBp5KJKc60Q6Gb/+YEBOFMGdO/iEzPsE1StElYtKSlfdgM=trusted comment: sigil-crypto fixture: prehashedgWEm4hy15jT9JNQqTqllc58wBdpu1m4bDJycmgqbPKkr/Zb+Qu/R+R5aSHy3kL3Q7vy4LZtABSdGP4OYPuTbAg==test/fixtures/minisign/hello.txt.Ed.minisigadded
untrusted comment: signature from minisign secret keyRWQEYrmQsj/rFBykYBac8OeKibJSYKcd+vrVMQ44BnmpbBibg2RMi75aC4zJKnPb2q4YwmUEfanfUccJ4Nn9ujGmkxui/Ms1cQ8=trusted comment: sigil-crypto fixture: legacyn3F3KbUvZENZMrgMek8cM48rRatGbW0n5RhKPR7YKcuwAbw9bb0NcQpo635PBwQ4QjoG5mOXAbUz1tShz1JwAg==test/fixtures/minisign/hello.txt.keyb.minisigadded
untrusted comment: signature from minisign secret keyRUTkFhGcyCuKwYTMUo4X8cdeC3c3LfG1rSDfz0MncA4JU60b51ReaUS53TOK0zjnYHs5JWshctEzUMALsI0iwm+6MV2dAor0Zgo=trusted comment: sigil-crypto fixture: key b2fz1Bwvo58gwgkeTH4CXzyHA3cO6YiB9u2ZejnG4mIZG0Z7KqXv1STMonZ0y15BY5n55GnQ+97dxfa+lRpOlAg==test/fixtures/minisign/hello.txt.unicode.minisigadded
untrusted comment: signature from minisign secret keyRUQEYrmQsj/rFGAyTtKQ+4xZK+0g3fTMxrwdwVx7Zjj99HA7wtkILpBp5KJKc60Q6Gb/+YEBOFMGdO/iEzPsE1StElYtKSlfdgM=trusted comment: fixture ✓ unicode — trustedeWW/fZv93llWpOOLFin428gYhWSYuaKdIfV7LcOvEUnrtv8RUxnfpN+dNf4rFJoa1j9WDn2wpSjMKHDM134DBQ==test/fixtures/minisign/make-fixtures.shadded
#!/bin/sh# Regenerate the minisign interop fixtures with the real minisign tool.## guix shell minisign curl -- test/fixtures/minisign/make-fixtures.sh## Keys are generated fresh (unencrypted, in a temp dir that is deleted);# only public keys, messages and signatures are kept. Re-running changes# every key and signature, so commit the whole directory together.## Also fetches two signatures made by other people's keys:# - production registry.json(.minisig) from pkg.usesigil.org, signed by# the Sigil registry ROOT key that sigil-env pins (trust.sgl);# - minisign-0.12.tar.gz(.minisig) from minisign's GitHub release,# signed by the minisign author's published key (minisign README).set -euDIR=$(cd "$(dirname "$0")" && pwd)KEYS=$(mktemp -d)trap 'rm -rf "$KEYS"' EXITcd "$DIR"minisign -vminisign -G -W -f -p a.pub -s "$KEYS/a.key" >/dev/nullminisign -G -W -f -p b.pub -s "$KEYS/b.key" >/dev/nullprintf 'hello, minisign\n' > hello.txt: > empty.txt# Every byte value, including NUL and CR, four times over.LC_ALL=C awk 'BEGIN { for (r = 0; r < 4; r++) for (i = 0; i < 256; i++) printf "%c", i }' > binary.bin[ "$(wc -c < binary.bin)" -eq 1024 ] || { echo "REFUSING: binary.bin is not 1024 bytes"; exit 1; }sign() { # sign <key> <file> <sigfile> <trusted-comment> [extra flags] key=$1 file=$2 out=$3 tc=$4; shift 4 minisign -S -s "$KEYS/$key.key" -m "$file" -x "$out" -t "$tc" "$@" >/dev/null}sign a hello.txt hello.txt.ED.minisig "sigil-crypto fixture: prehashed"sign a hello.txt hello.txt.Ed.minisig "sigil-crypto fixture: legacy" -lsign a empty.txt empty.txt.ED.minisig "sigil-crypto fixture: empty file"sign a binary.bin binary.bin.ED.minisig "sigil-crypto fixture: binary"sign a binary.bin binary.bin.Ed.minisig "sigil-crypto fixture: binary legacy" -lsign a hello.txt hello.txt.unicode.minisig "fixture ✓ unicode — trusted"sign b hello.txt hello.txt.keyb.minisig "sigil-crypto fixture: key b"# Every signature must verify with the tool itself before it is a fixture.minisign -V -q -p a.pub -m hello.txt -x hello.txt.ED.minisigminisign -V -q -p a.pub -m hello.txt -x hello.txt.Ed.minisigminisign -V -q -p a.pub -m empty.txt -x empty.txt.ED.minisigminisign -V -q -p a.pub -m binary.bin -x binary.bin.ED.minisigminisign -V -q -p a.pub -m binary.bin -x binary.bin.Ed.minisigminisign -V -q -p a.pub -m hello.txt -x hello.txt.unicode.minisigminisign -V -q -p b.pub -m hello.txt -x hello.txt.keyb.minisig# -H refuses the legacy one: the positive control for minisign-verify-prehashed.if minisign -V -q -H -p a.pub -m hello.txt -x hello.txt.Ed.minisig 2>/dev/null; then echo "REFUSING: minisign -H accepted a legacy signature"; exit 1ficurl -fsS -o registry.json https://pkg.usesigil.org/v1/meta/registry.jsoncurl -fsS -o registry.json.minisig https://pkg.usesigil.org/v1/meta/registry.json.minisigminisign -V -q -P RWRa9dPSUBFexBbLdzZIfuAmuCYL736UeHC7IbdAOIYpgGIyDmWRaQHY \ -m registry.json -x registry.json.minisigcurl -fsSL -o minisign-0.12.tar.gz \ https://github.com/jedisct1/minisign/releases/download/0.12/minisign-0.12.tar.gzcurl -fsSL -o minisign-0.12.tar.gz.minisig \ https://github.com/jedisct1/minisign/releases/download/0.12/minisign-0.12.tar.gz.minisigminisign -V -q -P RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3 \ -m minisign-0.12.tar.gz -x minisign-0.12.tar.gz.minisigsha256sum *.pub *.txt *.bin *.minisig registry.json minisign-0.12.tar.gz > SHA256SUMS.fixturesecho FIXTURES-COMPLETEtest/fixtures/minisign/minisign-0.12.tar.gzbinary
Binary. Not rendered here.
test/fixtures/minisign/minisign-0.12.tar.gz.minisigadded
untrusted comment: signature from minisign secret keyRUQf6LRCGA9i5waVmlhf9oT0Gur6lx+L3WKuMprQQ1BqCWqdCZnzPHFjFRadIlQxZlaymKfeCz8QHg3Ulh4lYxVQ89K/gKejDA0=trusted comment: timestamp:1736977639 file:minisign-0.12.tar.gz hashedNzfDbdEGyVNkoxsrCAJMh7udzsrRhRAJoq59PEcPy0JnFM2/jdF8UE68unWZVejyZ0TUGWI0VJTTbFQ4HL1UAQ==test/fixtures/minisign/registry.jsonadded
{ "schema": 1, "protocol": 1, "registry": "pkg.usesigil.org", "seq": 1, "updated": "2026-07-30T08:04:54Z", "keys": [ {"id":"C45E1150D2D3F55A","algorithm":"minisign-ed25519","roles":["root"],"public-key":"RWRa9dPSUBFexBbLdzZIfuAmuCYL736UeHC7IbdAOIYpgGIyDmWRaQHY","status":"active"}, {"id":"21CC9BE316C6E0FD","algorithm":"minisign-ed25519","roles":["index"],"public-key":"RWT94MYW45vMIbIdQurIMk46IDZQMiHzlP7VwYQPVNztxJwE23FkHuR1","status":"active"}, {"id":"7F92B426060F2F06","algorithm":"minisign-ed25519","roles":["toolchain"],"public-key":"RWQGLw8GJrSSfzudcy/vnMgUzoEUvVdmZxyzA20AJ6gSusjQk3eb3aBU","status":"active"}, {"id":"DB1A828BD034F595","algorithm":"minisign-ed25519","roles":["substitutes"],"public-key":"RWSV9TTQi4Ia2zvGgBaclHH8wIC4c/E1249XreikJ8g0U4/z+vsM77p2","status":"active"}, {"id":"989EF54F5E93C736","algorithm":"minisign-ed25519","roles":["channels"],"public-key":"RWQ2x5NeT/WemGsI3aV/G8gnrLevQftaIYIC2d06FPcoSV7n1hcan0j0","status":"active"} ], "log": null, "reproducibility": null}test/fixtures/minisign/registry.json.minisigadded
untrusted comment: signature from minisign secret keyRURa9dPSUBFexGJGC6m+fr4URX3C6/14b7cv85FbTgui4dCOAROj/xA0Vy4Sn5uXbBlsOW9PBYQNz+bZ2fvQPr4O5q//+bkLkQw=trusted comment: registry=pkg.usesigil.org path=/v1/meta/registry.json seq=1 ts=2026-07-30T08:04:54ZCL7XNWmV5Klo6bIHE8x2IXF18LwqHfZP2rynmoSPrRzDCLJtlGfw+MLx7cQGYSZo/Lk4cA2OGMFA/O1QzYBYCw==test/test-ed25519-vectors.sgladded
;;; GENERATED by test/vectors/gen-ed25519-vectors.sh from;;; test/vectors/ed25519-cases.txt. Do not edit by hand.;;;;;; Every case runs through ed25519-verify. A valid case must return #t;;;; an invalid one must return #f, or raise when the key or signature has the;;; wrong length (the API raises on wrong lengths; nothing else may raise).(import (sigil test) (sigil crypto) (sigil math))(define (hex->bv s) (if (string=? s "-") (make-bytevector 0 0) (let* ((n (quotient (string-length s) 2)) (bv (make-bytevector n 0))) (let loop ((i 0)) (if (< i n) (begin (bytevector-u8-set! bv i (string->number (substring s (* 2 i) (+ 2 (* 2 i))) 16)) (loop (+ i 1))) bv)))));; #t, #f, or the symbol raised when the call raises.(define (verdict pk sig msg) (guard (e (#t (quote raised))) (ed25519-verify (hex->bv pk) (hex->bv msg) (hex->bv sig))))(test-group "ed25519 vectors" (test "rfc8032-1 valid" (assert-eq #t (verdict "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a" "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b" "-"))) (test "rfc8032-2 valid" (assert-eq #t (verdict "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c" "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00" "72"))) (test "rfc8032-3 valid" (assert-eq #t (verdict "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025" "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a" "af82"))) (test "rfc8032-1024 valid" (assert-eq #t (verdict "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e" "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03" "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0"))) (test "rfc8032-SHAabc valid" (assert-eq #t (verdict "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf" "dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704" "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"))) (test "wycheproof-1 valid" (assert-eq #t (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "d4fbdb52bfa726b44d1786a8c0d171c3e62ca83c9e5bbe63de0bb2483f8fd6cc1429ab72cafc41ab56af02ff8fcc43b99bfe4c7ae940f60f38ebaa9d311c4007" "-"))) (test "wycheproof-2 valid" (assert-eq #t (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "d80737358ede548acb173ef7e0399f83392fe8125b2ce877de7975d8b726ef5b1e76632280ee38afad12125ea44b961bf92f1178c9fa819d020869975bcbe109" "78"))) (test "wycheproof-3 valid" (assert-eq #t (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d" "54657374"))) (test "wycheproof-4 valid" (assert-eq #t (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "1c1ad976cbaae3b31dee07971cf92c928ce2091a85f5899f5e11ecec90fc9f8e93df18c5037ec9b29c07195ad284e63d548cd0a6fe358cc775bd6c1608d2c905" "48656c6c6f"))) (test "wycheproof-5 valid" (assert-eq #t (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bf0cf5b3a289976458a1be6277a5055545253b45b07dcc1abd96c8b989c00f301" "313233343030"))) (test "wycheproof-6 valid" (assert-eq #t (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "d46543bfb892f84ec124dcdfc847034c19363bf3fc2fa89b1267833a14856e52e60736918783f950b6f1dd8d40dc343247cd43ce054c2d68ef974f7ed0f3c60f" "000000000000000000000000"))) (test "wycheproof-7 valid" (assert-eq #t (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "879350045543bc14ed2c08939b68c30d22251d83e018cacbaf0c9d7a48db577e80bdf76ce99e5926762bc13b7b3483260a5ef63d07e34b58eb9c14621ac92f00" "6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161"))) (test "wycheproof-8 valid" (assert-eq #t (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7bdc3f9919a05f1d5db4a3ada896094f6871c1f37afc75db82ec3147d84d6f237b7e5ecc26b59cfea0c7eaf1052dc427b0f724615be9c3d3e01356c65b9b5109" "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60"))) (test "wycheproof-9 valid" (assert-eq #t (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "5dbd7360e55aa38e855d6ad48c34bd35b7871628508906861a7c4776765ed7d1e13d910faabd689ec8618b78295c8ab8f0e19c8b4b43eb8685778499e943ae04" "ffffffffffffffffffffffffffffffff"))) (test "wycheproof-10 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" "3f"))) (test "wycheproof-11 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000" "3f"))) (test "wycheproof-12 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "0000000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" "3f"))) (test "wycheproof-13 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "0000000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" "3f"))) (test "wycheproof-14 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "0000000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f" "3f"))) (test "wycheproof-15 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" "3f"))) (test "wycheproof-16 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "01000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000" "3f"))) (test "wycheproof-17 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "0100000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" "3f"))) (test "wycheproof-18 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "0100000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" "3f"))) (test "wycheproof-19 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "0100000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f" "3f"))) (test "wycheproof-20 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000" "3f"))) (test "wycheproof-21 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000000" "3f"))) (test "wycheproof-22 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" "3f"))) (test "wycheproof-23 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" "3f"))) (test "wycheproof-24 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f" "3f"))) (test "wycheproof-25 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000" "3f"))) (test "wycheproof-26 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0100000000000000000000000000000000000000000000000000000000000000" "3f"))) (test "wycheproof-27 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" "3f"))) (test "wycheproof-28 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010" "3f"))) (test "wycheproof-29 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f" "3f"))) (test "wycheproof-30 " (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "54657374" "invalid"))) (test "wycheproof-31 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0" "54657374"))) (test "wycheproof-32 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946" "54657374"))) (test "wycheproof-33 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d2020" "54657374"))) (test "wycheproof-34 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "54657374"))) (test "wycheproof-35 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "007c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d" "54657374"))) (test "wycheproof-36 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0007a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d" "54657374"))) (test "wycheproof-37 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d00" "54657374"))) (test "wycheproof-38 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "93de3ca252426c95f735cb9edd92e83321ac62372d5aa5b379786bae111ab6b17251330e8f9a7c30d6993137c596007d7b001409287535ac4804e662bc58a3" "546573743137"))) (test "wycheproof-39 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "dffed33a7f420b62bb1731cfd03be805affd18a281ec02b1067ba6e9d20826569e742347df59c88ae96db1f1969fb189b0ec34381d85633e1889da48d95e0e" "54657374313236"))) (test "wycheproof-40 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "6e170c719577c25e0e1e8b8aa7a6346f8b109f37385cc2e85dc3b4c0f46a9c6bcafd67f52324c5dbaf40a1b673fb29c4a56052d2d6999d0838a8337bccb502" "546573743530"))) (test "wycheproof-41 invalid" (assert-eq (quote raised) (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "b0928b46e99fbbad3f5cb502d2cd309d94a7e86cfd4d84b1fcf4cea18075a9c36993c0582dba1e9e519fae5a8654f454201ae0c3cb397c37b8f4f8eef18400" "54657374333437"))) (test "wycheproof-42 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "647c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b1d125e5538f38afbcc1c84e489521083041d24bc6240767029da063271a1ff0c" "313233343030"))) (test "wycheproof-43 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "677c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bc108ca4b87a49c9ed2cf383aecad8f54a962b2899da891e12004d7993a627e01" "313233343030"))) (test "wycheproof-44 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "617c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b9ce23fc6213ed5b87912e9bbf92f5e2c780eae26d15c50a112d1e97d2ea33c06" "313233343030"))) (test "wycheproof-45 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "e57c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bbb3eb51cd98dddb235a5f46f2bded6af184a58d09cce928bda43f41d69118a03" "313233343030"))) (test "wycheproof-46 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657d1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcd237dda9a116501f67a5705a854b9adc304f34720803a91b324f2c13e0f5a09" "313233343030"))) (test "wycheproof-47 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1592402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b6b167bbdc0d881cc04d28905552c1876f3709851abc5007376940cc8a435c300" "313233343030"))) (test "wycheproof-48 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1412402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7fd2ac7da14afffcceeb13f2a0d6b887941cb1a5eb57a52f3cb131a16cce7b0e" "313233343030"))) (test "wycheproof-49 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492412ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7373ba13ebbef99cd2a8ead55ce735c987d85a35320925a8e871702dc7c5c40d" "313233343030"))) (test "wycheproof-50 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab54e03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bd35bd331c03f0855504ca1cab87b83c36a028425a3cf007ede4f4254c261cb00" "313233343030"))) (test "wycheproof-51 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce02e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcb35101f73cf467deac8c1a03b6c3dc35af544132734b7e57ab20c89b2e4750d" "313233343030"))) (test "wycheproof-52 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce03e2c3a7f2384d051b9cf3570f1207fc78c1bcc98c281c2bb58d2e8878290bff8d3355fdd4ea381924ee578752354eb6dee678ab4011c301" "313233343030"))) (test "wycheproof-53 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce03e2c3a7f0384d851b9cf3570f1207fc78c1bcc98c281c2bb978c866187ffb1cc7b29a0b4045aefc08768df65717194ff0c6e63f4dea0d02" "313233343030"))) (test "wycheproof-54 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281d2b0576ecf8eaf675f00f3dfbe19f75b83b7607a6c96414f6821af920a2498d0305" "313233343030"))) (test "wycheproof-55 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c289c2be5241a345c7b5428054c74b7c382fa10d4a5f1e8f8b79a71d3fdea2254f1ff0e" "313233343030"))) (test "wycheproof-56 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2a63950c85cd6dc96364e768de50ff7732b538f8a0b1615d799190ab600849230e" "313233343030"))) (test "wycheproof-57 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c0b543bd3da0a56a8c9c152f59c9fec12f31fa66434d48b817b30d90cb4efa8b501" "313233343030"))) (test "wycheproof-58 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c6b8da07efd07a6dafb015ed6a32fe136319a972ffbc341f3a0beae97ccf8136505" "313233343030"))) (test "wycheproof-59 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281cab227aedf259f910f0f3a759a335062665217925d019173b88917eae294f75d40f" "313233343030"))) (test "wycheproof-60 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "0000000000000000000000000000000000000000000000000000000000000000e0b8e7770d51c7a36375d006c5bffd6af43ff54aaf47e4330dc118c71d61ec02" "313233343030"))) (test "wycheproof-61 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff463a1908382e7eb7693acef9884f7cf931a215e0791876be22c631a59881fd0e" "313233343030"))) (test "wycheproof-62 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "9a83eb6dbfd54a31fc1d3c580fc7b2fae4630ca8f0edf803873e433673d7e3d40e94254586cb6188c5386c3febed477cb9a6cb29e3979adc4cb27cf5278fb70a" "313233343030"))) (test "wycheproof-63 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab067654bce3832c2d76f8f6f5dafc08d9339d4eef676573336a5c51eb6f946b31d" "54657374"))) (test "wycheproof-64 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab05439412b5395d42f462c67008eba6ca839d4eef676573336a5c51eb6f946b32d" "54657374"))) (test "wycheproof-65 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab02ee12ce5875bf9dff26556464bae2ad239d4eef676573336a5c51eb6f946b34d" "54657374"))) (test "wycheproof-66 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0e2300459f1e742404cd934d2c595a6253ad4eef676573336a5c51eb6f946b38d" "54657374"))) (test "wycheproof-67 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b32d" "54657374"))) (test "wycheproof-68 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b34d" "54657374"))) (test "wycheproof-69 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d" "54657374"))) (test "wycheproof-70 invalid" (assert-eq #f (verdict "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0679155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d" "54657374"))) (test "wycheproof-71 valid" (assert-eq #t (verdict "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c" "5056325d2ab440bf30bbf0f7173199aa8b4e6fbc091cf3eb6bc6cf87cd73d992ffc216c85e4ab5b8a0bbc7e9a6e9f8d33b7f6e5ac0ffdc22d9fcaf784af84302" "-"))) (test "wycheproof-72 valid" (assert-eq #t (verdict "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c" "481fafbf4364d7b682475282f517a3ac0538c9a6b6a562e99a3d8e5afb4f90a559b056b9f07af023905753b02d95eb329a35c77f154b79abbcd291615ce42f02" "78"))) (test "wycheproof-73 valid" (assert-eq #t (verdict "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c" "8a9bb4c465a3863abc9fd0dd35d80bb28f7d33d37d74679802d63f82b20da114b8d765a1206b3e9ad7cf2b2d8d778bb8651f1fa992db293c0039eacb6161480f" "54657374"))) (test "wycheproof-74 valid" (assert-eq #t (verdict "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c" "d839c20abfda1fd429531831c64f813f84b913e9928540310cf060b44c3dbf9457d44a7721fdc0d67724ff81cb450dd39b10cfb65db15dda4b8bf09d26bd3801" "48656c6c6f"))) (test "wycheproof-75 valid" (assert-eq #t (verdict "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c" "9bbb1052dcfa8ad2715c2eb716ae4f1902dea353d42ee09fd4c0b4fcb8b52b5219e2200016e1199d0061891c263e31b0bc3b55673c19610c4e0fa5408004160b" "313233343030"))) (test "wycheproof-76 valid" (assert-eq #t (verdict "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c" "f63b5c0667c7897fc283296416f7f60e84bbde9cbd832e56be463ed9f568069702b17a2f7c341ebf590706a6388ac76ac613c1675ec0f2c7118f2573422a500b" "000000000000000000000000"))) (test "wycheproof-77 valid" (assert-eq #t (verdict "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c" "1bc44d7001e6b5b9090fef34b2ca480f9786bbefa7d279353e5881e8dfb91b803ccd46500e270ef0109bfd741037558832120bc2a4f20fbe7b5fb3c3aaf23e08" "6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161"))) (test "wycheproof-78 valid" (assert-eq #t (verdict "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c" "ea8e22143b02372e76e99aece3ed36aec529768a27e2bb49bdc135d44378061e1f62d1ac518f33ebf37b2ee8cc6dde68a4bd7d4a2f4d6cb77f015f71ca9fc30d" "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60"))) (test "wycheproof-79 valid" (assert-eq #t (verdict "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c" "8acd679e1a914fc45d5fa83d3021f0509c805c8d271df54e52f43cfbd00cb6222bf81d58fe1de2de378df67ee9f453786626961fe50a9b05f12b6f0899ebdd0a" "ffffffffffffffffffffffffffffffff"))) (test "wycheproof-80 valid" (assert-eq #t (verdict "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a" "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b" "-"))) (test "wycheproof-81 valid" (assert-eq #t (verdict "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c" "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00" "72"))) (test "wycheproof-82 valid" (assert-eq #t (verdict "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025" "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a" "af82"))) (test "wycheproof-83 valid" (assert-eq #t (verdict "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e" "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03" "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0"))) (test "wycheproof-84 valid" (assert-eq #t (verdict "100fdf47fb94f1536a4f7c3fda27383fa03375a8f527c537e6f1703c47f94f86" "dac119d6ca87fc59ae611c157048f4d4fc932a149dbe20ec6effd1436abf83ea05c7df0fef06147241259113909bc71bd3c53ba4464ffcad3c0968f2ffffff0f" "124e583f8b8eca58bb29c271b41d36986bbc45541f8e51f9cb0133eca447601e"))) (test "wycheproof-85 invalid" (assert-eq #f (verdict "100fdf47fb94f1536a4f7c3fda27383fa03375a8f527c537e6f1703c47f94f86" "0971f86d2c9c78582524a103cb9cf949522ae528f8054dc20107d999be673ff4e25ebf2f2928766b1248bec6e91697775f8446639ede46ad4df4053000000010" "6a0bc2b0057cedfc0fa2e3f7f7d39279b30f454a69dfd1117c758d86b19d85e0"))) (test "wycheproof-86 valid" (assert-eq #t (verdict "8fd659b77b558ed93882c1157438450ac86ec62d421d568e98ee236f3810295a" "7db17557ac470c0eda4eedaabce99197ab62565653cf911f632ee8be0e5ffcfc88fb94276b42e0798fd3aa2f0318be7fc6a29fae75f70c3dcdc414a0ad866601" "b0729a713593a92e46b56eaa66b9e435f7a09a8e7de03b078f6f282285276635f301e7aaafe42187c45d6f5b13f9f16b11195cc125c05b90d24dfe4c"))) (test "wycheproof-87 valid" (assert-eq #t (verdict "2a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082" "67d84d4c3945aaf06e06d524be63acbfb5dbb1988c4aea96a5ee9f7a9b9eecc29df4f66b8aa1d9e8607a58fb1ef0c2ad69aac005b4f58e34103344a9c8871a09" "a8546e50ba31cae3234310d32672447be213fad91a227a19669c53d309b959782b0e6b71f8791fdb470043b58122003157d2d96a43a6cbd7d3a8d86bf4c97391883e268d50af80e1e6e12939c2bd50ca746cdadfad4edf1bda875299740724148efb1ebe73fb60088cda890317658627a5f7ab5a0c075d9d8f3f97b6492b35519e50ff6b38377432a7081f9176bb1c29a862deac1336ca20b097a47829cec10a6a7cec178eda2d12f6dc6c87f910454af0123555ba184e68804d9cced60fd5c8c90943e56599c8f0ba59a38491ba5e5a53460682474c07e40ca142983314fd762856bb1093f359da6eb0a756bd93a3160c10dd8feea6b97e7c6a17cb54bd5d7649c05c66d7bdee056671dfdaf689fa3945bb8e29a429f4bd5d355dce9687b06f01d5e33e3999f0e8"))) (test "wycheproof-88 valid" (assert-eq #t (verdict "c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051" "24087d47f3e20af51b9668ae0a88ce76586802d0ec75d8c0f28fc30962b5e1d1a1d509571a1624ed125a8df92a6e963728d6b5de99200b8e285f70feb6f05207" "cd2212eddb0706f62c995cef958634f0cb7793444cbf4d30e81c27c41ebea6cb02607510131f9c015692dfd521b148841e9a2d3564d20ac401f6cb8e40f520fe0cafbeaa88840b83013369d879f013463fe52a13267aa0c8c59c45cde9399cd1e6be8cc64cf48315ac2eb31a1c567a4fb7d601746d1f63b5ac020712adbbe07519bded6f"))) (test "wycheproof-89 valid" (assert-eq #t (verdict "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e" "d920d421a5956b69bfe1ba834c025e2babb6c7a6d78c97de1d9bb1116dfdd1185147b2887e34e15578172e150774275ea2aad9e02106f7e8ca1caa669a066f0c" "ec5c7cb078"))) (test "wycheproof-90 valid" (assert-eq #t (verdict "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e" "4f62daf7f7c162038552ad7d306e195baa37ecf6ca7604142679d7d1128e1f8af52e4cb3545748c44ef1ff1c64e877e4f4d248259b7f6eb56e3ef72097dc8e0c" "4668c6a76f0e482190a7175b9f3806a5fe4314a004fa69f988373f7a"))) (test "wycheproof-91 valid" (assert-eq #t (verdict "c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a" "6669acf94667c5b541afe5307bde9476b13ae7e0e6058a772101ac8eb0a94331428eb4db0a2c68a9b6c1763b8624dab259b0876cdcfaeacc17b21a18e3fc010a" "0f325ffd87e58131ffa23c05ea4579513b287fdba87b44"))) (test "wycheproof-92 valid" (assert-eq #t (verdict "cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10" "30490c28f806298225df62103521dcee047153912c33ab8ab8bbdd1ffabd70fd4fdb360f05be535b067d1cf4e78c2cb432206bf280aab3bd21aaa1cb894c5b06" "ec5c7cb078"))) (test "wycheproof-93 valid" (assert-eq #t (verdict "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e" "deecafb6f2ede73fec91a6f10e45b9c1c61c4b9bfbe6b6147e2de0b1df6938971f7896c3ab83851fb5d9e537037bff0fca0ccb4a3cc38f056f91f7d7a0557e08" "5dc9bb87eb11621a93f92abe53515697d2611b2eef73"))) (test "wycheproof-94 valid" (assert-eq #t (verdict "cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10" "4cd4f77ed473a6647387f3163541c67a1708a3c3bd1673247cb87f0cb68b3c56f04bfa72970c8a483efe659c87009ab4020b590b6641316b3deddb5450544e02" "67484059b2490b1a0a4f8dee77979e26"))) (test "wycheproof-95 valid" (assert-eq #t (verdict "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e" "7f8663cf98cbd39d5ff553f00bcf3d0d520605794f8866ce75714d77cc51e66c91818b657d7b0dae430a68353506edc4a714c345f5ddb5c8b958ba3d035f7a01" "7dcfe60f881e1285676f35b68a1b2dbcdd7be6f719a288ababc28d36e3a42ac3010a1ca54b32760e74"))) (test "wycheproof-96 valid" (assert-eq #t (verdict "cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10" "1e41a24fe732bd7cab14c2a2f5134ee8c87fcbd2e987e60957ed9239e5c32404d56977e1b4282871896cb10625a1937468e4dc266e16a9c1b8e9891177eca802" "a020a4381dc9141f47ee508871ab7a8b5a3648727c4281ae9932376f23a8e1bcda0626b7129197d864178631ec89c4332dbb18"))) (test "wycheproof-97 valid" (assert-eq #t (verdict "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e" "6aab49e5c0bc309b783378ee03ffda282f0185cdf94c847701ff307a6ee8d0865411c44e0a8206f6a5f606107451940c2593af790ce1860f4c14ab25b2deae08" "58e456064dff471109def4ca27fa8310a1df32739655b624f27e6418d34b7f007173f3faa5"))) (test "wycheproof-98 valid" (assert-eq #t (verdict "529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56" "01abfa4d6bbc726b196928ec84fd03f0c953a4fa2b228249562ff1442a4f63a7150b064f3712b51c2af768d2c2711a71aabf8d186833e941a0301b82f0502905" "e1cbf2d86827825613fb7a85811d"))) (test "wycheproof-99 valid" (assert-eq #t (verdict "cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10" "2a833aadecd9f28235cb5896bf3781521dc71f28af2e91dbe1735a61dce3e31ac15ca24b3fc47817a59d386bbbb2ce60a6adc0a2703bb2bdea8f70f91051f706" "a25176b3afea318b2ec11ddacb10caf7179c0b3f8eabbfa2895581138d3c1e0e"))) (test "wycheproof-100 valid" (assert-eq #t (verdict "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e" "1a74ed2cbdc7d8f3827014e8e6ecf8fd2698ac8f86833acccdd400df710fe0d6b0543c9cfa00d52bf024ab7ce0d91981944097233ec134d5c7abbd44bfd32d0d" "a1"))) (test "wycheproof-101 valid" (assert-eq #t (verdict "2252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1" "af0fd9dda7e03e12313410d8d8844ebb6fe6b7f65141f22d7bcba5695a25414a9e54326fb44d59fb14707899a8aae70857b23d4080d7ab2c396ef3a36d45ce02" "975ef941710071a9e1e6325a0c860becd7c695b5117c3107b686e330e5"))) (test "wycheproof-102 valid" (assert-eq #t (verdict "c0a773110f975de3732355bb7ec7f0c41c091c0252966070205516693b992a4a" "0280427e713378f49d478df6373c6cac847b622b567daa2376c839e7ac10e22c380ab0fa8617c9dcfe76c4d9db5459b21dc1413726e46cc8f387d359e344f407" "-"))) (test "wycheproof-103 valid" (assert-eq #t (verdict "cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10" "c97e3190f83bae7729ba473ad46b420b8aad735f0808ea42c0f898ccfe6addd4fd9d9fa3355d5e67ee21ab7e1f805cd07f1fce980e307f4d7ad36cc924eef00c" "a9e6d94870a67a9fe1cf13b1e6f9150cdd407bf6480ec841ea586ae3935e9787163cf419c1"))) (test "wycheproof-104 valid" (assert-eq #t (verdict "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e" "14ceb2eaf4688d995d482f44852d71ad878cd7c77b41e60b0065fd01a59b054ee74759224187dbde9e59a763a70277c960892ef89fba997aba2576b2c54ba608" "11cb1eafa4c42a8402c4193c4696f7b2e6d4585e4b42dcf1a8b67a80b2da80bc9d4b649fb2f35eaf1f56c426fd0b"))) (test "wycheproof-105 valid" (assert-eq #t (verdict "c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051" "c2656951e2a0285585a51ff0eda7e9a23c2dfd2ffa273aee7808f4604e8f9a8c8ea49e9fce4eb2d8d75d36b7238fe6fc13b6c5d9427dd58f8c6615d033c0bd0f" "27d465bc632743522aefa23c"))) (test "wycheproof-106 valid" (assert-eq #t (verdict "c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a" "931e5152fcef078c22cc5d6a3a65f06e396289f6f5f2d1efa6340254a53526ef5dc6874eeddf35c3f50991c53cd02bf06313e37d93ee1f7022128ffa3b8f300b" "5ffa"))) (test "wycheproof-107 valid" (assert-eq #t (verdict "529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56" "e4ae21f7a8f4b3b325c161a8c6e53e2edd7005b9c2f8a2e3b0ac4ba94aa80be6f2ee22ac8d4a96b9a3eb73a825e7bb5aff4a3393bf5b4a38119e9c9b1b041106" "25"))) (test "wycheproof-108 valid" (assert-eq #t (verdict "2252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1" "e097e0bd0370bff5bde359175a11b728ee9639095d5df8eda496395565616edfe079977f7d4dc8c75d6113a83d6a55e6e1676408c0967a2906339b43337dcb01" "80fdd6218f29c8c8f6bd820945f9b0854e3a8824"))) (test "wycheproof-109 valid" (assert-eq #t (verdict "2a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082" "28fafbb62b4d688fa79e1ac92851f46e319b161f801d4dc09acc21fdd6780a2c4292b8c1003c61c2bcebe7f3f88ccc4bb26d407387c5f27cb8c94cf6ce810405" "b477b0480bb84642608b908d29a51cf2fce63f24ee95"))) (test "wycheproof-110 valid" (assert-eq #t (verdict "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e" "83c40ce13d483cc58ff65844875862d93df4bd367af77efa469ec06a8ed9e6d7905a04879535708ddf225567a815c9b941d405c98e918fd0c151165cea7fb101" "aa365b442d12b7f3c925"))) (test "wycheproof-111 valid" (assert-eq #t (verdict "54cda623245759ad6d43e620a606908befc633d60792bc7798447a0ef38e7311" "14d9b497c19b91d43481c55bb6f5056de252d9ecb637575c807e58e9b4c5eac8b284089d97e2192dc242014363208e2c9a3435edf8928fb1d893553e9be4c703" "27e792b28b2f1702"))) (test "wycheproof-112 valid" (assert-eq #t (verdict "2362bac514d5fad33802642e979a1e82de6eb6f1bcbf6a5b304f2bb02b9e57fe" "242ddb3a5d938d07af690b1b0ef0fa75842c5f9549bf39c8750f75614c712e7cbaf2e37cc0799db38b858d41aec5b9dd2fca6a3c8e082c10408e2cf3932b9d08" "eef3bb0f617c17d0420c115c21c28e3762edc7b7fb048529b84a9c2bc6"))) (test "wycheproof-113 valid" (assert-eq #t (verdict "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e" "71a4a06a34075f2fd47bc3abf4714d46db7e97b08cb6180d3f1539ac50b18ce51f8af8ae95ed21d4fa0daab7235925631ecea1fd9d0d8a2ba7a7583fd04b900c" "475f"))) (test "wycheproof-114 valid" (assert-eq #t (verdict "037b55b427dc8daa0f80fcebaf0846902309f8a6cf18b465c0ce9b6539629ac8" "c964e100033ce8888b23466677da4f4aea29923f642ae508f9d0888d788150636ab9b2c3765e91bbb05153801114d9e52dc700df377212222bb766be4b8c020d" "01234567"))) (test "wycheproof-115 valid" (assert-eq #t (verdict "9c0007698f177998a7666c7cf7973e2b88e9c4946e33804a7bbe8968d2394b2e" "176065c6d64a136a2227687d77f61f3fca3b16122c966276fd9a8b14a1a2cea4c33b3533d11101717016684e3810efbea63bb23773f7cc480174199abd734f08" "9399a6db9433d2a28d2b0c11c8794ab7d108c95b"))) (test "wycheproof-116 valid" (assert-eq #t (verdict "ed3a6f9721dc9729c1f76635bcf080d7036e1c2f0228654ccbbe1e738c17b963" "7ca69331eec8610d38f00e2cdbd46966cb359dcde98a257ac6f362cc00c8f4fe85c02285fe4d66e31a44cadb2bf474e1a7957609eb4fe95a71473fe6699aa70d" "7af783afbbd44c1833ab7237ecaf63b94ffdd003"))) (test "wycheproof-117 valid" (assert-eq #t (verdict "4abfb535313705a6570018440cdec1a3ae33e51f352112fa6acbd0c6bc3ea859" "f296715e855d8aecccba782b670163dedc4458fe4eb509a856bcac450920fd2e95a3a3eb212d2d9ccaf948c39ae46a2548af125f8e2ad9b77bd18f92d59f9200" "321b5f663c19e30ee7bbb85e48ecf44db9d3f512"))) (test "wycheproof-118 valid" (assert-eq #t (verdict "4f2162e6bf03a712db0efa418b7e7006e23871d9d7ec555a313885c4afd96385" "367d07253a9d5a77d054b9c1a82d3c0a448a51905343320b3559325ef41839608aa45564978da1b2968c556cfb23b0c98a9be83e594d5e769d69d1156e1b1506" "c48890e92aeeb3af04858a8dc1d34f16a4347b91"))) (test "wycheproof-119 valid" (assert-eq #t (verdict "4abfb535313705a6570018440cdec1a3ae33e51f352112fa6acbd0c6bc3ea859" "f296715e855d8aecccba782b670163dedc4458fe4eb509a856bcac450920fd2e95a3a3eb212d2d9ccaf948c39ae46a2548af125f8e2ad9b77bd18f92d59f9200" "321b5f663c19e30ee7bbb85e48ecf44db9d3f512"))) (test "wycheproof-120 valid" (assert-eq #t (verdict "4f2162e6bf03a712db0efa418b7e7006e23871d9d7ec555a313885c4afd96385" "367d07253a9d5a77d054b9c1a82d3c0a448a51905343320b3559325ef41839608aa45564978da1b2968c556cfb23b0c98a9be83e594d5e769d69d1156e1b1506" "c48890e92aeeb3af04858a8dc1d34f16a4347b91"))) (test "wycheproof-121 valid" (assert-eq #t (verdict "0717d75ce27ea181ed5a30e6456c649b5cf453a6b4c12cd3f9fd16b31e0c25cd" "9588e02bc815649d359ce710cdc69814556dd8c8bab1c468f40a49ebefb7f0de7ed49725edfd1b708fa1bad277c35d6c1b9c5ec25990997645780f9203d7dd08" "26d5f0631f49106db58c4cfc903691134811b33c"))) (test "wycheproof-122 valid" (assert-eq #t (verdict "db5b9eab7e84e5a13505865fa711c9c896c898609fc11fc9bc1e55028f9496df" "2217a0be57dd0d6c0090641496bcb65e37213f02a0df50aff0368ee2808e1376504f37b37494132dfc4d4887f58b9e86eff924040db3925ee4f8e1428c4c500e" "2a71f064af982a3a1103a75cef898732d7881981"))) (test "wycheproof-123 valid" (assert-eq #t (verdict "7bac18f6d2625d3915f233434cda38a577247a7332a5170b37142a34644145e0" "1fda6dd4519fdbefb515bfa39e8e5911f4a0a8aa65f40ef0c542b8b34b87f9c249dc57f320718ff457ed5915c4d0fc352affc1287724d3f3a9de1ff777a02e01" "bf26796cef4ddafcf5033c8d105057db0210b6ad"))) (test "wycheproof-124 valid" (assert-eq #t (verdict "7bac18f6d2625d3915f233434cda38a577247a7332a5170b37142a34644145e0" "1fda6dd4519fdbefb515bfa39e8e5911f4a0a8aa65f40ef0c542b8b34b87f9c249dc57f320718ff457ed5915c4d0fc352affc1287724d3f3a9de1ff777a02e01" "bf26796cef4ddafcf5033c8d105057db0210b6ad"))) (test "wycheproof-125 valid" (assert-eq #t (verdict "38ead304624abebf3e2b31e20e5629531e3fc659008887c9106f5e55adbbc62a" "068eafdc2f36b97f9bae7fbda88b530d16b0e35054d3a351e3a4c914b22854c711505e49682e1a447e10a69e3b04d0759c859897b64f71137acf355b63faf100" "ae03da6997e40cea67935020152d3a9a365cc055"))) (test "wycheproof-126 valid" (assert-eq #t (verdict "e9bc95049af7e4817b17c402269ba5e767b7348757ac8002fec9e08390c0a9cf" "43670abc9f09a8a415e76f4a21c6a46156f066b5a37b3c1e867cf67248c7b927e8d13a763e37abf936f5f27f7a8aa290539d21f740efd26b65fd5ad27085f400" "489d473f7fb83c7f6823baf65482517bccd8f4ea"))) (test "wycheproof-127 valid" (assert-eq #t (verdict "ee8155ca4e8fe7bc5bca5992044eab7f8c3c6a13db1176f42f46c29da5b064f4" "56388f2228893b14ce4f2a5e0cc626591061de3a57c50a5ecab7b9d5bb2caeea191560a1cf2344c75fdb4a085444aa68d727b39f498169eaa82cf64a31f59803" "1b704d6692d60a07ad1e1d047b65e105a80d3459"))) (test "wycheproof-128 valid" (assert-eq #t (verdict "db507bfcc9576393f7157bb360532b05c5fcf2e764b690cc6698a4a30d349095" "553e5845fc480a577da6544e602caadaa00ae3e5aa3dce9ef332b1541b6d5f21bdf1d01e98baf80b8435f9932f89b3eb70f02da24787aac8e77279e797d0bd0b" "dc87030862c4c32f56261e93a367caf458c6be27"))) (test "wycheproof-129 valid" (assert-eq #t (verdict "994eaf03309d6ad9d95a656bc1744e2886f029023a3750b34f35086b3c7227f8" "bc10f88081b7be1f2505b6e76c5c82e358cf21ec11b7df1f334fb587bada465b53d9f7b4d4fec964432ee91ead1bc32ed3c82f2167da1c834a37515df7fe130e" "7f41ef68508343ef18813cb2fb332445ec6480cd"))) (test "wycheproof-130 valid" (assert-eq #t (verdict "127d37e406e0d83e4b55a09e21e8f50fb88af47e4a43f018cdebffc1948757f0" "00c11e76b5866b7c37528b0670188c1a0473fb93c33b72ae604a8865a7d6e094ff722e8ede3cb18389685ff3c4086c29006047466f81e71a329711e0b9294709" "e1ce107971534bc46a42ac609a1a37b4ca65791d"))) (test "wycheproof-131 valid" (assert-eq #t (verdict "d83ba84edfb4bec49f29be31d80a64b7c0b5a502438cdb1d0dd1e0e3e55786de" "0a6f0ac47ea136cb3ff00f7a96638e4984048999ee2da0af6e5c86bffb0e70bb97406b6ad5a4b764f7c99ebb6ec0fd434b8efe253b0423ef876c037998e8ab07" "869a827397c585cf35acf88a8728833ab1c8c81e"))) (test "wycheproof-132 valid" (assert-eq #t (verdict "d3c9aa2f3d6ef217a166e8ae403ed436c37facbbe3beceb78df6eb439f8fa04a" "b7cbb942a6661e2312f79548224f3e44f5841c6e880c68340756a00ce94a914e8404858265985e6bb97ef01d2d7e5e41340309606bfc43c8c6a8f925126b3d09" "619d8c4f2c93104be01cd574a385ceca08c33a9e"))) (test "wycheproof-133 valid" (assert-eq #t (verdict "d53280367c1c0b95ac4112218b92c6a71c51fb6312ce668de196c7d52a136155" "27a4f24009e579173ff3064a6eff2a4d20224f8f85fdec982a9cf2e6a3b51537348a1d7851a3a932128a923a393ea84e6b35eb3473c32dceb9d7e9cab03a0f0d" "5257a0bae8326d259a6ce97420c65e6c2794afe2"))) (test "wycheproof-134 valid" (assert-eq #t (verdict "94ac2336ba97a476fb4c9f2b5563e4167ca292c6e99e422350a911ae3172c315" "985b605fe3f449f68081197a68c714da0bfbf6ac2ab9abb0508b6384ea4999cb8d79af98e86f589409e8d2609a8f8bd7e80aaa8d92a84e7737fbe8dcef41920a" "5acb6afc9b368f7acac0e71f6a4831c72d628405"))) (test "wycheproof-135 valid" (assert-eq #t (verdict "e1e7316d231f7f275bdf403360304da1509fdf1af1fd25ca214eaac0a289398f" "1c8fbda3d39e2b441f06da6071c13115cb4115c7c3341704cf6513324d4cf1ef4a1dd7678a048b0dde84e48994d080befcd70854079d44b6a0b0f9fa002d130c" "3c87b3453277b353941591fc7eaa7dd37604b42a"))) (test "wycheproof-136 valid" (assert-eq #t (verdict "fffbeea71215efaf9888fec2cc68edb3703ff11a66fd629b53cbda5eabc18750" "59097233eb141ed948b4f3c28a9496b9a7eca77454ecfe7e46737d1449a0b76b15aacf77cf48af27a668aa4434cfa26c504d75a2bcc4feac46465446234c0508" "0a68e27ef6847bfd9e398b328a0ded3679d4649d"))) (test "wycheproof-137 valid" (assert-eq #t (verdict "19ccc0527599cb032e0b4c4d74e60f13901768a99df041c3bc1bf6c0ef271169" "519105608508fe2f1b6da4cc8b23e39798b1d18d25972beed0404cec722e01ba1b6a0f85e99e092cca8076b101b60d4ac5035684357f4d0daacdc642da742a06" "4e9bef60737c7d4dd10bd52567e1473a36d3573d"))) (test "wycheproof-138 valid" (assert-eq #t (verdict "0e726e27047563aa0a1a9c2e085d8d26af2acba129d0869c65031e3e6cac329a" "d8b03ee579e73f16477527fc9dc37a72eaac0748a733772c483ba013944f01ef64fb4ec5e3a95021dc22f4ae282baff6e9b9cc8433c6b6710d82e7397d72ef04" "cc82b3163efda3ba7e9240e765112caa69113694"))) (test "wycheproof-139 valid" (assert-eq #t (verdict "e77717b54a2b5e5bce5bccb8f0c5fdb5fd7df77ac254020fc9120dc0d4df4178" "26da61fdfd38e6d01792813f27840c8b4766b0faaed39d0ee898cb450d94a5d5f57e58b6a003d7f9b56b20561954c6edcf66492d116b8b5e91f205a3a6449d0b" "923a5c9e7b5635bb6c32c5a408a4a15b652450eb"))) (test "wycheproof-140 valid" (assert-eq #t (verdict "6220972d3f7d150b36790d7d522384876d64d640cd9913186815e1629582ed36" "4adeaff7a58c5010a5a067feea0ae504d37b0c6a76c6c153e222f13409dff2df0fab69bc5059b97d925dc1b89e9851d7c627cb82d65585f9fd976124553f8902" "6f2f0245de4587062979d0422d349f93ccdc3af2"))) (test "wycheproof-141 valid" (assert-eq #t (verdict "7b64a28c50ec7678a90e3e1a21522e30ac9db7b5215aea2bfb33bea037eab987" "4204d620cde0c3008c0b2901f5d6b44f88f0e3cb4f4d62252bf6f3cb37c1fb150a9ccb296afe5e7c75f65b5c8edd13dc4910ffe1e1265b3707c59042cf9a5902" "6e911edb27a170b983d4dee1110554f804330f41"))) (test "wycheproof-142 valid" (assert-eq #t (verdict "724452210a9e4c994819229bf12bf84e95768a3a97c08d8d8f5f939a4cad34c5" "f8a69d3fd8c2ff0a9dec41e4c6b43675ce08366a35e220b1185ffc246c339e22c20ac661e866f52054015efd04f42eca2adcee6834c4df923b4a62576e4dff0e" "b8cf807eea809aaf739aa091f3b7a3f2fd39fb51"))) (test "wycheproof-143 valid" (assert-eq #t (verdict "bad265b294ed2f422cb6a141694086238fbfe987571aa765d8b4f3a24105aa01" "61792c9442bc6338ac41fd42a40bee9b02ec1836503d60ff725128c63d72808880c36e6190b7da525cbee5d12900aa043547dd14a2709ef9e49d628f37f6b70c" "01a2b5f7fee813b4e9bd7fc25137648004795010"))) (test "wycheproof-144 valid" (assert-eq #t (verdict "0aaee4b723db9b51ba7d22eb23eb8a76a5ac02f4fc9dd06f77bea42e1d37ec5a" "fa3cd41e3a8c00b19eecd404a63c3cb787cd30de0dfc936966cff2117f5aff18db6bef80fcfd8856f3fb2e9c3dc47593e9471103032af918feee638a33d40505" "0fbf5d47cb5d498feace8f98f1896208da38a885"))) (test "wycheproof-145 valid" (assert-eq #t (verdict "812344af15a91ba83c2c91e96f1727ac0f3c4c41385b9fa84efa399ada5168be" "97fbbcd7a1d0eb42d2f8c42448ef35a2c2472740556b645547865330d6c57068af377fced08aaf810c08cd3c43d296f1975710312e9334c98b485f831efa4103" "36e67c1939750bffb3e4ba6cb85562612275e862"))) (test "wycheproof-146 valid" (assert-eq #t (verdict "0ee5cb5597fbdf8dccc48b01485e39b33aa133b52d30d23740277267cfec3e3e" "d7dbaa337ffd2a5fd8d5fd8ad5aeccc0c0f83795c2c59fe62a40b87903b1ae62ed748a8df5af4d32f9f822a65d0e498b6f40eaf369a9342a1164ee7d08b58103" "13945c894c1d3fe8562e8b20e5f0efaa26ade8e3"))) (test "wycheproof-147 valid" (assert-eq #t (verdict "9fba1de92b60b5b4703089763d0d6f9125e4dd7efae41f08a22882aef96892c4" "09a2ed303a2fa7027a1dd7c3b0d25121eeed2b644a2fbc17aa0c8aea4524071ede7e7dd7a536d5497f8165d29e4e1b63200f74bbae39fbbbccb29889c62c1f09" "4de142af4b8402f80a47fa812df84f42e283cee7"))) (test "wycheproof-148 valid" (assert-eq #t (verdict "7582ab1b52e1316e5c13671f43b39ca36b28133cd0832831bcddd0b0f23398cb" "e6884a6e6b2e60a0b5862251c001e7c79d581d777d6fc11d218d0aecd79f26a30e2ca22cc7c4674f8b72655bc4ee5cb5494ca07c05177656142ac55cc9d33e02" "563357f41b8b23b1d83f19f5667177a67da20b18"))) (test "wycheproof-149 valid" (assert-eq #t (verdict "dd2d678bae222f3fb6e8278f08cc9e1a66339c926c29ac0a16f9717f5ee18cd8" "6124c206d864507ea5d984b363b4cf583314db6856a45ded5e61eebff4d5e337e0b4c82b445ae2e52d549d2d961eace2ea01f81158e09a9686baa040db65ad08" "931bbf9c877a6571cf7d4609fc3eb867edd43f51"))) (test "wycheproof-150 valid" (assert-eq #t (verdict "ccbe7cb2e4bc215cee2f885e1d22f7e0d582b2bbbd782c104e548b152d26fc69" "cfbd450a2c83cb8436c348822fe3ee347d4ee937b7f2ea11ed755cc52852407c9eec2c1fa30d2f9aef90e89b2cc3bcef2b1b9ca59f712110d19894a9cf6a2802" "44530b0b34f598767a7b875b0caee3c7b9c502d1"))) (test "wycheproof-151 invalid" (assert-eq #f (verdict "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a" "0100000000000000000000000000000000000000000000000000000000000080c803ee1f2342aa96ff698a393d1ab5e66f3eda101d6d120b394c3fd32c117d0a" "313233343030"))) (test "speccheck-0 invalid" (assert-eq #f (verdict "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa" "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000" "8c93255d71dcab10e8f379c26200f3c7bd5f09d9bc3068d3ef4edeb4853022b6"))) (test "speccheck-1 invalid" (assert-eq #f (verdict "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa" "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43a5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04" "9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79"))) (test "speccheck-2 invalid" (assert-eq #f (verdict "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43" "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8c4bd45aecaca5b24fb97bc10ac27ac8751a7dfe1baff8b953ec9f5833ca260e" "aebf3f2601a0c8c5d39cc7d8911642f740b78168218da8471772b35f9d35b9ab"))) (test "speccheck-3 valid" (assert-eq #t (verdict "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d" "9046a64750444938de19f227bb80485e92b83fdb4b6506c160484c016cc1852f87909e14428a7a1d62e9f22f3d3ad7802db02eb2e688b6c52fcd6648a98bd009" "9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79"))) (test "speccheck-4 valid" (assert-eq #t (verdict "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d" "160a1cb0dc9c0258cd0a7d23e94d8fa878bcb1925f2c64246b2dee1796bed5125ec6bc982a269b723e0668e540911a9a6a58921d6925e434ab10aa7940551a09" "e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c"))) (test "speccheck-5 valid" (assert-eq #t (verdict "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d" "21122a84e0b5fca4052f5b1235c80a537878b38f3142356b2c2384ebad4668b7e40bc836dac0f71076f9abe3a53f9c03c1ceeeddb658d0030494ace586687405" "e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c"))) (test "speccheck-6 invalid" (assert-eq #f (verdict "442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623" "e96f66be976d82e60150baecff9906684aebb1ef181f67a7189ac78ea23b6c0e547f7690a0e2ddcd04d87dbc3490dc19b3b3052f7ff0538cb68afb369ba3a514" "85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40"))) (test "speccheck-7 invalid" (assert-eq #f (verdict "442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623" "8ce5b96c8f26d0ab6c47958c9e68b937104cd36e13c33566acd2fe8d38aa19427e71f98a473474f2f13f06f97c20d58cc3f54b8bd0d272f42b695dd7e89a8c22" "85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40"))) (test "speccheck-8 invalid" (assert-eq #f (verdict "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43" "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f" "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41"))) (test "speccheck-9 invalid" (assert-eq #f (verdict "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43" "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908" "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41"))) (test "speccheck-10 invalid" (assert-eq #f (verdict "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04" "e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b"))) (test "speccheck-11 invalid" (assert-eq #f (verdict "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04" "39a591f5321bbe07fd5a23dc2f39d025d74526615746727ceefd6e82ae65c06f"))) );;; 168 casestest/test-ed25519.sgladded
;;; Ed25519 (RFC 8032) and BLAKE2b-512 in (sigil crypto).;;;;;; The bulk vector sets (RFC 8032, Wycheproof, ed25519-speccheck) are in;;; test-ed25519-vectors.sgl. This file holds the RFC 8032 key derivation and;;; signing checks, the negative cases built from a valid signature with one;;; controlled change, and BLAKE2b-512.(import (sigil test) (sigil crypto) (sigil math))(define (hex->bv s) (let* ((n (quotient (string-length s) 2)) (bv (make-bytevector n 0))) (let loop ((i 0)) (if (< i n) (begin (bytevector-u8-set! bv i (string->number (substring s (* 2 i) (+ 2 (* 2 i))) 16)) (loop (+ i 1))) bv))))(define (bv->hex bv) (let loop ((i 0) (acc '())) (if (< i (bytevector-length bv)) (let* ((b (bytevector-u8-ref bv i)) (h (number->string b 16))) (loop (+ i 1) (cons (if (< b 16) (string-append "0" h) h) acc))) (apply string-append (reverse acc)))));; A copy of bv with bit `bit` of byte `index` flipped.(define (flip-bit bv index bit) (let ((out (bytevector-copy bv))) (bytevector-u8-set! out index (bitwise-xor (bytevector-u8-ref out index) (arithmetic-shift 1 bit))) out));; RFC 8032 section 7.1, TEST 1 to TEST 3.(define t1-seed (hex->bv "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"))(define t1-pk (hex->bv "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"))(define t1-msg (make-bytevector 0 0))(define t1-sig (hex->bv "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"))(define t2-seed (hex->bv "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb"))(define t2-pk (hex->bv "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c"))(define t2-msg (hex->bv "72"))(define t2-sig (hex->bv "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00"))(define t3-seed (hex->bv "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7"))(define t3-pk (hex->bv "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025"))(define t3-msg (hex->bv "af82"))(define t3-sig (hex->bv "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a"));; TEST 1's signature with S replaced by S + L (L = 2^252 +;; 27742317777372353535851937790883648493, the group order), computed with;; Python integers. [S + L]B = [S]B, so this satisfies the verification;; equation; only the S < L range check can reject it.(define t1-sig-s-plus-l (hex->bv (string-append "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155" "4c8c7872aa064e049dbb3013fbf29380d25bf5f0595bbe24655141438e7a101b")))(test-group "ed25519 RFC 8032 derivation and signing" (test "TEST 1 public key from seed" (assert-equal (bv->hex t1-pk) (bv->hex (ed25519-public-key t1-seed)))) (test "TEST 2 public key from seed" (assert-equal (bv->hex t2-pk) (bv->hex (ed25519-public-key t2-seed)))) (test "TEST 3 public key from seed" (assert-equal (bv->hex t3-pk) (bv->hex (ed25519-public-key t3-seed)))) (test "TEST 1 signature is the RFC's" (assert-equal (bv->hex t1-sig) (bv->hex (ed25519-sign t1-seed t1-msg)))) (test "TEST 2 signature is the RFC's" (assert-equal (bv->hex t2-sig) (bv->hex (ed25519-sign t2-seed t2-msg)))) (test "TEST 3 signature is the RFC's" (assert-equal (bv->hex t3-sig) (bv->hex (ed25519-sign t3-seed t3-msg)))) (test "the seed bytevector is not wiped by derivation or signing" (let ((seed (bytevector-copy t2-seed))) (ed25519-public-key seed) (ed25519-sign seed "x") (assert-equal (bv->hex t2-seed) (bv->hex seed)))) (test "a string message signs its UTF-8 bytes" (assert-equal (bv->hex (ed25519-sign t2-seed (bytevector 104 105))) (bv->hex (ed25519-sign t2-seed "hi")))))(test-group "ed25519 verify: controls" (test "TEST 1 verifies" (assert-eq #t (ed25519-verify t1-pk t1-msg t1-sig))) (test "TEST 2 verifies" (assert-eq #t (ed25519-verify t2-pk t2-msg t2-sig))) (test "TEST 3 verifies" (assert-eq #t (ed25519-verify t3-pk t3-msg t3-sig))) (test "a sign/verify round trip with a string message" (let ((sig (ed25519-sign t3-seed "round trip"))) (assert-eq #t (ed25519-verify t3-pk "round trip" sig)))));; Each negative below changes ONE input of a signature the control group;; shows verifying, so the change is the only possible cause of the #f.(test-group "ed25519 verify: negatives" (test "every single-bit flip of TEST 2's message fails" (let loop ((bit 0)) (when (< bit 8) (assert-eq #f (ed25519-verify t2-pk (flip-bit t2-msg 0 bit) t2-sig)) (loop (+ bit 1))))) (test "a flipped bit in each byte of TEST 3's signature fails" (let loop ((i 0)) (when (< i 64) (assert-eq #f (ed25519-verify t3-pk t3-msg (flip-bit t3-sig i (modulo i 8)))) (loop (+ i 1))))) (test "a flipped bit in each byte of TEST 3's public key fails" (let loop ((i 0)) (when (< i 32) (assert-eq #f (ed25519-verify (flip-bit t3-pk i (modulo i 8)) t3-msg t3-sig)) (loop (+ i 1))))) (test "a signature under another key fails" (assert-eq #f (ed25519-verify t2-pk t3-msg t3-sig))) (test "an extra trailing message byte fails" (assert-eq #f (ed25519-verify t3-pk (hex->bv "af8200") t3-sig))) (test "S + L (non-canonical S) fails although the equation holds" (assert-eq #f (ed25519-verify t1-pk t1-msg t1-sig-s-plus-l))) (test "the all-zero signature fails" (assert-eq #f (ed25519-verify t1-pk t1-msg (make-bytevector 64 0)))) (test "the identity public key fails for any signature" ;; Identity (order 1) as A: [8](sB - hA - R) = [8](sB - R), so a ;; cofactored check alone would accept R = [s]B for any message. ;; With R = B (the base point) and S = 1: [8]([1]B - h*O - B) = O for ;; every message, so only the small-order check on A can reject it. (let* ((identity (let ((b (make-bytevector 32 0))) (bytevector-u8-set! b 0 1) b)) (base-point (hex->bv "5866666666666666666666666666666666666666666666666666666666666666")) (one (let ((b (make-bytevector 32 0))) (bytevector-u8-set! b 0 1) b)) (forged (bytevector-append base-point one))) (assert-eq #f (ed25519-verify identity "anything" forged)) (assert-eq #f (ed25519-verify identity "anything else" forged)))))(test-group "ed25519 verify: argument checking" (test "a 31-byte public key raises" (assert-error (ed25519-verify (make-bytevector 31 0) "m" t1-sig))) (test "a 65-byte signature raises" (assert-error (ed25519-verify t1-pk "m" (make-bytevector 65 0)))) (test "a string public key raises" (assert-error (ed25519-verify "not a key" "m" t1-sig))) (test "a 16-byte seed raises" (assert-error (ed25519-sign (make-bytevector 16 0) "m"))))(test-group "blake2b-512" (test "RFC 7693 appendix A: abc" (assert-equal "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923" (bv->hex (blake2b-512 "abc")))) (test "empty input (coreutils b2sum)" (assert-equal "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce" (bv->hex (blake2b-512 (make-bytevector 0 0))))) (test "1000 x 'a', more than one 128-byte block (coreutils b2sum)" (assert-equal "d6a69459fe93fc6b9537ed4336e5099e0dcca3e97290a412500ed7a0daffb03d80cf3650a20e0591f748e10c3c534945ee83d5f2c9722f1a68d98b8c01af23fd" (bv->hex (blake2b-512 (make-bytevector 1000 97))))) (test "string and bytevector input agree" (assert-equal (bv->hex (blake2b-512 "abc")) (bv->hex (blake2b-512 (bytevector 97 98 99))))))test/test-minisign.sgladded
;;; (sigil crypto minisign) against signatures made by the real minisign.;;;;;; Fixtures live in test/fixtures/minisign and were made by;;; make-fixtures.sh with minisign 0.12, which also checked every one with;;; `minisign -V` before keeping it. Two come from other people's keys:;;; production registry.json under the Sigil registry root key, and the;;; minisign 0.12 source tarball under the minisign author's key.;;;;;; Every negative asserts the reason `minisign-failure-reason` gives, so a test;;; cannot pass because verification failed for some other cause.(import (sigil test) (sigil crypto) (sigil crypto minisign) (sigil fs) (sigil io) (sigil math) (sigil string))(define fixture-dir "test/fixtures/minisign/")(define (fixture name) (read-file-bytes (string-append fixture-dir name)))(define (fixture-text name) (utf8->string (fixture name)))(define (nth lst k) (if (= k 0) (car lst) (nth (cdr lst) (- k 1))))(define root-key-line "RWRa9dPSUBFexBbLdzZIfuAmuCYL736UeHC7IbdAOIYpgGIyDmWRaQHY")(define minisign-author-key-line "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3")(define key-a (minisign-parse-public-key (fixture "a.pub")))(define key-b (minisign-parse-public-key (fixture "b.pub")))(define root-key (minisign-parse-public-key root-key-line))(define author-key (minisign-parse-public-key minisign-author-key-line))(define (sig name) (minisign-parse-signature (fixture name)));; The lines of a text fixture, and a way to rebuild it with one changed.(define (lines-of name) (string-split (fixture-text name) "\n"))(define (join-lines lines) (string-join lines "\n"))(define (with-line lines index new) (let loop ((i 0) (ls lines) (acc '())) (if (null? ls) (reverse acc) (loop (+ i 1) (cdr ls) (cons (if (= i index) new (car ls)) acc)))));; Replace the character at `index` of `s` with `c`.(define (string-with-char s index c) (string-append (substring s 0 index) (string c) (substring s (+ index 1) (string-length s))));; A different base64 alphabet character than `c`.(define (other-b64-char c) (if (char=? c #\A) #\B #\A))(define (flip-byte bv index) (let ((out (bytevector-copy bv))) (bytevector-u8-set! out index (bitwise-xor (bytevector-u8-ref out index) 1)) out));; Rebuild a signature file's second line with bytes [start, end) of the;; decoded signature replaced by `new-bytes`.(define (resign-line line start new-bytes) (let* ((raw (base64-decode line)) (out (bytevector-copy raw))) (let loop ((i 0)) (when (< i (bytevector-length new-bytes)) (bytevector-u8-set! out (+ start i) (bytevector-u8-ref new-bytes i)) (loop (+ i 1)))) (base64-encode out)));; #t when thunk raises an error whose message contains `needle`.(define (raises-with? needle thunk) (guard (e (#t (and (error-object? e) (string-contains? (error-object-message e) needle)))) (thunk) #f))(define (raises? thunk) (guard (e (#t #t)) (thunk) #f))(test-group "minisign fixtures are present" ;; Presence probe with a positive answer: an empty or missing fixture ;; directory must fail here, not quietly weaken the tests below. (test "hello.txt reads back" (assert-equal "hello, minisign\n" (fixture-text "hello.txt"))) (test "binary.bin is all 1024 bytes" (assert-equal 1024 (bytevector-length (fixture "binary.bin")))))(test-group "minisign public keys" (test "a .pub file parses and its id matches the file's comment" (let* ((first-line (car (lines-of "a.pub"))) (id (substring first-line (- (string-length first-line) 16) (string-length first-line)))) (assert-equal id (minisign-public-key-id key-a)))) (test "the bare base64 line parses to the same key" (let ((bare (minisign-parse-public-key (cadr (lines-of "a.pub"))))) (assert-equal (minisign-public-key-id key-a) (minisign-public-key-id bare)) (assert-equal (minisign-public-key-bytes key-a) (minisign-public-key-bytes bare)))) (test "the registry root key has the id registry.json lists" (assert-equal "C45E1150D2D3F55A" (minisign-public-key-id root-key))) (test "public key bytes are 32 bytes" (assert-equal 32 (bytevector-length (minisign-public-key-bytes key-a)))) (test "a key line one character short raises (length)" (assert-true (raises-with? "wrong base64 length" (lambda () (minisign-parse-public-key (substring root-key-line 0 55)))))) (test "a key line with a character outside base64 raises" (assert-true (raises-with? "character outside base64" (lambda () (minisign-parse-public-key (string-with-char root-key-line 20 #\!)))))) (test "a key whose algorithm is not Ed raises" ;; "RW" starts the base64 of "Ed"; "RX" makes the algorithm "Et". (assert-true (raises-with? "algorithm is not Ed" (lambda () (minisign-parse-public-key (string-with-char root-key-line 1 #\X)))))) (test "three non-blank lines raise" (assert-true (raises-with? "must be one base64 line" (lambda () (minisign-parse-public-key (string-append (fixture-text "a.pub") root-key-line "\n")))))) (test "an empty string raises" (assert-true (raises-with? "must be one base64 line" (lambda () (minisign-parse-public-key ""))))))(test-group "minisign signature parsing" (test "ED is prehashed" (assert-eq 'prehashed (minisign-signature-algorithm (sig "hello.txt.ED.minisig")))) (test "Ed is legacy" (assert-eq 'legacy (minisign-signature-algorithm (sig "hello.txt.Ed.minisig")))) (test "the signature names key a" (assert-equal (minisign-public-key-id key-a) (minisign-signature-key-id (sig "hello.txt.ED.minisig")))) (test "fewer than four lines raise" (let ((ls (lines-of "hello.txt.ED.minisig"))) (assert-true (raises-with? "fewer than four lines" (lambda () (minisign-parse-signature (join-lines (list (car ls) (cadr ls) (caddr ls))))))))) (test "a first line without the untrusted prefix raises" (let ((ls (lines-of "hello.txt.ED.minisig"))) (assert-true (raises-with? "first line must start with" (lambda () (minisign-parse-signature (join-lines (with-line ls 0 "comment: x")))))))) (test "a third line without the trusted prefix raises" (let ((ls (lines-of "hello.txt.ED.minisig"))) (assert-true (raises-with? "third line must start with" (lambda () (minisign-parse-signature (join-lines (with-line ls 2 "trusted: x")))))))) (test "content after the global signature raises" (assert-true (raises-with? "content after the global signature" (lambda () (minisign-parse-signature (string-append (fixture-text "hello.txt.ED.minisig") "extra\n")))))) (test "a CR inside the trusted comment raises" (let ((ls (lines-of "hello.txt.ED.minisig"))) (assert-true (raises-with? "trusted comment contains a CR or NUL" (lambda () (minisign-parse-signature (join-lines (with-line ls 2 (string-append "trusted comment: a" (string #\return) "b"))))))))) (test "an unsupported algorithm raises" ;; "RU" starts the base64 of "ED"; "RV" makes ;; the second byte T, so the algorithm reads "ET". (let* ((ls (lines-of "hello.txt.ED.minisig")) (line (cadr ls))) (assert-true (raises-with? "unsupported signature algorithm" (lambda () (minisign-parse-signature (join-lines (with-line ls 1 (string-with-char line 1 #\V))))))))) (test "non-zero base64 pad bits raise" ;; The 74-byte signature ends in one '='; its last data character ;; carries 2 pad bits. Setting them keeps the alphabet valid. (let* ((ls (lines-of "hello.txt.ED.minisig")) (line (cadr ls)) (last-data (string-ref line 98)) (bumped (integer->char (+ 1 (char->integer last-data))))) (assert-true (raises-with? "non-canonical base64 padding" (lambda () (minisign-parse-signature (join-lines (with-line ls 1 (string-with-char line 98 bumped))))))))))(test-group "minisign verification: signatures made by minisign" (test "prehashed ED over a text file" (assert-equal "sigil-crypto fixture: prehashed" (minisign-verify key-a (sig "hello.txt.ED.minisig") (fixture "hello.txt")))) (test "legacy Ed over a text file" (assert-equal "sigil-crypto fixture: legacy" (minisign-verify key-a (sig "hello.txt.Ed.minisig") (fixture "hello.txt")))) (test "prehashed ED over an empty file" (assert-equal "sigil-crypto fixture: empty file" (minisign-verify key-a (sig "empty.txt.ED.minisig") (fixture "empty.txt")))) (test "prehashed ED over every byte value" (assert-equal "sigil-crypto fixture: binary" (minisign-verify key-a (sig "binary.bin.ED.minisig") (fixture "binary.bin")))) (test "legacy Ed over every byte value" (assert-equal "sigil-crypto fixture: binary legacy" (minisign-verify key-a (sig "binary.bin.Ed.minisig") (fixture "binary.bin")))) (test "a UTF-8 trusted comment comes back intact" (assert-equal "fixture ✓ unicode — trusted" (minisign-verify key-a (sig "hello.txt.unicode.minisig") (fixture "hello.txt")))) (test "a string message verifies like its bytes" (assert-equal "sigil-crypto fixture: prehashed" (minisign-verify key-a (sig "hello.txt.ED.minisig") "hello, minisign\n"))) (test "a signature file with CRLF line endings verifies" (let ((crlf (string-join (lines-of "hello.txt.ED.minisig") (string #\return #\newline)))) (assert-equal "sigil-crypto fixture: prehashed" (minisign-verify key-a (minisign-parse-signature crlf) (fixture "hello.txt"))))) (test "minisign-verify-prehashed accepts ED" (assert-equal "sigil-crypto fixture: prehashed" (minisign-verify-prehashed key-a (sig "hello.txt.ED.minisig") (fixture "hello.txt")))))(test-group "minisign verification: real published signatures" (test "production registry.json under the registry root key" (assert-equal "registry=pkg.usesigil.org path=/v1/meta/registry.json seq=1 ts=2026-07-30T08:04:54Z" (minisign-verify-prehashed root-key (sig "registry.json.minisig") (fixture "registry.json")))) (test "minisign 0.12's source tarball under the minisign author's key" (assert-true (string? (minisign-verify author-key (sig "minisign-0.12.tar.gz.minisig") (fixture "minisign-0.12.tar.gz"))))) (test "a one-bit change to registry.json is a bad signature" (assert-eq 'bad-signature (minisign-failure-reason root-key (sig "registry.json.minisig") (flip-byte (fixture "registry.json") 100) #t))) (test "a one-bit change to the tarball is a bad signature" (assert-eq 'bad-signature (minisign-failure-reason author-key (sig "minisign-0.12.tar.gz.minisig") (flip-byte (fixture "minisign-0.12.tar.gz") 10000) #f))) (test "registry.json.minisig does not verify under a fixture key" (assert-eq 'key-id-mismatch (minisign-failure-reason key-a (sig "registry.json.minisig") (fixture "registry.json") #f))))(test-group "minisign verification: negatives, each with its reason" (test "valid control: no failure reason" (assert-eq #f (minisign-failure-reason key-a (sig "hello.txt.ED.minisig") (fixture "hello.txt") #f))) (test "tampered message, prehashed" (assert-eq 'bad-signature (minisign-failure-reason key-a (sig "hello.txt.ED.minisig") "hello, minisigN\n" #f))) (test "tampered message, legacy" (assert-eq 'bad-signature (minisign-failure-reason key-a (sig "hello.txt.Ed.minisig") "hello, minisigN\n" #f))) (test "tampered binary message, every 64th byte" (let loop ((i 0)) (when (< i 1024) (assert-eq 'bad-signature (minisign-failure-reason key-a (sig "binary.bin.ED.minisig") (flip-byte (fixture "binary.bin") i) #f)) (loop (+ i 64))))) (test "a message with one extra byte" (assert-eq 'bad-signature (minisign-failure-reason key-a (sig "hello.txt.ED.minisig") "hello, minisign\n\n" #f))) (test "the right signature for a different file" (assert-eq 'bad-signature (minisign-failure-reason key-a (sig "empty.txt.ED.minisig") (fixture "hello.txt") #f))) (test "tampered trusted comment" (let ((ls (lines-of "hello.txt.ED.minisig"))) (assert-eq 'bad-trusted-comment-signature (minisign-failure-reason key-a (minisign-parse-signature (join-lines (with-line ls 2 "trusted comment: sigil-crypto fixture: prehashed!"))) (fixture "hello.txt") #f)))) (test "a trusted comment moved from another valid signature" ;; Both signatures are genuine; splicing one's comment onto the other ;; must fail the global signature. (let ((ls (lines-of "hello.txt.ED.minisig")) (other (lines-of "empty.txt.ED.minisig"))) (assert-eq 'bad-trusted-comment-signature (minisign-failure-reason key-a (minisign-parse-signature (join-lines (with-line (with-line ls 2 (caddr other)) 3 (nth other 3)))) (fixture "hello.txt") #f)))) (test "tampered signature bytes" (let* ((ls (lines-of "hello.txt.ED.minisig")) (line (cadr ls))) (assert-eq 'bad-signature (minisign-failure-reason key-a (minisign-parse-signature (join-lines (with-line ls 1 (string-with-char line 50 (other-b64-char (string-ref line 50)))))) (fixture "hello.txt") #f)))) (test "tampered global signature bytes" (let* ((ls (lines-of "hello.txt.ED.minisig")) (line (nth ls 3))) (assert-eq 'bad-trusted-comment-signature (minisign-failure-reason key-a (minisign-parse-signature (join-lines (with-line ls 3 (string-with-char line 40 (other-b64-char (string-ref line 40)))))) (fixture "hello.txt") #f)))) (test "a signature by key b checked with key a" (assert-eq 'key-id-mismatch (minisign-failure-reason key-a (sig "hello.txt.keyb.minisig") (fixture "hello.txt") #f))) (test "key b's signature relabelled with key a's id is still refused" ;; The key id is not authentication: with the id matching, the ;; Ed25519 check is what rejects it. (let* ((ls (lines-of "hello.txt.keyb.minisig")) (a-id (bytevector-copy (base64-decode (cadr (lines-of "hello.txt.ED.minisig"))) 2 10)) (relabelled (resign-line (cadr ls) 2 a-id))) (assert-eq 'bad-signature (minisign-failure-reason key-a (minisign-parse-signature (join-lines (with-line ls 1 relabelled))) (fixture "hello.txt") #f)))) (test "legacy refused when prehashed is required" (assert-eq 'legacy-refused (minisign-failure-reason key-a (sig "hello.txt.Ed.minisig") (fixture "hello.txt") #t))) (test "minisign-verify-prehashed returns #f for a valid legacy signature" (assert-false (minisign-verify-prehashed key-a (sig "hello.txt.Ed.minisig") (fixture "hello.txt")))) (test "a legacy signature relabelled as prehashed fails" ;; Changing Ed to ED makes the verifier hash first, so the same ;; Ed25519 signature no longer matches: the algorithm is bound. (let* ((ls (lines-of "hello.txt.Ed.minisig")) (relabelled (resign-line (cadr ls) 0 (bytevector 69 68)))) (assert-eq 'bad-signature (minisign-failure-reason key-a (minisign-parse-signature (join-lines (with-line ls 1 relabelled))) (fixture "hello.txt") #f)))) (test "minisign-verify returns #f, not a comment, on failure" (assert-false (minisign-verify key-a (sig "hello.txt.ED.minisig") "tampered"))))(test-group "minisign argument checking" (test "minisign-failure-reason refuses an unparsed key" (assert-true (raises-with? "not a parsed public key" (lambda () (minisign-failure-reason root-key-line (sig "hello.txt.ED.minisig") "x" #f))))) (test "minisign-failure-reason refuses an unparsed signature" (assert-true (raises-with? "not a parsed signature" (lambda () (minisign-failure-reason key-a (fixture-text "hello.txt.ED.minisig") "x" #f))))))test/vectors/ed25519-cases.txtadded
rfc8032-1 d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b - validrfc8032-2 3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c 92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00 72 validrfc8032-3 fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025 6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a af82 validrfc8032-1024 278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0 validrfc8032-SHAabc ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f validwycheproof-1 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa d4fbdb52bfa726b44d1786a8c0d171c3e62ca83c9e5bbe63de0bb2483f8fd6cc1429ab72cafc41ab56af02ff8fcc43b99bfe4c7ae940f60f38ebaa9d311c4007 - validwycheproof-2 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa d80737358ede548acb173ef7e0399f83392fe8125b2ce877de7975d8b726ef5b1e76632280ee38afad12125ea44b961bf92f1178c9fa819d020869975bcbe109 78 validwycheproof-3 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d 54657374 validwycheproof-4 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 1c1ad976cbaae3b31dee07971cf92c928ce2091a85f5899f5e11ecec90fc9f8e93df18c5037ec9b29c07195ad284e63d548cd0a6fe358cc775bd6c1608d2c905 48656c6c6f validwycheproof-5 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bf0cf5b3a289976458a1be6277a5055545253b45b07dcc1abd96c8b989c00f301 313233343030 validwycheproof-6 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa d46543bfb892f84ec124dcdfc847034c19363bf3fc2fa89b1267833a14856e52e60736918783f950b6f1dd8d40dc343247cd43ce054c2d68ef974f7ed0f3c60f 000000000000000000000000 validwycheproof-7 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 879350045543bc14ed2c08939b68c30d22251d83e018cacbaf0c9d7a48db577e80bdf76ce99e5926762bc13b7b3483260a5ef63d07e34b58eb9c14621ac92f00 6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 validwycheproof-8 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7bdc3f9919a05f1d5db4a3ada896094f6871c1f37afc75db82ec3147d84d6f237b7e5ecc26b59cfea0c7eaf1052dc427b0f724615be9c3d3e01356c65b9b5109 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60 validwycheproof-9 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 5dbd7360e55aa38e855d6ad48c34bd35b7871628508906861a7c4776765ed7d1e13d910faabd689ec8618b78295c8ab8f0e19c8b4b43eb8685778499e943ae04 ffffffffffffffffffffffffffffffff validwycheproof-10 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 3f invalidwycheproof-11 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000 3f invalidwycheproof-12 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 0000000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010 3f invalidwycheproof-13 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 0000000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010 3f invalidwycheproof-14 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 0000000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f 3f invalidwycheproof-15 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 3f invalidwycheproof-16 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 01000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000 3f invalidwycheproof-17 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 0100000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010 3f invalidwycheproof-18 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 0100000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010 3f invalidwycheproof-19 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 0100000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f 3f invalidwycheproof-20 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000 3f invalidwycheproof-21 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000000 3f invalidwycheproof-22 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010 3f invalidwycheproof-23 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010 3f invalidwycheproof-24 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f 3f invalidwycheproof-25 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000 3f invalidwycheproof-26 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0100000000000000000000000000000000000000000000000000000000000000 3f invalidwycheproof-27 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010 3f invalidwycheproof-28 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010 3f invalidwycheproof-29 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f 3f invalidwycheproof-30 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 54657374 invalidwycheproof-31 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0 54657374 invalidwycheproof-32 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946 54657374 invalidwycheproof-33 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d2020 54657374 invalidwycheproof-34 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 54657374 invalidwycheproof-35 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 007c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d 54657374 invalidwycheproof-36 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0007a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d 54657374 invalidwycheproof-37 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d00 54657374 invalidwycheproof-38 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 93de3ca252426c95f735cb9edd92e83321ac62372d5aa5b379786bae111ab6b17251330e8f9a7c30d6993137c596007d7b001409287535ac4804e662bc58a3 546573743137 invalidwycheproof-39 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa dffed33a7f420b62bb1731cfd03be805affd18a281ec02b1067ba6e9d20826569e742347df59c88ae96db1f1969fb189b0ec34381d85633e1889da48d95e0e 54657374313236 invalidwycheproof-40 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 6e170c719577c25e0e1e8b8aa7a6346f8b109f37385cc2e85dc3b4c0f46a9c6bcafd67f52324c5dbaf40a1b673fb29c4a56052d2d6999d0838a8337bccb502 546573743530 invalidwycheproof-41 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa b0928b46e99fbbad3f5cb502d2cd309d94a7e86cfd4d84b1fcf4cea18075a9c36993c0582dba1e9e519fae5a8654f454201ae0c3cb397c37b8f4f8eef18400 54657374333437 invalidwycheproof-42 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 647c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b1d125e5538f38afbcc1c84e489521083041d24bc6240767029da063271a1ff0c 313233343030 invalidwycheproof-43 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 677c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bc108ca4b87a49c9ed2cf383aecad8f54a962b2899da891e12004d7993a627e01 313233343030 invalidwycheproof-44 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 617c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b9ce23fc6213ed5b87912e9bbf92f5e2c780eae26d15c50a112d1e97d2ea33c06 313233343030 invalidwycheproof-45 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa e57c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bbb3eb51cd98dddb235a5f46f2bded6af184a58d09cce928bda43f41d69118a03 313233343030 invalidwycheproof-46 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657d1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcd237dda9a116501f67a5705a854b9adc304f34720803a91b324f2c13e0f5a09 313233343030 invalidwycheproof-47 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1592402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b6b167bbdc0d881cc04d28905552c1876f3709851abc5007376940cc8a435c300 313233343030 invalidwycheproof-48 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1412402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7fd2ac7da14afffcceeb13f2a0d6b887941cb1a5eb57a52f3cb131a16cce7b0e 313233343030 invalidwycheproof-49 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492412ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7373ba13ebbef99cd2a8ead55ce735c987d85a35320925a8e871702dc7c5c40d 313233343030 invalidwycheproof-50 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab54e03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bd35bd331c03f0855504ca1cab87b83c36a028425a3cf007ede4f4254c261cb00 313233343030 invalidwycheproof-51 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce02e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcb35101f73cf467deac8c1a03b6c3dc35af544132734b7e57ab20c89b2e4750d 313233343030 invalidwycheproof-52 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce03e2c3a7f2384d051b9cf3570f1207fc78c1bcc98c281c2bb58d2e8878290bff8d3355fdd4ea381924ee578752354eb6dee678ab4011c301 313233343030 invalidwycheproof-53 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce03e2c3a7f0384d851b9cf3570f1207fc78c1bcc98c281c2bb978c866187ffb1cc7b29a0b4045aefc08768df65717194ff0c6e63f4dea0d02 313233343030 invalidwycheproof-54 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281d2b0576ecf8eaf675f00f3dfbe19f75b83b7607a6c96414f6821af920a2498d0305 313233343030 invalidwycheproof-55 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c289c2be5241a345c7b5428054c74b7c382fa10d4a5f1e8f8b79a71d3fdea2254f1ff0e 313233343030 invalidwycheproof-56 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2a63950c85cd6dc96364e768de50ff7732b538f8a0b1615d799190ab600849230e 313233343030 invalidwycheproof-57 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c0b543bd3da0a56a8c9c152f59c9fec12f31fa66434d48b817b30d90cb4efa8b501 313233343030 invalidwycheproof-58 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c6b8da07efd07a6dafb015ed6a32fe136319a972ffbc341f3a0beae97ccf8136505 313233343030 invalidwycheproof-59 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281cab227aedf259f910f0f3a759a335062665217925d019173b88917eae294f75d40f 313233343030 invalidwycheproof-60 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 0000000000000000000000000000000000000000000000000000000000000000e0b8e7770d51c7a36375d006c5bffd6af43ff54aaf47e4330dc118c71d61ec02 313233343030 invalidwycheproof-61 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff463a1908382e7eb7693acef9884f7cf931a215e0791876be22c631a59881fd0e 313233343030 invalidwycheproof-62 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 9a83eb6dbfd54a31fc1d3c580fc7b2fae4630ca8f0edf803873e433673d7e3d40e94254586cb6188c5386c3febed477cb9a6cb29e3979adc4cb27cf5278fb70a 313233343030 invalidwycheproof-63 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab067654bce3832c2d76f8f6f5dafc08d9339d4eef676573336a5c51eb6f946b31d 54657374 invalidwycheproof-64 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab05439412b5395d42f462c67008eba6ca839d4eef676573336a5c51eb6f946b32d 54657374 invalidwycheproof-65 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab02ee12ce5875bf9dff26556464bae2ad239d4eef676573336a5c51eb6f946b34d 54657374 invalidwycheproof-66 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0e2300459f1e742404cd934d2c595a6253ad4eef676573336a5c51eb6f946b38d 54657374 invalidwycheproof-67 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b32d 54657374 invalidwycheproof-68 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b34d 54657374 invalidwycheproof-69 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d 54657374 invalidwycheproof-70 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0679155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d 54657374 invalidwycheproof-71 a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c 5056325d2ab440bf30bbf0f7173199aa8b4e6fbc091cf3eb6bc6cf87cd73d992ffc216c85e4ab5b8a0bbc7e9a6e9f8d33b7f6e5ac0ffdc22d9fcaf784af84302 - validwycheproof-72 a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c 481fafbf4364d7b682475282f517a3ac0538c9a6b6a562e99a3d8e5afb4f90a559b056b9f07af023905753b02d95eb329a35c77f154b79abbcd291615ce42f02 78 validwycheproof-73 a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c 8a9bb4c465a3863abc9fd0dd35d80bb28f7d33d37d74679802d63f82b20da114b8d765a1206b3e9ad7cf2b2d8d778bb8651f1fa992db293c0039eacb6161480f 54657374 validwycheproof-74 a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c d839c20abfda1fd429531831c64f813f84b913e9928540310cf060b44c3dbf9457d44a7721fdc0d67724ff81cb450dd39b10cfb65db15dda4b8bf09d26bd3801 48656c6c6f validwycheproof-75 a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c 9bbb1052dcfa8ad2715c2eb716ae4f1902dea353d42ee09fd4c0b4fcb8b52b5219e2200016e1199d0061891c263e31b0bc3b55673c19610c4e0fa5408004160b 313233343030 validwycheproof-76 a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c f63b5c0667c7897fc283296416f7f60e84bbde9cbd832e56be463ed9f568069702b17a2f7c341ebf590706a6388ac76ac613c1675ec0f2c7118f2573422a500b 000000000000000000000000 validwycheproof-77 a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c 1bc44d7001e6b5b9090fef34b2ca480f9786bbefa7d279353e5881e8dfb91b803ccd46500e270ef0109bfd741037558832120bc2a4f20fbe7b5fb3c3aaf23e08 6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 validwycheproof-78 a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c ea8e22143b02372e76e99aece3ed36aec529768a27e2bb49bdc135d44378061e1f62d1ac518f33ebf37b2ee8cc6dde68a4bd7d4a2f4d6cb77f015f71ca9fc30d 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60 validwycheproof-79 a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c 8acd679e1a914fc45d5fa83d3021f0509c805c8d271df54e52f43cfbd00cb6222bf81d58fe1de2de378df67ee9f453786626961fe50a9b05f12b6f0899ebdd0a ffffffffffffffffffffffffffffffff validwycheproof-80 d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b - validwycheproof-81 3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c 92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00 72 validwycheproof-82 fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025 6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a af82 validwycheproof-83 278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0 validwycheproof-84 100fdf47fb94f1536a4f7c3fda27383fa03375a8f527c537e6f1703c47f94f86 dac119d6ca87fc59ae611c157048f4d4fc932a149dbe20ec6effd1436abf83ea05c7df0fef06147241259113909bc71bd3c53ba4464ffcad3c0968f2ffffff0f 124e583f8b8eca58bb29c271b41d36986bbc45541f8e51f9cb0133eca447601e validwycheproof-85 100fdf47fb94f1536a4f7c3fda27383fa03375a8f527c537e6f1703c47f94f86 0971f86d2c9c78582524a103cb9cf949522ae528f8054dc20107d999be673ff4e25ebf2f2928766b1248bec6e91697775f8446639ede46ad4df4053000000010 6a0bc2b0057cedfc0fa2e3f7f7d39279b30f454a69dfd1117c758d86b19d85e0 invalidwycheproof-86 8fd659b77b558ed93882c1157438450ac86ec62d421d568e98ee236f3810295a 7db17557ac470c0eda4eedaabce99197ab62565653cf911f632ee8be0e5ffcfc88fb94276b42e0798fd3aa2f0318be7fc6a29fae75f70c3dcdc414a0ad866601 b0729a713593a92e46b56eaa66b9e435f7a09a8e7de03b078f6f282285276635f301e7aaafe42187c45d6f5b13f9f16b11195cc125c05b90d24dfe4c validwycheproof-87 2a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082 67d84d4c3945aaf06e06d524be63acbfb5dbb1988c4aea96a5ee9f7a9b9eecc29df4f66b8aa1d9e8607a58fb1ef0c2ad69aac005b4f58e34103344a9c8871a09 a8546e50ba31cae3234310d32672447be213fad91a227a19669c53d309b959782b0e6b71f8791fdb470043b58122003157d2d96a43a6cbd7d3a8d86bf4c97391883e268d50af80e1e6e12939c2bd50ca746cdadfad4edf1bda875299740724148efb1ebe73fb60088cda890317658627a5f7ab5a0c075d9d8f3f97b6492b35519e50ff6b38377432a7081f9176bb1c29a862deac1336ca20b097a47829cec10a6a7cec178eda2d12f6dc6c87f910454af0123555ba184e68804d9cced60fd5c8c90943e56599c8f0ba59a38491ba5e5a53460682474c07e40ca142983314fd762856bb1093f359da6eb0a756bd93a3160c10dd8feea6b97e7c6a17cb54bd5d7649c05c66d7bdee056671dfdaf689fa3945bb8e29a429f4bd5d355dce9687b06f01d5e33e3999f0e8 validwycheproof-88 c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051 24087d47f3e20af51b9668ae0a88ce76586802d0ec75d8c0f28fc30962b5e1d1a1d509571a1624ed125a8df92a6e963728d6b5de99200b8e285f70feb6f05207 cd2212eddb0706f62c995cef958634f0cb7793444cbf4d30e81c27c41ebea6cb02607510131f9c015692dfd521b148841e9a2d3564d20ac401f6cb8e40f520fe0cafbeaa88840b83013369d879f013463fe52a13267aa0c8c59c45cde9399cd1e6be8cc64cf48315ac2eb31a1c567a4fb7d601746d1f63b5ac020712adbbe07519bded6f validwycheproof-89 32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e d920d421a5956b69bfe1ba834c025e2babb6c7a6d78c97de1d9bb1116dfdd1185147b2887e34e15578172e150774275ea2aad9e02106f7e8ca1caa669a066f0c ec5c7cb078 validwycheproof-90 32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e 4f62daf7f7c162038552ad7d306e195baa37ecf6ca7604142679d7d1128e1f8af52e4cb3545748c44ef1ff1c64e877e4f4d248259b7f6eb56e3ef72097dc8e0c 4668c6a76f0e482190a7175b9f3806a5fe4314a004fa69f988373f7a validwycheproof-91 c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a 6669acf94667c5b541afe5307bde9476b13ae7e0e6058a772101ac8eb0a94331428eb4db0a2c68a9b6c1763b8624dab259b0876cdcfaeacc17b21a18e3fc010a 0f325ffd87e58131ffa23c05ea4579513b287fdba87b44 validwycheproof-92 cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10 30490c28f806298225df62103521dcee047153912c33ab8ab8bbdd1ffabd70fd4fdb360f05be535b067d1cf4e78c2cb432206bf280aab3bd21aaa1cb894c5b06 ec5c7cb078 validwycheproof-93 32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e deecafb6f2ede73fec91a6f10e45b9c1c61c4b9bfbe6b6147e2de0b1df6938971f7896c3ab83851fb5d9e537037bff0fca0ccb4a3cc38f056f91f7d7a0557e08 5dc9bb87eb11621a93f92abe53515697d2611b2eef73 validwycheproof-94 cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10 4cd4f77ed473a6647387f3163541c67a1708a3c3bd1673247cb87f0cb68b3c56f04bfa72970c8a483efe659c87009ab4020b590b6641316b3deddb5450544e02 67484059b2490b1a0a4f8dee77979e26 validwycheproof-95 32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e 7f8663cf98cbd39d5ff553f00bcf3d0d520605794f8866ce75714d77cc51e66c91818b657d7b0dae430a68353506edc4a714c345f5ddb5c8b958ba3d035f7a01 7dcfe60f881e1285676f35b68a1b2dbcdd7be6f719a288ababc28d36e3a42ac3010a1ca54b32760e74 validwycheproof-96 cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10 1e41a24fe732bd7cab14c2a2f5134ee8c87fcbd2e987e60957ed9239e5c32404d56977e1b4282871896cb10625a1937468e4dc266e16a9c1b8e9891177eca802 a020a4381dc9141f47ee508871ab7a8b5a3648727c4281ae9932376f23a8e1bcda0626b7129197d864178631ec89c4332dbb18 validwycheproof-97 32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e 6aab49e5c0bc309b783378ee03ffda282f0185cdf94c847701ff307a6ee8d0865411c44e0a8206f6a5f606107451940c2593af790ce1860f4c14ab25b2deae08 58e456064dff471109def4ca27fa8310a1df32739655b624f27e6418d34b7f007173f3faa5 validwycheproof-98 529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56 01abfa4d6bbc726b196928ec84fd03f0c953a4fa2b228249562ff1442a4f63a7150b064f3712b51c2af768d2c2711a71aabf8d186833e941a0301b82f0502905 e1cbf2d86827825613fb7a85811d validwycheproof-99 cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10 2a833aadecd9f28235cb5896bf3781521dc71f28af2e91dbe1735a61dce3e31ac15ca24b3fc47817a59d386bbbb2ce60a6adc0a2703bb2bdea8f70f91051f706 a25176b3afea318b2ec11ddacb10caf7179c0b3f8eabbfa2895581138d3c1e0e validwycheproof-100 32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e 1a74ed2cbdc7d8f3827014e8e6ecf8fd2698ac8f86833acccdd400df710fe0d6b0543c9cfa00d52bf024ab7ce0d91981944097233ec134d5c7abbd44bfd32d0d a1 validwycheproof-101 2252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1 af0fd9dda7e03e12313410d8d8844ebb6fe6b7f65141f22d7bcba5695a25414a9e54326fb44d59fb14707899a8aae70857b23d4080d7ab2c396ef3a36d45ce02 975ef941710071a9e1e6325a0c860becd7c695b5117c3107b686e330e5 validwycheproof-102 c0a773110f975de3732355bb7ec7f0c41c091c0252966070205516693b992a4a 0280427e713378f49d478df6373c6cac847b622b567daa2376c839e7ac10e22c380ab0fa8617c9dcfe76c4d9db5459b21dc1413726e46cc8f387d359e344f407 - validwycheproof-103 cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10 c97e3190f83bae7729ba473ad46b420b8aad735f0808ea42c0f898ccfe6addd4fd9d9fa3355d5e67ee21ab7e1f805cd07f1fce980e307f4d7ad36cc924eef00c a9e6d94870a67a9fe1cf13b1e6f9150cdd407bf6480ec841ea586ae3935e9787163cf419c1 validwycheproof-104 32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e 14ceb2eaf4688d995d482f44852d71ad878cd7c77b41e60b0065fd01a59b054ee74759224187dbde9e59a763a70277c960892ef89fba997aba2576b2c54ba608 11cb1eafa4c42a8402c4193c4696f7b2e6d4585e4b42dcf1a8b67a80b2da80bc9d4b649fb2f35eaf1f56c426fd0b validwycheproof-105 c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051 c2656951e2a0285585a51ff0eda7e9a23c2dfd2ffa273aee7808f4604e8f9a8c8ea49e9fce4eb2d8d75d36b7238fe6fc13b6c5d9427dd58f8c6615d033c0bd0f 27d465bc632743522aefa23c validwycheproof-106 c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a 931e5152fcef078c22cc5d6a3a65f06e396289f6f5f2d1efa6340254a53526ef5dc6874eeddf35c3f50991c53cd02bf06313e37d93ee1f7022128ffa3b8f300b 5ffa validwycheproof-107 529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56 e4ae21f7a8f4b3b325c161a8c6e53e2edd7005b9c2f8a2e3b0ac4ba94aa80be6f2ee22ac8d4a96b9a3eb73a825e7bb5aff4a3393bf5b4a38119e9c9b1b041106 25 validwycheproof-108 2252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1 e097e0bd0370bff5bde359175a11b728ee9639095d5df8eda496395565616edfe079977f7d4dc8c75d6113a83d6a55e6e1676408c0967a2906339b43337dcb01 80fdd6218f29c8c8f6bd820945f9b0854e3a8824 validwycheproof-109 2a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082 28fafbb62b4d688fa79e1ac92851f46e319b161f801d4dc09acc21fdd6780a2c4292b8c1003c61c2bcebe7f3f88ccc4bb26d407387c5f27cb8c94cf6ce810405 b477b0480bb84642608b908d29a51cf2fce63f24ee95 validwycheproof-110 32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e 83c40ce13d483cc58ff65844875862d93df4bd367af77efa469ec06a8ed9e6d7905a04879535708ddf225567a815c9b941d405c98e918fd0c151165cea7fb101 aa365b442d12b7f3c925 validwycheproof-111 54cda623245759ad6d43e620a606908befc633d60792bc7798447a0ef38e7311 14d9b497c19b91d43481c55bb6f5056de252d9ecb637575c807e58e9b4c5eac8b284089d97e2192dc242014363208e2c9a3435edf8928fb1d893553e9be4c703 27e792b28b2f1702 validwycheproof-112 2362bac514d5fad33802642e979a1e82de6eb6f1bcbf6a5b304f2bb02b9e57fe 242ddb3a5d938d07af690b1b0ef0fa75842c5f9549bf39c8750f75614c712e7cbaf2e37cc0799db38b858d41aec5b9dd2fca6a3c8e082c10408e2cf3932b9d08 eef3bb0f617c17d0420c115c21c28e3762edc7b7fb048529b84a9c2bc6 validwycheproof-113 32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e 71a4a06a34075f2fd47bc3abf4714d46db7e97b08cb6180d3f1539ac50b18ce51f8af8ae95ed21d4fa0daab7235925631ecea1fd9d0d8a2ba7a7583fd04b900c 475f validwycheproof-114 037b55b427dc8daa0f80fcebaf0846902309f8a6cf18b465c0ce9b6539629ac8 c964e100033ce8888b23466677da4f4aea29923f642ae508f9d0888d788150636ab9b2c3765e91bbb05153801114d9e52dc700df377212222bb766be4b8c020d 01234567 validwycheproof-115 9c0007698f177998a7666c7cf7973e2b88e9c4946e33804a7bbe8968d2394b2e 176065c6d64a136a2227687d77f61f3fca3b16122c966276fd9a8b14a1a2cea4c33b3533d11101717016684e3810efbea63bb23773f7cc480174199abd734f08 9399a6db9433d2a28d2b0c11c8794ab7d108c95b validwycheproof-116 ed3a6f9721dc9729c1f76635bcf080d7036e1c2f0228654ccbbe1e738c17b963 7ca69331eec8610d38f00e2cdbd46966cb359dcde98a257ac6f362cc00c8f4fe85c02285fe4d66e31a44cadb2bf474e1a7957609eb4fe95a71473fe6699aa70d 7af783afbbd44c1833ab7237ecaf63b94ffdd003 validwycheproof-117 4abfb535313705a6570018440cdec1a3ae33e51f352112fa6acbd0c6bc3ea859 f296715e855d8aecccba782b670163dedc4458fe4eb509a856bcac450920fd2e95a3a3eb212d2d9ccaf948c39ae46a2548af125f8e2ad9b77bd18f92d59f9200 321b5f663c19e30ee7bbb85e48ecf44db9d3f512 validwycheproof-118 4f2162e6bf03a712db0efa418b7e7006e23871d9d7ec555a313885c4afd96385 367d07253a9d5a77d054b9c1a82d3c0a448a51905343320b3559325ef41839608aa45564978da1b2968c556cfb23b0c98a9be83e594d5e769d69d1156e1b1506 c48890e92aeeb3af04858a8dc1d34f16a4347b91 validwycheproof-119 4abfb535313705a6570018440cdec1a3ae33e51f352112fa6acbd0c6bc3ea859 f296715e855d8aecccba782b670163dedc4458fe4eb509a856bcac450920fd2e95a3a3eb212d2d9ccaf948c39ae46a2548af125f8e2ad9b77bd18f92d59f9200 321b5f663c19e30ee7bbb85e48ecf44db9d3f512 validwycheproof-120 4f2162e6bf03a712db0efa418b7e7006e23871d9d7ec555a313885c4afd96385 367d07253a9d5a77d054b9c1a82d3c0a448a51905343320b3559325ef41839608aa45564978da1b2968c556cfb23b0c98a9be83e594d5e769d69d1156e1b1506 c48890e92aeeb3af04858a8dc1d34f16a4347b91 validwycheproof-121 0717d75ce27ea181ed5a30e6456c649b5cf453a6b4c12cd3f9fd16b31e0c25cd 9588e02bc815649d359ce710cdc69814556dd8c8bab1c468f40a49ebefb7f0de7ed49725edfd1b708fa1bad277c35d6c1b9c5ec25990997645780f9203d7dd08 26d5f0631f49106db58c4cfc903691134811b33c validwycheproof-122 db5b9eab7e84e5a13505865fa711c9c896c898609fc11fc9bc1e55028f9496df 2217a0be57dd0d6c0090641496bcb65e37213f02a0df50aff0368ee2808e1376504f37b37494132dfc4d4887f58b9e86eff924040db3925ee4f8e1428c4c500e 2a71f064af982a3a1103a75cef898732d7881981 validwycheproof-123 7bac18f6d2625d3915f233434cda38a577247a7332a5170b37142a34644145e0 1fda6dd4519fdbefb515bfa39e8e5911f4a0a8aa65f40ef0c542b8b34b87f9c249dc57f320718ff457ed5915c4d0fc352affc1287724d3f3a9de1ff777a02e01 bf26796cef4ddafcf5033c8d105057db0210b6ad validwycheproof-124 7bac18f6d2625d3915f233434cda38a577247a7332a5170b37142a34644145e0 1fda6dd4519fdbefb515bfa39e8e5911f4a0a8aa65f40ef0c542b8b34b87f9c249dc57f320718ff457ed5915c4d0fc352affc1287724d3f3a9de1ff777a02e01 bf26796cef4ddafcf5033c8d105057db0210b6ad validwycheproof-125 38ead304624abebf3e2b31e20e5629531e3fc659008887c9106f5e55adbbc62a 068eafdc2f36b97f9bae7fbda88b530d16b0e35054d3a351e3a4c914b22854c711505e49682e1a447e10a69e3b04d0759c859897b64f71137acf355b63faf100 ae03da6997e40cea67935020152d3a9a365cc055 validwycheproof-126 e9bc95049af7e4817b17c402269ba5e767b7348757ac8002fec9e08390c0a9cf 43670abc9f09a8a415e76f4a21c6a46156f066b5a37b3c1e867cf67248c7b927e8d13a763e37abf936f5f27f7a8aa290539d21f740efd26b65fd5ad27085f400 489d473f7fb83c7f6823baf65482517bccd8f4ea validwycheproof-127 ee8155ca4e8fe7bc5bca5992044eab7f8c3c6a13db1176f42f46c29da5b064f4 56388f2228893b14ce4f2a5e0cc626591061de3a57c50a5ecab7b9d5bb2caeea191560a1cf2344c75fdb4a085444aa68d727b39f498169eaa82cf64a31f59803 1b704d6692d60a07ad1e1d047b65e105a80d3459 validwycheproof-128 db507bfcc9576393f7157bb360532b05c5fcf2e764b690cc6698a4a30d349095 553e5845fc480a577da6544e602caadaa00ae3e5aa3dce9ef332b1541b6d5f21bdf1d01e98baf80b8435f9932f89b3eb70f02da24787aac8e77279e797d0bd0b dc87030862c4c32f56261e93a367caf458c6be27 validwycheproof-129 994eaf03309d6ad9d95a656bc1744e2886f029023a3750b34f35086b3c7227f8 bc10f88081b7be1f2505b6e76c5c82e358cf21ec11b7df1f334fb587bada465b53d9f7b4d4fec964432ee91ead1bc32ed3c82f2167da1c834a37515df7fe130e 7f41ef68508343ef18813cb2fb332445ec6480cd validwycheproof-130 127d37e406e0d83e4b55a09e21e8f50fb88af47e4a43f018cdebffc1948757f0 00c11e76b5866b7c37528b0670188c1a0473fb93c33b72ae604a8865a7d6e094ff722e8ede3cb18389685ff3c4086c29006047466f81e71a329711e0b9294709 e1ce107971534bc46a42ac609a1a37b4ca65791d validwycheproof-131 d83ba84edfb4bec49f29be31d80a64b7c0b5a502438cdb1d0dd1e0e3e55786de 0a6f0ac47ea136cb3ff00f7a96638e4984048999ee2da0af6e5c86bffb0e70bb97406b6ad5a4b764f7c99ebb6ec0fd434b8efe253b0423ef876c037998e8ab07 869a827397c585cf35acf88a8728833ab1c8c81e validwycheproof-132 d3c9aa2f3d6ef217a166e8ae403ed436c37facbbe3beceb78df6eb439f8fa04a b7cbb942a6661e2312f79548224f3e44f5841c6e880c68340756a00ce94a914e8404858265985e6bb97ef01d2d7e5e41340309606bfc43c8c6a8f925126b3d09 619d8c4f2c93104be01cd574a385ceca08c33a9e validwycheproof-133 d53280367c1c0b95ac4112218b92c6a71c51fb6312ce668de196c7d52a136155 27a4f24009e579173ff3064a6eff2a4d20224f8f85fdec982a9cf2e6a3b51537348a1d7851a3a932128a923a393ea84e6b35eb3473c32dceb9d7e9cab03a0f0d 5257a0bae8326d259a6ce97420c65e6c2794afe2 validwycheproof-134 94ac2336ba97a476fb4c9f2b5563e4167ca292c6e99e422350a911ae3172c315 985b605fe3f449f68081197a68c714da0bfbf6ac2ab9abb0508b6384ea4999cb8d79af98e86f589409e8d2609a8f8bd7e80aaa8d92a84e7737fbe8dcef41920a 5acb6afc9b368f7acac0e71f6a4831c72d628405 validwycheproof-135 e1e7316d231f7f275bdf403360304da1509fdf1af1fd25ca214eaac0a289398f 1c8fbda3d39e2b441f06da6071c13115cb4115c7c3341704cf6513324d4cf1ef4a1dd7678a048b0dde84e48994d080befcd70854079d44b6a0b0f9fa002d130c 3c87b3453277b353941591fc7eaa7dd37604b42a validwycheproof-136 fffbeea71215efaf9888fec2cc68edb3703ff11a66fd629b53cbda5eabc18750 59097233eb141ed948b4f3c28a9496b9a7eca77454ecfe7e46737d1449a0b76b15aacf77cf48af27a668aa4434cfa26c504d75a2bcc4feac46465446234c0508 0a68e27ef6847bfd9e398b328a0ded3679d4649d validwycheproof-137 19ccc0527599cb032e0b4c4d74e60f13901768a99df041c3bc1bf6c0ef271169 519105608508fe2f1b6da4cc8b23e39798b1d18d25972beed0404cec722e01ba1b6a0f85e99e092cca8076b101b60d4ac5035684357f4d0daacdc642da742a06 4e9bef60737c7d4dd10bd52567e1473a36d3573d validwycheproof-138 0e726e27047563aa0a1a9c2e085d8d26af2acba129d0869c65031e3e6cac329a d8b03ee579e73f16477527fc9dc37a72eaac0748a733772c483ba013944f01ef64fb4ec5e3a95021dc22f4ae282baff6e9b9cc8433c6b6710d82e7397d72ef04 cc82b3163efda3ba7e9240e765112caa69113694 validwycheproof-139 e77717b54a2b5e5bce5bccb8f0c5fdb5fd7df77ac254020fc9120dc0d4df4178 26da61fdfd38e6d01792813f27840c8b4766b0faaed39d0ee898cb450d94a5d5f57e58b6a003d7f9b56b20561954c6edcf66492d116b8b5e91f205a3a6449d0b 923a5c9e7b5635bb6c32c5a408a4a15b652450eb validwycheproof-140 6220972d3f7d150b36790d7d522384876d64d640cd9913186815e1629582ed36 4adeaff7a58c5010a5a067feea0ae504d37b0c6a76c6c153e222f13409dff2df0fab69bc5059b97d925dc1b89e9851d7c627cb82d65585f9fd976124553f8902 6f2f0245de4587062979d0422d349f93ccdc3af2 validwycheproof-141 7b64a28c50ec7678a90e3e1a21522e30ac9db7b5215aea2bfb33bea037eab987 4204d620cde0c3008c0b2901f5d6b44f88f0e3cb4f4d62252bf6f3cb37c1fb150a9ccb296afe5e7c75f65b5c8edd13dc4910ffe1e1265b3707c59042cf9a5902 6e911edb27a170b983d4dee1110554f804330f41 validwycheproof-142 724452210a9e4c994819229bf12bf84e95768a3a97c08d8d8f5f939a4cad34c5 f8a69d3fd8c2ff0a9dec41e4c6b43675ce08366a35e220b1185ffc246c339e22c20ac661e866f52054015efd04f42eca2adcee6834c4df923b4a62576e4dff0e b8cf807eea809aaf739aa091f3b7a3f2fd39fb51 validwycheproof-143 bad265b294ed2f422cb6a141694086238fbfe987571aa765d8b4f3a24105aa01 61792c9442bc6338ac41fd42a40bee9b02ec1836503d60ff725128c63d72808880c36e6190b7da525cbee5d12900aa043547dd14a2709ef9e49d628f37f6b70c 01a2b5f7fee813b4e9bd7fc25137648004795010 validwycheproof-144 0aaee4b723db9b51ba7d22eb23eb8a76a5ac02f4fc9dd06f77bea42e1d37ec5a fa3cd41e3a8c00b19eecd404a63c3cb787cd30de0dfc936966cff2117f5aff18db6bef80fcfd8856f3fb2e9c3dc47593e9471103032af918feee638a33d40505 0fbf5d47cb5d498feace8f98f1896208da38a885 validwycheproof-145 812344af15a91ba83c2c91e96f1727ac0f3c4c41385b9fa84efa399ada5168be 97fbbcd7a1d0eb42d2f8c42448ef35a2c2472740556b645547865330d6c57068af377fced08aaf810c08cd3c43d296f1975710312e9334c98b485f831efa4103 36e67c1939750bffb3e4ba6cb85562612275e862 validwycheproof-146 0ee5cb5597fbdf8dccc48b01485e39b33aa133b52d30d23740277267cfec3e3e d7dbaa337ffd2a5fd8d5fd8ad5aeccc0c0f83795c2c59fe62a40b87903b1ae62ed748a8df5af4d32f9f822a65d0e498b6f40eaf369a9342a1164ee7d08b58103 13945c894c1d3fe8562e8b20e5f0efaa26ade8e3 validwycheproof-147 9fba1de92b60b5b4703089763d0d6f9125e4dd7efae41f08a22882aef96892c4 09a2ed303a2fa7027a1dd7c3b0d25121eeed2b644a2fbc17aa0c8aea4524071ede7e7dd7a536d5497f8165d29e4e1b63200f74bbae39fbbbccb29889c62c1f09 4de142af4b8402f80a47fa812df84f42e283cee7 validwycheproof-148 7582ab1b52e1316e5c13671f43b39ca36b28133cd0832831bcddd0b0f23398cb e6884a6e6b2e60a0b5862251c001e7c79d581d777d6fc11d218d0aecd79f26a30e2ca22cc7c4674f8b72655bc4ee5cb5494ca07c05177656142ac55cc9d33e02 563357f41b8b23b1d83f19f5667177a67da20b18 validwycheproof-149 dd2d678bae222f3fb6e8278f08cc9e1a66339c926c29ac0a16f9717f5ee18cd8 6124c206d864507ea5d984b363b4cf583314db6856a45ded5e61eebff4d5e337e0b4c82b445ae2e52d549d2d961eace2ea01f81158e09a9686baa040db65ad08 931bbf9c877a6571cf7d4609fc3eb867edd43f51 validwycheproof-150 ccbe7cb2e4bc215cee2f885e1d22f7e0d582b2bbbd782c104e548b152d26fc69 cfbd450a2c83cb8436c348822fe3ee347d4ee937b7f2ea11ed755cc52852407c9eec2c1fa30d2f9aef90e89b2cc3bcef2b1b9ca59f712110d19894a9cf6a2802 44530b0b34f598767a7b875b0caee3c7b9c502d1 validwycheproof-151 d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a 0100000000000000000000000000000000000000000000000000000000000080c803ee1f2342aa96ff698a393d1ab5e66f3eda101d6d120b394c3fd32c117d0a 313233343030 invalidspeccheck-0 c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000 8c93255d71dcab10e8f379c26200f3c7bd5f09d9bc3068d3ef4edeb4853022b6 ?speccheck-1 c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43a5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04 9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79 ?speccheck-2 f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43 c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8c4bd45aecaca5b24fb97bc10ac27ac8751a7dfe1baff8b953ec9f5833ca260e aebf3f2601a0c8c5d39cc7d8911642f740b78168218da8471772b35f9d35b9ab ?speccheck-3 cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d 9046a64750444938de19f227bb80485e92b83fdb4b6506c160484c016cc1852f87909e14428a7a1d62e9f22f3d3ad7802db02eb2e688b6c52fcd6648a98bd009 9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79 ?speccheck-4 cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d 160a1cb0dc9c0258cd0a7d23e94d8fa878bcb1925f2c64246b2dee1796bed5125ec6bc982a269b723e0668e540911a9a6a58921d6925e434ab10aa7940551a09 e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c ?speccheck-5 cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d 21122a84e0b5fca4052f5b1235c80a537878b38f3142356b2c2384ebad4668b7e40bc836dac0f71076f9abe3a53f9c03c1ceeeddb658d0030494ace586687405 e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c ?speccheck-6 442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623 e96f66be976d82e60150baecff9906684aebb1ef181f67a7189ac78ea23b6c0e547f7690a0e2ddcd04d87dbc3490dc19b3b3052f7ff0538cb68afb369ba3a514 85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40 ?speccheck-7 442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623 8ce5b96c8f26d0ab6c47958c9e68b937104cd36e13c33566acd2fe8d38aa19427e71f98a473474f2f13f06f97c20d58cc3f54b8bd0d272f42b695dd7e89a8c22 85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40 ?speccheck-8 f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43 ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f 9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41 ?speccheck-9 f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43 ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908 9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41 ?speccheck-10 ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04 e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b ?speccheck-11 ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04 39a591f5321bbe07fd5a23dc2f39d025d74526615746727ceefd6e82ae65c06f ?test/vectors/gen-ed25519-vectors.shadded
#!/bin/sh# Generate test/test-ed25519-vectors.sgl from test/vectors/ed25519-cases.txt.## ed25519-cases.txt lines: "<label> <pk-hex> <sig-hex> <msg-hex|-> <expected>"# rfc8032-* RFC 8032 section 7.1 (Ed25519), expected valid# wycheproof-* C2SP/wycheproof testvectors_v1/ed25519_test.json# (commit 5722833ca004983abd1a91bcb6c24596d50ac0f9)# speccheck-* novifinancial/ed25519-speccheck cases.json# (commit 5e4bfc4542293286e9ad3cb2b805badee00503de), whose# expected column is "?": filled in below.## speccheck expectations are libsodium's (what the minisign tool uses):# reject 0-2 (small-order A or R), accept 3, reject 6-7 (S >= L) and 8-11# (non-canonical R or A). Cases 4 and 5 are the documented divergence:# they need a public key with a small-order component and pass the# cofactored equation (RFC 8032 section 5.1.7), which sigil-crypto checks,# but fail libsodium's cofactorless one. Measured by test/differential/run.sh.set -euDIR=$(cd "$(dirname "$0")" && pwd)OUT="$DIR/../test-ed25519-vectors.sgl"awk 'BEGIN { spec["0"]="invalid"; spec["1"]="invalid"; spec["2"]="invalid"; spec["3"]="valid"; spec["4"]="valid"; spec["5"]="valid"; spec["6"]="invalid"; spec["7"]="invalid"; spec["8"]="invalid"; spec["9"]="invalid"; spec["10"]="invalid"; spec["11"]="invalid"; print ";;; GENERATED by test/vectors/gen-ed25519-vectors.sh from" print ";;; test/vectors/ed25519-cases.txt. Do not edit by hand." print ";;;" print ";;; Every case runs through ed25519-verify. A valid case must return #t;" print ";;; an invalid one must return #f, or raise when the key or signature has the" print ";;; wrong length (the API raises on wrong lengths; nothing else may raise)." print "" print "(import (sigil test) (sigil crypto) (sigil math))" print "" print "(define (hex->bv s)" print " (if (string=? s \"-\")" print " (make-bytevector 0 0)" print " (let* ((n (quotient (string-length s) 2))" print " (bv (make-bytevector n 0)))" print " (let loop ((i 0))" print " (if (< i n)" print " (begin" print " (bytevector-u8-set! bv i (string->number (substring s (* 2 i) (+ 2 (* 2 i))) 16))" print " (loop (+ i 1)))" print " bv)))))" print "" print ";; #t, #f, or the symbol raised when the call raises." print "(define (verdict pk sig msg)" print " (guard (e (#t (quote raised)))" print " (ed25519-verify (hex->bv pk) (hex->bv msg) (hex->bv sig))))" print "" print "(test-group \"ed25519 vectors\""}{ label=$1; pk=$2; sig=$3; msg=$4; want_result=$5 if (label ~ /^speccheck-/) { k=label; sub(/^speccheck-/, "", k); want_result=spec[k] } if (want_result == "valid") want="(assert-eq #t (verdict \"" pk "\" \"" sig "\" \"" msg "\"))" else if (length(pk) == 64 && length(sig) == 128) want="(assert-eq #f (verdict \"" pk "\" \"" sig "\" \"" msg "\"))" else want="(assert-eq (quote raised) (verdict \"" pk "\" \"" sig "\" \"" msg "\"))" printf " (test \"%s %s\"\n %s)\n", label, want_result, want n++}END { print " )"; print ""; printf ";;; %d cases\n", n }' "$DIR/ed25519-cases.txt" > "$OUT"echo "wrote $OUT"test/vectors/speccheck-cases.jsonadded
[{"message":"8c93255d71dcab10e8f379c26200f3c7bd5f09d9bc3068d3ef4edeb4853022b6","pub_key":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa","signature":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000"},{"message":"9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79","pub_key":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa","signature":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43a5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04"},{"message":"aebf3f2601a0c8c5d39cc7d8911642f740b78168218da8471772b35f9d35b9ab","pub_key":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43","signature":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8c4bd45aecaca5b24fb97bc10ac27ac8751a7dfe1baff8b953ec9f5833ca260e"},{"message":"9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79","pub_key":"cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d","signature":"9046a64750444938de19f227bb80485e92b83fdb4b6506c160484c016cc1852f87909e14428a7a1d62e9f22f3d3ad7802db02eb2e688b6c52fcd6648a98bd009"},{"message":"e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c","pub_key":"cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d","signature":"160a1cb0dc9c0258cd0a7d23e94d8fa878bcb1925f2c64246b2dee1796bed5125ec6bc982a269b723e0668e540911a9a6a58921d6925e434ab10aa7940551a09"},{"message":"e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c","pub_key":"cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d","signature":"21122a84e0b5fca4052f5b1235c80a537878b38f3142356b2c2384ebad4668b7e40bc836dac0f71076f9abe3a53f9c03c1ceeeddb658d0030494ace586687405"},{"message":"85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40","pub_key":"442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623","signature":"e96f66be976d82e60150baecff9906684aebb1ef181f67a7189ac78ea23b6c0e547f7690a0e2ddcd04d87dbc3490dc19b3b3052f7ff0538cb68afb369ba3a514"},{"message":"85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40","pub_key":"442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623","signature":"8ce5b96c8f26d0ab6c47958c9e68b937104cd36e13c33566acd2fe8d38aa19427e71f98a473474f2f13f06f97c20d58cc3f54b8bd0d272f42b695dd7e89a8c22"},{"message":"9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41","pub_key":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43","signature":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f"},{"message":"9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41","pub_key":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43","signature":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908"},{"message":"e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b","pub_key":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","signature":"a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04"},{"message":"39a591f5321bbe07fd5a23dc2f39d025d74526615746727ceefd6e82ae65c06f","pub_key":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","signature":"a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04"}] No newline at end of filetest/vectors/wycheproof-ed25519_test.jsonadded
{ "algorithm": "EDDSA", "schema": "eddsa_verify_schema_v1.json", "numberOfTests": 151, "header": [ "Test vectors of type EddsaVerify are intended for testing" ], "notes": { "CompressedSignature": { "bugType": "CAN_OF_WORMS", "description": "The test vector contains a signature where r and s overlap or where 0 bytes were cut from the signature. This signature was specifically generated.", "effect": "The effect of the bug is unclear without further analysis. It could be rather benign and just allow signature malleability in some cases or it could hide a more severe flaw." }, "InvalidEncoding": { "bugType": "CAN_OF_WORMS", "description": "The test vector contains a signature with an invalid encoding of the values. The vector checks that invalid encodings are not accepted. For the vectors that modify the encoding of R, S has been recomputed so that the hash matches the modified R and the R recovered from S and the hash equals the original R. Such vectors are accepted only by verifiers that decode R leniently or that compare R to the recovered R incompletely.", "effect": "Accepting such signatures means the encoding of a signature is not unique. A holder of the private key can generate multiple distinct signatures for the same message, and different verifiers can disagree about which signatures are valid." }, "InvalidKtv": { "bugType": "UNKNOWN", "description": "The test vector contains a known invalid signature." }, "InvalidSignature": { "bugType": "AUTH_BYPASS", "description": "The test vector contains a signature with edge case values such as 0 or the order of the group.", "effect": "The effect of accepting such signatures probably indicates that signatures can be forged without even knowing the message itself." }, "Ktv": { "bugType": "BASIC", "description": "The test vector contains a known valid signature." }, "SignatureMalleability": { "bugType": "SIGNATURE_MALLEABILITY", "description": "EdDSA signatures are non-malleable, if implemented correctly. If an implementation fails to check the range of S then it may be possible to modify a signature in such a way that it still verifies. See RFC 8032, Section 5.1.7 and Section 8.4." }, "SignatureWithGarbage": { "bugType": "SIGNATURE_MALLEABILITY", "description": "The test vector contains a signature with additional content. EdDSA signature are expected to be non-malleable. Signatures of the wrong length should be rejected. See RFC 8032, Section 5.1.7 and Section 8.4." }, "TinkOverflow": { "bugType": "KNOWN_BUG", "description": "The test vector contains a signature that caused an arithmetic overflow in tink." }, "TruncatedSignature": { "bugType": "AUTH_BYPASS", "description": "The test vector contains a signature that was truncated.", "effect": "Accepting such signatures likely means that signatures can be forged." }, "Valid": { "bugType": "BASIC", "description": "The test vector is an ordinary valid signature." } }, "testGroups": [ { "type": "EddsaVerify", "source": { "name": "google-wycheproof", "version": "0.9rc5" }, "publicKey": { "type": "EDDSAPublicKey", "curve": "edwards25519", "keySize": 255, "pk": "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" }, "publicKeyDer": "302a300506032b65700321007d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAfU0Of2FTpptiQrUiq77mhf2kQg+INLEIw72uNp71Sfo=\n-----END PUBLIC KEY-----\n", "publicKeyJwk": { "kty": "OKP", "crv": "Ed25519", "kid": "none", "x": "fU0Of2FTpptiQrUiq77mhf2kQg-INLEIw72uNp71Sfo" }, "tests": [ { "tcId": 1, "comment": "", "flags": [ "Valid" ], "msg": "", "sig": "d4fbdb52bfa726b44d1786a8c0d171c3e62ca83c9e5bbe63de0bb2483f8fd6cc1429ab72cafc41ab56af02ff8fcc43b99bfe4c7ae940f60f38ebaa9d311c4007", "result": "valid" }, { "tcId": 2, "comment": "", "flags": [ "Valid" ], "msg": "78", "sig": "d80737358ede548acb173ef7e0399f83392fe8125b2ce877de7975d8b726ef5b1e76632280ee38afad12125ea44b961bf92f1178c9fa819d020869975bcbe109", "result": "valid" }, { "tcId": 3, "comment": "", "flags": [ "Valid" ], "msg": "54657374", "sig": "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", "result": "valid" }, { "tcId": 4, "comment": "", "flags": [ "Valid" ], "msg": "48656c6c6f", "sig": "1c1ad976cbaae3b31dee07971cf92c928ce2091a85f5899f5e11ecec90fc9f8e93df18c5037ec9b29c07195ad284e63d548cd0a6fe358cc775bd6c1608d2c905", "result": "valid" }, { "tcId": 5, "comment": "", "flags": [ "Valid" ], "msg": "313233343030", "sig": "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bf0cf5b3a289976458a1be6277a5055545253b45b07dcc1abd96c8b989c00f301", "result": "valid" }, { "tcId": 6, "comment": "", "flags": [ "Valid" ], "msg": "000000000000000000000000", "sig": "d46543bfb892f84ec124dcdfc847034c19363bf3fc2fa89b1267833a14856e52e60736918783f950b6f1dd8d40dc343247cd43ce054c2d68ef974f7ed0f3c60f", "result": "valid" }, { "tcId": 7, "comment": "", "flags": [ "Valid" ], "msg": "6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "sig": "879350045543bc14ed2c08939b68c30d22251d83e018cacbaf0c9d7a48db577e80bdf76ce99e5926762bc13b7b3483260a5ef63d07e34b58eb9c14621ac92f00", "result": "valid" }, { "tcId": 8, "comment": "", "flags": [ "Valid" ], "msg": "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60", "sig": "7bdc3f9919a05f1d5db4a3ada896094f6871c1f37afc75db82ec3147d84d6f237b7e5ecc26b59cfea0c7eaf1052dc427b0f724615be9c3d3e01356c65b9b5109", "result": "valid" }, { "tcId": 9, "comment": "", "flags": [ "Valid" ], "msg": "ffffffffffffffffffffffffffffffff", "sig": "5dbd7360e55aa38e855d6ad48c34bd35b7871628508906861a7c4776765ed7d1e13d910faabd689ec8618b78295c8ab8f0e19c8b4b43eb8685778499e943ae04", "result": "valid" } ] }, { "type": "EddsaVerify", "source": { "name": "google-wycheproof", "version": "0.9rc5" }, "publicKey": { "type": "EDDSAPublicKey", "curve": "edwards25519", "keySize": 255, "pk": "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" }, "publicKeyDer": "302a300506032b65700321007d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAfU0Of2FTpptiQrUiq77mhf2kQg+INLEIw72uNp71Sfo=\n-----END PUBLIC KEY-----\n", "publicKeyJwk": { "kty": "OKP", "crv": "Ed25519", "kid": "none", "x": "fU0Of2FTpptiQrUiq77mhf2kQg-INLEIw72uNp71Sfo" }, "tests": [ { "tcId": 10, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "result": "invalid" }, { "tcId": 11, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", "result": "invalid" }, { "tcId": 12, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "0000000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", "result": "invalid" }, { "tcId": 13, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "0000000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", "result": "invalid" }, { "tcId": 14, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "0000000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "result": "invalid" }, { "tcId": 15, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "result": "invalid" }, { "tcId": 16, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "01000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", "result": "invalid" }, { "tcId": 17, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "0100000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", "result": "invalid" }, { "tcId": 18, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "0100000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", "result": "invalid" }, { "tcId": 19, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "0100000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "result": "invalid" }, { "tcId": 20, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000", "result": "invalid" }, { "tcId": 21, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000000", "result": "invalid" }, { "tcId": 22, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", "result": "invalid" }, { "tcId": 23, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", "result": "invalid" }, { "tcId": 24, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "result": "invalid" }, { "tcId": 25, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", "result": "invalid" }, { "tcId": 26, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0100000000000000000000000000000000000000000000000000000000000000", "result": "invalid" }, { "tcId": 27, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", "result": "invalid" }, { "tcId": 28, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", "result": "invalid" }, { "tcId": 29, "comment": "special values for r and s", "flags": [ "InvalidSignature" ], "msg": "3f", "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "result": "invalid" } ] }, { "type": "EddsaVerify", "source": { "name": "google-wycheproof", "version": "0.9rc5" }, "publicKey": { "type": "EDDSAPublicKey", "curve": "edwards25519", "keySize": 255, "pk": "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa" }, "publicKeyDer": "302a300506032b65700321007d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAfU0Of2FTpptiQrUiq77mhf2kQg+INLEIw72uNp71Sfo=\n-----END PUBLIC KEY-----\n", "publicKeyJwk": { "kty": "OKP", "crv": "Ed25519", "kid": "none", "x": "fU0Of2FTpptiQrUiq77mhf2kQg-INLEIw72uNp71Sfo" }, "tests": [ { "tcId": 30, "comment": "empty signature", "flags": [ "TruncatedSignature" ], "msg": "54657374", "sig": "", "result": "invalid" }, { "tcId": 31, "comment": "s missing", "flags": [ "TruncatedSignature" ], "msg": "54657374", "sig": "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0", "result": "invalid" }, { "tcId": 32, "comment": "signature too short", "flags": [ "TruncatedSignature" ], "msg": "54657374", "sig": "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946", "result": "invalid" }, { "tcId": 33, "comment": "signature too long", "flags": [ "SignatureWithGarbage" ], "msg": "54657374", "sig": "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d2020", "result": "invalid" }, { "tcId": 34, "comment": "include pk in signature", "flags": [ "SignatureWithGarbage" ], "msg": "54657374", "sig": "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", "result": "invalid" }, { "tcId": 35, "comment": "prepending 0 byte to signature", "flags": [ "SignatureWithGarbage" ], "msg": "54657374", "sig": "007c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", "result": "invalid" }, { "tcId": 36, "comment": "prepending 0 byte to s", "flags": [ "SignatureWithGarbage" ], "msg": "54657374", "sig": "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0007a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", "result": "invalid" }, { "tcId": 37, "comment": "appending 0 byte to signature", "flags": [ "SignatureWithGarbage" ], "msg": "54657374", "sig": "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d00", "result": "invalid" }, { "tcId": 38, "comment": "removing 0 byte from signature", "flags": [ "CompressedSignature" ], "msg": "546573743137", "sig": "93de3ca252426c95f735cb9edd92e83321ac62372d5aa5b379786bae111ab6b17251330e8f9a7c30d6993137c596007d7b001409287535ac4804e662bc58a3",Showing the first 500 of 3361 diff lines for this file. This diff is INCOMPLETE; read the file or clone the repository for the rest.
test/wasm/.gitignoreadded
# The probe resolves sigil-crypto from ../.. and its lock would record the# local HEAD sha, which goes stale on every commit. run-wasm-test.mjs prints# the resolved versions instead.sigil.locktest/wasm/gen-fixtures.shadded
#!/bin/sh# Embed the minisign fixtures into test/wasm/src/crypto-probe/fixtures.sgl as# hex, so the probe can run where there is no filesystem (wasm in Node).set -euHERE=$(cd "$(dirname "$0")" && pwd)FIX="$HERE/../fixtures/minisign"OUT="$HERE/src/crypto-probe/fixtures.sgl"hex() { od -An -tx1 -v "$1" | tr -d ' \n'; }{ echo ";;; GENERATED by test/wasm/gen-fixtures.sh from test/fixtures/minisign." echo ";;; Do not edit by hand." echo "(define-library (crypto-probe fixtures)" echo " (export fixture)" echo " (import (sigil core) (sigil math))" echo " (begin" echo " (define (hex->bv s)" echo " (let* ((n (quotient (string-length s) 2))" echo " (bv (make-bytevector n 0)))" echo " (let loop ((i 0))" echo " (if (< i n)" echo " (begin" echo " (bytevector-u8-set! bv i (string->number (substring s (* 2 i) (+ 2 (* 2 i))) 16))" echo " (loop (+ i 1)))" echo " bv))))" echo " (define fixtures" echo " (list" for f in a.pub b.pub hello.txt hello.txt.ED.minisig hello.txt.Ed.minisig \ hello.txt.keyb.minisig binary.bin binary.bin.ED.minisig \ registry.json registry.json.minisig; do [ -s "$FIX/$f" ] || { echo "REFUSING: missing or empty fixture $f" >&2; exit 1; } printf ' (cons "%s" "%s")\n' "$f" "$(hex "$FIX/$f")" done echo " ))" echo " ;; The fixture's bytes; raises for an unknown name." echo " (define (fixture name)" echo " (let ((entry (assoc name fixtures)))" echo " (if entry" echo " (hex->bv (cdr entry))" echo " (error (string-append \"no such fixture: \" name)))))))"} > "$OUT"echo "wrote $OUT ($(wc -c < "$OUT") bytes)"test/wasm/package.sgladded
;;; sigil-crypto wasm probe: builds the same checks for the host and for;;; wasm32-wasi so test/wasm/run-wasm-test.mjs can compare them. Not;;; published; it exists to prove the narrow wasm build (Ed25519, BLAKE2b,;;; minisign) works and that the Mbed TLS procedures fail clearly there.;;;;;; cd test/wasm && sigil deps install;;; node run-wasm-test.mjs (builds both configs, runs, compares)(package name: "sigil-crypto-wasm-probe" version: "0.1.0" sigil: "0.22" description: "wasm and host differential probe for sigil-crypto" license: "BSD-3-Clause" entry: '(crypto-probe main) configs: (list ;; Host build: the reference output. (config name: 'host output-dir: "build/host" debug?: #f optimize: 2 bundle?: #t) ;; Static musl build: the release-binary shape. (config name: 'static output-dir: "build/static" toolchain: 'zig target: "x86_64-linux-musl" static?: #t debug?: #f optimize: 2 bundle?: #t) ;; Browser-shaped build: wasm32-wasi through zig with native codegen, ;; the shape Crash The Stack ships. The eval ABI is force-exported so ;; the Node harness can call the gated procedures by name. (config name: 'web output-dir: "build/web" toolchain: 'zig target: "wasm32-wasi" backend: 'native debug?: #f optimize: 2 c-flags: (with-sigil-c-flags '("-std=c99" "-D_GNU_SOURCE" "-D__SIGIL_WASM__" "-Wall" "-O2")) link-flags: '("-Wl,--export=sigil_wasm_init" "-Wl,--export=sigil_wasm_start" "-Wl,--export=sigil_wasm_eval_string_length" "-Wl,--export=sigil_wasm_last_result_length" "-Wl,--export=sigil_wasm_copy_result" "-Wl,--export=malloc" "-Wl,--export=free" "-lc") features: '(web wasm))) dependencies: (list (from-path dir: "../.." package: "sigil-crypto") (from-git url: "codeberg:sigil/sigil" package: "sigil-lib" version: ">=0.22") (from-git url: "codeberg:sigil/sigil" package: "sigil-stdlib" version: ">=0.22") (from-git url: "codeberg:sigil/sigil" package: "sigil-wasm-runtime" version: ">=0.22")) tasks: (list (task name: 'build configs: '(web) description: "Build the wasm probe" steps: (list (compile-sigil-modules sources: "src/**/*.sgl") (link-web-application name: "sigil-crypto-wasm-probe")))))test/wasm/run-wasm-test.mjsadded
#!/usr/bin/env node//// sigil-crypto wasm differential test.//// 1. Builds test/wasm for the host ('host), static musl ('static) and wasm32-wasi with// native codegen ('web config), unless SIGIL_PROBE_SKIP_BUILD=1.// 2. Runs the host bundle and the wasm module (in Node with a minimal WASI// shim) and requires their outputs to match line for line, except lines// starting "target:", which must show the Mbed TLS procedures working on// the host and refusing with "not available on wasm" on wasm.// 3. Checks every line against its expected value, so two identical wrong// outputs cannot pass.// 4. Drift gate: reads native/crypto.c, requires the wasm stub list to name// exactly the Mbed TLS natives the host registers, then calls each one// in the wasm module through the eval ABI and requires the refusal.//// Run from anywhere: node test/wasm/run-wasm-test.mjs// Needs: sigil on PATH, guix (for binaryen), node.// Exit 0 only on PASS. SETUP-FAILED (exit 2) when something could not be// built or found, so nothing was tested.import { spawnSync } from "node:child_process";import fs from "node:fs";import path from "node:path";import { fileURLToPath } from "node:url";const probeDir = path.dirname(fileURLToPath(import.meta.url));const repoRoot = path.resolve(probeDir, "../..");const hostBin = path.join(probeDir, "build/host/bin/sigil-crypto-wasm-probe");const wasmPath = path.join(probeDir, "build/web/sigil-crypto-wasm-probe.wasm");const staticBin = path.join(probeDir, "build/static/bin/sigil-crypto-wasm-probe");const cryptoC = path.join(repoRoot, "native/crypto.c");let failures = 0;function fail(msg) { console.error(`FAIL: ${msg}`); failures += 1;}function setupFailed(msg) { console.error(`SETUP-FAILED: ${msg}`); process.exit(2);}// Every non-target line and its expected value. A missing line fails.const EXPECTED = { "blake2b-512 abc": "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923", "blake2b-512 binary.bin": null, // checked against coreutils b2sum below "ed25519 rfc8032 test 2 verifies": "#t", "ed25519 rfc8032 test 3 verifies": "#t", "ed25519 test 2 flipped message": "#f", "ed25519 test 3 flipped signature": "#f", "ed25519 test 3 flipped key": "#f", "ed25519 test 2 public key": "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", "ed25519 test 2 signature": "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", "ed25519 31-byte key": "ed25519-verify: public key must be 32 bytes", "minisign key a id": null, // checked against a.pub's comment line below "minisign hello ED": "sigil-crypto fixture: prehashed", "minisign hello Ed": "sigil-crypto fixture: legacy", "minisign binary ED": "sigil-crypto fixture: binary", "minisign registry root": "registry=pkg.usesigil.org path=/v1/meta/registry.json seq=1 ts=2026-07-30T08:04:54Z", "minisign registry tampered": "bad-signature", "minisign hello tampered": "bad-signature", "minisign key mismatch": "key-id-mismatch", "minisign key b": "#f", "minisign legacy refused": "legacy-refused", "minisign bad key line": "minisign: public key has the wrong base64 length", "timing-safe-equal?": "#t",};const TARGET_LINES = ["target: sha256", "target: base64url-encode"];const WASM_REFUSAL = "not available on wasm";function run(cmd, args, opts = {}) { const r = spawnSync(cmd, args, { encoding: "utf8", ...opts }); return { status: r.status, out: (r.stdout || "") + (r.stderr || ""), error: r.error };}function build() { // cwd is the probe directory: sigil resolves the project and its // dependencies from cwd, not from the location of any file. const host = run("nice", ["-n", "19", "sigil", "build", "--config", "host"], { cwd: probeDir }); if (host.status !== 0) { process.stdout.write(host.out); setupFailed(`host build failed (exit ${host.status})`); } const stat = run("nice", ["-n", "19", "sigil", "build", "--config", "static"], { cwd: probeDir }); if (stat.status !== 0) { process.stdout.write(stat.out); setupFailed(`static musl build failed (exit ${stat.status})`); } const web = run( "guix", ["shell", "binaryen", "--", "sh", "-c", "command -v wasm-opt >/dev/null && nice -n 19 sigil build --config web"], { cwd: probeDir }, ); if (web.status !== 0) { process.stdout.write(web.out); setupFailed(`web build failed (exit ${web.status})`); } if (/vendor\/mbedtls\/library/.test(web.out)) { fail("the web build compiled Mbed TLS sources; the wasm build must skip them"); }}function describe(file) { if (!fs.existsSync(file)) setupFailed(`missing artifact ${file}`); const st = fs.statSync(file); console.log(`artifact ${file} ${st.size} bytes, mtime ${st.mtime.toISOString()}`);}// Minimal WASI preview1 shim, after sigil's test-native-facade-reexport.mjs.function makeWasi(module, output) { let instance = null; const decoder = new TextDecoder(); const view = () => new DataView(instance.exports.memory.buffer); const u8 = () => new Uint8Array(instance.exports.memory.buffer); const known = { fd_write(fd, iovsPtr, iovsLen, nwrittenPtr) { let written = 0; let text = ""; for (let i = 0; i < iovsLen; i += 1) { const ptr = view().getUint32(iovsPtr + i * 8, true); const len = view().getUint32(iovsPtr + i * 8 + 4, true); text += decoder.decode(u8().subarray(ptr, ptr + len)); written += len; } if (fd === 1 || fd === 2) output.push(text); if (nwrittenPtr) view().setUint32(nwrittenPtr, written, true); return 0; }, proc_exit(code) { throw new Error(`WASI proc_exit(${code})`); }, args_sizes_get(argcPtr, argvBufSizePtr) { view().setUint32(argcPtr, 0, true); view().setUint32(argvBufSizePtr, 0, true); return 0; }, environ_sizes_get(countPtr, bufSizePtr) { view().setUint32(countPtr, 0, true); view().setUint32(bufSizePtr, 0, true); return 0; }, clock_time_get(_id, _precision, timePtr) { view().setBigUint64(timePtr, BigInt(Date.now()) * 1000000n, true); return 0; }, // Ed25519 verification needs no entropy. The runtime may still ask // (hash seeds); this shim answers from Math.random, which is fine for // a test and would not be for anything that generates keys. random_get(ptr, len) { const bytes = u8(); for (let i = 0; i < len; i += 1) bytes[ptr + i] = (Math.random() * 256) | 0; return 0; }, fd_fdstat_get(_fd, statPtr) { u8().fill(0, statPtr, statPtr + 24); view().setUint8(statPtr, 2); return 0; }, fd_fdstat_set_flags() { return 0; }, fd_filestat_get(_fd, statPtr) { u8().fill(0, statPtr, statPtr + 64); view().setUint8(statPtr + 16, 2); return 0; }, fd_close() { return 0; }, fd_seek() { return 0; }, fd_fdstat_set_rights() { return 0; }, fd_prestat_get() { return 8; }, fd_prestat_dir_name() { return 8; }, path_open() { return 44; }, }; const wasi = {}; for (const entry of WebAssembly.Module.imports(module)) { if (entry.module === "wasi_snapshot_preview1") { wasi[entry.name] = known[entry.name] || (() => 0); } } return { imports: { wasi_snapshot_preview1: wasi }, setInstance(value) { instance = value; }, };}function parseLines(text) { const map = new Map(); const order = []; for (const line of text.split("\n")) { const i = line.indexOf(": "); if (i < 0) continue; const key = line.startsWith("target: ") ? line.slice(0, line.indexOf(": ", 8)) : line.slice(0, i); const value = line.slice(key.length + 2); map.set(key, value); order.push(key); } return { map, order };}async function runWasm() { const output = []; const module = await WebAssembly.compile(fs.readFileSync(wasmPath)); const wasi = makeWasi(module, output); const extra = {}; for (const entry of WebAssembly.Module.imports(module)) { if (entry.module === "wasi_snapshot_preview1") continue; extra[entry.module] ??= {}; if (entry.kind === "function") extra[entry.module][entry.name] = () => 0; } const instance = await WebAssembly.instantiate(module, { ...wasi.imports, ...extra }); wasi.setInstance(instance); const ex = instance.exports; for (const sym of ["sigil_wasm_init", "sigil_wasm_start", "sigil_wasm_eval_string_length", "malloc"]) { if (typeof ex[sym] !== "function") setupFailed(`wasm module does not export ${sym}`); } if (ex.sigil_wasm_init() !== 0) setupFailed("sigil_wasm_init failed"); const startRc = ex.sigil_wasm_start(); const compiled = output.join(""); output.length = 0; const encoder = new TextEncoder(); const evalStr = (expr) => { const bytes = encoder.encode(expr); const ptr = ex.malloc(bytes.length + 1); const mem = new Uint8Array(ex.memory.buffer); mem.set(bytes, ptr); mem[ptr + bytes.length] = 0; const rc = ex.sigil_wasm_eval_string_length(ptr); ex.free(ptr); if (rc < 0) return { rc, result: output.splice(0).join("") }; const len = ex.sigil_wasm_last_result_length(); const dest = ex.malloc(Math.max(len, 1)); const n = ex.sigil_wasm_copy_result(dest, len); const text = new TextDecoder().decode(new Uint8Array(ex.memory.buffer, dest, n)); ex.free(dest); return { rc, result: text.replace(/^"|"$/g, "") }; }; return { compiled, startRc, evalStr };}function checkExpected(label, lines) { for (const [key, want] of Object.entries(EXPECTED)) { if (!lines.map.has(key)) { fail(`${label}: line "${key}" missing`); } else if (want !== null && lines.map.get(key) !== want) { fail(`${label}: "${key}" = ${JSON.stringify(lines.map.get(key))}, want ${JSON.stringify(want)}`); } }}async function main() { if (process.env.SIGIL_PROBE_SKIP_BUILD !== "1") build(); const lock = path.join(probeDir, "sigil.lock"); if (fs.existsSync(lock)) { const entries = [...fs.readFileSync(lock, "utf8").matchAll(/name: "([^"]+)"[\s\S]*?sha: "([^"]*)"[\s\S]*?version: "([^"]+)"/g)]; for (const [, name, sha, version] of entries) { if (name === "sigil-crypto") continue; // from ../..; its lock sha is stale by design console.log(`input ${name} ${version} ${sha.slice(0, 12)}`); } } { const head = run("git", ["-C", repoRoot, "rev-parse", "HEAD"]).out.trim(); const dirty = run("git", ["-C", repoRoot, "status", "--porcelain", "--", ".", ":!test/wasm/sigil.lock"]).out.trim() !== ""; console.log(`input sigil-crypto (from ../..) ${head.slice(0, 12)}${dirty ? " +uncommitted changes" : ""}`); } describe(hostBin); describe(wasmPath); describe(staticBin); // Host run. cwd is the probe dir, for the same reason as the build. const host = run(hostBin, [], { cwd: probeDir }); if (host.status !== 0 || !host.out.includes("REACHED-END")) { process.stdout.write(host.out); setupFailed(`host probe did not complete (exit ${host.status})`); } // Static musl build: must print exactly what the host prints, target // lines included (Mbed TLS is built there). const stat = run(staticBin, [], { cwd: probeDir }); if (stat.status !== 0 || stat.out !== host.out) fail(`static musl output differs from host (exit ${stat.status})`); else console.log(`static musl: output identical to host (${host.out.trim().split("\n").length} lines)`); const wasm = await runWasm(); process.stdout.write(`=== wasm (sigil_wasm_start -> ${wasm.startRc}) ===\n${wasm.compiled}`); if (!wasm.compiled.includes("REACHED-END")) fail("wasm probe did not reach the end"); const h = parseLines(host.out); const w = parseLines(wasm.compiled); // Independent values for the two lines EXPECTED leaves open. const b2 = run("b2sum", [path.join(repoRoot, "test/fixtures/minisign/binary.bin")]); if (b2.status !== 0) setupFailed("b2sum did not run"); EXPECTED["blake2b-512 binary.bin"] = b2.out.split(" ")[0]; const pubComment = fs.readFileSync(path.join(repoRoot, "test/fixtures/minisign/a.pub"), "utf8").split("\n")[0]; EXPECTED["minisign key a id"] = pubComment.slice(-16); checkExpected("host", h); checkExpected("wasm", w); // Line-for-line agreement outside the target lines. const hOrder = h.order.filter((k) => !k.startsWith("target: ")); const wOrder = w.order.filter((k) => !k.startsWith("target: ")); if (JSON.stringify(hOrder) !== JSON.stringify(wOrder)) fail("host and wasm print different line sequences"); let agreed = 0; for (const key of hOrder) { if (h.map.get(key) === w.map.get(key)) agreed += 1; else fail(`differential: "${key}" host=${JSON.stringify(h.map.get(key))} wasm=${JSON.stringify(w.map.get(key))}`); } console.log(`differential: ${agreed}/${hOrder.length} lines agree`); for (const key of TARGET_LINES) { if (h.map.get(key) !== "no-error") fail(`host ${key}: ${JSON.stringify(h.map.get(key))}, want no-error`); if (!(w.map.get(key) || "").includes(WASM_REFUSAL)) fail(`wasm ${key}: ${JSON.stringify(w.map.get(key))}, want the refusal`); } // Drift gate: the stub list in crypto.c against the host registrations. const src = fs.readFileSync(cryptoC, "utf8"); const stubBlock = src.match(/mbedtls_only_natives\[\] = \{([\s\S]*?)NULL/); if (!stubBlock) setupFailed("could not find mbedtls_only_natives in crypto.c"); const stubs = [...stubBlock[1].matchAll(/"([^"]+)"/g)].map((m) => m[1]).sort(); const registered = [...src.matchAll(/REGISTER_AND_EXPORT\("([^"]+)"/g)].map((m) => m[1]).sort(); if (registered.length < 20) setupFailed(`found only ${registered.length} REGISTER_AND_EXPORT names`); if (JSON.stringify(stubs) !== JSON.stringify(registered)) { fail(`wasm stub list != host Mbed TLS registrations\n stubs only: ${stubs.filter((s) => !registered.includes(s))}\n host only: ${registered.filter((s) => !stubs.includes(s))}`); } let refused = 0; for (const name of registered) { const { rc, result } = wasm.evalStr( `(begin (import (sigil crypto)) (guard (e (#t (if (error-object? e) (error-object-message e) "non-error raise"))) (${name}) "no-error"))`, ); if (rc >= 0 && result.includes(WASM_REFUSAL)) refused += 1; else fail(`wasm eval (${name}): rc=${rc} ${JSON.stringify(result)}`); } console.log(`drift gate: ${registered.length} Mbed TLS natives, ${refused} refuse on wasm`); // Positive control for the eval path itself: it must be able to succeed. const control = wasm.evalStr(`(begin (import (sigil crypto)) (number->string (bytevector-length (blake2b-512 "abc"))))`); if (control.rc < 0 || control.result !== "64") fail(`eval positive control: rc=${control.rc} ${JSON.stringify(control.result)}`); if (failures) { console.error(`FAIL: ${failures} check(s) failed`); process.exit(1); } console.log("PASS: sigil-crypto wasm build matches the host; Mbed TLS procedures refuse on wasm");}await main();test/wasm/src/crypto-probe/fixtures.sgladded
;;; GENERATED by test/wasm/gen-fixtures.sh from test/fixtures/minisign.;;; Do not edit by hand.(define-library (crypto-probe fixtures) (export fixture) (import (sigil core) (sigil math)) (begin (define (hex->bv s) (let* ((n (quotient (string-length s) 2)) (bv (make-bytevector n 0))) (let loop ((i 0)) (if (< i n) (begin (bytevector-u8-set! bv i (string->number (substring s (* 2 i) (+ 2 (* 2 i))) 16)) (loop (+ i 1))) bv)))) (define fixtures (list (cons "a.pub" "756e7472757374656420636f6d6d656e743a206d696e697369676e207075626c6963206b657920313445423346423239304239363230340a5257514559726d51736a2f72464f49547836574f666b314a56754f736c4a56377a777668366d4d334e43444a48687359666c6c634153414d0a") (cons "b.pub" "756e7472757374656420636f6d6d656e743a206d696e697369676e207075626c6963206b657920433138413242433839433131313645340a5257546b466847637943754b77636161794b67714268463474584262784c6c596435597a7752414a6945312b55424e2f566a734f36656d740a") (cons "hello.txt" "68656c6c6f2c206d696e697369676e0a") (cons "hello.txt.ED.minisig" "756e7472757374656420636f6d6d656e743a207369676e61747572652066726f6d206d696e697369676e20736563726574206b65790a5255514559726d51736a2f724647417954744b512b34785a4b2b30673366544d78727764775678375a6a6a393948413777746b494c704270354b4a4b633630513647622f2b5945424f464d47644f2f69457a507345315374456c59744b536c6664674d3d0a7472757374656420636f6d6d656e743a20736967696c2d63727970746f20666978747572653a207072656861736865640a6757456d34687931356a54394a4e517154716c6c6335387742647075316d3462444a79636d677162504b6b722f5a622b51752f522b523561534879336b4c3351377679344c5a74414253644750344f595075546241673d3d0a") (cons "hello.txt.Ed.minisig" "756e7472757374656420636f6d6d656e743a207369676e61747572652066726f6d206d696e697369676e20736563726574206b65790a5257514559726d51736a2f724642796b59426163384f654b69624a53594b63642b7672564d513434426e6d70624269626732524d6937356143347a4a4b6e506232713459776d554566616e665563634a344e6e39756a476d6b7875692f4d73316351383d0a7472757374656420636f6d6d656e743a20736967696c2d63727970746f20666978747572653a206c65676163790a6e3346334b6255765a454e5a4d72674d656b38634d343872526174476257306e3552684b505237594b637577416277396262304e6351706f3633355042775134516a6f47356d4f584162557a317453687a314a7741673d3d0a") (cons "hello.txt.keyb.minisig" "756e7472757374656420636f6d6d656e743a207369676e61747572652066726f6d206d696e697369676e20736563726574206b65790a5255546b466847637943754b7759544d556f345838636465433363334c664731725344667a304d6e6341344a55363062353152656155533533544f4b307a6a6e594873354a5773686374457a554d414c73493069776d2b364d563264416f72305a676f3d0a7472757374656420636f6d6d656e743a20736967696c2d63727970746f20666978747572653a206b657920620a32667a314277766f35386777676b6554483443587a79484133634f365969423975325a656a6e47346d495a47305a374b7158763153544d6f6e5a307931354259356e3535476e512b3937647866612b6c52704f6c41673d3d0a") (cons "binary.bin" "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") (cons "binary.bin.ED.minisig" "756e7472757374656420636f6d6d656e743a207369676e61747572652066726f6d206d696e697369676e20736563726574206b65790a5255514559726d51736a2f72464c5637755a7575444f5a6e64626c434731743768765341702b377376636d35436f38496d556e555232362f4664307a44614f2b55702b304e5253654c446c5a7a376f32694b466d6d324b534f5069682f5969692b51633d0a7472757374656420636f6d6d656e743a20736967696c2d63727970746f20666978747572653a2062696e6172790a7832334f395961554a63626d41414f6f5266357a536f52476a3867766c33666a4556356e4d746c43717a38694775443263304e6556622b74636f733930764d496b6a4f763748496c44446c7253332b4d6730696143413d3d0a") (cons "registry.json" "7b0a202022736368656d61223a20312c0a20202270726f746f636f6c223a20312c0a2020227265676973747279223a2022706b672e757365736967696c2e6f7267222c0a202022736571223a20312c0a20202275706461746564223a2022323032362d30372d33305430383a30343a35345a222c0a2020226b657973223a205b0a202020207b226964223a2243343545313135304432443346353541222c22616c676f726974686d223a226d696e697369676e2d65643235353139222c22726f6c6573223a5b22726f6f74225d2c227075626c69632d6b6579223a225257526139645053554246657842624c647a5a496675416d7543594c3733365565484337496264414f49597067474979446d575261514859222c22737461747573223a22616374697665227d2c0a202020207b226964223a2232314343394245333136433645304644222c22616c676f726974686d223a226d696e697369676e2d65643235353139222c22726f6c6573223a5b22696e646578225d2c227075626c69632d6b6579223a2252575439344d59573435764d49624964517572494d6b343649445a514d69487a6c50375677595150564e7a74784a77453233466b48755231222c22737461747573223a22616374697665227d2c0a202020207b226964223a2237463932423432363036304632463036222c22616c676f726974686d223a226d696e697369676e2d65643235353139222c22726f6c6573223a5b22746f6f6c636861696e225d2c227075626c69632d6b6579223a22525751474c7738474a725353667a756463792f766e4d67557a6f45557656646d5a78797a413230414a36675375736a516b33656233614255222c22737461747573223a22616374697665227d2c0a202020207b226964223a2244423141383238424430333446353935222c22616c676f726974686d223a226d696e697369676e2d65643235353139222c22726f6c6573223a5b227375627374697475746573225d2c227075626c69632d6b6579223a22525753563954545169344961327a7647674261636c48483877494334632f4531323439587265696b4a38673055342f7a2b76734d37377032222c22737461747573223a22616374697665227d2c0a202020207b226964223a2239383945463534463545393343373336222c22616c676f726974686d223a226d696e697369676e2d65643235353139222c22726f6c6573223a5b226368616e6e656c73225d2c227075626c69632d6b6579223a225257513278354e65542f57656d4773493361562f4738676e724c65765166746149594943326430364650636f5356376e316863616e306a30222c22737461747573223a22616374697665227d0a20205d2c0a2020226c6f67223a206e756c6c2c0a202022726570726f6475636962696c697479223a206e756c6c0a7d0a") (cons "registry.json.minisig" "756e7472757374656420636f6d6d656e743a207369676e61747572652066726f6d206d696e697369676e20736563726574206b65790a52555261396450535542466578474a4743366d2b6672345552583343362f31346237637638354662546775693464434f41524f6a2f784130567934536e35755862426c734f5739504259514e7a2b625a326676515072344f35712f2f2b626b4c6b51773d0a7472757374656420636f6d6d656e743a2072656769737472793d706b672e757365736967696c2e6f726720706174683d2f76312f6d6574612f72656769737472792e6a736f6e207365713d312074733d323032362d30372d33305430383a30343a35345a0a434c37584e576d56354b6c6f366249484538783249584631384c777148665a503272796e6d6f535072527a44434c4a746c4766772b4d4c783763514759535a6f2f4c6b346341324f474d46412f4f31517a59425943773d3d0a") )) ;; The fixture's bytes; raises for an unknown name. (define (fixture name) (let ((entry (assoc name fixtures))) (if entry (hex->bv (cdr entry)) (error (string-append "no such fixture: " name)))))))test/wasm/src/crypto-probe/main.sgladded
;;; The sigil-crypto wasm probe: one line per check, printed identically on;;; every target. test/wasm/run-wasm-test.mjs builds this for the host and;;; for wasm32-wasi, runs both, and requires the two outputs to match line;;; for line (except lines starting "target:", which say what the target;;; is expected to differ on), and each line to have its expected value.(define-library (crypto-probe main) (import (sigil core) (sigil io) (sigil math) (sigil crypto) (sigil crypto minisign) (crypto-probe fixtures)) (export main) (begin (define (hex->bv s) (let* ((n (quotient (string-length s) 2)) (bv (make-bytevector n 0))) (let loop ((i 0)) (if (< i n) (begin (bytevector-u8-set! bv i (string->number (substring s (* 2 i) (+ 2 (* 2 i))) 16)) (loop (+ i 1))) bv)))) (define (bv->hex bv) (let loop ((i 0) (acc '())) (if (< i (bytevector-length bv)) (let* ((b (bytevector-u8-ref bv i)) (h (number->string b 16))) (loop (+ i 1) (cons (if (< b 16) (string-append "0" h) h) acc))) (apply string-append (reverse acc))))) (define (flip-byte bv index) (let ((out (bytevector-copy bv))) (bytevector-u8-set! out index (bitwise-xor (bytevector-u8-ref out index) 1)) out)) ;; The message of whatever `thunk` raises, or "no-error". (define (raised-message thunk) (guard (e (#t (if (error-object? e) (error-object-message e) "non-error raise"))) (thunk) "no-error")) (define (show label value) (println "~a: ~a" label value)) ;; RFC 8032 section 7.1 TEST 2 and TEST 3. (define t2-seed (hex->bv "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb")) (define t2-pk (hex->bv "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c")) (define t2-msg (hex->bv "72")) (define t2-sig (hex->bv "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00")) (define t3-pk (hex->bv "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025")) (define t3-msg (hex->bv "af82")) (define t3-sig (hex->bv "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a")) (define (main . args) (let ((key-a (minisign-parse-public-key (fixture "a.pub"))) (key-b (minisign-parse-public-key (fixture "b.pub"))) (root (minisign-parse-public-key "RWRa9dPSUBFexBbLdzZIfuAmuCYL736UeHC7IbdAOIYpgGIyDmWRaQHY")) (hello (fixture "hello.txt")) (sig (lambda (name) (minisign-parse-signature (fixture name))))) (show "blake2b-512 abc" (bv->hex (blake2b-512 "abc"))) (show "blake2b-512 binary.bin" (bv->hex (blake2b-512 (fixture "binary.bin")))) (show "ed25519 rfc8032 test 2 verifies" (ed25519-verify t2-pk t2-msg t2-sig)) (show "ed25519 rfc8032 test 3 verifies" (ed25519-verify t3-pk t3-msg t3-sig)) (show "ed25519 test 2 flipped message" (ed25519-verify t2-pk (flip-byte t2-msg 0) t2-sig)) (show "ed25519 test 3 flipped signature" (ed25519-verify t3-pk t3-msg (flip-byte t3-sig 5))) (show "ed25519 test 3 flipped key" (ed25519-verify (flip-byte t3-pk 7) t3-msg t3-sig)) (show "ed25519 test 2 public key" (bv->hex (ed25519-public-key t2-seed))) (show "ed25519 test 2 signature" (bv->hex (ed25519-sign t2-seed t2-msg))) (show "ed25519 31-byte key" (raised-message (lambda () (ed25519-verify (make-bytevector 31 0) "m" t2-sig)))) (show "minisign key a id" (minisign-public-key-id key-a)) (show "minisign hello ED" (minisign-verify key-a (sig "hello.txt.ED.minisig") hello)) (show "minisign hello Ed" (minisign-verify key-a (sig "hello.txt.Ed.minisig") hello)) (show "minisign binary ED" (minisign-verify key-a (sig "binary.bin.ED.minisig") (fixture "binary.bin"))) (show "minisign registry root" (minisign-verify-prehashed root (sig "registry.json.minisig") (fixture "registry.json"))) (show "minisign registry tampered" (minisign-failure-reason root (sig "registry.json.minisig") (flip-byte (fixture "registry.json") 100) #t)) (show "minisign hello tampered" (minisign-failure-reason key-a (sig "hello.txt.ED.minisig") (flip-byte hello 0) #f)) (show "minisign key mismatch" (minisign-failure-reason key-a (sig "hello.txt.keyb.minisig") hello #f)) (show "minisign key b" (minisign-failure-reason key-b (sig "hello.txt.keyb.minisig") hello #f)) (show "minisign legacy refused" (minisign-failure-reason key-a (sig "hello.txt.Ed.minisig") hello #t)) (show "minisign bad key line" (raised-message (lambda () (minisign-parse-public-key "RWQ")))) (show "timing-safe-equal?" (timing-safe-equal? "abc" "abc")) ;; Differs by design: Mbed TLS is not built for wasm. (show "target: sha256" (raised-message (lambda () (sha256 "abc")))) (show "target: base64url-encode" (raised-message (lambda () (base64url-encode "abc")))) (println "REACHED-END") 0))))