diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..0dc25f5 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,69 @@ +# options for analysis running +run: + # default concurrency is a available CPU number + concurrency: 4 + + # timeout for analysis, e.g. 30s, 5m, default is 1m + deadline: 2m + + # which files to skip: they will be analyzed, but issues from them + # won't be reported. Default value is empty list, but there is + # no need to include all autogenerated files, we confidently recognize + # autogenerated files. If it's not please let us know. + skip-files: + - ".*generated.*" + - ".*_test.go" + +# all available settings of specific linters +linters-settings: + gocyclo: + min-complexity: 20 + lll: + line-length: 200 + +linters: + enable: + - deadcode + - errcheck + - govet + - ineffassign + - staticcheck + - structcheck + - unused + - varcheck + - bodyclose + - depguard + - dupl + - gocyclo + - goimports + - golint + - gosec + - misspell + - stylecheck + - unconvert + disable-all: true + fast: true + + +issues: + exclude-use-default: false + + # List of regexps of issue texts to exclude, empty list by default. + # But independently from this option we use default exclude patterns, + # it can be disabled by `exclude-use-default: false`. To list all + # excluded by default patterns execute `golangci-lint run --help` + exclude: + # errcheck defer Close + - error return value not checked \(defer .*\.Close()\) + # errcheck: Almost all programs ignore errors on these functions and in most cases it's ok + - Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked + # gosec: Duplicated errcheck checks + - G104 + # gosec: Expect file permissions to be 0600 or less + - G302 + # gosec: Use of weak random number generators + - G404 + # errcheck defer Close + - error return value not checked \(defer .*\.Close()\) + # gosec: False positive is triggered by 'src, err := ioutil.ReadFile(filename)' + - Potential file inclusion via variable diff --git a/.gometalinter.json b/.gometalinter.json deleted file mode 100644 index 437515c..0000000 --- a/.gometalinter.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "Vendor": true, - "Test": true, - "Deadline": "2m", - "Sort": ["linter", "severity", "path", "line"], - "Exclude": [ - ".*generated.*" - ], - "EnableGC": true, - "Linters": { - "nakedret": { - "Command": "nakedret", - "Pattern": "^(?P.*?\\.go):(?P\\d+)\\s*(?P.*)$" - } - }, - "WarnUnmatchedDirective": true, - - "DisableAll": true, - "Enable": [ - "deadcode", - "gocyclo", - "gofmt", - "goimports", - "golint", - "gosimple", - "ineffassign", - "interfacer", - "lll", - "misspell", - "nakedret", - "unconvert", - "unparam", - "unused", - "vet" - ], - - "Cyclo": 16, - "LineLength": 200 -} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 940b66a..f87900a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ env: - GO111MODULE=on go: -- 1.11.x - 1.x script: diff --git a/dnscrypt.go b/dnscrypt.go index 584fe63..ff0dd60 100644 --- a/dnscrypt.go +++ b/dnscrypt.go @@ -183,9 +183,9 @@ func (c *Client) ExchangeConn(m *dns.Msg, s *ServerInfo, conn net.Conn) (*dns.Ms } if c.Timeout > 0 { - conn.SetDeadline(time.Now().Add(c.Timeout)) + _ = conn.SetDeadline(time.Now().Add(c.Timeout)) } - conn.Write(encryptedQuery) + _, _ = conn.Write(encryptedQuery) encryptedResponse := make([]byte, maxDNSPacketSize) // Reading the response @@ -344,8 +344,8 @@ func (s *ServerInfo) decrypt(encrypted []byte, nonce []byte) ([]byte, error) { sharedKey := &s.ServerCert.SharedKey serverMagicLen := len(serverMagic) responseHeaderLen := serverMagicLen + nonceSize - if len(encrypted) < responseHeaderLen+tagSize+int(minDNSPacketSize) || - len(encrypted) > responseHeaderLen+tagSize+int(maxDNSPacketSize) || + if len(encrypted) < responseHeaderLen+tagSize+minDNSPacketSize || + len(encrypted) > responseHeaderLen+tagSize+maxDNSPacketSize || !bytes.Equal(encrypted[:serverMagicLen], serverMagic[:]) { return encrypted, errors.New("invalid message size or prefix") } @@ -447,7 +447,7 @@ func computeSharedKey(cryptoConstruction CryptoConstruction, secretKey *[32]byte func isDigit(b byte) bool { return b >= '0' && b <= '9' } func dddToByte(s []byte) byte { - return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0')) + return (s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0') } func packTxtString(s string) ([]byte, error) { diff --git a/dnscrypt_test.go b/dnscrypt_test.go index 4bf881d..690bd7f 100644 --- a/dnscrypt_test.go +++ b/dnscrypt_test.go @@ -109,6 +109,10 @@ func TestDnsCryptResolver(t *testing.T) { // AdGuard DNS Family stampStr: "sdns://AQIAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMjo1NDQzILgxXdexS27jIKRw3C7Wsao5jMnlhvhdRUXWuMm1AFq6ITIuZG5zY3J5cHQuZmFtaWx5Lm5zMS5hZGd1YXJkLmNvbQ", }, + { + // AdGuard DNS Unfiltered + stampStr: "sdns://AQIAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzNjo1NDQzILXoRNa4Oj4-EmjraB--pw3jxfpo29aIFB2_LsBmstr6JTIuZG5zY3J5cHQudW5maWx0ZXJlZC5uczEuYWRndWFyZC5jb20", + }, { // Cisco OpenDNS stampStr: "sdns://AQAAAAAAAAAADjIwOC42Ny4yMjAuMjIwILc1EUAgbyJdPivYItf9aR6hwzzI1maNDL4Ev6vKQ_t5GzIuZG5zY3J5cHQtY2VydC5vcGVuZG5zLmNvbQ", @@ -117,14 +121,6 @@ func TestDnsCryptResolver(t *testing.T) { // Cisco OpenDNS Family Shield stampStr: "sdns://AQAAAAAAAAAADjIwOC42Ny4yMjAuMTIzILc1EUAgbyJdPivYItf9aR6hwzzI1maNDL4Ev6vKQ_t5GzIuZG5zY3J5cHQtY2VydC5vcGVuZG5zLmNvbQ", }, - //{ - // // Quad9 (anycast) dnssec/no-log/filter 9.9.9.9 - // stampStr: "sdns://AQMAAAAAAAAADDkuOS45Ljk6ODQ0MyBnyEe4yHWM0SAkVUO-dWdG3zTfHYTAC4xHA2jfgh2GPhkyLmRuc2NyeXB0LWNlcnQucXVhZDkubmV0", - //}, - { - // Yandex DNS - stampStr: "sdns://AQQAAAAAAAAAEDc3Ljg4LjguNzg6MTUzNTMg04TAccn3RmKvKszVe13MlxTUB7atNgHhrtwG1W1JYyciMi5kbnNjcnlwdC1jZXJ0LmJyb3dzZXIueWFuZGV4Lm5ldA", - }, } for _, test := range stamps { diff --git a/go.mod b/go.mod index e74d32e..5119e62 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,10 @@ require ( github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 github.com/ameshkov/dnsstamps v1.0.1 - github.com/miekg/dns v1.1.8 - golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 - golang.org/x/net v0.0.0-20190119204137-ed066c81e75e // indirect - golang.org/x/sync v0.0.0-20181108010431-42b317875d0f // indirect - golang.org/x/sys v0.0.0-20190122071731-054c452bb702 // indirect + github.com/miekg/dns v1.1.29 + golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 + golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect + golang.org/x/sys v0.0.0-20200331124033-c3d80250170d // indirect ) + +go 1.14 diff --git a/go.sum b/go.sum index 6ba0178..d8b4c56 100644 --- a/go.sum +++ b/go.sum @@ -4,15 +4,26 @@ github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyY github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us= github.com/ameshkov/dnsstamps v1.0.1 h1:LhGvgWDzhNJh+kBQd/AfUlq1vfVe109huiXw4JhnPug= github.com/ameshkov/dnsstamps v1.0.1/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A= -github.com/miekg/dns v1.1.1 h1:DVkblRdiScEnEr0LR9nTnEQqHYycjkXW9bOjd+2EL2o= -github.com/miekg/dns v1.1.1/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.8 h1:1QYRAKU3lN5cRfLCkPU08hwvLJFhvjP6MqNMmQz6ZVI= -github.com/miekg/dns v1.1.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/net v0.0.0-20190119204137-ed066c81e75e h1:MDa3fSUp6MdYHouVmCCNz/zaH2a6CRcxY3VhT/K3C5Q= -golang.org/x/net v0.0.0-20190119204137-ed066c81e75e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190122071731-054c452bb702 h1:Lk4tbZFnlyPgV+sLgTw5yGfzrlOn9kx4vSombi2FFlY= -golang.org/x/sys v0.0.0-20190122071731-054c452bb702/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg= +github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/xsecretbox/doc.go b/xsecretbox/doc.go new file mode 100644 index 0000000..14af511 --- /dev/null +++ b/xsecretbox/doc.go @@ -0,0 +1,2 @@ +// Package xsecretbox implements encryption/decryption of a message using specified keys +package xsecretbox diff --git a/xsecretbox/sharedkey.go b/xsecretbox/sharedkey.go index e1bd8e5..2195296 100644 --- a/xsecretbox/sharedkey.go +++ b/xsecretbox/sharedkey.go @@ -10,10 +10,16 @@ import ( // SharedKey computes a shared secret compatible with the one used by `crypto_box_xchacha20poly1305`` func SharedKey(secretKey [32]byte, publicKey [32]byte) ([32]byte, error) { var sharedKey [32]byte - curve25519.ScalarMult(&sharedKey, &secretKey, &publicKey) + + sk, err := curve25519.X25519(secretKey[:], publicKey[:]) + if err != nil { + return sharedKey, err + } + c := byte(0) for i := 0; i < 32; i++ { - c |= sharedKey[i] + sharedKey[i] = sk[i] + c |= sk[i] } if c == 0 { return sharedKey, errors.New("weak public key") diff --git a/xsecretbox/xsecretbox.go b/xsecretbox/xsecretbox.go index 90f3eac..21b20d7 100644 --- a/xsecretbox/xsecretbox.go +++ b/xsecretbox/xsecretbox.go @@ -52,7 +52,7 @@ func Seal(out, nonce, message, key []byte) []byte { var tag [TagSize]byte hash := poly1305.New(polyKey) - hash.Write(ciphertext) + _, _ = hash.Write(ciphertext) hash.Sum(tag[:0]) copy(tagOut, tag[:]) @@ -80,7 +80,7 @@ func Open(out, nonce, box, key []byte) ([]byte, error) { var tag [TagSize]byte ciphertext := box[TagSize:] hash := poly1305.New(polyKey) - hash.Write(ciphertext) + _, _ = hash.Write(ciphertext) hash.Sum(tag[:0]) if subtle.ConstantTimeCompare(tag[:], box[:TagSize]) != 1 { return nil, errors.New("ciphertext authentication failed")