2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-29 00:06:32 +00:00

Use CTR instead of CBC for encryption

This commit is contained in:
Alexander Neumann 2014-10-04 16:57:42 +02:00
parent f37d0bf45f
commit 58f7b1be1e
2 changed files with 9 additions and 46 deletions

53
key.go
View File

@ -1,7 +1,6 @@
package khepri package khepri
import ( import (
"bytes"
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"crypto/hmac" "crypto/hmac"
@ -231,40 +230,6 @@ func (k *Key) newIV() ([]byte, error) {
return buf, nil return buf, nil
} }
func (k *Key) pad(plaintext []byte) []byte {
l := aes.BlockSize - (len(plaintext) % aes.BlockSize)
if l == 0 {
l = aes.BlockSize
}
if l <= 0 || l > aes.BlockSize {
panic("invalid padding size")
}
return append(plaintext, bytes.Repeat([]byte{byte(l)}, l)...)
}
func (k *Key) unpad(plaintext []byte) []byte {
l := len(plaintext)
pad := plaintext[l-1]
if pad > aes.BlockSize {
panic(errors.New("padding > BlockSize"))
}
if pad == 0 {
panic(errors.New("invalid padding 0"))
}
for i := l - int(pad); i < l; i++ {
if plaintext[i] != pad {
panic(errors.New("invalid padding!"))
}
}
return plaintext[:l-int(pad)]
}
// Encrypt encrypts and signs data. Returned is IV || Ciphertext || HMAC. For // Encrypt encrypts and signs data. Returned is IV || Ciphertext || HMAC. For
// the hash function, SHA256 is used, so the overhead is 16+32=48 byte. // the hash function, SHA256 is used, so the overhead is 16+32=48 byte.
func (k *Key) encrypt(ks *keys, plaintext []byte) ([]byte, error) { func (k *Key) encrypt(ks *keys, plaintext []byte) ([]byte, error) {
@ -278,12 +243,11 @@ func (k *Key) encrypt(ks *keys, plaintext []byte) ([]byte, error) {
panic(fmt.Sprintf("unable to create cipher: %v", err)) panic(fmt.Sprintf("unable to create cipher: %v", err))
} }
e := cipher.NewCBCEncrypter(c, iv) e := cipher.NewCTR(c, iv)
p := k.pad(plaintext) l := len(iv)
ciphertext := make([]byte, len(p)) ciphertext := make([]byte, l+len(plaintext))
e.CryptBlocks(ciphertext, p) copy(ciphertext[:l], iv)
e.XORKeyStream(ciphertext[l:], plaintext)
ciphertext = append(iv, ciphertext...)
hm := hmac.New(sha256.New, ks.Sign) hm := hmac.New(sha256.New, ks.Sign)
@ -341,12 +305,11 @@ func (k *Key) decrypt(ks *keys, ciphertext []byte) ([]byte, error) {
} }
// decrypt // decrypt
e := cipher.NewCBCDecrypter(c, iv) e := cipher.NewCTR(c, iv)
plaintext := make([]byte, len(ciphertext)) plaintext := make([]byte, len(ciphertext))
e.CryptBlocks(plaintext, ciphertext) e.XORKeyStream(plaintext, ciphertext)
// remove padding and return return plaintext, nil
return k.unpad(plaintext), nil
} }
// Decrypt verifes and decrypts the ciphertext with the master key. Ciphertext // Decrypt verifes and decrypts the ciphertext with the master key. Ciphertext

View File

@ -15,7 +15,7 @@ var test_values = []struct {
{ {
ekey: decode_hex("303e8687b1d7db18421bdc6bb8588ccadac4d59ee87b8ff70c44e635790cafef"), ekey: decode_hex("303e8687b1d7db18421bdc6bb8588ccadac4d59ee87b8ff70c44e635790cafef"),
skey: decode_hex("cc8d4b948ee0ebfe1d415de921d10353ef4d8824cb80b2bcc5fbff8a9b12a42c"), skey: decode_hex("cc8d4b948ee0ebfe1d415de921d10353ef4d8824cb80b2bcc5fbff8a9b12a42c"),
ciphertext: decode_hex("154f582d77e6430409da392c3a09aa38e00a78bcc8919557fe18dd17f83e7b0b3053def59f4215b6e1c6b72ceb5acdddd8511ce3a853e054218de1e9f34637470d68f1f93ba8228e4d9817d7c9acfcd2"), ciphertext: decode_hex("fe85b32b108308f6f8834a96e463b66e0eae6a0f1e9809da0773a2db12a24528bce3220e6a5700b40bd45ef2a2ce96a7fc0a895a019d4a77eef5fc9579297059c6d0"),
plaintext: []byte("Dies ist ein Test!"), plaintext: []byte("Dies ist ein Test!"),
}, },
} }