2015-11-17 01:57:02 +00:00
|
|
|
package noise
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"bytes"
|
|
|
|
"encoding/hex"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
. "gopkg.in/check.v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
func mustHex(s []byte) []byte {
|
|
|
|
res, err := hex.DecodeString(string(s))
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
func hexReader(s []byte) io.Reader {
|
|
|
|
return bytes.NewBuffer(mustHex(s))
|
|
|
|
}
|
|
|
|
|
|
|
|
var patterns = make(map[string]HandshakePattern)
|
|
|
|
var ciphers = map[string]CipherFunc{
|
|
|
|
"AESGCM": CipherAESGCM,
|
|
|
|
"ChaChaPoly": CipherChaChaPoly,
|
|
|
|
}
|
|
|
|
var hashes = map[string]HashFunc{
|
|
|
|
"SHA256": HashSHA256,
|
|
|
|
"SHA512": HashSHA512,
|
|
|
|
"BLAKE2b": HashBLAKE2b,
|
|
|
|
"BLAKE2s": HashBLAKE2s,
|
|
|
|
}
|
|
|
|
|
|
|
|
var patternKeys = make(map[string]patternKeyInfo)
|
|
|
|
|
|
|
|
type patternKeyInfo struct {
|
|
|
|
is, rs, isr, rsi, e bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
2016-04-03 15:35:23 +00:00
|
|
|
for _, h := range []HandshakePattern{HandshakeNN, HandshakeKN, HandshakeNK, HandshakeKK, HandshakeNX, HandshakeKX, HandshakeXN, HandshakeIN, HandshakeXK, HandshakeIK, HandshakeXX, HandshakeXR, HandshakeIX, HandshakeN, HandshakeK, HandshakeX} {
|
2015-11-17 01:57:02 +00:00
|
|
|
patterns[h.Name] = h
|
|
|
|
var k patternKeyInfo
|
|
|
|
if len(h.Name) == 1 {
|
|
|
|
switch h.Name {
|
|
|
|
case "N":
|
|
|
|
k.rs = true
|
|
|
|
k.rsi = true
|
|
|
|
case "K":
|
|
|
|
k.is = true
|
|
|
|
k.isr = true
|
|
|
|
k.rs = true
|
|
|
|
k.rsi = true
|
|
|
|
case "X":
|
|
|
|
k.is = true
|
|
|
|
k.rs = true
|
|
|
|
k.rsi = true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch h.Name[0] {
|
|
|
|
case 'X', 'I':
|
|
|
|
k.is = true
|
|
|
|
case 'K':
|
|
|
|
k.is = true
|
|
|
|
k.isr = true
|
|
|
|
}
|
|
|
|
switch h.Name[1] {
|
|
|
|
case 'K':
|
|
|
|
k.rs = true
|
|
|
|
k.rsi = true
|
2016-04-03 15:35:23 +00:00
|
|
|
case 'X', 'R':
|
2015-11-17 01:57:02 +00:00
|
|
|
k.rs = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
patternKeys[h.Name] = k
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (NoiseSuite) TestVectors(c *C) {
|
|
|
|
f, err := os.Open("vectors.txt")
|
|
|
|
c.Assert(err, IsNil)
|
|
|
|
r := bufio.NewReader(f)
|
|
|
|
|
|
|
|
var hsI, hsR *HandshakeState
|
|
|
|
var staticR, staticI, ephR DHKey
|
|
|
|
var configI, configR Config
|
|
|
|
var keyInfo patternKeyInfo
|
2015-11-17 03:08:16 +00:00
|
|
|
var name string
|
|
|
|
var payload, psk []byte
|
|
|
|
var csW0, csW1, csR0, csR1 *CipherState
|
2015-11-17 01:57:02 +00:00
|
|
|
|
|
|
|
for {
|
|
|
|
line, _, err := r.ReadLine()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
c.Assert(err, IsNil)
|
|
|
|
|
2015-11-17 03:08:16 +00:00
|
|
|
if len(bytes.TrimSpace(line)) == 0 || line[0] == '#' {
|
2015-11-17 01:57:02 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
splitLine := bytes.SplitN(line, []byte("="), 2)
|
|
|
|
c.Assert(splitLine, HasLen, 2)
|
|
|
|
|
|
|
|
switch string(splitLine[0]) {
|
|
|
|
case "init_static":
|
|
|
|
staticI = DH25519.GenerateKeypair(hexReader(splitLine[1]))
|
|
|
|
case "resp_static":
|
|
|
|
staticR = DH25519.GenerateKeypair(hexReader(splitLine[1]))
|
|
|
|
case "resp_ephemeral":
|
|
|
|
ephR = DH25519.GenerateKeypair(hexReader(splitLine[1]))
|
|
|
|
case "handshake":
|
2015-11-17 03:08:16 +00:00
|
|
|
name = string(splitLine[1])
|
|
|
|
c.Log(name)
|
2015-11-17 01:57:02 +00:00
|
|
|
configI, configR = Config{Initiator: true}, Config{}
|
|
|
|
hsI, hsR = nil, nil
|
2015-11-17 03:08:16 +00:00
|
|
|
components := strings.SplitN(name, "_", 5)
|
2015-11-17 01:57:02 +00:00
|
|
|
keyInfo = patternKeys[components[1]]
|
|
|
|
configI.Pattern = patterns[components[1]]
|
|
|
|
configI.CipherSuite = NewCipherSuite(DH25519, ciphers[components[3]], hashes[components[4]])
|
|
|
|
configR.Pattern = configI.Pattern
|
|
|
|
configR.CipherSuite = configI.CipherSuite
|
|
|
|
case "gen_init_ephemeral":
|
|
|
|
configI.Random = hexReader(splitLine[1])
|
|
|
|
case "gen_resp_ephemeral":
|
|
|
|
configR.Random = hexReader(splitLine[1])
|
|
|
|
case "prologue":
|
|
|
|
configI.Prologue = mustHex(splitLine[1])
|
|
|
|
configR.Prologue = configI.Prologue
|
|
|
|
case "preshared_key":
|
2015-11-17 03:08:16 +00:00
|
|
|
psk = mustHex(splitLine[1])
|
2015-11-17 01:57:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !bytes.HasPrefix(splitLine[0], []byte("msg_")) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if bytes.HasSuffix(splitLine[0], []byte("_payload")) {
|
|
|
|
payload = mustHex(splitLine[1])
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if hsI == nil {
|
|
|
|
if keyInfo.is {
|
|
|
|
configI.StaticKeypair = staticI
|
|
|
|
}
|
|
|
|
if keyInfo.rs {
|
|
|
|
configR.StaticKeypair = staticR
|
|
|
|
}
|
|
|
|
if keyInfo.isr {
|
|
|
|
configR.PeerStatic = staticI.Public
|
|
|
|
}
|
|
|
|
if keyInfo.rsi {
|
|
|
|
configI.PeerStatic = staticR.Public
|
|
|
|
}
|
|
|
|
if keyInfo.e {
|
|
|
|
configR.EphemeralKeypair = ephR
|
|
|
|
configI.PeerEphemeral = ephR.Public
|
|
|
|
}
|
2015-11-17 03:08:16 +00:00
|
|
|
if strings.HasPrefix(name, "NoisePSK_") {
|
|
|
|
configI.PresharedKey = psk
|
|
|
|
configR.PresharedKey = psk
|
|
|
|
}
|
2015-11-17 01:57:02 +00:00
|
|
|
hsI, hsR = NewHandshakeState(configI), NewHandshakeState(configR)
|
|
|
|
}
|
|
|
|
|
|
|
|
i, _ := strconv.Atoi(string(splitLine[0][4:5]))
|
|
|
|
|
2015-11-17 03:08:16 +00:00
|
|
|
if i > len(configI.Pattern.Messages)-1 {
|
|
|
|
enc, dec := csW0, csR0
|
|
|
|
if (i-len(configI.Pattern.Messages))%2 != 0 {
|
|
|
|
enc, dec = csW1, csR1
|
|
|
|
}
|
|
|
|
encrypted := enc.Encrypt(nil, nil, payload)
|
|
|
|
c.Assert(fmt.Sprintf("%x", encrypted), Equals, string(splitLine[1]))
|
|
|
|
decrypted, err := dec.Decrypt(nil, nil, encrypted)
|
|
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(string(payload), Equals, string(decrypted))
|
|
|
|
payload = nil
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2015-11-17 01:57:02 +00:00
|
|
|
writer, reader := hsI, hsR
|
|
|
|
if i%2 != 0 {
|
|
|
|
writer, reader = hsR, hsI
|
|
|
|
}
|
|
|
|
|
2015-11-17 03:08:16 +00:00
|
|
|
var msg, res []byte
|
|
|
|
msg, csW0, csW1 = writer.WriteMessage(nil, payload)
|
2015-11-17 01:57:02 +00:00
|
|
|
c.Assert(fmt.Sprintf("%x", msg), Equals, string(splitLine[1]))
|
2015-11-17 03:08:16 +00:00
|
|
|
res, csR0, csR1, err = reader.ReadMessage(nil, msg)
|
2015-11-17 01:57:02 +00:00
|
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(string(res), Equals, string(payload))
|
|
|
|
payload = nil
|
|
|
|
}
|
|
|
|
}
|