diff --git a/DummyClient/Program.cs b/DummyClient/Program.cs index ed9e0316e8b5d59860343e4133158c578fddd7a4..0bb37157a8cbdcf8cde81423a66be63e4ae26854 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 bbfa68d3a42aab7d2e99d92baa48ed8d501c90a0..fe3670a791067adb4918d4e0fdd4f5e4b6a8a32d 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 8524e925681a697bdf92ac44950f5f1ff3e68736..a53393c3255da1be04834a7e284ddcc4d17e3423 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 ad1d0b4c8ec4c07b397eb2df7b79112861ff9e43..23b0a09e3251e734ac26fc1ae4fb4202fe137198 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 1a0c4f7be1fdfa68536d66d210f53f91be04b1f8..aa301c465a0490ee41b82b788be770dafd3f6135 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 d8cb6cfdf6d2d3c439c7dd32ff4da26d554e9cae..cdeedf2cb7692b68d5f6588a9302bc94f14bf03d 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 048d612c5b138da9a79fc263a714422b3b3f9cd7..06204459d9b6e70eddeba4c3040830c53c5a7243 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 860adf39c2040fce9b97241203312b7b6e671e8e..d6d5980c882fc2998d8260ca125b2cb58dda5565 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 1f86cdd8947597f76240482c25ac89f3d3811d07..56aca2ecf86a33f08e3e798b241de6a9566ca913 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("")); }