private/server,satellite/contact,misc: use new storj/common noise helpers

this change uses the new storj/common noise helpers, which:
 * add a security fix (require an expected node id for validating
   noise key attestations)
 * stops doing an unnecessary order signature validation (it's
   already been done inside of PutPiece)
 * removes some duplicate code

Change-Id: I5e67a08ff216cd9c5b0b82e40b4d9de664b6b0fc
This commit is contained in:
JT Olio 2023-02-02 17:43:57 -05:00 committed by JT Olio
parent dcebcf770d
commit 522aed083d
15 changed files with 42 additions and 388 deletions

6
go.mod
View File

@ -9,7 +9,6 @@ require (
github.com/calebcase/tmpfile v1.0.3 github.com/calebcase/tmpfile v1.0.3
github.com/cheggaaa/pb/v3 v3.0.5 github.com/cheggaaa/pb/v3 v3.0.5
github.com/fatih/color v1.9.0 github.com/fatih/color v1.9.0
github.com/flynn/noise v1.0.0
github.com/go-oauth2/oauth2/v4 v4.4.2 github.com/go-oauth2/oauth2/v4 v4.4.2
github.com/go-redis/redis/v8 v8.11.5 github.com/go-redis/redis/v8 v8.11.5
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
@ -39,7 +38,6 @@ require (
github.com/stripe/stripe-go/v72 v72.51.0 github.com/stripe/stripe-go/v72 v72.51.0
github.com/vivint/infectious v0.0.0-20200605153912-25a574ae18a3 github.com/vivint/infectious v0.0.0-20200605153912-25a574ae18a3
github.com/zeebo/assert v1.3.1 github.com/zeebo/assert v1.3.1
github.com/zeebo/blake3 v0.2.3
github.com/zeebo/clingy v0.0.0-20220926155919-717640cb8ccd github.com/zeebo/clingy v0.0.0-20220926155919-717640cb8ccd
github.com/zeebo/errs v1.3.0 github.com/zeebo/errs v1.3.0
github.com/zeebo/ini v0.0.0-20210331155437-86af75b4f524 github.com/zeebo/ini v0.0.0-20210331155437-86af75b4f524
@ -55,7 +53,7 @@ require (
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
gopkg.in/segmentio/analytics-go.v3 v3.1.0 gopkg.in/segmentio/analytics-go.v3 v3.1.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
storj.io/common v0.0.0-20230203132517-db6195f39c0d storj.io/common v0.0.0-20230207140859-1c86f3de8c15
storj.io/drpc v0.0.32 storj.io/drpc v0.0.32
storj.io/monkit-jaeger v0.0.0-20220915074555-d100d7589f41 storj.io/monkit-jaeger v0.0.0-20220915074555-d100d7589f41
storj.io/private v0.0.0-20230123202745-d3e63b336444 storj.io/private v0.0.0-20230123202745-d3e63b336444
@ -74,6 +72,7 @@ require (
github.com/cloudfoundry/gosigar v1.1.0 // indirect github.com/cloudfoundry/gosigar v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/golang-jwt/jwt v3.2.1+incompatible // indirect github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
@ -116,6 +115,7 @@ require (
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb // indirect github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb // indirect
github.com/zeebo/admission/v3 v3.0.3 // indirect github.com/zeebo/admission/v3 v3.0.3 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
github.com/zeebo/errs/v2 v2.0.3 // indirect github.com/zeebo/errs/v2 v2.0.3 // indirect
github.com/zeebo/float16 v0.1.0 // indirect github.com/zeebo/float16 v0.1.0 // indirect
github.com/zeebo/incenc v0.0.0-20180505221441-0d92902eec54 // indirect github.com/zeebo/incenc v0.0.0-20180505221441-0d92902eec54 // indirect

4
go.sum
View File

@ -960,8 +960,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
storj.io/common v0.0.0-20220719163320-cd2ef8e1b9b0/go.mod h1:mCYV6Ud5+cdbuaxdPD5Zht/HYaIn0sffnnws9ErkrMQ= storj.io/common v0.0.0-20220719163320-cd2ef8e1b9b0/go.mod h1:mCYV6Ud5+cdbuaxdPD5Zht/HYaIn0sffnnws9ErkrMQ=
storj.io/common v0.0.0-20230203132517-db6195f39c0d h1:YXUKpQExPezrMlUn05Zu1ydLGYDwcU1eyMkxDgsfwI0= storj.io/common v0.0.0-20230207140859-1c86f3de8c15 h1:zxniPpRV4V0e4UwYkJgLHik1ZeslbXt136Y04ms1G1s=
storj.io/common v0.0.0-20230203132517-db6195f39c0d/go.mod h1:oNPn8QmwPRXSGWwHoMFLGi9c+vOYbGmRYQQ/IhZi4lM= storj.io/common v0.0.0-20230207140859-1c86f3de8c15/go.mod h1:i5P+zXit50yn4GUHvjET+rJX/uB9S56EISpyaTOVkrE=
storj.io/drpc v0.0.32 h1:5p5ZwsK/VOgapaCu+oxaPVwO6UwIs+iwdMiD50+R4PI= storj.io/drpc v0.0.32 h1:5p5ZwsK/VOgapaCu+oxaPVwO6UwIs+iwdMiD50+R4PI=
storj.io/drpc v0.0.32/go.mod h1:6rcOyR/QQkSTX/9L5ZGtlZaE2PtXTTZl8d+ulSeeYEg= storj.io/drpc v0.0.32/go.mod h1:6rcOyR/QQkSTX/9L5ZGtlZaE2PtXTTZl8d+ulSeeYEg=
storj.io/monkit-jaeger v0.0.0-20220915074555-d100d7589f41 h1:SVuEocEhZfFc13J1AmlVLitdGXTVrvmbzN4Z9C9Ms40= storj.io/monkit-jaeger v0.0.0-20220915074555-d100d7589f41 h1:SVuEocEhZfFc13J1AmlVLitdGXTVrvmbzN4Z9C9Ms40=

View File

@ -1,131 +0,0 @@
// Copyright (C) 2022 Storj Labs, Inc.
// See LICENSE for copying information.
package server
import (
"context"
"crypto/subtle"
"encoding/binary"
"time"
"github.com/flynn/noise"
"storj.io/common/identity"
"storj.io/common/pb"
"storj.io/common/signing"
)
// NoiseHeader is the drpcmigrate.Header prefix for DRPC over Noise.
const NoiseHeader = "DRPC!N!1"
// defaultNoiseProto is the protobuf enum value that specifies what noise
// protocol is in use.
// defaultNoiseInfo and defaultNoiseConfig should be changed together.
var defaultNoiseProto = pb.NoiseProtocol_NOISE_IK_25519_CHACHAPOLY_BLAKE2B
// defaultNoiseConfig returns the structure that tells this node what Noise
// settings to use.
// defaultNoiseProto and defaultNoiseConfig should be changed together.
func defaultNoiseConfig() noise.Config {
return noise.Config{
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashBLAKE2b),
Pattern: noise.HandshakeIK,
}
}
func signableNoisePublicKey(ts time.Time, key []byte) []byte {
var buf [8]byte
tsnano := ts.UnixNano()
if tsnano < 0 {
tsnano = 0
}
binary.BigEndian.PutUint64(buf[:], uint64(tsnano))
return append(buf[:], key...)
}
// GenerateNoiseKeyAttestation will sign a given Noise public key using the
// Node's leaf key and certificate chain, generating a pb.NoiseKeyAttestation.
func GenerateNoiseKeyAttestation(ctx context.Context, ident *identity.FullIdentity, info *pb.NoiseInfo) (_ *pb.NoiseKeyAttestation, err error) {
defer mon.Task()(&ctx)(&err)
ts := time.Now()
signature, err := signing.SignerFromFullIdentity(ident).HashAndSign(ctx,
append([]byte("noise-key-attestation-v1:"), signableNoisePublicKey(ts, info.PublicKey)...))
if err != nil {
return nil, Error.Wrap(err)
}
return &pb.NoiseKeyAttestation{
NodeId: ident.ID,
NodeCertchain: identity.EncodePeerIdentity(ident.PeerIdentity()),
NoiseProto: info.Proto,
NoisePublicKey: info.PublicKey,
Timestamp: ts,
Signature: signature,
}, nil
}
// ValidateNoiseKeyAttestation will confirm that a provided
// *pb.NoiseKeyAttestation was signed correctly.
func ValidateNoiseKeyAttestation(ctx context.Context, attestation *pb.NoiseKeyAttestation) (err error) {
defer mon.Task()(&ctx)(&err)
peer, err := identity.DecodePeerIdentity(ctx, attestation.NodeCertchain)
if err != nil {
return Error.Wrap(err)
}
err = peer.Leaf.CheckSignatureFrom(peer.CA)
if err != nil {
return Error.New("certificate chain invalid: %w", err)
}
if subtle.ConstantTimeCompare(peer.ID.Bytes(), attestation.NodeId.Bytes()) != 1 {
return Error.New("node id mismatch")
}
signee := signing.SigneeFromPeerIdentity(peer)
unsigned := signableNoisePublicKey(attestation.Timestamp, attestation.NoisePublicKey)
err = signee.HashAndVerifySignature(ctx,
append([]byte("noise-key-attestation-v1:"), unsigned...),
attestation.Signature)
return Error.Wrap(err)
}
// GenerateNoiseSessionAttestation will sign a given Noise session handshake
// hash using the Node's leaf key and certificate chain, generating a
// pb.NoiseSessionAttestation.
func GenerateNoiseSessionAttestation(ctx context.Context, ident *identity.FullIdentity, handshakeHash []byte) (_ *pb.NoiseSessionAttestation, err error) {
defer mon.Task()(&ctx)(&err)
signature, err := signing.SignerFromFullIdentity(ident).HashAndSign(ctx,
append([]byte("noise-session-attestation-v1:"), handshakeHash...))
if err != nil {
return nil, Error.Wrap(err)
}
return &pb.NoiseSessionAttestation{
NodeId: ident.ID,
NodeCertchain: identity.EncodePeerIdentity(ident.PeerIdentity()),
NoiseHandshakeHash: handshakeHash,
Signature: signature,
}, nil
}
// ValidateNoiseSessionAttestation will confirm that a provided
// *pb.NoiseSessionAttestation was signed correctly.
func ValidateNoiseSessionAttestation(ctx context.Context, attestation *pb.NoiseSessionAttestation) (err error) {
defer mon.Task()(&ctx)(&err)
peer, err := identity.DecodePeerIdentity(ctx, attestation.NodeCertchain)
if err != nil {
return Error.Wrap(err)
}
err = peer.Leaf.CheckSignatureFrom(peer.CA)
if err != nil {
return Error.New("certificate chain invalid: %w", err)
}
if subtle.ConstantTimeCompare(peer.ID.Bytes(), attestation.NodeId.Bytes()) != 1 {
return Error.New("node id mismatch")
}
signee := signing.SigneeFromPeerIdentity(peer)
err = signee.HashAndVerifySignature(ctx,
append([]byte("noise-session-attestation-v1:"), attestation.NoiseHandshakeHash...),
attestation.Signature)
return Error.Wrap(err)
}

View File

@ -1,117 +0,0 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
package server
import (
"crypto/rand"
"testing"
"time"
"github.com/stretchr/testify/require"
"storj.io/common/identity"
"storj.io/common/pb"
"storj.io/common/storj"
"storj.io/common/testcontext"
)
func TestNoiseKeyAttestation(t *testing.T) {
ctx := testcontext.New(t)
ident, err := identity.NewFullIdentity(ctx, identity.NewCAOptions{})
require.NoError(t, err)
ident2, err := identity.NewFullIdentity(ctx, identity.NewCAOptions{})
require.NoError(t, err)
ident3, err := identity.NewFullIdentity(ctx, identity.NewCAOptions{})
require.NoError(t, err)
noiseCfg, err := generateNoiseConf(ident)
require.NoError(t, err)
attestation, err := GenerateNoiseKeyAttestation(ctx, ident, &pb.NoiseInfo{
Proto: defaultNoiseProto,
PublicKey: noiseCfg.StaticKeypair.Public,
})
require.NoError(t, err)
require.NoError(t, ValidateNoiseKeyAttestation(ctx, attestation))
badAttestation1 := *attestation
badAttestation1.NodeId, err = storj.NodeIDFromString("121RTSDpyNZVcEU84Ticf2L1ntiuUimbWgfATz21tuvgk3vzoA6")
require.NoError(t, err)
err = ValidateNoiseKeyAttestation(ctx, &badAttestation1)
require.Error(t, err)
require.Contains(t, err.Error(), "node id mismatch")
badAttestation2 := *attestation
badAttestation2.NoisePublicKey = badAttestation2.NoisePublicKey[:len(badAttestation2.NoisePublicKey)-1]
err = ValidateNoiseKeyAttestation(ctx, &badAttestation2)
require.Error(t, err)
require.Contains(t, err.Error(), "signature is not valid")
badAttestation3 := *attestation
badAttestation3.Timestamp = time.Now()
err = ValidateNoiseKeyAttestation(ctx, &badAttestation3)
require.Error(t, err)
require.Contains(t, err.Error(), "signature is not valid")
ident2.CA = ident.CA
badAttestation4 := *attestation
badAttestation4.NodeCertchain = identity.EncodePeerIdentity(ident2.PeerIdentity())
err = ValidateNoiseKeyAttestation(ctx, &badAttestation4)
require.Error(t, err)
require.Contains(t, err.Error(), "certificate chain invalid")
ident3.Leaf = ident.Leaf
badAttestation5 := *attestation
badAttestation5.NodeCertchain = identity.EncodePeerIdentity(ident3.PeerIdentity())
err = ValidateNoiseKeyAttestation(ctx, &badAttestation5)
require.Error(t, err)
require.Contains(t, err.Error(), "certificate chain invalid")
}
func TestNoiseSessionAttestation(t *testing.T) {
ctx := testcontext.New(t)
ident, err := identity.NewFullIdentity(ctx, identity.NewCAOptions{})
require.NoError(t, err)
ident2, err := identity.NewFullIdentity(ctx, identity.NewCAOptions{})
require.NoError(t, err)
ident3, err := identity.NewFullIdentity(ctx, identity.NewCAOptions{})
require.NoError(t, err)
var hash [32]byte
_, err = rand.Read(hash[:])
require.NoError(t, err)
attestation, err := GenerateNoiseSessionAttestation(ctx, ident, hash[:])
require.NoError(t, err)
require.NoError(t, ValidateNoiseSessionAttestation(ctx, attestation))
badAttestation1 := *attestation
badAttestation1.NodeId, err = storj.NodeIDFromString("121RTSDpyNZVcEU84Ticf2L1ntiuUimbWgfATz21tuvgk3vzoA6")
require.NoError(t, err)
err = ValidateNoiseSessionAttestation(ctx, &badAttestation1)
require.Error(t, err)
require.Contains(t, err.Error(), "node id mismatch")
badAttestation2 := *attestation
badAttestation2.NoiseHandshakeHash = badAttestation2.NoiseHandshakeHash[:len(badAttestation2.NoiseHandshakeHash)-1]
err = ValidateNoiseSessionAttestation(ctx, &badAttestation2)
require.Error(t, err)
require.Contains(t, err.Error(), "signature is not valid")
ident2.CA = ident.CA
badAttestation3 := *attestation
badAttestation3.NodeCertchain = identity.EncodePeerIdentity(ident2.PeerIdentity())
err = ValidateNoiseSessionAttestation(ctx, &badAttestation3)
require.Error(t, err)
require.Contains(t, err.Error(), "certificate chain invalid")
ident3.Leaf = ident.Leaf
badAttestation4 := *attestation
badAttestation4.NodeCertchain = identity.EncodePeerIdentity(ident3.PeerIdentity())
err = ValidateNoiseSessionAttestation(ctx, &badAttestation4)
require.Error(t, err)
require.Contains(t, err.Error(), "certificate chain invalid")
}

View File

@ -1,51 +0,0 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
package server
import (
"github.com/zeebo/errs"
"storj.io/common/pb"
"storj.io/drpc"
)
type replayRouter struct {
replaySafe, all drpc.Mux
}
func newReplayRouter(replaySafe, all drpc.Mux) drpc.Mux {
return &replayRouter{
replaySafe: replaySafe,
all: all,
}
}
// Register implements drpc.Mux.
func (r *replayRouter) Register(srv interface{}, desc drpc.Description) error {
allErr := r.all.Register(srv, desc)
switch desc.(type) {
case pb.DRPCPiecestoreDescription:
return errs.Combine(allErr, r.replaySafe.Register(srv, replaySafePiecestore{}))
default:
return allErr
}
}
type replaySafePiecestore struct{}
func (replaySafePiecestore) NumMethods() int { return 2 }
func (replaySafePiecestore) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
switch n {
case 0:
rpc, enc, receiver, method, ok := (pb.DRPCPiecestoreDescription{}).Method(0)
return rpc, enc, receiver, method, ok && rpc == "/piecestore.Piecestore/Upload"
case 1:
rpc, enc, receiver, method, ok := (pb.DRPCPiecestoreDescription{}).Method(1)
return rpc, enc, receiver, method, ok && rpc == "/piecestore.Piecestore/Download"
default:
return "", nil, nil, nil, false
}
}

View File

@ -6,9 +6,7 @@ package server
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"crypto/x509"
"errors" "errors"
"io"
"net" "net"
"net/http" "net/http"
"os" "os"
@ -16,9 +14,7 @@ import (
"sync" "sync"
"syscall" "syscall"
"github.com/flynn/noise"
"github.com/jtolio/noiseconn" "github.com/jtolio/noiseconn"
"github.com/zeebo/blake3"
"github.com/zeebo/errs" "github.com/zeebo/errs"
"go.uber.org/zap" "go.uber.org/zap"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
@ -29,6 +25,7 @@ import (
"storj.io/common/pb" "storj.io/common/pb"
"storj.io/common/peertls/tlsopts" "storj.io/common/peertls/tlsopts"
"storj.io/common/rpc" "storj.io/common/rpc"
"storj.io/common/rpc/noise"
"storj.io/common/rpc/quic" "storj.io/common/rpc/quic"
"storj.io/common/rpc/rpctracing" "storj.io/common/rpc/rpctracing"
"storj.io/drpc" "storj.io/drpc"
@ -79,36 +76,10 @@ type Server struct {
done chan struct{} done chan struct{}
} }
func identityBasedEntropy(context string, ident *identity.FullIdentity) (io.Reader, error) {
h := blake3.NewDeriveKey(context)
serialized, err := x509.MarshalPKCS8PrivateKey(ident.Key)
if err != nil {
return nil, Error.Wrap(err)
}
_, err = h.Write(serialized)
return h.Digest(), Error.Wrap(err)
}
func generateNoiseConf(ident *identity.FullIdentity) (noise.Config, error) {
noiseConf := defaultNoiseConfig()
noiseConf.Initiator = false
entropy, err := identityBasedEntropy("noise key", ident)
if err != nil {
return noise.Config{}, err
}
noiseConf.StaticKeypair, err = noiseConf.CipherSuite.GenerateKeypair(entropy)
if err != nil {
return noise.Config{}, Error.Wrap(err)
}
return noiseConf, nil
}
// New creates a Server out of an Identity, a net.Listener, // New creates a Server out of an Identity, a net.Listener,
// and interceptors. // and interceptors.
func New(log *zap.Logger, tlsOptions *tlsopts.Options, config Config) (_ *Server, err error) { func New(log *zap.Logger, tlsOptions *tlsopts.Options, config Config) (_ *Server, err error) {
noiseConf, err := generateNoiseConf(tlsOptions.Ident) noiseConf, err := noise.GenerateServerConf(noise.DefaultProto, tlsOptions.Ident)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -208,12 +179,16 @@ func (p *Server) Addr() net.Addr { return p.addr }
// PrivateAddr returns the server's private listener address. // PrivateAddr returns the server's private listener address.
func (p *Server) PrivateAddr() net.Addr { return p.privateTCPListener.Addr() } func (p *Server) PrivateAddr() net.Addr { return p.privateTCPListener.Addr() }
// DRPC returns the server's DRPC mux for registration purposes. // DRPC returns the server's DRPC mux that supports all endpoints for
// registration purposes.
func (p *Server) DRPC() drpc.Mux { func (p *Server) DRPC() drpc.Mux {
return newReplayRouter( return p.publicEndpointsAll.mux
p.publicEndpointsReplaySafe.mux, }
p.publicEndpointsAll.mux,
) // ReplaySafeDRPC returns the server's DRPC mux that supports replay safe
// endpoints for registration purposes.
func (p *Server) ReplaySafeDRPC() drpc.Mux {
return p.publicEndpointsReplaySafe.mux
} }
// PrivateDRPC returns the server's DRPC mux for registration purposes. // PrivateDRPC returns the server's DRPC mux for registration purposes.
@ -222,19 +197,14 @@ func (p *Server) PrivateDRPC() drpc.Mux { return p.privateEndpoints.mux }
// IsQUICEnabled checks if QUIC is enabled by config and udp port is open. // IsQUICEnabled checks if QUIC is enabled by config and udp port is open.
func (p *Server) IsQUICEnabled() bool { return !p.config.DisableQUIC && p.publicUDPConn != nil } func (p *Server) IsQUICEnabled() bool { return !p.config.DisableQUIC && p.publicUDPConn != nil }
// NoiseInfo returns the noise configuration for this server. This includes the
// keypair in use.
func (p *Server) NoiseInfo() *pb.NoiseInfo {
return &pb.NoiseInfo{
Proto: defaultNoiseProto,
PublicKey: p.noiseConf.StaticKeypair.Public,
}
}
// NoiseKeyAttestation returns the noise key attestation for this server. // NoiseKeyAttestation returns the noise key attestation for this server.
func (p *Server) NoiseKeyAttestation(ctx context.Context) (_ *pb.NoiseKeyAttestation, err error) { func (p *Server) NoiseKeyAttestation(ctx context.Context) (_ *pb.NoiseKeyAttestation, err error) {
defer mon.Task()(&ctx)(&err) defer mon.Task()(&ctx)(&err)
return GenerateNoiseKeyAttestation(ctx, p.tlsOptions.Ident, p.NoiseInfo()) info, err := noise.ConfigToInfo(p.noiseConf)
if err != nil {
return nil, err
}
return noise.GenerateKeyAttestation(ctx, p.tlsOptions.Ident, info)
} }
// Close shuts down the server. // Close shuts down the server.
@ -328,7 +298,7 @@ func (p *Server) Run(ctx context.Context) (err error) {
if p.publicTCPListener != nil { if p.publicTCPListener != nil {
publicLMux := drpcmigrate.NewListenMux(p.publicTCPListener, len(drpcmigrate.DRPCHeader)) publicLMux := drpcmigrate.NewListenMux(p.publicTCPListener, len(drpcmigrate.DRPCHeader))
publicTLSDRPCListener = tls.NewListener(publicLMux.Route(drpcmigrate.DRPCHeader), p.tlsOptions.ServerTLSConfig()) publicTLSDRPCListener = tls.NewListener(publicLMux.Route(drpcmigrate.DRPCHeader), p.tlsOptions.ServerTLSConfig())
publicNoiseDRPCListener = noiseconn.NewListener(publicLMux.Route(NoiseHeader), p.noiseConf) publicNoiseDRPCListener = noiseconn.NewListener(publicLMux.Route(noise.Header), p.noiseConf)
if p.publicHTTP != nil { if p.publicHTTP != nil {
publicHTTPListener = NewPrefixedListener([]byte("GET / HT"), publicLMux.Route("GET / HT")) publicHTTPListener = NewPrefixedListener([]byte("GET / HT"), publicLMux.Route("GET / HT"))
} }

View File

@ -200,6 +200,8 @@ func TestDownloadFromUnresponsiveNode(t *testing.T) {
err = pb.DRPCRegisterPiecestore(server.DRPC(), &piecestoreMock{}) err = pb.DRPCRegisterPiecestore(server.DRPC(), &piecestoreMock{})
require.NoError(t, err) require.NoError(t, err)
err = pb.DRPCRegisterReplaySafePiecestore(server.ReplaySafeDRPC(), &piecestoreMock{})
require.NoError(t, err)
defer ctx.Check(server.Close) defer ctx.Check(server.Close)

View File

@ -14,11 +14,11 @@ import (
"storj.io/common/identity" "storj.io/common/identity"
"storj.io/common/pb" "storj.io/common/pb"
"storj.io/common/rpc/noise"
"storj.io/common/rpc/rpcstatus" "storj.io/common/rpc/rpcstatus"
"storj.io/common/storj" "storj.io/common/storj"
"storj.io/drpc/drpcctx" "storj.io/drpc/drpcctx"
"storj.io/storj/private/nodeoperator" "storj.io/storj/private/nodeoperator"
"storj.io/storj/private/server"
"storj.io/storj/satellite/overlay" "storj.io/storj/satellite/overlay"
) )
@ -89,7 +89,7 @@ func (endpoint *Endpoint) CheckIn(ctx context.Context, req *pb.CheckInRequest) (
var noiseInfo *pb.NoiseInfo var noiseInfo *pb.NoiseInfo
if req.NoiseKeyAttestation != nil { if req.NoiseKeyAttestation != nil {
if err := server.ValidateNoiseKeyAttestation(ctx, req.NoiseKeyAttestation); err == nil { if err := noise.ValidateKeyAttestation(ctx, req.NoiseKeyAttestation, nodeID); err == nil {
noiseInfo = &pb.NoiseInfo{ noiseInfo = &pb.NoiseInfo{
Proto: req.NoiseKeyAttestation.NoiseProto, Proto: req.NoiseKeyAttestation.NoiseProto,
PublicKey: req.NoiseKeyAttestation.NoisePublicKey, PublicKey: req.NoiseKeyAttestation.NoisePublicKey,

View File

@ -10,7 +10,6 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
"storj.io/common/pb" "storj.io/common/pb"
"storj.io/common/storj"
"storj.io/common/sync2" "storj.io/common/sync2"
"storj.io/storj/satellite/nodeselection/uploadselection" "storj.io/storj/satellite/nodeselection/uploadselection"
) )
@ -122,18 +121,9 @@ func (cache *UploadSelectionCache) Size(ctx context.Context) (reputableNodeCount
func convNodesToSelectedNodes(nodes []*uploadselection.Node) (xs []*SelectedNode) { func convNodesToSelectedNodes(nodes []*uploadselection.Node) (xs []*SelectedNode) {
for _, n := range nodes { for _, n := range nodes {
var noiseInfo *pb.NoiseInfo
if n.NoiseInfo.PublicKey != "" && n.NoiseInfo.Proto != storj.NoiseProto_Unset {
// TODO(jt): storj/common's NoiseInfoConvert or NodeFromNodeURL should
// handle this empty case.
noiseInfo = pb.NoiseInfoConvert(n.NoiseInfo)
}
xs = append(xs, &SelectedNode{ xs = append(xs, &SelectedNode{
ID: n.ID, ID: n.ID,
Address: &pb.NodeAddress{ Address: pb.NodeFromNodeURL(n.NodeURL).Address,
Address: n.Address,
NoiseInfo: noiseInfo,
},
LastNet: n.LastNet, LastNet: n.LastNet,
LastIPPort: n.LastIPPort, LastIPPort: n.LastIPPort,
CountryCode: n.CountryCode, CountryCode: n.CountryCode,
@ -144,17 +134,11 @@ func convNodesToSelectedNodes(nodes []*uploadselection.Node) (xs []*SelectedNode
func convSelectedNodesToNodes(nodes []*SelectedNode) (xs []*uploadselection.Node) { func convSelectedNodesToNodes(nodes []*SelectedNode) (xs []*uploadselection.Node) {
for _, n := range nodes { for _, n := range nodes {
nodeurl := storj.NodeURL{
ID: n.ID,
Address: n.Address.Address,
}
if n.Address.NoiseInfo != nil {
// TODO(jt): storj/common's (*pb.Node).NodeURL() should
// handle this if statement.
nodeurl.NoiseInfo = n.Address.NoiseInfo.Convert()
}
xs = append(xs, &uploadselection.Node{ xs = append(xs, &uploadselection.Node{
NodeURL: nodeurl, NodeURL: (&pb.Node{
Id: n.ID,
Address: n.Address,
}).NodeURL(),
LastNet: n.LastNet, LastNet: n.LastNet,
LastIPPort: n.LastIPPort, LastIPPort: n.LastIPPort,
CountryCode: n.CountryCode, CountryCode: n.CountryCode,

View File

@ -560,6 +560,9 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
if err := pb.DRPCRegisterPiecestore(peer.Server.DRPC(), peer.Storage2.Endpoint); err != nil { if err := pb.DRPCRegisterPiecestore(peer.Server.DRPC(), peer.Storage2.Endpoint); err != nil {
return nil, errs.Combine(err, peer.Close()) return nil, errs.Combine(err, peer.Close())
} }
if err := pb.DRPCRegisterReplaySafePiecestore(peer.Server.ReplaySafeDRPC(), peer.Storage2.Endpoint); err != nil {
return nil, errs.Combine(err, peer.Close())
}
// TODO workaround for custom timeout for order sending request (read/write) // TODO workaround for custom timeout for order sending request (read/write)
sc := config.Server sc := config.Server

View File

@ -145,7 +145,7 @@ func (c *service) TransferPiece(ctx context.Context, satelliteID storj.NodeID, t
putCtx, cancel := context.WithTimeout(ctx, maxTransferTime) putCtx, cancel := context.WithTimeout(ctx, maxTransferTime)
defer cancel() defer cancel()
pieceHash, peerID, err := c.ecClient.PutPiece(putCtx, ctx, addrLimit, pk, reader) pieceHash, _, err := c.ecClient.PutPiece(putCtx, ctx, addrLimit, pk, reader)
if err != nil { if err != nil {
if piecestore.ErrVerifyUntrusted.Has(err) { if piecestore.ErrVerifyUntrusted.Has(err) {
return failMessage("failed hash verification", err, pb.TransferFailed_HASH_VERIFICATION) return failMessage("failed hash verification", err, pb.TransferFailed_HASH_VERIFICATION)
@ -163,12 +163,6 @@ func (c *service) TransferPiece(ctx context.Context, satelliteID storj.NodeID, t
return failMessage(msg, Error.New(msg), pb.TransferFailed_HASH_VERIFICATION) return failMessage(msg, Error.New(msg), pb.TransferFailed_HASH_VERIFICATION)
} }
signee := signing.SigneeFromPeerIdentity(peerID)
err = signing.VerifyPieceHashSignature(ctx, signee, pieceHash)
if err != nil {
return failMessage("invalid piece hash signature from new storagenode", err, pb.TransferFailed_HASH_VERIFICATION)
}
success := &pb.StorageNodeMessage{ success := &pb.StorageNodeMessage{
Message: &pb.StorageNodeMessage_Succeeded{ Message: &pb.StorageNodeMessage_Succeeded{
Succeeded: &pb.TransferSucceeded{ Succeeded: &pb.TransferSucceeded{

View File

@ -10,7 +10,7 @@ require (
github.com/zeebo/errs v1.3.0 github.com/zeebo/errs v1.3.0
go.uber.org/zap v1.21.0 go.uber.org/zap v1.21.0
golang.org/x/sync v0.1.0 golang.org/x/sync v0.1.0
storj.io/common v0.0.0-20230203132517-db6195f39c0d storj.io/common v0.0.0-20230207140859-1c86f3de8c15
storj.io/private v0.0.0-20230123202745-d3e63b336444 storj.io/private v0.0.0-20230123202745-d3e63b336444
storj.io/storj v1.63.1 storj.io/storj v1.63.1
storj.io/storjscan v0.0.0-20220926140643-1623c3b391b0 storj.io/storjscan v0.0.0-20220926140643-1623c3b391b0

View File

@ -1217,8 +1217,8 @@ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
storj.io/common v0.0.0-20220719163320-cd2ef8e1b9b0/go.mod h1:mCYV6Ud5+cdbuaxdPD5Zht/HYaIn0sffnnws9ErkrMQ= storj.io/common v0.0.0-20220719163320-cd2ef8e1b9b0/go.mod h1:mCYV6Ud5+cdbuaxdPD5Zht/HYaIn0sffnnws9ErkrMQ=
storj.io/common v0.0.0-20230203132517-db6195f39c0d h1:YXUKpQExPezrMlUn05Zu1ydLGYDwcU1eyMkxDgsfwI0= storj.io/common v0.0.0-20230207140859-1c86f3de8c15 h1:zxniPpRV4V0e4UwYkJgLHik1ZeslbXt136Y04ms1G1s=
storj.io/common v0.0.0-20230203132517-db6195f39c0d/go.mod h1:oNPn8QmwPRXSGWwHoMFLGi9c+vOYbGmRYQQ/IhZi4lM= storj.io/common v0.0.0-20230207140859-1c86f3de8c15/go.mod h1:i5P+zXit50yn4GUHvjET+rJX/uB9S56EISpyaTOVkrE=
storj.io/drpc v0.0.32 h1:5p5ZwsK/VOgapaCu+oxaPVwO6UwIs+iwdMiD50+R4PI= storj.io/drpc v0.0.32 h1:5p5ZwsK/VOgapaCu+oxaPVwO6UwIs+iwdMiD50+R4PI=
storj.io/drpc v0.0.32/go.mod h1:6rcOyR/QQkSTX/9L5ZGtlZaE2PtXTTZl8d+ulSeeYEg= storj.io/drpc v0.0.32/go.mod h1:6rcOyR/QQkSTX/9L5ZGtlZaE2PtXTTZl8d+ulSeeYEg=
storj.io/monkit-jaeger v0.0.0-20220915074555-d100d7589f41 h1:SVuEocEhZfFc13J1AmlVLitdGXTVrvmbzN4Z9C9Ms40= storj.io/monkit-jaeger v0.0.0-20220915074555-d100d7589f41 h1:SVuEocEhZfFc13J1AmlVLitdGXTVrvmbzN4Z9C9Ms40=

View File

@ -10,7 +10,7 @@ require (
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.8.0
go.uber.org/zap v1.23.0 go.uber.org/zap v1.23.0
storj.io/common v0.0.0-20230203132517-db6195f39c0d storj.io/common v0.0.0-20230207140859-1c86f3de8c15
storj.io/gateway-mt v1.46.0 storj.io/gateway-mt v1.46.0
storj.io/private v0.0.0-20230123202745-d3e63b336444 storj.io/private v0.0.0-20230123202745-d3e63b336444
storj.io/storj v0.12.1-0.20221125175451-ef4b564b82f7 storj.io/storj v0.12.1-0.20221125175451-ef4b564b82f7

View File

@ -1921,8 +1921,8 @@ sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
storj.io/common v0.0.0-20220719163320-cd2ef8e1b9b0/go.mod h1:mCYV6Ud5+cdbuaxdPD5Zht/HYaIn0sffnnws9ErkrMQ= storj.io/common v0.0.0-20220719163320-cd2ef8e1b9b0/go.mod h1:mCYV6Ud5+cdbuaxdPD5Zht/HYaIn0sffnnws9ErkrMQ=
storj.io/common v0.0.0-20230203132517-db6195f39c0d h1:YXUKpQExPezrMlUn05Zu1ydLGYDwcU1eyMkxDgsfwI0= storj.io/common v0.0.0-20230207140859-1c86f3de8c15 h1:zxniPpRV4V0e4UwYkJgLHik1ZeslbXt136Y04ms1G1s=
storj.io/common v0.0.0-20230203132517-db6195f39c0d/go.mod h1:oNPn8QmwPRXSGWwHoMFLGi9c+vOYbGmRYQQ/IhZi4lM= storj.io/common v0.0.0-20230207140859-1c86f3de8c15/go.mod h1:i5P+zXit50yn4GUHvjET+rJX/uB9S56EISpyaTOVkrE=
storj.io/dotworld v0.0.0-20210324183515-0d11aeccd840 h1:oqMwoF6vaOrCe92SKRyr8cc2WSjLYAd8fjpAHA7rNqY= storj.io/dotworld v0.0.0-20210324183515-0d11aeccd840 h1:oqMwoF6vaOrCe92SKRyr8cc2WSjLYAd8fjpAHA7rNqY=
storj.io/drpc v0.0.32 h1:5p5ZwsK/VOgapaCu+oxaPVwO6UwIs+iwdMiD50+R4PI= storj.io/drpc v0.0.32 h1:5p5ZwsK/VOgapaCu+oxaPVwO6UwIs+iwdMiD50+R4PI=
storj.io/drpc v0.0.32/go.mod h1:6rcOyR/QQkSTX/9L5ZGtlZaE2PtXTTZl8d+ulSeeYEg= storj.io/drpc v0.0.32/go.mod h1:6rcOyR/QQkSTX/9L5ZGtlZaE2PtXTTZl8d+ulSeeYEg=