github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/encryption/nacl.go (about)

     1  package encryption
     2  
     3  import (
     4  	cryptorand "crypto/rand"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/docker/swarmkit/api"
     9  
    10  	"golang.org/x/crypto/nacl/secretbox"
    11  )
    12  
    13  const naclSecretboxKeySize = 32
    14  const naclSecretboxNonceSize = 24
    15  
    16  // This provides the default implementation of an encrypter and decrypter, as well
    17  // as the default KDF function.
    18  
    19  // NACLSecretbox is an implementation of an encrypter/decrypter.  Encrypting
    20  // generates random Nonces.
    21  type NACLSecretbox struct {
    22  	key [naclSecretboxKeySize]byte
    23  }
    24  
    25  // NewNACLSecretbox returns a new NACL secretbox encrypter/decrypter with the given key
    26  func NewNACLSecretbox(key []byte) NACLSecretbox {
    27  	secretbox := NACLSecretbox{}
    28  	copy(secretbox.key[:], key)
    29  	return secretbox
    30  }
    31  
    32  // Algorithm returns the type of algorithm this is (NACL Secretbox using XSalsa20 and Poly1305)
    33  func (n NACLSecretbox) Algorithm() api.MaybeEncryptedRecord_Algorithm {
    34  	return api.MaybeEncryptedRecord_NACLSecretboxSalsa20Poly1305
    35  }
    36  
    37  // Encrypt encrypts some bytes and returns an encrypted record
    38  func (n NACLSecretbox) Encrypt(data []byte) (*api.MaybeEncryptedRecord, error) {
    39  	var nonce [24]byte
    40  	if _, err := io.ReadFull(cryptorand.Reader, nonce[:]); err != nil {
    41  		return nil, err
    42  	}
    43  
    44  	// Seal's first argument is an "out", the data that the new encrypted message should be
    45  	// appended to.  Since we don't want to append anything, we pass nil.
    46  	encrypted := secretbox.Seal(nil, data, &nonce, &n.key)
    47  	return &api.MaybeEncryptedRecord{
    48  		Algorithm: n.Algorithm(),
    49  		Data:      encrypted,
    50  		Nonce:     nonce[:],
    51  	}, nil
    52  }
    53  
    54  // Decrypt decrypts a MaybeEncryptedRecord and returns some bytes
    55  func (n NACLSecretbox) Decrypt(record api.MaybeEncryptedRecord) ([]byte, error) {
    56  	if record.Algorithm != n.Algorithm() {
    57  		return nil, fmt.Errorf("not a NACL secretbox record")
    58  	}
    59  	if len(record.Nonce) != naclSecretboxNonceSize {
    60  		return nil, fmt.Errorf("invalid nonce size for NACL secretbox: require 24, got %d", len(record.Nonce))
    61  	}
    62  
    63  	var decryptNonce [naclSecretboxNonceSize]byte
    64  	copy(decryptNonce[:], record.Nonce[:naclSecretboxNonceSize])
    65  
    66  	// Open's first argument is an "out", the data that the decrypted message should be
    67  	// appended to.  Since we don't want to append anything, we pass nil.
    68  	decrypted, ok := secretbox.Open(nil, record.Data, &decryptNonce, &n.key)
    69  	if !ok {
    70  		return nil, fmt.Errorf("no decryption key for record encrypted with %s", n.Algorithm())
    71  	}
    72  	return decrypted, nil
    73  }