crypto.go raw

   1  package transport
   2  
   3  import (
   4  	"crypto/cipher"
   5  	"crypto/rand"
   6  	"encoding/hex"
   7  	"errors"
   8  	"fmt"
   9  	"io"
  10  )
  11  
  12  // DecryptMessage attempts to decode the received message
  13  func DecryptMessage(creator string, ciph cipher.AEAD, data []byte) (msg []byte, e error) {
  14  	nonceSize := ciph.NonceSize()
  15  	msg, e = ciph.Open(nil, data[:nonceSize], data[nonceSize:], nil)
  16  	if e != nil {
  17  		e = errors.New(fmt.Sprintf("%s %s", creator, e.Error()))
  18  	} else {
  19  		D.Ln("decrypted message", hex.EncodeToString(data[:nonceSize]))
  20  	}
  21  	return
  22  }
  23  
  24  // EncryptMessage encrypts a message, if the nonce is given it uses that
  25  // otherwise it generates a new one. If there is no cipher this just returns a
  26  // message with the given magic prepended.
  27  func EncryptMessage(creator string, ciph cipher.AEAD, magic []byte, nonce, data []byte) (msg []byte, e error) {
  28  	if ciph != nil {
  29  		if nonce == nil {
  30  			nonce, e = GetNonce(ciph)
  31  		}
  32  		msg = append(append(magic, nonce...), ciph.Seal(nil, nonce, data, nil)...)
  33  	} else {
  34  		msg = append(magic, data...)
  35  	}
  36  	return
  37  }
  38  
  39  // GetNonce reads from a cryptographicallly secure random number source
  40  func GetNonce(ciph cipher.AEAD) (nonce []byte, e error) {
  41  	// get a nonce for the packet, it is both message ID and salt
  42  	nonce = make([]byte, ciph.NonceSize())
  43  	if _, e = io.ReadFull(rand.Reader, nonce); E.Chk(e) {
  44  	}
  45  	return
  46  }
  47