Compare commits

...

9 Commits

  1. 5
      crypto/CryptoOutputSocket.java
  2. 119
      crypto/CryptoSocket.java
  3. 63
      crypto/InterleavedOutput.java
  4. 47
      crypto/PaddedInputStream.java
  5. 64
      crypto/PaddedOutputStream.java
  6. 31
      crypto/W25519.java
  7. 32
      crypto/WeierstrassCurve.java
  8. 99
      crypto/WeierstrassPoint.java
  9. 64
      sample/Main.java

5
crypto/CryptoOutputSocket.java

@ -0,0 +1,5 @@
package crypto;
public class CryptoOutputSocket
{
}

119
crypto/CryptoSocket.java

@ -0,0 +1,119 @@
package crypto;
import javafx.scene.shape.Ellipse;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
public class CryptoSocket
{
private Socket socket;
private OutputStream out;
private InputStream in;
SecretKey key;
Cipher ciphout;
Cipher ciphin;
public CryptoSocket(Socket socket) throws IOException
{
this.socket = socket;
this.out = socket.getOutputStream();
this.in = socket.getInputStream();
WeierstrassCurve w25519 = W25519.getW25519();
WeierstrassPoint g = W25519.getGenerator();
BigInteger x = new BigInteger(w25519.mod.bitLength(), new Random());
// Heaven forbid there's an identity point in either of these transmissions; it will be fatal anyway, so ignore the possibility.
WeierstrassPoint i = g.mult(x);
sendBigInteger(out, i.x);
sendBigInteger(out, i.y);
BigInteger newx = receiveBigInteger(in);
BigInteger newy = receiveBigInteger(in);
WeierstrassPoint p = new WeierstrassPoint(w25519, newx, newy);
WeierstrassPoint c = p.mult(x);
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e)
{
throw new IOException("NoSuchAlgorithmException: " + e.getMessage());
}
md.update(c.x.toByteArray());
md.update(c.y.toByteArray());
byte[] keybytes = md.digest();
this.key = new SecretKeySpec(keybytes, "AES");
try {
this.ciphout = Cipher.getInstance("AES/CBC/PCKS5Padding");
this.ciphin = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
throw new IOException("NoSuchAlgorithmException: " + e.getMessage());
} catch (NoSuchPaddingException e) {
throw new IOException("NoSuchPaddingException: " + e.getMessage());
}
try {
this.ciphout.init(Cipher.ENCRYPT_MODE, this.key);
this.ciphin.init(Cipher.DECRYPT_MODE, this.key);
} catch (InvalidKeyException e)
{
throw new IOException(e.getMessage());
}
this.out = this.socket.getOutputStream();
this.in = this.socket.getInputStream();
}
public DataOutputStream getOutputStream()
{
return new DataOutputStream(new CipherOutputStream(this.out, ciphout));
}
public DataInputStream getInputStream()
{
return new DataInputStream(new CipherInputStream(this.in, ciphin));
}
private void sendBigInteger(OutputStream o, BigInteger i) throws java.io.IOException
{
byte[] ba = i.toByteArray();
if (ba.length >= 32768)
throw new IOException("Integer too large to send over a socket");
o.write((byte) (ba.length >> 8));
o.write((byte) ba.length);
for (byte b : ba)
o.write(b);
}
private BigInteger receiveBigInteger(InputStream i) throws java.io.IOException
{
int l = i.read();
l = l << 8;
l = l | i.read();
byte[] bytes = new byte[l];
for (int ii = 0; ii < l; ii++)
{
bytes[ii] = (byte) i.read();
}
return new BigInteger(bytes);
}
}

63
crypto/InterleavedOutput.java

@ -0,0 +1,63 @@
package crypto;
import java.io.IOException;
import java.io.OutputStream;
public class InterleavedOutput
{
private byte length;
private byte buffers[][];
private int heads[];
private byte nstreams;
private byte buffer;
private OutputStream underlying;
public InterleavedOutput(OutputStream underlying, byte length, byte nstreams)
{
this.underlying = underlying;
this.length = length;
this.nstreams = nstreams;
this.buffers = new byte[Byte.toUnsignedInt(nstreams)][Byte.toUnsignedInt(length)];
}
synchronized void writeBuffer(byte which) throws IOException
{
underlying.write(which);
underlying.write(buffers[Byte.toUnsignedInt(which)]);
}
void writeTo(byte which, byte v) throws IOException
{
int idx = Byte.toUnsignedInt(which);
buffers[idx][heads[idx]] = v;
if (heads[idx] == length)
{
writeBuffer(which);
heads[idx] = 0;
}
}
public PaddedOutputStream getStream(byte which) throws IOException
{
if (Byte.toUnsignedInt(which) >= nstreams)
throw new IOException("Stream number too high");
return new PaddedOutputStream(new InterleavedOutputStream(which), length);
}
class InterleavedOutputStream extends OutputStream
{
private byte which;
public InterleavedOutputStream(byte which)
{
this.which = which;
}
@Override
public void write(int i) throws IOException
{
writeTo(which, (byte) i);
}
}
}

