Files
sharpcompress/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs

77 lines
2.2 KiB
C#
Raw Normal View History

2020-05-23 16:27:55 -07:00
#nullable disable
2015-12-30 11:19:42 +00:00
using System;
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(
_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
}
}
}
}