Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
        /// <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).ConfigureAwait(false);

            if (responseMessage.StatusCode == HttpStatusCode.NotFound)
            {
                // delete inbox item and move on.
                await this.DeletePayloadReferenceAsync(inboxItem.Location, cancellationToken).ConfigureAwait(false);

                this.Log("Missing payload reference.", null);
                return(null);
            }

            responseMessage.EnsureSuccessStatusCode();
            var responseStream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false);

            var responseStreamCopy = new MemoryStream();
            await responseStream.CopyToAsync(responseStreamCopy, 4096, cancellationToken).ConfigureAwait(false);

            responseStreamCopy.Position = 0;

            var encryptedKey = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken).ConfigureAwait(false);

            var key = WinRTCrypto.CryptographicEngine.Decrypt(this.Endpoint.EncryptionKey, encryptedKey);
            var iv  = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken).ConfigureAwait(false);

            var ciphertextStream = await responseStreamCopy.ReadSizeAndStreamAsync(cancellationToken).ConfigureAwait(false);

            var encryptedVariables = new SymmetricEncryptionVariables(key, iv);

            var plainTextPayloadStream = new MemoryStream();

            await this.CryptoServices.DecryptAsync(ciphertextStream, plainTextPayloadStream, encryptedVariables, cancellationToken).ConfigureAwait(false);

            plainTextPayloadStream.Position = 0;
            AsymmetricAlgorithm?signingHashAlgorithm = null;    //// Encoding.UTF8.GetString(await plainTextPayloadStream.ReadSizeAndBufferAsync(cancellationToken));

            byte[] signature = await plainTextPayloadStream.ReadSizeAndBufferAsync(cancellationToken).ConfigureAwait(false);

            long payloadStartPosition = plainTextPayloadStream.Position;
            var  signedBytes          = new byte[plainTextPayloadStream.Length - plainTextPayloadStream.Position];
            await plainTextPayloadStream.ReadAsync(signedBytes, 0, signedBytes.Length).ConfigureAwait(false);

            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 (messageReference.HashAlgorithmName == null)
            {
                messageReference.HashAlgorithmName = Utilities.GuessHashAlgorithmFromLength(messageReference.Hash.Length).GetHashAlgorithmName();
            }

            if (!CryptoProviderExtensions.VerifySignatureWithTolerantHashAlgorithm(notificationAuthor.SigningKeyPublicMaterial, signedBytes, signature, signingHashAlgorithm))
            {
                throw new InvalidMessageException();
            }

            if (!Utilities.AreEquivalent(recipientPublicSigningKeyBuffer, this.Endpoint.PublicEndpoint.SigningKeyPublicMaterial))
            {
                throw new InvalidMessageException(Strings.MisdirectedMessage);
            }

            return(messageReference);
        }