Compare commits

...

41 Commits

Author SHA1 Message Date
Adam Hathcock
372a2c8375 Mark for 0.35.0 2023-12-18 09:59:46 +00:00
Adam Hathcock
8f27121f21 Merge pull request #789 from adamhathcock/dotnet8
Dotnet8
2023-12-18 09:57:50 +00:00
Adam Hathcock
b986bf675f just remove readme 2023-12-18 09:31:33 +00:00
Adam Hathcock
80718a461b fix readme? 2023-12-18 09:24:00 +00:00
Adam Hathcock
2d14ecf58b add readme 2023-12-18 09:20:44 +00:00
Adam Hathcock
32aa9877c0 remove caching 2023-12-18 09:16:02 +00:00
Adam Hathcock
cee3a9c11d Revert "add lock files"
This reverts commit 30a31de45b.
2023-12-18 09:15:26 +00:00
Adam Hathcock
b78643f2d8 update upload artifact 2023-12-18 09:15:15 +00:00
Adam Hathcock
30a31de45b add lock files 2023-12-18 09:13:14 +00:00
Adam Hathcock
e4c4db534c build for dotnet 8 2023-12-18 09:09:31 +00:00
Adam Hathcock
4f7a0d3ad0 CI to dotnet 8 2023-12-18 09:08:06 +00:00
Adam Hathcock
ea3a96eead update and rerun csharpier 2023-12-18 09:04:04 +00:00
Adam Hathcock
c0e01ac132 Use dotnet 8 and update deps 2023-12-18 09:01:54 +00:00
Adam Hathcock
28ea50bca4 Merge pull request #788 from Erior/develop
RAR5 decryption support
2023-12-18 08:51:25 +00:00
Lars Vahlenberg
619e44b30f CSharpier fixes 2023-12-16 03:08:51 +01:00
Lars Vahlenberg
d678275dee Implement RAR5 decryption 2023-12-16 02:53:09 +01:00
Adam Hathcock
08eed53595 Merge pull request #787 from adamhathcock/dependabot/github_actions/actions/setup-dotnet-4
Bump actions/setup-dotnet from 3 to 4
2023-12-11 10:09:28 +00:00
dependabot[bot]
ff40f7d262 Bump actions/setup-dotnet from 3 to 4
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3 to 4.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 09:35:30 +00:00
Adam Hathcock
3c1ae51dae Merge pull request #786 from Erior/feature/Issue-774
LZMA EOS marker detection
2023-12-11 08:46:20 +00:00
Adam Hathcock
8a59fc9aaf Merge pull request #785 from Erior/feature/Issue-782
Handle tar files generated with tar -H oldgnu that has large uid/gid values
2023-12-11 08:44:54 +00:00
Adam Hathcock
b7ea9dd841 Merge pull request #784 from Erior/feature/rar-comment
Dont crash on reading rar5 comment #783
2023-12-11 08:44:01 +00:00
Lars Vahlenberg
0320db6b4a LZMA EOS marker detection 2023-12-09 13:41:35 +01:00
Lars Vahlenberg
18c7f58093 Handle tar files generated with tar -H oldgnu that has large uid/gid values 2023-12-04 22:35:11 +01:00
Lars Vahlenberg
7f6f7b1436 Resharpier fix 2023-12-04 20:28:16 +01:00
Lars Vahlenberg
ca49176b97 Dont crash on reading rar5 comment 2023-12-04 20:19:11 +01:00
Adam Hathcock
67be0cd9d7 Mark for 0.34.2 2023-11-15 11:32:51 +00:00
Adam Hathcock
902fadef83 Merge pull request #780 from caesay/cs/revert-disable-strongname
Revert change disabling strong name signing in 92df1ec
2023-11-15 11:22:02 +00:00
Adam Hathcock
2777b6411f Merge branch 'master' into cs/revert-disable-strongname 2023-11-15 11:18:30 +00:00
Adam Hathcock
e3235d7f04 Merge pull request #781 from adamhathcock/fix-formatting
Update csharpier and fix formatting
2023-11-15 11:18:04 +00:00
Adam Hathcock
dc89c8858e comment out more C++ bits 2023-11-15 11:14:39 +00:00
Adam Hathcock
d28a278d63 Comment out flag to allow formatting 2023-11-15 11:10:05 +00:00
Adam Hathcock
7080c2abd0 Update csharpier and fix formatting 2023-11-15 11:05:30 +00:00
Caelan Sayler
43f86bcab8 Revert change disabling strong name signing in 92df1ec 2023-11-14 16:34:58 +00:00
Adam Hathcock
7d9c875c4d Merge pull request #778 from LANCommander/throw-cancelled-exception
Throw ReaderCancelledException on reader cancelled
2023-11-13 08:34:15 +00:00
Pat Hartl
ed4099eb12 Throw ReaderCancelledException on reader cancelled 2023-11-10 23:36:14 -06:00
Adam Hathcock
632b83f75d Mark for 0.34.1 2023-10-02 08:44:14 +01:00
Adam Hathcock
66c92637f9 Merge pull request #769 from Erior/feature/766
Update Zstd to 0.7.2
2023-09-25 09:01:51 +01:00
Adam Hathcock
6bcaebc471 Merge pull request #768 from Erior/feature/761
Feature/761
2023-09-25 09:01:20 +01:00
Lars Vahlenberg
7feee1027c Update Zstd to 0.7.2 2023-09-23 16:02:27 +02:00
Lars Vahlenberg
4fd8c77fa9 CSharpier cleanup 2023-09-23 14:52:39 +02:00
Lars Vahlenberg
bc3bb2d323 Set FilePart properties for directory type 2023-09-23 14:51:08 +02:00
65 changed files with 668 additions and 2315 deletions

View File

