mirror of
https://github.com/SamTherapy/dnscrypt.git
synced 2024-12-22 00:50:42 +00:00
fix dependency
This commit is contained in:
parent
a12971f563
commit
227ce1fa8f
6 changed files with 178 additions and 20 deletions
13
dnscrypt.go
13
dnscrypt.go
|
@ -11,8 +11,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ameshkov/dnscrypt/xsecretbox"
|
||||
"github.com/jedisct1/go-dnsstamps"
|
||||
"github.com/jedisct1/xsecretbox"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
|
@ -51,7 +51,7 @@ const (
|
|||
// <min-query-len> is a variable length, initially set to 256 bytes, and
|
||||
// must be a multiple of 64 bytes. (see https://dnscrypt.info/protocol)
|
||||
// Some servers do not work if padded length is less than 256. Example: Quad9
|
||||
minUdpQuestionSize = 256
|
||||
minUDPQuestionSize = 256
|
||||
)
|
||||
|
||||
// Client contains parameters for a DNSCrypt client
|
||||
|
@ -198,9 +198,9 @@ func (c *Client) ExchangeConn(m *dns.Msg, s *ServerInfo, conn net.Conn) (*dns.Ms
|
|||
return nil, 0, err
|
||||
}
|
||||
} else {
|
||||
length, err := conn.Read(encryptedResponse)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
length, readErr := conn.Read(encryptedResponse)
|
||||
if readErr != nil {
|
||||
return nil, 0, readErr
|
||||
}
|
||||
encryptedResponse = encryptedResponse[:length]
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ func (s *ServerInfo) encrypt(packet []byte) (encrypted []byte, clientNonce []byt
|
|||
|
||||
minQuestionSize := queryOverhead + len(packet)
|
||||
if s.Proto == "udp" {
|
||||
minQuestionSize = max(minUdpQuestionSize, minQuestionSize)
|
||||
minQuestionSize = max(minUDPQuestionSize, minQuestionSize)
|
||||
} else {
|
||||
var xpad [1]byte
|
||||
rand.Read(xpad[:])
|
||||
|
@ -378,7 +378,6 @@ func (s *ServerInfo) decrypt(encrypted []byte, nonce []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
func txtToCertInfo(answerRr dns.RR, serverInfo *ServerInfo) (CertInfo, error) {
|
||||
|
||||
now := uint32(time.Now().Unix())
|
||||
certInfo := CertInfo{CryptoConstruction: UndefinedConstruction}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
)
|
||||
|
||||
func TestParseStamp(t *testing.T) {
|
||||
|
||||
// Google DoH
|
||||
stampStr := "sdns://AgUAAAAAAAAAAAAOZG5zLmdvb2dsZS5jb20NL2V4cGVyaW1lbnRhbA"
|
||||
stamp, err := dnsstamps.NewServerStampFromString(stampStr)
|
||||
|
@ -43,7 +42,6 @@ func TestParseStamp(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestInvalidStamp(t *testing.T) {
|
||||
|
||||
client := Client{}
|
||||
_, _, err := client.Dial("sdns://AQIAAAAAAAAAFDE")
|
||||
if err == nil {
|
||||
|
@ -52,7 +50,6 @@ func TestInvalidStamp(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTimeoutOnDialError(t *testing.T) {
|
||||
|
||||
// AdGuard DNS pointing to a wrong IP
|
||||
stampStr := "sdns://AQIAAAAAAAAADDguOC44Ljg6NTQ0MyDRK0fyUtzywrv4mRCG6vec5EldixbIoMQyLlLKPzkIcyIyLmRuc2NyeXB0LmRlZmF1bHQubnMxLmFkZ3VhcmQuY29t"
|
||||
client := Client{Timeout: 300 * time.Millisecond}
|
||||
|
@ -68,7 +65,6 @@ func TestTimeoutOnDialError(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTimeoutOnDialExchange(t *testing.T) {
|
||||
|
||||
// AdGuard DNS
|
||||
stampStr := "sdns://AQIAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20"
|
||||
client := Client{Timeout: 300 * time.Millisecond}
|
||||
|
@ -100,7 +96,6 @@ func TestTimeoutOnDialExchange(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDnsCryptResolver(t *testing.T) {
|
||||
|
||||
stamps := []struct {
|
||||
stampStr string
|
||||
}{
|
||||
|
@ -135,14 +130,14 @@ func TestDnsCryptResolver(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range stamps {
|
||||
|
||||
checkDnsCryptServer(t, test.stampStr, "")
|
||||
checkDnsCryptServer(t, test.stampStr, "tcp")
|
||||
t.Run(test.stampStr, func(t *testing.T) {
|
||||
checkDNSCryptServer(t, test.stampStr, "")
|
||||
checkDNSCryptServer(t, test.stampStr, "tcp")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func checkDnsCryptServer(t *testing.T, stampStr string, proto string) {
|
||||
|
||||
func checkDNSCryptServer(t *testing.T, stampStr string, proto string) {
|
||||
client := Client{Proto: proto, Timeout: 10 * time.Second, AdjustPayloadSize: true}
|
||||
serverInfo, rtt, err := client.Dial(stampStr)
|
||||
if err != nil {
|
||||
|
|
5
go.mod
5
go.mod
|
@ -1,10 +1,9 @@
|
|||
module github.com/ameshkov/dnscrypt
|
||||
|
||||
require (
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
|
||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da
|
||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20180418170050-1e4999280f86
|
||||
github.com/jedisct1/xsecretbox v0.0.0-20180508184500-7a679c0bcd9a
|
||||
github.com/miekg/dns v1.1.1
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9
|
||||
golang.org/x/net v0.0.0-20181213202711-891ebc4b82d6 // indirect
|
||||
|
|
24
xsecretbox/sharedkey.go
Normal file
24
xsecretbox/sharedkey.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package xsecretbox
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/aead/chacha20/chacha"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
// 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)
|
||||
c := byte(0)
|
||||
for i := 0; i < 32; i++ {
|
||||
c |= sharedKey[i]
|
||||
}
|
||||
if c == 0 {
|
||||
return sharedKey, errors.New("weak public key")
|
||||
}
|
||||
var nonce [16]byte
|
||||
chacha.HChaCha20(&sharedKey, &nonce, &sharedKey)
|
||||
return sharedKey, nil
|
||||
}
|
115
xsecretbox/xsecretbox.go
Normal file
115
xsecretbox/xsecretbox.go
Normal file
|
@ -0,0 +1,115 @@
|
|||
package xsecretbox
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
|
||||
"github.com/aead/chacha20/chacha"
|
||||
"github.com/aead/poly1305"
|
||||
)
|
||||
|
||||
const (
|
||||
// KeySize is what the name suggests
|
||||
KeySize = 32
|
||||
// NonceSize is what the name suggests
|
||||
NonceSize = 24
|
||||
// TagSize is what the name suggests
|
||||
TagSize = 16
|
||||
)
|
||||
|
||||
// Seal does what the name suggests
|
||||
func Seal(out, nonce, message, key []byte) []byte {
|
||||
if len(nonce) != NonceSize {
|
||||
panic("unsupported nonce size")
|
||||
}
|
||||
if len(key) != KeySize {
|
||||
panic("unsupported key size")
|
||||
}
|
||||
|
||||
var firstBlock [64]byte
|
||||
cipher, _ := chacha.NewCipher(nonce, key, 20)
|
||||
cipher.XORKeyStream(firstBlock[:], firstBlock[:])
|
||||
var polyKey [32]byte
|
||||
copy(polyKey[:], firstBlock[:32])
|
||||
|
||||
ret, out := sliceForAppend(out, TagSize+len(message))
|
||||
firstMessageBlock := message
|
||||
if len(firstMessageBlock) > 32 {
|
||||
firstMessageBlock = firstMessageBlock[:32]
|
||||
}
|
||||
|
||||
tagOut := out
|
||||
out = out[poly1305.TagSize:]
|
||||
for i, x := range firstMessageBlock {
|
||||
out[i] = firstBlock[32+i] ^ x
|
||||
}
|
||||
message = message[len(firstMessageBlock):]
|
||||
ciphertext := out
|
||||
out = out[len(firstMessageBlock):]
|
||||
|
||||
cipher.SetCounter(1)
|
||||
cipher.XORKeyStream(out, message)
|
||||
|
||||
var tag [TagSize]byte
|
||||
hash := poly1305.New(polyKey)
|
||||
hash.Write(ciphertext)
|
||||
hash.Sum(tag[:0])
|
||||
copy(tagOut, tag[:])
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Open does what the name suggests
|
||||
func Open(out, nonce, box, key []byte) ([]byte, error) {
|
||||
if len(nonce) != NonceSize {
|
||||
panic("unsupported nonce size")
|
||||
}
|
||||
if len(key) != KeySize {
|
||||
panic("unsupported key size")
|
||||
}
|
||||
if len(box) < TagSize {
|
||||
return nil, errors.New("ciphertext is too short")
|
||||
}
|
||||
|
||||
var firstBlock [64]byte
|
||||
cipher, _ := chacha.NewCipher(nonce, key, 20)
|
||||
cipher.XORKeyStream(firstBlock[:], firstBlock[:])
|
||||
var polyKey [32]byte
|
||||
copy(polyKey[:], firstBlock[:32])
|
||||
|
||||
var tag [TagSize]byte
|
||||
ciphertext := box[TagSize:]
|
||||
hash := poly1305.New(polyKey)
|
||||
hash.Write(ciphertext)
|
||||
hash.Sum(tag[:0])
|
||||
if subtle.ConstantTimeCompare(tag[:], box[:TagSize]) != 1 {
|
||||
return nil, errors.New("ciphertext authentication failed")
|
||||
}
|
||||
|
||||
ret, out := sliceForAppend(out, len(ciphertext))
|
||||
|
||||
firstMessageBlock := ciphertext
|
||||
if len(firstMessageBlock) > 32 {
|
||||
firstMessageBlock = firstMessageBlock[:32]
|
||||
}
|
||||
for i, x := range firstMessageBlock {
|
||||
out[i] = firstBlock[32+i] ^ x
|
||||
}
|
||||
ciphertext = ciphertext[len(firstMessageBlock):]
|
||||
out = out[len(firstMessageBlock):]
|
||||
|
||||
cipher.SetCounter(1)
|
||||
cipher.XORKeyStream(out, ciphertext)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func sliceForAppend(in []byte, n int) (head, tail []byte) {
|
||||
if total := len(in) + n; cap(in) >= total {
|
||||
head = in[:total]
|
||||
} else {
|
||||
head = make([]byte, total)
|
||||
copy(head, in)
|
||||
}
|
||||
tail = head[len(in):]
|
||||
return
|
||||
}
|
26
xsecretbox/xsecretbox_test.go
Normal file
26
xsecretbox/xsecretbox_test.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package xsecretbox
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSecretbox(t *testing.T) {
|
||||
key := [32]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}
|
||||
nonce := [24]byte{23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
|
||||
src := []byte{42, 42, 42, 42, 42, 42, 42, 42, 42, 42}
|
||||
|
||||
dst := Seal(nil, nonce[:], src[:], key[:])
|
||||
dec, err := Open(nil, nonce[:], dst[:], key[:])
|
||||
if err != nil || !bytes.Equal(src, dec) {
|
||||
t.Errorf("got %x instead of %x", dec, src)
|
||||
}
|
||||
|
||||
dst[0]++
|
||||
_, err = Open(nil, nonce[:], dst[:], key[:])
|
||||
if err == nil {
|
||||
t.Errorf("tag validation failed")
|
||||
}
|
||||
|
||||
_, _ = SharedKey(key, key)
|
||||
}
|
Loading…
Reference in a new issue