mirror of
https://github.com/logos-messaging/noise.git
synced 2026-01-04 23:23:13 +00:00
Add test vector generator and tester
This commit is contained in:
parent
4db302538c
commit
3881dc9640
@ -40,7 +40,7 @@ var HandshakeNE = HandshakePattern{
|
||||
Name: "NE",
|
||||
ResponderPreMessages: []MessagePattern{MessagePatternS, MessagePatternE},
|
||||
Messages: [][]MessagePattern{
|
||||
{MessagePatternE, MessagePatternDHEE, MessagePatternDHSE},
|
||||
{MessagePatternE, MessagePatternDHEE, MessagePatternDHES},
|
||||
{MessagePatternE, MessagePatternDHEE},
|
||||
},
|
||||
}
|
||||
|
||||
198
vector_test.go
Normal file
198
vector_test.go
Normal file
@ -0,0 +1,198 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
147
vectorgen/vectorgen.go
Normal file
147
vectorgen/vectorgen.go
Normal file
@ -0,0 +1,147 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
. "github.com/titanous/noise"
|
||||
)
|
||||
|
||||
func main() {
|
||||
for ci, cipher := range []CipherFunc{CipherAESGCM, CipherChaChaPoly} {
|
||||
for _, hash := range []HashFunc{HashSHA256, HashSHA512, HashBLAKE2b, HashBLAKE2s} {
|
||||
for hi, handshake := range []HandshakePattern{HandshakeNN, HandshakeKN, HandshakeNK, HandshakeKK, HandshakeNE, HandshakeKE, HandshakeNX, HandshakeKX, HandshakeXN, HandshakeIN, HandshakeXK, HandshakeIK, HandshakeXE, HandshakeIE, HandshakeXX, HandshakeIX, HandshakeN, HandshakeK, HandshakeX} {
|
||||
for _, psk := range []bool{false, true} {
|
||||
payloads := (psk && hi%2 == 0) || (!psk && hi%2 != 0)
|
||||
prologue := ci == 0
|
||||
writeHandshake(os.Stdout, NewCipherSuite(DH25519, cipher, hash), handshake, psk, prologue, payloads)
|
||||
fmt.Fprintln(os.Stdout)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hexReader(s string) io.Reader {
|
||||
res, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bytes.NewBuffer(res)
|
||||
}
|
||||
|
||||
const (
|
||||
key0 = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
key1 = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"
|
||||
key2 = "2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40"
|
||||
key3 = "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
|
||||
key4 = "4142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60"
|
||||
)
|
||||
|
||||
func writeHandshake(out io.Writer, cs CipherSuite, h HandshakePattern, hasPSK, hasPrologue, payloads bool) {
|
||||
var prologue, psk []byte
|
||||
if hasPrologue {
|
||||
prologue = []byte("notsecret")
|
||||
}
|
||||
if hasPSK {
|
||||
psk = []byte("verysecret")
|
||||
}
|
||||
|
||||
staticI := cs.GenerateKeypair(hexReader(key0))
|
||||
staticR := cs.GenerateKeypair(hexReader(key1))
|
||||
ephR := cs.GenerateKeypair(hexReader(key2))
|
||||
|
||||
configI := Config{
|
||||
CipherSuite: cs,
|
||||
Random: hexReader(key3),
|
||||
Pattern: h,
|
||||
Initiator: true,
|
||||
Prologue: prologue,
|
||||
PresharedKey: psk,
|
||||
}
|
||||
configR := configI
|
||||
configR.Random = hexReader(key4)
|
||||
configR.Initiator = false
|
||||
|
||||
var pskName string
|
||||
if hasPSK {
|
||||
pskName = "PSK"
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "handshake=Noise%s_%s_%s\n", pskName, h.Name, cs.Name())
|
||||
|
||||
if len(h.Name) == 1 {
|
||||
switch h.Name {
|
||||
case "N":
|
||||
configR.StaticKeypair = staticR
|
||||
configI.PeerStatic = staticR.Public
|
||||
fmt.Fprintf(out, "resp_static=%x\n", staticR.Private)
|
||||
case "K":
|
||||
configI.StaticKeypair = staticI
|
||||
configR.PeerStatic = staticI.Public
|
||||
configR.StaticKeypair = staticR
|
||||
configI.PeerStatic = staticR.Public
|
||||
fmt.Fprintf(out, "init_static=%x\n", staticI.Private)
|
||||
fmt.Fprintf(out, "resp_static=%x\n", staticR.Private)
|
||||
case "X":
|
||||
configI.StaticKeypair = staticI
|
||||
configR.StaticKeypair = staticR
|
||||
configI.PeerStatic = staticR.Public
|
||||
fmt.Fprintf(out, "init_static=%x\n", staticI.Private)
|
||||
fmt.Fprintf(out, "resp_static=%x\n", staticR.Private)
|
||||
}
|
||||
} else {
|
||||
switch h.Name[0] {
|
||||
case 'K', 'X', 'I':
|
||||
configI.StaticKeypair = staticI
|
||||
if h.Name[0] == 'K' {
|
||||
configR.PeerStatic = staticI.Public
|
||||
}
|
||||
fmt.Fprintf(out, "init_static=%x\n", staticI.Private)
|
||||
}
|
||||
switch h.Name[1] {
|
||||
case 'K', 'E', 'X':
|
||||
configR.StaticKeypair = staticR
|
||||
fmt.Fprintf(out, "resp_static=%x\n", staticR.Private)
|
||||
switch h.Name[1] {
|
||||
case 'K':
|
||||
configI.PeerStatic = staticR.Public
|
||||
case 'E':
|
||||
configR.EphemeralKeypair = ephR
|
||||
configI.PeerEphemeral = ephR.Public
|
||||
configI.PeerStatic = staticR.Public
|
||||
fmt.Fprintf(out, "resp_ephemeral=%x\n", ephR.Private)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "gen_init_ephemeral=%s\n", key3)
|
||||
fmt.Fprintf(out, "gen_resp_ephemeral=%s\n", key4)
|
||||
fmt.Fprintf(out, "prologue=%x\n", prologue)
|
||||
fmt.Fprintf(out, "preshared_key=%x\n", psk)
|
||||
|
||||
hsI := NewHandshakeState(configI)
|
||||
hsR := NewHandshakeState(configR)
|
||||
|
||||
for i := range h.Messages {
|
||||
writer, reader := hsI, hsR
|
||||
if i%2 != 0 {
|
||||
writer, reader = hsR, hsI
|
||||
}
|
||||
|
||||
var payload string
|
||||
if payloads {
|
||||
payload = fmt.Sprintf("test_msg_%d", i)
|
||||
}
|
||||
msg, _, _ := writer.WriteMessage(nil, []byte(payload))
|
||||
_, _, _, err := reader.ReadMessage(nil, msg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Fprintf(out, "msg_%d_payload=%x\n", i, payload)
|
||||
fmt.Fprintf(out, "msg_%d_ciphertext=%x\n", i, msg)
|
||||
}
|
||||
}
|
||||
3600
vectors.txt
Normal file
3600
vectors.txt
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user