mirror of
https://github.com/octoleo/restic.git
synced 2024-12-23 11:28:54 +00:00
examine: add byte repair mode
This commit is contained in:
parent
52061e817c
commit
ce4b6d0874
@ -47,12 +47,14 @@ Exit status is 0 if the command was successful, and non-zero if there was any er
|
|||||||
}
|
}
|
||||||
|
|
||||||
var tryRepair bool
|
var tryRepair bool
|
||||||
|
var repairByte bool
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRoot.AddCommand(cmdDebug)
|
cmdRoot.AddCommand(cmdDebug)
|
||||||
cmdDebug.AddCommand(cmdDebugDump)
|
cmdDebug.AddCommand(cmdDebugDump)
|
||||||
cmdDebug.AddCommand(cmdDebugExamine)
|
cmdDebug.AddCommand(cmdDebugExamine)
|
||||||
cmdDebugExamine.Flags().BoolVar(&tryRepair, "try-repair", false, "try to repair broken blobs with single bit flips")
|
cmdDebugExamine.Flags().BoolVar(&tryRepair, "try-repair", false, "try to repair broken blobs with single bit flips")
|
||||||
|
cmdDebugExamine.Flags().BoolVar(&repairByte, "repair-byte", false, "try to repair broken blobs by trying bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
func prettyPrintJSON(wr io.Writer, item interface{}) error {
|
func prettyPrintJSON(wr io.Writer, item interface{}) error {
|
||||||
@ -186,8 +188,12 @@ var cmdDebugExamine = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryRepairWithBitflip(ctx context.Context, key *crypto.Key, input []byte) {
|
func tryRepairWithBitflip(ctx context.Context, key *crypto.Key, input []byte, bytewise bool) {
|
||||||
|
if bytewise {
|
||||||
|
fmt.Printf(" trying to repair blob by finding a broken byte\n")
|
||||||
|
} else {
|
||||||
fmt.Printf(" trying to repair blob with single bit flip\n")
|
fmt.Printf(" trying to repair blob with single bit flip\n")
|
||||||
|
}
|
||||||
|
|
||||||
ch := make(chan int)
|
ch := make(chan int)
|
||||||
var wg errgroup.Group
|
var wg errgroup.Group
|
||||||
@ -205,6 +211,25 @@ func tryRepairWithBitflip(ctx context.Context, key *crypto.Key, input []byte) {
|
|||||||
case <-done:
|
case <-done:
|
||||||
return nil
|
return nil
|
||||||
case i := <-ch:
|
case i := <-ch:
|
||||||
|
if bytewise {
|
||||||
|
for j := 0; j < 255; j++ {
|
||||||
|
// flip bits
|
||||||
|
buf[i] ^= byte(j)
|
||||||
|
|
||||||
|
nonce, plaintext := buf[:key.NonceSize()], buf[key.NonceSize():]
|
||||||
|
plaintext, err := key.Open(plaintext[:0], nonce, plaintext, nil)
|
||||||
|
if err == nil {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf(" blob could be repaired by XORing byte %v with 0x%02x\n", i, j)
|
||||||
|
fmt.Printf(" hash is %v\n", restic.Hash(plaintext))
|
||||||
|
close(done)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// flip bits back
|
||||||
|
buf[i] ^= byte(j)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for j := 0; j < 7; j++ {
|
for j := 0; j < 7; j++ {
|
||||||
// flip bit
|
// flip bit
|
||||||
buf[i] ^= (1 << uint(j))
|
buf[i] ^= (1 << uint(j))
|
||||||
@ -224,6 +249,7 @@ func tryRepairWithBitflip(ctx context.Context, key *crypto.Key, input []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +270,7 @@ outer:
|
|||||||
remaining := len(input) - i
|
remaining := len(input) - i
|
||||||
eta := time.Duration(float64(remaining)/gps) * time.Second
|
eta := time.Duration(float64(remaining)/gps) * time.Second
|
||||||
|
|
||||||
fmt.Printf("\r%d byte of %d done (%.2f%%), %.2f guesses per second, ETA %v",
|
fmt.Printf("\r%d byte of %d done (%.2f%%), %.0f byte per second, ETA %v",
|
||||||
i, len(input), float32(i)/float32(len(input)*100),
|
i, len(input), float32(i)/float32(len(input)*100),
|
||||||
gps, eta)
|
gps, eta)
|
||||||
info = time.Now()
|
info = time.Now()
|
||||||
@ -294,8 +320,8 @@ func loadBlobs(ctx context.Context, repo restic.Repository, pack string, list []
|
|||||||
plaintext, err = key.Open(plaintext[:0], nonce, plaintext, nil)
|
plaintext, err = key.Open(plaintext[:0], nonce, plaintext, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error decrypting blob: %v\n", err)
|
fmt.Fprintf(os.Stderr, "error decrypting blob: %v\n", err)
|
||||||
if tryRepair {
|
if tryRepair || repairByte {
|
||||||
tryRepairWithBitflip(ctx, key, buf)
|
tryRepairWithBitflip(ctx, key, buf, repairByte)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user