Added NEWHOPE and NEWHOPE_SIMPLE KEM algs

Fixed some -h typos, missing H_SHA512 option
randReader seed time.Now().UnixNano()

Signed-off-by: Russ Magee <rmagee@gmail.com>
This commit is contained in:
Russ Magee 2019-04-08 21:58:33 -07:00
parent a53ec4ac2d
commit f09d6bbfef
5 changed files with 213 additions and 14 deletions

View file

@ -10,4 +10,4 @@ package hkexsh
// common constants for the HKExSh // common constants for the HKExSh
// Version string returned by tools // Version string returned by tools
const Version = "0.8.0 (NO WARRANTY)" const Version = "0.8.1 (NO WARRANTY)"

View file

@ -20,8 +20,8 @@ const (
KEX_KYBER768 KEX_KYBER768
KEX_KYBER1024 KEX_KYBER1024
KEX_resvd11 KEX_resvd11
KEX_resvd12 KEX_NEWHOPE
KEX_resvd13 KEX_NEWHOPE_SIMPLE // 'NewHopeLP-Simple' - https://eprint.iacr.org/2016/1157
KEX_resvd14 KEX_resvd14
KEX_resvd15 KEX_resvd15
) )

View file

@ -49,6 +49,7 @@ import (
"blitter.com/go/herradurakex" "blitter.com/go/herradurakex"
"blitter.com/go/hkexsh/logger" "blitter.com/go/hkexsh/logger"
kyber "git.schwanenlied.me/yawning/kyber.git" kyber "git.schwanenlied.me/yawning/kyber.git"
newhope "git.schwanenlied.me/yawning/newhope.git"
) )
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
@ -197,6 +198,12 @@ func getkexalgnum(extensions ...string) (k KEXAlg) {
case "KEX_KYBER1024": case "KEX_KYBER1024":
k = KEX_KYBER1024 k = KEX_KYBER1024
break //out of for break //out of for
case "KEX_NEWHOPE":
k = KEX_NEWHOPE
break //out of for
case "KEX_NEWHOPE_SIMPLE":
k = KEX_NEWHOPE_SIMPLE
break //out of for
} }
} }
return return
@ -227,12 +234,16 @@ func _new(kexAlg KEXAlg, conn *net.Conn) (hc *Conn, e error) {
case KEX_HERRADURA1024: case KEX_HERRADURA1024:
fallthrough fallthrough
case KEX_HERRADURA2048: case KEX_HERRADURA2048:
log.Printf("[KEx alg %d accepted]\n", kexAlg) fallthrough
case KEX_KYBER512: case KEX_KYBER512:
fallthrough fallthrough
case KEX_KYBER768: case KEX_KYBER768:
fallthrough fallthrough
case KEX_KYBER1024: case KEX_KYBER1024:
fallthrough
case KEX_NEWHOPE:
fallthrough
case KEX_NEWHOPE_SIMPLE:
log.Printf("[KEx alg %d accepted]\n", kexAlg) log.Printf("[KEx alg %d accepted]\n", kexAlg)
default: default:
// UNREACHABLE: _getkexalgnum() guarantees a valid KEX value // UNREACHABLE: _getkexalgnum() guarantees a valid KEX value
@ -276,7 +287,7 @@ func (hc *Conn) applyConnExtensions(extensions ...string) {
} }
// randReader wraps rand.Read() in a struct that implements io.Reader // randReader wraps rand.Read() in a struct that implements io.Reader
// for use by the Kyber KEM methods. // for use by the Kyber and NEWHOPE/NEWHOPE_SIMPLE KEM methods.
type randReader struct { type randReader struct {
} }
@ -285,11 +296,101 @@ func (r randReader) Read(b []byte) (n int, e error) {
return return
} }
func NewHopeDialSetup(c io.ReadWriter, hc *Conn) (err error) {
// Send hkexnet.Conn parameters to remote side
// Alice, step 1: Generate a key pair.
r := new(randReader)
rand.Seed(time.Now().UnixNano())
privKeyAlice, pubKeyAlice, err := newhope.GenerateKeyPairAlice(r)
if err != nil {
panic(err)
}
// Alice, step 2: Send the public key to Bob
fmt.Fprintf(c, "0x%x\n0x%x:0x%x\n", pubKeyAlice.Send,
hc.cipheropts, hc.opts)
// [Bob does step 1-3], from which we read Bob's pubkey
publicKeyBob := big.NewInt(0)
fmt.Fscanf(c, "0x%x\n", publicKeyBob)
var pubKeyBob newhope.PublicKeyBob
for i := range(pubKeyBob.Send) {
pubKeyBob.Send[i] = publicKeyBob.Bytes()[i]
}
log.Printf("[Got server pubKey[]:%v]\n", pubKeyBob)
// Read cipheropts, session opts
_, err = fmt.Fscanf(c, "0x%x:0x%x\n",
&hc.cipheropts, &hc.opts)
if err != nil {
return err
}
// Alice, step 3: Derive shared secret
// (NOTE: actual over-wire exchange was already done above. This is
// the math voodoo 'exchange' done after receiving data from Bob.)
aliceSharedSecret, err := newhope.KeyExchangeAlice(&pubKeyBob, privKeyAlice)
if err != nil {
panic(err)
}
log.Printf("[Derived sharedSecret:0x%x]\n", aliceSharedSecret)
hc.r, hc.rm, err = hc.getStream(aliceSharedSecret)
hc.w, hc.wm, err = hc.getStream(aliceSharedSecret)
return
}
func NewHopeSimpleDialSetup(c io.ReadWriter, hc *Conn) (err error) {
// Send hkexnet.Conn parameters to remote side
// Alice, step 1: Generate a key pair.
r := new(randReader)
rand.Seed(time.Now().UnixNano())
privKeyAlice, pubKeyAlice, err := newhope.GenerateKeyPairSimpleAlice(r)
if err != nil {
panic(err)
}
// Alice, step 2: Send the public key to Bob
fmt.Fprintf(c, "0x%x\n0x%x:0x%x\n", pubKeyAlice.Send,
hc.cipheropts, hc.opts)
// [Bob does step 1-3], from which we read Bob's pubkey
publicKeyBob := big.NewInt(0)
fmt.Fscanf(c, "0x%x\n", publicKeyBob)
var pubKeyBob newhope.PublicKeySimpleBob
for i := range(pubKeyBob.Send) {
pubKeyBob.Send[i] = publicKeyBob.Bytes()[i]
}
log.Printf("[Got server pubKey[]:%v]\n", pubKeyBob)
// Read cipheropts, session opts
_, err = fmt.Fscanf(c, "0x%x:0x%x\n",
&hc.cipheropts, &hc.opts)
if err != nil {
return err
}
// Alice, step 3: Derive shared secret
// (NOTE: actual over-wire exchange was already done above. This is
// the math voodoo 'exchange' done after receiving data from Bob.)
aliceSharedSecret, err := newhope.KeyExchangeSimpleAlice(&pubKeyBob, privKeyAlice)
if err != nil {
panic(err)
}
log.Printf("[Derived sharedSecret:0x%x]\n", aliceSharedSecret)
hc.r, hc.rm, err = hc.getStream(aliceSharedSecret)
hc.w, hc.wm, err = hc.getStream(aliceSharedSecret)
return
}
func KyberDialSetup(c io.ReadWriter /*net.Conn*/, hc *Conn) (err error) { func KyberDialSetup(c io.ReadWriter /*net.Conn*/, hc *Conn) (err error) {
// Send hkexnet.Conn parameters to remote side // Send hkexnet.Conn parameters to remote side
// Alice, step 1: Generate a key pair. // Alice, step 1: Generate a key pair.
r := new(randReader) r := new(randReader)
rand.Seed(time.Now().UnixNano())
var alicePublicKey *kyber.PublicKey var alicePublicKey *kyber.PublicKey
var alicePrivateKey *kyber.PrivateKey var alicePrivateKey *kyber.PrivateKey
switch hc.kex { switch hc.kex {
@ -312,12 +413,12 @@ func KyberDialSetup(c io.ReadWriter /*net.Conn*/, hc *Conn) (err error) {
hc.cipheropts, hc.opts) hc.cipheropts, hc.opts)
// [Bob, step 1-3], from which we read cipher text // [Bob, step 1-3], from which we read cipher text
cipherB := make([]byte, 4096) pubKeyB := make([]byte, 4096)
fmt.Fscanf(c, "0x%x\n", &cipherB) fmt.Fscanf(c, "0x%x\n", &pubKeyB)
//if err != nil { //if err != nil {
// return err // return err
//} //}
log.Printf("[Got server ciphertext[]:%v]\n", cipherB) log.Printf("[Got server pubKeyB[]:%v]\n", pubKeyB)
// Read cipheropts, session opts // Read cipheropts, session opts
_, err = fmt.Fscanf(c, "0x%x:0x%x\n", _, err = fmt.Fscanf(c, "0x%x:0x%x\n",
@ -327,7 +428,7 @@ func KyberDialSetup(c io.ReadWriter /*net.Conn*/, hc *Conn) (err error) {
} }
// Alice, step 3: Decrypt the KEM cipher text. // Alice, step 3: Decrypt the KEM cipher text.
aliceSharedSecret := alicePrivateKey.KEMDecrypt(cipherB) aliceSharedSecret := alicePrivateKey.KEMDecrypt(pubKeyB)
log.Printf("[Derived sharedSecret:0x%x]\n", aliceSharedSecret) log.Printf("[Derived sharedSecret:0x%x]\n", aliceSharedSecret)
hc.r, hc.rm, err = hc.getStream(aliceSharedSecret) hc.r, hc.rm, err = hc.getStream(aliceSharedSecret)
@ -378,6 +479,84 @@ func HKExDialSetup(c io.ReadWriter /*net.Conn*/, hc *Conn) (err error) {
return return
} }
func NewHopeAcceptSetup(c *net.Conn, hc *Conn) (err error) {
r := new(randReader)
rand.Seed(time.Now().UnixNano())
// Bob, step 1: Deserialize Alice's public key from the binary encoding.
alicePublicKey := big.NewInt(0)
_, err = fmt.Fscanln(*c, alicePublicKey)
log.Printf("[Got client pubKey:0x%x\n]", alicePublicKey)
if err != nil {
return err
}
var pubKeyAlice newhope.PublicKeyAlice
for i := range(pubKeyAlice.Send) {
pubKeyAlice.Send[i] = alicePublicKey.Bytes()[i]
}
_, err = fmt.Fscanf(*c, "0x%x:0x%x\n",
&hc.cipheropts, &hc.opts)
log.Printf("[Got cipheropts, opts:%v, %v]", hc.cipheropts, hc.opts)
if err != nil {
return err
}
// Bob, step 2: Generate the KEM cipher text and shared secret.
pubKeyBob, bobSharedSecret, err := newhope.KeyExchangeBob(r, &pubKeyAlice)
if err != nil {
panic(err)
}
// Bob, step 3: Send the cipher text to Alice.
fmt.Fprintf(*c, "0x%x\n0x%x:0x%x\n", pubKeyBob.Send,
hc.cipheropts, hc.opts)
log.Printf("[Derived sharedSecret:0x%x]\n", bobSharedSecret)
hc.r, hc.rm, err = hc.getStream(bobSharedSecret)
hc.w, hc.wm, err = hc.getStream(bobSharedSecret)
return
}
func NewHopeSimpleAcceptSetup(c *net.Conn, hc *Conn) (err error) {
r := new(randReader)
rand.Seed(time.Now().UnixNano())
// Bob, step 1: Deserialize Alice's public key from the binary encoding.
alicePublicKey := big.NewInt(0)
_, err = fmt.Fscanln(*c, alicePublicKey)
log.Printf("[Got client pubKey:0x%x\n]", alicePublicKey)
if err != nil {
return err
}
var pubKeyAlice newhope.PublicKeySimpleAlice
for i := range(pubKeyAlice.Send) {
pubKeyAlice.Send[i] = alicePublicKey.Bytes()[i]
}
_, err = fmt.Fscanf(*c, "0x%x:0x%x\n",
&hc.cipheropts, &hc.opts)
log.Printf("[Got cipheropts, opts:%v, %v]", hc.cipheropts, hc.opts)
if err != nil {
return err
}
// Bob, step 2: Generate the KEM cipher text and shared secret.
pubKeyBob, bobSharedSecret, err := newhope.KeyExchangeSimpleBob(r, &pubKeyAlice)
if err != nil {
panic(err)
}
// Bob, step 3: Send the cipher text to Alice.
fmt.Fprintf(*c, "0x%x\n0x%x:0x%x\n", pubKeyBob.Send,
hc.cipheropts, hc.opts)
log.Printf("[Derived sharedSecret:0x%x]\n", bobSharedSecret)
hc.r, hc.rm, err = hc.getStream(bobSharedSecret)
hc.w, hc.wm, err = hc.getStream(bobSharedSecret)
return
}
func KyberAcceptSetup(c *net.Conn, hc *Conn) (err error) { func KyberAcceptSetup(c *net.Conn, hc *Conn) (err error) {
// Bob, step 1: Deserialize Alice's public key from the binary encoding. // Bob, step 1: Deserialize Alice's public key from the binary encoding.
alicePublicKey := big.NewInt(0) alicePublicKey := big.NewInt(0)
@ -411,13 +590,13 @@ func KyberAcceptSetup(c *net.Conn, hc *Conn) (err error) {
// Bob, step 2: Generate the KEM cipher text and shared secret. // Bob, step 2: Generate the KEM cipher text and shared secret.
r := new(randReader) r := new(randReader)
rand.Seed(time.Now().UnixNano())
cipherText, bobSharedSecret, err := peerPublicKey.KEMEncrypt(r) cipherText, bobSharedSecret, err := peerPublicKey.KEMEncrypt(r)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// Bob, step 3: Send the cipher text to Alice. // Bob, step 3: Send the cipher text to Alice.
//fmt.Println("cipherText:",cipherText)
fmt.Fprintf(*c, "0x%x\n0x%x:0x%x\n", cipherText, fmt.Fprintf(*c, "0x%x\n0x%x:0x%x\n", cipherText,
hc.cipheropts, hc.opts) hc.cipheropts, hc.opts)
@ -525,6 +704,16 @@ func Dial(protocol string, ipport string, extensions ...string) (hc Conn, err er
if KyberDialSetup(c, &hc) != nil { if KyberDialSetup(c, &hc) != nil {
return Conn{}, nil return Conn{}, nil
} }
case KEX_NEWHOPE:
log.Printf("[Setting up for KEX_NEWHOPE %d]\n", hc.kex)
if NewHopeDialSetup(c, &hc) != nil {
return Conn{}, nil
}
case KEX_NEWHOPE_SIMPLE:
log.Printf("[Setting up for KEX_NEWHOPE_SIMPLE %d]\n", hc.kex)
if NewHopeSimpleDialSetup(c, &hc) != nil {
return Conn{}, nil
}
default: default:
return Conn{}, err return Conn{}, err
} }
@ -686,6 +875,16 @@ func (hl *HKExListener) Accept() (hc Conn, err error) {
if KyberAcceptSetup(&c, &hc) != nil { if KyberAcceptSetup(&c, &hc) != nil {
return Conn{}, err return Conn{}, err
} }
case KEX_NEWHOPE:
log.Printf("[Setting up for KEX_NEWHOPE %d]\n", hc.kex)
if NewHopeAcceptSetup(&c, &hc) != nil {
return Conn{}, err
}
case KEX_NEWHOPE_SIMPLE:
log.Printf("[Setting up for KEX_NEWHOPE_SIMPLE %d]\n", hc.kex)
if NewHopeSimpleAcceptSetup(&c, &hc) != nil {
return Conn{}, err
}
default: default:
return Conn{}, err return Conn{}, err
} }

View file

@ -623,11 +623,11 @@ func main() {
flag.BoolVar(&vopt, "v", false, "show version") flag.BoolVar(&vopt, "v", false, "show version")
flag.BoolVar(&dbg, "d", false, "debug logging") flag.BoolVar(&dbg, "d", false, "debug logging")
flag.StringVar(&cipherAlg, "c", "C_AES_256", "`cipher` [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\" | \"C_CRYPTMT1\"]") flag.StringVar(&cipherAlg, "c", "C_AES_256", "`cipher` [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\" | \"C_CRYPTMT1\"]")
flag.StringVar(&hmacAlg, "m", "H_SHA256", "`hmac` [\"H_SHA256\"]") flag.StringVar(&hmacAlg, "m", "H_SHA256", "`hmac` [\"H_SHA256\" | \"H_SHA512\"]")
flag.StringVar(&kexAlg, "k", "KEX_HERRADURA256", "`kex` [\"KEX_HERRADURA{256/512/1024/2048}\" | \"KEX_KYBER{512/768/1024}\"]") flag.StringVar(&kexAlg, "k", "KEX_HERRADURA256", "`kex` [\"KEX_HERRADURA{256/512/1024/2048}\" | \"KEX_KYBER{512/768/1024}\" | \"KEX_NEWHOPE\" | \"KEX_NEWHOPE_SIMPLE\"]")
flag.UintVar(&port, "p", 2000, "`port`") flag.UintVar(&port, "p", 2000, "`port`")
//flag.StringVar(&authCookie, "a", "", "auth cookie") //flag.StringVar(&authCookie, "a", "", "auth cookie")
flag.BoolVar(&chaffEnabled, "e", true, "enabled chaff pkts (default true)") flag.BoolVar(&chaffEnabled, "e", true, "enable chaff pkts")
flag.UintVar(&chaffFreqMin, "f", 100, "`msecs-min` chaff pkt freq min (msecs)") flag.UintVar(&chaffFreqMin, "f", 100, "`msecs-min` chaff pkt freq min (msecs)")
flag.UintVar(&chaffFreqMax, "F", 5000, "`msecs-max` chaff pkt freq max (msecs)") flag.UintVar(&chaffFreqMax, "F", 5000, "`msecs-max` chaff pkt freq max (msecs)")
flag.UintVar(&chaffBytesMax, "B", 64, "chaff pkt size max (bytes)") flag.UintVar(&chaffBytesMax, "B", 64, "chaff pkt size max (bytes)")

View file

@ -387,7 +387,7 @@ func main() {
flag.BoolVar(&vopt, "v", false, "show version") flag.BoolVar(&vopt, "v", false, "show version")
flag.StringVar(&laddr, "l", ":2000", "interface[:port] to listen") flag.StringVar(&laddr, "l", ":2000", "interface[:port] to listen")
flag.BoolVar(&chaffEnabled, "e", true, "enabled chaff pkts") flag.BoolVar(&chaffEnabled, "e", true, "enable chaff pkts")
flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min (msecs)") flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min (msecs)")
flag.UintVar(&chaffFreqMax, "F", 5000, "chaff pkt freq max (msecs)") flag.UintVar(&chaffFreqMax, "F", 5000, "chaff pkt freq max (msecs)")
flag.UintVar(&chaffBytesMax, "B", 64, "chaff pkt size max (bytes)") flag.UintVar(&chaffBytesMax, "B", 64, "chaff pkt size max (bytes)")