@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"csharpier": {
"version": "0.25.0",
"version": "0.26.7",
"commands": [
"dotnet-csharpier"
]

View File

@@ -15,18 +15,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v3
- uses: actions/setup-dotnet@v4
with:
dotnet-version: 7.0.x
- name: NuGet Caching
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('packages.lock.json', '*/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
dotnet-version: 8.0.x
- run: dotnet run --project build/build.csproj
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}-sharpcompress.nupkg
path: artifacts/*

View File

@@ -61,7 +61,7 @@ Target(
Target(
Test,
DependsOn(Build),
ForEach("net7.0", "net462"),
ForEach("net8.0", "net462"),
framework =>
{
IEnumerable<string> GetFiles(string d)

View File

@@ -1,6 +1,6 @@
{
"sdk": {
"version": "7.0.101",
"version": "8.0.100",
"rollForward": "latestFeature"
}
}

View File

@@ -25,8 +25,8 @@ public static class ArchiveFactory
public static IWritableArchive Create(ArchiveType type)
{
var factory = Factory.Factories
.OfType<IWriteableArchiveFactory>()
var factory = Factory
.Factories.OfType<IWriteableArchiveFactory>()
.FirstOrDefault(item => item.KnownArchiveType == type);
if (factory != null)

View File

@@ -25,10 +25,19 @@ internal class SeekableFilePart : RarFilePart
internal override Stream GetCompressedStream()
{
stream.Position = FileHeader.DataStartPosition;
if (FileHeader.R4Salt != null)
{
return new RarCryptoWrapper(stream, password!, FileHeader.R4Salt);
var cryptKey = new CryptKey3(password!);
return new RarCryptoWrapper(stream, FileHeader.R4Salt, cryptKey);
}
if (FileHeader.Rar5CryptoInfo != null)
{
var cryptKey = new CryptKey5(password!, FileHeader.Rar5CryptoInfo);
return new RarCryptoWrapper(stream, FileHeader.Rar5CryptoInfo.Salt, cryptKey);
}
return stream;
}

View File

@@ -0,0 +1,87 @@
#nullable disable
using System.Security.Cryptography;
using System.Text;
using SharpCompress.Common.Rar.Headers;
namespace SharpCompress.Common.Rar;
internal class CryptKey3 : ICryptKey
{
const int AES_128 = 128;
private string _password;
public CryptKey3(string password)
{
_password = password ?? "";
}
public ICryptoTransform Transformer(byte[] salt)
{
var aesIV = new byte[EncryptionConstV5.SIZE_INITV];
var rawLength = 2 * _password.Length;
var rawPassword = new byte[rawLength + EncryptionConstV5.SIZE_SALT30];
var passwordBytes = Encoding.UTF8.GetBytes(_password);
for (var i = 0; i < _password.Length; i++)
{
rawPassword[i * 2] = passwordBytes[i];
rawPassword[(i * 2) + 1] = 0;
}
for (var i = 0; i < salt.Length; i++)
{
rawPassword[i + rawLength] = salt[i];
}
var msgDigest = SHA1.Create();
const int noOfRounds = (1 << 18);
const int iblock = 3;
byte[] digest;
var data = new byte[(rawPassword.Length + iblock) * noOfRounds];
//TODO slow code below, find ways to optimize
for (var i = 0; i < noOfRounds; i++)
{
rawPassword.CopyTo(data, i * (rawPassword.Length + iblock));
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 0] = (byte)i;
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 1] = (byte)(i >> 8);
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 2] = (byte)(i >> 16);
if (i % (noOfRounds / EncryptionConstV5.SIZE_INITV) == 0)
{
digest = msgDigest.ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock));
aesIV[i / (noOfRounds / EncryptionConstV5.SIZE_INITV)] = digest[19];
}
}
digest = msgDigest.ComputeHash(data);
//slow code ends
var aesKey = new byte[EncryptionConstV5.SIZE_INITV];
for (var i = 0; i < 4; i++)
{
for (var j = 0; j < 4; j++)
{
aesKey[(i * 4) + j] = (byte)(
(
((digest[i * 4] * 0x1000000) & 0xff000000)
| (uint)((digest[(i * 4) + 1] * 0x10000) & 0xff0000)
| (uint)((digest[(i * 4) + 2] * 0x100) & 0xff00)
| (uint)(digest[(i * 4) + 3] & 0xff)
) >> (j * 8)
);
}
}
var aes = Aes.Create();
aes.KeySize = AES_128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
aes.Key = aesKey;
aes.IV = aesIV;
return aes.CreateDecryptor();
}
}

View File

@@ -0,0 +1,97 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using SharpCompress.Common.Rar.Headers;
namespace SharpCompress.Common.Rar;
internal class CryptKey5 : ICryptKey
{
const int AES_256 = 256;
const int DERIVED_KEY_LENGTH = 0x10;
const int SHA256_DIGEST_SIZE = 32;
private string _password;
private Rar5CryptoInfo _cryptoInfo;
private byte[] _pswCheck = { };
private byte[] _hashKey = { };
public CryptKey5(string password, Rar5CryptoInfo rar5CryptoInfo)
{
_password = password;
_cryptoInfo = rar5CryptoInfo;
}
public byte[] PswCheck => _pswCheck;
public byte[] HashKey => _hashKey;
private static List<byte[]> GenerateRarPBKDF2Key(
string password,
byte[] salt,
int iterations,
int keyLength
)
{
using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password)))
{
byte[] block = hmac.ComputeHash(salt);
byte[] finalHash = (byte[])block.Clone();
var loop = new int[] { iterations, 17, 17 };
var res = new List<byte[]> { };
for (int x = 0; x < 3; x++)
{
for (int i = 1; i < loop[x]; i++)
{
block = hmac.ComputeHash(block);
for (int j = 0; j < finalHash.Length; j++)
{
finalHash[j] ^= block[j];
}
}
res.Add((byte[])finalHash.Clone());
}
return res;
}
}
public ICryptoTransform Transformer(byte[] salt)
{
int iterations = (1 << _cryptoInfo.LG2Count); // Adjust the number of iterations as needed
var salt_rar5 = salt.Concat(new byte[] { 0, 0, 0, 1 });
var derivedKey = GenerateRarPBKDF2Key(
_password,
salt_rar5.ToArray(),
iterations,
DERIVED_KEY_LENGTH
);
_hashKey = derivedKey[1];
_pswCheck = new byte[EncryptionConstV5.SIZE_PSWCHECK];
for (int i = 0; i < SHA256_DIGEST_SIZE; i++)
{
_pswCheck[i % EncryptionConstV5.SIZE_PSWCHECK] ^= derivedKey[2][i];
}
if (_cryptoInfo.UsePswCheck && !_cryptoInfo.PswCheck.SequenceEqual(_pswCheck))
{
throw new CryptographicException("The password did not match.");
}
var aes = Aes.Create();
aes.KeySize = AES_256;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
aes.Key = derivedKey[0];
aes.IV = _cryptoInfo.InitV;
return aes.CreateDecryptor();
}
}

View File

@@ -1,50 +1,21 @@
#nullable disable
using System;
using System.Security.Cryptography;
using SharpCompress.Common.Rar.Headers;
using SharpCompress.IO;
namespace SharpCompress.Common.Rar.Headers;
internal class ArchiveCryptHeader : 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 const int CRYPT5_KDF_LG2_COUNT_MAX = 24; // LOG2 of maximum accepted iteration count.
private bool _usePswCheck;
private uint _lg2Count; // Log2 of PBKDF2 repetition count.
private byte[] _salt;
private byte[] _pswCheck;
private byte[] _pswCheckCsm;
public ArchiveCryptHeader(RarHeader header, RarCrcBinaryReader reader)
: base(header, reader, HeaderType.Crypt) { }
public Rar5CryptoInfo CryptInfo = new Rar5CryptoInfo();
protected override void ReadFinish(MarkingBinaryReader reader)
{
var cryptVersion = reader.ReadRarVIntUInt32();
if (cryptVersion > CRYPT_VERSION)
{
//error?
return;
}
var encryptionFlags = reader.ReadRarVIntUInt32();
_usePswCheck = FlagUtility.HasFlag(encryptionFlags, EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK);
_lg2Count = reader.ReadRarVIntByte(1);
//UsePswCheck = HasHeaderFlag(EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK);
if (_lg2Count > CRYPT5_KDF_LG2_COUNT_MAX)
{
//error?
return;
}
_salt = reader.ReadBytes(SIZE_SALT50);
if (_usePswCheck)
{
_pswCheck = reader.ReadBytes(SIZE_PSWCHECK);
_pswCheckCsm = reader.ReadBytes(SIZE_PSWCHECK_CSUM);
}
CryptInfo = new Rar5CryptoInfo(reader, false);
}
}

View File

@@ -1,5 +1,11 @@
#nullable disable
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using SharpCompress.IO;
#if !Rar2017_64bit
using size_t = System.UInt32;
#else
@@ -8,11 +14,6 @@ using nuint = System.UInt64;
using size_t = System.UInt64;
#endif
using SharpCompress.IO;
using System;
using System.IO;
using System.Text;
namespace SharpCompress.Common.Rar.Headers;
internal class FileHeader : RarHeader
@@ -104,7 +105,13 @@ internal class FileHeader : RarHeader
throw new InvalidFormatException("rar5 header size / extra size inconsistency");
}
isEncryptedRar5 = false;
const ushort FHEXTRA_CRYPT = 0x01;
const ushort FHEXTRA_HASH = 0x02;
const ushort FHEXTRA_HTIME = 0x03;
// const ushort FHEXTRA_VERSION = 0x04;
// const ushort FHEXTRA_REDIR = 0x05;
// const ushort FHEXTRA_UOWNER = 0x06;
// const ushort FHEXTRA_SUBDATA = 0x07;
while (RemainingHeaderBytes(reader) > 0)
{
@@ -114,21 +121,34 @@ internal class FileHeader : RarHeader
switch (type)
{
//TODO
case 1: // file encryption
case FHEXTRA_CRYPT: // file encryption
{
isEncryptedRar5 = true;
Rar5CryptoInfo = new Rar5CryptoInfo(reader, true);
//var version = reader.ReadRarVIntByte();
//if (version != 0) throw new InvalidFormatException("unknown encryption algorithm " + version);
if (Rar5CryptoInfo.PswCheck.All(singleByte => singleByte == 0))
{
Rar5CryptoInfo = null;
}
}
break;
// case 2: // file hash
// {
//
// }
// break;
case 3: // file time
case FHEXTRA_HASH:
{
const uint FHEXTRA_HASH_BLAKE2 = 0x0;
const uint HASH_BLAKE2 = 0x03;
const int BLAKE2_DIGEST_SIZE = 0x20;
if ((uint)reader.ReadRarVInt() == FHEXTRA_HASH_BLAKE2)
{
var hash = HASH_BLAKE2;
var digest = reader.ReadBytes(BLAKE2_DIGEST_SIZE);
throw new InvalidFormatException("Not yet implemented " + hash);
}
// enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2};
}
break;
case FHEXTRA_HTIME: // file time
{
var flags = reader.ReadRarVIntUInt16();
@@ -148,22 +168,22 @@ internal class FileHeader : RarHeader
}
break;
//TODO
// case 4: // file version
// case FHEXTRA_VERSION: // file version
// {
//
// }
// break;
// case 5: // file system redirection
// case FHEXTRA_REDIR: // file system redirection
// {
//
// }
// break;
// case 6: // unix owner
// case FHEXTRA_UOWNER: // unix owner
// {
//
// }
// break;
// case 7: // service data
// case FHEXTRA_SUBDATA: // service data
// {
//
// }
@@ -255,7 +275,6 @@ internal class FileHeader : RarHeader
var fileNameBytes = reader.ReadBytes(nameSize);
const int saltSize = 8;
const int newLhdSize = 32;
switch (HeaderCode)
@@ -293,7 +312,7 @@ internal class FileHeader : RarHeader
var datasize = HeaderSize - newLhdSize - nameSize;
if (HasFlag(FileFlagsV4.SALT))
{
datasize -= saltSize;
datasize -= EncryptionConstV5.SIZE_SALT30;
}
if (datasize > 0)
{
@@ -314,7 +333,7 @@ internal class FileHeader : RarHeader
if (HasFlag(FileFlagsV4.SALT))
{
R4Salt = reader.ReadBytes(saltSize);
R4Salt = reader.ReadBytes(EncryptionConstV5.SIZE_SALT30);
}
if (HasFlag(FileFlagsV4.EXT_TIME))
{
@@ -432,7 +451,7 @@ internal class FileHeader : RarHeader
internal size_t WindowSize { get; private set; }
internal byte[] R4Salt { get; private set; }
internal Rar5CryptoInfo Rar5CryptoInfo { get; private set; }
private byte HostOs { get; set; }
internal uint FileAttributes { get; private set; }
internal long CompressedSize { get; private set; }
@@ -450,8 +469,7 @@ internal class FileHeader : RarHeader
public bool IsDirectory => HasFlag(IsRar5 ? FileFlagsV5.DIRECTORY : FileFlagsV4.DIRECTORY);
private bool isEncryptedRar5 = false;
public bool IsEncrypted => IsRar5 ? isEncryptedRar5 : HasFlag(FileFlagsV4.PASSWORD);
public bool IsEncrypted => IsRar5 ? Rar5CryptoInfo != null : HasFlag(FileFlagsV4.PASSWORD);
internal DateTime? FileLastModifiedTime { get; private set; }

View File

@@ -50,6 +50,17 @@ internal static class EncryptionFlagsV5
public const uint FHEXTRA_CRYPT_HASHMAC = 0x02;
}
internal static class EncryptionConstV5
{
public const int VERSION = 0;
public const uint CRYPT5_KDF_LG2_COUNT_MAX = 0x24;
public const int SIZE_SALT30 = 0x08;
public const int SIZE_SALT50 = 0x10;
public const int SIZE_INITV = 0x10;
public const int SIZE_PSWCHECK = 0x08;
public const int SIZE_PSWCHECK_CSUM = 0x04;
}
internal static class HeaderFlagsV5
{
public const ushort HAS_EXTRA = 0x0001;

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using SharpCompress.IO;

View File

@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.Common.Rar;
using SharpCompress.IO;
using SharpCompress.Readers;
@@ -9,6 +11,8 @@ public class RarHeaderFactory
{
private bool _isRar5;
private Rar5CryptoInfo? _cryptInfo;
public RarHeaderFactory(StreamingMode mode, ReaderOptions options)
{
StreamingMode = mode;
@@ -53,7 +57,19 @@ public class RarHeaderFactory
"Encrypted Rar archive has no password specified."
);
}
reader = new RarCryptoBinaryReader(stream, Options.Password);
if (_isRar5 && _cryptInfo != null)
{
_cryptInfo.ReadInitV(new MarkingBinaryReader(stream));
var _headerKey = new CryptKey5(Options.Password!, _cryptInfo);
reader = new RarCryptoBinaryReader(stream, _headerKey, _cryptInfo.Salt);
}
else
{
var key = new CryptKey3(Options.Password);
reader = new RarCryptoBinaryReader(stream, key);
}
}
var header = RarHeader.TryReadBase(reader, _isRar5, Options.ArchiveEncoding);
@@ -105,7 +121,14 @@ public class RarHeaderFactory
case HeaderCodeV.RAR5_SERVICE_HEADER:
{
var fh = new FileHeader(header, reader, HeaderType.Service);
SkipData(fh, reader);
if (fh.FileName == "CMT")
{
fh.PackedStream = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize);
}
else
{
SkipData(fh, reader);
}
return fh;
}
@@ -133,7 +156,7 @@ public class RarHeaderFactory
{
var ms = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize);
if (fh.R4Salt is null)
if (fh.R4Salt is null && fh.Rar5CryptoInfo is null)
{
fh.PackedStream = ms;
}
@@ -141,8 +164,10 @@ public class RarHeaderFactory
{
fh.PackedStream = new RarCryptoWrapper(
ms,
Options.Password!,
fh.R4Salt
fh.R4Salt is null ? fh.Rar5CryptoInfo.Salt : fh.R4Salt,
fh.R4Salt is null
? new CryptKey5(Options.Password!, fh.Rar5CryptoInfo)
: new CryptKey3(Options.Password!)
);
}
}
@@ -161,9 +186,11 @@ public class RarHeaderFactory
}
case HeaderCodeV.RAR5_ARCHIVE_ENCRYPTION_HEADER:
{
var ch = new ArchiveCryptHeader(header, reader);
var cryptoHeader = new ArchiveCryptHeader(header, reader);
IsEncrypted = true;
return ch;
_cryptInfo = cryptoHeader.CryptInfo;
return cryptoHeader;
}
default:
{

View File

@@ -0,0 +1,8 @@
using System.Security.Cryptography;
namespace SharpCompress.Common.Rar;
internal interface ICryptKey
{
ICryptoTransform Transformer(byte[] salt);
}

View File

@@ -0,0 +1,59 @@
using System;
using System.Security.Cryptography;
using SharpCompress.Common.Rar.Headers;
using SharpCompress.IO;
namespace SharpCompress.Common.Rar;
internal class Rar5CryptoInfo
{
public Rar5CryptoInfo() { }
public Rar5CryptoInfo(MarkingBinaryReader reader, bool readInitV)
{
var cryptVersion = reader.ReadRarVIntUInt32();
if (cryptVersion > EncryptionConstV5.VERSION)
{
throw new CryptographicException($"Unsupported crypto version of {cryptVersion}");
}
var encryptionFlags = reader.ReadRarVIntUInt32();
UsePswCheck = FlagUtility.HasFlag(encryptionFlags, EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK);
LG2Count = reader.ReadRarVIntByte(1);
if (LG2Count > EncryptionConstV5.CRYPT5_KDF_LG2_COUNT_MAX)
{
throw new CryptographicException($"Unsupported LG2 count of {LG2Count}.");
}
Salt = reader.ReadBytes(EncryptionConstV5.SIZE_SALT50);
if (readInitV) // File header needs to read IV here
{
ReadInitV(reader);
}
if (UsePswCheck)
{
PswCheck = reader.ReadBytes(EncryptionConstV5.SIZE_PSWCHECK);
var _pswCheckCsm = reader.ReadBytes(EncryptionConstV5.SIZE_PSWCHECK_CSUM);
var sha = SHA256.Create();
UsePswCheck = sha.ComputeHash(PswCheck).AsSpan().StartsWith(_pswCheckCsm.AsSpan());
}
}
public void ReadInitV(MarkingBinaryReader reader)
{
InitV = reader.ReadBytes(EncryptionConstV5.SIZE_INITV);
}
public bool UsePswCheck = false;
public int LG2Count = 0;
public byte[] InitV = { };
public byte[] Salt = { };
public byte[] PswCheck = { };
}

View File

@@ -1,27 +1,30 @@
using System.Collections.Generic;
#nullable disable
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common.Rar.Headers;
using SharpCompress.Crypto;
namespace SharpCompress.Common.Rar;
internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader
{
private RarRijndael _rijndael;
private byte[] _salt;
private readonly string _password;
private BlockTransformer _rijndael;
private readonly Queue<byte> _data = new Queue<byte>();
private long _readCount;
public RarCryptoBinaryReader(Stream stream, string password)
public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey)
: base(stream)
{
_password = password;
var salt = base.ReadBytes(EncryptionConstV5.SIZE_SALT30);
_readCount += EncryptionConstV5.SIZE_SALT30;
_rijndael = new BlockTransformer(cryptKey.Transformer(salt));
}
// coderb: not sure why this was being done at this logical point
//SkipQueue();
var salt = ReadBytes(8);
_salt = salt;
_rijndael = RarRijndael.InitializeFrom(_password, salt);
public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey, byte[] salt)
: base(stream)
{
_rijndael = new BlockTransformer(cryptKey.Transformer(salt));
}
// track read count ourselves rather than using the underlying stream since we buffer
@@ -36,28 +39,14 @@ internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader
public override void Mark() => _readCount = 0;
private bool UseEncryption => _salt != null;
public override byte ReadByte()
{
if (UseEncryption)
{
return ReadAndDecryptBytes(1)[0];
}
_readCount++;
return base.ReadByte();
return ReadAndDecryptBytes(1)[0];
}
public override byte[] ReadBytes(int count)
{
if (UseEncryption)
{
return ReadAndDecryptBytes(count);
}
_readCount += count;
return base.ReadBytes(count);
return ReadAndDecryptBytes(count);
}
private byte[] ReadAndDecryptBytes(int count)

View File

@@ -1,21 +1,20 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Crypto;
namespace SharpCompress.Common.Rar;
internal sealed class RarCryptoWrapper : Stream
{
private readonly Stream _actualStream;
private readonly byte[] _salt;
private RarRijndael _rijndael;
private BlockTransformer _rijndael;
private readonly Queue<byte> _data = new Queue<byte>();
public RarCryptoWrapper(Stream actualStream, string password, byte[] salt)
public RarCryptoWrapper(Stream actualStream, byte[] salt, ICryptKey key)
{
_actualStream = actualStream;
_salt = salt;
_rijndael = RarRijndael.InitializeFrom(password ?? "", salt);
_rijndael = new BlockTransformer(key.Transformer(salt));
}
public override void Flush() => throw new NotSupportedException();
@@ -26,10 +25,6 @@ internal sealed class RarCryptoWrapper : Stream
public override int Read(byte[] buffer, int offset, int count)
{
if (_salt is null)
{
return _actualStream.Read(buffer, offset, count);
}
return ReadAndDecrypt(buffer, offset, count);
}
@@ -41,7 +36,7 @@ internal sealed class RarCryptoWrapper : Stream
if (sizeToRead > 0)
{
var alignedSize = sizeToRead + ((~sizeToRead + 1) & 0xf);
Span<byte> cipherText = stackalloc byte[RarRijndael.CRYPTO_BLOCK_SIZE];
Span<byte> cipherText = stackalloc byte[16];
for (var i = 0; i < alignedSize / 16; i++)
{
//long ax = System.currentTimeMillis();

View File

@@ -1,114 +0,0 @@
#nullable disable
using System;
using System.Security.Cryptography;
using System.Text;
using SharpCompress.Crypto;
namespace SharpCompress.Common.Rar;
internal class RarRijndael : IDisposable
{
internal const int CRYPTO_BLOCK_SIZE = 16;
private readonly string _password;
private readonly byte[] _salt;
private byte[] _aesInitializationVector;
private RijndaelEngine _rijndael;
private RarRijndael(string password, byte[] salt)
{
_password = password;
_salt = salt;
}
private void Initialize()
{
_rijndael = new RijndaelEngine();
_aesInitializationVector = new byte[CRYPTO_BLOCK_SIZE];
var rawLength = 2 * _password.Length;
var rawPassword = new byte[rawLength + 8];
var passwordBytes = Encoding.UTF8.GetBytes(_password);
for (var i = 0; i < _password.Length; i++)
{
rawPassword[i * 2] = passwordBytes[i];
rawPassword[(i * 2) + 1] = 0;
}
for (var i = 0; i < _salt.Length; i++)
{
rawPassword[i + rawLength] = _salt[i];
}
const int noOfRounds = (1 << 18);
const int iblock = 3;
byte[] digest;
var data = new byte[(rawPassword.Length + iblock) * noOfRounds];
//TODO slow code below, find ways to optimize
for (var i = 0; i < noOfRounds; i++)
{
rawPassword.CopyTo(data, i * (rawPassword.Length + iblock));
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 0] = (byte)i;
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 1] = (byte)(i >> 8);
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 2] = (byte)(
i >> CRYPTO_BLOCK_SIZE
);
if (i % (noOfRounds / CRYPTO_BLOCK_SIZE) == 0)
{
digest = SHA1.Create()
.ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock));
_aesInitializationVector[i / (noOfRounds / CRYPTO_BLOCK_SIZE)] = digest[19];
}
}
digest = SHA1.Create().ComputeHash(data);
//slow code ends
var aesKey = new byte[CRYPTO_BLOCK_SIZE];
for (var i = 0; i < 4; i++)
{
for (var j = 0; j < 4; j++)
{
aesKey[(i * 4) + j] = (byte)(
(
((digest[i * 4] * 0x1000000) & 0xff000000)
| (uint)((digest[(i * 4) + 1] * 0x10000) & 0xff0000)
| (uint)((digest[(i * 4) + 2] * 0x100) & 0xff00)
| (uint)(digest[(i * 4) + 3] & 0xff)
) >> (j * 8)
);
}
}
_rijndael.Init(false, new KeyParameter(aesKey));
}
public static RarRijndael InitializeFrom(string password, byte[] salt)
{
var rijndael = new RarRijndael(password, salt);
rijndael.Initialize();
return rijndael;
}
public byte[] ProcessBlock(ReadOnlySpan<byte> cipherText)
{
Span<byte> plainText = stackalloc byte[CRYPTO_BLOCK_SIZE]; // 16 bytes
var decryptedBytes = new byte[CRYPTO_BLOCK_SIZE];
_rijndael.ProcessBlock(cipherText, plainText);
for (var j = 0; j < CRYPTO_BLOCK_SIZE; j++)
{
decryptedBytes[j] = (byte)(plainText[j] ^ _aesInitializationVector[j % 16]); //32:114, 33:101
}
for (var j = 0; j < _aesInitializationVector.Length; j++)
{
_aesInitializationVector[j] = cipherText[j];
}
return decryptedBytes;
}
public void Dispose() { }
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SharpCompress.Common.Rar.Headers;
using SharpCompress.IO;
using SharpCompress.Readers;
@@ -70,11 +71,7 @@ public abstract class RarVolume : Volume
var part = CreateFilePart(lastMarkHeader!, fh);
var buffer = new byte[fh.CompressedSize];
part.GetCompressedStream().Read(buffer, 0, buffer.Length);
Comment = System.Text.Encoding.UTF8.GetString(
buffer,
0,
buffer.Length - 1
);
Comment = Encoding.UTF8.GetString(buffer, 0, buffer.Length - 1);
}
}
break;

View File

@@ -0,0 +1,12 @@
using System;
namespace SharpCompress.Common;
public class ReaderCancelledException : Exception
{
public ReaderCancelledException(string message)
: base(message) { }
public ReaderCancelledException(string message, Exception inner)
: base(message, inner) { }
}

View File

@@ -75,6 +75,9 @@ internal class SevenZipFilePart : FilePart
internal CompressionType GetCompression()
{
if (Header.IsDir)
return CompressionType.None;
var coder = Folder!._coders.First();
switch (coder._methodId._id)
{
@@ -97,5 +100,7 @@ internal class SevenZipFilePart : FilePart
}
internal bool IsEncrypted =>
Folder!._coders.FindIndex(c => c._methodId._id == CMethodId.K_AES_ID) != -1;
Header.IsDir
? false
: Folder!._coders.FindIndex(c => c._methodId._id == CMethodId.K_AES_ID) != -1;
}

View File

@@ -1,4 +1,4 @@
#nullable disable
#nullable disable
using System;
using System.Buffers.Binary;
@@ -132,8 +132,8 @@ internal sealed class TarHeader
Mode |= 0b1_000_000_000;
}
UserId = ReadAsciiInt64Base8(buffer, 108, 7);
GroupId = ReadAsciiInt64Base8(buffer, 116, 7);
UserId = ReadAsciiInt64Base8oldGnu(buffer, 108, 7);
GroupId = ReadAsciiInt64Base8oldGnu(buffer, 116, 7);
var unixTimeStamp = ReadAsciiInt64Base8(buffer, 136, 11);
LastModifiedTime = EPOCH.AddSeconds(unixTimeStamp).ToLocalTime();
@@ -249,6 +249,24 @@ internal sealed class TarHeader
return Convert.ToInt64(s, 8);
}
private static long ReadAsciiInt64Base8oldGnu(byte[] buffer, int offset, int count)
{
if (buffer[offset] == 0x80 && buffer[offset + 1] == 0x00)
{
return buffer[offset + 4] << 24
| buffer[offset + 5] << 16
| buffer[offset + 6] << 8
| buffer[offset + 7];
}
var s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls();
if (string.IsNullOrEmpty(s))
{
return 0;
}
return Convert.ToInt64(s, 8);
}
private static long ReadAsciiInt64(byte[] buffer, int offset, int count)
{
var s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls();

View File

@@ -1,6 +1,6 @@
using SharpCompress.IO;
using System;
using System;
using System.IO;
using SharpCompress.IO;
namespace SharpCompress.Common.Tar;

View File

@@ -48,15 +48,15 @@ internal class WinzipAesEncryptionData
private void Initialize()
{
#if NET7_0
#if NETFRAMEWORK || NETSTANDARD2_0
var rfc2898 = new Rfc2898DeriveBytes(_password, _salt, RFC2898_ITERATIONS);
#else
var rfc2898 = new Rfc2898DeriveBytes(
_password,
_salt,
RFC2898_ITERATIONS,
HashAlgorithmName.SHA1
);
#else
var rfc2898 = new Rfc2898DeriveBytes(_password, _salt, RFC2898_ITERATIONS);
#endif
KeyBytes = rfc2898.GetBytes(KeySizeInBytes); // 16 or 24 or 32 ???

View File

@@ -69,7 +69,6 @@
// -----------------------------------------------------------------------
using System;
using SharpCompress.Algorithms;
namespace SharpCompress.Compressors.Deflate;
@@ -1959,7 +1958,9 @@ internal sealed partial class DeflateManager
// returning Z_STREAM_END instead of Z_BUFF_ERROR.
}
else if (
_codec.AvailableBytesIn == 0 && (int)flush <= old_flush && flush != FlushType.Finish
_codec.AvailableBytesIn == 0
&& (int)flush <= old_flush
&& flush != FlushType.Finish
)
{
// workitem 8557

View File

@@ -64,7 +64,6 @@
// -----------------------------------------------------------------------
using System;
using SharpCompress.Algorithms;
namespace SharpCompress.Compressors.Deflate;

View File

@@ -30,8 +30,8 @@ using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common.Tar.Headers;
using System.Text;
using SharpCompress.Common.Tar.Headers;
namespace SharpCompress.Compressors.Deflate;

View File

@@ -4,11 +4,11 @@
#nullable disable
using SharpCompress.Common.Zip;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using SharpCompress.Common.Zip;
namespace SharpCompress.Compressors.Deflate64;

View File

@@ -207,14 +207,23 @@ public class LzmaStream : Stream
if (_availableBytes == 0 && !_uncompressedChunk)
{
_rangeDecoder.ReleaseStream();
// Check range corruption scenario
if (
!_rangeDecoder.IsFinished
|| (_rangeDecoderLimit >= 0 && _rangeDecoder._total != _rangeDecoderLimit)
)
{
throw new DataErrorException();
// Stream might have End Of Stream marker
_outWindow.SetLimit(toProcess + 1);
if (!_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder))
{
_rangeDecoder.ReleaseStream();
throw new DataErrorException();
}
}
_rangeDecoder.ReleaseStream();
_inputPosition += _rangeDecoder._total;
if (_outWindow.HasPending)
{

View File

@@ -866,7 +866,8 @@ internal partial class Model
);
}
else if (
(currentContext.SummaryFrequency += 4) > 128 + (4 * currentContext.NumberStatistics)
(currentContext.SummaryFrequency += 4)
> 128 + (4 * currentContext.NumberStatistics)
)
{
Refresh((uint)((currentContext.NumberStatistics + 2) >> 1), true, currentContext);

View File

@@ -1,5 +1,4 @@
using System;
using SharpCompress.Compressors.Rar.VM;
namespace SharpCompress.Compressors.Rar.UnpackV1;

View File

@@ -1,5 +1,6 @@
#nullable disable
using System;
#if !Rar2017_64bit
using size_t = System.UInt32;
#else
@@ -7,7 +8,6 @@ using nint = System.Int64;
using nuint = System.UInt64;
using size_t = System.UInt64;
#endif
using System;
namespace SharpCompress.Compressors.Rar.UnpackV2017;

View File

@@ -1,13 +1,13 @@
#if !Rar2017_64bit
using System;
using System.IO;
using SharpCompress.Common.Rar.Headers;
#if !Rar2017_64bit
using size_t = System.UInt32;
#else
using nint = System.Int64;
using nuint = System.UInt64;
using size_t = System.UInt64;
#endif
using System;
using System.IO;
using SharpCompress.Common.Rar.Headers;
namespace SharpCompress.Compressors.Rar.UnpackV2017;

View File

@@ -1,10 +1,12 @@
#if !Rar2017_64bit
using uint32 = System.UInt32;
/*#if !Rar2017_64bit
#else
using nint = System.Int64;
using nuint = System.UInt64;
using size_t = System.UInt64;
#endif
using uint32 = System.UInt32;
#endif*/
namespace SharpCompress.Compressors.Rar.UnpackV2017;

View File

@@ -1,12 +1,14 @@
#if !Rar2017_64bit
using System;
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local;
/*#if !Rar2017_64bit
#else
using nint = System.Int64;
using nuint = System.UInt64;
using size_t = System.UInt64;
#endif
using System;
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local;
#endif*/
namespace SharpCompress.Compressors.Rar.UnpackV2017;

View File

@@ -1,5 +1,9 @@
#nullable disable
using System;
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
using int64 = System.Int64;
#if !Rar2017_64bit
using size_t = System.UInt32;
#else
@@ -7,11 +11,6 @@ using nint = System.Int64;
using nuint = System.UInt64;
using size_t = System.UInt64;
#endif
using int64 = System.Int64;
using System;
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
namespace SharpCompress.Compressors.Rar.UnpackV2017;

View File

@@ -1,5 +1,9 @@
#nullable disable
using System;
using SharpCompress.Common;
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
#if !Rar2017_64bit
using size_t = System.UInt32;
#else
@@ -8,11 +12,6 @@ using nuint = System.UInt64;
using size_t = System.UInt64;
#endif
using System;
using SharpCompress.Common;
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
namespace SharpCompress.Compressors.Rar.UnpackV2017;
internal sealed partial class Unpack : BitInput
@@ -30,12 +29,12 @@ internal sealed partial class Unpack : BitInput
Suspended = false;
UnpAllBuf = false;
UnpSomeRead = false;
#if RarV2017_RAR_SMP
MaxUserThreads = 1;
UnpThreadPool = CreateThreadPool();
ReadBufMT = null;
UnpThreadData = null;
#endif
/*#if RarV2017_RAR_SMP
MaxUserThreads = 1;
UnpThreadPool = CreateThreadPool();
ReadBufMT = null;
UnpThreadData = null;
#endif*/
MaxWinSize = 0;
MaxWinMask = 0;
@@ -199,21 +198,21 @@ internal sealed partial class Unpack : BitInput
break;
#endif
case 50: // RAR 5.0 compression algorithm.
#if RarV2017_RAR_SMP
if (MaxUserThreads > 1)
{
// We do not use the multithreaded unpack routine to repack RAR archives
// in 'suspended' mode, because unlike the single threaded code it can
// write more than one dictionary for same loop pass. So we would need
// larger buffers of unknown size. Also we do not support multithreading
// in fragmented window mode.
if (!Fragmented)
{
Unpack5MT(Solid);
break;
}
}
#endif
/*#if RarV2017_RAR_SMP
if (MaxUserThreads > 1)
{
// We do not use the multithreaded unpack routine to repack RAR archives
// in 'suspended' mode, because unlike the single threaded code it can
// write more than one dictionary for same loop pass. So we would need
// larger buffers of unknown size. Also we do not support multithreading
// in fragmented window mode.
if (!Fragmented)
{
Unpack5MT(Solid);
break;
}
}
#endif*/
Unpack5(Solid);
break;
#if !Rar2017_NOSTRICT

View File

@@ -1,10 +1,12 @@
#if !Rar2017_64bit
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
/*#if !Rar2017_64bit
#else
using nint = System.Int64;
using nuint = System.UInt64;
using size_t = System.UInt64;
#endif
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
#endif*/
namespace SharpCompress.Compressors.Rar.UnpackV2017;

View File

@@ -1,3 +1,8 @@
using System;
using System.Collections.Generic;
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
using int64 = System.Int64;
#if !Rar2017_64bit
using size_t = System.UInt32;
#else
@@ -5,12 +10,6 @@ using nint = System.Int64;
using nuint = System.UInt64;
using size_t = System.UInt64;
#endif
using int64 = System.Int64;
using System.Collections.Generic;
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
using System;
// TODO: REMOVE THIS... WIP
#pragma warning disable 169
@@ -20,8 +19,6 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017;
internal static class UnpackGlobal
{
// Maximum allowed number of compressed bits processed in quick mode.
public const int MAX_QUICK_DECODE_BITS = 10;
@@ -97,11 +94,11 @@ internal struct UnpackBlockHeader
internal struct UnpackBlockTables
{
public DecodeTable LD; // Decode literals.
public DecodeTable DD; // Decode distances.
public DecodeTable LD; // Decode literals.
public DecodeTable DD; // Decode distances.
public DecodeTable LDD; // Decode lower bits of distances.
public DecodeTable RD; // Decode repeating distances.
public DecodeTable BD; // Decode bit lengths in Huffman table.
public DecodeTable RD; // Decode repeating distances.
public DecodeTable BD; // Decode bit lengths in Huffman table.
public void Init()
{
@@ -113,8 +110,7 @@ internal struct UnpackBlockTables
}
};
#if RarV2017_RAR_SMP
/*#if RarV2017_RAR_SMP
enum UNP_DEC_TYPE {
UNPDT_LITERAL,UNPDT_MATCH,UNPDT_FULLREP,UNPDT_REP,UNPDT_FILTER
};
@@ -161,7 +157,7 @@ if (Decoded!=NULL)
free(Decoded);
}
};
#endif
#endif*/
//struct UnpackFilter
@@ -171,12 +167,12 @@ internal class UnpackFilter
public uint BlockStart;
public uint BlockLength;
public byte Channels;
// uint Width;
// byte PosR;
public bool NextWindow;
};
//struct UnpackFilter30
internal class UnpackFilter30
{
@@ -195,15 +191,21 @@ internal class UnpackFilter30
internal class AudioVariables // For RAR 2.0 archives only.
{
public int K1, K2, K3, K4, K5;
public int D1, D2, D3, D4;
public int K1,
K2,
K3,
K4,
K5;
public int D1,
D2,
D3,
D4;
public int LastDelta;
public readonly uint[] Dif = new uint[11];
public uint ByteCount;
public int LastChar;
};
// We can use the fragmented dictionary in case heap does not have the single
// large enough memory block. It is slower than normal dictionary.
internal partial class FragmentedWindow
@@ -223,10 +225,8 @@ internal partial class FragmentedWindow
//size_t GetBlockSize(size_t StartPos,size_t RequiredSize);
};
internal partial class Unpack
{
//void Unpack5(bool Solid);
//void Unpack5MT(bool Solid);
//bool UnpReadBuf();
@@ -254,16 +254,16 @@ internal partial class Unpack
//BitInput Inp;
private BitInput Inp => this; // hopefully this gets inlined
#if RarV2017_RAR_SMP
void InitMT();
bool UnpackLargeBlock(UnpackThreadData &D);
bool ProcessDecoded(UnpackThreadData &D);
ThreadPool *UnpThreadPool;
UnpackThreadData *UnpThreadData;
uint MaxUserThreads;
byte *ReadBufMT;
#endif
/*#if RarV2017_RAR_SMP
void InitMT();
bool UnpackLargeBlock(UnpackThreadData &D);
bool ProcessDecoded(UnpackThreadData &D);
ThreadPool *UnpThreadPool;
UnpackThreadData *UnpThreadData;
uint MaxUserThreads;
byte *ReadBufMT;
#endif*/
private byte[] FilterSrcMemory = Array.Empty<byte>();
private byte[] FilterDstMemory = Array.Empty<byte>();
@@ -279,7 +279,8 @@ byte *ReadBufMT;
// array. In RAR3 last distance is always stored in OldDist[0].
private uint LastDist;
private size_t UnpPtr, WrPtr;
private size_t UnpPtr,
WrPtr;
// Top border of read packed data.
private int ReadTop;
@@ -307,7 +308,6 @@ byte *ReadBufMT;
private int64 WrittenFileSize;
private bool FileExtracted;
/***************************** Unpack v 1.5 *********************************/
//void Unpack15(bool Solid);
//void ShortLZ();
@@ -320,12 +320,29 @@ byte *ReadBufMT;
//void CopyString15(uint Distance,uint Length);
//uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab);
private readonly ushort[] ChSet = new ushort[256], ChSetA = new ushort[256], ChSetB = new ushort[256], ChSetC = new ushort[256];
private readonly byte[] NToPl = new byte[256], NToPlB = new byte[256], NToPlC = new byte[256];
private uint FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3;
private int Buf60, NumHuf, StMode, LCount, FlagsCnt;
private readonly ushort[] ChSet = new ushort[256],
ChSetA = new ushort[256],
ChSetB = new ushort[256],
ChSetC = new ushort[256];
private readonly byte[] NToPl = new byte[256],
NToPlB = new byte[256],
NToPlC = new byte[256];
private uint FlagBuf,
AvrPlc,
AvrPlcB,
AvrLn1,
AvrLn2,
AvrLn3;
private int Buf60,
NumHuf,
StMode,
LCount,
FlagsCnt;
private uint Nhfb,
Nlzb,
MaxDist3;
private uint Nhfb, Nlzb, MaxDist3;
/***************************** Unpack v 1.5 *********************************/
/***************************** Unpack v 2.0 *********************************/
@@ -335,9 +352,11 @@ byte *ReadBufMT;
private readonly byte[] UnpOldTable20 = new byte[MC20 * 4];
private bool UnpAudioBlock;
private uint UnpChannels, UnpCurChannel;
private uint UnpChannels,
UnpCurChannel;
private int UnpChannelDelta;
//void CopyString20(uint Length,uint Distance);
//bool ReadTables20();
//void UnpWriteBuf20();
@@ -345,6 +364,7 @@ byte *ReadBufMT;
//void ReadLastTables();
//byte DecodeAudio(int Delta);
private AudioVariables[] AudV = new AudioVariables[4];
/***************************** Unpack v 2.0 *********************************/
/***************************** Unpack v 3.0 *********************************/
@@ -363,7 +383,8 @@ byte *ReadBufMT;
// because we can have a corrupt archive with one algorithm file
// followed by another algorithm file with "solid" flag and we do not
// want to reuse tables from one algorithm in another.
private bool TablesRead2, TablesRead5;
private bool TablesRead2,
TablesRead5;
// Virtual machine to execute filters code.
/*#if !RarV2017_RAR5ONLY
@@ -385,13 +406,13 @@ byte *ReadBufMT;
// the data block length if lengths are repeating.
private readonly List<int> OldFilterLengths = new List<int>();
#if RarV2017_RAR_SMP
// More than 8 threads are unlikely to provide a noticeable gain
// for unpacking, but would use the additional memory.
void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);}
void UnpackDecode(UnpackThreadData &D);
#endif
/*#if RarV2017_RAR_SMP
// More than 8 threads are unlikely to provide a noticeable gain
// for unpacking, but would use the additional memory.
void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);}
void UnpackDecode(UnpackThreadData &D);
#endif*/
private size_t MaxWinSize;
private size_t MaxWinMask;

View File

@@ -0,0 +1,32 @@
#nullable disable
using System;
using System.Security.Cryptography;
namespace SharpCompress.Crypto;
internal class BlockTransformer : IDisposable
{
private ICryptoTransform _transform;
public BlockTransformer(ICryptoTransform transformer)
{
_transform = transformer;
}
public byte[] ProcessBlock(ReadOnlySpan<byte> cipherText)
{
var decryptedBytes = new byte[cipherText.Length];
var bytes = _transform.TransformBlock(
cipherText.ToArray(),
0,
cipherText.Length,
decryptedBytes,
0
);
return decryptedBytes;
}
public void Dispose() { }
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using SharpCompress.Archives;
using SharpCompress.Archives.GZip;
using SharpCompress.Archives.Tar;

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.IO;
using SharpCompress.Archives;
using SharpCompress.Archives.Tar;
using SharpCompress.Common;

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.IO;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;

View File

@@ -75,7 +75,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IReaderExtracti
}
if (Cancelled)
{
throw new InvalidOperationException("Reader has been cancelled.");
throw new ReaderCancelledException("Reader has been cancelled.");
}
if (entriesForCurrentReadStream is null)
{

View File

@@ -8,9 +8,9 @@ using SharpCompress.Common.Tar;
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
using SharpCompress.Compressors.Deflate;
using SharpCompress.IO;
using SharpCompress.Compressors.LZMA;
using SharpCompress.Compressors.Xz;
using SharpCompress.IO;
namespace SharpCompress.Readers.Tar;

View File

@@ -2,14 +2,14 @@
<PropertyGroup>
<AssemblyTitle>SharpCompress - Pure C# Decompression/Compression</AssemblyTitle>
<NeutralLanguage>en-US</NeutralLanguage>
<VersionPrefix>0.34.0</VersionPrefix>
<AssemblyVersion>0.34.0</AssemblyVersion>
<FileVersion>0.34.0</FileVersion>
<VersionPrefix>0.35.0</VersionPrefix>
<AssemblyVersion>0.35.0</AssemblyVersion>
<FileVersion>0.35.0</FileVersion>
<Authors>Adam Hathcock</Authors>
<TargetFrameworks>net462;netstandard2.0;netstandard2.1;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net462;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0</TargetFrameworks>
<AssemblyName>SharpCompress</AssemblyName>
<AssemblyOriginatorKeyFile>../../SharpCompress.snk</AssemblyOriginatorKeyFile>
<SignAssembly>False</SignAssembly>
<SignAssembly>true</SignAssembly>
<PackageId>SharpCompress</PackageId>
<PackageTags>rar;unrar;zip;unzip;bzip2;gzip;tar;7zip;lzip;xz</PackageTags>
<PackageProjectUrl>https://github.com/adamhathcock/sharpcompress</PackageProjectUrl>
@@ -23,22 +23,22 @@
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<IsTrimmable>true</IsTrimmable>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<PackageReference Include="ZstdSharp.Port" Version="0.6.1" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
<PackageReference Include="ZstdSharp.Port" Version="0.7.4" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
<ItemGroup Condition=" '$(VersionlessImplicitFrameworkDefine)' == 'NETFRAMEWORK' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
</Project>

View File

@@ -1,5 +1,4 @@
using System.IO;
using SharpCompress.Factories;
namespace SharpCompress.Writers;

View File

@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Linq;
using SharpCompress.Common;
namespace SharpCompress.Writers;
@@ -10,8 +9,8 @@ public static class WriterFactory
{
public static IWriter Open(Stream stream, ArchiveType archiveType, WriterOptions writerOptions)
{
var factory = Factories.Factory.Factories
.OfType<IWriterFactory>()
var factory = Factories
.Factory.Factories.OfType<IWriterFactory>()
.FirstOrDefault(item => item.KnownArchiveType == archiveType);
if (factory != null)

View File

@@ -298,10 +298,10 @@ public class ArchiveTests : ReaderTests
memory.Position = 0;
for (int y = 0; y < 9; y++)
for (int x = 0; x < 256; x++)
{
Assert.Equal(x, memory.ReadByte());
}
for (int x = 0; x < 256; x++)
{
Assert.Equal(x, memory.ReadByte());
}
Assert.Equal((int)-1, memory.ReadByte());
}

View File

@@ -22,11 +22,16 @@ public class RarArchiveTests : ArchiveTests
() => ReadRarPassword("Rar.encrypted_filesAndHeader.rar", null)
);
/*[Fact]
public void Rar5_EncryptedFileAndHeader_Archive()
{
[Fact]
public void Rar5_EncryptedFileAndHeader_Archive() =>
ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "test");
}*/
[Fact]
public void Rar5_EncryptedFileAndHeader_Archive_Err() =>
Assert.Throws(
typeof(CryptographicException),
() => ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "failed")
);
[Fact]
public void Rar5_EncryptedFileAndHeader_NoPasswordExceptionTest() =>
@@ -39,20 +44,23 @@ public class RarArchiveTests : ArchiveTests
public void Rar_EncryptedFileOnly_Archive() =>
ReadRarPassword("Rar.encrypted_filesOnly.rar", "test");
/*[Fact]
public void Rar5_EncryptedFileOnly_Archive()
{
[Fact]
public void Rar_EncryptedFileOnly_Archive_Err() =>
Assert.Throws(
typeof(CryptographicException),
() => ReadRarPassword("Rar5.encrypted_filesOnly.rar", "failed")
);
[Fact]
public void Rar5_EncryptedFileOnly_Archive() =>
ReadRarPassword("Rar5.encrypted_filesOnly.rar", "test");
}*/
[Fact]
public void Rar_Encrypted_Archive() => ReadRarPassword("Rar.Encrypted.rar", "test");
/*[Fact]
public void Rar5_Encrypted_Archive()
{
[Fact]
public void Rar5_Encrypted_Archive() =>
ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "test");
}*/
private void ReadRarPassword(string testArchive, string? password)
{

View File

@@ -284,6 +284,12 @@ public class RarReaderTests : ReaderTests
[Fact]
public void Rar_Solid_Reader() => Read("Rar.solid.rar", CompressionType.Rar);
[Fact]
public void Rar_Comment_Reader() => Read("Rar.comment.rar", CompressionType.Rar);
[Fact]
public void Rar5_Comment_Reader() => Read("Rar5.comment.rar", CompressionType.Rar);
[Fact]
public void Rar5_Solid_Reader() => Read("Rar5.solid.rar", CompressionType.Rar);

View File

@@ -135,6 +135,9 @@ public class SevenZipArchiveTests : ArchiveTests
)
);
[Fact]
public void SevenZipArchive_EOS_FileRead() => ArchiveFileRead("7Zip.eos.7z");
[Fact]
public void SevenZipArchive_Delta_FileRead() => ArchiveFileRead("7Zip.delta.7z");

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net462</TargetFrameworks>
<TargetFrameworks>net8.0;net462</TargetFrameworks>
<AssemblyName>SharpCompress.Test</AssemblyName>
<PackageId>SharpCompress.Test</PackageId>
</PropertyGroup>
@@ -8,13 +8,13 @@
<ProjectReference Include="..\..\src\SharpCompress\SharpCompress.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit" Version="2.6.3" />
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
</ItemGroup>
<ItemGroup Condition=" '$(VersionlessImplicitFrameworkDefine)' != 'NETFRAMEWORK' ">

View File

@@ -1,15 +1,15 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using SharpCompress.Archives;
using SharpCompress.Archives.Tar;
using SharpCompress.Common;
using SharpCompress.Writers;
using Xunit;
using System.Text;
using SharpCompress.Readers;
using SharpCompress.Writers.Tar;
using SharpCompress.Readers.Tar;
using SharpCompress.Writers;
using SharpCompress.Writers.Tar;
using Xunit;
namespace SharpCompress.Test.Tar;

View File

@@ -56,6 +56,9 @@ public class TarReaderTests : ReaderTests
[Fact]
public void Tar_Xz_Reader() => Read("Tar.tar.xz", CompressionType.Xz);
[Fact]
public void Tar_GZip_OldGnu_Reader() => Read("Tar.oldgnu.tar.gz", CompressionType.GZip);
[Fact]
public void Tar_BZip2_Entry_Stream()
{

View File

@@ -1,7 +1,7 @@
using System;
using Xunit;
using System.IO;
using SharpCompress.Compressors.Xz.Filters;
using Xunit;
namespace SharpCompress.Test.Xz.Filters;

View File

@@ -1,5 +1,5 @@
using SharpCompress.Compressors.Xz;
using System.IO;
using SharpCompress.Compressors.Xz;
using Xunit;
namespace SharpCompress.Test.Xz;

View File

@@ -1,5 +1,5 @@
using SharpCompress.Compressors.Xz;
using System.IO;
using System.IO;
using SharpCompress.Compressors.Xz;
using Xunit;
namespace SharpCompress.Test.Xz;

View File

@@ -1,5 +1,5 @@
using SharpCompress.Compressors.Xz;
using System.IO;
using System.IO;
using SharpCompress.Compressors.Xz;
using Xunit;
namespace SharpCompress.Test.Xz;

View File

@@ -1,5 +1,4 @@
using System.Text;
using SharpCompress.Common;
using Xunit;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.