This commit is contained in:
Jonathan Rudenberg 2014-06-17 23:29:23 -07:00
parent 8c41d1b57c
commit 16ad7c857e
No known key found for this signature in database
GPG Key ID: E38D8C6BAA8C49AA
1 changed files with 70 additions and 1 deletions

View File

@ -7,10 +7,15 @@ import (
"encoding/binary" "encoding/binary"
"io" "io"
"strconv" "strconv"
"github.com/codahale/chacha20"
"code.google.com/p/go.crypto/curve25519"
"code.google.com/p/go.crypto/poly1305"
) )
type Ciphersuite interface { type Ciphersuite interface {
Name() [24]byte Name() []byte
DHLen() int DHLen() int
CCLen() int CCLen() int
MACLen() int MACLen() int
@ -80,3 +85,67 @@ func NoiseBox(c Ciphersuite, dst []byte, ephKey, senderKey Key, recvrPubkey []by
header := cc1.Encrypt(ephKey.Public, ephKey.Public, senderKey.Public) header := cc1.Encrypt(ephKey.Public, ephKey.Public, senderKey.Public)
return noiseBody(cc2, header, padLen, appData, header), cv2 return noiseBody(cc2, header, padLen, appData, header), cv2
} }
type Noise255 struct{}
func (Noise255) Name() []byte { return []byte("Noise255") }
func (Noise255) DHLen() int { return 32 }
func (Noise255) CCLen() int { return 40 }
func (Noise255) MACLen() int { return 16 }
func (Noise255) DH(privkey, pubkey []byte) []byte {
var dst, in, base [32]byte
copy(in[:], privkey)
copy(base[:], pubkey)
curve25519.ScalarMult(&dst, &in, &base)
return dst[:]
}
func (Noise255) NewCipher(cv []byte) CipherContext {
return &noise255{cv}
}
type noise255 struct {
cc []byte
}
func (n *noise255) Encrypt(dst, authtext, plaintext []byte) []byte {
cipherKey := n.cc[:32]
iv := n.cc[32:40]
c, err := chacha20.NewCipher(cipherKey, iv)
if err != nil {
panic(err)
}
keystream := make([]byte, 128)
c.XORKeyStream(keystream, keystream)
ciphertext := make([]byte, len(plaintext), len(plaintext)+16)
c.XORKeyStream(ciphertext, plaintext)
var macKey [32]byte
var mac [16]byte
copy(macKey[:], keystream)
poly1305.Sum(&mac, n.authData(authtext, plaintext), &macKey)
n.cc = keystream[64:104]
return append(dst, append(ciphertext, mac[:]...)...)
}
func (noise255) authData(authtext, plaintext []byte) []byte {
// PAD16(authtext) || PAD16(plaintext) || (uint64)len(authtext) || (uint64)len(plaintext)
authData := make([]byte, pad16len(len(authtext))+pad16len(len(plaintext))+8+8)
copy(authData, authtext)
offset := pad16len(len(authtext))
copy(authData[offset:], plaintext)
offset += pad16len(len(plaintext))
binary.BigEndian.PutUint64(authData[offset:], uint64(len(authtext)))
offset += 8
binary.BigEndian.PutUint64(authData[offset:], uint64(len(plaintext)))
return authData
}
func pad16len(l int) int {
return l + (16 - (l % 16))
}