summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--obfs4.go11
-rw-r--r--obfs4proxy/obfs4proxy.go20
-rw-r--r--packet.go6
-rw-r--r--weighted_dist.go62
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=<Base64 Bridge public key> node-id=<Base64 Bridge Node ID>
+// Bridge obfs4 X.X.X.X:YYYY <fingerprint> public-key=<Base64 Bridge public key> node-id=<Base64 Bridge 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 <IP Address:Port> %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)