Last active
September 20, 2020 18:35
-
-
Save DrBrad/0148f54cb1e5f5b04414c7756b97996a to your computer and use it in GitHub Desktop.
Socket Cipher Data Input / Output Stream for AES
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javax.crypto.Cipher; | |
import javax.crypto.NullCipher; | |
import java.io.EOFException; | |
import java.io.FilterInputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.util.Arrays; | |
public class SRI extends FilterInputStream { | |
/** | |
* THIS HAS BEEN TESTED & WORKS WITH | |
* CTR - WORKS | |
* GCM - DOESN'T WORK - "Must recreate a new cipher per message" | |
**/ | |
private Cipher cipher; | |
private byte[] buf = new byte[8]; | |
private byte[] obuffer = new byte[0]; | |
public SRI(InputStream in){ | |
this(in, new NullCipher()); | |
} | |
public SRI(InputStream in, Cipher cipher){ | |
super(in); | |
this.cipher = cipher; | |
} | |
/** | |
* PLEASE NOTE AVAILABLE DOES NOT OUTPUT THE CORRECT AVAILABLE | |
* IT OUTPUTS DECRYPTED BUFFER LENGTH + ENCRYPTED AVAILABLE THIS | |
* ENSURES THAT THE AVAILABLE WILL BE > 0 WHILE BYTES COMING IN | |
**/ | |
public int available()throws IOException { | |
if(obuffer.length > 0){ | |
return obuffer.length+super.available(); | |
}else{ | |
return super.available(); | |
} | |
} | |
public int read()throws IOException { | |
byte[] buf = new byte[1]; | |
read(buf, 0, 1); | |
return buf[0]; | |
} | |
public int read(byte[] buf)throws IOException { | |
return read(buf, 0, buf.length); | |
} | |
/** | |
* FIRST WE READ AN integer WITH THE ENCRYPTED BYTES LENGTH | |
* THIS ENSURES THAT WE NEVER OVERLAP DECRYPTION AND CAUSE AN | |
* ERROR. NEXT WE READ THE MESSAGE TO THE LENGTH AND STORE THE | |
* REST OF THE MESSAGE IN obuffer AS DECRYPTED BYTES | |
**/ | |
public int read(byte[] buf, int off, int len)throws IOException { | |
if(obuffer.length > 0){ | |
if(len < obuffer.length){ | |
System.arraycopy(obuffer, off, buf, 0, len); | |
obuffer = Arrays.copyOfRange(obuffer, len, obuffer.length); | |
return len; | |
}else{ | |
len = obuffer.length; | |
System.arraycopy(obuffer, off, buf, 0, len); | |
obuffer = new byte[0]; | |
return len; | |
} | |
}else{ | |
obuffer = new byte[getMessageLength()]; | |
int position = 0; | |
byte[] buffer = new byte[(obuffer.length > 4096) ? 4096 : obuffer.length]; | |
int length; | |
while(position < obuffer.length){ | |
length = in.read(buffer); | |
System.arraycopy(buffer, 0, obuffer, position, length); | |
position += length; | |
} | |
try{ | |
obuffer = cipher.doFinal(obuffer); | |
if(len < obuffer.length){ | |
System.arraycopy(obuffer, off, buf, 0, len); | |
obuffer = Arrays.copyOfRange(obuffer, len, obuffer.length); | |
return len; | |
}else{ | |
len = obuffer.length; | |
System.arraycopy(obuffer, off, buf, 0, len); | |
obuffer = new byte[0]; | |
return len; | |
} | |
}catch(Exception e){ | |
IOException ioe = new IOException("Cipher can't decrypt message."); | |
ioe.initCause(e); | |
throw ioe; | |
} | |
} | |
} | |
public long skip()throws IOException { | |
//I haven't implemented this yet... | |
return 0; | |
} | |
public boolean markSupported(){ | |
return false; | |
} | |
public void mark(int mark){ | |
} | |
public void reset()throws IOException { | |
throw new IOException("reset not supported"); | |
} | |
//DATA INPUT TIME | |
public boolean readBoolean()throws Exception { | |
int b = read(); | |
if(b < 0){ | |
throw new EOFException(); | |
} | |
return (b != 0); | |
} | |
public byte readByte()throws Exception { | |
int b = read(); | |
if(b < 0){ | |
throw new EOFException(); | |
} | |
return (byte) b; | |
} | |
public short readShort()throws Exception { | |
readFully(buf, 0, 2); | |
return (short) ((buf [0] << 8) | (buf [1] & 0xff)); | |
} | |
public char readChar()throws Exception { | |
readFully(buf, 0, 2); | |
return (char) ((buf [0] << 8) | (buf [1] & 0xff)); | |
} | |
public int readInt()throws Exception { | |
readFully(buf, 0, 4); | |
return (((buf[0] & 0xff) << 24) | ((buf[1] & 0xff) << 16) | ((buf[2] & 0xff) << 8) | (buf[3] & 0xff)); | |
} | |
public long readLong()throws Exception { | |
readFully(buf, 0, 8); | |
return (((long)(buf[0] & 0xff) << 56) | ((long)(buf[1] & 0xff) << 48) | ((long)(buf[2] & 0xff) << 40) | ((long)(buf[3] & 0xff) << 32) | | |
((long)(buf[4] & 0xff) << 24) | ((long)(buf[5] & 0xff) << 16) | ((long)(buf[6] & 0xff) << 8) | ((long)(buf[7] & 0xff))); | |
} | |
public float readFloat()throws Exception { | |
return Float.intBitsToFloat(readInt()); | |
} | |
public double readDouble()throws Exception { | |
return Double.longBitsToDouble(readLong()); | |
} | |
public void readFully(byte[] b, int off, int len)throws Exception { | |
if(len < 0){ | |
throw new IndexOutOfBoundsException("Negative length: "+len); | |
} | |
while(len > 0){ | |
int numread = read(b, off, len); | |
if(numread < 0){ | |
throw new EOFException(); | |
} | |
len -= numread; | |
off += numread; | |
} | |
} | |
private int getMessageLength()throws IOException { | |
byte[] buffer = new byte[4]; | |
int off = 0, len = 4; | |
while(len > 0){ | |
int numread = in.read(buffer, off, len); | |
if(numread < 0){ | |
throw new EOFException(); | |
} | |
len -= numread; | |
off += numread; | |
} | |
return (((buffer[0] & 0xff) << 24) | ((buffer[1] & 0xff) << 16) | ((buffer[2] & 0xff) << 8) | (buffer[3] & 0xff)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javax.crypto.Cipher; | |
import javax.crypto.NullCipher; | |
import java.io.FilterOutputStream; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
import static java.nio.charset.StandardCharsets.UTF_8; | |
public class SRO extends FilterOutputStream { | |
private Cipher cipher; | |
public SRO(OutputStream out){ | |
this(out, new NullCipher()); | |
} | |
public SRO(OutputStream out, Cipher cipher){ | |
super(out); | |
this.cipher = cipher; | |
} | |
public void flush()throws IOException { | |
//System.out.println("FLUSH"); | |
out.flush(); | |
} | |
public void write(int value)throws IOException { | |
write(new byte[]{ (byte) value }, 0, 1); | |
} | |
public void write(byte[] buf)throws IOException { | |
write(buf, 0, buf.length); | |
} | |
public void write(byte[] buf, int off, int len)throws IOException { | |
try{ | |
buf = cipher.doFinal(buf, off, len); | |
setMessageLength(buf.length); | |
out.write(buf); | |
}catch(Exception e){ | |
IOException ioex = new IOException(String.valueOf(e)); | |
ioex.initCause(e); | |
throw ioex; | |
} | |
} | |
//DATA OUTPUT TIME | |
public void writeBoolean(boolean value)throws Exception { | |
write(value ? 1 : 0); | |
} | |
public void writeByte(int value)throws Exception { | |
value = value&0xff; | |
write(value); | |
} | |
public void writeShort(int value)throws Exception { | |
byte[] buf = new byte[]{ | |
(byte) (0xff & (value >> 8)), | |
(byte) (0xff & value) }; | |
write(buf); | |
} | |
public void writeChar(int value)throws Exception { | |
byte[] buf = new byte[]{ | |
(byte) (0xff & (value >> 8)), | |
(byte) (0xff & value) }; | |
write(buf); | |
} | |
public void writeInt(int value)throws Exception { | |
byte[] buf = new byte[]{ | |
(byte) (0xff & (value >> 24)), | |
(byte) (0xff & (value >> 16)), | |
(byte) (0xff & (value >> 8)), | |
(byte) (0xff & value) }; | |
write(buf); | |
} | |
public void writeLong(long value)throws Exception { | |
byte[] buf = new byte[]{ | |
(byte) (0xff & (value >> 56)), | |
(byte) (0xff & (value >> 48)), | |
(byte) (0xff & (value >> 40)), | |
(byte) (0xff & (value >> 32)), | |
(byte) (0xff & (value >> 24)), | |
(byte) (0xff & (value >> 16)), | |
(byte) (0xff & (value >> 8)), | |
(byte) (0xff & value) }; | |
write(buf); | |
} | |
public void writeFloat(float value)throws Exception { | |
writeInt(Float.floatToIntBits(value)); | |
} | |
public void writeDouble(double value)throws Exception { | |
writeLong(Double.doubleToLongBits(value)); | |
} | |
public void writeBytes(String value)throws Exception { | |
byte[] buf = value.getBytes(UTF_8); | |
write(buf); | |
} | |
public void writeChars(String value)throws Exception { | |
byte[] buf = value.getBytes(UTF_8); | |
write(buf); | |
} | |
private void setMessageLength(int value)throws Exception { | |
out.write((byte) (0xff & (value >> 24))); | |
out.write((byte) (0xff & (value >> 16))); | |
out.write((byte) (0xff & (value >> 8))); | |
out.write((byte) (0xff & value)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment