I2P repliable datagrams

This commit is contained in:
human
2004-04-17 23:16:28 +00:00
committed by zzz
parent 8206a26267
commit ccb309fd92
3 changed files with 269 additions and 0 deletions

View 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;
}
}

View 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;
}
}
}

View File

@ -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);
}
}