commit ba2c03afe36f8ec80e2b0896b35e0fbbe5eeee39 Author: Russ Magee Date: Sat Jan 6 15:30:56 2018 +0000 Initial commit diff --git a/demo/Herradura b/demo/Herradura new file mode 100755 index 0000000..7872bcb Binary files /dev/null and b/demo/Herradura differ diff --git a/demo/Herradura.go b/demo/Herradura.go new file mode 100644 index 0000000..57fa663 --- /dev/null +++ b/demo/Herradura.go @@ -0,0 +1,57 @@ +/* Herradura - a Key exchange scheme in the style of Diffie-Hellman Key Exchange. + Copyright (C) 2017 Omar Alejandro Herrera Reyna + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + golang implementation by Russ Magee (rmagee_at_gmail.com) */ +package main + +import ( + "flag" + "fmt" + hkex "blitter.com/herradurakex" +) + +func main() { + var s int //MUST be 2^n where n is an integer + var p int //Amount of bits to share (a,a,b,b2) + + flag.IntVar(&s, "s", 256, "Size in bits of secret (fa,fa2)") + flag.IntVar(&p, "p", 64, "Size in bits of shared public portion (b,b2)") + flag.Parse() + + fmt.Printf("s=%v p=%v\n", s, p) + + hkexAlice := hkex.New(s, p) + hkexBob := hkex.New(s, p) + + fmt.Println("ALICE:") + fmt.Println(hkexAlice) + + fmt.Println("BOB:") + fmt.Println(hkexBob) + + // Alice and Bob exchange D + // (This, of course, would occur over a public channel between peers) + // hkexAlice and hkexBob would each be in separate contexts + // (processes, client/server etc.) + hkexBob.PeerD = hkexAlice.D() + hkexAlice.PeerD = hkexBob.D() + + hkexAlice.FA() + fmt.Println(hkexAlice) + + hkexBob.FA() + fmt.Println(hkexBob) +} diff --git a/demo/client b/demo/client new file mode 100755 index 0000000..3ff95e2 Binary files /dev/null and b/demo/client differ diff --git a/demo/client.go b/demo/client.go new file mode 100644 index 0000000..301f709 --- /dev/null +++ b/demo/client.go @@ -0,0 +1,18 @@ +package main + +import ( + "bufio" + "fmt" + "net" +) + +func main() { + conn, err := net.Dial("tcp", "localhost:2000") + if err != nil { + // handle error + } + fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n") +// status, err := bufio.NewReader(conn).ReadString('\n') + _, err = bufio.NewReader(conn).ReadString('\n') + // ... +} diff --git a/demo/server b/demo/server new file mode 100755 index 0000000..dd72b73 Binary files /dev/null and b/demo/server differ diff --git a/demo/server.go b/demo/server.go new file mode 100644 index 0000000..91c59fb --- /dev/null +++ b/demo/server.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "io" + "log" + "net" +) + +func main() { + // Listen on TCP port 2000 on all available unicast and + // anycast IP addresses of the local system. + l, err := net.Listen("tcp", ":2000") + if err != nil { + log.Fatal(err) + } + defer l.Close() + + fmt.Println("Serving on port 2000") + for { + // Wait for a connection. + conn, err := l.Accept() + if err != nil { + log.Fatal(err) + } + + fmt.Println("Accepted client") + + + // Handle the connection in a new goroutine. + // The loop then returns to accepting, so that + // multiple connections may be served concurrently. + go func(c net.Conn) { + // Echo all incoming data. + io.Copy(c, c) + fmt.Println("Client sent:%v\n",c) + // Shut down the connection. + c.Close() + }(conn) + } +} diff --git a/herradurakex.go b/herradurakex.go new file mode 100644 index 0000000..e5be8f8 --- /dev/null +++ b/herradurakex.go @@ -0,0 +1,132 @@ +/* Herradura - a Key exchange scheme in the style of Diffie-Hellman Key Exchange. + Copyright (C) 2017 Omar Alejandro Herrera Reyna + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + golang implementation by Russ Magee (rmagee_at_gmail.com) */ +package herradurakex + +import ( + "fmt" + "math/big" + "math/rand" + "time" +) + +// This type holds the session state for a key exchange +type HerraduraKEx struct { + intSz, pubSz int + randctx *rand.Rand + a *big.Int + b *big.Int + d, PeerD *big.Int + fa *big.Int +} + +// Returns a new HerraduraKEx struct +func New(i int, p int) (h *HerraduraKEx) { + h = new(HerraduraKEx) + + h.intSz = i + h.pubSz = p + + h.seed() + h.a = h.rand() + h.b = h.rand() + + h.d = h.fscxRevolve(h.a, h.b, h.pubSz) + return h +} + +func (h *HerraduraKEx) seed() { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + h.randctx = r +} + +func (h *HerraduraKEx) rand() (v *big.Int) { + v = big.NewInt(0) + v.Rand(h.randctx, h.getMax()) + return v +} + +// Return max value for an n-bit big.Int +func (h *HerraduraKEx) getMax() (v *big.Int) { + v = big.NewInt(0) + var max big.Int + + for i := 0; i < h.intSz; i++ { + max.SetBit(v, i, 1) + } + v = &max + return v +} + +func (h *HerraduraKEx) bitX(x *big.Int, pos int) (ret int64) { + if pos < 0 { + pos = h.intSz - pos + } + + if pos == 0 { + ret = int64(x.Bit(1) ^ x.Bit(0) ^ x.Bit(h.intSz-1)) + } else if pos == h.intSz-1 { + ret = int64(x.Bit(0) ^ x.Bit(pos) ^ x.Bit(pos-1)) + } else { + ret = int64(x.Bit((pos+1)%h.intSz) ^ x.Bit(pos) ^ x.Bit(pos-1)) + } + return ret +} + +func (h *HerraduraKEx) bit(up, down *big.Int, posU, posD int) (ret *big.Int) { + return big.NewInt(h.bitX(up, posU) ^ h.bitX(down, posD)) +} + +func (h *HerraduraKEx) fscx(up, down *big.Int) (result *big.Int) { + result = big.NewInt(0) + + for count := 0; count < h.intSz; count++ { + result.Lsh(result, 1) + result.Add(result, h.bit(up, down, count, count)) + } + return result +} + +// This is the iteration function using the result of the previous iteration as the first +// parameter and the second parameter of the first iteration +func (h *HerraduraKEx) fscxRevolve(x, y *big.Int, passes int) (result *big.Int) { + result = big.NewInt(0) + + result = x + for count := 0; count < passes; count++ { + result = h.fscx(result, y) + } + return result +} + +func (h *HerraduraKEx) D() *big.Int { + return h.d +} + +func (h *HerraduraKEx) FA() { + h.fa = h.fscxRevolve(h.PeerD, h.b, h.intSz-h.pubSz) + h.fa.Xor(h.fa, h.a) +} + +func (h *HerraduraKEx) String() string { + return fmt.Sprintf("s:%d p:%d\na:%s\nb:%s\nd:->%s\n<-PeerD:%s\nfa:%s", + h.intSz, h.pubSz, + h.a.Text(16), h.b.Text(16), + h.d.Text(16), + h.PeerD.Text(16), + h.fa.Text(16)) +}