diff options
Diffstat (limited to 'src/org/noreply/fancydress/type3/SURB.java')
-rw-r--r-- | src/org/noreply/fancydress/type3/SURB.java | 84 |
1 files changed, 76 insertions, 8 deletions
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); } } - |