storj/pkg/storj/piecekey.go

160 lines
4.7 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package storj
import (
"database/sql/driver"
"github.com/zeebo/errs"
"golang.org/x/crypto/ed25519"
)
// ErrPieceKey is used when something goes wrong with a piece key
var ErrPieceKey = errs.Class("piece key error")
// PiecePublicKey is the unique identifier for pieces
type PiecePublicKey struct {
pub ed25519.PublicKey
}
// PiecePrivateKey is the unique identifier for pieces
type PiecePrivateKey struct {
priv ed25519.PrivateKey
}
// NewPieceKey creates a piece key pair
func NewPieceKey() (PiecePublicKey, PiecePrivateKey, error) {
pub, priv, err := ed25519.GenerateKey(nil)
return PiecePublicKey{pub}, PiecePrivateKey{priv}, ErrPieceKey.Wrap(err)
}
// PiecePublicKeyFromBytes converts bytes to a piece public key.
func PiecePublicKeyFromBytes(data []byte) (PiecePublicKey, error) {
if len(data) != ed25519.PublicKeySize {
return PiecePublicKey{}, ErrPieceKey.New("invalid public key length %v", len(data))
}
return PiecePublicKey{ed25519.PublicKey(data)}, nil
}
// PiecePrivateKeyFromBytes converts bytes to a piece private key.
func PiecePrivateKeyFromBytes(data []byte) (PiecePrivateKey, error) {
if len(data) != ed25519.PrivateKeySize {
return PiecePrivateKey{}, ErrPieceKey.New("invalid private key length %v", len(data))
}
return PiecePrivateKey{ed25519.PrivateKey(data)}, nil
}
// Sign signs the message with privateKey and returns a signature.
func (key PiecePrivateKey) Sign(data []byte) ([]byte, error) {
if len(key.priv) != ed25519.PrivateKeySize {
return nil, ErrPieceKey.New("invalid private key length %v", len(key.priv))
}
return ed25519.Sign(key.priv, data), nil
}
// Verify reports whether signature is a valid signature of message by publicKey.
func (key PiecePublicKey) Verify(data, signature []byte) error {
if len(key.pub) != ed25519.PublicKeySize {
return ErrPieceKey.New("invalid public key length %v", len(key.pub))
}
if !ed25519.Verify(key.pub, data, signature) {
return ErrPieceKey.New("invalid signature")
}
return nil
}
// Bytes returns bytes of the piece public key
func (key PiecePublicKey) Bytes() []byte { return key.pub[:] }
// Bytes returns bytes of the piece private key
func (key PiecePrivateKey) Bytes() []byte { return key.priv[:] }
// IsZero returns whether the key is empty.
func (key PiecePublicKey) IsZero() bool { return len(key.pub) == 0 }
// IsZero returns whether the key is empty.
func (key PiecePrivateKey) IsZero() bool { return len(key.priv) == 0 }
// Marshal serializes a piece public key
func (key PiecePublicKey) Marshal() ([]byte, error) { return key.Bytes(), nil }
// Marshal serializes a piece private key
func (key PiecePrivateKey) Marshal() ([]byte, error) { return key.Bytes(), nil }
// MarshalTo serializes a piece public key into the passed byte slice
func (key *PiecePublicKey) MarshalTo(data []byte) (n int, err error) {
n = copy(data, key.Bytes())
return n, nil
}
// MarshalTo serializes a piece private key into the passed byte slice
func (key *PiecePrivateKey) MarshalTo(data []byte) (n int, err error) {
n = copy(data, key.Bytes())
return n, nil
}
// Unmarshal deserializes a piece public key
func (key *PiecePublicKey) Unmarshal(data []byte) error {
// allow empty keys
if len(data) == 0 {
key.pub = nil
return nil
}
var err error
*key, err = PiecePublicKeyFromBytes(data)
return err
}
// Unmarshal deserializes a piece private key
func (key *PiecePrivateKey) Unmarshal(data []byte) error {
// allow empty keys
if len(data) == 0 {
key.priv = nil
return nil
}
if len(data) == 0 {
return nil
}
var err error
*key, err = PiecePrivateKeyFromBytes(data)
return err
}
// Size returns the length of a piece public key (implements gogo's custom type interface)
func (key *PiecePublicKey) Size() int { return len(key.pub) }
// Size returns the length of a piece private key (implements gogo's custom type interface)
func (key *PiecePrivateKey) Size() int { return len(key.priv) }
// Value set a PiecePublicKey to a database field
func (key PiecePublicKey) Value() (driver.Value, error) {
return key.Bytes(), nil
}
// Value set a PiecePrivateKey to a database field
func (key PiecePrivateKey) Value() (driver.Value, error) { return key.Bytes(), nil }
// Scan extracts a PiecePublicKey from a database field
func (key *PiecePublicKey) Scan(src interface{}) (err error) {
b, ok := src.([]byte)
if !ok {
return ErrPieceKey.New("PiecePublicKey Scan expects []byte")
}
n, err := PiecePublicKeyFromBytes(b)
*key = n
return err
}
// Scan extracts a PiecePrivateKey from a database field
func (key *PiecePrivateKey) Scan(src interface{}) (err error) {
b, ok := src.([]byte)
if !ok {
return ErrPieceKey.New("PiecePrivateKey Scan expects []byte")
}
n, err := PiecePrivateKeyFromBytes(b)
*key = n
return err
}