SEBPatch/SafeExamBrowser.Proctoring/ScreenProctoring/Encryptor.cs

91 lines
2.3 KiB
C#

/*
* Copyright (c) 2025 ETH Zürich, IT Services
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Linq;
using System.Text;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using SafeExamBrowser.Settings.Proctoring;
namespace SafeExamBrowser.Proctoring.ScreenProctoring
{
internal class Encryptor
{
private const int IV_BYTES = 16;
private const int MAC_BITS = 128;
private readonly Lazy<byte[]> encryptionSecret;
internal Encryptor(ScreenProctoringSettings settings)
{
encryptionSecret = new Lazy<byte[]>(() => Encoding.UTF8.GetBytes(settings.EncryptionSecret));
}
internal byte[] Decrypt(byte[] data)
{
var (iv, encrypted) = Split(data);
var cipher = new GcmBlockCipher(new AesEngine());
var key = new KeyParameter(encryptionSecret.Value);
var parameters = new AeadParameters(key, MAC_BITS, iv);
cipher.Init(false, parameters);
var outputSize = cipher.GetOutputSize(encrypted.Length);
var decrypted = new byte[outputSize];
var offset = cipher.ProcessBytes(encrypted, 0, encrypted.Length, decrypted, 0);
cipher.DoFinal(decrypted, offset);
return decrypted;
}
internal byte[] Encrypt(byte[] data)
{
var cipher = new GcmBlockCipher(new AesEngine());
var iv = GenerateInitializationVector();
var key = new KeyParameter(encryptionSecret.Value);
var parameters = new AeadParameters(key, MAC_BITS, iv);
cipher.Init(true, parameters);
var outputSize = cipher.GetOutputSize(data.Length);
var encrypted = new byte[outputSize];
var offset = cipher.ProcessBytes(data, 0, data.Length, encrypted, 0);
cipher.DoFinal(encrypted, offset);
return Merge(iv, encrypted);
}
private byte[] GenerateInitializationVector()
{
var vector = new byte[IV_BYTES];
var random = new Random();
random.NextBytes(vector);
return vector;
}
private byte[] Merge(byte[] iv, byte[] encrypted)
{
return iv.Concat(encrypted).ToArray();
}
private (byte[] iv, byte[] encrypted) Split(byte[] data)
{
var iv = data.Take(IV_BYTES).ToArray();
var encrypted = data.Skip(IV_BYTES).ToArray();
return (iv, encrypted);
}
}
}