Browse Source

Increse otp digits generated by defaults

The OTP library supports just the minimum of up to 9 digits which is what is
documented in https://www.rfc-editor.org/rfc/rfc4226#section-5.3. While this is perfectly fine
for human usage, also RFC defines that this is an example and more digits should be used for
a in increased security. As our case is not human-facing, we can bump this to the maximum
size allowed by the hashing algorithm.

Credits to @aleksej-paschenko for discoverying that the gotp lib returned 0 padded strings!
Ettore Di Giacinto 2 years ago
parent
commit
54ab0fefdc
8 changed files with 59 additions and 22 deletions
  1. 3 1
      go.mod
  2. 2 2
      go.sum
  3. 31 0
      pkg/crypto/otp.go
  4. 3 4
      pkg/discovery/dht.go
  5. 4 4
      pkg/hub/hub.go
  6. 2 2
      pkg/node/connection.go
  7. 1 1
      pkg/node/node.go
  8. 13 8
      pkg/node/options.go

+ 3 - 1
go.mod

@@ -8,6 +8,7 @@ require (
 	github.com/c-robinson/iplib v1.0.3
 	github.com/c-robinson/iplib v1.0.3
 	github.com/cenkalti/backoff/v4 v4.1.3
 	github.com/cenkalti/backoff/v4 v4.1.3
 	github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
+	github.com/creachadair/otp v0.3.2
 	github.com/google/btree v1.1.2 // indirect
 	github.com/google/btree v1.1.2 // indirect
 	github.com/google/gopacket v1.1.19
 	github.com/google/gopacket v1.1.19
 	github.com/hashicorp/errwrap v1.1.0 // indirect
 	github.com/hashicorp/errwrap v1.1.0 // indirect
@@ -37,7 +38,6 @@ require (
 	github.com/urfave/cli v1.22.10
 	github.com/urfave/cli v1.22.10
 	github.com/vishvananda/netlink v1.1.0
 	github.com/vishvananda/netlink v1.1.0
 	github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
 	github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
-	github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f
 	go.uber.org/zap v1.23.0
 	go.uber.org/zap v1.23.0
 	golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
 	golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
 	golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
 	golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
@@ -46,3 +46,5 @@ require (
 )
 )
 
 
 replace github.com/elastic/gosigar => github.com/mudler/gosigar v0.14.3-0.20220502202347-34be910bdaaf
 replace github.com/elastic/gosigar => github.com/mudler/gosigar v0.14.3-0.20220502202347-34be910bdaaf
+
+replace github.com/creachadair/otp => github.com/mudler/otp v0.0.0-20221028140802-168056309dfc

+ 2 - 2
go.sum

@@ -543,6 +543,8 @@ github.com/mudler/go-processmanager v0.0.0-20220724164624-c45b5c61312d h1:/lAg9v
 github.com/mudler/go-processmanager v0.0.0-20220724164624-c45b5c61312d/go.mod h1:HGGAOJhipApckwNV8ZTliRJqxctUv3xRY+zbQEwuytc=
 github.com/mudler/go-processmanager v0.0.0-20220724164624-c45b5c61312d/go.mod h1:HGGAOJhipApckwNV8ZTliRJqxctUv3xRY+zbQEwuytc=
 github.com/mudler/gosigar v0.14.3-0.20220502202347-34be910bdaaf h1:hNa6C3a7+14a2qwMkYZbq94ddebYc8CloF2KOVytf+A=
 github.com/mudler/gosigar v0.14.3-0.20220502202347-34be910bdaaf h1:hNa6C3a7+14a2qwMkYZbq94ddebYc8CloF2KOVytf+A=
 github.com/mudler/gosigar v0.14.3-0.20220502202347-34be910bdaaf/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
 github.com/mudler/gosigar v0.14.3-0.20220502202347-34be910bdaaf/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
+github.com/mudler/otp v0.0.0-20221028140802-168056309dfc h1:J7yENI2ZTlOOg+8Bkxd1jkgXJkwSgDWh1PkBBfYJkOI=
+github.com/mudler/otp v0.0.0-20221028140802-168056309dfc/go.mod h1:mDkCUSoWN8zqxFoDMw20Boe6xeDd1jJuy6pNQQ4lCy4=
 github.com/mudler/water v0.0.0-20221010214108-8c7313014ce0 h1:Qh6ghkMgTu6siFbTf7L3IszJmshMhXxNL4V+t7IIA6w=
 github.com/mudler/water v0.0.0-20221010214108-8c7313014ce0 h1:Qh6ghkMgTu6siFbTf7L3IszJmshMhXxNL4V+t7IIA6w=
 github.com/mudler/water v0.0.0-20221010214108-8c7313014ce0/go.mod h1:nViSE8jcOcraZwhi34joEqn7HYFISgs0M8/YujzY5Xk=
 github.com/mudler/water v0.0.0-20221010214108-8c7313014ce0/go.mod h1:nViSE8jcOcraZwhi34joEqn7HYFISgs0M8/YujzY5Xk=
 github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
 github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
@@ -773,8 +775,6 @@ github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1
 github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow=
 github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow=
 github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg=
 github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg=
 github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
 github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
-github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f h1:C8De+7emQKojPBC+mXA0fr39XN5mKjRm9IUzdxI4whI=
-github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

+ 31 - 0
pkg/crypto/otp.go

@@ -0,0 +1,31 @@
+/*
+Copyright © 2022 Ettore Di Giacinto <[email protected]>
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+    http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package crypto
+
+import (
+	"hash"
+
+	"github.com/creachadair/otp"
+)
+
+func TOTP(f func() hash.Hash, digits int, t int, key string) string {
+	cfg := otp.Config{
+		Hash:     f,      // default is sha1.New
+		Digits:   digits, // default is 6
+		TimeStep: otp.TimeWindow(t),
+		Key:      key,
+		NoTrunc:  true,
+	}
+	return cfg.TOTP()
+}

+ 3 - 4
pkg/discovery/dht.go

@@ -15,6 +15,7 @@ package discovery
 
 
 import (
 import (
 	"context"
 	"context"
+	"crypto/sha256"
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
@@ -29,7 +30,6 @@ import (
 	"github.com/libp2p/go-libp2p/core/peer"
 	"github.com/libp2p/go-libp2p/core/peer"
 	"github.com/libp2p/go-libp2p/core/routing"
 	"github.com/libp2p/go-libp2p/core/routing"
 	discovery "github.com/libp2p/go-libp2p/p2p/discovery/routing"
 	discovery "github.com/libp2p/go-libp2p/p2p/discovery/routing"
-	"github.com/xlzd/gotp"
 )
 )
 
 
 type DHT struct {
 type DHT struct {
@@ -56,10 +56,9 @@ func (d *DHT) Option(ctx context.Context) func(c *libp2p.Config) error {
 }
 }
 func (d *DHT) Rendezvous() string {
 func (d *DHT) Rendezvous() string {
 	if d.OTPKey != "" {
 	if d.OTPKey != "" {
-		totp := gotp.NewTOTP(d.OTPKey, d.KeyLength, d.OTPInterval, nil)
+		totp := internalCrypto.TOTP(sha256.New, d.KeyLength, d.OTPInterval, d.OTPKey)
 
 
-		//totp := gotp.NewDefaultTOTP(d.OTPKey)
-		rv := internalCrypto.MD5(totp.Now())
+		rv := internalCrypto.MD5(totp)
 		d.latestRendezvous = rv
 		d.latestRendezvous = rv
 		return rv
 		return rv
 	}
 	}

+ 4 - 4
pkg/hub/hub.go

@@ -17,13 +17,13 @@ package hub
 
 
 import (
 import (
 	"context"
 	"context"
+	"crypto/sha256"
 	"errors"
 	"errors"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
 	"github.com/mudler/edgevpn/pkg/crypto"
 	"github.com/mudler/edgevpn/pkg/crypto"
-	"github.com/xlzd/gotp"
 
 
 	pubsub "github.com/libp2p/go-libp2p-pubsub"
 	pubsub "github.com/libp2p/go-libp2p-pubsub"
 	"github.com/libp2p/go-libp2p/core/host"
 	"github.com/libp2p/go-libp2p/core/host"
@@ -54,11 +54,11 @@ func NewHub(otp string, maxsize, keyLength, interval int, joinPublic bool) *Mess
 }
 }
 
 
 func (m *MessageHub) topicKey(salts ...string) string {
 func (m *MessageHub) topicKey(salts ...string) string {
-	totp := gotp.NewTOTP(strings.ToUpper(m.otpKey), m.keyLength, m.interval, nil)
+	totp := crypto.TOTP(sha256.New, m.keyLength, m.interval, m.otpKey)
 	if len(salts) > 0 {
 	if len(salts) > 0 {
-		return crypto.MD5(totp.Now() + strings.Join(salts, ":"))
+		return crypto.MD5(totp + strings.Join(salts, ":"))
 	}
 	}
-	return crypto.MD5(totp.Now())
+	return crypto.MD5(totp)
 }
 }
 
 
 func (m *MessageHub) joinRoom(host host.Host) error {
 func (m *MessageHub) joinRoom(host host.Host) error {

+ 2 - 2
pkg/node/connection.go

@@ -16,6 +16,7 @@ package node
 import (
 import (
 	"context"
 	"context"
 	"crypto/rand"
 	"crypto/rand"
+	"crypto/sha256"
 	"io"
 	"io"
 	mrand "math/rand"
 	mrand "math/rand"
 	"net"
 	"net"
@@ -29,7 +30,6 @@ import (
 	conngater "github.com/libp2p/go-libp2p/p2p/net/conngater"
 	conngater "github.com/libp2p/go-libp2p/p2p/net/conngater"
 	hub "github.com/mudler/edgevpn/pkg/hub"
 	hub "github.com/mudler/edgevpn/pkg/hub"
 	multiaddr "github.com/multiformats/go-multiaddr"
 	multiaddr "github.com/multiformats/go-multiaddr"
-	"github.com/xlzd/gotp"
 )
 )
 
 
 // Host returns the libp2p peer host
 // Host returns the libp2p peer host
@@ -115,7 +115,7 @@ func (e *Node) genHost(ctx context.Context) (host.Host, error) {
 }
 }
 
 
 func (e *Node) sealkey() string {
 func (e *Node) sealkey() string {
-	return internalCrypto.MD5(gotp.NewTOTP(e.config.ExchangeKey, e.config.SealKeyLength, e.config.SealKeyInterval, nil).Now())
+	return internalCrypto.MD5(internalCrypto.TOTP(sha256.New, e.config.SealKeyLength, e.config.SealKeyInterval, e.config.ExchangeKey))
 }
 }
 
 
 func (e *Node) handleEvents(ctx context.Context, inputChannel chan *hub.Message, roomMessages chan *hub.Message, pub func(*hub.Message) error, handlers []Handler, peerGater bool) {
 func (e *Node) handleEvents(ctx context.Context, inputChannel chan *hub.Message, roomMessages chan *hub.Message, pub func(*hub.Message) error, handlers []Handler, peerGater bool) {

+ 1 - 1
pkg/node/node.go

@@ -61,7 +61,7 @@ func New(p ...Option) (*Node, error) {
 		StreamHandlers:           make(map[protocol.Protocol]StreamHandler),
 		StreamHandlers:           make(map[protocol.Protocol]StreamHandler),
 		LedgerAnnounceTime:       5 * time.Second,
 		LedgerAnnounceTime:       5 * time.Second,
 		LedgerSyncronizationTime: 5 * time.Second,
 		LedgerSyncronizationTime: 5 * time.Second,
-		SealKeyLength:            12,
+		SealKeyLength:            defaultKeyLength,
 		Options:                  defaultLibp2pOptions,
 		Options:                  defaultLibp2pOptions,
 		Logger:                   logger.New(log.LevelDebug),
 		Logger:                   logger.New(log.LevelDebug),
 		Sealer:                   &crypto.AESSealer{},
 		Sealer:                   &crypto.AESSealer{},

+ 13 - 8
pkg/node/options.go

@@ -25,7 +25,6 @@ import (
 	"github.com/mudler/edgevpn/pkg/protocol"
 	"github.com/mudler/edgevpn/pkg/protocol"
 	"github.com/mudler/edgevpn/pkg/utils"
 	"github.com/mudler/edgevpn/pkg/utils"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
-	"github.com/xlzd/gotp"
 	"gopkg.in/yaml.v2"
 	"gopkg.in/yaml.v2"
 )
 )
 
 
@@ -286,12 +285,18 @@ func (y YAMLConnectionConfig) copy(mdns, dht bool, cfg *Config, d *discovery.DHT
 	cfg.MaxMessageSize = y.MaxMessageSize
 	cfg.MaxMessageSize = y.MaxMessageSize
 }
 }
 
 
-const defaultKeyLength = 32
+const defaultKeyLength = 43
 
 
 func GenerateNewConnectionData(i ...int) *YAMLConnectionConfig {
 func GenerateNewConnectionData(i ...int) *YAMLConnectionConfig {
 	defaultInterval := 9000
 	defaultInterval := 9000
 	maxMessSize := 20 << 20 // 20MB
 	maxMessSize := 20 << 20 // 20MB
-	if len(i) >= 2 {
+	keyLength := defaultKeyLength
+
+	if len(i) >= 3 {
+		keyLength = i[2]
+		defaultInterval = i[0]
+		maxMessSize = i[1]
+	} else if len(i) >= 2 {
 		defaultInterval = i[0]
 		defaultInterval = i[0]
 		maxMessSize = i[1]
 		maxMessSize = i[1]
 	} else if len(i) == 1 {
 	} else if len(i) == 1 {
@@ -300,17 +305,17 @@ func GenerateNewConnectionData(i ...int) *YAMLConnectionConfig {
 
 
 	return &YAMLConnectionConfig{
 	return &YAMLConnectionConfig{
 		MaxMessageSize: maxMessSize,
 		MaxMessageSize: maxMessSize,
-		RoomName:       gotp.RandomSecret(defaultKeyLength),
-		Rendezvous:     utils.RandStringRunes(defaultKeyLength),
-		MDNS:           utils.RandStringRunes(defaultKeyLength),
+		RoomName:       utils.RandStringRunes(keyLength),
+		Rendezvous:     utils.RandStringRunes(keyLength),
+		MDNS:           utils.RandStringRunes(keyLength),
 		OTP: OTP{
 		OTP: OTP{
 			DHT: OTPConfig{
 			DHT: OTPConfig{
-				Key:      gotp.RandomSecret(defaultKeyLength),
+				Key:      utils.RandStringRunes(keyLength),
 				Interval: defaultInterval,
 				Interval: defaultInterval,
 				Length:   defaultKeyLength,
 				Length:   defaultKeyLength,
 			},
 			},
 			Crypto: OTPConfig{
 			Crypto: OTPConfig{
-				Key:      gotp.RandomSecret(defaultKeyLength),
+				Key:      utils.RandStringRunes(keyLength),
 				Interval: defaultInterval,
 				Interval: defaultInterval,
 				Length:   defaultKeyLength,
 				Length:   defaultKeyLength,
 			},
 			},