6e1a3987b7
This commit adds a command called `self-update` which downloads the latest released version of restic from GitHub and replacing the current binary with it. It does not rely on any external program (so it'll work everywhere), but still verifies the GPG signature using the embedded GPG public key. By default, the `self-update` command is hidden behind the `selfupdate` built tag, which is only set when restic is built using `build.go`. The reason for this is that downstream distributions will then not include the command by default, so users are encouraged to use the platform-specific distribution mechanism.
143 lines
3.6 KiB
Go
143 lines
3.6 KiB
Go
// Copyright 2010 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
|
|
|
|
package packet
|
|
|
|
import (
|
|
"crypto/cipher"
|
|
)
|
|
|
|
type ocfbEncrypter struct {
|
|
b cipher.Block
|
|
fre []byte
|
|
outUsed int
|
|
}
|
|
|
|
// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
|
|
// performed.
|
|
type OCFBResyncOption bool
|
|
|
|
const (
|
|
OCFBResync OCFBResyncOption = true
|
|
OCFBNoResync OCFBResyncOption = false
|
|
)
|
|
|
|
// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's
|
|
// cipher feedback mode using the given cipher.Block, and an initial amount of
|
|
// ciphertext. randData must be random bytes and be the same length as the
|
|
// cipher.Block's block size. Resync determines if the "resynchronization step"
|
|
// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on
|
|
// this point.
|
|
func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
|
|
blockSize := block.BlockSize()
|
|
if len(randData) != blockSize {
|
|
return nil, nil
|
|
}
|
|
|
|
x := &ocfbEncrypter{
|
|
b: block,
|
|
fre: make([]byte, blockSize),
|
|
outUsed: 0,
|
|
}
|
|
prefix := make([]byte, blockSize+2)
|
|
|
|
block.Encrypt(x.fre, x.fre)
|
|
for i := 0; i < blockSize; i++ {
|
|
prefix[i] = randData[i] ^ x.fre[i]
|
|
}
|
|
|
|
block.Encrypt(x.fre, prefix[:blockSize])
|
|
prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
|
|
prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
|
|
|
|
if resync {
|
|
block.Encrypt(x.fre, prefix[2:])
|
|
} else {
|
|
x.fre[0] = prefix[blockSize]
|
|
x.fre[1] = prefix[blockSize+1]
|
|
x.outUsed = 2
|
|
}
|
|
return x, prefix
|
|
}
|
|
|
|
func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
|
|
for i := 0; i < len(src); i++ {
|
|
if x.outUsed == len(x.fre) {
|
|
x.b.Encrypt(x.fre, x.fre)
|
|
x.outUsed = 0
|
|
}
|
|
|
|
x.fre[x.outUsed] ^= src[i]
|
|
dst[i] = x.fre[x.outUsed]
|
|
x.outUsed++
|
|
}
|
|
}
|
|
|
|
type ocfbDecrypter struct {
|
|
b cipher.Block
|
|
fre []byte
|
|
outUsed int
|
|
}
|
|
|
|
// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
|
|
// cipher feedback mode using the given cipher.Block. Prefix must be the first
|
|
// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
|
|
// block size. If an incorrect key is detected then nil is returned. On
|
|
// successful exit, blockSize+2 bytes of decrypted data are written into
|
|
// prefix. Resync determines if the "resynchronization step" from RFC 4880,
|
|
// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
|
|
func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
|
|
blockSize := block.BlockSize()
|
|
if len(prefix) != blockSize+2 {
|
|
return nil
|
|
}
|
|
|
|
x := &ocfbDecrypter{
|
|
b: block,
|
|
fre: make([]byte, blockSize),
|
|
outUsed: 0,
|
|
}
|
|
prefixCopy := make([]byte, len(prefix))
|
|
copy(prefixCopy, prefix)
|
|
|
|
block.Encrypt(x.fre, x.fre)
|
|
for i := 0; i < blockSize; i++ {
|
|
prefixCopy[i] ^= x.fre[i]
|
|
}
|
|
|
|
block.Encrypt(x.fre, prefix[:blockSize])
|
|
prefixCopy[blockSize] ^= x.fre[0]
|
|
prefixCopy[blockSize+1] ^= x.fre[1]
|
|
|
|
if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
|
|
prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
|
|
return nil
|
|
}
|
|
|
|
if resync {
|
|
block.Encrypt(x.fre, prefix[2:])
|
|
} else {
|
|
x.fre[0] = prefix[blockSize]
|
|
x.fre[1] = prefix[blockSize+1]
|
|
x.outUsed = 2
|
|
}
|
|
copy(prefix, prefixCopy)
|
|
return x
|
|
}
|
|
|
|
func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
|
|
for i := 0; i < len(src); i++ {
|
|
if x.outUsed == len(x.fre) {
|
|
x.b.Encrypt(x.fre, x.fre)
|
|
x.outUsed = 0
|
|
}
|
|
|
|
c := src[i]
|
|
dst[i] = x.fre[x.outUsed] ^ src[i]
|
|
x.fre[x.outUsed] = c
|
|
x.outUsed++
|
|
}
|
|
}
|