From 6f875c99a9047d8a04a9ac2db9c6305dee3e2901 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Thu, 15 May 2014 19:08:03 +0000 Subject: [PATCH] Load the drbg-seed from the ServerTransportOptions args. This also adds the drgb-seed option to the `-gen` obfs4proxy output. --- obfs4.go | 11 +++---- obfs4proxy/obfs4proxy.go | 20 ++++++++++--- packet.go | 6 ++-- weighted_dist.go | 62 +++++++++++++++++++++------------------- 4 files changed, 56 insertions(+), 43 deletions(-) diff --git a/obfs4.go b/obfs4.go index d3dfc38..17f8b3c 100644 --- a/obfs4.go +++ b/obfs4.go @@ -468,7 +468,7 @@ func Dial(network, address, nodeID, publicKey string) (net.Conn, error) { } // Generate the initial length obfuscation distribution. - seed, err := newRandomDrbgSeed() + seed, err := NewDrbgSeed() if err != nil { return nil, err } @@ -498,7 +498,7 @@ type Obfs4Listener struct { keyPair *ntor.Keypair nodeID *ntor.NodeID - seed *drbgSeed + seed *DrbgSeed } func (l *Obfs4Listener) Accept() (net.Conn, error) { @@ -538,7 +538,7 @@ func (l *Obfs4Listener) PublicKey() string { return l.keyPair.Public().Base64() } -func Listen(network, laddr, nodeID, privateKey string) (net.Listener, error) { +func Listen(network, laddr, nodeID, privateKey, seed string) (net.Listener, error) { var err error // Decode node_id/private_key. @@ -551,10 +551,7 @@ func Listen(network, laddr, nodeID, privateKey string) (net.Listener, error) { if err != nil { return nil, err } - - // Generate the initial length obfuscation distribution. - // XXX: Load this from args. - l.seed, err = newRandomDrbgSeed() + l.seed, err = DrbgSeedFromBase64(seed) if err != nil { return nil, err } diff --git a/obfs4proxy/obfs4proxy.go b/obfs4proxy/obfs4proxy.go index e4a7a35..02873b9 100644 --- a/obfs4proxy/obfs4proxy.go +++ b/obfs4proxy/obfs4proxy.go @@ -31,7 +31,7 @@ // // Client usage (in torrc): // UseBridges 1 -// Bridge obfs4 X.X.X.X:YYYY public-key= node-id= +// Bridge obfs4 X.X.X.X:YYYY public-key= node-id= // ClientTransportPlugin obfs4 exec obfs4proxy // // Server usage (in torrc): @@ -176,10 +176,15 @@ func serverSetup() bool { pt.SmethodError(bindaddr.MethodName, "needs a node-id option") break } + seed, ok := bindaddr.Options.Get("drbg-seed") + if !ok { + pt.SmethodError(bindaddr.MethodName, "needs a drbg-seed option") + break + } // Initialize the listener. ln, err := obfs4.Listen("tcp", bindaddr.Addr.String(), nodeID, - privateKey) + privateKey, seed) if err != nil { pt.SmethodError(bindaddr.MethodName, err.Error()) break @@ -345,16 +350,23 @@ func generateServerParams(id string) { return } + seed, err := obfs4.NewDrbgSeed() + if err != nil { + fmt.Println("Failed to generate DRBG seed:", err) + return + } + fmt.Println("Generated private-key:", keypair.Private().Base64()) fmt.Println("Generated public-key:", keypair.Public().Base64()) + fmt.Println("Generated drbg-seed:", seed.Base64()) fmt.Println() fmt.Println("Client config: ") fmt.Printf(" Bridge obfs4 %s node-id=%s public-key=%s\n", id, parsedID.Base64(), keypair.Public().Base64()) fmt.Println() fmt.Println("Server config:") - fmt.Printf(" ServerTransportOptions obfs4 node-id=%s private-key=%s\n", - parsedID.Base64(), keypair.Private().Base64()) + fmt.Printf(" ServerTransportOptions obfs4 node-id=%s private-key=%s drbg-seed=%s\n", + parsedID.Base64(), keypair.Private().Base64(), seed.Base64()) } func main() { diff --git a/packet.go b/packet.go index 2528a53..f1c0ab1 100644 --- a/packet.go +++ b/packet.go @@ -173,9 +173,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 { - var seed *drbgSeed - seed, err = drbgSeedFromBytes(payload[:drbgSeedLength]) + if len(payload) >= DrbgSeedLength && !c.isServer { + var seed *DrbgSeed + seed, err = DrbgSeedFromBytes(payload[:DrbgSeedLength]) if err != nil { break } diff --git a/weighted_dist.go b/weighted_dist.go index 56128ae..3a6d5b0 100644 --- a/weighted_dist.go +++ b/weighted_dist.go @@ -38,26 +38,26 @@ import ( "github.com/dchest/siphash" ) -const drbgSeedLength = 32 +const DrbgSeedLength = 32 -// drbgSeed is the initial state for a hashDrbg. It consists of a SipHash-2-4 +// DrbgSeed is the initial state for a hashDrbg. It consists of a SipHash-2-4 // key, and 16 bytes of initial data. -type drbgSeed [drbgSeedLength]byte +type DrbgSeed [DrbgSeedLength]byte -// bytes returns a pointer to the raw hashDrbg seed. -func (seed *drbgSeed) bytes() *[drbgSeedLength]byte { - return (*[drbgSeedLength]byte)(seed) +// Bytes returns a pointer to the raw hashDrbg seed. +func (seed *DrbgSeed) Bytes() *[DrbgSeedLength]byte { + return (*[DrbgSeedLength]byte)(seed) } -// base64 returns the Base64 representation of the seed. -func (seed *drbgSeed) base64() string { - return base64.StdEncoding.EncodeToString(seed.bytes()[:]) +// Base64 returns the Base64 representation of the seed. +func (seed *DrbgSeed) Base64() string { + return base64.StdEncoding.EncodeToString(seed.Bytes()[:]) } -// newRandomDrbgSeed returns a drbgSeed initialized with the runtime CSPRNG. -func newRandomDrbgSeed() (seed *drbgSeed, err error) { - seed = new(drbgSeed) - _, err = csrand.Read(seed.bytes()[:]) +// NewDrbgSeed returns a DrbgSeed initialized with the runtime CSPRNG. +func NewDrbgSeed() (seed *DrbgSeed, err error) { + seed = new(DrbgSeed) + _, err = csrand.Read(seed.Bytes()[:]) if err != nil { return nil, err } @@ -65,24 +65,28 @@ func newRandomDrbgSeed() (seed *drbgSeed, err error) { return } -// drbgSeedFromBytes returns a drbg seed initialized with the caller provided -// slice. -func drbgSeedFromBytes(src []byte) (seed *drbgSeed, err error) { - if len(src) != drbgSeedLength { +// DrbgSeedFromBytes creates a DrbgSeed from the raw bytes. +func DrbgSeedFromBytes(src []byte) (seed *DrbgSeed, err error) { + if len(src) != DrbgSeedLength { return nil, InvalidSeedLengthError(len(src)) } - seed = new(drbgSeed) - copy(seed.bytes()[:], src) + seed = new(DrbgSeed) + copy(seed.Bytes()[:], src) return } -/* -func drbgSeedFromBse64(encoded string) (seed *drbgSeed, err error) { - return +// DrbgSeedFromBase64 creates a DrbgSeed from the Base64 representation. +func DrbgSeedFromBase64(encoded string) (seed *DrbgSeed, err error) { + var raw []byte + raw, err = base64.StdEncoding.DecodeString(encoded) + if err != nil { + return nil, err + } + + return DrbgSeedFromBytes(raw) } -*/ // InvalidSeedLengthError is the error returned when the seed provided to the // DRBG is an invalid length. @@ -99,11 +103,11 @@ type hashDrbg struct { } // newHashDrbg makes a hashDrbg instance based off an optional seed. The seed -// is truncated to drbgSeedLength. -func newHashDrbg(seed *drbgSeed) *hashDrbg { +// is truncated to DrbgSeedLength. +func newHashDrbg(seed *DrbgSeed) *hashDrbg { drbg := new(hashDrbg) - drbg.sip = siphash.New(seed.bytes()[:16]) - copy(drbg.ofb[:], seed.bytes()[16:]) + drbg.sip = siphash.New(seed.Bytes()[:16]) + copy(drbg.ofb[:], seed.Bytes()[16:]) return drbg } @@ -135,7 +139,7 @@ type wDist struct { // newWDist creates a weighted distribution of values ranging from min to max // based on a hashDrbg initialized with seed. -func newWDist(seed *drbgSeed, min, max int) (w *wDist) { +func newWDist(seed *DrbgSeed, min, max int) (w *wDist) { w = new(wDist) w.minValue = min w.maxValue = max @@ -166,7 +170,7 @@ func (w *wDist) sample() int { } // reset generates a new distribution with the same min/max based on a new seed. -func (w *wDist) reset(seed *drbgSeed) { +func (w *wDist) reset(seed *DrbgSeed) { // Initialize the deterministic random number generator. drbg := newHashDrbg(seed) dRng := rand.New(drbg)