Remove 2 allocs by reusing CipherContext

This commit is contained in:
Jonathan Rudenberg 2014-07-03 22:54:08 -07:00
parent 6650461c89
commit a98f07ba16
No known key found for this signature in database
GPG Key ID: E38D8C6BAA8C49AA
1 changed files with 24 additions and 14 deletions

View File

@ -28,6 +28,7 @@ type Ciphersuite interface {
} }
type CipherContext interface { type CipherContext interface {
Reset(cv []byte)
Encrypt(dst, authtext, plaintext []byte) []byte Encrypt(dst, authtext, plaintext []byte) []byte
Decrypt(authtext, ciphertext []byte) ([]byte, error) Decrypt(authtext, ciphertext []byte) ([]byte, error)
} }
@ -57,6 +58,7 @@ type Crypter struct {
KDFNum int KDFNum int
keyBuf [512]byte keyBuf [512]byte
cc CipherContext
} }
func (c *Crypter) Encrypt(dst []byte, ephKey *Key, plaintext []byte, padLen int) ([]byte, error) { func (c *Crypter) Encrypt(dst []byte, ephKey *Key, plaintext []byte, padLen int) ([]byte, error) {
@ -84,18 +86,24 @@ func (c *Crypter) Encrypt(dst []byte, ephKey *Key, plaintext []byte, padLen int)
cv1 := c.deriveKey(dh1, c.ChainVar) cv1 := c.deriveKey(dh1, c.ChainVar)
c.ChainVar = c.deriveKey(dh2, cv1) c.ChainVar = c.deriveKey(dh2, cv1)
cc1 := c.Cipher.NewCipher(cv1)
cc2 := c.Cipher.NewCipher(c.ChainVar)
dst = append(dst, ephKey.Public...) dst = append(dst, ephKey.Public...)
dst = cc1.Encrypt(dst, ephKey.Public, c.SenderKey.Public) dst = c.cipher(cv1).Encrypt(dst, ephKey.Public, c.SenderKey.Public)
return noiseBody(cc2, dst, padLen, plaintext, dst[dstPrefixLen:]), nil return noiseBody(c.cipher(c.ChainVar), dst, padLen, plaintext, dst[dstPrefixLen:]), nil
} }
func (c *Crypter) EncryptedLen(n int) int { func (c *Crypter) EncryptedLen(n int) int {
return n + (2 * c.Cipher.DHLen()) + (2 * c.Cipher.MACLen()) + 4 return n + (2 * c.Cipher.DHLen()) + (2 * c.Cipher.MACLen()) + 4
} }
func (c *Crypter) cipher(cv []byte) CipherContext {
if c.cc == nil {
c.cc = c.Cipher.NewCipher(cv)
} else {
c.cc.Reset(cv)
}
return c.cc
}
func (c *Crypter) Decrypt(ciphertext []byte) ([]byte, error) { func (c *Crypter) Decrypt(ciphertext []byte) ([]byte, error) {
if len(c.ChainVar) == 0 { if len(c.ChainVar) == 0 {
c.ChainVar = make([]byte, cvLen) c.ChainVar = make([]byte, cvLen)
@ -104,19 +112,17 @@ func (c *Crypter) Decrypt(ciphertext []byte) ([]byte, error) {
ephPubKey := ciphertext[:c.Cipher.DHLen()] ephPubKey := ciphertext[:c.Cipher.DHLen()]
dh1 := c.Cipher.DH(c.ReceiverKey.Private, ephPubKey) dh1 := c.Cipher.DH(c.ReceiverKey.Private, ephPubKey)
cv1 := c.deriveKey(dh1, c.ChainVar) cv1 := c.deriveKey(dh1, c.ChainVar)
cc1 := c.Cipher.NewCipher(cv1)
header := ciphertext[:(2*c.Cipher.DHLen())+c.Cipher.MACLen()] header := ciphertext[:(2*c.Cipher.DHLen())+c.Cipher.MACLen()]
ciphertext = ciphertext[len(header):] ciphertext = ciphertext[len(header):]
senderPubKey, err := cc1.Decrypt(ephPubKey, header[c.Cipher.DHLen():]) senderPubKey, err := c.cipher(cv1).Decrypt(ephPubKey, header[c.Cipher.DHLen():])
if err != nil { if err != nil {
return nil, err return nil, err
} }
dh2 := c.Cipher.DH(c.ReceiverKey.Private, senderPubKey) dh2 := c.Cipher.DH(c.ReceiverKey.Private, senderPubKey)
c.ChainVar = c.deriveKey(dh2, cv1) c.ChainVar = c.deriveKey(dh2, cv1)
cc2 := c.Cipher.NewCipher(c.ChainVar) body, err := c.cipher(c.ChainVar).Decrypt(header, ciphertext)
body, err := cc2.Decrypt(header, ciphertext)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -187,17 +193,21 @@ func (noise255) DH(privkey, pubkey []byte) []byte {
} }
func (noise255) NewCipher(cv []byte) CipherContext { func (noise255) NewCipher(cv []byte) CipherContext {
return &noise255ctx{cc: cv} return &noise255ctx{cv: cv}
} }
type noise255ctx struct { type noise255ctx struct {
cc []byte cv []byte
keystream [128]byte keystream [128]byte
} }
func (n *noise255ctx) Reset(cv []byte) {
n.cv = cv
}
func (n *noise255ctx) key() (cipher.Stream, []byte) { func (n *noise255ctx) key() (cipher.Stream, []byte) {
cipherKey := n.cc[:32] cipherKey := n.cv[:32]
iv := n.cc[32:40] iv := n.cv[32:40]
c, err := chacha20.NewCipher(cipherKey, iv) c, err := chacha20.NewCipher(cipherKey, iv)
if err != nil { if err != nil {
@ -210,7 +220,7 @@ func (n *noise255ctx) key() (cipher.Stream, []byte) {
c.XORKeyStream(n.keystream[:], n.keystream[:]) c.XORKeyStream(n.keystream[:], n.keystream[:])
n.cc = n.keystream[64:104] n.cv = n.keystream[64:104]
return c, n.keystream[:] return c, n.keystream[:]
} }