The public history carried kat/__pycache__/mlkem768_reference.cpython-314.pyc, a compiled Python artifact embedding the operator's absolute local path. Text secret scanners do not read compiled binaries, which is exactly how it slipped through, and removing it from the tip would have left it reachable through the old root commits. So this repository is republished from a single clean root. This root also carries, from the previously unpublished line of work: - corrected LICENSE year, LICENSING.md, VERIFY-POLICY.md, and CITATIONS-UNRESOLVED.md remeasured 2026-08-11 (101 paths, README aligned) - O-018: run_consensus_verification.py ran 19 of 29 models and reported PASS; it now runs all 29, and computemarket_smt.py gains resolveByTimeout / reclaimUnsettled cases plus a negative control - O-006: the word 'audited' removed from next to Bouncy Castle, twice, after a concurrent edit resurrected it - O-014: prior art named and dated - Algorand's native falcon_verify shipped about ten months before AERE's precompiles; the primacy claim is withdrawn where it was implied - bench/ scripts parametrized so they actually run for an outsider (the earlier textual sanitization left $STAGING unexpanded inside Python strings) - AIP-2/AIP-3 errata with measured figures, spec remeasurements at 2026-08-01, and the spec-zk-stack retractions (owner is an operational key, not the Foundation; 'maximally sound' withdrawn; aggregator V1 deprecated) The redacted bench-host environment files from the sanitized line are kept exactly as published; the unredacted local variants are not carried.
120 lines
5.2 KiB
Java
120 lines
5.2 KiB
Java
package org.hyperledger.besu.evm.precompile;
|
|
|
|
// AERE Falcon HashToPoint precompile (0x0AE7) KAT + vector generator.
|
|
//
|
|
// 1. Generates real Falcon-512 signatures with Bouncy Castle, extracts each
|
|
// (nonce, message), and runs them through the REAL HashToPointPrecompiledContract.
|
|
// 2. Emits two files:
|
|
// hashtopoint_vectors.txt : tcId|logn|nonce_hex|message_hex|precompile_coeffs_hex
|
|
// (the coeffs are the precompile output; htp_reference.py recomputes them
|
|
// independently with Python's stdlib SHAKE256 and must match)
|
|
// falcon512_bench_vectors.txt : tcId|pk_hex|sm_hex
|
|
// (real (pk, signed-message) pairs for the on-chain Falcon-verify benchmark
|
|
// and the precompile-vs-in-EVM integration check)
|
|
// 3. Adds deterministic edge vectors (all-zero nonce, empty message, a logn=10 case).
|
|
|
|
import org.apache.tuweni.bytes.Bytes;
|
|
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
|
|
import org.bouncycastle.pqc.crypto.falcon.*;
|
|
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
|
|
import java.io.*;
|
|
import java.nio.file.*;
|
|
import java.security.SecureRandom;
|
|
import java.util.*;
|
|
|
|
public class HashToPointKat {
|
|
|
|
static String hex(byte[] b) {
|
|
StringBuilder s = new StringBuilder();
|
|
for (byte x : b) s.append(String.format("%02x", x));
|
|
return s.toString();
|
|
}
|
|
|
|
static HashToPointPrecompiledContract PC =
|
|
new HashToPointPrecompiledContract(new CancunGasCalculator());
|
|
|
|
// Run the precompile for logn || nonce || message, return coeff bytes (2*n).
|
|
static byte[] htp(int logn, byte[] nonce, byte[] message) {
|
|
byte[] input = new byte[1 + nonce.length + message.length];
|
|
input[0] = (byte) logn;
|
|
System.arraycopy(nonce, 0, input, 1, nonce.length);
|
|
System.arraycopy(message, 0, input, 1 + nonce.length, message.length);
|
|
Bytes out = PC.computePrecompile(Bytes.wrap(input), null).output();
|
|
return out == null ? new byte[0] : out.toArrayUnsafe();
|
|
}
|
|
|
|
public static void main(String[] a) throws Exception {
|
|
String htpVec = a.length > 0 ? a[0] : "hashtopoint_vectors.txt";
|
|
String benchVec = a.length > 1 ? a[1] : "falcon512_bench_vectors.txt";
|
|
int nSigs = a.length > 2 ? Integer.parseInt(a[2]) : 8;
|
|
|
|
SecureRandom rnd = new SecureRandom();
|
|
StringBuilder htp = new StringBuilder();
|
|
StringBuilder bench = new StringBuilder();
|
|
int tc = 0;
|
|
|
|
// ---- real Falcon-512 signatures ----
|
|
FalconKeyPairGenerator kg = new FalconKeyPairGenerator();
|
|
kg.init(new FalconKeyGenerationParameters(rnd, FalconParameters.falcon_512));
|
|
for (int i = 0; i < nSigs; i++) {
|
|
AsymmetricCipherKeyPair kp = kg.generateKeyPair();
|
|
FalconPublicKeyParameters pub = (FalconPublicKeyParameters) kp.getPublic();
|
|
FalconPrivateKeyParameters priv = (FalconPrivateKeyParameters) kp.getPrivate();
|
|
byte[] message = ("AERE Falcon HashToPoint KAT vector #" + i + " (isolated fork)").getBytes();
|
|
|
|
FalconSigner fs = new FalconSigner();
|
|
fs.init(true, priv);
|
|
byte[] bcSig = fs.generateSignature(message); // (0x30|logn) || nonce(40) || compressed
|
|
byte[] nonce = Arrays.copyOfRange(bcSig, 1, 41);
|
|
byte[] compressed = Arrays.copyOfRange(bcSig, 41, bcSig.length);
|
|
|
|
// HashToPoint vector
|
|
byte[] coeffs = htp(9, nonce, message);
|
|
htp.append(tc).append("|9|").append(hex(nonce)).append("|").append(hex(message))
|
|
.append("|").append(hex(coeffs)).append("\n");
|
|
|
|
// Falcon bench vector: pk = 0x09 || h ; sm = sigLen(2) || nonce(40) || message || (0x29||compressed)
|
|
byte[] h = pub.getH();
|
|
byte[] pk = new byte[1 + h.length];
|
|
pk[0] = 0x09;
|
|
System.arraycopy(h, 0, pk, 1, h.length);
|
|
byte[] sigBlock = new byte[1 + compressed.length];
|
|
sigBlock[0] = (byte) 0x29; // 0x20 | logn(9)
|
|
System.arraycopy(compressed, 0, sigBlock, 1, compressed.length);
|
|
int sigLen = sigBlock.length;
|
|
ByteArrayOutputStream sm = new ByteArrayOutputStream();
|
|
sm.write((sigLen >> 8) & 0xff);
|
|
sm.write(sigLen & 0xff);
|
|
sm.write(nonce);
|
|
sm.write(message);
|
|
sm.write(sigBlock);
|
|
bench.append(tc).append("|").append(hex(pk)).append("|").append(hex(sm.toByteArray())).append("\n");
|
|
tc++;
|
|
}
|
|
|
|
// ---- deterministic edge vectors (HashToPoint only) ----
|
|
byte[] zeroNonce = new byte[40];
|
|
byte[][] edgeMsgs = new byte[][] {
|
|
new byte[0],
|
|
"abc".getBytes(),
|
|
"The quick brown fox jumps over the lazy dog".getBytes()
|
|
};
|
|
for (byte[] msg : edgeMsgs) {
|
|
byte[] c9 = htp(9, zeroNonce, msg);
|
|
htp.append(tc).append("|9|").append(hex(zeroNonce)).append("|").append(hex(msg))
|
|
.append("|").append(hex(c9)).append("\n");
|
|
tc++;
|
|
}
|
|
// one Falcon-1024 sized (logn=10) HashToPoint vector
|
|
byte[] c10 = htp(10, zeroNonce, "AERE Falcon-1024 HashToPoint".getBytes());
|
|
htp.append(tc).append("|10|").append(hex(zeroNonce)).append("|")
|
|
.append(hex("AERE Falcon-1024 HashToPoint".getBytes())).append("|").append(hex(c10)).append("\n");
|
|
tc++;
|
|
|
|
Files.write(Paths.get(htpVec), htp.toString().getBytes());
|
|
Files.write(Paths.get(benchVec), bench.toString().getBytes());
|
|
System.out.println("HashToPoint: wrote " + tc + " vectors to " + htpVec
|
|
+ " and " + nSigs + " Falcon bench vectors to " + benchVec);
|
|
}
|
|
}
|