diff --git a/pkg/cryptstate/cryptstate.go b/pkg/cryptstate/cryptstate.go index d5f7891..3b8e205 100644 --- a/pkg/cryptstate/cryptstate.go +++ b/pkg/cryptstate/cryptstate.go @@ -55,6 +55,8 @@ func createMode(mode string) (CryptoMode, error) { return &ocb2Mode{}, nil case "XSalsa20-Poly1305": return &secretBoxMode{}, nil + case "NULL": + return &nullMode{}, nil } return nil, errors.New("cryptstate: no such CryptoMode") } diff --git a/pkg/cryptstate/cryptstate_test.go b/pkg/cryptstate/cryptstate_test.go index 6c48d53..eacd8fd 100644 --- a/pkg/cryptstate/cryptstate_test.go +++ b/pkg/cryptstate/cryptstate_test.go @@ -68,7 +68,10 @@ func TestOCB2AES128Decrypt(t *testing.T) { cs := CryptState{} out := make([]byte, 15) cs.SetKey("OCB2-AES128", key[:], div[:], eiv[:]) - cs.Decrypt(out, crypted[:]) + err := cs.Decrypt(out, crypted[:]) + if err != nil { + t.Fatalf("%v", err) + } if !bytes.Equal(out, expected[:]) { t.Errorf("Mismatch in output") @@ -146,11 +149,40 @@ func TestXSalsa20Poly1305Decrypt(t *testing.T) { } message, _ := hex.DecodeString("028442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad") - cs.SetKey("XSalsa20-Poly1305", key[:], div[:], eiv[:]) + cs.SetKey("XSalsa20-Poly1305", key[:], eiv[:], div[:]) dst := make([]byte, len(message)-cs.Overhead()) - cs.Decrypt(dst, message[:]) + err := cs.Decrypt(dst, message[:]) + if err != nil { + t.Fatalf("%v", err) + } if !bytes.Equal(dst, expected[:]) { t.Fatalf("mismatch! got\n%x\n, expected\n%x", dst, expected) } +} + +func TestNullEncrypt(t *testing.T) { + cs := CryptState{} + cs.SetKey("NULL", []byte{}, []byte{1}, []byte{1}) + msg := []byte("HelloWorld") + dst := make([]byte, len(msg)+cs.Overhead()) + cs.Encrypt(dst, msg) + if !bytes.Equal(dst[1:], msg) { + t.Fatalf("mismatch! got\n%x\n, expected\n%x", dst, msg) + } +} + +func TestNullDecrypt(t *testing.T) { + cs := CryptState{} + cs.SetKey("NULL", []byte{}, []byte{1}, []byte{1}) + msg := []byte{2} + msg = append(msg, []byte("HelloWorld")...) + dst := make([]byte, len(msg)-cs.Overhead()) + err := cs.Decrypt(dst, msg) + if err != nil { + t.Fatalf("%v", err) + } + if !bytes.Equal(dst, msg[1:]) { + t.Fatalf("mismatch! got\n%x\n, expected\n%x", dst, msg) + } } \ No newline at end of file diff --git a/pkg/cryptstate/mode_null.go b/pkg/cryptstate/mode_null.go new file mode 100644 index 0000000..ad5c0c8 --- /dev/null +++ b/pkg/cryptstate/mode_null.go @@ -0,0 +1,38 @@ +// Copyright (c) 2012 The Grumble Authors +// The use of this source code is goverened by a BSD-style +// license that can be found in the LICENSE-file. + +package cryptstate + +// nullMode implements the NULL CryptoMode +type nullMode struct {} + +// NonceSize returns the nonce size to be used with NULL. +func (n *nullMode) NonceSize() int { + return 1 +} + +// KeySize returns the key size to be used with NULL. +func (n *nullMode) KeySize() int { + return 0 +} + +// Overhead returns the overhead that a ciphertext has over a plaintext. +func (n *nullMode) Overhead() int { + return 0 +} + +// SetKey sets a new key. The key must have a length equal to KeySize(). +func (n *nullMode) SetKey(key []byte) { +} + +// Encrypt encrypts a message using NULL and outputs it to dst. +func (n *nullMode) Encrypt(dst []byte, src []byte, nonce []byte) { + copy(dst, src) +} + +// Decrypt decrypts a message using NULL and outputs it to dst. +func (n *nullMode) Decrypt(dst []byte, src []byte, nonce []byte) bool { + copy(dst, src) + return true +}