mirror of https://github.com/restic/restic.git
Use CTR instead of CBC for encryption
This commit is contained in:
parent
f37d0bf45f
commit
58f7b1be1e
53
key.go
53
key.go
|
@ -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
|
||||||
|
|
|
@ -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!"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue