Files
aliasvault/apps/server/Tests/AliasVault.UnitTests/Utilities/RsaEncryptionTests.cs
2025-09-03 14:59:14 +02:00

140 lines
7.5 KiB
C#

//-----------------------------------------------------------------------
// <copyright file="RsaEncryptionTests.cs" company="aliasvault">
// Copyright (c) aliasvault. All rights reserved.
// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
namespace AliasVault.UnitTests.Utilities;
using System.Text.Json;
using AliasVault.Cryptography.Server;
/// <summary>
/// Tests for the SrpArgonEncryption class.
/// </summary>
public class RsaEncryptionTests
{
/// <summary>
/// Example public key for RSA encryption tests. This is a public key generated by the JSInterop on the client.
/// </summary>
public const string PublicKey = "{\"alg\":\"RSA-OAEP-256\",\"e\":\"AQAB\",\"ext\":true,\"key_ops\":[\"encrypt\"],\"kty\":\"RSA\",\"n\":\"lW8fRfSvLQiK9uZgm_kFjHMY1SedAZlVvZ_8d_d5oqWezQhan8-Y10Qvx0NMe57sQB3ePnShJFNE33w83kgRNkOyxKJ2FOVKtRptd7CgwIt_l9TPjdrB0J0hFn9b1eit2vpQlOdP_Wa8WvW2eVdXYEMWuBU4-aj8vY2qzcmBc-HhJX-Me9oXhUscJxeqMP4_sNiN7D4I0enrmYicB3JQMhUIwMmNt-0srHTdSvHh_6vFZMqB9ohfh2D9Q0BzYcI8rGEy1RTYsmF1zYyoOOzeRGOcKCVNeLO9LZxfAdm1Eq5zv47uw543cxCZXIZPlXOVriMEtTRwaGzE_3RZmpGJqw\"}";
/// <summary>
/// Example private key for RSA encryption tests. This is a private key generated by the JSInterop on the client.
/// </summary>
public const string PrivateKey = "{\"alg\":\"RSA-OAEP-256\",\"d\":\"KLByToUaseNym1oNkkrTRPQOHfREXywWWaTXhP8AwtXgEKomqv9G-c6aR-K-T6btY2P-oPj268I0rbnRhSEQdrsmUT5_cp8goYGJrx6MFwGlA32x6klXnus6GDsjkXJi7I5eJL17XV99CDOBtTagFxkNdaBpvClUcHTDvncQ5bGAIrNqS7KADoi-E19BxiW_GcSJiVT4H8kDHCkcgTjZx4rKJjTPqqJOLg_poDrvnTJbsjcXP80kQ1AAENRAvDGhSWzP0IYtP1DM_2FzM1s1b_SrUsS3KiO8drR2Kv-PSOvncpaNVnZGElGCraJ3B2Mm-dr3vFjkyWeWPceqyhtYoQ\",\"dp\":\"ttxRg6uB2YLWfkPKUkzAaBWniZDHM4silJX3IgexA5GJBd9GIhUiVEolc_MgmieQbZ10CC65wqcHVv82lgCeqxYHxHWLxxJCrOpvkFlYE8wr_WqOPQEzYKv3KsL6s6Fj7Pbv9WehWpXdlbJUm4Cy5cgUkdH6PXiwBSvfhCQGrYk\",\"dq\":\"YFqlDAVTfvTR2bMJulvWzd_at81CsEmR-lPo91h-3cLpxcLDOlrTP-d3Ass2I4r1PtBT1bKuuHeQ6fZmHH55a6m8XxPEs2BuIxlh9RiFfWbd66969UOnItuawf0rfGneKt1zl4st60T3KXd8-ECrLxdsvOYpOEuNzvIY_b3qitE\",\"e\":\"AQAB\",\"ext\":true,\"key_ops\":[\"decrypt\"],\"kty\":\"RSA\",\"n\":\"lW8fRfSvLQiK9uZgm_kFjHMY1SedAZlVvZ_8d_d5oqWezQhan8-Y10Qvx0NMe57sQB3ePnShJFNE33w83kgRNkOyxKJ2FOVKtRptd7CgwIt_l9TPjdrB0J0hFn9b1eit2vpQlOdP_Wa8WvW2eVdXYEMWuBU4-aj8vY2qzcmBc-HhJX-Me9oXhUscJxeqMP4_sNiN7D4I0enrmYicB3JQMhUIwMmNt-0srHTdSvHh_6vFZMqB9ohfh2D9Q0BzYcI8rGEy1RTYsmF1zYyoOOzeRGOcKCVNeLO9LZxfAdm1Eq5zv47uw543cxCZXIZPlXOVriMEtTRwaGzE_3RZmpGJqw\",\"p\":\"yUdbuDwmVwKhou5xXUxJfi1eOjN-5F88wtyR4LpgU2OvZ7m-er4hpXx5I2E-KTVX_iIp0Q9VDXhHH-WkN3qg20RXjRoxwgrggYbfdIYdrB-2kbMamq5cOf2XbXGEO8PoDXYoZprIB0EhrD4qVVykPUYg5El0hIKPdfs9LNoOEzs\",\"q\":\"vg93lGTurG0EY179tPr6Qe3ttKEN9zvQ97dZ9034DOWDoWLe-iMKG1-yKmkG4uwC8QqNnm1mPz7EqOuHPPGVTTib9NA4JdM27PUHSPKDUvp0cV4LhF6e-W7tMFk8WbJ2ACqkqhZHYgm-FDkZBCpnehNegTxipLluKa79G__ZHFE\",\"qi\":\"fnI3Wh5aYuxI0R18NTeFKjo1P7_Ck65Gc9O3CmeqiIe58EJaXQEcdwdSOG8aVmn03szXLHEnp7anNIH63f0ericbRYdCQVhcQpvsXzEM_sp4aYmwz45palrjlY4Jc6G6XQn3FwiqqRDvpnXdsunnQ62HHhxmslaEMYHQyLng2ss\"}";
/// <summary>
/// Full flow test for server-side email encryption and client-side decryption.
/// </summary>
[Test]
public void EmailEncryptionAndDecryptionTest()
{
// -----------------
// Server-side part:
// -----------------
// 1. Generate symmetric key.
var symmetricKey = Encryption.GenerateRandomSymmetricKey();
// 2. Encrypt email body with symmetric key.
var emailBody = "Hello, RSA encryption!";
var encryptedEmailBody = Encryption.SymmetricEncrypt(emailBody, symmetricKey);
// 3. Encrypt symmetric key with public key.
var encryptedSymmetricKey = Encryption.EncryptSymmetricKeyWithRsa(symmetricKey, PublicKey);
// -----------------
// Client-side part:
// -----------------
// 4. Decrypt symmetric key with private key.
var decryptedSymmetricKey = Encryption.DecryptSymmetricKeyWithRsa(encryptedSymmetricKey, PrivateKey);
// 5. Decrypt email body with symmetric key.
var decryptedEmailBody = Encryption.SymmetricDecrypt(encryptedEmailBody, decryptedSymmetricKey);
Assert.That(decryptedEmailBody, Is.EqualTo(emailBody));
}
/// <summary>
/// Tests that GenerateRsaKeyPair method returns a valid key pair.
/// </summary>
[Test]
public void GenerateRsaKeyPair_ShouldReturnValidKeyPair()
{
Assert.Multiple(() =>
{
Assert.That(PublicKey, Is.Not.Null);
Assert.That(PrivateKey, Is.Not.Null);
Assert.That(PublicKey, Is.Not.EqualTo(PrivateKey));
// Verify that the keys are in valid JSON format
Assert.That(() => JsonSerializer.Deserialize<Dictionary<string, object>>(PublicKey), Throws.Nothing);
Assert.That(() => JsonSerializer.Deserialize<Dictionary<string, object>>(PrivateKey), Throws.Nothing);
});
}
/// <summary>
/// Tests if GenerateRandomSymmetricKey method returns a key of correct length.
/// </summary>
[Test]
public void GenerateRandomSymmetricKey_ReturnsCorrectLength()
{
var key = Encryption.GenerateRandomSymmetricKey();
Assert.That(key, Has.Length.EqualTo(32), "The generated key should be 32 bytes (256 bits) long.");
}
/// <summary>
/// Tests if GenerateRandomSymmetricKey method generates different keys on consecutive calls.
/// </summary>
[Test]
public void GenerateRandomSymmetricKey_GeneratesDifferentKeys()
{
var key1 = Encryption.GenerateRandomSymmetricKey();
var key2 = Encryption.GenerateRandomSymmetricKey();
Assert.That(key1, Is.Not.EqualTo(key2), "Two generated keys should not be identical.");
}
/// <summary>
/// Tests if EncryptSymmetricKey method correctly encrypts a symmetric key.
/// </summary>
[Test]
public void EncryptSymmetricKey_EncryptsCorrectly()
{
var symmetricKey = Encryption.GenerateRandomSymmetricKey();
var encryptedKey = Encryption.EncryptSymmetricKeyWithRsa(symmetricKey, PublicKey);
Assert.That(encryptedKey, Is.Not.Null.And.Not.Empty, "Encrypted key should not be null or empty.");
Assert.That(encryptedKey, Is.Not.EqualTo(Convert.ToBase64String(symmetricKey)), "Encrypted key should be different from the original key.");
}
/// <summary>
/// Tests if a symmetric key can be correctly encrypted and then decrypted.
/// </summary>
[Test]
public void EncryptAndDecryptSymmetricKey_ReturnsOriginalKey()
{
var symmetricKey = Encryption.GenerateRandomSymmetricKey();
var encryptedKey = Encryption.EncryptSymmetricKeyWithRsa(symmetricKey, PublicKey);
// Assuming you have a method to decrypt with the private key
var decryptedKey = Encryption.DecryptSymmetricKeyWithRsa(encryptedKey, PrivateKey);
Assert.That(decryptedKey, Is.EqualTo(symmetricKey), "Decrypted key should match the original symmetric key.");
}
/// <summary>
/// Tests if EncryptSymmetricKey method throws an exception when given an invalid public key.
/// </summary>
[Test]
public void EncryptSymmetricKey_WithInvalidPublicKey_ThrowsException()
{
var symmetricKey = Encryption.GenerateRandomSymmetricKey();
var invalidPublicKey = "invalid_key";
Assert.Throws<JsonException>(
() => Encryption.EncryptSymmetricKeyWithRsa(symmetricKey, invalidPublicKey),
"Encrypting with an invalid public key should throw an ArgumentException.");
}
}