Fix readme typo.
[champa.git] / noise / noise.go
blob49c76d8e24f69f028b43896305bda2e084814921
1 // Package noise provides a net.Conn-like interface for a
2 // Noise_NK_25519_ChaChaPoly_BLAKE2s. It encodes Noise messages onto a reliable
3 // stream using 16-bit length prefixes.
4 //
5 // https://noiseprotocol.org/noise.html
6 package noise
8 import (
9 "bufio"
10 "crypto/rand"
11 "encoding/hex"
12 "fmt"
13 "io"
14 "net"
15 "strings"
17 "github.com/flynn/noise"
18 "golang.org/x/crypto/curve25519"
21 // The length of public and private keys as returned by GeneratePrivkey.
22 const KeyLen = 32
24 const (
25 MsgTypeHandshakeInit = 1
26 MsgTypeHandshakeResp = 2
27 MsgTypeTransport = 4
30 // cipherSuite represents 25519_ChaChaPoly_BLAKE2s.
31 var cipherSuite = noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashBLAKE2s)
33 func ReadMessageFrom(conn net.PacketConn) (byte, []byte, net.Addr, error) {
34 var buf [1500]byte
35 for {
36 n, addr, err := conn.ReadFrom(buf[:])
37 if err != nil {
38 return 0, nil, nil, err
40 if n >= 1 {
41 return buf[0], buf[1:n], addr, nil
46 // newConfig instantiates configuration settings that are common to clients and
47 // servers.
48 func newConfig() noise.Config {
49 return noise.Config{
50 CipherSuite: cipherSuite,
51 Pattern: noise.HandshakeNK,
52 Prologue: []byte("Champa 2021-06-17"),
56 // GeneratePrivkey generates a private key. The corresponding private key can be
57 // generated using PubkeyFromPrivkey.
58 func GeneratePrivkey() ([]byte, error) {
59 pair, err := noise.DH25519.GenerateKeypair(rand.Reader)
60 return pair.Private, err
63 // PubkeyFromPrivkey returns the public key that corresponds to privkey.
64 func PubkeyFromPrivkey(privkey []byte) []byte {
65 pubkey, err := curve25519.X25519(privkey, curve25519.Basepoint)
66 if err != nil {
67 panic(err)
69 return pubkey
72 // ReadKey reads a hex-encoded key from r. r must consist of a single line, with
73 // or without a '\n' line terminator. The line must consist of KeyLen
74 // hex-encoded bytes.
75 func ReadKey(r io.Reader) ([]byte, error) {
76 br := bufio.NewReader(io.LimitReader(r, 100))
77 line, err := br.ReadString('\n')
78 if err == io.EOF {
79 err = nil
81 if err == nil {
82 // Check that we're at EOF.
83 _, err = br.ReadByte()
84 if err == io.EOF {
85 err = nil
86 } else if err == nil {
87 err = fmt.Errorf("file contains more than one line")
90 if err != nil {
91 return nil, err
93 line = strings.TrimSuffix(line, "\n")
94 return DecodeKey(line)
97 // WriteKey writes the hex-encoded key in a single line to w.
98 func WriteKey(w io.Writer, key []byte) error {
99 _, err := fmt.Fprintf(w, "%x\n", key)
100 return err
103 // DecodeKey decodes a hex-encoded private or public key.
104 func DecodeKey(s string) ([]byte, error) {
105 key, err := hex.DecodeString(s)
106 if err == nil && len(key) != KeyLen {
107 err = fmt.Errorf("length is %d, expected %d", len(key), KeyLen)
109 return key, err
112 // EncodeKey encodes a hex-encoded private or public key.
113 func EncodeKey(key []byte) string {
114 return hex.EncodeToString(key)