patbef-ServiceOutside/ServiceShared/Models/Response/EncryptedResponse.cs

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))));
}
}
}
}