Compare commits
merge into: thajohns:master
thajohns:cam
thajohns:crypto
thajohns:crypto-a4
thajohns:master
thajohns:proto
thajohns:server
pull from: thajohns:crypto
thajohns:cam
thajohns:crypto
thajohns:crypto-a4
thajohns:master
thajohns:proto
thajohns:server
9 Commits
Author | SHA1 | Message | Date |
---|---|---|---|
|
7555b52417 |
Moving to a different machine
|
2 years ago |
|
d31369247c |
Made some things protected instead of private, may or may not actually use them
|
2 years ago |
|
0fa0d6aba6 |
Added padded streams
|
2 years ago |
|
bf68ba54c2 |
Broken code, need to figure out flushing
|
2 years ago |
|
57c3189cae |
Finished (?) crypto
|
2 years ago |
|
6cb8370be6 |
Did more work
|
2 years ago |
|
9a8f987a46 |
Fixed a few bugs
|
2 years ago |
|
36c4ba5d80 |
Amended elliptic curve code
|
2 years ago |
|
ded46c9c67 |
Added first iteration of EC code
|
2 years ago |
9 changed files with 512 additions and 12 deletions
-
5crypto/CryptoOutputSocket.java
-
119crypto/CryptoSocket.java
-
63crypto/InterleavedOutput.java
-
47crypto/PaddedInputStream.java
-
64crypto/PaddedOutputStream.java
-
31crypto/W25519.java
-
32crypto/WeierstrassCurve.java
-
99crypto/WeierstrassPoint.java
-
64sample/Main.java
@ -0,0 +1,5 @@ |
|||
package crypto; |
|||
|
|||
public class CryptoOutputSocket |
|||
{ |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
|||
} |
@ -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(); |
|||
} |
|||
} |
@ -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(); |
|||
} |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
|||
|
@ -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; |
|||
} |
|||
} |
@ -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(); |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue