blob: 34277e1f96c17ffa918a944969d5f407b6714284 [file] [log] [blame] [raw]
package net.glowstone.net;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.CFBBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
public class EncryptionChannelProcessor extends FixedSimpleMessageProcessor {
private CryptBuf encodeBuf;
private CryptBuf decodeBuf;
public EncryptionChannelProcessor(byte[] sharedSecret, int capacity) {
super(capacity);
CipherParameters parameters = new ParametersWithIV(new KeyParameter(sharedSecret), sharedSecret);
BufferedBlockCipher encode = new BufferedBlockCipher(new CFBBlockCipher(new AESEngine(), 8));
BufferedBlockCipher decode = new BufferedBlockCipher(new CFBBlockCipher(new AESEngine(), 8));
encode.init(true, parameters);
decode.init(false, parameters);
this.encodeBuf = new CryptBuf(encode, capacity * 2);
this.decodeBuf = new CryptBuf(decode, capacity * 2);
}
@Override
protected void writeEncode(byte[] buf, int length) {
encodeBuf.write(buf, length);
}
@Override
protected int readEncode(byte[] buf) {
return encodeBuf.read(buf);
}
@Override
protected void writeDecode(byte[] buf, int length) {
decodeBuf.write(buf, length);
}
@Override
protected int readDecode(byte[] buf) {
return decodeBuf.read(buf);
}
private static class CryptBuf {
private final BufferedBlockCipher cipher;
private final byte[] buffer;
private int writePosition;
private int readPosition;
private CryptBuf(BufferedBlockCipher cipher, int bufSize) {
this.cipher = cipher;
this.buffer = new byte[bufSize];
}
private int read(byte[] dest) {
if (readPosition >= writePosition) {
return 0;
} else {
int amount = Math.min(dest.length, writePosition - readPosition);
System.arraycopy(buffer, readPosition, dest, 0, amount);
readPosition += amount;
return amount;
}
}
private void write(byte[] src, int length) {
if (readPosition < writePosition) {
throw new IllegalStateException("Stored data must be completely read before writing more data");
}
writePosition = cipher.processBytes(src, 0, length, buffer, 0);
readPosition = 0;
}
}
}