add pow tests (vectors from tor), don't pass yet

This commit is contained in:
zzz
2024-01-02 10:14:29 -05:00
parent 5f3794a57c
commit 98e9bc2a3c
3 changed files with 216 additions and 11 deletions

46
LICENSE-tor Normal file
View File

@ -0,0 +1,46 @@
This file contains the license for Tor,
a free software project to provide anonymity on the Internet.
It also lists the licenses for other components used by Tor.
For more information about Tor, see https://www.torproject.org/.
If you got this file as a part of a larger bundle,
there may be other license terms that you should be aware of.
===============================================================================
Tor is distributed under the "3-clause BSD" license, a commonly used
software license that means Tor is both free software and open source:
Copyright (c) 2001-2004, Roger Dingledine
Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
Copyright (c) 2007-2019, The Tor Project, Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the names of the copyright owners nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===============================================================================

View File

@ -15,19 +15,19 @@ import net.i2p.pow.equix.Heap;
import net.i2p.pow.hashx.HXCtx;
public class POW {
private static final byte[] P = DataHelper.getASCII("Tor hs intro v1\0");
private static final int SEED_LEN = 32;
private static final int NONCE_LEN = 16;
private static final int EFFORT_LEN = 4;
public static final byte[] P = DataHelper.getASCII("Tor hs intro v1\0");
public static final int SEED_LEN = 32;
public static final int NONCE_LEN = 16;
public static final int EFFORT_LEN = 4;
// 100
private static final int CHALLENGE_LEN = P.length + Hash.HASH_LENGTH + SEED_LEN + NONCE_LEN + EFFORT_LEN;
private static final int SOLUTION_LEN = 16;
private static final int SEED_PFX_LEN = 4;
public static final int CHALLENGE_LEN = P.length + Hash.HASH_LENGTH + SEED_LEN + NONCE_LEN + EFFORT_LEN;
public static final int SOLUTION_LEN = 16;
public static final int SEED_PFX_LEN = 4;
// 116
private static final int CHECK_LEN = CHALLENGE_LEN + SOLUTION_LEN;
public static final int CHECK_LEN = CHALLENGE_LEN + SOLUTION_LEN;
// 40
private static final int PROOF_LEN = NONCE_LEN + SOLUTION_LEN + EFFORT_LEN + SEED_PFX_LEN;
private static final int BLAKE2B_32_LEN = 4;
public static final int PROOF_LEN = NONCE_LEN + SOLUTION_LEN + EFFORT_LEN + SEED_PFX_LEN;
public static final int BLAKE2B_32_LEN = 4;
/**
* @return 40 byte proof
@ -127,7 +127,8 @@ public class POW {
if (claimedEffort > effort) {
System.out.println("Proof effort " + claimedEffort + " is more than required effort " + effort);
// replace effort in proof so it will validate
DataHelper.toLong(proof, P.length + Hash.HASH_LENGTH + SEED_LEN + NONCE_LEN, 4, effort);
// no, can't do this
//DataHelper.toLong(proof, NONCE_LEN, 4, effort);
}
char[] solution = new char[8];
off = NONCE_LEN + EFFORT_LEN;

View File

@ -0,0 +1,158 @@
package net.i2p.pow;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.pow.equix.Heap;
import net.i2p.pow.hashx.HXCtx;
/**
* Vectors from Tor test_hs_pow.c
*
* Copyright (c) 2020-2023, The Tor Project, Inc.
* See LICENSE for licensing information
*/
public class Test {
private static int test_no;
/*
static const struct {
uint32_t claimed_effort;
uint32_t validated_effort;
int expected_retval;
const char *seed_hex;
const char *service_blinded_id_hex;
const char *nonce_hex;
const char *sol_hex;
const char *encoded_hex;
} vectors[] = {
*/
private static final int[] claimed = { 1, 0, 1000000, 1000000, 999999, 1000000, 1000000 };
private static final int[] validated = { 0, 0, 1000000, 0, 0, 0, 1000000 };
private static final int[] retval = { -1, 0, 0, -1, -1, -1, 0 };
private static final String[] V0 =
{
/* All zero, expect invalid */
//1, 0, -1,
"0000000000000000000000000000000000000000000000000000000000000000",
"1111111111111111111111111111111111111111111111111111111111111111",
"00000000000000000000000000000000", "00000000000000000000000000000000",
"01" +
"00000000000000000000000000000000" +
"00000001" + "00000000" +
"00000000000000000000000000000000"
};
private static final String[] V1 =
{
/* Valid zero-effort solution */
//0, 0, 0,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"1111111111111111111111111111111111111111111111111111111111111111",
"55555555555555555555555555555555", "4312f87ceab844c78e1c793a913812d7",
"01" +
"55555555555555555555555555555555" +
"00000000" + "aaaaaaaa" +
"4312f87ceab844c78e1c793a913812d7"
};
private static final String[] V2 =
{
/* Valid high-effort solution */
//1000000, 1000000, 0,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"1111111111111111111111111111111111111111111111111111111111111111",
"59217255555555555555555555555555", "0f3db97b9cac20c1771680a1a34848d3",
"01" +
"59217255555555555555555555555555" +
"000f4240" + "aaaaaaaa" +
"0f3db97b9cac20c1771680a1a34848d3"
};
private static final String[] V3 =
{
/* Reject replays */
//1000000, 0, -1,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"1111111111111111111111111111111111111111111111111111111111111111",
"59217255555555555555555555555555", "0f3db97b9cac20c1771680a1a34848d3",
"01" +
"59217255555555555555555555555555" +
"000f4240" + "aaaaaaaa" +
"0f3db97b9cac20c1771680a1a34848d3"
};
private static final String[] V4 =
{
/* The claimed effort must exactly match what's in the challenge */
//99999, 0, -1,
"86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f",
"bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed",
"2eff9fdbc34326d9d2f18ed277469c63", "400cb091139f86b352119f6e131802d6",
"01" +
"2eff9fdbc34326d9d2f18ed277469c63" +
"0001869f" + "86fb0acf" +
"400cb091139f86b352119f6e131802d6"
};
private static final String[] V5 =
{
/* Otherwise good solution but with a corrupted nonce */
//100000, 0, -1,
"86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f",
"bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed",
"2eff9fdbc34326d9a2f18ed277469c63", "400cb091139f86b352119f6e131802d6",
"01" +
"2eff9fdbc34326d9a2f18ed277469c63" +
"000186a0" + "86fb0acf" +
"400cb091139f86b352119f6e131802d6"
};
private static final String[] V6 =
{
/* Corrected version of above */
//100000, 100000, 0,
"86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f",
"bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed",
"2eff9fdbc34326d9d2f18ed277469c63", "400cb091139f86b352119f6e131802d6",
"01" +
"2eff9fdbc34326d9d2f18ed277469c63" +
"000186a0" + "86fb0acf" +
"400cb091139f86b352119f6e131802d6"
};
public static void main(String[] args) {
test(V0, claimed[0], validated[0], retval[0]);
test(V1, claimed[1], validated[1], retval[1]);
test(V2, claimed[2], validated[2], retval[2]);
test(V3, claimed[3], validated[3], retval[3]);
test(V4, claimed[4], validated[4], retval[4]);
test(V5, claimed[5], validated[5], retval[5]);
test(V6, claimed[6], validated[6], retval[6]);
}
private static void test(String[] v, int claimed, int validated, int retval) {
System.out.println("Test " + (++test_no));
byte[] seed = fromHex(v[0]);
byte[] service_blinded_id = fromHex(v[1]);
byte[] nonce = fromHex(v[2]);
byte[] sol = fromHex(v[3]);
byte[] encoded = fromHex(v[4]);
HXCtx ctx = new HXCtx(512);
Hash h = new Hash(service_blinded_id);
byte[] proof = new byte[POW.PROOF_LEN];
// nonce, effort, solution 16 + 4 + 16
// skip the "01"
System.arraycopy(encoded, 1, proof, 0, POW.NONCE_LEN + POW.EFFORT_LEN + POW.SOLUTION_LEN);
// seed pfx
System.arraycopy(seed, 0, proof, 36, POW.SEED_PFX_LEN);
boolean ok = POW.verify(ctx, h, seed, validated, proof);
System.out.println("Verify " + test_no + " expected " + (retval == 0) + " actual " + ok);
ok = ok == (retval == 0);
System.out.println("Test " + test_no + (ok ? " PASSED" : " FAILED"));
}
private static byte[] fromHex(String v) {
int sz = v.length() / 2;
byte[] b = new byte[sz];
for (int i = 0; i < sz; i++) {
b[i] = (byte) (Integer.parseInt(v.substring(i*2, (i*2) + 2), 16) & 0xff);
}
return b;
}
}