Add AES encryption between nodes

This commit is contained in:
2021-04-23 16:17:44 +02:00
parent 0a4217b5b9
commit ddaab52527
5 changed files with 132 additions and 1 deletions

86
net/crypt.go Normal file
View File

@@ -0,0 +1,86 @@
package net
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"flag"
"fmt"
"io"
)
var (
key string
sharedGCM cipher.AEAD
nonceSize int
)
// RegisterCryptFlags Registers the flags required for cryptography
func RegisterCryptFlags() {
flag.StringVar(&key, "key", "", "32 random bytes, base64-wrapped, to AES-encrypt traffic between nodes")
}
// InitCrypt creates a cipher object out of the key handed over via --key
func InitCrypt() error {
// Check if a key was handed over
if key == "" {
// no key, no service
return nil
}
// Unwrap base64'ed crypto bytes
rawKey, base64Err := base64.StdEncoding.DecodeString(key)
if base64Err != nil {
return fmt.Errorf("failed to unpack base64'ed key: %s", base64Err)
}
// Create cipher object using that key
block, cipherErr := aes.NewCipher(rawKey)
if cipherErr != nil {
return fmt.Errorf("failed to use your key as AES256 key: %s", cipherErr)
}
// Create GCM with cipher object
gcm, gcmErr := cipher.NewGCM(block)
if gcmErr != nil {
return fmt.Errorf("failed to create GCM for your key: %s", gcmErr)
}
// Set shared GCM instance
sharedGCM = gcm
nonceSize = gcm.NonceSize()
// No error to report
return nil
}
// CryptApplicable checks if we are able to encrypt or decrypt things, means if this instance was given a proper key
func CryptApplicable() bool {
// if the shared GCM object is set, we were able to get the key off user's hands, else we don't crypt
return sharedGCM != nil
}
// Encrypt encrypts the given bytes using the symmetric key
func Encrypt(plain []byte) ([]byte, error) {
// create nonce and fill it with random bytes
nonce := make([]byte, nonceSize)
_, readErr := io.ReadFull(rand.Reader, nonce)
if readErr != nil {
return nil, fmt.Errorf("failed to get random bytes: %s", readErr)
}
// Encrypt plaintext
return sharedGCM.Seal(nonce, nonce, plain, nil), nil
}
// Decrypt decrypts the given bytes using the symmetric key
func Decrypt(enc []byte) ([]byte, error) {
// Sanity check on input
if len(enc) < sharedGCM.NonceSize() {
return nil, fmt.Errorf("failed to decrypt packet: too short")
}
// Decrypt encrypted bytes
return sharedGCM.Open(nil, enc[:nonceSize], enc[nonceSize:], nil)
}

View File

@@ -76,9 +76,20 @@ func handle(conn net.Conn, outputDirectory string) {
// Read raw content
cont, contErr := ioutil.ReadAll(conn) // bufio.NewReader(conn).ReadString('\x00')
// Check if we are able to decrypt
if CryptApplicable() {
// Decrypt packet
var decryptErr error
cont, decryptErr = Decrypt(cont)
if decryptErr != nil {
log.Printf("Failed to decrypt packet from %s: %s", conn.RemoteAddr().String(), decryptErr)
return
}
}
if contErr == nil || contErr == io.EOF {
// We received the whole content, time to process it
unpackErr := logistic.UnpackInto([]byte(cont), outputDirectory)
unpackErr := logistic.UnpackInto(cont, outputDirectory)
if unpackErr != nil {
log.Printf("Encountered error processing packet from %s: %s", conn.RemoteAddr().String(), unpackErr)
}

View File

@@ -37,6 +37,17 @@ func CreatePeer(address string) Peer {
// Sends the given content to the peer
func (p *Peer) SendToPeer(content []byte) {
// Encrypt content if desired
if CryptApplicable() {
// Encrypt packet
var encryptErr error
content, encryptErr = Encrypt(content)
if encryptErr != nil {
log.Printf("Failed to decrypt packet from %s: %s", p.Address, encryptErr)
return
}
}
// Build up a connection
tcpConn, dialErr := net.Dial("tcp", p.Address)
if dialErr != nil {