Skip to content

Commit

Permalink
pkg/object: support chacha20 cipher
Browse files Browse the repository at this point in the history
  • Loading branch information
qingyunha committed Jul 3, 2022
1 parent 3ade892 commit e3bd513
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 23 deletions.
7 changes: 6 additions & 1 deletion cmd/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ Details: https://juicefs.com/docs/community/quick_start_guide`,
Name: "encrypt-rsa-key",
Usage: "a path to RSA private key (PEM)",
},
&cli.BoolFlag{
Name: "chacha20",
Usage: "encrypt use chacha20 instead of aes",
},
&cli.IntFlag{
Name: "trash-days",
Value: 1,
Expand Down Expand Up @@ -237,7 +241,7 @@ func createStorage(format meta.Format) (object.ObjectStorage, error) {
if err != nil {
return nil, fmt.Errorf("incorrect passphrase: %s", err)
}
encryptor := object.NewAESEncryptor(object.NewRSAEncryptor(privKey))
encryptor := object.NewDataEncryptor(object.NewRSAEncryptor(privKey), format.ChaCha20)
blob = object.NewEncrypted(blob, encryptor)
}
return blob, nil
Expand Down Expand Up @@ -392,6 +396,7 @@ func format(c *cli.Context) error {
SecretKey: c.String("secret-key"),
SessionToken: c.String("session-token"),
EncryptKey: loadEncrypt(c.String("encrypt-rsa-key")),
ChaCha20: c.Bool("chacha20"),
Shards: c.Int("shards"),
HashPrefix: c.Bool("hash-prefix"),
Capacity: c.Uint64("capacity") << 30,
Expand Down
1 change: 1 addition & 0 deletions pkg/meta/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type Format struct {
Inodes uint64 `json:",omitempty"`
EncryptKey string `json:",omitempty"`
KeyEncrypted bool `json:",omitempty"`
ChaCha20 bool `json:",omitempty"`
TrashDays int `json:",omitempty"`
MetaVersion int `json:",omitempty"`
MinClientVersion string `json:",omitempty"`
Expand Down
43 changes: 24 additions & 19 deletions pkg/object/encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (
"io"
"io/ioutil"
"strings"

"golang.org/x/crypto/chacha20poly1305"
)

type Encryptor interface {
Expand Down Expand Up @@ -114,16 +116,27 @@ func (e *rsaEncryptor) Decrypt(ciphertext []byte) ([]byte, error) {
return rsa.DecryptOAEP(sha256.New(), rand.Reader, e.privKey, ciphertext, e.label)
}

type aesEncryptor struct {
type dataEncryptor struct {
keyEncryptor Encryptor
keyLen int
aead func(key []byte) (cipher.AEAD, error)
}

func NewAESEncryptor(keyEncryptor Encryptor) Encryptor {
return &aesEncryptor{keyEncryptor, 32} // AES-256-GCM
func NewDataEncryptor(keyEncryptor Encryptor, chacha20 bool) Encryptor {
if chacha20 {
return &dataEncryptor{keyEncryptor, chacha20poly1305.KeySize, chacha20poly1305.New}
}
aead := func(key []byte) (cipher.AEAD, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
return cipher.NewGCM(block)
}
return &dataEncryptor{keyEncryptor, 32, aead} // AES-256-GCM
}

func (e *aesEncryptor) Encrypt(plaintext []byte) ([]byte, error) {
func (e *dataEncryptor) Encrypt(plaintext []byte) ([]byte, error) {
key := make([]byte, e.keyLen)
if _, err := io.ReadFull(rand.Reader, key); err != nil {
return nil, err
Expand All @@ -132,21 +145,17 @@ func (e *aesEncryptor) Encrypt(plaintext []byte) ([]byte, error) {
if err != nil {
return nil, err
}
block, err := aes.NewCipher(key)
aead, err := e.aead(key)
if err != nil {
return nil, err
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, aesgcm.NonceSize())
nonce := make([]byte, aead.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return nil, err
}

headerSize := 3 + len(cipherkey) + len(nonce)
buf := make([]byte, headerSize+len(plaintext)+aesgcm.Overhead())
buf := make([]byte, headerSize+len(plaintext)+aead.Overhead())
buf[0] = byte(len(cipherkey) >> 8)
buf[1] = byte(len(cipherkey) & 0xFF)
buf[2] = byte(len(nonce))
Expand All @@ -155,11 +164,11 @@ func (e *aesEncryptor) Encrypt(plaintext []byte) ([]byte, error) {
p = p[len(cipherkey):]
copy(p, nonce)
p = p[len(nonce):]
ciphertext := aesgcm.Seal(p[:0], nonce, plaintext, nil)
ciphertext := aead.Seal(p[:0], nonce, plaintext, nil)
return buf[:headerSize+len(ciphertext)], nil
}

func (e *aesEncryptor) Decrypt(ciphertext []byte) ([]byte, error) {
func (e *dataEncryptor) Decrypt(ciphertext []byte) ([]byte, error) {
keyLen := int(ciphertext[0])<<8 + int(ciphertext[1])
nonceLen := int(ciphertext[2])
if 3+keyLen+nonceLen >= len(ciphertext) {
Expand All @@ -174,15 +183,11 @@ func (e *aesEncryptor) Decrypt(ciphertext []byte) ([]byte, error) {
if err != nil {
return nil, errors.New("decryt key: " + err.Error())
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
aesgcm, err := cipher.NewGCM(block)
aead, err := e.aead(key)
if err != nil {
return nil, err
}
return aesgcm.Open(ciphertext[:0], nonce, ciphertext, nil)
return aead.Open(ciphertext[:0], nonce, ciphertext, nil)
}

type encrypted struct {
Expand Down
4 changes: 2 additions & 2 deletions pkg/object/encrypt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func BenchmarkRSA4096Decrypt(b *testing.B) {

func TestAESGCM(t *testing.T) {
kc := NewRSAEncryptor(testkey)
dc := NewAESEncryptor(kc)
dc := NewDataEncryptor(kc, false)
data := []byte("hello")
ciphertext, _ := dc.Encrypt(data)
plaintext, _ := dc.Decrypt(ciphertext)
Expand All @@ -139,7 +139,7 @@ func TestAESGCM(t *testing.T) {
func TestEncryptedStore(t *testing.T) {
s, _ := CreateStorage("mem", "", "", "", "")
kc := NewRSAEncryptor(testkey)
dc := NewAESEncryptor(kc)
dc := NewDataEncryptor(kc, false)
es := NewEncrypted(s, dc)
_ = es.Put("a", bytes.NewReader([]byte("hello")))
r, err := es.Get("a", 1, 2)
Expand Down
2 changes: 1 addition & 1 deletion pkg/object/object_storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ func TestEncrypted(t *testing.T) {
s, _ := CreateStorage("mem", "", "", "", "")
privkey, _ := rsa.GenerateKey(rand.Reader, 2048)
kc := NewRSAEncryptor(privkey)
dc := NewAESEncryptor(kc)
dc := NewDataEncryptor(kc, false)
es := NewEncrypted(s, dc)
testStorage(t, es)
}
Expand Down

0 comments on commit e3bd513

Please sign in to comment.