160 lines
4.7 KiB
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
|
|
}
|