Exemplo n.º 1
0
        /// <summary>
        /// Shares the reference to a message payload with the specified recipient.
        /// </summary>
        /// <param name="messageReference">The payload reference to share.</param>
        /// <param name="recipient">The recipient that should be notified of the message.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The task representing the asynchronous operation.</returns>
        protected virtual async Task <NotificationPostedReceipt> PostPayloadReferenceAsync(PayloadReference messageReference, Endpoint recipient, CancellationToken cancellationToken)
        {
            Requires.NotNull(recipient, "recipient");
            Requires.NotNull(messageReference, "messageReference");

            cancellationToken.ThrowIfCancellationRequested();

            // Prepare the payload.
            var plainTextPayloadStream = new MemoryStream();
            var plainTextPayloadWriter = new BinaryWriter(plainTextPayloadStream);

            // Include the intended recipient's signing certificate so the recipient knows that
            // the message author intended the recipient to receive it (defeats fowarding and re-encrypting
            // a message notification with the intent to deceive a victim that a message was intended for them when it was not.)
            plainTextPayloadWriter.WriteSizeAndBuffer(recipient.SigningKeyPublicMaterial);

            plainTextPayloadWriter.Write(DateTime.UtcNow.ToBinary());

            // Write out the author of this notification (which may be different from the author of the
            // message itself in the case of a "forward").
            plainTextPayloadWriter.SerializeDataContract(this.Endpoint.PublicEndpoint);

            plainTextPayloadWriter.SerializeDataContract(messageReference);
            plainTextPayloadWriter.Flush();
            this.Log("Message invite plaintext", plainTextPayloadStream.ToArray());

            byte[] notificationSignature        = WinRTCrypto.CryptographicEngine.Sign(this.Endpoint.SigningKey, plainTextPayloadStream.ToArray());
            var    signedPlainTextPayloadStream = new MemoryStream((int)plainTextPayloadStream.Length + notificationSignature.Length + 4);
            ////await signedPlainTextPayloadStream.WriteSizeAndBufferAsync(Encoding.UTF8.GetBytes(this.CryptoServices.HashAlgorithmName), cancellationToken);
            await signedPlainTextPayloadStream.WriteSizeAndBufferAsync(notificationSignature, cancellationToken).ConfigureAwait(false);

            plainTextPayloadStream.Position = 0;
            await plainTextPayloadStream.CopyToAsync(signedPlainTextPayloadStream, 4096, cancellationToken).ConfigureAwait(false);

            signedPlainTextPayloadStream.Position = 0;
            var cipherTextStream   = new MemoryStream();
            var encryptedVariables = await this.CryptoServices.EncryptAsync(signedPlainTextPayloadStream, cipherTextStream, cancellationToken : cancellationToken).ConfigureAwait(false);

            this.Log("Message invite ciphertext", cipherTextStream.ToArray());
            this.Log("Message invite key", encryptedVariables.Key);
            this.Log("Message invite IV", encryptedVariables.IV);

            var builder           = new UriBuilder(recipient.MessageReceivingEndpoint);
            var lifetimeInMinutes = (int)(messageReference.ExpiresUtc - DateTime.UtcNow).TotalMinutes;

            builder.Query += "&lifetime=" + lifetimeInMinutes.ToString(CultureInfo.InvariantCulture);

            var postContent   = new MemoryStream();
            var encryptionKey = CryptoSettings.EncryptionAlgorithm.ImportPublicKey(
                recipient.EncryptionKeyPublicMaterial,
                CryptoSettings.PublicKeyFormat);
            var encryptedKey = WinRTCrypto.CryptographicEngine.Encrypt(encryptionKey, encryptedVariables.Key);

            this.Log("Message invite encrypted key", encryptedKey);
            await postContent.WriteSizeAndBufferAsync(encryptedKey, cancellationToken).ConfigureAwait(false);

            await postContent.WriteSizeAndBufferAsync(encryptedVariables.IV, cancellationToken).ConfigureAwait(false);

            cipherTextStream.Position = 0;
            await postContent.WriteSizeAndStreamAsync(cipherTextStream, cancellationToken).ConfigureAwait(false);

            await postContent.FlushAsync().ConfigureAwait(false);

            postContent.Position = 0;

            using (var response = await this.HttpClient.PostAsync(builder.Uri, new StreamContent(postContent), cancellationToken).ConfigureAwait(false))
            {
                if (response.Content != null)
                {
                    // Just to help in debugging.
                    string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                }

                response.EnsureSuccessStatusCode();
                var receipt = new NotificationPostedReceipt(recipient, response.Headers.Date);
                return(receipt);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Shares the reference to a message payload with the specified recipient.
        /// </summary>
        /// <param name="messageReference">The payload reference to share.</param>
        /// <param name="recipient">The recipient that should be notified of the message.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The task representing the asynchronous operation.</returns>
        protected virtual async Task<NotificationPostedReceipt> PostPayloadReferenceAsync(PayloadReference messageReference, Endpoint recipient, CancellationToken cancellationToken)
        {
            Requires.NotNull(recipient, "recipient");
            Requires.NotNull(messageReference, "messageReference");

            cancellationToken.ThrowIfCancellationRequested();

            // Prepare the payload.
            var plainTextPayloadStream = new MemoryStream();
            var plainTextPayloadWriter = new BinaryWriter(plainTextPayloadStream);

            // Include the intended recipient's signing certificate so the recipient knows that
            // the message author intended the recipient to receive it (defeats fowarding and re-encrypting
            // a message notification with the intent to deceive a victim that a message was intended for them when it was not.)
            plainTextPayloadWriter.WriteSizeAndBuffer(recipient.SigningKeyPublicMaterial);

            plainTextPayloadWriter.Write(DateTime.UtcNow.ToBinary());

            // Write out the author of this notification (which may be different from the author of the
            // message itself in the case of a "forward").
            plainTextPayloadWriter.SerializeDataContract(this.Endpoint.PublicEndpoint);

            plainTextPayloadWriter.SerializeDataContract(messageReference);
            plainTextPayloadWriter.Flush();
            this.Log("Message invite plaintext", plainTextPayloadStream.ToArray());

            byte[] notificationSignature = WinRTCrypto.CryptographicEngine.Sign(this.Endpoint.SigningKey, plainTextPayloadStream.ToArray());
            var signedPlainTextPayloadStream = new MemoryStream((int)plainTextPayloadStream.Length + notificationSignature.Length + 4);
            ////await signedPlainTextPayloadStream.WriteSizeAndBufferAsync(Encoding.UTF8.GetBytes(this.CryptoServices.HashAlgorithmName), cancellationToken);
            await signedPlainTextPayloadStream.WriteSizeAndBufferAsync(notificationSignature, cancellationToken).ConfigureAwait(false);
            plainTextPayloadStream.Position = 0;
            await plainTextPayloadStream.CopyToAsync(signedPlainTextPayloadStream, 4096, cancellationToken).ConfigureAwait(false);
            signedPlainTextPayloadStream.Position = 0;
            var cipherTextStream = new MemoryStream();
            var encryptedVariables = await this.CryptoServices.EncryptAsync(signedPlainTextPayloadStream, cipherTextStream, cancellationToken: cancellationToken).ConfigureAwait(false);
            this.Log("Message invite ciphertext", cipherTextStream.ToArray());
            this.Log("Message invite key", encryptedVariables.Key);
            this.Log("Message invite IV", encryptedVariables.IV);

            var builder = new UriBuilder(recipient.MessageReceivingEndpoint);
            var lifetimeInMinutes = (int)(messageReference.ExpiresUtc - DateTime.UtcNow).TotalMinutes;
            builder.Query += "&lifetime=" + lifetimeInMinutes.ToString(CultureInfo.InvariantCulture);

            var postContent = new MemoryStream();
            var encryptionKey = CryptoSettings.EncryptionAlgorithm.ImportPublicKey(
                recipient.EncryptionKeyPublicMaterial,
                CryptoSettings.PublicKeyFormat);
            var encryptedKey = WinRTCrypto.CryptographicEngine.Encrypt(encryptionKey, encryptedVariables.Key);
            this.Log("Message invite encrypted key", encryptedKey);
            await postContent.WriteSizeAndBufferAsync(encryptedKey, cancellationToken).ConfigureAwait(false);
            await postContent.WriteSizeAndBufferAsync(encryptedVariables.IV, cancellationToken).ConfigureAwait(false);
            cipherTextStream.Position = 0;
            await postContent.WriteSizeAndStreamAsync(cipherTextStream, cancellationToken).ConfigureAwait(false);
            await postContent.FlushAsync().ConfigureAwait(false);
            postContent.Position = 0;

            using (var response = await this.HttpClient.PostAsync(builder.Uri, new StreamContent(postContent), cancellationToken).ConfigureAwait(false))
            {
                if (response.Content != null)
                {
                    // Just to help in debugging.
                    string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                }

                response.EnsureSuccessStatusCode();
                var receipt = new NotificationPostedReceipt(recipient, response.Headers.Date);
                return receipt;
            }
        }