/// <summary> /// Downloads the message payload referred to by the specified <see cref="PayloadReference"/>. /// </summary> /// <param name="notification">The payload reference.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task representing the asynchronous operation.</returns> protected virtual async Task <Payload> DownloadPayloadAsync(PayloadReference notification, CancellationToken cancellationToken) { Requires.NotNull(notification, "notification"); var responseMessage = await this.HttpClient.GetAsync(notification.Location, cancellationToken); var messageBuffer = await responseMessage.Content.ReadAsByteArrayAsync(); // Calculate hash of downloaded message and check that it matches the referenced message hash. var messageHash = this.CryptoServices.Hash(messageBuffer); if (!Utilities.AreEquivalent(messageHash, notification.Hash)) { throw new InvalidMessageException(); } var encryptedResult = new SymmetricEncryptionResult( notification.Key, notification.IV, messageBuffer); var plainTextBuffer = this.CryptoServices.Decrypt(encryptedResult); var plainTextStream = new MemoryStream(plainTextBuffer); var plainTextReader = new BinaryReader(plainTextStream); var message = Utilities.DeserializeDataContract <Payload>(plainTextReader); message.PayloadReferenceUri = notification.ReferenceLocation; return(message); }
/// <summary> /// Symmetrically decrypts a buffer using the specified key. /// </summary> /// <param name="data">The encrypted data and the key and IV used to encrypt it.</param> /// <returns> /// The decrypted buffer. /// </returns> public virtual byte[] Decrypt(SymmetricEncryptionResult data) { Requires.NotNull(data, "data"); var plaintext = new MemoryStream(); var ciphertext = new MemoryStream(data.Ciphertext); this.DecryptAsync(ciphertext, plaintext, data, CancellationToken.None).Wait(); return(plaintext.ToArray()); }
/// <summary> /// Downloads a <see cref="PayloadReference"/> that is referenced from an incoming inbox item. /// </summary> /// <param name="inboxItem">The inbox item that referenced the <see cref="PayloadReference"/>.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task representing the asynchronous operation.</returns> protected virtual async Task <PayloadReference> DownloadPayloadReferenceAsync(IncomingList.IncomingItem inboxItem, CancellationToken cancellationToken) { Requires.NotNull(inboxItem, "inboxItem"); var responseMessage = await this.HttpClient.GetAsync(inboxItem.Location, cancellationToken); if (responseMessage.StatusCode == HttpStatusCode.NotFound) { // delete inbox item and move on. await this.DeletePayloadReferenceAsync(inboxItem.Location, cancellationToken); this.Log("Missing payload reference.", null); return(null); } responseMessage.EnsureSuccessStatusCode(); var responseStream = await responseMessage.Content.ReadAsStreamAsync(); var responseStreamCopy = new MemoryStream(); await responseStream.CopyToAsync(responseStreamCopy, 4096, cancellationToken); responseStreamCopy.Position = 0; var encryptedKey = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken); var key = this.CryptoServices.Decrypt(this.Endpoint.EncryptionKeyPrivateMaterial, encryptedKey); var iv = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken); var ciphertext = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken); var encryptedPayload = new SymmetricEncryptionResult(key, iv, ciphertext); var plainTextPayloadBuffer = this.CryptoServices.Decrypt(encryptedPayload); var plainTextPayloadStream = new MemoryStream(plainTextPayloadBuffer); var signature = await plainTextPayloadStream.ReadSizeAndBufferAsync(cancellationToken); long payloadStartPosition = plainTextPayloadStream.Position; var signedBytes = new byte[plainTextPayloadStream.Length - plainTextPayloadStream.Position]; await plainTextPayloadStream.ReadAsync(signedBytes, 0, signedBytes.Length); plainTextPayloadStream.Position = payloadStartPosition; var plainTextPayloadReader = new BinaryReader(plainTextPayloadStream); var recipientPublicSigningKeyBuffer = plainTextPayloadReader.ReadSizeAndBuffer(); var creationDateUtc = DateTime.FromBinary(plainTextPayloadReader.ReadInt64()); var notificationAuthor = Utilities.DeserializeDataContract <Endpoint>(plainTextPayloadReader); var messageReference = Utilities.DeserializeDataContract <PayloadReference>(plainTextPayloadReader); messageReference.ReferenceLocation = inboxItem.Location; if (!this.CryptoServices.VerifySignature(notificationAuthor.SigningKeyPublicMaterial, signedBytes, signature)) { throw new InvalidMessageException(); } if (!Utilities.AreEquivalent(recipientPublicSigningKeyBuffer, this.Endpoint.PublicEndpoint.SigningKeyPublicMaterial)) { throw new InvalidMessageException(Strings.MisdirectedMessage); } return(messageReference); }
/// <summary> /// Symmetrically decrypts a buffer using the specified key. /// </summary> /// <param name="cryptoProvider">The crypto provider.</param> /// <param name="data">The encrypted data and the key and IV used to encrypt it.</param> /// <returns> /// The decrypted buffer. /// </returns> public static byte[] Decrypt(this CryptoSettings cryptoProvider, SymmetricEncryptionResult data) { var symmetricKey = CryptoSettings.SymmetricAlgorithm.CreateSymmetricKey(data.Key); return WinRTCrypto.CryptographicEngine.Decrypt(symmetricKey, data.Ciphertext, data.IV); }
/// <summary> /// Downloads the message payload referred to by the specified <see cref="PayloadReference"/>. /// </summary> /// <param name="notification">The payload reference.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task representing the asynchronous operation.</returns> protected virtual async Task<Payload> DownloadPayloadAsync(PayloadReference notification, CancellationToken cancellationToken) { Requires.NotNull(notification, "notification"); var responseMessage = await this.HttpClient.GetAsync(notification.Location, cancellationToken); var messageBuffer = await responseMessage.Content.ReadAsByteArrayAsync(); // Calculate hash of downloaded message and check that it matches the referenced message hash. var messageHash = this.CryptoServices.Hash(messageBuffer); if (!Utilities.AreEquivalent(messageHash, notification.Hash)) { throw new InvalidMessageException(); } var encryptedResult = new SymmetricEncryptionResult( notification.Key, notification.IV, messageBuffer); var plainTextBuffer = this.CryptoServices.Decrypt(encryptedResult); var plainTextStream = new MemoryStream(plainTextBuffer); var plainTextReader = new BinaryReader(plainTextStream); var message = Utilities.DeserializeDataContract<Payload>(plainTextReader); message.PayloadReferenceUri = notification.ReferenceLocation; return message; }
/// <summary> /// Downloads a <see cref="PayloadReference"/> that is referenced from an incoming inbox item. /// </summary> /// <param name="inboxItem">The inbox item that referenced the <see cref="PayloadReference"/>.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task representing the asynchronous operation.</returns> protected virtual async Task<PayloadReference> DownloadPayloadReferenceAsync(IncomingList.IncomingItem inboxItem, CancellationToken cancellationToken) { Requires.NotNull(inboxItem, "inboxItem"); var responseMessage = await this.HttpClient.GetAsync(inboxItem.Location, cancellationToken); if (responseMessage.StatusCode == HttpStatusCode.NotFound) { // delete inbox item and move on. await this.DeletePayloadReferenceAsync(inboxItem.Location, cancellationToken); this.Log("Missing payload reference.", null); return null; } responseMessage.EnsureSuccessStatusCode(); var responseStream = await responseMessage.Content.ReadAsStreamAsync(); var responseStreamCopy = new MemoryStream(); await responseStream.CopyToAsync(responseStreamCopy, 4096, cancellationToken); responseStreamCopy.Position = 0; var encryptedKey = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken); var key = this.CryptoServices.Decrypt(this.Endpoint.EncryptionKeyPrivateMaterial, encryptedKey); var iv = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken); var ciphertext = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken); var encryptedPayload = new SymmetricEncryptionResult(key, iv, ciphertext); var plainTextPayloadBuffer = this.CryptoServices.Decrypt(encryptedPayload); var plainTextPayloadStream = new MemoryStream(plainTextPayloadBuffer); var signature = await plainTextPayloadStream.ReadSizeAndBufferAsync(cancellationToken); long payloadStartPosition = plainTextPayloadStream.Position; var signedBytes = new byte[plainTextPayloadStream.Length - plainTextPayloadStream.Position]; await plainTextPayloadStream.ReadAsync(signedBytes, 0, signedBytes.Length); plainTextPayloadStream.Position = payloadStartPosition; var plainTextPayloadReader = new BinaryReader(plainTextPayloadStream); var recipientPublicSigningKeyBuffer = plainTextPayloadReader.ReadSizeAndBuffer(); var creationDateUtc = DateTime.FromBinary(plainTextPayloadReader.ReadInt64()); var notificationAuthor = Utilities.DeserializeDataContract<Endpoint>(plainTextPayloadReader); var messageReference = Utilities.DeserializeDataContract<PayloadReference>(plainTextPayloadReader); messageReference.ReferenceLocation = inboxItem.Location; if (!this.CryptoServices.VerifySignature(notificationAuthor.SigningKeyPublicMaterial, signedBytes, signature)) { throw new InvalidMessageException(); } if (!Utilities.AreEquivalent(recipientPublicSigningKeyBuffer, this.Endpoint.PublicEndpoint.SigningKeyPublicMaterial)) { throw new InvalidMessageException(Strings.MisdirectedMessage); } return messageReference; }
/// <summary> /// Symmetrically decrypts a buffer using the specified key. /// </summary> /// <param name="data">The encrypted data and the key and IV used to encrypt it.</param> /// <returns> /// The decrypted buffer. /// </returns> public abstract byte[] Decrypt(SymmetricEncryptionResult data);