aboutsummaryrefslogtreecommitdiff
path: root/gocryptfs-xray/xray_main.go
AgeCommit message (Collapse)Author
2019-03-03Allow multiple -extpass argumentsJakob Unterwurzacher
To support arguments containing spaces, -extpass can now be passed multiple times. https://github.com/rfjakob/gocryptfs/issues/289
2019-01-04xray: print "assuming AES-GCM mode" unless -aessiv is passedJakob Unterwurzacher
To alert the user that they can and should choose the right mode.
2019-01-04xray: add support for inspecting AES-SIV files (-aessiv flag)Jakob Unterwurzacher
https://github.com/rfjakob/gocryptfs/issues/299 : In GCM mode the auth tags are at the end of each block, but in SIV mode the auth tags follow immediately after the nonce. As a result, in AES-SIV mode the output of gocryptfs-xray is misleading and does not actually print the auth tag, but just the last 16-byte of the ciphertext. diff --git a/gocryptfs-xray/xray_main.go b/gocryptfs-xray/xray_main.go index 74c9fb3..5a81caf 100644 --- a/gocryptfs-xray/xray_main.go +++ b/gocryptfs-xray/xray_main.go @@ -16,9 +16,10 @@ import ( ) const ( - ivLen = contentenc.DefaultIVBits / 8 - blockSize = contentenc.DefaultBS + ivLen + cryptocore.AuthTagLen - myName = "gocryptfs-xray" + ivLen = contentenc.DefaultIVBits / 8 + authTagLen = cryptocore.AuthTagLen + blockSize = contentenc.DefaultBS + ivLen + cryptocore.AuthTagLen + myName = "gocryptfs-xray" ) func errExit(err error) { @@ -26,13 +27,18 @@ func errExit(err error) { os.Exit(1) } -func prettyPrintHeader(h *contentenc.FileHeader) { +func prettyPrintHeader(h *contentenc.FileHeader, aessiv bool) { id := hex.EncodeToString(h.ID) - fmt.Printf("Header: Version: %d, Id: %s\n", h.Version, id) + msg := "Header: Version: %d, Id: %s" + if aessiv { + msg += ", assuming AES-SIV mode" + } + fmt.Printf(msg+"\n", h.Version, id) } func main() { dumpmasterkey := flag.Bool("dumpmasterkey", false, "Decrypt and dump the master key") + aessiv := flag.Bool("aessiv", false, "Assume AES-SIV mode instead of AES-GCM") flag.Parse() if flag.NArg() != 1 { fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] FILE\n"+ @@ -54,7 +60,7 @@ func main() { if *dumpmasterkey { dumpMasterKey(fn) } else { - inspectCiphertext(fd) + inspectCiphertext(fd, *aessiv) } } @@ -72,7 +78,7 @@ func dumpMasterKey(fn string) { } } -func inspectCiphertext(fd *os.File) { +func inspectCiphertext(fd *os.File, aessiv bool) { headerBytes := make([]byte, contentenc.HeaderLen) n, err := fd.ReadAt(headerBytes, 0) if err == io.EOF && n == 0 { @@ -88,34 +94,30 @@ func inspectCiphertext(fd *os.File) { if err != nil { errExit(err) } - prettyPrintHeader(header) + prettyPrintHeader(header, aessiv) var i int64 + buf := make([]byte, blockSize) for i = 0; ; i++ { - blockLen := int64(blockSize) off := contentenc.HeaderLen + i*blockSize - iv := make([]byte, ivLen) - _, err := fd.ReadAt(iv, off) - if err == io.EOF { - break - } else if err != nil { + n, err := fd.ReadAt(buf, off) + if err != nil && err != io.EOF { errExit(err) } - tag := make([]byte, cryptocore.AuthTagLen) - _, err = fd.ReadAt(tag, off+blockSize-cryptocore.AuthTagLen) - if err == io.EOF { - fi, err2 := fd.Stat() - if err2 != nil { - errExit(err2) - } - _, err2 = fd.ReadAt(tag, fi.Size()-cryptocore.AuthTagLen) - if err2 != nil { - errExit(err2) - } - blockLen = (fi.Size() - contentenc.HeaderLen) % blockSize - } else if err != nil { - errExit(err) + if n == 0 && err == io.EOF { + break + } + // A block contains at least the IV, the Auth Tag and 1 data byte + if n < ivLen+authTagLen+1 { + errExit(fmt.Errorf("corrupt block: truncated data, len=%d", n)) + } + data := buf[:n] + // Parse block data + iv := data[:ivLen] + tag := data[len(data)-authTagLen:] + if aessiv { + tag = data[ivLen : ivLen+authTagLen] } fmt.Printf("Block %2d: IV: %s, Tag: %s, Offset: %5d Len: %d\n", - i, hex.EncodeToString(iv), hex.EncodeToString(tag), off, blockLen) + i, hex.EncodeToString(iv), hex.EncodeToString(tag), off, len(data)) } } diff --git a/gocryptfs-xray/xray_tests/aessiv_fs.masterkey.txt b/gocryptfs-xray/xray_tests/aessiv_fs.masterkey.txt new file mode 100644 index 0000000..70835ac --- /dev/null +++ b/gocryptfs-xray/xray_tests/aessiv_fs.masterkey.txt @@ -0,0 +1,5 @@ +Your master key is: + + 29dd219d-e227ff20-8474469d-9fc9fdc6- + b434ab35-404e808c-489d441e-2c1003f2 + diff --git a/gocryptfs-xray/xray_tests/aessiv_fs.xray.txt b/gocryptfs-xray/xray_tests/aessiv_fs.xray.txt new file mode 100644 index 0000000..6a48079 --- /dev/null +++ b/gocryptfs-xray/xray_tests/aessiv_fs.xray.txt @@ -0,0 +1,3 @@ +Header: Version: 2, Id: c2f21142e108952a47edfe16053d2bb9, assuming AES-SIV mode +Block 0: IV: 7621fdc35be7671ac6f369214436e8ff, Tag: e8108c158b22cad6bb3296645357eb75, Offset: 18 Len: 4128 +Block 1: IV: f096d86a4dc3461ef17655cfcf865b13, Tag: 925f23d647e4ab7add2c8d36362cc5a9, Offset: 4146 Len: 936 diff --git a/gocryptfs-xray/xray_tests/aessiv_fs/Ldq-c4ADpM5iGSSrPjUAqQ b/gocryptfs-xray/xray_tests/aessiv_fs/Ldq-c4ADpM5iGSSrPjUAqQ new file mode 100644 index 0000000..bfd4dfe Binary files /dev/null and b/gocryptfs-xray/xray_tests/aessiv_fs/Ldq-c4ADpM5iGSSrPjUAqQ differ diff --git a/gocryptfs-xray/xray_tests/aessiv_fs/gocryptfs.conf b/gocryptfs-xray/xray_tests/aessiv_fs/gocryptfs.conf new file mode 100644 index 0000000..9b8b95f --- /dev/null +++ b/gocryptfs-xray/xray_tests/aessiv_fs/gocryptfs.conf @@ -0,0 +1,21 @@ +{ + "Creator": "gocryptfs v1.7-beta1-7-g6b94f5e", + "EncryptedKey": "D0kHfg/pryMO9Ydo15EwpYjNHf3iWKq2GJyNocbjwJt9blEeMoLD5DnoARuDzQs54hblw+9MHwFjCSHYmJrFbA==", + "ScryptObject": { + "Salt": "ehn0LM/Hy/4QkXAMCZq3c3p0O9G7gu5e3OQSR8MiJ6c=", + "N": 65536, + "R": 8, + "P": 1, + "KeyLen": 32 + }, + "Version": 2, + "FeatureFlags": [ + "GCMIV128", + "HKDF", + "DirIV", + "EMENames", + "LongNames", + "Raw64", + "AESSIV" + ] +} diff --git a/gocryptfs-xray/xray_tests/aessiv_fs/gocryptfs.diriv b/gocryptfs-xray/xray_tests/aessiv_fs/gocryptfs.diriv new file mode 100644 index 0000000..dd57ce1 --- /dev/null +++ b/gocryptfs-xray/xray_tests/aessiv_fs/gocryptfs.diriv @@ -0,0 +1 @@ +.¨Í1Aiõ&Á4—öÉ \ No newline at end of file diff --git a/gocryptfs-xray/xray_tests/xray_test.go b/gocryptfs-xray/xray_tests/xray_test.go index a3374b0..8e5fc0c 100644 --- a/gocryptfs-xray/xray_tests/xray_test.go +++ b/gocryptfs-xray/xray_tests/xray_test.go @@ -24,3 +24,20 @@ func TestAesgcmXray(t *testing.T) { fmt.Printf("have:\n%s", string(out)) } } + +func TestAessivXray(t *testing.T) { + expected, err := ioutil.ReadFile("aessiv_fs.xray.txt") + if err != nil { + t.Fatal(err) + } + cmd := exec.Command("../gocryptfs-xray", "-aessiv", "aessiv_fs/Ldq-c4ADpM5iGSSrPjUAqQ") + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatal(err) + } + if bytes.Compare(out, expected) != 0 { + t.Errorf("Unexpected output") + fmt.Printf("expected:\n%s", string(expected)) + fmt.Printf("have:\n%s", string(out)) + } +}
2018-12-15passfile: directly read file instead of invoking catJakob Unterwurzacher
Allows better error handling, gets rid of the call to an external program, and fixes https://github.com/rfjakob/gocryptfs/issues/278 .
2018-09-08configfile: add LoadAndDecrypt wrapperJakob Unterwurzacher
Callers that do not want to decrypt the masterkey should call plain Load(). https://github.com/rfjakob/gocryptfs/issues/258
2018-07-01configfile: reduce function name stutterJakob Unterwurzacher
configfile.LoadConfFile() -> configfile.Load() configfile.CreateConfFile() -> configfile.Create()
2018-03-22Add `-masterkey=stdin` functionalityJakob Unterwurzacher
https://github.com/rfjakob/gocryptfs/issues/218
2018-02-18main: zero password once we are done with itJakob Unterwurzacher
Overwrite the password we have got from the user with zeros once we don't need it anymore, and make sure the variable runs out of scope.
2017-05-28gocryptfs-xray: dumpmasterkey: disable "Reading password from stdin"Jakob Unterwurzacher
...and also exit with the proper exit code when we get an error.
2017-05-28gocryptfs-xray: add function to dump the master keyJakob Unterwurzacher
Fixes https://github.com/rfjakob/gocryptfs/issues/83
2016-10-04lint fixesValient Gough
2016-09-29xray: print block offsetsJakob Unterwurzacher
2016-09-25contentenc: rename constant "IVBitLen" to "DefaultIVBits" and clarify commentJakob Unterwurzacher
128-bit IVs are NOT used everywhere.
2016-09-25xray: add "gocryptfs-xray", on-disk-format exploration toolJakob Unterwurzacher
Example output for a file encrypted in reverse mode: Header: Version: 2, Id: 0b7f5e2574e4afa859a9bb156a2e7772 Block 0: IV: 0b7f5e2574e4afa859a9bb156a2e7773, Tag: bf39279ac6b1ccd852567aaf26ee386b, Len: 4128 Block 1: IV: 0b7f5e2574e4afa859a9bb156a2e7774, Tag: a4f0f9cde7f70a752254aa8fe7718699, Len: 4128 Block 2: IV: 0b7f5e2574e4afa859a9bb156a2e7775, Tag: b467b153016fc1d531818b65ab9e24f6, Len: 4128 Block 3: IV: 0b7f5e2574e4afa859a9bb156a2e7776, Tag: 1fcb7ffd8f1816fbe807df8148718a5c, Len: 4128 Block 4: IV: 0b7f5e2574e4afa859a9bb156a2e7777, Tag: a217e7933ef434c9f03ad931bb5fde9b, Len: 4128 Block 5: IV: 0b7f5e2574e4afa859a9bb156a2e7778, Tag: f3e6240d75cd66371a0b301111d6f1fc, Len: 4128 Block 6: IV: 0b7f5e2574e4afa859a9bb156a2e7779, Tag: bc85d322ebc7761ae5ef114ea3903a56, Len: 4128 Block 7: IV: 0b7f5e2574e4afa859a9bb156a2e777a, Tag: efda01c6b794690f939a12d6d49ac3af, Len: 4128 Block 8: IV: 0b7f5e2574e4afa859a9bb156a2e777b, Tag: b198329d489d1392080f710206932ff0, Len: 2907