47
crypto/PaddedInputStream.java

@ -0,0 +1,47 @@
package crypto;
import java.io.IOException;
import java.io.InputStream;
public class PaddedInputStream extends InputStream
{
protected int length;
protected int received;
protected int head;
protected byte buffer[];
protected InputStream underlying;
public PaddedInputStream(InputStream underlying, int length)
{
this.underlying = underlying;
this.length = length;
this.received = 0;
this.head = 0;
this.buffer = new byte[length];
}
protected byte popBuffer()
{
head += 1;
return buffer[head - 1];
}
protected void readIntoBuffer() throws IOException
{
for (int ii = 0; ii < length; ii++)
buffer[ii] = (byte) underlying.read();
received = length - Byte.toUnsignedInt(buffer[length - 1]);
head = 0;
}
@Override
public int read() throws IOException
{
if (head >= received)
{
readIntoBuffer();
return read();
}
return popBuffer();
}
}

64
crypto/PaddedOutputStream.java

@ -0,0 +1,64 @@
package crypto;
import java.io.IOException;
import java.io.OutputStream;
public class PaddedOutputStream extends OutputStream
{
protected byte length;
protected byte accumulated;
protected byte buffer[];
protected OutputStream underlying;
public PaddedOutputStream(OutputStream underlying, byte length)
{
this.underlying = underlying;
this.length = length;
this.buffer = new byte[length - 1];
this.accumulated = 0;
}
protected boolean addToBuffer(int i)
{
buffer[accumulated] = (byte) i;
accumulated += 1;
if (accumulated + 1 == length)
{
return true;
}
return false;
}
protected void writeBuffer() throws IOException
{
underlying.write(buffer, 0, accumulated);
for (int ii = 0; ii < length - accumulated; ii++) {
underlying.write(length - accumulated);
}
}
protected void resetBuffer()
{
accumulated = 0;
}
@Override
public void write(int i) throws IOException
{
if (addToBuffer(i))
{
writeBuffer();
resetBuffer();
}
}
@Override
public void flush() throws IOException
{
if (accumulated != 0) {
writeBuffer();
resetBuffer();
underlying.flush();
}
}
}

31
crypto/W25519.java

