diff --git a/crypto/crypto.go b/crypto/crypto.go index 182e0a33a..5509d394c 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -18,14 +18,14 @@ import ( ) const ( - AESKeySize = 32 // for AES256 - MACKeySizeK = 16 // for AES-128 - MACKeySizeR = 16 // for Poly1305 - MACKeySize = MACKeySizeK + MACKeySizeR // for Poly1305-AES128 + aesKeySize = 32 // for AES256 + macKeySizeK = 16 // for AES-128 + macKeySizeR = 16 // for Poly1305 + macKeySize = macKeySizeK + macKeySizeR // for Poly1305-AES128 ivSize = aes.BlockSize - macSize = poly1305.TagSize // Poly1305 size is 16 byte - CiphertextExtension = ivSize + macSize + macSize = poly1305.TagSize // Poly1305 size is 16 byte + Extension = ivSize + macSize ) var ( @@ -37,11 +37,11 @@ var ( ErrBufferTooSmall = errors.New("destination buffer too small") ) -// MasterKeys holds signing and encryption keys for a repository. It is stored +// Key holds signing and encryption keys for a repository. It is stored // encrypted and signed as a JSON data structure in the Data field of the Key // structure. For the master key, the secret random polynomial used for content // defined chunking is included. -type MasterKeys struct { +type Key struct { Sign MACKey `json:"sign"` Encrypt AESKey `json:"encrypt"` ChunkerPolynomial chunker.Pol `json:"chunker_polynomial,omitempty"` @@ -141,21 +141,21 @@ func poly1305_verify(msg []byte, nonce []byte, key *MACKey, mac []byte) bool { return poly1305.Verify(&m, msg, &k) } -// returns new encryption and mac keys. k.MACKey.R is already masked. -func GenerateRandomKeys() (k *MasterKeys) { - k = &MasterKeys{} +// GenerateKey returns new encryption and signing keys. +func GenerateKey() (k *Key) { + k = &Key{} n, err := rand.Read(k.Encrypt[:]) - if n != AESKeySize || err != nil { + if n != aesKeySize || err != nil { panic("unable to read enough random bytes for encryption key") } n, err = rand.Read(k.Sign.K[:]) - if n != MACKeySizeK || err != nil { + if n != macKeySizeK || err != nil { panic("unable to read enough random bytes for mac encryption key") } n, err = rand.Read(k.Sign.R[:]) - if n != MACKeySizeR || err != nil { + if n != macKeySizeR || err != nil { panic("unable to read enough random bytes for mac signing key") } // mask r @@ -198,7 +198,7 @@ func (k *AESKey) MarshalJSON() ([]byte, error) { } func (k *AESKey) UnmarshalJSON(data []byte) error { - d := make([]byte, AESKeySize) + d := make([]byte, aesKeySize) err := json.Unmarshal(data, &d) if err != nil { return err @@ -210,7 +210,7 @@ func (k *AESKey) UnmarshalJSON(data []byte) error { // Encrypt encrypts and signs data. Stored in ciphertext is IV || Ciphertext || // MAC. Encrypt returns the ciphertext's length. -func Encrypt(ks *MasterKeys, ciphertext, plaintext []byte) (int, error) { +func Encrypt(ks *Key, ciphertext, plaintext []byte) (int, error) { if cap(ciphertext) < len(plaintext)+ivSize+macSize { return 0, ErrBufferTooSmall } @@ -236,7 +236,7 @@ func Encrypt(ks *MasterKeys, ciphertext, plaintext []byte) (int, error) { // Decrypt verifies and decrypts the ciphertext. Ciphertext must be in the form // IV || Ciphertext || MAC. -func Decrypt(ks *MasterKeys, plaintext, ciphertext []byte) ([]byte, error) { +func Decrypt(ks *Key, plaintext, ciphertext []byte) ([]byte, error) { // check for plausible length if len(ciphertext) < ivSize+macSize { panic("trying to decrypt invalid data: ciphertext too small") @@ -275,14 +275,14 @@ func Decrypt(ks *MasterKeys, plaintext, ciphertext []byte) ([]byte, error) { // KDF derives encryption and signing keys from the password using the supplied // parameters N, R and P and the Salt. -func KDF(N, R, P int, salt []byte, password string) (*MasterKeys, error) { +func KDF(N, R, P int, salt []byte, password string) (*Key, error) { if len(salt) == 0 { return nil, fmt.Errorf("scrypt() called with empty salt") } - derKeys := &MasterKeys{} + derKeys := &Key{} - keybytes := MACKeySize + AESKeySize + keybytes := macKeySize + aesKeySize scryptKeys, err := scrypt.Key([]byte(password), salt, N, R, P, keybytes) if err != nil { return nil, fmt.Errorf("error deriving keys from password: %v", err) @@ -293,10 +293,10 @@ func KDF(N, R, P int, salt []byte, password string) (*MasterKeys, error) { } // first 32 byte of scrypt output is the encryption key - copy(derKeys.Encrypt[:], scryptKeys[:AESKeySize]) + copy(derKeys.Encrypt[:], scryptKeys[:aesKeySize]) // next 32 byte of scrypt output is the mac key, in the form k||r - macKeyFromSlice(&derKeys.Sign, scryptKeys[AESKeySize:]) + macKeyFromSlice(&derKeys.Sign, scryptKeys[aesKeySize:]) return derKeys, nil } @@ -305,7 +305,7 @@ type encryptWriter struct { iv IV wroteIV bool data *bytes.Buffer - key *MasterKeys + key *Key s cipher.Stream w io.Writer origWr io.Writer @@ -376,7 +376,7 @@ func (e *encryptWriter) Write(p []byte) (int, error) { // EncryptTo buffers data written to the returned io.WriteCloser. When Close() // is called, the data is encrypted an written to the underlying writer. -func EncryptTo(ks *MasterKeys, wr io.Writer) io.WriteCloser { +func EncryptTo(ks *Key, wr io.Writer) io.WriteCloser { ew := &encryptWriter{ iv: generateRandomIV(), data: bytes.NewBuffer(getBuffer()[:0]), @@ -462,7 +462,7 @@ func (d *decryptReader) Close() error { // drained, locally buffered and made available on the returned Reader // afterwards. If a MAC verification failure is observed, it is returned // immediately. -func DecryptFrom(ks *MasterKeys, rd io.Reader) (io.ReadCloser, error) { +func DecryptFrom(ks *Key, rd io.Reader) (io.ReadCloser, error) { ciphertext := getBuffer() ciphertext = ciphertext[0:cap(ciphertext)] diff --git a/crypto/crypto_int_test.go b/crypto/crypto_int_test.go index d626844ae..5c5351303 100644 --- a/crypto/crypto_int_test.go +++ b/crypto/crypto_int_test.go @@ -100,7 +100,7 @@ func should_panic(f func()) (did_panic bool) { func TestCrypto(t *testing.T) { for _, tv := range test_values { // test encryption - k := &MasterKeys{ + k := &Key{ Encrypt: tv.ekey, Sign: tv.skey, } diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index 7da3e57d7..ec39211e9 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -17,7 +17,7 @@ import ( var testLargeCrypto = flag.Bool("test.largecrypto", false, "also test crypto functions with large payloads") func TestEncryptDecrypt(t *testing.T) { - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() tests := []int{5, 23, 2<<18 + 23, 1 << 20} if *testLargeCrypto { @@ -43,7 +43,7 @@ func TestEncryptDecrypt(t *testing.T) { } func TestSmallBuffer(t *testing.T) { - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() size := 600 data := make([]byte, size) @@ -65,7 +65,7 @@ func TestLargeEncrypt(t *testing.T) { t.SkipNow() } - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() for _, size := range []int{chunker.MaxSize, chunker.MaxSize + 1, chunker.MaxSize + 1<<20} { data := make([]byte, size) @@ -75,7 +75,7 @@ func TestLargeEncrypt(t *testing.T) { _, err = io.ReadFull(f, data) OK(t, err) - ciphertext := make([]byte, size+crypto.CiphertextExtension) + ciphertext := make([]byte, size+crypto.Extension) n, err := crypto.Encrypt(k, ciphertext, data) OK(t, err) @@ -90,7 +90,7 @@ func BenchmarkEncryptWriter(b *testing.B) { size := 8 << 20 // 8MiB rd := RandomReader(23, size) - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() b.ResetTimer() b.SetBytes(int64(size)) @@ -108,8 +108,8 @@ func BenchmarkEncrypt(b *testing.B) { size := 8 << 20 // 8MiB data := make([]byte, size) - k := crypto.GenerateRandomKeys() - buf := make([]byte, len(data)+crypto.CiphertextExtension) + k := crypto.GenerateKey() + buf := make([]byte, len(data)+crypto.Extension) b.ResetTimer() b.SetBytes(int64(size)) @@ -123,9 +123,9 @@ func BenchmarkEncrypt(b *testing.B) { func BenchmarkDecryptReader(b *testing.B) { size := 8 << 20 // 8MiB buf := Random(23, size) - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() - ciphertext := make([]byte, len(buf)+crypto.CiphertextExtension) + ciphertext := make([]byte, len(buf)+crypto.Extension) _, err := crypto.Encrypt(k, ciphertext, buf) OK(b, err) @@ -145,7 +145,7 @@ func BenchmarkDecryptReader(b *testing.B) { } func BenchmarkEncryptDecryptReader(b *testing.B) { - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() size := 8 << 20 // 8MiB rd := RandomReader(23, size) @@ -176,7 +176,7 @@ func BenchmarkDecrypt(b *testing.B) { size := 8 << 20 // 8MiB data := make([]byte, size) - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() ciphertext := restic.GetChunkBuf("BenchmarkDecrypt") defer restic.FreeChunkBuf("BenchmarkDecrypt", ciphertext) @@ -196,7 +196,7 @@ func BenchmarkDecrypt(b *testing.B) { } func TestEncryptStreamWriter(t *testing.T) { - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() tests := []int{5, 23, 2<<18 + 23, 1 << 20} if *testLargeCrypto { @@ -215,7 +215,7 @@ func TestEncryptStreamWriter(t *testing.T) { OK(t, err) OK(t, wr.Close()) - l := len(data) + crypto.CiphertextExtension + l := len(data) + crypto.Extension Assert(t, len(ciphertext.Bytes()) == l, "wrong ciphertext length: expected %d, got %d", l, len(ciphertext.Bytes())) @@ -230,7 +230,7 @@ func TestEncryptStreamWriter(t *testing.T) { } func TestDecryptStreamReader(t *testing.T) { - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() tests := []int{5, 23, 2<<18 + 23, 1 << 20} if *testLargeCrypto { @@ -242,14 +242,14 @@ func TestDecryptStreamReader(t *testing.T) { _, err := io.ReadFull(RandomReader(42, size), data) OK(t, err) - ciphertext := make([]byte, size+crypto.CiphertextExtension) + ciphertext := make([]byte, size+crypto.Extension) // encrypt with default function n, err := crypto.Encrypt(k, ciphertext, data) OK(t, err) - Assert(t, n == len(data)+crypto.CiphertextExtension, + Assert(t, n == len(data)+crypto.Extension, "wrong number of bytes returned after encryption: expected %d, got %d", - len(data)+crypto.CiphertextExtension, n) + len(data)+crypto.Extension, n) rd, err := crypto.DecryptFrom(k, bytes.NewReader(ciphertext)) OK(t, err) @@ -264,7 +264,7 @@ func TestDecryptStreamReader(t *testing.T) { } func TestEncryptWriter(t *testing.T) { - k := crypto.GenerateRandomKeys() + k := crypto.GenerateKey() tests := []int{5, 23, 2<<18 + 23, 1 << 20} if *testLargeCrypto { @@ -285,7 +285,7 @@ func TestEncryptWriter(t *testing.T) { ciphertext := buf.Bytes() - l := len(data) + crypto.CiphertextExtension + l := len(data) + crypto.Extension Assert(t, len(ciphertext) == l, "wrong ciphertext length: expected %d, got %d", l, len(ciphertext)) diff --git a/key.go b/key.go index 7a42088ef..e7a62ce41 100644 --- a/key.go +++ b/key.go @@ -44,8 +44,8 @@ type Key struct { Salt []byte `json:"salt"` Data []byte `json:"data"` - user *crypto.MasterKeys - master *crypto.MasterKeys + user *crypto.Key + master *crypto.Key name string } @@ -81,7 +81,7 @@ func OpenKey(s Server, name string, password string) (*Key, error) { } // restore json - k.master = &crypto.MasterKeys{} + k.master = &crypto.Key{} err = json.Unmarshal(buf, k.master) if err != nil { return nil, err @@ -176,7 +176,7 @@ func AddKey(s Server, password string, template *Key) (*Key, error) { if template == nil { // generate new random master keys - newkey.master = crypto.GenerateRandomKeys() + newkey.master = crypto.GenerateKey() // generate random polynomial for cdc p, err := chunker.RandomPolynomial() if err != nil { @@ -264,12 +264,12 @@ func (k *Key) DecryptFrom(rd io.Reader) (io.ReadCloser, error) { // Master() returns the master keys for this repository. Only included for // debug purposes. -func (k *Key) Master() *crypto.MasterKeys { +func (k *Key) Master() *crypto.Key { return k.master } // User() returns the user keys for this key. Only included for debug purposes. -func (k *Key) User() *crypto.MasterKeys { +func (k *Key) User() *crypto.Key { return k.user } diff --git a/pools.go b/pools.go index cc7e02a20..10dadfef6 100644 --- a/pools.go +++ b/pools.go @@ -21,7 +21,7 @@ type poolStats struct { max int } -const maxCiphertextSize = crypto.CiphertextExtension + chunker.MaxSize +const maxCiphertextSize = crypto.Extension + chunker.MaxSize func (s *poolStats) Get(k string) { s.m.Lock() diff --git a/server.go b/server.go index 6891907b7..7b16873ed 100644 --- a/server.go +++ b/server.go @@ -159,11 +159,11 @@ func (s Server) Save(t backend.Type, data []byte, id backend.ID) (Blob, error) { var ciphertext []byte // if the data is small enough, use a slice from the pool - if len(data) <= maxCiphertextSize-crypto.CiphertextExtension { + if len(data) <= maxCiphertextSize-crypto.Extension { ciphertext = GetChunkBuf("ch.Save()") defer FreeChunkBuf("ch.Save()", ciphertext) } else { - l := len(data) + crypto.CiphertextExtension + l := len(data) + crypto.Extension debug.Log("Server.Save", "create large slice of %d bytes for ciphertext", l)