199 lines
7.6 KiB
C#
199 lines
7.6 KiB
C#
|
using ServiceShared.Crypto;
|
|||
|
using System.Text;
|
|||
|
using System.Text.Json;
|
|||
|
|
|||
|
namespace ServiceShared.Models.Response
|
|||
|
{
|
|||
|
public class EncryptedResponse
|
|||
|
{
|
|||
|
public string descriptor { get; set; }
|
|||
|
public string encrypted_content { get; set; }
|
|||
|
public string hmac { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Default constructor of EncryptedResponse
|
|||
|
/// </summary>
|
|||
|
public EncryptedResponse()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Constructor for EncryptedResponse
|
|||
|
/// </summary>
|
|||
|
/// <param name="descriptor">Descriptor of the content object</param>
|
|||
|
/// <param name="contentObject">content object that should be encrypted</param>
|
|||
|
/// <param name="deriveKey">shared deriveKey that should be used in the encrption</param>
|
|||
|
public EncryptedResponse(string descriptor, object? contentObject, byte[] deriveKey)
|
|||
|
{
|
|||
|
this.Encrypt(descriptor, contentObject, deriveKey);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Constructor for EncryptedResponse
|
|||
|
/// </summary>
|
|||
|
/// <param name="descriptor">Descriptor of the content object</param>
|
|||
|
/// <param name="contentObject">content object that should be encrypted</param>
|
|||
|
/// <param name="deriveKey">shared deriveKey that should be used in the encrption</param>
|
|||
|
/// <returns>returns true if encryption was successfully</returns>
|
|||
|
public bool Encrypt(string descriptor, object? contentObject, byte[] deriveKey)
|
|||
|
{
|
|||
|
bool result = false;
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
if (deriveKey != null && deriveKey.Length > 0 && !string.IsNullOrEmpty(descriptor))
|
|||
|
{
|
|||
|
this.descriptor = AES.Encrypt(descriptor, deriveKey);
|
|||
|
|
|||
|
if (contentObject != null)
|
|||
|
{
|
|||
|
string json = JsonSerializer.Serialize(contentObject, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(json))
|
|||
|
{
|
|||
|
this.encrypted_content = AES.Encrypt(json, deriveKey);
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(this.encrypted_content))
|
|||
|
{
|
|||
|
this.hmac = SHA512.HMAC(this.encrypted_content, deriveKey);
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(hmac))
|
|||
|
{
|
|||
|
result = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
this.hmac = SHA512.HMAC(this.descriptor, deriveKey);
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(hmac))
|
|||
|
{
|
|||
|
result = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception ex)
|
|||
|
{
|
|||
|
Log.Error(ex, "ServiceOutside.Models.Request.EncryptedResponse", "Encrypt");
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Decrypts the encrypted content
|
|||
|
/// </summary>
|
|||
|
/// <typeparam name="T">Type of content object</typeparam>
|
|||
|
/// <param name="deriveKey">shared deriveKey for the decryption</param>
|
|||
|
/// <returns>returns a object with defined type</returns>
|
|||
|
public T? Decrypt<T>(byte[] deriveKey)
|
|||
|
{
|
|||
|
object? result = null;
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
if (deriveKey != null && !string.IsNullOrEmpty(this.descriptor))
|
|||
|
{
|
|||
|
this.descriptor = AES.Decrypt(this.descriptor, deriveKey);
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(this.encrypted_content))
|
|||
|
{
|
|||
|
string json = AES.Decrypt(this.encrypted_content, deriveKey);
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(json))
|
|||
|
{
|
|||
|
result = JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions
|
|||
|
{
|
|||
|
PropertyNameCaseInsensitive = true
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception ex)
|
|||
|
{
|
|||
|
Log.Error(ex, "ServiceOutside.Models.Request.EncryptedResponse", "Decrypt<T>(byte[])");
|
|||
|
}
|
|||
|
|
|||
|
return (T?)result;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Decrypts the encrypted content
|
|||
|
/// </summary>
|
|||
|
/// <param name="deriveKey">shared deriveKey for the decryption</param>
|
|||
|
/// <returns>returns a object</returns>
|
|||
|
public object? Decrypt(byte[] deriveKey)
|
|||
|
{
|
|||
|
object? result = null;
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
if (deriveKey != null && deriveKey.Length > 0 && !string.IsNullOrEmpty(this.descriptor))
|
|||
|
{
|
|||
|
this.descriptor = AES.Decrypt(this.descriptor, deriveKey);
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(this.encrypted_content))
|
|||
|
{
|
|||
|
string json = AES.Decrypt(this.encrypted_content, deriveKey);
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(json))
|
|||
|
{
|
|||
|
result = JsonSerializer.Deserialize<object?>(json, new JsonSerializerOptions
|
|||
|
{
|
|||
|
PropertyNameCaseInsensitive = true
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception ex)
|
|||
|
{
|
|||
|
Log.Error(ex, "ServiceOutside.Models.Request.EncryptedResponse", "Decrypt(byte[])");
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Validates the encrypted request by HMAC and Ed25519
|
|||
|
/// </summary>
|
|||
|
/// <param name="deriveKey">shared derive key, that should be used for the HMAC Authentification</param>
|
|||
|
/// <param name="clientSignatur">client signature, that should be verified</param>
|
|||
|
/// <param name="clientSignaturKey">client public signature key, that was used in client signature</param>
|
|||
|
/// <returns>true if request is valid</returns>
|
|||
|
public bool ValidSignature(byte[] deriveKey, string clientSignatur, string clientSignaturKey)
|
|||
|
{
|
|||
|
if (!string.IsNullOrEmpty(this.encrypted_content))
|
|||
|
{
|
|||
|
return
|
|||
|
// Validate over HMAC
|
|||
|
((!string.IsNullOrEmpty(this.hmac) &&
|
|||
|
deriveKey != null &&
|
|||
|
deriveKey.Length > 0 &&
|
|||
|
Crypto.SHA512.isValidAuthenticationCode(hmac, this.encrypted_content, deriveKey)) &&
|
|||
|
|
|||
|
//Validate over Ed25519
|
|||
|
(!string.IsNullOrEmpty(clientSignatur) &&
|
|||
|
Ed25519.CheckValid(Convert.FromBase64String(clientSignatur), Encoding.UTF8.GetBytes(this.encrypted_content), Convert.FromBase64String(clientSignaturKey))));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return
|
|||
|
// Validate over HMAC
|
|||
|
((!string.IsNullOrEmpty(this.hmac) &&
|
|||
|
deriveKey != null &&
|
|||
|
deriveKey.Length > 0 &&
|
|||
|
Crypto.SHA512.isValidAuthenticationCode(hmac, this.descriptor, deriveKey)) &&
|
|||
|
|
|||
|
//Validate over Ed25519
|
|||
|
(!string.IsNullOrEmpty(clientSignatur) &&
|
|||
|
Ed25519.CheckValid(Convert.FromBase64String(clientSignatur), Encoding.UTF8.GetBytes(this.descriptor), Convert.FromBase64String(clientSignaturKey))));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|