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

76 lines
2.3 KiB
C#
Raw Normal View History

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;
using System.Text;
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 WinzipAesKeySize _keySize;
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;
2024-04-23 09:59:30 +01:00
#if NETFRAMEWORK
2024-04-23 09:59:30 +01:00
var rfc2898 = new Rfc2898DeriveBytes(password, salt, RFC2898_ITERATIONS);
KeyBytes = rfc2898.GetBytes(KeySizeInBytes);
IvBytes = rfc2898.GetBytes(KeySizeInBytes);
var generatedVerifyValue = rfc2898.GetBytes(2);
#elif NET10_0_OR_GREATER
var derivedKeySize = (KeySizeInBytes * 2) + 2;
var passwordBytes = Encoding.UTF8.GetBytes(password);
var derivedKey = Rfc2898DeriveBytes.Pbkdf2(
passwordBytes,
salt,
RFC2898_ITERATIONS,
HashAlgorithmName.SHA1,
derivedKeySize
);
KeyBytes = derivedKey.AsSpan(0, KeySizeInBytes).ToArray();
IvBytes = derivedKey.AsSpan(KeySizeInBytes, KeySizeInBytes).ToArray();
var generatedVerifyValue = derivedKey.AsSpan((KeySizeInBytes * 2), 2).ToArray();
2024-04-23 09:59:30 +01:00
#else
var rfc2898 = new Rfc2898DeriveBytes(
password,
salt,
RFC2898_ITERATIONS,
HashAlgorithmName.SHA1
);
KeyBytes = rfc2898.GetBytes(KeySizeInBytes);
2024-04-23 09:59:30 +01:00
IvBytes = rfc2898.GetBytes(KeySizeInBytes);
var generatedVerifyValue = rfc2898.GetBytes(2);
#endif
2024-04-23 09:59:30 +01:00
var verify = BinaryPrimitives.ReadInt16LittleEndian(passwordVerifyValue);
var generated = BinaryPrimitives.ReadInt16LittleEndian(generatedVerifyValue);
if (verify != generated)
{
throw new InvalidFormatException("bad password");
}
2022-12-20 15:06:44 +00:00
}
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
}