forked from TrueCloudLab/frostfs-node
01ed366e99
Add `WithEncryption` option that passes ECDSA key to the persistent session storage. It uses 32 bytes from marshalled ECDSA key in ASN.1 DER from in AES-256 algorithm encryption in Galois/Counter Mode. Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
76 lines
1.6 KiB
Go
76 lines
1.6 KiB
Go
package persistent
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/x509"
|
|
"encoding/binary"
|
|
"fmt"
|
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/services/session/storage"
|
|
"go.etcd.io/bbolt"
|
|
)
|
|
|
|
const expOffset = 8
|
|
|
|
func (s *TokenStore) packToken(exp uint64, key *ecdsa.PrivateKey) ([]byte, error) {
|
|
rawKey, err := x509.MarshalECPrivateKey(key)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not marshal private key: %w", err)
|
|
}
|
|
|
|
if s.gcm != nil {
|
|
rawKey, err = s.encrypt(rawKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not encrypt session key: %w", err)
|
|
}
|
|
}
|
|
|
|
res := make([]byte, expOffset, expOffset+len(rawKey))
|
|
binary.LittleEndian.PutUint64(res, exp)
|
|
|
|
res = append(res, rawKey...)
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func (s *TokenStore) unpackToken(raw []byte) (*storage.PrivateToken, error) {
|
|
var err error
|
|
|
|
epoch := epochFromToken(raw)
|
|
rawKey := raw[expOffset:]
|
|
|
|
if s.gcm != nil {
|
|
rawKey, err = s.decrypt(rawKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not decrypt session key: %w", err)
|
|
}
|
|
}
|
|
|
|
key, err := x509.ParseECPrivateKey(rawKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not unmarshal private key: %w", err)
|
|
}
|
|
|
|
return storage.NewPrivateToken(key, epoch), nil
|
|
}
|
|
|
|
func epochFromToken(rawToken []byte) uint64 {
|
|
return binary.LittleEndian.Uint64(rawToken)
|
|
}
|
|
|
|
func iterateNestedBuckets(b *bbolt.Bucket, fn func(b *bbolt.Bucket) error) error {
|
|
c := b.Cursor()
|
|
|
|
for k, v := c.First(); k != nil; k, v = c.Next() {
|
|
// nil value is a hallmark
|
|
// of the nested buckets
|
|
if v == nil {
|
|
err := fn(b.Bucket(k))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|