Adapt storj and encryption packages (#513)
This commit is contained in:
parent
fc2fe0c294
commit
ac4805a841
@ -17,6 +17,7 @@ import (
|
||||
"storj.io/storj/pkg/eestream"
|
||||
"storj.io/storj/pkg/encryption"
|
||||
"storj.io/storj/pkg/ranger"
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -37,15 +38,14 @@ func main() {
|
||||
|
||||
// Main is the exported CLI executable function
|
||||
func Main() error {
|
||||
encKey := encryption.Key(sha256.Sum256([]byte(*key)))
|
||||
encKey := storj.Key(sha256.Sum256([]byte(*key)))
|
||||
fc, err := infectious.NewFEC(*rsk, *rsn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
es := eestream.NewRSScheme(fc, *erasureShareSize)
|
||||
var firstNonce encryption.Nonce
|
||||
cipher := encryption.AESGCM
|
||||
decrypter, err := cipher.NewDecrypter(&encKey, &firstNonce, es.StripeSize())
|
||||
var firstNonce storj.Nonce
|
||||
decrypter, err := encryption.NewDecrypter(storj.AESGCM, &encKey, &firstNonce, es.StripeSize())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"storj.io/storj/pkg/eestream"
|
||||
"storj.io/storj/pkg/encryption"
|
||||
"storj.io/storj/pkg/ranger"
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -46,15 +47,14 @@ func main() {
|
||||
|
||||
// Main is the exported CLI executable function
|
||||
func Main() error {
|
||||
encKey := encryption.Key(sha256.Sum256([]byte(*key)))
|
||||
encKey := storj.Key(sha256.Sum256([]byte(*key)))
|
||||
fc, err := infectious.NewFEC(*rsk, *rsn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
es := eestream.NewRSScheme(fc, *erasureShareSize)
|
||||
var firstNonce encryption.Nonce
|
||||
cipher := encryption.AESGCM
|
||||
decrypter, err := cipher.NewDecrypter(&encKey, &firstNonce, es.StripeSize())
|
||||
var firstNonce storj.Nonce
|
||||
decrypter, err := encryption.NewDecrypter(storj.AESGCM, &encKey, &firstNonce, es.StripeSize())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
|
||||
"storj.io/storj/pkg/eestream"
|
||||
"storj.io/storj/pkg/encryption"
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -53,10 +54,9 @@ func Main() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
encKey := encryption.Key(sha256.Sum256([]byte(*key)))
|
||||
var firstNonce encryption.Nonce
|
||||
cipher := encryption.AESGCM
|
||||
encrypter, err := cipher.NewEncrypter(&encKey, &firstNonce, es.StripeSize())
|
||||
encKey := storj.Key(sha256.Sum256([]byte(*key)))
|
||||
var firstNonce storj.Nonce
|
||||
encrypter, err := encryption.NewEncrypter(storj.AESGCM, &encKey, &firstNonce, es.StripeSize())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"storj.io/storj/internal/pkg/readcloser"
|
||||
"storj.io/storj/pkg/encryption"
|
||||
"storj.io/storj/pkg/ranger"
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
func randData(amount int) []byte {
|
||||
@ -103,10 +104,9 @@ func TestRSRanger(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
encKey := encryption.Key(sha256.Sum256([]byte("the secret key")))
|
||||
var firstNonce encryption.Nonce
|
||||
cipher := encryption.AESGCM
|
||||
encrypter, err := cipher.NewEncrypter(&encKey, &firstNonce, rs.StripeSize())
|
||||
encKey := storj.Key(sha256.Sum256([]byte("the secret key")))
|
||||
var firstNonce storj.Nonce
|
||||
encrypter, err := encryption.NewEncrypter(storj.AESGCM, &encKey, &firstNonce, rs.StripeSize())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -123,7 +123,7 @@ func TestRSRanger(t *testing.T) {
|
||||
for i, piece := range pieces {
|
||||
rrs[i] = ranger.ByteRanger(piece)
|
||||
}
|
||||
decrypter, err := cipher.NewDecrypter(&encKey, &firstNonce, rs.StripeSize())
|
||||
decrypter, err := encryption.NewDecrypter(storj.AESGCM, &encKey, &firstNonce, rs.StripeSize())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -8,12 +8,14 @@ import (
|
||||
"crypto/cipher"
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
type aesgcmEncrypter struct {
|
||||
blockSize int
|
||||
key Key
|
||||
startingNonce AESGCMNonce
|
||||
key *storj.Key
|
||||
startingNonce *AESGCMNonce
|
||||
overhead int
|
||||
aesgcm cipher.AEAD
|
||||
}
|
||||
@ -31,8 +33,8 @@ type aesgcmEncrypter struct {
|
||||
//
|
||||
// When in doubt, generate a new key from crypto/rand and a startingNonce
|
||||
// from crypto/rand as often as possible.
|
||||
func NewAESGCMEncrypter(key *Key, startingNonce *AESGCMNonce, encryptedBlockSize int) (Transformer, error) {
|
||||
block, err := aes.NewCipher((*key)[:])
|
||||
func NewAESGCMEncrypter(key *storj.Key, startingNonce *AESGCMNonce, encryptedBlockSize int) (Transformer, error) {
|
||||
block, err := aes.NewCipher(key[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -45,8 +47,8 @@ func NewAESGCMEncrypter(key *Key, startingNonce *AESGCMNonce, encryptedBlockSize
|
||||
}
|
||||
return &aesgcmEncrypter{
|
||||
blockSize: encryptedBlockSize - aesgcmEncrypt.Overhead(),
|
||||
key: *key,
|
||||
startingNonce: *startingNonce,
|
||||
key: key,
|
||||
startingNonce: startingNonce,
|
||||
overhead: aesgcmEncrypt.Overhead(),
|
||||
aesgcm: aesgcmEncrypt,
|
||||
}, nil
|
||||
@ -69,19 +71,19 @@ func calcGCMNonce(startingNonce *AESGCMNonce, blockNum int64) (rv [12]byte, err
|
||||
}
|
||||
|
||||
func (s *aesgcmEncrypter) Transform(out, in []byte, blockNum int64) ([]byte, error) {
|
||||
n, err := calcGCMNonce(&s.startingNonce, blockNum)
|
||||
nonce, err := calcGCMNonce(s.startingNonce, blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertext := s.aesgcm.Seal(out, n[:], in, nil)
|
||||
ciphertext := s.aesgcm.Seal(out, nonce[:], in, nil)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
type aesgcmDecrypter struct {
|
||||
blockSize int
|
||||
key Key
|
||||
startingNonce AESGCMNonce
|
||||
key *storj.Key
|
||||
startingNonce *AESGCMNonce
|
||||
overhead int
|
||||
aesgcm cipher.AEAD
|
||||
}
|
||||
@ -89,7 +91,7 @@ type aesgcmDecrypter struct {
|
||||
// NewAESGCMDecrypter returns a Transformer that decrypts the data passing
|
||||
// through with key. See the comments for NewAESGCMEncrypter about
|
||||
// startingNonce.
|
||||
func NewAESGCMDecrypter(key *Key, startingNonce *AESGCMNonce, encryptedBlockSize int) (Transformer, error) {
|
||||
func NewAESGCMDecrypter(key *storj.Key, startingNonce *AESGCMNonce, encryptedBlockSize int) (Transformer, error) {
|
||||
block, err := aes.NewCipher(key[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -103,8 +105,8 @@ func NewAESGCMDecrypter(key *Key, startingNonce *AESGCMNonce, encryptedBlockSize
|
||||
}
|
||||
return &aesgcmDecrypter{
|
||||
blockSize: encryptedBlockSize - aesgcmDecrypt.Overhead(),
|
||||
key: *key,
|
||||
startingNonce: *startingNonce,
|
||||
key: key,
|
||||
startingNonce: startingNonce,
|
||||
overhead: aesgcmDecrypt.Overhead(),
|
||||
aesgcm: aesgcmDecrypt,
|
||||
}, nil
|
||||
@ -118,16 +120,16 @@ func (s *aesgcmDecrypter) OutBlockSize() int {
|
||||
}
|
||||
|
||||
func (s *aesgcmDecrypter) Transform(out, in []byte, blockNum int64) ([]byte, error) {
|
||||
n, err := calcGCMNonce(&s.startingNonce, blockNum)
|
||||
nonce, err := calcGCMNonce(s.startingNonce, blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.aesgcm.Open(out, n[:], in, nil)
|
||||
return s.aesgcm.Open(out, nonce[:], in, nil)
|
||||
}
|
||||
|
||||
// EncryptAESGCM encrypts byte data with a key and nonce. The cipher data is returned
|
||||
func EncryptAESGCM(data []byte, key *Key, nonce *AESGCMNonce) (cipherData []byte, err error) {
|
||||
func EncryptAESGCM(data []byte, key *storj.Key, nonce *AESGCMNonce) (cipherData []byte, err error) {
|
||||
block, err := aes.NewCipher(key[:])
|
||||
if err != nil {
|
||||
return []byte{}, errs.Wrap(err)
|
||||
@ -141,7 +143,7 @@ func EncryptAESGCM(data []byte, key *Key, nonce *AESGCMNonce) (cipherData []byte
|
||||
}
|
||||
|
||||
// DecryptAESGCM decrypts byte data with a key and nonce. The plain data is returned
|
||||
func DecryptAESGCM(cipherData []byte, key *Key, nonce *AESGCMNonce) (data []byte, err error) {
|
||||
func DecryptAESGCM(cipherData []byte, key *storj.Key, nonce *AESGCMNonce) (data []byte, err error) {
|
||||
if len(cipherData) == 0 {
|
||||
return []byte{}, errs.New("empty cipher data")
|
||||
}
|
||||
|
@ -7,11 +7,13 @@ import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
func TestAesGcm(t *testing.T) {
|
||||
var key Key
|
||||
copy(key[:], randData(KeySize))
|
||||
var key storj.Key
|
||||
copy(key[:], randData(storj.KeySize))
|
||||
var firstNonce AESGCMNonce
|
||||
copy(firstNonce[:], randData(AESGCMNonceSize))
|
||||
encrypter, err := NewAESGCMEncrypter(&key, &firstNonce, 4*1024)
|
||||
|
@ -5,138 +5,98 @@ package encryption
|
||||
|
||||
import (
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
// Cipher is a type used to define the type of encryption to use
|
||||
type Cipher byte
|
||||
// AESGCMNonceSize is the size of an AES-GCM nonce
|
||||
const AESGCMNonceSize = 12
|
||||
|
||||
// Constant definitions for no encryption (0), AESGCM (1), and SecretBox (2)
|
||||
const (
|
||||
None = Cipher(iota)
|
||||
AESGCM
|
||||
SecretBox
|
||||
)
|
||||
// AESGCMNonce represents the nonce used by the AES-GCM protocol
|
||||
type AESGCMNonce [AESGCMNonceSize]byte
|
||||
|
||||
// Constant definitions for key and nonce sizes
|
||||
const (
|
||||
KeySize = 32
|
||||
NonceSize = 24
|
||||
AESGCMNonceSize = 12
|
||||
)
|
||||
|
||||
// Key represents the largest key used by any encryption protocol
|
||||
type Key [KeySize]byte
|
||||
|
||||
// Bytes returns the key as a byte array pointer
|
||||
func (k *Key) Bytes() *[KeySize]byte {
|
||||
return (*[KeySize]byte)(k)
|
||||
}
|
||||
|
||||
// Encrypt encrypts the current key with the given key and nonce
|
||||
func (k *Key) Encrypt(cipher Cipher, key *Key, nonce *Nonce) (EncryptedPrivateKey, error) {
|
||||
return cipher.Encrypt(k[:], key, nonce)
|
||||
}
|
||||
|
||||
// Nonce represents the largest nonce used by any encryption protocol
|
||||
type Nonce [NonceSize]byte
|
||||
|
||||
// Bytes returns the nonce as a byte array pointer
|
||||
func (nonce *Nonce) Bytes() *[NonceSize]byte {
|
||||
return (*[NonceSize]byte)(nonce)
|
||||
}
|
||||
|
||||
// Increment increments the nonce with the given amount
|
||||
func (nonce *Nonce) Increment(amount int64) (truncated bool, err error) {
|
||||
return incrementBytes(nonce[:], amount)
|
||||
}
|
||||
|
||||
// AESGCMNonce returns the nonce as a AES-GCM nonce
|
||||
func (nonce *Nonce) AESGCMNonce() *AESGCMNonce {
|
||||
// ToAESGCMNonce returns the nonce as a AES-GCM nonce
|
||||
func ToAESGCMNonce(nonce *storj.Nonce) *AESGCMNonce {
|
||||
aes := new(AESGCMNonce)
|
||||
copy((*aes)[:], nonce[:AESGCMNonceSize])
|
||||
return aes
|
||||
}
|
||||
|
||||
// AESGCMNonce represents the nonce used by the AES-GCM protocol
|
||||
type AESGCMNonce [AESGCMNonceSize]byte
|
||||
|
||||
// Bytes returns the nonce as a byte array pointer
|
||||
func (nonce *AESGCMNonce) Bytes() *[AESGCMNonceSize]byte {
|
||||
return (*[AESGCMNonceSize]byte)(nonce)
|
||||
// Increment increments the nonce with the given amount
|
||||
func Increment(nonce *storj.Nonce, amount int64) (truncated bool, err error) {
|
||||
return incrementBytes(nonce[:], amount)
|
||||
}
|
||||
|
||||
// EncryptedPrivateKey is a private key that has been encrypted
|
||||
type EncryptedPrivateKey []byte
|
||||
|
||||
// Decrypt decrypts the current key with the given key and nonce
|
||||
func (k EncryptedPrivateKey) Decrypt(cipher Cipher, key *Key, nonce *Nonce) (*Key, error) {
|
||||
plainData, err := cipher.Decrypt(k, key, nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var decryptedKey Key
|
||||
copy(decryptedKey[:], plainData)
|
||||
|
||||
return &decryptedKey, nil
|
||||
}
|
||||
|
||||
// Encrypt encrypts byte data with a key and nonce. The cipher data is returned
|
||||
// The type of encryption to use can be modified with encType
|
||||
func (cipher Cipher) Encrypt(data []byte, key *Key, nonce *Nonce) (cipherData []byte, err error) {
|
||||
// Encrypt encrypts data with the given cipher, key and nonce
|
||||
func Encrypt(data []byte, cipher storj.Cipher, key *storj.Key, nonce *storj.Nonce) (cipherData []byte, err error) {
|
||||
switch cipher {
|
||||
case None:
|
||||
case storj.Unencrypted:
|
||||
return data, nil
|
||||
case AESGCM:
|
||||
return EncryptAESGCM(data, key, nonce.AESGCMNonce())
|
||||
case SecretBox:
|
||||
case storj.AESGCM:
|
||||
return EncryptAESGCM(data, key, ToAESGCMNonce(nonce))
|
||||
case storj.SecretBox:
|
||||
return EncryptSecretBox(data, key, nonce)
|
||||
default:
|
||||
return nil, errs.New("Invalid encryption type")
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypt decrypts byte data with a key and nonce. The plain data is returned
|
||||
// The type of encryption to use can be modified with encType
|
||||
func (cipher Cipher) Decrypt(cipherData []byte, key *Key, nonce *Nonce) (data []byte, err error) {
|
||||
// Decrypt decrypts cipherData with the given cipher, key and nonce
|
||||
func Decrypt(cipherData []byte, cipher storj.Cipher, key *storj.Key, nonce *storj.Nonce) (data []byte, err error) {
|
||||
switch cipher {
|
||||
case None:
|
||||
case storj.Unencrypted:
|
||||
return cipherData, nil
|
||||
case AESGCM:
|
||||
return DecryptAESGCM(cipherData, key, nonce.AESGCMNonce())
|
||||
case SecretBox:
|
||||
case storj.AESGCM:
|
||||
return DecryptAESGCM(cipherData, key, ToAESGCMNonce(nonce))
|
||||
case storj.SecretBox:
|
||||
return DecryptSecretBox(cipherData, key, nonce)
|
||||
default:
|
||||
return nil, errs.New("Invalid encryption type")
|
||||
}
|
||||
}
|
||||
|
||||
// NewEncrypter creates transform stream using a key and a nonce to encrypt data passing through it
|
||||
// The type of encryption to use can be modified with encType
|
||||
func (cipher Cipher) NewEncrypter(key *Key, startingNonce *Nonce, encBlockSize int) (Transformer, error) {
|
||||
// NewEncrypter creates a Transformer using the given cipher, key and nonce to encrypt data passing through it
|
||||
func NewEncrypter(cipher storj.Cipher, key *storj.Key, startingNonce *storj.Nonce, encryptedBlockSize int) (Transformer, error) {
|
||||
switch cipher {
|
||||
case None:
|
||||
case storj.Unencrypted:
|
||||
return &NoopTransformer{}, nil
|
||||
case AESGCM:
|
||||
return NewAESGCMEncrypter(key, startingNonce.AESGCMNonce(), encBlockSize)
|
||||
case SecretBox:
|
||||
return NewSecretboxEncrypter(key, startingNonce, encBlockSize)
|
||||
case storj.AESGCM:
|
||||
return NewAESGCMEncrypter(key, ToAESGCMNonce(startingNonce), encryptedBlockSize)
|
||||
case storj.SecretBox:
|
||||
return NewSecretboxEncrypter(key, startingNonce, encryptedBlockSize)
|
||||
default:
|
||||
return nil, errs.New("Invalid encryption type")
|
||||
}
|
||||
}
|
||||
|
||||
// NewDecrypter creates transform stream using a key and a nonce to decrypt data passing through it
|
||||
// The type of encryption to use can be modified with encType
|
||||
func (cipher Cipher) NewDecrypter(key *Key, startingNonce *Nonce, encBlockSize int) (Transformer, error) {
|
||||
// NewDecrypter creates a Transformer using the given cipher, key and nonce to decrypt data passing through it
|
||||
func NewDecrypter(cipher storj.Cipher, key *storj.Key, startingNonce *storj.Nonce, encryptedBlockSize int) (Transformer, error) {
|
||||
switch cipher {
|
||||
case None:
|
||||
case storj.Unencrypted:
|
||||
return &NoopTransformer{}, nil
|
||||
case AESGCM:
|
||||
return NewAESGCMDecrypter(key, startingNonce.AESGCMNonce(), encBlockSize)
|
||||
case SecretBox:
|
||||
return NewSecretboxDecrypter(key, startingNonce, encBlockSize)
|
||||
case storj.AESGCM:
|
||||
return NewAESGCMDecrypter(key, ToAESGCMNonce(startingNonce), encryptedBlockSize)
|
||||
case storj.SecretBox:
|
||||
return NewSecretboxDecrypter(key, startingNonce, encryptedBlockSize)
|
||||
default:
|
||||
return nil, errs.New("Invalid encryption type")
|
||||
}
|
||||
}
|
||||
|
||||
// EncryptKey encrypts keyToEncrypt with the given cipher, key and nonce
|
||||
func EncryptKey(keyToEncrypt *storj.Key, cipher storj.Cipher, key *storj.Key, nonce *storj.Nonce) (storj.EncryptedPrivateKey, error) {
|
||||
return Encrypt(keyToEncrypt[:], cipher, key, nonce)
|
||||
}
|
||||
|
||||
// DecryptKey decrypts keyToDecrypt with the given cipher, key and nonce
|
||||
func DecryptKey(keyToDecrypt storj.EncryptedPrivateKey, cipher storj.Cipher, key *storj.Key, nonce *storj.Nonce) (*storj.Key, error) {
|
||||
plainData, err := Decrypt(keyToDecrypt, cipher, key, nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var decryptedKey storj.Key
|
||||
copy(decryptedKey[:], plainData)
|
||||
|
||||
return &decryptedKey, nil
|
||||
}
|
||||
|
@ -6,12 +6,14 @@ package encryption
|
||||
import (
|
||||
"github.com/zeebo/errs"
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
type secretboxEncrypter struct {
|
||||
blockSize int
|
||||
key Key
|
||||
startingNonce Nonce
|
||||
key *storj.Key
|
||||
startingNonce *storj.Nonce
|
||||
}
|
||||
|
||||
// NewSecretboxEncrypter returns a Transformer that encrypts the data passing
|
||||
@ -27,14 +29,14 @@ type secretboxEncrypter struct {
|
||||
//
|
||||
// When in doubt, generate a new key from crypto/rand and a startingNonce
|
||||
// from crypto/rand as often as possible.
|
||||
func NewSecretboxEncrypter(key *Key, startingNonce *Nonce, encryptedBlockSize int) (Transformer, error) {
|
||||
func NewSecretboxEncrypter(key *storj.Key, startingNonce *storj.Nonce, encryptedBlockSize int) (Transformer, error) {
|
||||
if encryptedBlockSize <= secretbox.Overhead {
|
||||
return nil, Error.New("block size too small")
|
||||
}
|
||||
return &secretboxEncrypter{
|
||||
blockSize: encryptedBlockSize - secretbox.Overhead,
|
||||
key: *key,
|
||||
startingNonce: *startingNonce,
|
||||
key: key,
|
||||
startingNonce: startingNonce,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -46,8 +48,8 @@ func (s *secretboxEncrypter) OutBlockSize() int {
|
||||
return s.blockSize + secretbox.Overhead
|
||||
}
|
||||
|
||||
func calcNonce(startingNonce *Nonce, blockNum int64) (rv *Nonce, err error) {
|
||||
rv = new(Nonce)
|
||||
func calcNonce(startingNonce *storj.Nonce, blockNum int64) (rv *storj.Nonce, err error) {
|
||||
rv = new(storj.Nonce)
|
||||
if copy(rv[:], (*startingNonce)[:]) != len(rv) {
|
||||
return rv, Error.New("didn't copy memory?!")
|
||||
}
|
||||
@ -56,30 +58,30 @@ func calcNonce(startingNonce *Nonce, blockNum int64) (rv *Nonce, err error) {
|
||||
}
|
||||
|
||||
func (s *secretboxEncrypter) Transform(out, in []byte, blockNum int64) ([]byte, error) {
|
||||
n, err := calcNonce(&s.startingNonce, blockNum)
|
||||
nonce, err := calcNonce(s.startingNonce, blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return secretbox.Seal(out, in, n.Bytes(), s.key.Bytes()), nil
|
||||
return secretbox.Seal(out, in, nonce.Raw(), s.key.Raw()), nil
|
||||
}
|
||||
|
||||
type secretboxDecrypter struct {
|
||||
blockSize int
|
||||
key Key
|
||||
startingNonce Nonce
|
||||
key *storj.Key
|
||||
startingNonce *storj.Nonce
|
||||
}
|
||||
|
||||
// NewSecretboxDecrypter returns a Transformer that decrypts the data passing
|
||||
// through with key. See the comments for NewSecretboxEncrypter about
|
||||
// startingNonce.
|
||||
func NewSecretboxDecrypter(key *Key, startingNonce *Nonce, encryptedBlockSize int) (Transformer, error) {
|
||||
func NewSecretboxDecrypter(key *storj.Key, startingNonce *storj.Nonce, encryptedBlockSize int) (Transformer, error) {
|
||||
if encryptedBlockSize <= secretbox.Overhead {
|
||||
return nil, Error.New("block size too small")
|
||||
}
|
||||
return &secretboxDecrypter{
|
||||
blockSize: encryptedBlockSize - secretbox.Overhead,
|
||||
key: *key,
|
||||
startingNonce: *startingNonce,
|
||||
key: key,
|
||||
startingNonce: startingNonce,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -92,11 +94,11 @@ func (s *secretboxDecrypter) OutBlockSize() int {
|
||||
}
|
||||
|
||||
func (s *secretboxDecrypter) Transform(out, in []byte, blockNum int64) ([]byte, error) {
|
||||
n, err := calcNonce(&s.startingNonce, blockNum)
|
||||
nonce, err := calcNonce(s.startingNonce, blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rv, success := secretbox.Open(out, in, n.Bytes(), s.key.Bytes())
|
||||
rv, success := secretbox.Open(out, in, nonce.Raw(), s.key.Raw())
|
||||
if !success {
|
||||
return nil, Error.New("failed decrypting")
|
||||
}
|
||||
@ -104,13 +106,13 @@ func (s *secretboxDecrypter) Transform(out, in []byte, blockNum int64) ([]byte,
|
||||
}
|
||||
|
||||
// EncryptSecretBox encrypts byte data with a key and nonce. The cipher data is returned
|
||||
func EncryptSecretBox(data []byte, key *Key, nonce *Nonce) (cipherData []byte, err error) {
|
||||
return secretbox.Seal(nil, data, nonce.Bytes(), key.Bytes()), nil
|
||||
func EncryptSecretBox(data []byte, key *storj.Key, nonce *storj.Nonce) (cipherData []byte, err error) {
|
||||
return secretbox.Seal(nil, data, nonce.Raw(), key.Raw()), nil
|
||||
}
|
||||
|
||||
// DecryptSecretBox decrypts byte data with a key and nonce. The plain data is returned
|
||||
func DecryptSecretBox(cipherData []byte, key *Key, nonce *Nonce) (data []byte, err error) {
|
||||
data, success := secretbox.Open(nil, cipherData, nonce.Bytes(), key.Bytes())
|
||||
func DecryptSecretBox(cipherData []byte, key *storj.Key, nonce *storj.Nonce) (data []byte, err error) {
|
||||
data, success := secretbox.Open(nil, cipherData, nonce.Raw(), key.Raw())
|
||||
if !success {
|
||||
return nil, errs.New("Failed decrypting")
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"crypto/rand"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
func randData(amount int) []byte {
|
||||
@ -20,10 +22,10 @@ func randData(amount int) []byte {
|
||||
}
|
||||
|
||||
func TestSecretbox(t *testing.T) {
|
||||
var key Key
|
||||
copy(key[:], randData(KeySize))
|
||||
var firstNonce Nonce
|
||||
copy(firstNonce[:], randData(NonceSize))
|
||||
var key storj.Key
|
||||
copy(key[:], randData(storj.KeySize))
|
||||
var firstNonce storj.Nonce
|
||||
copy(firstNonce[:], randData(storj.NonceSize))
|
||||
encrypter, err := NewSecretboxEncrypter(&key, &firstNonce, 4*1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"storj.io/storj/pkg/storage/objects"
|
||||
segment "storj.io/storj/pkg/storage/segments"
|
||||
streams "storj.io/storj/pkg/storage/streams"
|
||||
"storj.io/storj/pkg/storj"
|
||||
"storj.io/storj/pkg/transport"
|
||||
)
|
||||
|
||||
@ -154,7 +155,7 @@ func (c Config) GetBucketStore(ctx context.Context, identity *provider.FullIdent
|
||||
err = Error.New("EncryptionBlockSize must be a multiple of ErasureShareSize * RS MinThreshold")
|
||||
return nil, err
|
||||
}
|
||||
stream, err := streams.NewStreamStore(segments, c.SegmentSize, c.EncKey, c.EncBlockSize, c.EncType)
|
||||
stream, err := streams.NewStreamStore(segments, c.SegmentSize, c.EncKey, c.EncBlockSize, storj.Cipher(c.EncType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
ranger "storj.io/storj/pkg/ranger"
|
||||
"storj.io/storj/pkg/storage/meta"
|
||||
"storj.io/storj/pkg/storage/segments"
|
||||
"storj.io/storj/pkg/storj"
|
||||
"storj.io/storj/storage"
|
||||
)
|
||||
|
||||
@ -68,11 +69,11 @@ type streamStore struct {
|
||||
segmentSize int64
|
||||
rootKey []byte
|
||||
encBlockSize int
|
||||
encType encryption.Cipher
|
||||
cipher storj.Cipher
|
||||
}
|
||||
|
||||
// NewStreamStore stuff
|
||||
func NewStreamStore(segments segments.Store, segmentSize int64, rootKey string, encBlockSize int, encType int) (Store, error) {
|
||||
func NewStreamStore(segments segments.Store, segmentSize int64, rootKey string, encBlockSize int, cipher storj.Cipher) (Store, error) {
|
||||
if segmentSize <= 0 {
|
||||
return nil, errs.New("segment size must be larger than 0")
|
||||
}
|
||||
@ -88,7 +89,7 @@ func NewStreamStore(segments segments.Store, segmentSize int64, rootKey string,
|
||||
segmentSize: segmentSize,
|
||||
rootKey: []byte(rootKey),
|
||||
encBlockSize: encBlockSize,
|
||||
encType: encryption.Cipher(encType),
|
||||
cipher: cipher,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -122,13 +123,12 @@ func (s *streamStore) Put(ctx context.Context, path paths.Path, data io.Reader,
|
||||
if err != nil {
|
||||
return Meta{}, err
|
||||
}
|
||||
cipher := s.encType
|
||||
|
||||
eofReader := NewEOFReader(data)
|
||||
|
||||
for !eofReader.isEOF() && !eofReader.hasError() {
|
||||
// generate random key for encrypting the segment's content
|
||||
var contentKey encryption.Key
|
||||
var contentKey storj.Key
|
||||
_, err = rand.Read(contentKey[:])
|
||||
if err != nil {
|
||||
return Meta{}, err
|
||||
@ -137,25 +137,25 @@ func (s *streamStore) Put(ctx context.Context, path paths.Path, data io.Reader,
|
||||
// Initialize the content nonce with the segment's index incremented by 1.
|
||||
// The increment by 1 is to avoid nonce reuse with the metadata encryption,
|
||||
// which is encrypted with the zero nonce.
|
||||
var contentNonce encryption.Nonce
|
||||
_, err := contentNonce.Increment(currentSegment + 1)
|
||||
var contentNonce storj.Nonce
|
||||
_, err := encryption.Increment(&contentNonce, currentSegment+1)
|
||||
if err != nil {
|
||||
return Meta{}, err
|
||||
}
|
||||
|
||||
encrypter, err := cipher.NewEncrypter(&contentKey, &contentNonce, s.encBlockSize)
|
||||
encrypter, err := encryption.NewEncrypter(s.cipher, &contentKey, &contentNonce, s.encBlockSize)
|
||||
if err != nil {
|
||||
return Meta{}, err
|
||||
}
|
||||
|
||||
// generate random nonce for encrypting the content key
|
||||
var keyNonce encryption.Nonce
|
||||
var keyNonce storj.Nonce
|
||||
_, err = rand.Read(keyNonce[:])
|
||||
if err != nil {
|
||||
return Meta{}, err
|
||||
}
|
||||
|
||||
encryptedKey, err := contentKey.Encrypt(cipher, (*encryption.Key)(derivedKey), &keyNonce)
|
||||
encryptedKey, err := encryption.EncryptKey(&contentKey, s.cipher, (*storj.Key)(derivedKey), &keyNonce)
|
||||
if err != nil {
|
||||
return Meta{}, err
|
||||
}
|
||||
@ -176,7 +176,7 @@ func (s *streamStore) Put(ctx context.Context, path paths.Path, data io.Reader,
|
||||
if err != nil {
|
||||
return Meta{}, err
|
||||
}
|
||||
cipherData, err := cipher.Encrypt(data, &contentKey, &contentNonce)
|
||||
cipherData, err := encryption.Encrypt(data, s.cipher, &contentKey, &contentNonce)
|
||||
if err != nil {
|
||||
return Meta{}, err
|
||||
}
|
||||
@ -192,7 +192,7 @@ func (s *streamStore) Put(ctx context.Context, path paths.Path, data io.Reader,
|
||||
if !eofReader.isEOF() {
|
||||
segmentPath := getSegmentPath(encPath, currentSegment)
|
||||
|
||||
if cipher == encryption.None {
|
||||
if s.cipher == storj.Unencrypted {
|
||||
return segmentPath, nil, nil
|
||||
}
|
||||
|
||||
@ -220,18 +220,18 @@ func (s *streamStore) Put(ctx context.Context, path paths.Path, data io.Reader,
|
||||
}
|
||||
|
||||
// encrypt metadata with the content encryption key and zero nonce
|
||||
encryptedStreamInfo, err := cipher.Encrypt(streamInfo, &contentKey, &encryption.Nonce{})
|
||||
encryptedStreamInfo, err := encryption.Encrypt(streamInfo, s.cipher, &contentKey, &storj.Nonce{})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
streamMeta := pb.StreamMeta{
|
||||
EncryptedStreamInfo: encryptedStreamInfo,
|
||||
EncryptionType: int32(s.encType),
|
||||
EncryptionType: int32(s.cipher),
|
||||
EncryptionBlockSize: int32(s.encBlockSize),
|
||||
}
|
||||
|
||||
if cipher != encryption.None {
|
||||
if s.cipher != storj.Unencrypted {
|
||||
streamMeta.LastSegmentMeta = &pb.SegmentMeta{
|
||||
EncryptedKey: encryptedKey,
|
||||
KeyNonce: keyNonce[:],
|
||||
@ -314,8 +314,8 @@ func (s *streamStore) Get(ctx context.Context, path paths.Path) (rr ranger.Range
|
||||
for i := int64(0); i < stream.NumberOfSegments-1; i++ {
|
||||
currentPath := getSegmentPath(encPath, i)
|
||||
size := stream.SegmentsSize
|
||||
var contentNonce encryption.Nonce
|
||||
_, err := contentNonce.Increment(i + 1)
|
||||
var contentNonce storj.Nonce
|
||||
_, err := encryption.Increment(&contentNonce, i+1)
|
||||
if err != nil {
|
||||
return nil, Meta{}, err
|
||||
}
|
||||
@ -323,16 +323,16 @@ func (s *streamStore) Get(ctx context.Context, path paths.Path) (rr ranger.Range
|
||||
segments: s.segments,
|
||||
path: currentPath,
|
||||
size: size,
|
||||
derivedKey: (*encryption.Key)(derivedKey),
|
||||
derivedKey: (*storj.Key)(derivedKey),
|
||||
startingNonce: &contentNonce,
|
||||
encBlockSize: int(streamMeta.EncryptionBlockSize),
|
||||
encType: encryption.Cipher(streamMeta.EncryptionType),
|
||||
cipher: storj.Cipher(streamMeta.EncryptionType),
|
||||
}
|
||||
rangers = append(rangers, rr)
|
||||
}
|
||||
|
||||
var contentNonce encryption.Nonce
|
||||
_, err = contentNonce.Increment(stream.NumberOfSegments)
|
||||
var contentNonce storj.Nonce
|
||||
_, err = encryption.Increment(&contentNonce, stream.NumberOfSegments)
|
||||
if err != nil {
|
||||
return nil, Meta{}, err
|
||||
}
|
||||
@ -341,8 +341,8 @@ func (s *streamStore) Get(ctx context.Context, path paths.Path) (rr ranger.Range
|
||||
ctx,
|
||||
lastSegmentRanger,
|
||||
stream.LastSegmentSize,
|
||||
encryption.Cipher(streamMeta.EncryptionType),
|
||||
(*encryption.Key)(derivedKey),
|
||||
storj.Cipher(streamMeta.EncryptionType),
|
||||
(*storj.Key)(derivedKey),
|
||||
encryptedKey,
|
||||
keyNonce,
|
||||
&contentNonce,
|
||||
@ -518,10 +518,10 @@ type lazySegmentRanger struct {
|
||||
segments segments.Store
|
||||
path paths.Path
|
||||
size int64
|
||||
derivedKey *encryption.Key
|
||||
startingNonce *encryption.Nonce
|
||||
derivedKey *storj.Key
|
||||
startingNonce *storj.Nonce
|
||||
encBlockSize int
|
||||
encType encryption.Cipher
|
||||
cipher storj.Cipher
|
||||
}
|
||||
|
||||
// Size implements Ranger.Size
|
||||
@ -542,7 +542,7 @@ func (lr *lazySegmentRanger) Range(ctx context.Context, offset, length int64) (i
|
||||
return nil, err
|
||||
}
|
||||
encryptedKey, keyNonce := getEncryptedKeyAndNonce(&segmentMeta)
|
||||
lr.ranger, err = decryptRanger(ctx, rr, lr.size, lr.encType, lr.derivedKey, encryptedKey, keyNonce, lr.startingNonce, lr.encBlockSize)
|
||||
lr.ranger, err = decryptRanger(ctx, rr, lr.size, lr.cipher, lr.derivedKey, encryptedKey, keyNonce, lr.startingNonce, lr.encBlockSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -551,14 +551,13 @@ func (lr *lazySegmentRanger) Range(ctx context.Context, offset, length int64) (i
|
||||
}
|
||||
|
||||
// decryptRanger returns a decrypted ranger of the given rr ranger
|
||||
func decryptRanger(ctx context.Context, rr ranger.Ranger, decryptedSize int64, cipher encryption.Cipher, derivedKey *encryption.Key, encryptedKey []byte, encryptedKeyNonce, startingNonce *encryption.Nonce, encBlockSize int) (ranger.Ranger, error) {
|
||||
e, err := cipher.Decrypt(encryptedKey, derivedKey, encryptedKeyNonce)
|
||||
func decryptRanger(ctx context.Context, rr ranger.Ranger, decryptedSize int64, cipher storj.Cipher, derivedKey *storj.Key, encryptedKey storj.EncryptedPrivateKey, encryptedKeyNonce, startingNonce *storj.Nonce, encBlockSize int) (ranger.Ranger, error) {
|
||||
contentKey, err := encryption.DecryptKey(encryptedKey, cipher, derivedKey, encryptedKeyNonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var encKey encryption.Key
|
||||
copy(encKey[:], e)
|
||||
decrypter, err := cipher.NewDecrypter(&encKey, startingNonce, encBlockSize)
|
||||
|
||||
decrypter, err := encryption.NewDecrypter(cipher, contentKey, startingNonce, encBlockSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -573,7 +572,7 @@ func decryptRanger(ctx context.Context, rr ranger.Ranger, decryptedSize int64, c
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := cipher.Decrypt(cipherData, &encKey, startingNonce)
|
||||
data, err := encryption.Decrypt(cipherData, cipher, contentKey, startingNonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -637,12 +636,12 @@ func (s *streamStore) cancelHandler(ctx context.Context, totalSegments int64, pa
|
||||
}
|
||||
}
|
||||
|
||||
func getEncryptedKeyAndNonce(m *pb.SegmentMeta) (encryption.EncryptedPrivateKey, *encryption.Nonce) {
|
||||
func getEncryptedKeyAndNonce(m *pb.SegmentMeta) (storj.EncryptedPrivateKey, *storj.Nonce) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var nonce encryption.Nonce
|
||||
var nonce storj.Nonce
|
||||
copy(nonce[:], m.KeyNonce)
|
||||
|
||||
return m.EncryptedKey, &nonce
|
||||
@ -660,13 +659,13 @@ func decryptStreamInfo(ctx context.Context, item segments.Meta, path paths.Path,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cipher := encryption.Cipher(streamMeta.EncryptionType)
|
||||
cipher := storj.Cipher(streamMeta.EncryptionType)
|
||||
encryptedKey, keyNonce := getEncryptedKeyAndNonce(streamMeta.LastSegmentMeta)
|
||||
contentKey, err := encryptedKey.Decrypt(cipher, (*encryption.Key)(derivedKey), keyNonce)
|
||||
contentKey, err := encryption.DecryptKey(encryptedKey, cipher, (*storj.Key)(derivedKey), keyNonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// decrypt metadata with the content encryption key and zero nonce
|
||||
return cipher.Decrypt(streamMeta.EncryptedStreamInfo, contentKey, &encryption.Nonce{})
|
||||
return encryption.Decrypt(streamMeta.EncryptedStreamInfo, cipher, contentKey, &storj.Nonce{})
|
||||
}
|
||||
|
@ -5,22 +5,40 @@ package storj
|
||||
|
||||
// EncryptionScheme is the scheme and parameters used for encryption
|
||||
type EncryptionScheme struct {
|
||||
Algorithm EncryptionAlgorithm
|
||||
Cipher Cipher
|
||||
}
|
||||
|
||||
// EncryptionAlgorithm specifies an encryption algorithm
|
||||
type EncryptionAlgorithm byte
|
||||
// Cipher specifies an encryption algorithm
|
||||
type Cipher byte
|
||||
|
||||
// List of supported encryption algorithms
|
||||
const (
|
||||
InvalidEncryptionAlgorithm = EncryptionAlgorithm(iota)
|
||||
Unencrypted
|
||||
Unencrypted = Cipher(iota)
|
||||
AESGCM
|
||||
Secretbox
|
||||
SecretBox
|
||||
)
|
||||
|
||||
// Constant definitions for key and nonce sizes
|
||||
const (
|
||||
KeySize = 32
|
||||
NonceSize = 24
|
||||
)
|
||||
|
||||
// Key represents the largest key used by any encryption protocol
|
||||
type Key [KeySize]byte
|
||||
|
||||
// Raw returns the key as a raw byte array pointer
|
||||
func (key *Key) Raw() *[KeySize]byte {
|
||||
return (*[KeySize]byte)(key)
|
||||
}
|
||||
|
||||
// Nonce represents the largest nonce used by any encryption protocol
|
||||
type Nonce [24]byte // TODO: unify with eestream.Nonce
|
||||
type Nonce [NonceSize]byte
|
||||
|
||||
// Raw returns the nonce as a raw byte array pointer
|
||||
func (nonce *Nonce) Raw() *[NonceSize]byte {
|
||||
return (*[NonceSize]byte)(nonce)
|
||||
}
|
||||
|
||||
// EncryptedPrivateKey is a private key that has been encrypted
|
||||
type EncryptedPrivateKey []byte
|
||||
|
Loading…
Reference in New Issue
Block a user