diff --git a/README.md b/README.md index 8704f3a..e33a0fc 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files | | PRODINFO | | [`patterns/prodinfo.hexpat`](patterns/prodinfo.hexpat) | Nintendo Switch PRODINFO | | Protobuf | | [`patterns/protobuf.hexpat`](patterns/protobuf.hexpat) | Google Protobuf encoding | +| psafe3 | | [`patterns/psafe3.hexpat`](patterns/psafe3.hexpat`) | Password Safe V3 | | PyInstaller | | [`patterns/pyinstaller.hexpat`](patterns/pyinstaller.hexpat) | PyInstaller binray files | | PYC | | [`patterns/pyc.hexpat`](patterns/pyc.hexpat) | Python bytecode files | | QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file | diff --git a/patterns/psafe3.hexpat b/patterns/psafe3.hexpat new file mode 100644 index 0000000..eb3ecb7 --- /dev/null +++ b/patterns/psafe3.hexpat @@ -0,0 +1,33 @@ +// Password Safe V3 +// Only a small part of the file is unencrypted. + +#pragma endian little +#pragma description Password Safe V3 + +import std.mem; +import std.sys; + +struct Prologue { + u8 SALT[32]; + u32 ITER; + u8 HPP[32] [[name("H(P')")]]; + u8 B1[16]; + u8 B2[16]; + u8 B3[16]; + u8 B4[16]; + u8 IV[16]; +}; + +struct EOF { + u8 HMAC[32]; +}; + +char magic[4] @ 0x00; +std::assert(magic == "PWS3", "Invalid file: bad tag!"); +char marker[16] @ std::mem::size() - 48; +std::assert(marker == "PWS3-EOFPWS3-EOF", "Invalid file: bad end marker!"); + +Prologue prologue @ 0x04; +u8 HMAC[32] @ std::mem::size() - 32; + +EOF eof @ std::mem::size() - 48; \ No newline at end of file diff --git a/tests/patterns/test_data/psafe3.hexpat.psafe3 b/tests/patterns/test_data/psafe3.hexpat.psafe3 new file mode 100644 index 0000000..717d171 Binary files /dev/null and b/tests/patterns/test_data/psafe3.hexpat.psafe3 differ