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)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										117
									
								
								hkexnet.go
								
								
								
								
							
							
						
						
									
										117
									
								
								hkexnet.go
								
								
								
								
							| 
						 | 
					@ -33,35 +33,111 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A HKex connection - drop-in replacement for net.Conn
 | 
					// A HKex connection - drop-in replacement for net.Conn
 | 
				
			||||||
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
 | 
				
			||||||
	r cipher.Stream
 | 
						cipheropts uint32 // post-KEx cipher/hmac options
 | 
				
			||||||
	w cipher.Stream
 | 
						opts       uint32 // post-KEx protocol options
 | 
				
			||||||
 | 
						r          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