summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Palfrader <peter@palfrader.org>2003-10-27 19:07:26 +0000
committerPeter Palfrader <peter@palfrader.org>2003-10-27 19:07:26 +0000
commit6ee27b4e16c9478762516bb90ac49e64317b6e57 (patch)
tree225197ff93b89501dccf1e59663495697c8afbc2
parent09cc39b5ffde8b790535929e278ff5c295af88e9 (diff)
First go at SURBs. Still needs testing. Moo.
-rw-r--r--src/org/noreply/fancydress/misc/Util.java27
-rw-r--r--src/org/noreply/fancydress/type3/SURB.java84
2 files changed, 103 insertions, 8 deletions
diff --git a/src/org/noreply/fancydress/misc/Util.java b/src/org/noreply/fancydress/misc/Util.java
index d9b46da..5b67956 100644
--- a/src/org/noreply/fancydress/misc/Util.java
+++ b/src/org/noreply/fancydress/misc/Util.java
@@ -1,6 +1,7 @@
/* $Id$ */
package org.noreply.fancydress.misc;
+import org.bouncycastle.util.encoders.Base64;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.text.ParseException;
@@ -260,4 +261,30 @@ public class Util {
return (String[]) list.toArray(new String[list.size()]);
}
+
+ /**
+ * embed the data in RFC2440 ASCII Armor.
+ *
+ * @param buf octet array to encode
+ * @param header header text
+ * @param additionalHeaders additional headers. /*FIXME: docs are bad
+ */
+ public static String armor(byte[] buf, String header, String[] additionalHeaders) {
+ StringBuffer strbuf = new StringBuffer();
+ strbuf.append("-----BEGIN ");
+ strbuf.append(header);
+ strbuf.append("-----\n");
+ for(int i=0; i<additionalHeaders.length; i++) {
+ strbuf.append(additionalHeaders[i]);
+ strbuf.append("\n");
+ }
+ strbuf.append("\n");
+ strbuf.append(new String(Base64.encode(buf)));
+ strbuf.append("\n");
+ strbuf.append("-----END ");
+ strbuf.append(header);
+ strbuf.append("-----\n");
+
+ return strbuf.toString();
+ }
}
diff --git a/src/org/noreply/fancydress/type3/SURB.java b/src/org/noreply/fancydress/type3/SURB.java
index 400db34..4ef8948 100644
--- a/src/org/noreply/fancydress/type3/SURB.java
+++ b/src/org/noreply/fancydress/type3/SURB.java
@@ -4,23 +4,91 @@ package org.noreply.fancydress.type3;
import org.noreply.fancydress.type3.routing.*;
import org.noreply.fancydress.status.*;
import org.noreply.fancydress.crypto.*;
+import org.noreply.fancydress.misc.*;
public class SURB extends SingleLeg {
+ public static final byte[] VERSION = {0, 1};
+ public static final String ARMOR_VERSION = "0.2";
+ private byte[] sharedSecret;
- public SURB (Path path, RoutingDestination address) throws Mix3BadArgumentsChainTooLongException {
+ public SURB (HalfPath path, byte[] secret, RoutingDestination address) throws Mix3BadArgumentsChainTooLongException {
super();
+ byte[] seed;
+ byte[] validateHash;
+ byte[] validate = Util.toOctets("Validate");
- byte[][] sharedKeys = {};
- Hop[] hops = new Hop[0]; // path.getHops();
+ Hop[] hops = path.getHops();
- /* FIXME */
+ do {
+ seed = CryptoPrimitives.rand(20);
+ seed[0] &= 0x7f;
+ validateHash = CryptoPrimitives.hash(seed, secret, validate);
+ } while (validateHash[validateHash.length-1] == 0);
- makeLeg ( hops, sharedKeys, address);
+ byte[] key = Util.slice(CryptoPrimitives.hash(seed, secret, Util.toOctets("Generate")), 0,CryptoPrimitives.KEY_LEN);
+ byte[] stream = CryptoPrimitives.prng(key, CryptoPrimitives.KEY_LEN*(hops.length + 1));
+ sharedSecret = Util.slice(stream, CryptoPrimitives.KEY_LEN*hops.length, CryptoPrimitives.KEY_LEN);
+ byte[][] sharedKeys = new byte[hops.length][];
+ for (int i=0; i<hops.length; i++)
+ sharedKeys[i] = Util.slice(stream, (hops.length-i-1)*CryptoPrimitives.KEY_LEN, CryptoPrimitives.KEY_LEN);
+
+ makeLeg(hops, sharedKeys, address);
};
- public byte[] getEncryptionKey() {
- return new byte[16];
+ /*
+ Begin Marker: 4 octets
+ Version: 2 octets
+ Use-by-Date: 4 octets
+ SURB header: 2048 octets
+ Routing Size: 2 octets
+ Routing Type: 2 octets
+ Encryption key: 16 octets
+ Routing Info: (Routing Size) octets
+ */
+
+ public String export() {
+ byte[] beginMarker = Util.toOctets("SURB");
+ int useBy = 1068595200; //FIXME // Y2k36
+ byte[] routingInformation = getRoute().getRoutingInformation();
+ int routingSize = routingInformation.length;
+ int routingType = getRoute().getRoutingType();
+
+ byte[] result = new byte[4+2+4+SINGLE_HEADER_LEN+2+2+CryptoPrimitives.KEY_LEN+routingSize];
+
+ int pos = 0;
+ System.arraycopy(beginMarker, 0, result, pos, beginMarker.length);
+ pos += beginMarker.length;
+ System.arraycopy(VERSION, 0, result, pos, VERSION.length);
+ pos += VERSION.length;
+ result[pos] = (byte) ( (useBy >>24) & 0xff);
+ pos++;
+ result[pos] = (byte) ( (useBy >>16) & 0xff);
+ pos++;
+ result[pos] = (byte) ( (useBy >> 8) & 0xff);
+ pos++;
+ result[pos] = (byte) ( (useBy ) & 0xff);
+ pos++;
+ System.arraycopy(super.asOctets(), 0, result, pos, SINGLE_HEADER_LEN);
+ pos += SINGLE_HEADER_LEN;
+ result[pos] = (byte) ( (routingSize >> 8) & 0xff);
+ pos++;
+ result[pos] = (byte) ( routingSize & 0xff);
+ pos++;
+ result[pos] = (byte) ( (routingType >> 8) & 0xff);
+ pos++;
+ result[pos] = (byte) ( routingType & 0xff);
+ pos++;
+ System.arraycopy(sharedSecret, 0, result, pos, CryptoPrimitives.KEY_LEN);
+ pos += CryptoPrimitives.KEY_LEN;
+ System.arraycopy(routingInformation, 0, result, pos, routingSize);
+ pos += routingSize;
+
+ if (pos != result.length)
+ throw new Error("did not fill in expected number of bytes");
+
+ String[] headers = new String[1];
+ headers[0] = "Version: "+ARMOR_VERSION;
+ return Util.armor(result, "TYPE III REPLY BLOCK", headers);
}
}
-