mirror of
https://github.com/octoleo/restic.git
synced 2024-11-26 06:46:34 +00:00
Collect all master crypto keys in a single structure
This commit is contained in:
parent
78727c17a3
commit
664a12c950
41
crypto.go
41
crypto.go
@ -85,13 +85,10 @@ func maskKey(k *MACKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// construct mac key from slice (k||r), with masking
|
// construct mac key from slice (k||r), with masking
|
||||||
func macKeyFromSlice(data []byte) *MACKey {
|
func macKeyFromSlice(mk *MACKey, data []byte) {
|
||||||
mk := &MACKey{}
|
|
||||||
copy(mk.K[:], data[:16])
|
copy(mk.K[:], data[:16])
|
||||||
copy(mk.R[:], data[16:32])
|
copy(mk.R[:], data[16:32])
|
||||||
maskKey(mk)
|
maskKey(mk)
|
||||||
|
|
||||||
return mk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// key: k||r
|
// key: k||r
|
||||||
@ -119,31 +116,27 @@ func poly1305_verify(msg []byte, nonce []byte, key *MACKey, mac []byte) bool {
|
|||||||
return poly1305.Verify(&m, msg, &k)
|
return poly1305.Verify(&m, msg, &k)
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateRandomAESKey() (k *AESKey) {
|
// returns new encryption and mac keys. k.MACKey.R is already masked.
|
||||||
k = &AESKey{}
|
func generateRandomKeys() (k *keys) {
|
||||||
n, err := rand.Read(k[:])
|
k = &keys{}
|
||||||
|
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")
|
panic("unable to read enough random bytes for encryption key")
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns a new mac key. k.R is already masked
|
n, err = rand.Read(k.Sign.K[:])
|
||||||
func generateRandomMACKey() (k *MACKey) {
|
|
||||||
k = &MACKey{}
|
|
||||||
n, err := rand.Read(k.K[:])
|
|
||||||
if n != MACKeySizeK || err != nil {
|
if n != MACKeySizeK || err != nil {
|
||||||
panic("unable to read enough random bytes for mac encryption key")
|
panic("unable to read enough random bytes for mac encryption key")
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err = rand.Read(k.R[:])
|
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")
|
panic("unable to read enough random bytes for mac signing key")
|
||||||
}
|
}
|
||||||
// mask r
|
// mask r
|
||||||
maskKey(k)
|
maskKey(&k.Sign)
|
||||||
|
|
||||||
return
|
return k
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateRandomIV() (iv IV) {
|
func generateRandomIV() (iv IV) {
|
||||||
@ -174,7 +167,7 @@ func Encrypt(ks *keys, ciphertext, plaintext []byte) (int, error) {
|
|||||||
e.XORKeyStream(ciphertext[ivSize:cap(ciphertext)], plaintext)
|
e.XORKeyStream(ciphertext[ivSize:cap(ciphertext)], plaintext)
|
||||||
ciphertext = ciphertext[:ivSize+len(plaintext)]
|
ciphertext = ciphertext[:ivSize+len(plaintext)]
|
||||||
|
|
||||||
mac := poly1305_sign(ciphertext[ivSize:], ciphertext[:ivSize], ks.Sign)
|
mac := poly1305_sign(ciphertext[ivSize:], ciphertext[:ivSize], &ks.Sign)
|
||||||
ciphertext = append(ciphertext, mac...)
|
ciphertext = append(ciphertext, mac...)
|
||||||
|
|
||||||
return len(ciphertext), nil
|
return len(ciphertext), nil
|
||||||
@ -198,7 +191,7 @@ func Decrypt(ks *keys, plaintext, ciphertext []byte) ([]byte, error) {
|
|||||||
ciphertext, mac := ciphertext[:l], ciphertext[l:]
|
ciphertext, mac := ciphertext[:l], ciphertext[l:]
|
||||||
|
|
||||||
// verify mac
|
// verify mac
|
||||||
if !poly1305_verify(ciphertext[ivSize:], ciphertext[:ivSize], ks.Sign, mac) {
|
if !poly1305_verify(ciphertext[ivSize:], ciphertext[:ivSize], &ks.Sign, mac) {
|
||||||
return nil, ErrUnauthenticated
|
return nil, ErrUnauthenticated
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,6 +218,8 @@ func kdf(k *Key, password string) (*keys, error) {
|
|||||||
return nil, fmt.Errorf("scrypt() called with empty salt")
|
return nil, fmt.Errorf("scrypt() called with empty salt")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
derKeys := &keys{}
|
||||||
|
|
||||||
keybytes := MACKeySize + AESKeySize
|
keybytes := MACKeySize + AESKeySize
|
||||||
scryptKeys, err := scrypt.Key([]byte(password), k.Salt, k.N, k.R, k.P, keybytes)
|
scryptKeys, err := scrypt.Key([]byte(password), k.Salt, k.N, k.R, k.P, keybytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -236,12 +231,12 @@ func kdf(k *Key, password string) (*keys, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// first 32 byte of scrypt output is the encryption key
|
// first 32 byte of scrypt output is the encryption key
|
||||||
ek := &AESKey{}
|
copy(derKeys.Encrypt[:], scryptKeys[:AESKeySize])
|
||||||
copy(ek[:], scryptKeys[:AESKeySize])
|
|
||||||
|
|
||||||
// next 32 byte of scrypt output is the mac key, in the form k||r
|
// next 32 byte of scrypt output is the mac key, in the form k||r
|
||||||
mk := macKeyFromSlice(scryptKeys[AESKeySize:])
|
macKeyFromSlice(&derKeys.Sign, scryptKeys[AESKeySize:])
|
||||||
return &keys{Encrypt: ek, Sign: mk}, nil
|
|
||||||
|
return derKeys, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type encryptWriter struct {
|
type encryptWriter struct {
|
||||||
@ -257,7 +252,7 @@ type encryptWriter struct {
|
|||||||
|
|
||||||
func (e *encryptWriter) Close() error {
|
func (e *encryptWriter) Close() error {
|
||||||
// write mac
|
// write mac
|
||||||
mac := poly1305_sign(e.data.Bytes()[ivSize:], e.data.Bytes()[:ivSize], e.key.Sign)
|
mac := poly1305_sign(e.data.Bytes()[ivSize:], e.data.Bytes()[:ivSize], &e.key.Sign)
|
||||||
_, err := e.origWr.Write(mac)
|
_, err := e.origWr.Write(mac)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -103,8 +103,8 @@ func TestCrypto(t *testing.T) {
|
|||||||
for _, tv := range test_values {
|
for _, tv := range test_values {
|
||||||
// test encryption
|
// test encryption
|
||||||
r.master = &keys{
|
r.master = &keys{
|
||||||
Encrypt: &tv.ekey,
|
Encrypt: tv.ekey,
|
||||||
Sign: &tv.skey,
|
Sign: tv.skey,
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := make([]byte, maxCiphertextSize)
|
msg := make([]byte, maxCiphertextSize)
|
||||||
|
13
key.go
13
key.go
@ -64,8 +64,8 @@ type Key struct {
|
|||||||
// encrypted and signed as a JSON data structure in the Data field of the Key
|
// encrypted and signed as a JSON data structure in the Data field of the Key
|
||||||
// structure.
|
// structure.
|
||||||
type keys struct {
|
type keys struct {
|
||||||
Sign *MACKey
|
Sign MACKey
|
||||||
Encrypt *AESKey
|
Encrypt AESKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateKey initializes a master key in the given backend and encrypts it with
|
// CreateKey initializes a master key in the given backend and encrypts it with
|
||||||
@ -186,7 +186,7 @@ func AddKey(s Server, password string, template *Key) (*Key, error) {
|
|||||||
|
|
||||||
if template == nil {
|
if template == nil {
|
||||||
// generate new random master keys
|
// generate new random master keys
|
||||||
newkey.master = newkey.newKeys()
|
newkey.master = generateRandomKeys()
|
||||||
} else {
|
} else {
|
||||||
// copy master keys from old key
|
// copy master keys from old key
|
||||||
newkey.master = template.master
|
newkey.master = template.master
|
||||||
@ -236,13 +236,6 @@ func AddKey(s Server, password string, template *Key) (*Key, error) {
|
|||||||
return newkey, nil
|
return newkey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Key) newKeys() *keys {
|
|
||||||
return &keys{
|
|
||||||
Encrypt: generateRandomAESKey(),
|
|
||||||
Sign: generateRandomMACKey(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *Key) newIV(buf []byte) error {
|
func (k *Key) newIV(buf []byte) error {
|
||||||
_, err := io.ReadFull(rand.Reader, buf[:ivSize])
|
_, err := io.ReadFull(rand.Reader, buf[:ivSize])
|
||||||
buf = buf[:ivSize]
|
buf = buf[:ivSize]
|
||||||
|
Loading…
Reference in New Issue
Block a user