forked from I2P_Developers/i2p.i2p
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