forked from TrueCloudLab/frostfs-s3-gw
Merge pull request #85 from KirillovDenis/feature/75-using_256r1_instead_of_ed25519
[#75] Using secp256r1 instead of curve25519
This commit is contained in:
commit
9060b0a988
12 changed files with 179 additions and 406 deletions
21
README.md
21
README.md
|
@ -34,29 +34,22 @@ Minimalistic S3 gateway setup needs:
|
|||
NeoFS nodes with weighted load balancing).
|
||||
* a key used to communicate with NeoFS nodes
|
||||
Passed via `--neofs-key` parameter or `S3_GW_NEOFS-KEY` environment variable.
|
||||
* a key used for client authentication
|
||||
Passed via `--auth-key` parameter or `S3_GW_AUTH-KEY` environment variable.
|
||||
To generate it use `neofs-authmate generate-keys` command.
|
||||
|
||||
These two commands are functionally equivalent, they run the gate with one
|
||||
backend node, some keys and otherwise default settings:
|
||||
```
|
||||
$ neofs-s3-gw -p 192.168.130.72:8080 --neofs-key KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr \
|
||||
--auth-key a04edd5b3c497eed83be25fb136bafd056928c17986440745775223615f2cbab
|
||||
$ neofs-s3-gw -p 192.168.130.72:8080 --neofs-key KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr
|
||||
|
||||
$ S3_GW_PEERS_0_ADDRESS=192.168.130.72:8080 \
|
||||
S3_GW_NEOFS-KEY=KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr \
|
||||
S3_GW_AUTH-KEY=a04edd5b3c497eed83be25fb136bafd056928c17986440745775223615f2cbab \
|
||||
neofs-s3-gw
|
||||
```
|
||||
It's also possible to specify uri scheme (grpc or grpcs) when using `-p` or environment variables:
|
||||
```
|
||||
$ neofs-s3-gw -p grpc://192.168.130.72:8080 --neofs-key KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr \
|
||||
--auth-key a04edd5b3c497eed83be25fb136bafd056928c17986440745775223615f2cbab
|
||||
$ neofs-s3-gw -p grpc://192.168.130.72:8080 --neofs-key KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr
|
||||
|
||||
$ S3_GW_PEERS_0_ADDRESS=grpcs://192.168.130.72:8080 \
|
||||
S3_GW_NEOFS-KEY=KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr \
|
||||
S3_GW_AUTH-KEY=a04edd5b3c497eed83be25fb136bafd056928c17986440745775223615f2cbab \
|
||||
neofs-s3-gw
|
||||
```
|
||||
|
||||
|
@ -84,12 +77,10 @@ $ HTTP_GW_PEERS_0_ADDRESS=192.168.130.72:8080 HTTP_GW_PEERS_0_WEIGHT=9 \
|
|||
This command will make gateway use 192.168.130.72 for 90% of requests and
|
||||
192.168.130.71 for remaining 10%.
|
||||
|
||||
### Keys
|
||||
### Key
|
||||
|
||||
NeoFS (`--neofs-key`) and authentication (`--auth-key`) keys are mandatory
|
||||
parameters. NeoFS key can be a path to private key file (as raw bytes), a hex
|
||||
string or (unencrypted) WIF string. Authentication key is either a path to
|
||||
raw private key file or a hex string.
|
||||
NeoFS (`--neofs-key`) is mandatory parameter. NeoFS key can be a path to private key file (as raw bytes),
|
||||
a hex string or (unencrypted) WIF string.
|
||||
|
||||
### Binding and TLS
|
||||
|
||||
|
@ -208,7 +199,7 @@ potentially).
|
|||
|
||||
#### Generation of key pairs
|
||||
|
||||
To generate key pairs for gateways, run the following command (`--count` is 1
|
||||
To generate neofs key pairs for gateways, run the following command (`--count` is 1
|
||||
by default):
|
||||
|
||||
```
|
||||
|
|
|
@ -2,6 +2,7 @@ package auth
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -15,7 +16,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/authmate"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/hcs"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/tokens"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/pkg/pool"
|
||||
"go.uber.org/zap"
|
||||
|
@ -38,7 +38,6 @@ type (
|
|||
Params struct {
|
||||
Pool pool.Pool
|
||||
Logger *zap.Logger
|
||||
Credential hcs.Credentials
|
||||
}
|
||||
|
||||
prs int
|
||||
|
@ -58,7 +57,7 @@ func (p prs) Seek(_ int64, _ int) (int64, error) {
|
|||
var _ io.ReadSeeker = prs(0)
|
||||
|
||||
// New creates an instance of AuthCenter.
|
||||
func New(conns pool.Pool, key hcs.PrivateKey) Center {
|
||||
func New(conns pool.Pool, key *ecdsa.PrivateKey) Center {
|
||||
return ¢er{
|
||||
cli: tokens.New(conns, key),
|
||||
reg: ®expSubmatcher{re: authorizationFieldRegexp},
|
||||
|
|
|
@ -21,16 +21,16 @@ import (
|
|||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/session"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/policy"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/hcs"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/tokens"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/pkg/pool"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultAuthContainerBasicACL uint32 = 0b00111100100011001000110011001100
|
||||
defaultAuthContainerBasicACL uint32 = 0b00111100100011001000110011001110
|
||||
containerCreationTimeout = 120 * time.Second
|
||||
containerPollInterval = 5 * time.Second
|
||||
)
|
||||
|
@ -52,8 +52,7 @@ type (
|
|||
ContainerID *cid.ID
|
||||
ContainerFriendlyName string
|
||||
NeoFSKey *ecdsa.PrivateKey
|
||||
OwnerPrivateKey hcs.PrivateKey
|
||||
GatesPublicKeys []hcs.PublicKey
|
||||
GatesPublicKeys []*ecdsa.PublicKey
|
||||
EACLRules []byte
|
||||
ContextRules []byte
|
||||
SessionTkn bool
|
||||
|
@ -62,7 +61,7 @@ type (
|
|||
// ObtainSecretOptions contains options for passing to Agent.ObtainSecret method.
|
||||
ObtainSecretOptions struct {
|
||||
SecretAddress string
|
||||
GatePrivateKey hcs.PrivateKey
|
||||
GatePrivateKey *ecdsa.PrivateKey
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -134,7 +133,7 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
|
|||
var (
|
||||
err error
|
||||
cid *cid.ID
|
||||
box accessbox.AccessBox
|
||||
box *accessbox.AccessBox
|
||||
)
|
||||
|
||||
a.log.Info("check container", zap.Stringer("cid", options.ContainerID))
|
||||
|
@ -142,8 +141,6 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
|
|||
return err
|
||||
}
|
||||
|
||||
box.SetOwnerPublicKey(options.OwnerPrivateKey.PublicKey())
|
||||
|
||||
oid, err := ownerIDFromNeoFSKey(&options.NeoFSKey.PublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -155,35 +152,24 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
|
|||
return fmt.Errorf("failed to build eacl table: %w", err)
|
||||
}
|
||||
|
||||
bearerTkn, err := buildBearerToken(options.NeoFSKey, oid, bearerRules)
|
||||
bearerTkn, err := buildBearerToken(options.NeoFSKey, bearerRules, options.GatesPublicKeys[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build bearer token: %w", err)
|
||||
}
|
||||
|
||||
err = box.AddBearerToken(bearerTkn, options.OwnerPrivateKey, options.GatesPublicKeys...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add bearer token to accessbox: %w", err)
|
||||
}
|
||||
a.log.Info("store bearer token into NeoFS",
|
||||
zap.Stringer("owner_tkn", bearerTkn.Issuer()))
|
||||
|
||||
if options.SessionTkn {
|
||||
sessionRules, err := buildContext(options.ContextRules)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build context for session token: %w", err)
|
||||
}
|
||||
|
||||
sessionTkn, err := buildSessionToken(options.NeoFSKey, oid, sessionRules)
|
||||
sessionTkn, err := createSessionToken(options, oid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create session token: %w", err)
|
||||
}
|
||||
|
||||
err = box.AddSessionToken(sessionTkn, options.OwnerPrivateKey, options.GatesPublicKeys...)
|
||||
box, ownerKey, err := accessbox.PackTokens(bearerTkn, sessionTkn, options.GatesPublicKeys...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add session token to accessbox: %w", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
a.log.Info("store bearer token into NeoFS",
|
||||
zap.Stringer("owner_tkn", bearerTkn.Issuer()))
|
||||
|
||||
if !options.SessionTkn && len(options.ContextRules) > 0 {
|
||||
_, err := w.Write([]byte("Warning: rules for session token were set but --create-session flag wasn't, " +
|
||||
"so session token was not created\n"))
|
||||
|
@ -193,8 +179,8 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
|
|||
}
|
||||
|
||||
address, err := tokens.
|
||||
New(a.pool, options.OwnerPrivateKey).
|
||||
Put(ctx, cid, oid, &box, options.GatesPublicKeys...)
|
||||
New(a.pool, ownerKey).
|
||||
Put(ctx, cid, oid, box, options.GatesPublicKeys...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to put bearer token: %w", err)
|
||||
}
|
||||
|
@ -209,7 +195,7 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
|
|||
ir := &issuingResult{
|
||||
AccessKeyID: accessKeyID,
|
||||
SecretAccessKey: secret,
|
||||
OwnerPrivateKey: options.OwnerPrivateKey.String(),
|
||||
OwnerPrivateKey: hex.EncodeToString(crypto.MarshalPrivateKey(ownerKey)),
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
|
@ -316,7 +302,12 @@ func buildContext(rules []byte) (*session.ContainerContext, error) {
|
|||
return sessionCtx, nil
|
||||
}
|
||||
|
||||
func buildBearerToken(key *ecdsa.PrivateKey, oid *owner.ID, table *eacl.Table) (*token.BearerToken, error) {
|
||||
func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, ownerKey *ecdsa.PublicKey) (*token.BearerToken, error) {
|
||||
oid, err := ownerIDFromNeoFSKey(ownerKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bearerToken := token.NewBearerToken()
|
||||
bearerToken.SetEACLTable(table)
|
||||
bearerToken.SetOwner(oid)
|
||||
|
@ -338,6 +329,17 @@ func buildSessionToken(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.Contai
|
|||
return tok, tok.Sign(key)
|
||||
}
|
||||
|
||||
func createSessionToken(options *IssueSecretOptions, oid *owner.ID) (*session.Token, error) {
|
||||
if options.SessionTkn {
|
||||
sessionRules, err := buildContext(options.ContextRules)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build context for session token: %w", err)
|
||||
}
|
||||
return buildSessionToken(options.NeoFSKey, oid, sessionRules)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// BearerToAccessKey returns secret access key generated from given BearerToken.
|
||||
func BearerToAccessKey(tkn *token.BearerToken) (string, error) {
|
||||
data, err := tkn.Marshal()
|
||||
|
@ -356,3 +358,16 @@ func ownerIDFromNeoFSKey(key *ecdsa.PublicKey) (*owner.ID, error) {
|
|||
}
|
||||
return owner.NewIDFromNeo3Wallet(wallet), nil
|
||||
}
|
||||
|
||||
// LoadPublicKey returns ecdsa.PublicKey from hex string.
|
||||
func LoadPublicKey(val string) (*ecdsa.PublicKey, error) {
|
||||
data, err := hex.DecodeString(val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unknown key format (%q), expect: hex-string", val)
|
||||
}
|
||||
|
||||
if key := crypto.UnmarshalPublicKey(data); key != nil {
|
||||
return key, nil
|
||||
}
|
||||
return nil, fmt.Errorf("couldn't unmarshal public key (%q)", val)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package main
|
|||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
@ -15,7 +17,6 @@ import (
|
|||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/authmate"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/hcs"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/internal/version"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/pkg/pool"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
@ -40,7 +41,6 @@ var (
|
|||
contextRulesFlag string
|
||||
gatePrivateKeyFlag string
|
||||
accessKeyIDFlag string
|
||||
ownerPrivateKeyFlag string
|
||||
containerIDFlag string
|
||||
containerFriendlyName string
|
||||
gatesPublicKeysFlag cli.StringSlice
|
||||
|
@ -124,14 +124,14 @@ func appCommands() []*cli.Command {
|
|||
}
|
||||
}
|
||||
|
||||
func generateGatesKeys(count int) ([]hcs.Credentials, error) {
|
||||
func generateGatesKeys(count int) ([]*ecdsa.PrivateKey, error) {
|
||||
var (
|
||||
err error
|
||||
res = make([]hcs.Credentials, count)
|
||||
res = make([]*ecdsa.PrivateKey, count)
|
||||
)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
if res[i], err = hcs.Generate(rand.Reader); err != nil {
|
||||
if res[i], err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ func generateKeys() *cli.Command {
|
|||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "count",
|
||||
Usage: "number of x25519 key pairs to generate",
|
||||
Usage: "number of 256r1 key pairs to generate",
|
||||
Value: 1,
|
||||
Destination: &gatesKeysCountFlag,
|
||||
},
|
||||
|
@ -154,18 +154,18 @@ func generateKeys() *cli.Command {
|
|||
Action: func(c *cli.Context) error {
|
||||
_, log := prepare()
|
||||
|
||||
log.Info("start generating x25519 keys")
|
||||
log.Info("start generating P-256 keys")
|
||||
|
||||
csl, err := generateGatesKeys(gatesKeysCountFlag)
|
||||
if err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to create key pairs of gates: %s", err), 1)
|
||||
}
|
||||
|
||||
log.Info("generated x25519 keys")
|
||||
log.Info("generated P-256 keys")
|
||||
|
||||
gatesKeys := make([]gateKey, len(csl))
|
||||
for i, cs := range csl {
|
||||
privateKey, publicKey := cs.PrivateKey().String(), cs.PublicKey().String()
|
||||
privateKey, publicKey := hex.EncodeToString(cs.D.Bytes()), hex.EncodeToString(crypto.MarshalPublicKey(&cs.PublicKey))
|
||||
gatesKeys[i] = gateKey{PrivateKey: privateKey, PublicKey: publicKey}
|
||||
}
|
||||
|
||||
|
@ -213,16 +213,10 @@ func issueSecret() *cli.Command {
|
|||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "gate-public-key",
|
||||
Usage: "public x25519 key of a gate (use flags repeatedly for multiple gates)",
|
||||
Usage: "public 256r1 key of a gate (use flags repeatedly for multiple gates)",
|
||||
Required: true,
|
||||
Destination: &gatesPublicKeysFlag,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "owner-private-key",
|
||||
Usage: "owner's private x25519 key",
|
||||
Required: false,
|
||||
Destination: &ownerPrivateKeyFlag,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "container-id",
|
||||
Usage: "auth container id to put the secret into",
|
||||
|
@ -269,14 +263,9 @@ func issueSecret() *cli.Command {
|
|||
}
|
||||
}
|
||||
|
||||
var owner hcs.Credentials
|
||||
if owner, err = fetchHCSCredentials(ownerPrivateKeyFlag); err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to create owner's private key: %s", err), 4)
|
||||
}
|
||||
|
||||
var gatesPublicKeys []hcs.PublicKey
|
||||
var gatesPublicKeys []*ecdsa.PublicKey
|
||||
for _, key := range gatesPublicKeysFlag.Value() {
|
||||
gpk, err := hcs.LoadPublicKey(key)
|
||||
gpk, err := authmate.LoadPublicKey(key)
|
||||
if err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to load gate's public key: %s", err), 5)
|
||||
}
|
||||
|
@ -287,7 +276,6 @@ func issueSecret() *cli.Command {
|
|||
ContainerID: containerID,
|
||||
ContainerFriendlyName: containerFriendlyName,
|
||||
NeoFSKey: key,
|
||||
OwnerPrivateKey: owner.PrivateKey(),
|
||||
GatesPublicKeys: gatesPublicKeys,
|
||||
EACLRules: []byte(eaclRulesFlag),
|
||||
ContextRules: []byte(contextRulesFlag),
|
||||
|
@ -355,7 +343,7 @@ func obtainSecret() *cli.Command {
|
|||
|
||||
var _ = agent
|
||||
|
||||
gateCreds, err := hcs.NewCredentials(gatePrivateKeyFlag)
|
||||
gateCreds, err := crypto.LoadPrivateKey(gatePrivateKeyFlag)
|
||||
if err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to create owner's private key: %s", err), 4)
|
||||
}
|
||||
|
@ -364,7 +352,7 @@ func obtainSecret() *cli.Command {
|
|||
|
||||
obtainSecretOptions := &authmate.ObtainSecretOptions{
|
||||
SecretAddress: secretAddress,
|
||||
GatePrivateKey: gateCreds.PrivateKey(),
|
||||
GatePrivateKey: gateCreds,
|
||||
}
|
||||
|
||||
if err = agent.ObtainSecret(ctx, os.Stdout, obtainSecretOptions); err != nil {
|
||||
|
@ -377,14 +365,6 @@ func obtainSecret() *cli.Command {
|
|||
return command
|
||||
}
|
||||
|
||||
func fetchHCSCredentials(val string) (hcs.Credentials, error) {
|
||||
if val == "" {
|
||||
return hcs.Generate(rand.Reader)
|
||||
}
|
||||
|
||||
return hcs.NewCredentials(val)
|
||||
}
|
||||
|
||||
func createSDKClient(ctx context.Context, log *zap.Logger, key *ecdsa.PrivateKey, peerAddress string) (pool.Pool, error) {
|
||||
log.Debug("prepare connection pool")
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ const ( // Settings.
|
|||
|
||||
// Keys.
|
||||
cfgNeoFSPrivateKey = "neofs-key"
|
||||
cfgGateAuthPrivateKey = "auth-key"
|
||||
|
||||
// HTTPS/TLS.
|
||||
cfgTLSKeyFile = "tls.key_file"
|
||||
|
@ -163,7 +162,6 @@ func newSettings() *viper.Viper {
|
|||
versionFlag := flags.BoolP(cmdVersion, "v", false, "show version")
|
||||
|
||||
flags.String(cfgNeoFSPrivateKey, "", "set value to hex string, WIF string, or path to NeoFS private key file")
|
||||
flags.String(cfgGateAuthPrivateKey, "", "set path to file with auth (curve25519) private key to use in auth scheme")
|
||||
|
||||
flags.Bool(cfgGRPCVerbose, false, "set debug mode of gRPC connections")
|
||||
flags.Duration(cfgRequestTimeout, defaultRequestTimeout, "set gRPC request timeout")
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-s3-gw/api/auth"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/api/handler"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/hcs"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/pkg/pool"
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
|
@ -51,8 +50,6 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
|
|||
ctr auth.Center
|
||||
obj layer.Client
|
||||
|
||||
hcsCred hcs.Credentials
|
||||
|
||||
poolPeers = fetchPeers(l, v)
|
||||
|
||||
reBalance = defaultRebalanceTimer
|
||||
|
@ -62,7 +59,6 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
|
|||
maxClientsCount = defaultMaxClientsCount
|
||||
maxClientsDeadline = defaultMaxClientsDeadline
|
||||
|
||||
hcsCredential = v.GetString(cfgGateAuthPrivateKey)
|
||||
nfsCredential = v.GetString(cfgNeoFSPrivateKey)
|
||||
)
|
||||
|
||||
|
@ -90,10 +86,6 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
|
|||
l.Fatal("could not load NeoFS private key")
|
||||
}
|
||||
|
||||
if hcsCred, err = hcs.NewCredentials(hcsCredential); err != nil {
|
||||
l.Fatal("could not load gate auth key")
|
||||
}
|
||||
|
||||
if v.IsSet(cfgTLSKeyFile) && v.IsSet(cfgTLSCertFile) {
|
||||
tls = &tlsConfig{
|
||||
KeyFile: v.GetString(cfgTLSKeyFile),
|
||||
|
@ -102,7 +94,6 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
|
|||
}
|
||||
|
||||
l.Info("using credentials",
|
||||
zap.String("HCS", hcsCredential),
|
||||
zap.String("NeoFS", nfsCredential))
|
||||
|
||||
opts := &pool.BuilderOptions{
|
||||
|
@ -121,7 +112,7 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
|
|||
obj = layer.NewLayer(l, conns)
|
||||
|
||||
// prepare auth center
|
||||
ctr = auth.New(conns, hcsCred.PrivateKey())
|
||||
ctr = auth.New(conns, key)
|
||||
|
||||
if caller, err = handler.New(l, obj); err != nil {
|
||||
l.Fatal("could not initialize API handler", zap.Error(err))
|
||||
|
|
|
@ -2,14 +2,19 @@ package accessbox
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/session"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/hcs"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
|
@ -28,43 +33,34 @@ func (x *AccessBox) Unmarshal(data []byte) error {
|
|||
return proto.Unmarshal(data, x)
|
||||
}
|
||||
|
||||
// AddBearerToken adds a bearer token to BearerTokens list.
|
||||
func (x *AccessBox) AddBearerToken(tkn *token.BearerToken, owner hcs.PrivateKey, keys ...hcs.PublicKey) error {
|
||||
if x.OwnerPublicKey == nil {
|
||||
return fmt.Errorf("owner's public key is nil")
|
||||
// PackTokens adds a bearer and session tokens to BearerTokens and SessionToken lists respectively.
|
||||
// Session token can be nil.
|
||||
func PackTokens(bearer *token.BearerToken, sess *session.Token, keys ...*ecdsa.PublicKey) (*AccessBox, *ecdsa.PrivateKey, error) {
|
||||
box := &AccessBox{}
|
||||
ephemeralKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// restriction to rewrite token for the second time
|
||||
if len(x.BearerTokens) > 0 {
|
||||
return fmt.Errorf("bearer token is already set")
|
||||
}
|
||||
return x.addToken(tkn, &x.BearerTokens, owner, keys...)
|
||||
}
|
||||
box.OwnerPublicKey = crypto.MarshalPublicKey(&ephemeralKey.PublicKey)
|
||||
|
||||
// AddSessionToken adds a session token to SessionTokens list.
|
||||
func (x *AccessBox) AddSessionToken(tkn *session.Token, owner hcs.PrivateKey, keys ...hcs.PublicKey) error {
|
||||
if x.OwnerPublicKey == nil {
|
||||
return fmt.Errorf("owner's public key is nil")
|
||||
if err := box.addToken(bearer, &box.BearerTokens, ephemeralKey, keys...); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to add bearer token to accessbox: %w", err)
|
||||
}
|
||||
if sess != nil {
|
||||
if err := box.addToken(sess, &box.SessionTokens, ephemeralKey, keys...); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to add session token to accessbox: %w", err)
|
||||
}
|
||||
//restriction to rewrite token for the second time
|
||||
if len(x.SessionTokens) > 0 {
|
||||
return fmt.Errorf("bearer token is already set")
|
||||
}
|
||||
return x.addToken(tkn, &x.SessionTokens, owner, keys...)
|
||||
}
|
||||
|
||||
// SetOwnerPublicKey sets a public key of an issuer.
|
||||
func (x *AccessBox) SetOwnerPublicKey(key hcs.PublicKey) {
|
||||
x.OwnerPublicKey = key.Bytes()
|
||||
return box, ephemeralKey, err
|
||||
}
|
||||
|
||||
// GetBearerToken returns bearer token from AccessBox.
|
||||
func (x *AccessBox) GetBearerToken(owner hcs.PrivateKey) (*token.BearerToken, error) {
|
||||
sender, err := hcs.PublicKeyFromBytes(x.OwnerPublicKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load owner public key from AccessBox: %w", err)
|
||||
}
|
||||
func (x *AccessBox) GetBearerToken(owner *ecdsa.PrivateKey) (*token.BearerToken, error) {
|
||||
sender := crypto.UnmarshalPublicKey(x.OwnerPublicKey)
|
||||
ownerKey := crypto.MarshalPublicKey(&owner.PublicKey)
|
||||
for _, data := range x.BearerTokens {
|
||||
if !bytes.Equal(data.GatePublicKey, owner.PublicKey().Bytes()) {
|
||||
if !bytes.Equal(data.GatePublicKey, ownerKey) {
|
||||
continue
|
||||
}
|
||||
tkn := token.NewBearerToken()
|
||||
|
@ -74,17 +70,15 @@ func (x *AccessBox) GetBearerToken(owner hcs.PrivateKey) (*token.BearerToken, er
|
|||
return tkn, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no bearer token for key %s was found", owner.String())
|
||||
return nil, fmt.Errorf("no bearer token for key %x was found", ownerKey)
|
||||
}
|
||||
|
||||
// GetSessionToken returns session token from AccessBox.
|
||||
func (x *AccessBox) GetSessionToken(owner hcs.PrivateKey) (*session.Token, error) {
|
||||
sender, err := hcs.PublicKeyFromBytes(x.OwnerPublicKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load owner public key from AccessBox: %w", err)
|
||||
}
|
||||
func (x *AccessBox) GetSessionToken(owner *ecdsa.PrivateKey) (*session.Token, error) {
|
||||
sender := crypto.UnmarshalPublicKey(x.OwnerPublicKey)
|
||||
ownerKey := crypto.MarshalPublicKey(&owner.PublicKey)
|
||||
for _, data := range x.SessionTokens {
|
||||
if !bytes.Equal(data.GatePublicKey, owner.PublicKey().Bytes()) {
|
||||
if !bytes.Equal(data.GatePublicKey, ownerKey) {
|
||||
continue
|
||||
}
|
||||
tkn := session.NewToken()
|
||||
|
@ -95,16 +89,16 @@ func (x *AccessBox) GetSessionToken(owner hcs.PrivateKey) (*session.Token, error
|
|||
return tkn, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no session token for key %s was found", owner.String())
|
||||
return nil, fmt.Errorf("no session token for key %x was found", ownerKey)
|
||||
}
|
||||
|
||||
func (x *AccessBox) addToken(tkn tokenInterface, list *[]*AccessBox_Token, owner hcs.PrivateKey, keys ...hcs.PublicKey) error {
|
||||
func (x *AccessBox) addToken(tkn tokenInterface, list *[]*AccessBox_Token, owner *ecdsa.PrivateKey, keys ...*ecdsa.PublicKey) error {
|
||||
for i, sender := range keys {
|
||||
data, err := encodeToken(tkn, owner, sender)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w, sender = %d", err, i)
|
||||
}
|
||||
*list = append(*list, newToken(data, sender.Bytes()))
|
||||
*list = append(*list, newToken(data, crypto.MarshalPublicKey(sender)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -116,7 +110,7 @@ func newToken(data []byte, key []byte) *AccessBox_Token {
|
|||
return res
|
||||
}
|
||||
|
||||
func encodeToken(tkn tokenInterface, owner hcs.PrivateKey, sender hcs.PublicKey) ([]byte, error) {
|
||||
func encodeToken(tkn tokenInterface, owner *ecdsa.PrivateKey, sender *ecdsa.PublicKey) ([]byte, error) {
|
||||
data, err := tkn.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -129,7 +123,7 @@ func encodeToken(tkn tokenInterface, owner hcs.PrivateKey, sender hcs.PublicKey)
|
|||
return encrypted, nil
|
||||
}
|
||||
|
||||
func decodeToken(data []byte, tkn tokenInterface, owner hcs.PrivateKey, sender hcs.PublicKey) error {
|
||||
func decodeToken(data []byte, tkn tokenInterface, owner *ecdsa.PrivateKey, sender *ecdsa.PublicKey) error {
|
||||
decoded, err := decrypt(owner, sender, data)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -143,13 +137,32 @@ func decodeToken(data []byte, tkn tokenInterface, owner hcs.PrivateKey, sender h
|
|||
return nil
|
||||
}
|
||||
|
||||
func encrypt(owner hcs.PrivateKey, sender hcs.PublicKey, data []byte) ([]byte, error) {
|
||||
key, err := curve25519.X25519(owner.Bytes(), sender.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func generateShared256(prv *ecdsa.PrivateKey, pub *ecdsa.PublicKey) (sk []byte, err error) {
|
||||
if prv.PublicKey.Curve != pub.Curve {
|
||||
return nil, fmt.Errorf("not equal curves")
|
||||
}
|
||||
|
||||
enc, err := chacha20poly1305.NewX(key)
|
||||
x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes())
|
||||
if x == nil {
|
||||
return nil, fmt.Errorf("shared key is point at infinity")
|
||||
}
|
||||
|
||||
sk = make([]byte, 32)
|
||||
skBytes := x.Bytes()
|
||||
copy(sk[len(sk)-len(skBytes):], skBytes)
|
||||
return sk, nil
|
||||
}
|
||||
|
||||
func deriveKey(secret []byte) ([]byte, error) {
|
||||
hash := sha256.New
|
||||
kdf := hkdf.New(hash, secret, nil, nil)
|
||||
key := make([]byte, 32)
|
||||
_, err := io.ReadFull(kdf, key)
|
||||
return key, err
|
||||
}
|
||||
|
||||
func encrypt(owner *ecdsa.PrivateKey, sender *ecdsa.PublicKey, data []byte) ([]byte, error) {
|
||||
enc, err := getCipher(owner, sender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -162,15 +175,8 @@ func encrypt(owner hcs.PrivateKey, sender hcs.PublicKey, data []byte) ([]byte, e
|
|||
return enc.Seal(nonce, nonce, data, nil), nil
|
||||
}
|
||||
|
||||
func decrypt(owner hcs.PrivateKey, sender hcs.PublicKey, data []byte) ([]byte, error) {
|
||||
sb := sender.Bytes()
|
||||
|
||||
key, err := curve25519.X25519(owner.Bytes(), sb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dec, err := chacha20poly1305.NewX(key)
|
||||
func decrypt(owner *ecdsa.PrivateKey, sender *ecdsa.PublicKey, data []byte) ([]byte, error) {
|
||||
dec, err := getCipher(owner, sender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -182,3 +188,21 @@ func decrypt(owner hcs.PrivateKey, sender hcs.PublicKey, data []byte) ([]byte, e
|
|||
nonce, cypher := data[:dec.NonceSize()], data[dec.NonceSize():]
|
||||
return dec.Open(nil, nonce, cypher, nil)
|
||||
}
|
||||
|
||||
func getCipher(owner *ecdsa.PrivateKey, sender *ecdsa.PublicKey) (cipher.AEAD, error) {
|
||||
secret, err := generateShared256(owner, sender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := deriveKey(secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aead, err := chacha20poly1305.NewX(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return aead, nil
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/hcs"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -20,16 +19,16 @@ func Test_tokens_encode_decode(t *testing.T) {
|
|||
sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
cred, err := hcs.Generate(rand.Reader)
|
||||
cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
tkn.SetEACLTable(eacl.NewTable())
|
||||
require.NoError(t, tkn.SignToken(sec))
|
||||
|
||||
data, err := encodeToken(tkn, cred.PrivateKey(), cred.PublicKey())
|
||||
data, err := encodeToken(tkn, cred, &cred.PublicKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = decodeToken(data, tkn2, cred.PrivateKey(), cred.PublicKey())
|
||||
err = decodeToken(data, tkn2, cred, &cred.PublicKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, tkn, tkn2)
|
||||
|
@ -37,22 +36,21 @@ func Test_tokens_encode_decode(t *testing.T) {
|
|||
|
||||
func Test_bearer_token_in_access_box(t *testing.T) {
|
||||
var (
|
||||
box, box2 AccessBox
|
||||
box *AccessBox
|
||||
box2 AccessBox
|
||||
tkn = token.NewBearerToken()
|
||||
)
|
||||
|
||||
sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
cred, err := hcs.Generate(rand.Reader)
|
||||
cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
tkn.SetEACLTable(eacl.NewTable())
|
||||
require.NoError(t, tkn.SignToken(sec))
|
||||
|
||||
box.SetOwnerPublicKey(cred.PublicKey())
|
||||
|
||||
err = box.AddBearerToken(tkn, cred.PrivateKey(), cred.PublicKey())
|
||||
box, _, err = PackTokens(tkn, nil, &cred.PublicKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := box.Marshal()
|
||||
|
@ -61,7 +59,7 @@ func Test_bearer_token_in_access_box(t *testing.T) {
|
|||
err = box2.Unmarshal(data)
|
||||
require.NoError(t, err)
|
||||
|
||||
tkn2, err := box2.GetBearerToken(cred.PrivateKey())
|
||||
tkn2, err := box2.GetBearerToken(cred)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, tkn, tkn2)
|
||||
|
@ -69,35 +67,30 @@ func Test_bearer_token_in_access_box(t *testing.T) {
|
|||
|
||||
func Test_accessbox_multiple_keys(t *testing.T) {
|
||||
var (
|
||||
box AccessBox
|
||||
box *AccessBox
|
||||
tkn = token.NewBearerToken()
|
||||
)
|
||||
|
||||
sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
cred, err := hcs.Generate(rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
tkn.SetEACLTable(eacl.NewTable())
|
||||
require.NoError(t, tkn.SignToken(sec))
|
||||
|
||||
count := 10
|
||||
pubs := make([]hcs.PublicKey, 0, count)
|
||||
keys := make([]hcs.PrivateKey, 0, count)
|
||||
pubs := make([]*ecdsa.PublicKey, 0, count)
|
||||
keys := make([]*ecdsa.PrivateKey, 0, count)
|
||||
{ // generate keys
|
||||
for i := 0; i < count; i++ {
|
||||
cred, err := hcs.Generate(rand.Reader)
|
||||
cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
pubs = append(pubs, cred.PublicKey())
|
||||
keys = append(keys, cred.PrivateKey())
|
||||
pubs = append(pubs, &cred.PublicKey)
|
||||
keys = append(keys, cred)
|
||||
}
|
||||
}
|
||||
|
||||
box.SetOwnerPublicKey(cred.PublicKey())
|
||||
|
||||
err = box.AddBearerToken(tkn, cred.PrivateKey(), pubs...)
|
||||
box, _, err = PackTokens(tkn, nil, pubs...)
|
||||
require.NoError(t, err)
|
||||
|
||||
for i, k := range keys {
|
||||
|
@ -109,27 +102,25 @@ func Test_accessbox_multiple_keys(t *testing.T) {
|
|||
|
||||
func Test_unknown_key(t *testing.T) {
|
||||
var (
|
||||
box AccessBox
|
||||
box *AccessBox
|
||||
tkn = token.NewBearerToken()
|
||||
)
|
||||
|
||||
sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
cred, err := hcs.Generate(rand.Reader)
|
||||
cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
wrongCred, err := hcs.Generate(rand.Reader)
|
||||
wrongCred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
tkn.SetEACLTable(eacl.NewTable())
|
||||
require.NoError(t, tkn.SignToken(sec))
|
||||
|
||||
box.SetOwnerPublicKey(cred.PublicKey())
|
||||
|
||||
err = box.AddBearerToken(tkn, cred.PrivateKey(), cred.PublicKey())
|
||||
box, _, err = PackTokens(tkn, nil, &cred.PublicKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = box.GetBearerToken(wrongCred.PrivateKey())
|
||||
_, err = box.GetBearerToken(wrongCred)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
package hcs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
type (
|
||||
// Credentials is an HCS interface (private/public key).
|
||||
Credentials interface {
|
||||
PublicKey() PublicKey
|
||||
PrivateKey() PrivateKey
|
||||
}
|
||||
|
||||
keyer interface {
|
||||
io.WriterTo
|
||||
|
||||
Bytes() []byte
|
||||
String() string
|
||||
}
|
||||
|
||||
// PublicKey is a public key wrapper providing useful methods.
|
||||
PublicKey interface {
|
||||
keyer
|
||||
}
|
||||
|
||||
// PrivateKey is private key wrapper providing useful methods.
|
||||
PrivateKey interface {
|
||||
keyer
|
||||
|
||||
PublicKey() PublicKey
|
||||
}
|
||||
|
||||
credentials struct {
|
||||
public PublicKey
|
||||
secret PrivateKey
|
||||
}
|
||||
|
||||
public []byte
|
||||
secret []byte
|
||||
)
|
||||
|
||||
// ErrEmptyCredentials is returned when no credentials are provided.
|
||||
var ErrEmptyCredentials = errors.New("empty credentials")
|
||||
|
||||
var _ = NewCredentials
|
||||
|
||||
// Generate generates new key pair using given source of randomness.
|
||||
func Generate(r io.Reader) (Credentials, error) {
|
||||
buf := make([]byte, curve25519.ScalarSize)
|
||||
|
||||
if _, err := r.Read(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sk := secret(buf)
|
||||
return &credentials{
|
||||
secret: &sk,
|
||||
public: sk.PublicKey(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewCredentials loads private key from the string given and returns Credentials wrapper.
|
||||
func NewCredentials(val string) (Credentials, error) {
|
||||
if val == "" {
|
||||
return nil, ErrEmptyCredentials
|
||||
}
|
||||
|
||||
sk, err := loadPrivateKey(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &credentials{
|
||||
secret: sk,
|
||||
public: sk.PublicKey(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PublicKey returns public key.
|
||||
func (c *credentials) PublicKey() PublicKey {
|
||||
return c.public
|
||||
}
|
||||
|
||||
// PrivateKey returns private key.
|
||||
func (c *credentials) PrivateKey() PrivateKey {
|
||||
return c.secret
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package hcs
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
func (p *public) Bytes() []byte {
|
||||
buf := make([]byte, curve25519.PointSize)
|
||||
copy(buf, *p)
|
||||
return buf
|
||||
}
|
||||
|
||||
func (p *public) String() string {
|
||||
buf := p.Bytes()
|
||||
return hex.EncodeToString(buf)
|
||||
}
|
||||
|
||||
func (p *public) WriteTo(w io.Writer) (int64, error) {
|
||||
pb := p.Bytes()
|
||||
pl, err := w.Write(pb)
|
||||
return int64(pl), err
|
||||
}
|
||||
|
||||
// PublicKeyFromBytes reads a public key from given bytes.
|
||||
func PublicKeyFromBytes(v []byte) (PublicKey, error) {
|
||||
pub := public(v)
|
||||
return &pub, nil
|
||||
}
|
||||
|
||||
func publicKeyFromString(val string) (PublicKey, error) {
|
||||
v, err := hex.DecodeString(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return PublicKeyFromBytes(v)
|
||||
}
|
||||
|
||||
// NewPublicKeyFromReader reads new public key from given reader.
|
||||
func NewPublicKeyFromReader(r io.Reader) (PublicKey, error) {
|
||||
data := make([]byte, curve25519.PointSize)
|
||||
if _, err := r.Read(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return PublicKeyFromBytes(data)
|
||||
}
|
||||
|
||||
// LoadPublicKey loads public key from given file or (serialized) string.
|
||||
func LoadPublicKey(val string) (PublicKey, error) {
|
||||
data, err := ioutil.ReadFile(val)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return publicKeyFromString(val)
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return PublicKeyFromBytes(data)
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
package hcs
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
func (s *secret) Bytes() []byte {
|
||||
buf := make([]byte, curve25519.ScalarSize)
|
||||
copy(buf, *s)
|
||||
return buf
|
||||
}
|
||||
|
||||
func (s *secret) String() string {
|
||||
buf := s.Bytes()
|
||||
return hex.EncodeToString(buf)
|
||||
}
|
||||
|
||||
func (s *secret) PublicKey() PublicKey {
|
||||
sk := s.Bytes()
|
||||
|
||||
pb, _ := curve25519.X25519(sk, curve25519.Basepoint)
|
||||
pk := public(pb)
|
||||
return &pk
|
||||
}
|
||||
|
||||
func (s *secret) WriteTo(w io.Writer) (int64, error) {
|
||||
sb := s.Bytes()
|
||||
sl, err := w.Write(sb)
|
||||
return int64(sl), err
|
||||
}
|
||||
|
||||
func privateKeyFromBytes(val []byte) (PrivateKey, error) {
|
||||
sk := secret(val)
|
||||
return &sk, nil
|
||||
}
|
||||
|
||||
func privateKeyFromString(val string) (PrivateKey, error) {
|
||||
data, err := hex.DecodeString(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return privateKeyFromBytes(data)
|
||||
}
|
||||
|
||||
func loadPrivateKey(val string) (PrivateKey, error) {
|
||||
data, err := ioutil.ReadFile(val)
|
||||
if os.IsNotExist(err) {
|
||||
return privateKeyFromString(val)
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return privateKeyFromBytes(data)
|
||||
}
|
|
@ -3,6 +3,7 @@ package tokens
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
@ -15,7 +16,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-api-go/pkg/session"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/hcs"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/pkg/pool"
|
||||
)
|
||||
|
||||
|
@ -24,11 +24,11 @@ type (
|
|||
Credentials interface {
|
||||
GetBearerToken(context.Context, *object.Address) (*token.BearerToken, error)
|
||||
GetSessionToken(context.Context, *object.Address) (*session.Token, error)
|
||||
Put(context.Context, *cid.ID, *owner.ID, *accessbox.AccessBox, ...hcs.PublicKey) (*object.Address, error)
|
||||
Put(context.Context, *cid.ID, *owner.ID, *accessbox.AccessBox, ...*ecdsa.PublicKey) (*object.Address, error)
|
||||
}
|
||||
|
||||
cred struct {
|
||||
key hcs.PrivateKey
|
||||
key *ecdsa.PrivateKey
|
||||
pool pool.Pool
|
||||
}
|
||||
)
|
||||
|
@ -49,7 +49,7 @@ var bufferPool = sync.Pool{
|
|||
var _ = New
|
||||
|
||||
// New creates new Credentials instance using given cli and key.
|
||||
func New(conns pool.Pool, key hcs.PrivateKey) Credentials {
|
||||
func New(conns pool.Pool, key *ecdsa.PrivateKey) Credentials {
|
||||
return &cred{pool: conns, key: key}
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ func (c *cred) getAccessBox(ctx context.Context, address *object.Address) (*acce
|
|||
return &box, nil
|
||||
}
|
||||
|
||||
func (c *cred) Put(ctx context.Context, cid *cid.ID, issuer *owner.ID, box *accessbox.AccessBox, keys ...hcs.PublicKey) (*object.Address, error) {
|
||||
func (c *cred) Put(ctx context.Context, cid *cid.ID, issuer *owner.ID, box *accessbox.AccessBox, keys ...*ecdsa.PublicKey) (*object.Address, error) {
|
||||
var (
|
||||
err error
|
||||
created = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
|
Loading…
Reference in a new issue