/* $Id$ */ package org.noreply.fancydress.type3; import org.noreply.fancydress.misc.Util; import org.noreply.fancydress.type3.routing.*; import org.noreply.fancydress.crypto.*; import org.noreply.fancydress.status.*; import java.util.*; public class Packet { private byte[] packet; private RoutingForward thisRoute; public Packet( Path path, RoutingDestination address, byte[] payload) throws Mix3BadArgumentsChainTooLongException { ForwardLeg leg2 = new ForwardLeg(path.getSecondHalf(), address); if (!(leg2.getRoute() instanceof RoutingForward)) throw new Error("Routing Type of second leg is not a forward type."); ForwardLeg leg1 = new ForwardLeg(path.getFirstHalf(), ((RoutingForward)leg2.getRoute()).asSwap()); makePacket(leg1, leg2, payload); } public Packet( HalfPath path, SURB surb, byte[] payload) throws Mix3BadArgumentsChainTooLongException { ForwardLeg leg1 = new ForwardLeg(path, surb.getRoute()); makePacket(leg1, surb, payload); } public static boolean isPacketVersionSupported(String s) { return s.equals(SingleLeg.MAJOR_VERSION + "." + SingleLeg.MINOR_VERSION); } private void makePacket(ForwardLeg leg1, SingleLeg leg2, byte[] p) { byte h1[] = leg1.asOctets(); byte h2[] = leg2.asOctets(); if (p.length != 28*1024) throw new IllegalArgumentException("Payload needs to be 28 kb long"); // Phase 1 if (leg2 instanceof SURB) { byte[] k = ((SURB) leg2).getEncryptionKey(); p = CryptoPrimitives.sprpDecrypt(k, "PAYLOAD ENCRYPT", p); } else { byte[][] sk = ((ForwardLeg) leg2).getSharedKeys(); for (int i=sk.length-1; i>=0; i--) p = CryptoPrimitives.sprpEncrypt(sk[i], "PAYLOAD ENCRYPT", p); } // Phase 2 h2 = CryptoPrimitives.sprpEncrypt(CryptoPrimitives.hash(p), "HIDE HEADER", h2); p = CryptoPrimitives.sprpEncrypt(CryptoPrimitives.hash(h2), "HIDE PAYLOAD", p); byte[][] sk = leg1.getSharedKeys(); for (int i=sk.length-1; i>=0; i--) { h2 = CryptoPrimitives.sprpEncrypt(sk[i], "HEADER ENCRYPT", h2); p = CryptoPrimitives.sprpEncrypt(sk[i], "PAYLOAD ENCRYPT", p); } packet = Util.concat(Util.concat(h1,h2),p); thisRoute = leg1.getRoute(); if (packet.length != 32*1024) throw new Error("packet is not 32k bytes"); } public RoutingForward getRoute() { return thisRoute; } public byte[] asOctets() { return packet; } }