I2P repliable datagrams
This commit is contained in:
160
core/java/src/net/i2p/client/datagram/I2PDatagramDissector.java
Normal file
160
core/java/src/net/i2p/client/datagram/I2PDatagramDissector.java
Normal file
@ -0,0 +1,160 @@
|
||||
package net.i2p.client.datagram;
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by human in 2004 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* your children, but it might. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.i2p.crypto.DSAEngine;
|
||||
import net.i2p.crypto.SHA256Generator;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Signature;
|
||||
import net.i2p.util.HexDump;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Class for dissecting I2P repliable datagrams, checking the authenticity of
|
||||
* the sender. Note that objects of this class are NOT THREAD SAFE!
|
||||
*
|
||||
* @author human
|
||||
*/
|
||||
public final class I2PDatagramDissector {
|
||||
|
||||
private static Log _log = new Log(I2PDatagramDissector.class);
|
||||
|
||||
private static int DGRAM_BUFSIZE = 32768;
|
||||
|
||||
private DSAEngine dsaEng = DSAEngine.getInstance();
|
||||
private SHA256Generator hashGen = SHA256Generator.getInstance();
|
||||
|
||||
private byte[] rxHashBytes = null;
|
||||
|
||||
private Signature rxSign = new Signature();
|
||||
|
||||
private Destination rxDest = new Destination();
|
||||
|
||||
private byte[] rxPayload = new byte[DGRAM_BUFSIZE];
|
||||
|
||||
private int rxPayloadLen = 0;
|
||||
|
||||
/**
|
||||
* Crate a new I2P repliable datagram dissector.
|
||||
*/
|
||||
public I2PDatagramDissector() {}
|
||||
|
||||
/**
|
||||
* Load an I2P repliable datagram into the dissector.
|
||||
*
|
||||
* @param dgram I2P repliable datagram to be loader
|
||||
*
|
||||
* @throws DataFormatException If there's an error in the datagram format
|
||||
*/
|
||||
public void loadI2PDatagram(byte[] dgram) throws DataFormatException {
|
||||
ByteArrayInputStream dgStream = new ByteArrayInputStream(dgram);
|
||||
byte[] hashedData;
|
||||
|
||||
|
||||
try {
|
||||
rxSign.readBytes(dgStream);
|
||||
|
||||
rxDest.readBytes(dgStream);
|
||||
rxPayloadLen = dgStream.read(rxPayload);
|
||||
|
||||
hashedData = new byte[dgram.length - Signature.SIGNATURE_BYTES];
|
||||
System.arraycopy(dgram, Signature.SIGNATURE_BYTES,
|
||||
hashedData, 0,
|
||||
hashedData.length);
|
||||
rxHashBytes = hashGen.calculateHash(hashedData).toByteArray();
|
||||
} catch (IOException e) {
|
||||
_log.error("Caught IOException - INCONSISTENT STATE!", e);
|
||||
}
|
||||
|
||||
//_log.debug("Datagram payload size: " + rxPayloadLen + "; content:\n"
|
||||
// + HexDump.dump(rxPayload, 0, rxPayloadLen));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the payload carried by an I2P repliable datagram (previously loaded
|
||||
* with the loadI2PDatagram() method), verifying the datagram signature.
|
||||
*
|
||||
* @return A byte array containing the datagram payload
|
||||
*
|
||||
* @throws I2PInvalidDatagramException if the signature verification fails
|
||||
*/
|
||||
public byte[] getPayload() throws I2PInvalidDatagramException {
|
||||
if (!dsaEng.verifySignature(rxSign, rxHashBytes,
|
||||
rxDest.getSigningPublicKey())) {
|
||||
throw new I2PInvalidDatagramException("Incorrect I2P repliable datagram signature");
|
||||
}
|
||||
|
||||
byte[] retPayload = new byte[rxPayloadLen];
|
||||
System.arraycopy(rxPayload, 0, retPayload, 0, rxPayloadLen);
|
||||
|
||||
return retPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sender of an I2P repliable datagram (previously loaded with the
|
||||
* loadI2PDatagram() method), verifying the datagram signature.
|
||||
*
|
||||
* @return The Destination of the I2P repliable datagram sender
|
||||
*
|
||||
* @throws I2PInvalidDatagramException if the signature verification fails
|
||||
*/
|
||||
public Destination getSender() throws I2PInvalidDatagramException {
|
||||
if (!dsaEng.verifySignature(rxSign, rxHashBytes,
|
||||
rxDest.getSigningPublicKey())) {
|
||||
throw new I2PInvalidDatagramException("Incorrect I2P repliable datagram signature");
|
||||
}
|
||||
|
||||
Destination retDest = new Destination();
|
||||
try {
|
||||
retDest.fromByteArray(rxDest.toByteArray());
|
||||
} catch (DataFormatException e) {
|
||||
_log.error("Caught DataFormatException", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return retDest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the payload carried by an I2P repliable datagram (previously
|
||||
* loaded with the loadI2PDatagram() method), without verifying the
|
||||
* datagram signature.
|
||||
*
|
||||
* @return A byte array containing the datagram payload
|
||||
*/
|
||||
public byte[] extractPayload() {
|
||||
byte[] retPayload = new byte[rxPayloadLen];
|
||||
System.arraycopy(rxPayload, 0, retPayload, 0, rxPayloadLen);
|
||||
|
||||
return retPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the sender of an I2P repliable datagram (previously loaded with
|
||||
* the loadI2PDatagram() method), without verifying the datagram signature.
|
||||
*
|
||||
* @return The Destination of the I2P repliable datagram sender
|
||||
*/
|
||||
public Destination extractSender() {
|
||||
Destination retDest = new Destination();
|
||||
try {
|
||||
retDest.fromByteArray(rxDest.toByteArray());
|
||||
} catch (DataFormatException e) {
|
||||
_log.error("Caught DataFormatException", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return retDest;
|
||||
}
|
||||
}
|
84
core/java/src/net/i2p/client/datagram/I2PDatagramMaker.java
Normal file
84
core/java/src/net/i2p/client/datagram/I2PDatagramMaker.java
Normal file
@ -0,0 +1,84 @@
|
||||
package net.i2p.client.datagram;
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by human in 2004 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* your children, but it might. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.crypto.DSAEngine;
|
||||
import net.i2p.crypto.SHA256Generator;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.SigningPrivateKey;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Class for creating I2P repliable datagrams. Note that objects of this class
|
||||
* are NOT THREAD SAFE!
|
||||
*
|
||||
* @author human
|
||||
*/
|
||||
public final class I2PDatagramMaker {
|
||||
|
||||
private static Log _log = new Log(I2PDatagramMaker.class);
|
||||
|
||||
private static int DGRAM_BUFSIZE = 32768;
|
||||
|
||||
private SHA256Generator hashGen = SHA256Generator.getInstance();
|
||||
private DSAEngine dsaEng = DSAEngine.getInstance();
|
||||
|
||||
private SigningPrivateKey sxPrivKey = null;
|
||||
private byte[] sxDestBytes = null;
|
||||
|
||||
private ByteArrayOutputStream sxBuf = new ByteArrayOutputStream(DGRAM_BUFSIZE);
|
||||
private ByteArrayOutputStream sxDGram = new ByteArrayOutputStream(DGRAM_BUFSIZE);
|
||||
|
||||
/**
|
||||
* Construct a new I2PDatagramMaker that will be able to create I2P
|
||||
* repliable datagrams going to be sent through the specified I2PSession.
|
||||
*
|
||||
* @param session I2PSession used to send I2PDatagrams through
|
||||
*/
|
||||
public I2PDatagramMaker(I2PSession session) {
|
||||
sxPrivKey = session.getPrivateKey();
|
||||
sxDestBytes = session.getMyDestination().toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a repliable I2P datagram containing the specified payload.
|
||||
*
|
||||
* @param payload Bytes to be contained in the I2P datagram.
|
||||
*/
|
||||
public byte[] makeI2PDatagram(byte[] payload) {
|
||||
byte[] hashedData;
|
||||
|
||||
sxBuf.reset();
|
||||
sxDGram.reset();
|
||||
|
||||
try {
|
||||
sxBuf.write(sxDestBytes);
|
||||
sxBuf.write(payload);
|
||||
|
||||
hashedData = sxBuf.toByteArray();
|
||||
|
||||
dsaEng.sign(hashGen.calculateHash(hashedData).toByteArray(),
|
||||
sxPrivKey).writeBytes(sxDGram);
|
||||
|
||||
sxDGram.write(hashedData);
|
||||
|
||||
return sxDGram.toByteArray();
|
||||
} catch (IOException e) {
|
||||
_log.error("Caught IOException", e);
|
||||
return null;
|
||||
} catch (DataFormatException e) {
|
||||
_log.error("Caught DataFormatException", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package net.i2p.client.datagram;
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by human in 2004 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* your children, but it might. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception thrown when I2P repliable datagram signature verification fails.
|
||||
*
|
||||
* @author human
|
||||
*/
|
||||
public class I2PInvalidDatagramException extends Exception {
|
||||
|
||||
public I2PInvalidDatagramException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public I2PInvalidDatagramException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user