diff --git a/obfs4.go b/obfs4.go
index 17f8b3c3d700f107ab79e85969b9913862b80d5c..f13e14afbb5d61a9e6a1bb1bfda33c3ef02145fd 100644
--- a/obfs4.go
+++ b/obfs4.go
@@ -79,18 +79,37 @@ type Obfs4Conn struct {
 	listener *Obfs4Listener
 }
 
-func (c *Obfs4Conn) calcPadLen(burstLen int) int {
-	tailLen := burstLen % framing.MaximumSegmentLength
+func (c *Obfs4Conn) padBurst(burst *bytes.Buffer) (err error) {
+	tailLen := burst.Len() % framing.MaximumSegmentLength
 	toPadTo := c.lenProbDist.sample()
 
-	ret := 0
+	padLen := 0
 	if toPadTo >= tailLen {
-		ret = toPadTo - tailLen
+		padLen = toPadTo - tailLen
 	} else {
-		ret = (framing.MaximumSegmentLength - tailLen) + toPadTo
+		padLen = (framing.MaximumSegmentLength - tailLen) + toPadTo
 	}
 
-	return ret
+	if padLen > headerLength {
+		err = c.producePacket(burst, packetTypePayload, []byte{},
+			uint16(padLen-headerLength))
+		if err != nil {
+			return
+		}
+	} else if padLen > 0 {
+		err = c.producePacket(burst, packetTypePayload, []byte{},
+			maxPacketPayloadLength)
+		if err != nil {
+			return
+		}
+		err = c.producePacket(burst, packetTypePayload, []byte{},
+			uint16(padLen))
+		if err != nil {
+			return
+		}
+	}
+
+	return
 }
 
 func (c *Obfs4Conn) closeAfterDelay() {
@@ -231,6 +250,11 @@ func (c *Obfs4Conn) serverHandshake(nodeID *ntor.NodeID, keypair *ntor.Keypair)
 		}
 		c.receiveBuffer.Reset()
 
+		err = c.conn.SetDeadline(time.Time{})
+		if err != nil {
+			return
+		}
+
 		// Use the derived key material to intialize the link crypto.
 		okm := ntor.Kdf(seed, framing.KeyLength*2)
 		c.encoder = framing.NewEncoder(okm[framing.KeyLength:])
@@ -249,17 +273,21 @@ func (c *Obfs4Conn) serverHandshake(nodeID *ntor.NodeID, keypair *ntor.Keypair)
 	if err != nil {
 		return
 	}
+	c.state = stateEstablished
 
-	err = c.conn.SetDeadline(time.Time{})
+	// Send the PRNG seed as the first packet.
+	var frameBuf bytes.Buffer
+	err = c.producePacket(&frameBuf, packetTypePrngSeed, c.listener.seed.Bytes()[:], 0)
 	if err != nil {
 		return
 	}
+	err = c.padBurst(&frameBuf)
+	if err != nil {
+		return
+	}
+	_, err = c.conn.Write(frameBuf.Bytes())
 
-	c.state = stateEstablished
-
-	// TODO: Generate/send the PRNG seed.
-
-	return nil
+	return
 }
 
 func (c *Obfs4Conn) CanHandshake() bool {
@@ -379,27 +407,12 @@ func (c *Obfs4Conn) Write(b []byte) (n int, err error) {
 		}
 	}
 
-	// Insert random padding.  In theory it's possible to inline padding for
-	// certain framesizes into the last AEAD packet, but always sending 1 or 2
-	// padding frames is considerably easier.
-	padLen := c.calcPadLen(frameBuf.Len())
-	if padLen > headerLength {
-		err = c.producePacket(&frameBuf, packetTypePayload, []byte{},
-			uint16(padLen-headerLength))
-		if err != nil {
-			return 0, err
-		}
-	} else if padLen > 0 {
-		err = c.producePacket(&frameBuf, packetTypePayload, []byte{},
-			maxPacketPayloadLength)
-		if err != nil {
-			return 0, err
-		}
-		err = c.producePacket(&frameBuf, packetTypePayload, []byte{},
-			uint16(padLen))
-		if err != nil {
-			return 0, err
-		}
+	// Insert random padding.  In theory for some padding lengths, this can be
+	// inlined with the payload, but doing it this way simplifies the code
+	// significantly.
+	err = c.padBurst(&frameBuf)
+	if err != nil {
+		return 0, err
 	}
 
 	// Send the frame(s).
diff --git a/obfs4proxy/obfs4proxy.go b/obfs4proxy/obfs4proxy.go
index 02873b9306b189b4c3364ffe4c175dc2a6ed82ff..8447eb89fef5492dc11a9437e5aca3efb271f1ed 100644
--- a/obfs4proxy/obfs4proxy.go
+++ b/obfs4proxy/obfs4proxy.go
@@ -39,7 +39,7 @@
 //   ORPort 9001
 //   ExtORPort 6669
 //   ServerTransportPlugin obfs4 exec obfs4proxy
-//   ServerTransportOptions obfs4 private-key=<Base64 Bridge private key> node-id=<Base64 Node ID>
+//   ServerTransportOptions obfs4 private-key=<Base64 Bridge private key> node-id=<Base64 Node ID> drbg-seed=<Base64 DRBG seed>
 //
 // Because the pluggable transport requires arguments, obfs4proxy requires
 // tor-0.2.5.x to be useful.
diff --git a/packet.go b/packet.go
index f1c0ab1aa1b787dfd8f19d3bb6b90e1b5295a8b8..4112c9b85e8e5c9c0f7e74482e5404c922dcadbc 100644
--- a/packet.go
+++ b/packet.go
@@ -37,9 +37,10 @@ import (
 )
 
 const (
-	packetOverhead         = 2 + 1
-	maxPacketPayloadLength = framing.MaximumFramePayloadLength - packetOverhead
-	maxPacketPaddingLength = maxPacketPayloadLength
+	packetOverhead          = 2 + 1
+	maxPacketPayloadLength  = framing.MaximumFramePayloadLength - packetOverhead
+	maxPacketPaddingLength  = maxPacketPayloadLength
+	seedPacketPayloadLength = DrbgSeedLength
 
 	consumeReadSize = framing.MaximumSegmentLength * 16
 )
@@ -173,9 +174,9 @@ func (c *Obfs4Conn) consumeFramedPackets(w io.Writer) (n int, err error) {
 			}
 		case packetTypePrngSeed:
 			// Only regenerate the distribution if we are the client.
-			if len(payload) >= DrbgSeedLength && !c.isServer {
+			if len(payload) == seedPacketPayloadLength && !c.isServer {
 				var seed *DrbgSeed
-				seed, err = DrbgSeedFromBytes(payload[:DrbgSeedLength])
+				seed, err = DrbgSeedFromBytes(payload)
 				if err != nil {
 					break
 				}