From 9934a856ddb1d0a4b3dd24fbf8cdd796bcbd3cc1 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sat, 21 Sep 2019 12:54:45 -0700 Subject: [PATCH] More go --- one.cpp => attic/one.cpp | 0 go/go.mod | 5 +- go/go.sum | 7 --- go/pkg/zerotier/errors.go | 1 + go/pkg/zerotier/identity.go | 113 ++++++++--------------------------- go/pkg/zerotier/nativetap.go | 2 - go/pkg/zerotier/node.go | 2 +- 7 files changed, 29 insertions(+), 101 deletions(-) rename one.cpp => attic/one.cpp (100%) diff --git a/one.cpp b/attic/one.cpp similarity index 100% rename from one.cpp rename to attic/one.cpp diff --git a/go/go.mod b/go/go.mod index bd0aaff0..8c49ab48 100644 --- a/go/go.mod +++ b/go/go.mod @@ -2,7 +2,4 @@ module zerotier go 1.13 -require ( - github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 - golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 -) +require github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 diff --git a/go/go.sum b/go/go.sum index 56484479..ad7bf1bb 100644 --- a/go/go.sum +++ b/go/go.sum @@ -1,11 +1,4 @@ github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 h1:S4qyfL2sEm5Budr4KVMyEniCy+PbS55651I/a+Kn/NQ= github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95/go.mod h1:QiyDdbZLaJ/mZP4Zwc9g2QsfaEA4o7XvvgZegSci5/E= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -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-20190529164535-6a60838ec259 h1:so6Hr/LodwSZ5UQDu/7PmQiDeS112WwtLvU3lpSPZTU= golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/go/pkg/zerotier/errors.go b/go/pkg/zerotier/errors.go index 54c4772f..54cf7608 100644 --- a/go/pkg/zerotier/errors.go +++ b/go/pkg/zerotier/errors.go @@ -26,4 +26,5 @@ const ( ErrInvalidParameter Err = "invalid parameter" ErrTapInitFailed Err = "unable to create native Tap instance" ErrUncrecognizedIdentityType Err = "unrecognized identity type" + ErrInvalidKey Err = "invalid key data" ) diff --git a/go/pkg/zerotier/identity.go b/go/pkg/zerotier/identity.go index 7eaaf961..f31c4b51 100644 --- a/go/pkg/zerotier/identity.go +++ b/go/pkg/zerotier/identity.go @@ -14,77 +14,25 @@ package zerotier import ( - secrand "crypto/rand" - "crypto/sha512" - "encoding/binary" + "encoding/base32" "encoding/hex" "fmt" "strings" - - "golang.org/x/crypto/salsa20/salsa" - - "golang.org/x/crypto/curve25519" - - "golang.org/x/crypto/ed25519" ) -const ztIdentityGenMemory = 2097152 -const ztIdentityHashCashFirstByteLessThan = 17 - // IdentityTypeC25519 is a classic Curve25519/Ed25519 identity const IdentityTypeC25519 = 0 // IdentityTypeP384 is an identity containing both NIST P-384 and Curve25519/Ed25519 key types and leveraging both when possible const IdentityTypeP384 = 1 -func computeZeroTierIdentityMemoryHardHash(publicKey []byte) []byte { - s512 := sha512.Sum512(publicKey) - - var genmem [ztIdentityGenMemory]byte - var s20key [32]byte - var s20ctr [16]byte - var s20ctri uint64 - copy(s20key[:], s512[0:32]) - copy(s20ctr[0:8], s512[32:40]) - salsa.XORKeyStream(genmem[0:64], genmem[0:64], &s20ctr, &s20key) - s20ctri++ - for i := 64; i < ztIdentityGenMemory; i += 64 { - binary.LittleEndian.PutUint64(s20ctr[8:16], s20ctri) - salsa.XORKeyStream(genmem[i:i+64], genmem[i-64:i], &s20ctr, &s20key) - s20ctri++ - } - - var tmp [8]byte - for i := 0; i < ztIdentityGenMemory; { - idx1 := uint(binary.BigEndian.Uint64(genmem[i:])&7) * 8 - i += 8 - idx2 := (uint(binary.BigEndian.Uint64(genmem[i:])) % uint(ztIdentityGenMemory/8)) * 8 - i += 8 - gm := genmem[idx2 : idx2+8] - d := s512[idx1 : idx1+8] - copy(tmp[:], gm) - copy(gm, d) - copy(d, tmp[:]) - binary.LittleEndian.PutUint64(s20ctr[8:16], s20ctri) - salsa.XORKeyStream(s512[:], s512[:], &s20ctr, &s20key) - s20ctri++ - } - - return s512[:] -} - -// generateDualPair generates a key pair containing two pairs: one for curve25519 and one for ed25519. -func generateDualPair() (pub [64]byte, priv [64]byte) { - k0pub, k0priv, _ := ed25519.GenerateKey(secrand.Reader) - var k1pub, k1priv [32]byte - secrand.Read(k1priv[:]) - curve25519.ScalarBaseMult(&k1pub, &k1priv) - copy(pub[0:32], k1pub[:]) - copy(pub[32:64], k0pub[0:32]) - copy(priv[0:32], k1priv[:]) - copy(priv[32:64], k0priv[0:32]) - return -} +// Sizes of components of different identity types +const ( + IdentityTypeC25519PublicKeySize = 64 // C25519/Ed25519 keys + IdentityTypeC25519PrivateKeySize = 64 // C25519/Ed25519 private keys + IdentityTypeP384PublicKeySize = 209 // C25519/Ed25519, P-384 point-compressed public, P-384 self-signature + IdentityTypeP384PrivateKeySize = 112 // C25519/Ed25519 and P-384 private keys +) // Identity is precisely what it sounds like: the address and associated keys for a ZeroTier node type Identity struct { @@ -100,33 +48,6 @@ type Identity struct { privateKey []byte } -// NewIdentity generates a new ZeroTier Identity. -// This can be a little bit time consuming due to one way proof of work requirements (usually a few hundred milliseconds). -func NewIdentity() (id Identity) { - for { - pub, priv := generateDualPair() - dig := computeZeroTierIdentityMemoryHardHash(pub[:]) - if dig[0] < ztIdentityHashCashFirstByteLessThan && dig[59] != 0xff { - addr := uint64(dig[59]) - addr <<= 8 - addr |= uint64(dig[60]) - addr <<= 8 - addr |= uint64(dig[61]) - addr <<= 8 - addr |= uint64(dig[62]) - addr <<= 8 - addr |= uint64(dig[63]) - if addr != 0 { - id.Address = Address(addr) - id.PublicKey = pub[:] - id.privateKey = priv[:] - break - } - } - } - return -} - // NewIdentityFromString generates a new identity from its string representation. // The private key is imported as well if it is present. func NewIdentityFromString(s string) (*Identity, error) { @@ -151,6 +72,7 @@ func NewIdentityFromString(s string) (*Identity, error) { } switch id.Type { + case 0: id.PublicKey, err = hex.DecodeString(ss[2]) if err != nil { @@ -162,7 +84,24 @@ func NewIdentityFromString(s string) (*Identity, error) { return nil, err } } + case 1: + id.PublicKey, err = base32.StdEncoding.DecodeString(ss[2]) + if err != nil { + return nil, err + } + if len(id.PublicKey) != IdentityTypeP384PublicKeySize { + return nil, ErrInvalidKey + } + if len(ss) >= 4 { + id.privateKey, err = base32.StdEncoding.DecodeString(ss[3]) + if err != nil { + return nil, err + } + if len(id.privateKey) != IdentityTypeP384PrivateKeySize { + return nil, ErrInvalidKey + } + } } diff --git a/go/pkg/zerotier/nativetap.go b/go/pkg/zerotier/nativetap.go index 83e8050d..e870902b 100644 --- a/go/pkg/zerotier/nativetap.go +++ b/go/pkg/zerotier/nativetap.go @@ -38,8 +38,6 @@ type nativeTap struct { multicastGroupHandlersLock sync.Mutex } -var _ Tap = &nativeTap{} - // Type returns a human-readable description of this tap implementation func (t *nativeTap) Type() string { return "native" diff --git a/go/pkg/zerotier/node.go b/go/pkg/zerotier/node.go index c36529cb..ae8f6ee0 100644 --- a/go/pkg/zerotier/node.go +++ b/go/pkg/zerotier/node.go @@ -49,7 +49,7 @@ const ( ////////////////////////////////////////////////////////////////////////////// -// Node is an instance of a ZeroTier node +// Node represents an instance of the ZeroTier core node and related C++ I/O code type Node struct { path string networks map[uint64]*Network