-Added client -c option to pass cipher alg

-Note about blowfish iv len (lack of) bounds check in .NewOFB();
-TODO added to enforce keymat from HKex >= 2*chosen cipher blocksize
 (assuming keylen == blocksize -- might not be true for all future algs)
This commit is contained in:
Russ Magee 2018-01-11 23:01:39 -08:00
parent aaa99360be
commit 5493921e9f
3 changed files with 41 additions and 11 deletions

View File

@ -1,6 +1,7 @@
package main
import (
"flag"
"fmt"
hkex "blitter.com/herradurakex"
@ -13,7 +14,12 @@ import (
// encrypt/decrypt is done within the type.
// Compare to 'clientp.go' in this directory to see the equivalence.
func main() {
conn, err := hkex.Dial("tcp", "localhost:2000", "C_TWOFISH_128")
var cAlg string
flag.StringVar(&cAlg, "c", "C_AES_256", "cipher [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\"]")
flag.Parse()
conn, err := hkex.Dial("tcp", "localhost:2000", cAlg)
if err != nil {
// handle error
fmt.Println("Err!")

View File

@ -28,6 +28,7 @@ import (
"math/big"
"os"
"golang.org/x/crypto/blowfish"
"golang.org/x/crypto/twofish"
)
@ -35,6 +36,7 @@ import (
const (
C_AES_256 = iota
C_TWOFISH_128 // golang.org/x/crypto/twofish
C_BLOWFISH_64 // golang.org/x/crypto/blowfish
C_NONE_DISALLOWED
)
@ -52,31 +54,48 @@ been negotiated via hkexnet.go
func (hc Conn) getStream(keymat *big.Int) (ret cipher.Stream) {
var key []byte
var block cipher.Block
var ivlen int
var err error
copts := hc.cipheropts & 0xFF
// TODO: each cipher alg case should ensure len(keymat.Bytes())
// is >= 2*cipher.BlockSize (enough for both key and iv)
switch copts {
case C_AES_256:
key = keymat.Bytes()[0:aes.BlockSize]
block, err = aes.NewCipher(key)
ivlen = aes.BlockSize
iv := make([]byte, aes.BlockSize)
//if _, err = io.ReadFull(crand.Reader, iv); err != nil {
// panic(err)
//}
iv = keymat.Bytes()[aes.BlockSize:]
iv = keymat.Bytes()[aes.BlockSize : aes.BlockSize+ivlen]
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)
ivlen = twofish.BlockSize
iv := make([]byte, twofish.BlockSize)
//if _, err = io.ReadFull(crand.Reader, iv); err != nil {
// panic(err)
//}
iv = keymat.Bytes()[twofish.BlockSize:]
iv = keymat.Bytes()[twofish.BlockSize : twofish.BlockSize+ivlen]
ret = cipher.NewOFB(block, iv)
fmt.Printf("[cipher TWOFISH_256 (%d)]\n", copts)
fmt.Printf("[cipher TWOFISH_128 (%d)]\n", copts)
break
case C_BLOWFISH_64:
key = keymat.Bytes()[0:blowfish.BlockSize]
block, err = blowfish.NewCipher(key)
ivlen = blowfish.BlockSize
iv := make([]byte, blowfish.BlockSize)
// N.b. Bounds enforcement of differing cipher algorithms
// ------------------------------------------------------
// cipher/aes and x/cipher/twofish appear to allow one to
// pass an iv larger than the blockSize harmlessly to
// cipher.NewOFB(); x/cipher/blowfish implementation will
// segfault here if len(iv) is not exactly blowfish.BlockSize.
//
// I assume the other two check bounds and only
// copy what's needed whereas blowfish does no such check.
iv = keymat.Bytes()[blowfish.BlockSize : blowfish.BlockSize+ivlen]
ret = cipher.NewOFB(block, iv)
fmt.Printf("[cipher BLOWFISH_64 (%d)]\n", copts)
break
default:
fmt.Printf("DOOFUS SET A VALID CIPHER ALG (%d)\n", copts)
@ -86,7 +105,7 @@ func (hc Conn) getStream(keymat *big.Int) (ret cipher.Stream) {
hopts := (hc.cipheropts >> 8) & 0xFF
switch hopts {
case H_BOGUS:
case H_BOGUS:
fmt.Printf("[nop H_BOGUS (%d)]\n", hopts)
break
case H_SHA256:

View File

@ -89,6 +89,11 @@ func (hc *Conn) applyConnExtensions(extensions ...string) {
hc.cipheropts &= (0xFFFFFF00)
hc.cipheropts |= C_TWOFISH_128
break
case "C_BLOWFISH_64":
fmt.Println("[extension arg = C_BLOWFISH_64]")
hc.cipheropts &= (0xFFFFFF00)
hc.cipheropts |= C_BLOWFISH_64
break
case "H_SHA256":
hc.cipheropts &= (0xFFFF00FF)
hc.cipheropts |= (H_SHA256 << 8)