noise/vector_test.go

199 lines
4.6 KiB
Go
Raw Normal View History

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() {
for _, h := range []HandshakePattern{HandshakeNN, HandshakeKN, HandshakeNK, HandshakeKK, HandshakeNE, HandshakeKE, HandshakeNX, HandshakeKX, HandshakeXN, HandshakeIN, HandshakeXK, HandshakeIK, HandshakeXE, HandshakeIE, HandshakeXX, HandshakeIX, HandshakeN, HandshakeK, HandshakeX} {
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
case 'E':
k.rs = true
k.rsi = true
k.e = true
case 'X':
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
var payload []byte
for {
line, _, err := r.ReadLine()
if err == io.EOF {
break
}
c.Assert(err, IsNil)
if len(bytes.TrimSpace(line)) == 0 {
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":
c.Log(string(splitLine[1]))
configI, configR = Config{Initiator: true}, Config{}
hsI, hsR = nil, nil
components := strings.SplitN(string(splitLine[1]), "_", 5)
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":
configI.PresharedKey = mustHex(splitLine[1])
configR.PresharedKey = configI.PresharedKey
}
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
}
hsI, hsR = NewHandshakeState(configI), NewHandshakeState(configR)
}
i, _ := strconv.Atoi(string(splitLine[0][4:5]))
writer, reader := hsI, hsR
if i%2 != 0 {
writer, reader = hsR, hsI
}
msg, csW0, csW1 := writer.WriteMessage(nil, payload)
c.Assert(fmt.Sprintf("%x", msg), Equals, string(splitLine[1]))
res, csR0, csR1, err := reader.ReadMessage(nil, msg)
c.Assert(err, IsNil)
c.Assert(string(res), Equals, string(payload))
if i == len(configI.Pattern.Messages) {
plain := []byte("yellowsubmarine")
encrypted := csW0.Encrypt(nil, nil, plain)
decrypted, err := csR0.Decrypt(nil, nil, encrypted)
c.Assert(err, IsNil)
c.Assert(string(decrypted), Equals, string(plain))
encrypted = csW1.Encrypt(nil, nil, plain)
decrypted, err = csR1.Decrypt(nil, nil, encrypted)
c.Assert(err, IsNil)
c.Assert(string(decrypted), Equals, string(plain))
}
payload = nil
}
}