From 15534f466af2389844b8ae545f4d2116197bbf4f Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Sat, 28 Apr 2018 18:20:40 +0100 Subject: [PATCH] Add basic rar5 crypt header --- .../Common/Rar/Headers/CryptHeader.cs | 50 +++++++++++++++++++ src/SharpCompress/Common/Rar/Headers/Flags.cs | 9 +++- .../Common/Rar/Headers/RarHeaderFactory.cs | 6 +++ .../Rar/RarHeaderFactoryTest.cs | 2 +- 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 src/SharpCompress/Common/Rar/Headers/CryptHeader.cs diff --git a/src/SharpCompress/Common/Rar/Headers/CryptHeader.cs b/src/SharpCompress/Common/Rar/Headers/CryptHeader.cs new file mode 100644 index 00000000..6cb347c6 --- /dev/null +++ b/src/SharpCompress/Common/Rar/Headers/CryptHeader.cs @@ -0,0 +1,50 @@ +using SharpCompress.IO; + +namespace SharpCompress.Common.Rar.Headers +{ + internal class CryptHeader : RarHeader + { + + private const int CRYPT_VERSION = 0; // Supported encryption version. + private const int SIZE_SALT50 = 16; + private const int SIZE_PSWCHECK = 8; + private const int SIZE_PSWCHECK_CSUM = 4; + + + private bool UsePswCheck; + private uint Lg2Count; // Log2 of PBKDF2 repetition count. + private byte[] Salt; + private byte[] PswCheck; + + public CryptHeader(RarHeader header, RarCrcBinaryReader reader) + : base(header, reader, HeaderType.Crypt) + { + } + + protected override void ReadFinish(MarkingBinaryReader reader) + { + var cryptVersion = reader.ReadRarVIntUInt32(); + if (cryptVersion > CRYPT_VERSION) + { + //error? + return; + } + + UsePswCheck = HasHeaderFlag(EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK); + Lg2Count = reader.ReadRarVIntByte(1); + if (Lg2Count > 0) + { + //error? + return; + } + + Salt = reader.ReadBytes(SIZE_SALT50); + if (UsePswCheck) + { + PswCheck = reader.ReadBytes(SIZE_PSWCHECK); + + var csum = reader.ReadBytes(SIZE_PSWCHECK_CSUM); + } + } + } +} \ No newline at end of file diff --git a/src/SharpCompress/Common/Rar/Headers/Flags.cs b/src/SharpCompress/Common/Rar/Headers/Flags.cs index 9c5060e9..7fe7d9b2 100644 --- a/src/SharpCompress/Common/Rar/Headers/Flags.cs +++ b/src/SharpCompress/Common/Rar/Headers/Flags.cs @@ -12,7 +12,8 @@ namespace SharpCompress.Common.Rar.Headers Protect, Sign, NewSub, - EndArchive + EndArchive, + Crypt } internal static class HeaderCodeV @@ -40,6 +41,12 @@ namespace SharpCompress.Common.Rar.Headers public const ushort HasData = 0x8000; } + internal static class EncryptionFlagsV5 + { + // RAR 5.0 archive encryption header specific flags. + public const ushort CHFL_CRYPT_PSWCHECK = 0x0001; // Password check data is present. + } + internal static class HeaderFlagsV5 { public const ushort HasExtra = 0x0001; diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index cb670368..0a637241 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -158,6 +158,12 @@ namespace SharpCompress.Common.Rar.Headers { return new EndArchiveHeader(header, reader); } + case HeaderCodeV.Rar5EncryptionHeader: + { + var ch = new CryptHeader(header, reader); + IsEncrypted = true; + return ch; + } default: { throw new InvalidFormatException("Unknown Rar Header: " + header.HeaderCode); diff --git a/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs b/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs index f334903b..c2732522 100644 --- a/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs +++ b/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs @@ -51,7 +51,7 @@ namespace SharpCompress.Test.Rar { foreach (var header in rarHeaderFactory.ReadHeaders(stream)) { - if (header.HeaderType == HeaderType.Archive) + if (header.HeaderType == HeaderType.Archive || header.HeaderType == HeaderType.Crypt) { Assert.Equal(isEncrypted, rarHeaderFactory.IsEncrypted); break;