From 00772f6e82738dad5116475bbdba857d8f91bcb0 Mon Sep 17 00:00:00 2001 From: Klaus Fischer <klaus.fischer@eloware.com> Date: Wed, 15 Jun 2022 16:41:18 +0200 Subject: [PATCH] Implemented 1st abstraction layer except SubmitSubmission --- DummyClient/Program.cs | 5 +- ...EncryptionWithSelfSignedCertificateTest.cs | 2 +- .../SenderEncryptionWithoutCertificateTest.cs | 2 +- FitConnect/FluentSender.cs | 2 +- FitConnect/FluentSubscriber.cs | 51 ++++++++++++++----- FitConnect/Models/Submission.cs | 8 ++- FitConnect/Security/IEncryption.cs | 4 +- FitConnect/Security/RsaEncryption.cs | 7 ++- FluentApiTest/FluentSubscriberPollingTests.cs | 4 +- 9 files changed, 59 insertions(+), 26 deletions(-) diff --git a/DummyClient/Program.cs b/DummyClient/Program.cs index ed9e0316..0bb37157 100644 --- a/DummyClient/Program.cs +++ b/DummyClient/Program.cs @@ -52,11 +52,8 @@ void FluentSubscriberCall() { // Reading submission client.Subscriber .Authenticate(clientId!, clientSecret!) - .GetSubmission("destinationId", "submissionId") + .GetSubmission("submissionId") .GetAttachments() - .DecryptAttachments() - .DecryptData() - .DecryptMetadata() .ConfirmSubmission(); } diff --git a/EncryptionTests/SenderEncryptionWithSelfSignedCertificateTest.cs b/EncryptionTests/SenderEncryptionWithSelfSignedCertificateTest.cs index bbfa68d3..fe3670a7 100644 --- a/EncryptionTests/SenderEncryptionWithSelfSignedCertificateTest.cs +++ b/EncryptionTests/SenderEncryptionWithSelfSignedCertificateTest.cs @@ -61,7 +61,7 @@ public class SenderEncryptionWithSelfSignedCertificateTest { [Test] [Order(20)] public void Decrypt_ResultShouldMatchToEncrypt() { - var result = _sender.Encryption.DecryptDataAsync(cypher!); + var result = _sender.Encryption.DecryptData(cypher!); Encoding.UTF8.GetString(result).Should().Be(ToEncrypt); } diff --git a/EncryptionTests/SenderEncryptionWithoutCertificateTest.cs b/EncryptionTests/SenderEncryptionWithoutCertificateTest.cs index 8524e925..a53393c3 100644 --- a/EncryptionTests/SenderEncryptionWithoutCertificateTest.cs +++ b/EncryptionTests/SenderEncryptionWithoutCertificateTest.cs @@ -42,7 +42,7 @@ public class SenderEncryptionWithoutCertificateTest { [Order(20)] public void DecryptData_ShouldMatchToEncrypt() { var cypher = Convert.FromBase64String(_cypherText); - var plain = _sender.Encryption.DecryptDataAsync(cypher); + var plain = _sender.Encryption.DecryptData(cypher); Encoding.UTF8.GetString(plain).Should().Be(ToEncrypt); } diff --git a/FitConnect/FluentSender.cs b/FitConnect/FluentSender.cs index ad1d0b4c..23b0a09e 100644 --- a/FitConnect/FluentSender.cs +++ b/FitConnect/FluentSender.cs @@ -133,7 +133,7 @@ public class FluentSender : Sender, IFluentApi<FluentSender> { /// <returns></returns> /// <remarks>This call finishes the submission process</remarks> /// <exception cref="InvalidOperationException"></exception> - public FluentSender SendSubmission(Metadata metadata, Data? data = null) { + public FluentSender SendSubmission(Metadata? metadata, Data? data = null) { if (_nextStep != State.SendSubmission) throw new InvalidOperationException( "Can only send a submission after attachments have been uploaded"); diff --git a/FitConnect/FluentSubscriber.cs b/FitConnect/FluentSubscriber.cs index 1a0c4f7b..aa301c46 100644 --- a/FitConnect/FluentSubscriber.cs +++ b/FitConnect/FluentSubscriber.cs @@ -1,8 +1,11 @@ +using System.Buffers.Text; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; +using FitConnect.Models; using FitConnect.Services; using FitConnect.Services.Models; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; namespace FitConnect; @@ -16,6 +19,7 @@ public class FluentSubscriber : Subscriber, IFluentApi<FluentSubscriber> { public Dictionary<string, IEnumerable<string>>? Submissions { get; private set; } public long? AvailableSubmissions { get; private set; } + public Submission? Submission { get; set; } #endregion @@ -48,13 +52,21 @@ public class FluentSubscriber : Subscriber, IFluentApi<FluentSubscriber> { /// <summary> /// Receives a specific submission from the server. /// </summary> - /// <param name="destinationId"></param> /// <param name="submissionId"></param> /// <returns></returns> - public FluentSubscriber GetSubmission(string destinationId, string submissionId) { + public FluentSubscriber GetSubmission(string submissionId) { if (_token == null) - throw new AuthenticationException("You must authenticate before you can get a submission."); - throw new NotImplementedException(); + throw new AuthenticationException( + "You must authenticate before you can get a submission."); + + Submission = (Submission)SubmissionService.GetSubmission(submissionId); + Submission.Metadata = + JsonConvert.DeserializeObject<Metadata>( + Encryption.DecryptData(Submission.EncryptedMetadata)); + Submission.Data = + JsonConvert.DeserializeObject<Data>(Encryption.DecryptData(Submission.EncryptedData)); + + return this; } /// <summary> @@ -82,23 +94,34 @@ public class FluentSubscriber : Subscriber, IFluentApi<FluentSubscriber> { return this; } + /// <summary> + /// Reading attachments for a submission. + /// </summary> + /// <returns></returns> + /// <exception cref="NotImplementedException"></exception> public FluentSubscriber GetAttachments() { - throw new NotImplementedException(); - } + // TODO add guard calls - public FluentSubscriber DecryptAttachments() { - throw new NotImplementedException(); - } + var attachments = new List<Attachment>(); + foreach (var id in Submission!.Attachments.Select(a => a.Id)) { + var encryptedAttachment = SubmissionService.GetAttachment(Submission.Id, id); - public FluentSubscriber DecryptData() { - throw new NotImplementedException(); - } + var content = Encryption.DecryptData(Convert.FromBase64String(encryptedAttachment)); + // TODO Where to get the HASH from? + attachments.Add(new Attachment(id, content, "HASH")); + } - public FluentSubscriber DecryptMetadata() { - throw new NotImplementedException(); + Submission.Attachments = attachments; + return this; } + public FluentSubscriber ConfirmSubmission() { + // TODO add guard calls + throw new NotImplementedException(); + SubmissionService.SubmitSubmission(Submission.Id, (SubmitSubmissionDto)Submission); + + return this; } } diff --git a/FitConnect/Models/Submission.cs b/FitConnect/Models/Submission.cs index d8cb6cfd..cdeedf2c 100644 --- a/FitConnect/Models/Submission.cs +++ b/FitConnect/Models/Submission.cs @@ -30,8 +30,10 @@ public class Submission { public ServiceType ServiceType { get; init; } public Callback? Callback { get; set; } - public Metadata Metadata { get; set; } + public Metadata? Metadata { get; set; } public Data? Data { get; set; } + public string EncryptedMetadata { get; set; } + public string EncryptedData { get; set; } public bool IsSubmissionReadyToAdd(out string? error) { var innerError = ""; @@ -70,6 +72,10 @@ public class Submission { }; } + public static explicit operator SubmitSubmissionDto(Submission dto) { + throw new NotImplementedException(); + } + public static explicit operator CreateSubmissionDto(Submission sub) { return new CreateSubmissionDto { AnnouncedAttachments = sub.Attachments.Select(a => a.Id).ToList(), diff --git a/FitConnect/Security/IEncryption.cs b/FitConnect/Security/IEncryption.cs index 048d612c..06204459 100644 --- a/FitConnect/Security/IEncryption.cs +++ b/FitConnect/Security/IEncryption.cs @@ -20,7 +20,9 @@ public interface IEncryption { /// <exception cref="Exception"></exception> void ImportCertificate(string certificatePath, string password); - byte[] DecryptDataAsync(byte[] data); + byte[] DecryptData(byte[] data); + string DecryptData(string data); + byte[] ExportPublicKey(); byte[] ExportPrivateKey(); byte[] EncryptData(byte[] data); diff --git a/FitConnect/Security/RsaEncryption.cs b/FitConnect/Security/RsaEncryption.cs index 860adf39..d6d5980c 100644 --- a/FitConnect/Security/RsaEncryption.cs +++ b/FitConnect/Security/RsaEncryption.cs @@ -2,6 +2,7 @@ using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; +using System.Text; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; @@ -82,10 +83,14 @@ public class RsaEncryption : IEncryption { _rsa.ImportParameters(parameters.Value); } - public byte[] DecryptDataAsync(byte[] data) { + public byte[] DecryptData(byte[] data) { return (_privateKey ?? _rsa).Decrypt(data, RSAEncryptionPadding.OaepSHA256); } + public string DecryptData(string data) { + return Encoding.UTF8.GetString(DecryptData(Encoding.UTF8.GetBytes(data))); + } + public byte[] ExportPublicKey() { return _rsa.ExportRSAPublicKey(); } diff --git a/FluentApiTest/FluentSubscriberPollingTests.cs b/FluentApiTest/FluentSubscriberPollingTests.cs index 1f86cdd8..56aca2ec 100644 --- a/FluentApiTest/FluentSubscriberPollingTests.cs +++ b/FluentApiTest/FluentSubscriberPollingTests.cs @@ -42,8 +42,8 @@ public class FluentSubscriberPollingTests { [Test] public void - FluentSubscriberPollSubmissions_UnauthenticatedPollCall_ThrowsInvalidOperationException() { - Assert.Throws<InvalidOperationException>(() => + FluentSubscriberPollSubmissions_UnauthenticatedPollCall_ThrowsAuthenticationException() { + Assert.Throws<AuthenticationException>(() => _client.Subscriber .GetSubmissions("")); } -- GitLab