2020-05-23 16:27:55 -07:00
|
|
|
#nullable disable
|
|
|
|
|
|
2015-12-30 11:19:42 +00:00
|
|
|
using System;
|
2019-12-30 18:58:25 +01:00
|
|
|
using System.Buffers.Binary;
|
2016-02-13 09:42:59 +00:00
|
|
|
using System.Security.Cryptography;
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
namespace SharpCompress.Common.Zip;
|
|
|
|
|
|
|
|
|
|
internal class WinzipAesEncryptionData
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
private const int RFC2898_ITERATIONS = 1000;
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
private readonly byte[] _salt;
|
|
|
|
|
private readonly WinzipAesKeySize _keySize;
|
|
|
|
|
private readonly byte[] _passwordVerifyValue;
|
|
|
|
|
private readonly string _password;
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
private byte[] _generatedVerifyValue;
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
internal WinzipAesEncryptionData(
|
|
|
|
|
WinzipAesKeySize keySize,
|
|
|
|
|
byte[] salt,
|
|
|
|
|
byte[] passwordVerifyValue,
|
|
|
|
|
string password
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
_keySize = keySize;
|
|
|
|
|
_salt = salt;
|
|
|
|
|
_passwordVerifyValue = passwordVerifyValue;
|
|
|
|
|
_password = password;
|
|
|
|
|
Initialize();
|
|
|
|
|
}
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
internal byte[] IvBytes { get; set; }
|
2020-05-23 16:27:55 -07:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
internal byte[] KeyBytes { get; set; }
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:20:49 +00:00
|
|
|
private int KeySizeInBytes => KeyLengthInBytes(_keySize);
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:20:49 +00:00
|
|
|
internal static int KeyLengthInBytes(WinzipAesKeySize keySize) =>
|
|
|
|
|
keySize switch
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
WinzipAesKeySize.KeySize128 => 16,
|
|
|
|
|
WinzipAesKeySize.KeySize192 => 24,
|
|
|
|
|
WinzipAesKeySize.KeySize256 => 32,
|
|
|
|
|
_ => throw new InvalidOperationException(),
|
|
|
|
|
};
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
private void Initialize()
|
|
|
|
|
{
|
2023-12-18 09:01:54 +00:00
|
|
|
#if NETFRAMEWORK || NETSTANDARD2_0
|
2022-12-20 15:06:44 +00:00
|
|
|
var rfc2898 = new Rfc2898DeriveBytes(_password, _salt, RFC2898_ITERATIONS);
|
2023-12-18 09:01:54 +00:00
|
|
|
#else
|
|
|
|
|
var rfc2898 = new Rfc2898DeriveBytes(
|
2023-12-18 09:04:04 +00:00
|
|
|
_password,
|
|
|
|
|
_salt,
|
|
|
|
|
RFC2898_ITERATIONS,
|
|
|
|
|
HashAlgorithmName.SHA1
|
|
|
|
|
);
|
2022-12-20 13:45:47 +00:00
|
|
|
#endif
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
KeyBytes = rfc2898.GetBytes(KeySizeInBytes); // 16 or 24 or 32 ???
|
|
|
|
|
IvBytes = rfc2898.GetBytes(KeySizeInBytes);
|
|
|
|
|
_generatedVerifyValue = rfc2898.GetBytes(2);
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
var verify = BinaryPrimitives.ReadInt16LittleEndian(_passwordVerifyValue);
|
|
|
|
|
if (_password != null)
|
|
|
|
|
{
|
|
|
|
|
var generated = BinaryPrimitives.ReadInt16LittleEndian(_generatedVerifyValue);
|
|
|
|
|
if (verify != generated)
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
throw new InvalidFormatException("bad password");
|
2015-12-30 11:19:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|