forked from I2P_Developers/i2p.i2p
SSU2: More prep for Peer Test (WIP)
This commit is contained in:
@@ -112,9 +112,9 @@ class SSU2Payload {
|
||||
public void gotRelayIntro(Hash aliceHash, byte[] data);
|
||||
|
||||
/**
|
||||
* @param msg 1-7
|
||||
* @param msg 1-4
|
||||
* @param status 0 = accept, 1-255 = reject
|
||||
* @param h Alice or Charlie hash
|
||||
* @param h Alice or Charlie hash for msg 2 and 4, null for msg 1 and 3
|
||||
* @param data excludes flag, includes signature
|
||||
*/
|
||||
public void gotPeerTest(int msg, int status, Hash h, byte[] data);
|
||||
@@ -320,13 +320,25 @@ class SSU2Payload {
|
||||
case BLOCK_PEERTEST: {
|
||||
if (isHandshake)
|
||||
throw new IOException("Illegal block in handshake: " + type);
|
||||
if (len < 92) // 32 byte hash + 20 byte data w/ IPv4 + 40 byte DSA sig
|
||||
if (len < 20) // 20 byte data w/ IPv4 (hash and sig optional)
|
||||
throw new IOException("Bad length for PEERTEST: " + len);
|
||||
int mnum = payload[i] & 0xff;
|
||||
if (mnum == 0 || mnum > 4)
|
||||
throw new DataFormatException("Bad PEERTEST number: " + mnum);
|
||||
int resp = payload[i + 1] & 0xff;
|
||||
Hash h = Hash.create(payload, i + 3); // skip flag
|
||||
byte[] data = new byte[len - (3 + Hash.HASH_LENGTH)];
|
||||
System.arraycopy(payload, i + 3 + Hash.HASH_LENGTH, data, 0, data.length);
|
||||
int o = i + 3; // skip flag
|
||||
int datalen;
|
||||
Hash h;
|
||||
if (mnum == 2 || mnum == 4) {
|
||||
h = Hash.create(payload, o);
|
||||
datalen = len - (3 + Hash.HASH_LENGTH);
|
||||
o += Hash.HASH_LENGTH;
|
||||
} else {
|
||||
datalen = len - 3;
|
||||
h = null;
|
||||
}
|
||||
byte[] data = new byte[datalen];
|
||||
System.arraycopy(payload, o, data, 0, datalen);
|
||||
cb.gotPeerTest(mnum, resp, h, data);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -132,18 +132,61 @@ final class SSU2Util {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the data for the peer test block
|
||||
*
|
||||
* @param h to be included in sig, not included in data
|
||||
* @param h2 may be null, to be included in sig, not included in data
|
||||
* @return null on failure
|
||||
*/
|
||||
public static byte[] createPeerTestData(I2PAppContext ctx, Hash h, Hash h2,
|
||||
PeerTestState.Role role, long nonce, byte[] ip, int port,
|
||||
SigningPrivateKey spk) {
|
||||
int datalen = 13 + ip.length;
|
||||
byte[] data = new byte[datalen + spk.getType().getSigLen()];
|
||||
if (role == PeerTestState.Role.BOB)
|
||||
throw new IllegalArgumentException();
|
||||
data[0] = (byte) ((role == PeerTestState.Role.ALICE) ? 1 : 3);
|
||||
data[1] = 2; // version
|
||||
DataHelper.toLong(data, 2, 4, nonce);
|
||||
DataHelper.toLong(data, 6, 4, ctx.clock().now() / 1000);
|
||||
data[10] = (byte) ip.length;
|
||||
System.arraycopy(ip, 0, data, 11, ip.length);
|
||||
DataHelper.toLong(data, 11 + ip.length, 2, port);
|
||||
Signature sig = sign(ctx, PEER_TEST_PROLOGUE, h, h2, data, datalen, spk);
|
||||
if (sig == null)
|
||||
return null;
|
||||
byte[] s = sig.getData();
|
||||
System.arraycopy(s, 0, data, datalen, s.length);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign the relay or peer test data, using
|
||||
* the prologue and hash as the initial data,
|
||||
* and then the provided data.
|
||||
*
|
||||
* @param data if desired, leave room at end for sig
|
||||
* @param datalen the length of the data to be signed
|
||||
* @param h to be included in sig, not included in data
|
||||
* @param h2 may be null, to be included in sig, not included in data
|
||||
* @return null on failure
|
||||
*/
|
||||
public static Signature sign(I2PAppContext ctx, byte[] prologue, Hash h, byte[] data, SigningPrivateKey spk) {
|
||||
byte[] buf = new byte[prologue.length + Hash.HASH_LENGTH + data.length];
|
||||
public static Signature sign(I2PAppContext ctx, byte[] prologue, Hash h, Hash h2,
|
||||
byte[] data, int datalen, SigningPrivateKey spk) {
|
||||
int len = prologue.length + Hash.HASH_LENGTH + datalen;
|
||||
if (h2 != null)
|
||||
len += Hash.HASH_LENGTH;
|
||||
byte[] buf = new byte[len];
|
||||
System.arraycopy(prologue, 0, buf, 0, prologue.length);
|
||||
System.arraycopy(h.getData(), 0, buf, prologue.length, Hash.HASH_LENGTH);
|
||||
System.arraycopy(data, 0, buf, prologue.length + Hash.HASH_LENGTH, data.length);
|
||||
System.arraycopy(h.getData(), 0, buf, prologue.length, Hash.HASH_LENGTH);
|
||||
int off = prologue.length + Hash.HASH_LENGTH;
|
||||
if (h2 != null) {
|
||||
System.arraycopy(h2.getData(), 0, buf, off, Hash.HASH_LENGTH);
|
||||
off += Hash.HASH_LENGTH;
|
||||
}
|
||||
System.arraycopy(data, 0, buf, off, datalen);
|
||||
return ctx.dsa().sign(buf, spk);
|
||||
}
|
||||
|
||||
@@ -151,14 +194,24 @@ final class SSU2Util {
|
||||
* Validate the signed relay or peer test data, using
|
||||
* the prologue and hash as the initial data,
|
||||
* and then the provided data which ends with a signature of the specified type.
|
||||
*
|
||||
* @param h2 may be null
|
||||
*/
|
||||
public static boolean validateSig(I2PAppContext ctx, byte[] prologue, Hash h, byte[] data, SigningPublicKey spk) {
|
||||
public static boolean validateSig(I2PAppContext ctx, byte[] prologue, Hash h, Hash h2, byte[] data, SigningPublicKey spk) {
|
||||
SigType type = spk.getType();
|
||||
int siglen = type.getSigLen();
|
||||
byte[] buf = new byte[prologue.length + Hash.HASH_LENGTH + data.length - siglen];
|
||||
int len = prologue.length + Hash.HASH_LENGTH + data.length - siglen;
|
||||
if (h2 != null)
|
||||
len += Hash.HASH_LENGTH;
|
||||
byte[] buf = new byte[len];
|
||||
System.arraycopy(prologue, 0, buf, 0, prologue.length);
|
||||
System.arraycopy(h.getData(), 0, buf, prologue.length, Hash.HASH_LENGTH);
|
||||
System.arraycopy(data, 0, buf, prologue.length + Hash.HASH_LENGTH, data.length - siglen);
|
||||
int off = prologue.length + Hash.HASH_LENGTH;
|
||||
if (h2 != null) {
|
||||
System.arraycopy(h2.getData(), 0, buf, off, Hash.HASH_LENGTH);
|
||||
off += Hash.HASH_LENGTH;
|
||||
}
|
||||
System.arraycopy(data, 0, buf, off, data.length - siglen);
|
||||
byte[] bsig = new byte[siglen];
|
||||
System.arraycopy(data, data.length - siglen, bsig, 0, siglen);
|
||||
Signature sig = new Signature(type, bsig);
|
||||
|
||||
Reference in New Issue
Block a user