@ -0,0 +1,31 @@
package crypto;
import java.math.BigInteger;
public class W25519
{
static WeierstrassCurve w25519 = null;
static WeierstrassPoint generator = null;
static WeierstrassCurve getW25519()
{
if (w25519 == null)
{
w25519 = new WeierstrassCurve(new BigInteger("19298681539552699237261830834781317975544997444273427339909597334573241639236"),
new BigInteger("55751746669818908907645289078257140818241103727901012315294400837956729358436"),
new BigInteger("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16));
}
return w25519;
}
static WeierstrassPoint getGenerator()
{
if (generator == null)
{
generator = new WeierstrassPoint(getW25519(),
new BigInteger("19298681539552699237261830834781317975544997444273427339909597334652188435546"),
new BigInteger("43114425171068552920764898935933967039370386198203806730763910166200978582548"));
}
return generator;
}
}

32
crypto/WeierstrassCurve.java

@ -0,0 +1,32 @@
package crypto;
import java.math.BigInteger;
public class WeierstrassCurve
{
public BigInteger a;
public BigInteger b;
public BigInteger mod;
public WeierstrassCurve(BigInteger a, BigInteger b, BigInteger mod)
{
this.a = a;
this.b = b;
this.mod = mod;
}
@Override
public boolean equals(Object otherobj)
{
if (!(otherobj instanceof WeierstrassCurve))
{
return false;
}
WeierstrassCurve other = (WeierstrassCurve) otherobj;
boolean b = this.a.equals(other.a) && this.b.equals(other.b) && this.mod.equals(other.mod);
if (b) return true;
else return false;
}
}

99
crypto/WeierstrassPoint.java

@ -0,0 +1,99 @@
package crypto;
import java.math.BigInteger;
public class WeierstrassPoint {
public BigInteger x;
public BigInteger y;
public WeierstrassCurve curve;
public boolean isIdentity;
public WeierstrassPoint(WeierstrassCurve curve)
{
this.x = null;
this.y = null;
this.curve = curve;
this.isIdentity = true;
}
public WeierstrassPoint(WeierstrassCurve curve, BigInteger x, BigInteger y)
{
// if (!y.multiply(y).mod(curve.mod).equals(x.modPow(BigInteger.ONE.add(BigInteger.ONE).add(BigInteger.ONE), curve.mod).add(x.multiply(curve.a)).add(curve.b).mod(curve.mod)))
// {
// System.out.println("x = " + x.toString());
// System.out.println("y = " + y.toString());
// System.out.println("m = " + curve.mod.toString());
// System.out.println("y^2 = " + y.multiply(y).mod(curve.mod).toString());
// System.out.println("x^3 + ax + b = " + x.modPow(BigInteger.ONE.add(BigInteger.ONE).add(BigInteger.ONE), curve.mod).add(x.multiply(curve.a)).add(curve.b).mod(curve.mod).toString());
// throw new ArithmeticException("Invalid points on elliptic curve");
// }
this.curve = curve;
this.x = x;
this.y = y;
this.isIdentity = false;
}
public WeierstrassPoint add(WeierstrassPoint other)
{
BigInteger x, y, m;
if (this.isIdentity)
return other;
if (other.isIdentity)
return this;
if (this.x.mod(curve.mod).equals(other.x.mod(curve.mod)))
{
if (this.y.mod(curve.mod).equals(other.y.mod(curve.mod)))
{
m = this.x.multiply(this.x).multiply(new BigInteger(new byte[]{3})).add(curve.a).multiply(this.y.add(this.y).modInverse(curve.mod));
} else
{
return new WeierstrassPoint(this.curve);
}
} else
{
m = other.y.add(this.y.negate()).multiply(other.x.add(this.x.negate()).modInverse(curve.mod));
}
x = m.multiply(m).add(this.x.negate()).add(other.x.negate());
y = x.add(this.x.negate()).multiply(m).add(this.y);
return new WeierstrassPoint(this.curve, x.mod(curve.mod), y.negate().mod(curve.mod));
}
public WeierstrassPoint mult(BigInteger n)
{
if (n.compareTo(BigInteger.ZERO) == 0)
{
return new WeierstrassPoint(this.curve);
}
WeierstrassPoint half = this.mult(n.shiftRight(1));
if (n.getLowestSetBit() == 0)
{
return this.add(half).add(half);
} else
{
return half.add(half);
}
}
public WeierstrassPoint inv()
{
return new WeierstrassPoint(this.curve, this.x, this.y.negate());
}
@Override
public boolean equals(Object otherobj)
{
if (!(otherobj instanceof WeierstrassPoint))
{
return false;
}
WeierstrassPoint other = (WeierstrassPoint) otherobj;
if (!other.isIdentity && !this.isIdentity)
return true;
if (this.curve.equals(other.curve) && this.isIdentity == other.isIdentity && this.x.equals(other.x) && this.y.equals(other.y))
return true;
else return false;
}
}

64
sample/Main.java

@ -1,23 +1,63 @@
package sample;
import crypto.CryptoSocket;
import crypto.PaddedInputStream;
import crypto.PaddedOutputStream;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
import javax.xml.crypto.Data;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Main
{
public static void main(String[] args) {
launch(args);
}
Object lock = new Object();
try
{
ServerSocket ssock = new ServerSocket(25519);
Socket s = new Socket("127.0.0.1", 25519);
System.out.println("launching other thread");
new Thread(new Runnable() { public void run() { try
{
//CryptoSocket csock = new CryptoSocket(sock.accept());
Socket sock = ssock.accept();
System.out.println("connection accepted");
DataOutputStream out = new DataOutputStream(new PaddedOutputStream(sock.getOutputStream(), (byte) 32));
//PaddedOutputStream out = new PaddedOutputStream(sock.getOutputStream(), (byte) 32);
DataInputStream in = new DataInputStream(new PaddedInputStream(sock.getInputStream(), (byte) 32));
out.writeUTF("server->client KDKDKDDKKDKDKDKDKDDDKDKDKKDKDDKDKDKDKDKKDKDKDKDKDKDKKDKDKDKDKDKDKDK");
out.flush();
synchronized (lock)
{
System.out.print("server: ");
System.out.println(in.readUTF());
}
} catch (Exception e) {} } }).start();
System.out.println("done; connecting socket");
//CryptoSocket csock = new CryptoSocket(s);
DataOutputStream out = new DataOutputStream(new PaddedOutputStream(s.getOutputStream(), (byte) 32));
DataInputStream in = new DataInputStream(new PaddedInputStream(s.getInputStream(), (byte) 32));
out.writeUTF("client->server REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE");
out.flush();
synchronized (lock)
{
System.out.print("client: ");
System.out.println(in.readUTF());
System.out.println("done printing");
// while (true)
// System.out.println("byte: " + in.read());
}
//System.out.println("done");
} catch (IOException e)
{
e.printStackTrace();
}
}
}
Loading…
Cancel
Save