-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathContentEncryption.cs
More file actions
75 lines (68 loc) · 4.29 KB
/
ContentEncryption.cs
File metadata and controls
75 lines (68 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using BytecodeApi.Extensions;
namespace BytecodeApi.Cryptography;
/// <summary>
/// Class to encrypt and decrypt content using AES-256. Encrypted <see cref="byte" />[] objects generated by this class are proprietary and specific to this class only. For generic AES operations, see <see cref="Encryption" />.
/// </summary>
public static class ContentEncryption
{
private static readonly byte[] Magic = "BAPI_AES_1".ToAnsiBytes();
/// <summary>
/// Encrypts the specified <see cref="byte" />[] using the specified password and returns a <see cref="byte" />[] representing the encrypted version of <paramref name="data" />. The resulting binary is proprietary and can be decrypted using the <see cref="Decrypt" /> method.
/// </summary>
/// <param name="data">A <see cref="byte" />[] with the data to be encrypted.</param>
/// <param name="password">A <see cref="string" /> representing the password to encrypt <paramref name="data" /> with. The password is hashed using SHA-256.</param>
/// <returns>
/// A new <see cref="byte" />[] representing the encrypted version of <paramref name="data" />. The resulting binary is proprietary and can be decrypted using the <see cref="Decrypt" /> method.
/// </returns>
public static byte[] Encrypt(byte[] data, string password)
{
return Encrypt(data, password, 1);
}
/// <summary>
/// Encrypts the specified <see cref="byte" />[] using the specified password and returns a <see cref="byte" />[] representing the encrypted version of <paramref name="data" />. The resulting binary is proprietary and can be decrypted using the <see cref="Decrypt" /> method.
/// </summary>
/// <param name="data">A <see cref="byte" />[] with the data to be encrypted.</param>
/// <param name="password">A <see cref="string" /> representing the password to encrypt <paramref name="data" /> with. The password is hashed using SHA-256.</param>
/// <param name="passwordHashPasses">A <see cref="int" /> value indicating the number of hash passes for <paramref name="password" />.</param>
/// <returns>
/// A new <see cref="byte" />[] representing the encrypted version of <paramref name="data" />. The resulting binary is proprietary and can be decrypted using the <see cref="Decrypt" /> method.
/// </returns>
public static byte[] Encrypt(byte[] data, string password, int passwordHashPasses)
{
Check.ArgumentNull(data);
Check.ArgumentNull(password);
Check.ArgumentOutOfRangeEx.Greater0(passwordHashPasses);
byte[] iv = Encryption.GenerateIV();
byte[] key = Hashes.ComputeBytes(password, HashType.SHA256, passwordHashPasses);
byte[] keyHash = Hashes.ComputeBytes(key, HashType.SHA256, passwordHashPasses);
return Magic.Concat(iv, BitConverter.GetBytes(passwordHashPasses), keyHash, Encryption.Encrypt(data, iv, key));
}
/// <summary>
/// Decrypts the specified <see cref="byte" />[] using the specified password and returns a <see cref="byte" />[] representing the decrypted version of <paramref name="data" />. The <paramref name="data" /> parameter is a proprietary binary, created by the <see cref="Encrypt(byte[], string)" /> method.
/// </summary>
/// <param name="data">A <see cref="byte" />[] with the data to be decrypted.</param>
/// <param name="password">A <see cref="string" /> representing the password to decrypt <paramref name="data" /> with.</param>
/// <returns>
/// A new <see cref="byte" />[] representing the decrypted version of <paramref name="data" />.
/// </returns>
public static byte[] Decrypt(byte[] data, string password)
{
Check.ArgumentNull(data);
Check.ArgumentNull(password);
Check.Format(data.Length >= Magic.Length && data.GetBytes(0, Magic.Length).Compare(Magic), $"Binary does not represent a valid {nameof(ContentEncryption)} binary.");
byte[] iv = data.GetBytes(Magic.Length, 16);
int passwordPasses = BitConverter.ToInt32(data, Magic.Length + 16);
byte[] keyHash = data.GetBytes(Magic.Length + 20, 32);
byte[] key = Hashes.ComputeBytes(password, HashType.SHA256, passwordPasses);
byte[] userKeyHash = Hashes.ComputeBytes(key, HashType.SHA256, passwordPasses);
if (userKeyHash.Compare(keyHash))
{
int dataOffset = Magic.Length + 52;
return Encryption.Decrypt(data.GetBytes(dataOffset, data.Length - dataOffset), iv, key);
}
else
{
throw Throw.WrongPassword();
}
}
}