I use the CQRS pattern in the Onion architecture and I encrypt the user’s private data such as email, phone number, and address and store them in the database. I couldn’t reach a conclusion on whether I should encrypt each data separately or whether doing it all at once would provide me with a more accurate and optimized result. Can you tell me your thoughts on this point?
Below is the entire code, here is the part I encrypted one by one;
createUserDto.Email = await _cryptoHelperService.EncryptString(request.Email);
createUserDto.Address = await _cryptoHelperService.EncryptString(request.Address);
createUserDto.GSM = await _cryptoHelperService.EncryptString(request.GSM);
createUserDto.GSMPersonal = await _cryptoHelperService.EncryptString(request.GSMPersonal);
My parallel encryption method, which I did all at once, is;
private async Task EncryptAndAssignAsync(Action<string> propertySetter, string value)
{
var encryptedValue = await _cryptoHelperService.EncryptString(value);
propertySetter(encryptedValue);
}
var encryptTasks = new List<Task>
{
EncryptAndAssignAsync(val => createUserDto.Email = val, request.Email),
EncryptAndAssignAsync(val => createUserDto.Address = val, request.Address),
EncryptAndAssignAsync(val => createUserDto.GSM = val, request.GSM),
EncryptAndAssignAsync(val => createUserDto.GSMPersonal = val, request.GSMPersonal)
};
await Task.WhenAll(encryptTasks);
the entire method;
public class CreateUserCommandHandler : IRequestHandler<CreateUserCommandRequest, OptResult<CreateUserCommandResponse>>
{
private readonly IUserService _userService;
private readonly ICryptographyService _cryptoHelperService;
private readonly IMapper _mapper;
public CreateUserCommandHandler(IUserService userService, ICryptographyService cryptoHelperService, IMapper mapper)
{
_userService = userService;
_cryptoHelperService = cryptoHelperService;
_mapper = mapper;
}
private async Task EncryptAndAssignAsync(Action<string> propertySetter, string value)
{
var encryptedValue = await _cryptoHelperService.EncryptString(value);
propertySetter(encryptedValue);
}
public async Task<OptResult<CreateUserCommandResponse>> Handle(CreateUserCommandRequest request, CancellationToken cancellationToken)
{
var startTime = DateTime.UtcNow;
OptResult<CreateUserCommandResponse> response = new OptResult<CreateUserCommandResponse>();
return await ExceptionHandler.HandleOptResultAsync(async () =>
{
var createUserDto = _mapper.Map<CreateUser_Dto>(request);
createUserDto.Guid = Guid.NewGuid().ToString();
createUserDto.Email = await _cryptoHelperService.EncryptString(request.Email);
createUserDto.Address = await _cryptoHelperService.EncryptString(request.Address);
createUserDto.GSM = await _cryptoHelperService.EncryptString(request.GSM);
createUserDto.GSMPersonal = await _cryptoHelperService.EncryptString(request.GSMPersonal);
var encryptTasks = new List<Task>
{
EncryptAndAssignAsync(val => createUserDto.Email = val, request.Email),
EncryptAndAssignAsync(val => createUserDto.Address = val, request.Address),
EncryptAndAssignAsync(val => createUserDto.GSM = val, request.GSM),
EncryptAndAssignAsync(val => createUserDto.GSMPersonal = val, request.GSMPersonal)
};
await Task.WhenAll(encryptTasks);
var createdUser = await _userService.CreateAsync(createUserDto);
string DescryptedEmail = await _cryptoHelperService.DecryptString(createUserDto.Email);
string DescryptedGSM = await _cryptoHelperService.DecryptString(createUserDto.GSM);
var endTime = DateTime.UtcNow;
// Geçen süreyi hesapla
var elapsedTime = endTime - startTime;
Console.WriteLine($"İşlem tamamlandı. Geçen süre: {elapsedTime.TotalMilliseconds} ms");
if (createUserDto != null)
{
response.Succeeded = true;
response.Data = new CreateUserCommandResponse
{
Id = createUserDto.Guid,
UserName = createUserDto.UserName,
Email = DescryptedEmail,
GSM = DescryptedGSM,
};
}
else
{
response.Succeeded = false;
response.Message = "User creation failed.";
}
return response;
});
}
}