diff --git a/config/secrets/box/box.go b/config/secrets/box/box.go deleted file mode 100644 index 67c559ff..00000000 --- a/config/secrets/box/box.go +++ /dev/null @@ -1,89 +0,0 @@ -// Package box is an asymmetric implementation of config/secrets using nacl/box -package box - -import ( - "github.com/micro/go-micro/v2/config/secrets" - "github.com/pkg/errors" - naclbox "golang.org/x/crypto/nacl/box" - - "crypto/rand" -) - -const keyLength = 32 - -type box struct { - options secrets.Options - - publicKey [keyLength]byte - privateKey [keyLength]byte -} - -// NewSecrets returns a nacl-box codec -func NewSecrets(opts ...secrets.Option) secrets.Secrets { - b := &box{} - for _, o := range opts { - o(&b.options) - } - return b -} - -// Init initialises a box -func (b *box) Init(opts ...secrets.Option) error { - for _, o := range opts { - o(&b.options) - } - if len(b.options.PrivateKey) != keyLength || len(b.options.PublicKey) != keyLength { - return errors.Errorf("a public key and a private key of length %d must both be provided", keyLength) - } - copy(b.privateKey[:], b.options.PrivateKey) - copy(b.publicKey[:], b.options.PublicKey) - return nil -} - -// Options returns options -func (b *box) Options() secrets.Options { - return b.options -} - -// String returns nacl-box -func (*box) String() string { - return "nacl-box" -} - -// Encrypt encrypts a message with the sender's private key and the receipient's public key -func (b *box) Encrypt(in []byte, opts ...secrets.EncryptOption) ([]byte, error) { - var options secrets.EncryptOptions - for _, o := range opts { - o(&options) - } - if len(options.RecipientPublicKey) != keyLength { - return []byte{}, errors.New("recepient's public key must be provided") - } - var recipientPublicKey [keyLength]byte - copy(recipientPublicKey[:], options.RecipientPublicKey) - var nonce [24]byte - if _, err := rand.Reader.Read(nonce[:]); err != nil { - return []byte{}, errors.Wrap(err, "couldn't obtain a random nonce from crypto/rand") - } - return naclbox.Seal(nonce[:], in, &nonce, &recipientPublicKey, &b.privateKey), nil -} - -// Decrypt Decrypts a message with the receiver's private key and the sender's public key -func (b *box) Decrypt(in []byte, opts ...secrets.DecryptOption) ([]byte, error) { - var options secrets.DecryptOptions - for _, o := range opts { - o(&options) - } - if len(options.SenderPublicKey) != keyLength { - return []byte{}, errors.New("sender's public key bust be provided") - } - var nonce [24]byte - var senderPublicKey [32]byte - copy(nonce[:], in[:24]) - copy(senderPublicKey[:], options.SenderPublicKey) - decrypted, ok := naclbox.Open(nil, in[24:], &nonce, &senderPublicKey, &b.privateKey) - if !ok { - return []byte{}, errors.New("incoming message couldn't be verified / decrypted") - } - return decrypted, nil -} diff --git a/config/secrets/box/box_test.go b/config/secrets/box/box_test.go deleted file mode 100644 index 3196ae8c..00000000 --- a/config/secrets/box/box_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package box - -import ( - "crypto/rand" - "reflect" - "testing" - - "github.com/micro/go-micro/v2/config/secrets" - naclbox "golang.org/x/crypto/nacl/box" -) - -func TestBox(t *testing.T) { - alicePublicKey, alicePrivateKey, err := naclbox.GenerateKey(rand.Reader) - if err != nil { - t.Fatal(err) - } - bobPublicKey, bobPrivateKey, err := naclbox.GenerateKey(rand.Reader) - if err != nil { - t.Fatal(err) - } - alice, bob := NewSecrets(secrets.PublicKey(alicePublicKey[:]), secrets.PrivateKey(alicePrivateKey[:])), NewSecrets() - if err := alice.Init(); err != nil { - t.Error(err) - } - if err := bob.Init(secrets.PublicKey(bobPublicKey[:]), secrets.PrivateKey(bobPrivateKey[:])); err != nil { - t.Error(err) - } - if alice.String() != "nacl-box" { - t.Error("String() doesn't return nacl-box") - } - aliceSecret := []byte("Why is a raven like a writing-desk?") - if _, err := alice.Encrypt(aliceSecret); err == nil { - t.Error("alice.Encrypt succeded without a public key") - } - enc, err := alice.Encrypt(aliceSecret, secrets.RecipientPublicKey(bob.Options().PublicKey)) - if err != nil { - t.Error("alice.Encrypt failed") - } - if _, err := bob.Decrypt(enc); err == nil { - t.Error("bob.Decrypt succeded without a public key") - } - if dec, err := bob.Decrypt(enc, secrets.SenderPublicKey(alice.Options().PublicKey)); err == nil { - if !reflect.DeepEqual(dec, aliceSecret) { - t.Errorf("Bob's decrypted message didn't match Alice's encrypted message: %v != %v", aliceSecret, dec) - } - } else { - t.Errorf("bob.Decrypt failed (%s)", err) - } - - bobSecret := []byte("I haven't the slightest idea") - enc, err = bob.Encrypt(bobSecret, secrets.RecipientPublicKey(alice.Options().PublicKey)) - if err != nil { - t.Error(err) - } - dec, err := alice.Decrypt(enc, secrets.SenderPublicKey(bob.Options().PrivateKey)) - if err == nil { - t.Error(err) - } - dec, err = alice.Decrypt(enc, secrets.SenderPublicKey(bob.Options().PublicKey)) - if err != nil { - t.Error(err) - } - if !reflect.DeepEqual(dec, bobSecret) { - t.Errorf("Alice's decrypted message didn't match Bob's encrypted message %v != %v", bobSecret, dec) - } -} diff --git a/config/secrets/secretbox/secretbox.go b/config/secrets/secretbox/secretbox.go deleted file mode 100644 index 50dae519..00000000 --- a/config/secrets/secretbox/secretbox.go +++ /dev/null @@ -1,73 +0,0 @@ -// Package secretbox is a config/secrets implementation that uses nacl/secretbox -// to do symmetric encryption / verification -package secretbox - -import ( - "github.com/micro/go-micro/v2/config/secrets" - "github.com/pkg/errors" - "golang.org/x/crypto/nacl/secretbox" - - "crypto/rand" -) - -const keyLength = 32 - -type secretBox struct { - options secrets.Options - - secretKey [keyLength]byte -} - -// NewSecrets returns a secretbox codec -func NewSecrets(opts ...secrets.Option) secrets.Secrets { - sb := &secretBox{} - for _, o := range opts { - o(&sb.options) - } - return sb -} - -func (s *secretBox) Init(opts ...secrets.Option) error { - for _, o := range opts { - o(&s.options) - } - if len(s.options.Key) == 0 { - return errors.New("no secret key is defined") - } - if len(s.options.Key) != keyLength { - return errors.Errorf("secret key must be %d bytes long", keyLength) - } - copy(s.secretKey[:], s.options.Key) - return nil -} - -func (s *secretBox) Options() secrets.Options { - return s.options -} - -func (s *secretBox) String() string { - return "nacl-secretbox" -} - -func (s *secretBox) Encrypt(in []byte, opts ...secrets.EncryptOption) ([]byte, error) { - // no opts are expected, so they are ignored - - // there must be a unique nonce for each message - var nonce [24]byte - if _, err := rand.Reader.Read(nonce[:]); err != nil { - return []byte{}, errors.Wrap(err, "couldn't obtain a random nonce from crypto/rand") - } - return secretbox.Seal(nonce[:], in, &nonce, &s.secretKey), nil -} - -func (s *secretBox) Decrypt(in []byte, opts ...secrets.DecryptOption) ([]byte, error) { - // no options are expected, so they are ignored - - var decryptNonce [24]byte - copy(decryptNonce[:], in[:24]) - decrypted, ok := secretbox.Open(nil, in[24:], &decryptNonce, &s.secretKey) - if !ok { - return []byte{}, errors.New("decryption failed (is the key set correctly?)") - } - return decrypted, nil -} diff --git a/config/secrets/secretbox/secretbox_test.go b/config/secrets/secretbox/secretbox_test.go deleted file mode 100644 index a0c1e07a..00000000 --- a/config/secrets/secretbox/secretbox_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package secretbox - -import ( - "encoding/base64" - "reflect" - "testing" - - "github.com/micro/go-micro/v2/config/secrets" -) - -func TestSecretBox(t *testing.T) { - secretKey, err := base64.StdEncoding.DecodeString("4jbVgq8FsAV7vy+n8WqEZrl7BUtNqh3fYT5RXzXOPFY=") - if err != nil { - t.Fatal(err) - } - - s := NewSecrets() - - if err := s.Init(); err == nil { - t.Error("Secretbox accepted an empty secret key") - } - if err := s.Init(secrets.Key([]byte("invalid"))); err == nil { - t.Error("Secretbox accepted a secret key that is invalid") - } - - if err := s.Init(secrets.Key(secretKey)); err != nil { - t.Fatal(err) - } - - o := s.Options() - if !reflect.DeepEqual(o.Key, secretKey) { - t.Error("Init() didn't set secret key correctly") - } - if s.String() != "nacl-secretbox" { - t.Error(s.String() + " should be nacl-secretbox") - } - - // Try 10 times to get different nonces - for i := 0; i < 10; i++ { - message := []byte(`Can you hear me, Major Tom?`) - - encrypted, err := s.Encrypt(message) - if err != nil { - t.Errorf("Failed to encrypt message (%s)", err) - } - - decrypted, err := s.Decrypt(encrypted) - if err != nil { - t.Errorf("Failed to decrypt encrypted message (%s)", err) - } - - if !reflect.DeepEqual(message, decrypted) { - t.Errorf("Decrypted Message dod not match encrypted message") - } - } -} diff --git a/config/secrets/secrets.go b/config/secrets/secrets.go deleted file mode 100644 index c8551355..00000000 --- a/config/secrets/secrets.go +++ /dev/null @@ -1,88 +0,0 @@ -// Package secrets is an interface for encrypting and decrypting secrets -package secrets - -import "context" - -// Secrets encrypts or decrypts arbitrary data. The data should be as small as possible -type Secrets interface { - // Initialise options - Init(...Option) error - // Return the options - Options() Options - // Decrypt a value - Decrypt([]byte, ...DecryptOption) ([]byte, error) - // Encrypt a value - Encrypt([]byte, ...EncryptOption) ([]byte, error) - // Secrets implementation - String() string -} - -type Options struct { - // Key is a symmetric key for encoding - Key []byte - // Private key for decoding - PrivateKey []byte - // Public key for encoding - PublicKey []byte - // Context for other opts - Context context.Context -} - -// Option sets options -type Option func(*Options) - -// Key sets the symmetric secret key -func Key(k []byte) Option { - return func(o *Options) { - o.Key = make([]byte, len(k)) - copy(o.Key, k) - } -} - -// PublicKey sets the asymmetric Public Key of this codec -func PublicKey(key []byte) Option { - return func(o *Options) { - o.PublicKey = make([]byte, len(key)) - copy(o.PublicKey, key) - } -} - -// PrivateKey sets the asymmetric Private Key of this codec -func PrivateKey(key []byte) Option { - return func(o *Options) { - o.PrivateKey = make([]byte, len(key)) - copy(o.PrivateKey, key) - } -} - -// DecryptOptions can be passed to Secrets.Decrypt -type DecryptOptions struct { - SenderPublicKey []byte -} - -// DecryptOption sets DecryptOptions -type DecryptOption func(*DecryptOptions) - -// SenderPublicKey is the Public Key of the Secrets that encrypted this message -func SenderPublicKey(key []byte) DecryptOption { - return func(d *DecryptOptions) { - d.SenderPublicKey = make([]byte, len(key)) - copy(d.SenderPublicKey, key) - } -} - -// EncryptOptions can be passed to Secrets.Encrypt -type EncryptOptions struct { - RecipientPublicKey []byte -} - -// EncryptOption Sets EncryptOptions -type EncryptOption func(*EncryptOptions) - -// RecipientPublicKey is the Public Key of the Secrets that will decrypt this message -func RecipientPublicKey(key []byte) EncryptOption { - return func(e *EncryptOptions) { - e.RecipientPublicKey = make([]byte, len(key)) - copy(e.RecipientPublicKey, key) - } -}