From c243ae5a661dafa86438b55034ae7f4fc2eec31e Mon Sep 17 00:00:00 2001 From: Pedro Pombeiro Date: Tue, 21 Aug 2018 11:18:46 +0200 Subject: [PATCH] Add makefile with lint support (#4) --- .golangci.yml | 74 ++++++++++++++++++++++++++++++++++++++++++ Makefile | 59 +++++++++++++++++++++++++++++++++ chains_test.go | 3 +- crypto.go | 2 +- crypto_test.go | 3 +- default_crypto.go | 21 +++++++----- default_crypto_test.go | 3 +- keys_storage_test.go | 17 +++++++--- message_test.go | 3 +- options.go | 4 +++ options_test.go | 3 +- session.go | 2 +- session_he.go | 10 +++--- session_he_test.go | 4 +-- session_test.go | 3 +- state_test.go | 3 +- 16 files changed, 185 insertions(+), 29 deletions(-) create mode 100644 .golangci.yml create mode 100644 Makefile diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..e733e60 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,74 @@ +run: + concurrency: 4 + deadline: 1m + issues-exit-code: 1 + tests: true + # build-tags: + # - mytag + skip-dirs: + - static + skip-files: + - .*_mock.go + - jail/doc.go + +output: + format: colored-line-number + print-issued-lines: true + print-linter-name: true + +linters-settings: + errcheck: + check-type-assertions: false + check-blank: false + govet: + check-shadowing: false + golint: + min-confidence: 0.8 + gofmt: + simplify: true + gocyclo: + min-complexity: 16 + maligned: + suggest-new: true + dupl: + threshold: 50 + goconst: + min-len: 3 + min-occurrences: 2 + # depguard: + # list-type: blacklist + # include-go-root: false + # packages: + # - github.com/davecgh/go-spew/spew + +linters: + disable-all: true + enable: + - deadcode + #- depguard + - errcheck + - gas + - goconst + - gocyclo + - gofmt + - golint + - govet + - ineffassign + - interfacer + - megacheck + - misspell + - structcheck + - typecheck + - unconvert + - varcheck + fast: false + +issues: + exclude: + - "composite literal uses unkeyed fields" # govet +# exclude-use-default: true +# max-per-linter: 0 +# max-same: 0 +# new: false +# new-from-rev: "" +# new-from-patch: "" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e87d51c --- /dev/null +++ b/Makefile @@ -0,0 +1,59 @@ +.PHONY: help + +help: ##@other Show this help + @perl -e '$(HELP_FUN)' $(MAKEFILE_LIST) + +ifndef GOPATH + $(error GOPATH not set. Please set GOPATH and make sure status-go is located at $$GOPATH/src/github.com/status-im/status-go. \ + For more information about the GOPATH environment variable, see https://golang.org/doc/code.html#GOPATH) +endif + + +EXPECTED_PATH=$(shell go env GOPATH)/src/github.com/status-im/doubleratchet +ifneq ($(CURDIR),$(EXPECTED_PATH)) +define NOT_IN_GOPATH_ERROR + +Current dir is $(CURDIR), which seems to be different from your GOPATH. +Please, build status-go from GOPATH for proper build. + GOPATH = $(shell go env GOPATH) + Current dir = $(CURDIR) + Expected dir = $(EXPECTED_PATH)) +See https://golang.org/doc/code.html#GOPATH for more info + +endef +$(error $(NOT_IN_GOPATH_ERROR)) +endif + +GOBIN=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))build/bin +GIT_COMMIT := $(shell git rev-parse --short HEAD) + +# This is a code for automatic help generator. +# It supports ANSI colors and categories. +# To add new item into help output, simply add comments +# starting with '##'. To add category, use @category. +GREEN := $(shell echo "\e[32m") +WHITE := $(shell echo "\e[37m") +YELLOW := $(shell echo "\e[33m") +RESET := $(shell echo "\e[0m") +HELP_FUN = \ + %help; \ + while(<>) { push @{$$help{$$2 // 'options'}}, [$$1, $$3] if /^([a-zA-Z0-9\-]+)\s*:.*\#\#(?:@([a-zA-Z\-]+))?\s(.*)$$/ }; \ + print "Usage: make [target]\n\n"; \ + for (sort keys %help) { \ + print "${WHITE}$$_:${RESET}\n"; \ + for (@{$$help{$$_}}) { \ + $$sep = " " x (32 - length $$_->[0]); \ + print " ${YELLOW}$$_->[0]${RESET}$$sep${GREEN}$$_->[1]${RESET}\n"; \ + }; \ + print "\n"; \ + } + +setup: lint-install ##@other Prepare project for first build + +lint-install: + @# The following installs a specific version of golangci-lint, which is appropriate for a CI server to avoid different results from build to build + curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $(GOPATH)/bin v1.9.1 + +lint: ##@other Run linter + @echo "lint" + @golangci-lint run ./... diff --git a/chains_test.go b/chains_test.go index 6ee6392..e149bf7 100644 --- a/chains_test.go +++ b/chains_test.go @@ -1,8 +1,9 @@ package doubleratchet import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) var chainKey = Key{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40} diff --git a/crypto.go b/crypto.go index 11908a7..d4d2cf6 100644 --- a/crypto.go +++ b/crypto.go @@ -27,7 +27,7 @@ type DHPair interface { PublicKey() Key } -// Keys is any 32-byte key. It's created for the possibility of pretty hex output. +// Key is any 32-byte key. It's created for the possibility of pretty hex output. type Key [32]byte // Stringer interface compliance. diff --git a/crypto_test.go b/crypto_test.go index 5d4e9d1..cf3b29c 100644 --- a/crypto_test.go +++ b/crypto_test.go @@ -1,8 +1,9 @@ package doubleratchet import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestKey_String(t *testing.T) { diff --git a/default_crypto.go b/default_crypto.go index 72d0c8f..5deb68f 100644 --- a/default_crypto.go +++ b/default_crypto.go @@ -19,7 +19,7 @@ import ( // see function comments for details. type DefaultCrypto struct{} -// See the Crypto interface. +// GenerateDH creates a new Diffie-Hellman key pair. func (c DefaultCrypto) GenerateDH() (DHPair, error) { var privKey [32]byte if _, err := io.ReadFull(rand.Reader, privKey[:]); err != nil { @@ -37,7 +37,8 @@ func (c DefaultCrypto) GenerateDH() (DHPair, error) { }, nil } -// See the Crypto interface. +// DH returns the output from the Diffie-Hellman calculation between +// the private key from the DH key pair dhPair and the DH public key dbPub. func (c DefaultCrypto) DH(dhPair DHPair, dhPub Key) Key { var ( dhOut [32]byte @@ -48,7 +49,8 @@ func (c DefaultCrypto) DH(dhPair DHPair, dhPub Key) Key { return dhOut } -// See the Crypto interface. +// KdfRK returns a pair (32-byte root key, 32-byte chain key) as the output of applying +// a KDF keyed by a 32-byte root key rk to a Diffie-Hellman output dhOut. func (c DefaultCrypto) KdfRK(rk, dhOut Key) (rootKey, chainKey, headerKey Key) { var ( r = hkdf.New(sha256.New, dhOut[:], rk[:], []byte("rsZUpEuXUqqwXBvSy3EcievAh4cMj6QL")) @@ -64,7 +66,8 @@ func (c DefaultCrypto) KdfRK(rk, dhOut Key) (rootKey, chainKey, headerKey Key) { return } -// See the Crypto interface. +// KdfCK returns a pair (32-byte chain key, 32-byte message key) as the output of applying +// a KDF keyed by a 32-byte chain key ck to some constant. func (c DefaultCrypto) KdfCK(ck Key) (chainKey Key, msgKey Key) { const ( ckInput = 15 @@ -73,11 +76,11 @@ func (c DefaultCrypto) KdfCK(ck Key) (chainKey Key, msgKey Key) { h := hmac.New(sha256.New, ck[:]) - h.Write([]byte{ckInput}) + _, _ = h.Write([]byte{ckInput}) copy(chainKey[:], h.Sum(nil)) h.Reset() - h.Write([]byte{mkInput}) + _, _ = h.Write([]byte{mkInput}) copy(msgKey[:], h.Sum(nil)) return chainKey, msgKey @@ -101,7 +104,7 @@ func (c DefaultCrypto) Encrypt(mk Key, plaintext, ad []byte) []byte { return append(ciphertext, c.computeSignature(authKey[:], ciphertext, ad)...) } -// See the Crypto interface. +// Decrypt returns the AEAD decryption of ciphertext with message key mk. func (c DefaultCrypto) Decrypt(mk Key, authCiphertext, ad []byte) ([]byte, error) { var ( l = len(authCiphertext) @@ -147,8 +150,8 @@ func (c DefaultCrypto) deriveEncKeys(mk Key) (encKey Key, authKey Key, iv [16]by func (c DefaultCrypto) computeSignature(authKey, ciphertext, associatedData []byte) []byte { h := hmac.New(sha256.New, authKey) - h.Write(associatedData) - h.Write(ciphertext) + _, _ = h.Write(associatedData) + _, _ = h.Write(ciphertext) return h.Sum(nil) } diff --git a/default_crypto_test.go b/default_crypto_test.go index cc64b4e..527032b 100644 --- a/default_crypto_test.go +++ b/default_crypto_test.go @@ -2,8 +2,9 @@ package doubleratchet import ( "fmt" - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestDhPair(t *testing.T) { diff --git a/keys_storage_test.go b/keys_storage_test.go index fcb9349..0bc1e8a 100644 --- a/keys_storage_test.go +++ b/keys_storage_test.go @@ -1,8 +1,9 @@ package doubleratchet import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) var ( @@ -28,7 +29,8 @@ func TestKeysStorageInMemory_Put(t *testing.T) { ks := &KeysStorageInMemory{} // Act and assert. - ks.Put(pubKey1, 0, mk) + err := ks.Put(pubKey1, 0, mk) + require.NoError(t, err) } func TestKeysStorageInMemory_Count(t *testing.T) { @@ -58,12 +60,15 @@ func TestKeysStorageInMemory_Flow(t *testing.T) { t.Run("delete non-existent pubkey", func(t *testing.T) { // Act and assert. - ks.DeletePk(pubKey1) + err := ks.DeletePk(pubKey1) + require.NoError(t, err) }) t.Run("put and get existing", func(t *testing.T) { // Act. - ks.Put(pubKey1, 0, mk) + err := ks.Put(pubKey1, 0, mk) + require.NoError(t, err) + k, ok, err := ks.Get(pubKey1, 0) // Assert. @@ -124,7 +129,9 @@ func TestKeysStorageInMemory_Flow(t *testing.T) { t.Run("delete existing message key", func(t *testing.T) { // Act. - ks.DeleteMk(pubKey1, 0) + err := ks.DeleteMk(pubKey1, 0) + require.NoError(t, err) + cnt, err := ks.Count(pubKey1) // Assert. diff --git a/message_test.go b/message_test.go index 4909af7..ff1eeec 100644 --- a/message_test.go +++ b/message_test.go @@ -1,8 +1,9 @@ package doubleratchet import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestMessageHeader_EncodeAndDecode(t *testing.T) { diff --git a/options.go b/options.go index 982d63a..1c740bf 100644 --- a/options.go +++ b/options.go @@ -6,6 +6,7 @@ import "fmt" type option func(*State) error // WithMaxSkip specifies the maximum number of skipped message in a single chain. +// nolint: golint func WithMaxSkip(n int) option { return func(s *State) error { if n < 0 { @@ -17,6 +18,7 @@ func WithMaxSkip(n int) option { } // WithMaxKeep specifies the maximum number of ratchet steps before a message is deleted. +// nolint: golint func WithMaxKeep(n int) option { return func(s *State) error { if n < 0 { @@ -28,6 +30,7 @@ func WithMaxKeep(n int) option { } // WithKeysStorage replaces the default keys storage with the specified. +// nolint: golint func WithKeysStorage(ks KeysStorage) option { return func(s *State) error { if ks == nil { @@ -39,6 +42,7 @@ func WithKeysStorage(ks KeysStorage) option { } // WithCrypto replaces the default cryptographic supplement with the specified. +// nolint: golint func WithCrypto(c Crypto) option { return func(s *State) error { if c == nil { diff --git a/options_test.go b/options_test.go index 0c3b9a0..0e27255 100644 --- a/options_test.go +++ b/options_test.go @@ -1,8 +1,9 @@ package doubleratchet import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestWithMaxSkip_OK(t *testing.T) { diff --git a/session.go b/session.go index 065f981..05a47a4 100644 --- a/session.go +++ b/session.go @@ -114,7 +114,7 @@ func (s *sessionState) RatchetDecrypt(m Message, ad []byte) ([]byte, error) { if err != nil { return nil, fmt.Errorf("can't decrypt skipped message: %s", err) } - s.MkSkipped.DeleteMk(m.Header.DH, uint(m.Header.N)) + _ = s.MkSkipped.DeleteMk(m.Header.DH, uint(m.Header.N)) return plaintext, nil } diff --git a/session_he.go b/session_he.go index 55f99ab..32f7e2c 100644 --- a/session_he.go +++ b/session_he.go @@ -79,7 +79,7 @@ func (s *sessionHE) RatchetDecrypt(m MessageHE, ad []byte) ([]byte, error) { var ( // All changes must be applied on a different session object, so that this session won't be modified nor left in a dirty session. - sc State = s.State + sc = s.State skippedKeys1 []skippedKey skippedKeys2 []skippedKey @@ -103,9 +103,11 @@ func (s *sessionHE) RatchetDecrypt(m MessageHE, ad []byte) ([]byte, error) { return nil, fmt.Errorf("can't decrypt: %s", err) } - s.applyChanges(sc, append(skippedKeys1, skippedKeys2...)) + if err = s.applyChanges(sc, append(skippedKeys1, skippedKeys2...)); err != nil { + return nil, fmt.Errorf("failed to apply changes: %s", err) + } if step { - s.deleteSkippedKeys(s.HKr) + _ = s.deleteSkippedKeys(s.HKr) } return plaintext, nil @@ -146,7 +148,7 @@ func (s *sessionHE) trySkippedMessages(m MessageHE, ad []byte) ([]byte, error) { if err != nil { return nil, fmt.Errorf("can't decrypt skipped message: %s", err) } - s.MkSkipped.DeleteMk(hk, n) + _ = s.MkSkipped.DeleteMk(hk, n) return plaintext, nil } } diff --git a/session_he_test.go b/session_he_test.go index b367107..bc7b36b 100644 --- a/session_he_test.go +++ b/session_he_test.go @@ -2,14 +2,14 @@ package doubleratchet import ( "fmt" - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) var ( sharedHka = Key{0xbd, 0x29, 0x18, 0xcb, 0x18, 0x6c, 0x26, 0x32, 0xd5, 0x82, 0x41, 0x2d, 0x11, 0xa4, 0x55, 0x87, 0x1e, 0x5b, 0xa3, 0xb5, 0x5a, 0x6d, 0xe1, 0x97, 0xde, 0xf7, 0x5e, 0xc3, 0xf2, 0xec, 0x1d, 0xd} sharedNhkb = Key{0x32, 0x89, 0x3a, 0xed, 0x4b, 0xf0, 0xbf, 0xc1, 0xa5, 0xa9, 0x53, 0x73, 0x5b, 0xf9, 0x76, 0xce, 0x70, 0x8e, 0xe1, 0xa, 0xed, 0x98, 0x1d, 0xe3, 0xb4, 0xe9, 0xa9, 0x88, 0x54, 0x94, 0xaf, 0x23} - k = Key{0x4b, 0x22, 0x7f, 0x60, 0x7b, 0x1e, 0x76, 0xb6, 0xf5, 0xf2, 0x72, 0x22, 0xf3, 0x14, 0xaf, 0x69, 0x60, 0xca, 0xd4, 0x26, 0x51, 0x88, 0xc9, 0xd, 0xbf, 0x23, 0x42, 0xfd, 0x1a, 0x30, 0xad, 0x4b} ) func TestNewHE(t *testing.T) { diff --git a/session_test.go b/session_test.go index ce580c0..208709d 100644 --- a/session_test.go +++ b/session_test.go @@ -2,8 +2,9 @@ package doubleratchet import ( "fmt" - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestNew(t *testing.T) { diff --git a/state_test.go b/state_test.go index 60d8276..06134df 100644 --- a/state_test.go +++ b/state_test.go @@ -1,8 +1,9 @@ package doubleratchet import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) var (