mirror of https://gogs.blitter.com/RLabs/xs
Dial() extensions to specify cipher/hmac alg and protocol options
This commit is contained in:
parent
02d4d0cd50
commit
9054bcb89f
|
@ -13,7 +13,7 @@ import (
|
||||||
// encrypt/decrypt is done within the type.
|
// encrypt/decrypt is done within the type.
|
||||||
// Compare to 'clientp.go' in this directory to see the equivalence.
|
// Compare to 'clientp.go' in this directory to see the equivalence.
|
||||||
func main() {
|
func main() {
|
||||||
conn, err := hkex.Dial("tcp", "localhost:2000")
|
conn, err := hkex.Dial("tcp", "localhost:2000", "C_TWOFISH_128")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// handle error
|
// handle error
|
||||||
fmt.Println("Err!")
|
fmt.Println("Err!")
|
||||||
|
|
|
@ -38,11 +38,6 @@ type HerraduraKEx struct {
|
||||||
fa *big.Int
|
fa *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
//// Returns a new HerraduraKEx struct with default intSz,pubSz
|
|
||||||
//func New() (h *HerraduraKEx) {
|
|
||||||
// return New(256, 64)
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Return a new HerraduraKEx struct.
|
// Return a new HerraduraKEx struct.
|
||||||
// i - internal (private) random nonce
|
// i - internal (private) random nonce
|
||||||
// p - public (exchanged) random nonce (typically 1/4 bitsize of i)
|
// p - public (exchanged) random nonce (typically 1/4 bitsize of i)
|
||||||
|
@ -145,7 +140,6 @@ func (h *HerraduraKEx) FA() {
|
||||||
h.fa = h.fscxRevolve(h.PeerD, h.b, h.intSz-h.pubSz)
|
h.fa = h.fscxRevolve(h.PeerD, h.b, h.intSz-h.pubSz)
|
||||||
h.fa.Xor(h.fa, h.a)
|
h.fa.Xor(h.fa, h.a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output HerraduraKEx type value as a string. Implements Stringer interface.
|
// Output HerraduraKEx type value as a string. Implements Stringer interface.
|
||||||
func (h *HerraduraKEx) String() string {
|
func (h *HerraduraKEx) String() string {
|
||||||
return fmt.Sprintf("s:%d p:%d\na:%s\nb:%s\nd:->%s\n<-PeerD:%s\nfa:%s",
|
return fmt.Sprintf("s:%d p:%d\na:%s\nb:%s\nd:->%s\n<-PeerD:%s\nfa:%s",
|
||||||
|
|
45
hkexchan.go
45
hkexchan.go
|
@ -27,31 +27,35 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/twofish"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Available ciphers for hkex.Conn
|
// Available ciphers for hkex.Conn
|
||||||
const (
|
const (
|
||||||
C_AES_256 = 0 // (TODO: config or pass during KEx Dial()/Accept()) AES-256 cipher
|
C_AES_256 = iota
|
||||||
|
C_TWOFISH_128 // golang.org/x/crypto/twofish
|
||||||
|
C_NONE_DISALLOWED
|
||||||
)
|
)
|
||||||
|
|
||||||
// Available HMACs for hkex.Conn (TODO: not currently used)
|
// Available HMACs for hkex.Conn (TODO: not currently used)
|
||||||
const (
|
const (
|
||||||
H_SHA256 = 0
|
H_BOGUS = iota
|
||||||
|
H_SHA256
|
||||||
|
H_NONE_DISALLOWED
|
||||||
)
|
)
|
||||||
|
|
||||||
/*TODO: HMAC derived from HKEx FA.*/
|
/*TODO: HMAC derived from HKEx FA.*/
|
||||||
/* Support functionality to set up encryption after a channel has
|
/* Support functionality to set up encryption after a channel has
|
||||||
been negotiated via hkexnet.go
|
been negotiated via hkexnet.go
|
||||||
*/
|
*/
|
||||||
func (hc Conn) getStream(keymat *big.Int, flags uint32) (ret cipher.Stream) {
|
func (hc Conn) getStream(keymat *big.Int) (ret cipher.Stream) {
|
||||||
var key []byte
|
var key []byte
|
||||||
var block cipher.Block
|
var block cipher.Block
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// 256 algs should be enough for everybody.(tm)
|
copts := hc.cipheropts & 0xFF
|
||||||
cipherAlg := (flags & 8)
|
switch copts {
|
||||||
//TODO: flags for HMAC from keymat
|
|
||||||
switch cipherAlg {
|
|
||||||
case C_AES_256:
|
case C_AES_256:
|
||||||
key = keymat.Bytes()[0:aes.BlockSize]
|
key = keymat.Bytes()[0:aes.BlockSize]
|
||||||
block, err = aes.NewCipher(key)
|
block, err = aes.NewCipher(key)
|
||||||
|
@ -61,13 +65,38 @@ func (hc Conn) getStream(keymat *big.Int, flags uint32) (ret cipher.Stream) {
|
||||||
//}
|
//}
|
||||||
iv = keymat.Bytes()[aes.BlockSize:]
|
iv = keymat.Bytes()[aes.BlockSize:]
|
||||||
ret = cipher.NewOFB(block, iv)
|
ret = cipher.NewOFB(block, iv)
|
||||||
|
fmt.Printf("[cipher AES_256 (%d)]\n", copts)
|
||||||
|
break
|
||||||
|
case C_TWOFISH_128:
|
||||||
|
key = keymat.Bytes()[0:twofish.BlockSize]
|
||||||
|
block, err = twofish.NewCipher(key)
|
||||||
|
iv := make([]byte, twofish.BlockSize)
|
||||||
|
//if _, err = io.ReadFull(crand.Reader, iv); err != nil {
|
||||||
|
// panic(err)
|
||||||
|
//}
|
||||||
|
iv = keymat.Bytes()[twofish.BlockSize:]
|
||||||
|
ret = cipher.NewOFB(block, iv)
|
||||||
|
fmt.Printf("[cipher TWOFISH_256 (%d)]\n", copts)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
fmt.Println("DOOFUS SET A VALID CIPHER ALG")
|
fmt.Printf("DOOFUS SET A VALID CIPHER ALG (%d)\n", copts)
|
||||||
block, err = nil, nil
|
block, err = nil, nil
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hopts := (hc.cipheropts >> 8) & 0xFF
|
||||||
|
switch hopts {
|
||||||
|
case H_BOGUS:
|
||||||
|
fmt.Printf("[nop H_BOGUS (%d)]\n", hopts)
|
||||||
|
break
|
||||||
|
case H_SHA256:
|
||||||
|
fmt.Printf("[nop H_SHA256 (%d)]\n", hopts)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
fmt.Printf("DOOFUS SET A VALID HMAC ALG (%d)\n", hopts)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
109
hkexnet.go
109
hkexnet.go
|
@ -35,33 +35,109 @@ import (
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
c net.Conn // which also implements io.Reader, io.Writer, ...
|
c net.Conn // which also implements io.Reader, io.Writer, ...
|
||||||
h *HerraduraKEx
|
h *HerraduraKEx
|
||||||
|
cipheropts uint32 // post-KEx cipher/hmac options
|
||||||
|
opts uint32 // post-KEx protocol options
|
||||||
r cipher.Stream
|
r cipher.Stream
|
||||||
w cipher.Stream
|
w cipher.Stream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the cipher/hmac options value, which is sent to the peer but is
|
||||||
|
// not itself part of the KEx.
|
||||||
|
// (Used for protocol-level negotiations after KEx such as
|
||||||
|
// cipher/HMAC algorithm options etc.)
|
||||||
|
func (c *Conn) ConnOpts() uint32 {
|
||||||
|
return c.cipheropts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set cipher/hmac options value, which is sent to the peer as part of
|
||||||
|
// KEx but not part of the KEx itself.
|
||||||
|
//
|
||||||
|
// opts - bitfields for cipher and hmac alg. to use after KEx
|
||||||
|
func (c *Conn) SetConnOpts(copts uint32) {
|
||||||
|
c.cipheropts = copts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the protocol options value, which is sent to the peer but is
|
||||||
|
// not itself part of the KEx or connection (cipher/hmac) setup.
|
||||||
|
//
|
||||||
|
// Consumers of this lib may use this for protocol-level options not part
|
||||||
|
// of the KEx or encryption info used by the connection.
|
||||||
|
func (c *Conn) Opts() uint32 {
|
||||||
|
return c.opts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the protocol options value, which is sent to the peer but is
|
||||||
|
// not itself part of the KEx or connection (cipher/hmac) setup.
|
||||||
|
|
||||||
|
// Consumers of this lib may use this for protocol-level options not part
|
||||||
|
// of the KEx of encryption info used by the connection.
|
||||||
|
//
|
||||||
|
// opts - a uint32, caller-defined
|
||||||
|
func (c *Conn) SetOpts(opts uint32) {
|
||||||
|
c.opts = opts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *Conn) applyConnExtensions(extensions ...string) {
|
||||||
|
for _, s := range extensions {
|
||||||
|
switch s {
|
||||||
|
case "C_AES_256":
|
||||||
|
hc.cipheropts &= (0xFFFFFF00)
|
||||||
|
hc.cipheropts |= C_AES_256
|
||||||
|
break
|
||||||
|
case "C_TWOFISH_128":
|
||||||
|
fmt.Println("[extension arg = C_TWOFISH_128]")
|
||||||
|
hc.cipheropts &= (0xFFFFFF00)
|
||||||
|
hc.cipheropts |= C_TWOFISH_128
|
||||||
|
break
|
||||||
|
case "H_SHA256":
|
||||||
|
hc.cipheropts &= (0xFFFF00FF)
|
||||||
|
hc.cipheropts |= (H_SHA256 << 8)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
fmt.Printf("[Dial ext \"%s\" ignored]\n", s)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dial as net.Dial(), but with implicit HKEx PeerD read on connect
|
// Dial as net.Dial(), but with implicit HKEx PeerD read on connect
|
||||||
func Dial(protocol string, ipport string) (hc *Conn, err error) {
|
// Can be called like net.Dial(), defaulting to C_AES_256/H_SHA256,
|
||||||
|
// or additional option arguments can be passed amongst the following:
|
||||||
|
//
|
||||||
|
// "C_AES_256" | "C_TWOFISH_128"
|
||||||
|
//
|
||||||
|
// "H_SHA256"
|
||||||
|
func Dial(protocol string, ipport string, extensions ...string) (hc *Conn, err error) {
|
||||||
c, err := net.Dial(protocol, ipport)
|
c, err := net.Dial(protocol, ipport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hc = &Conn{c, New(0, 0), nil, nil}
|
hc = &Conn{c: c, h: New(0, 0), cipheropts: 0, opts: 0, r: nil, w: nil}
|
||||||
|
|
||||||
fmt.Fprintf(c, "0x%s\n", hc.h.d.Text(16))
|
hc.applyConnExtensions(extensions...)
|
||||||
|
|
||||||
|
fmt.Fprintf(c, "0x%s\n%08x:%08x\n", hc.h.d.Text(16),
|
||||||
|
hc.cipheropts, hc.opts)
|
||||||
|
|
||||||
d := big.NewInt(0)
|
d := big.NewInt(0)
|
||||||
_, err = fmt.Fscanln(c, d)
|
_, err = fmt.Fscanln(c, d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = fmt.Fscanf(c, "%08x:%08x\n",
|
||||||
|
&hc.cipheropts, &hc.opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
hc.h.PeerD = d
|
hc.h.PeerD = d
|
||||||
fmt.Printf("** D:%s\n", hc.h.d.Text(16))
|
fmt.Printf("** D:%s\n", hc.h.d.Text(16))
|
||||||
fmt.Printf("**(c)** peerD:%s\n", hc.h.PeerD.Text(16))
|
fmt.Printf("**(c)** peerD:%s\n", hc.h.PeerD.Text(16))
|
||||||
hc.h.FA()
|
hc.h.FA()
|
||||||
fmt.Printf("**(c)** FA:%s\n", hc.h.fa)
|
fmt.Printf("**(c)** FA:%s\n", hc.h.fa)
|
||||||
|
|
||||||
hc.r = hc.getStream(hc.h.fa, 0x0)
|
hc.r = hc.getStream(hc.h.fa)
|
||||||
hc.w = hc.getStream(hc.h.fa, 0x0)
|
hc.w = hc.getStream(hc.h.fa)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,17 +175,22 @@ func (hl *HKExListener) Close() {
|
||||||
// Accept a client connection, conforming to net.Listener.Accept()
|
// Accept a client connection, conforming to net.Listener.Accept()
|
||||||
func (hl *HKExListener) Accept() (hc Conn, err error) {
|
func (hl *HKExListener) Accept() (hc Conn, err error) {
|
||||||
c, err := hl.l.Accept()
|
c, err := hl.l.Accept()
|
||||||
|
|
||||||
fmt.Println("[Accepted]")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Conn{nil, nil, nil, nil}, err
|
return Conn{c: nil, h: nil, cipheropts: 0, opts: 0,
|
||||||
|
r: nil, w: nil}, err
|
||||||
}
|
}
|
||||||
hc = Conn{c: c, h: New(0, 0), r: nil, w: nil}
|
fmt.Println("[Accepted]")
|
||||||
|
|
||||||
|
hc = Conn{c: c, h: New(0, 0), cipheropts: 0, opts: 0, r: nil, w: nil}
|
||||||
|
|
||||||
d := big.NewInt(0)
|
d := big.NewInt(0)
|
||||||
_, err = fmt.Fscanln(c, d)
|
_, err = fmt.Fscanln(c, d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("[Error]")
|
return hc, err
|
||||||
|
}
|
||||||
|
_, err = fmt.Fscanf(c, "%08x:%08x\n",
|
||||||
|
&hc.cipheropts, &hc.opts)
|
||||||
|
if err != nil {
|
||||||
return hc, err
|
return hc, err
|
||||||
}
|
}
|
||||||
hc.h.PeerD = d
|
hc.h.PeerD = d
|
||||||
|
@ -118,10 +199,11 @@ func (hl *HKExListener) Accept() (hc Conn, err error) {
|
||||||
hc.h.FA()
|
hc.h.FA()
|
||||||
fmt.Printf("**(s)** FA:%s\n", hc.h.fa)
|
fmt.Printf("**(s)** FA:%s\n", hc.h.fa)
|
||||||
|
|
||||||
fmt.Fprintf(c, "0x%s\n", hc.h.d.Text(16))
|
fmt.Fprintf(c, "0x%s\n%08x:%08x\n", hc.h.d.Text(16),
|
||||||
|
hc.cipheropts, hc.opts)
|
||||||
|
|
||||||
hc.r = hc.getStream(hc.h.fa, 0x0)
|
hc.r = hc.getStream(hc.h.fa)
|
||||||
hc.w = hc.getStream(hc.h.fa, 0x0)
|
hc.w = hc.getStream(hc.h.fa)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,4 +258,3 @@ func (hc Conn) Write(b []byte) (n int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue