Example #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="encryptedPayload"></param>
        /// <param name="cryptoKey">EncryptionResult.PublicKey (server public key) "dh=BNSSQjo..."</param>
        /// <param name="contentEncoding">aesgcm</param>
        /// <param name="encryption">EncryptionResult.Salt? "salt=WASwg7..."</param>
        /// <param name="p256dh">Client-generated</param>
        /// <param name="authKey">Client-generated</param>
        /// <returns></returns>
        public static string Decrypt(string encryptedPayload, string cryptoKey, string contentEncoding, string encryption, byte[] userPrivateKey, byte[] userPublicKey, string authKey)
        {
            // Trim the null terminator
            if (encryptedPayload.EndsWith("\0"))
            {
                encryptedPayload = encryptedPayload.Substring(0, encryptedPayload.Length - 1);
            }

            byte[] encryptedBytes;

            // WNS either gives us Base64 or UTF16, try both
            try
            {
                encryptedBytes = Convert.FromBase64String(encryptedPayload);
            }
            catch
            {
                encryptedBytes = Encoding.Unicode.GetBytes(encryptedPayload);
            }


            string serverPublicKey = cryptoKey.Substring("dh=".Length);

            // Note that using UrlBase64.Decode fails later on, but our WebEncoder seems to decode it so that it works later on
            byte[] serverPublicKeyBytes = WebEncoder.Base64UrlDecode(serverPublicKey);

            string saltStr = encryption.Substring("salt=".Length);

            return(Decrypt(encryptedBytes, serverPublicKeyBytes, contentEncoding, WebEncoder.Base64UrlDecode(saltStr), userPrivateKey, userPublicKey, WebEncoder.Base64UrlDecode(authKey)));
        }
Example #2
0
        private static async Task <string> GetDecryptedContentHelperAsync(RawNotification notification)
        {
            if (notification.Headers == null)
            {
                // It's not encrypted
                return(notification.Content);
            }

            string encryptedPayload = notification.Content;                     // r/JwZaorThJfqkpZjV6umbDXQy9G
            string cryptoKey        = notification.Headers["Crypto-Key"];       // dh=BNSSQjo...
            string contentEncoding  = notification.Headers["Content-Encoding"]; // aesgcm
            string encryption       = notification.Headers["Encryption"];       // salt=WASwg7...

            var storage = await PushSubscriptionStorage.GetAsync();

            StoredPushSubscription[] storedSubscriptions = storage.GetSubscriptions(notification.ChannelId);

            foreach (var sub in storedSubscriptions)
            {
                try
                {
                    byte[] userPrivateKey = WebEncoder.Base64UrlDecode(sub.P265Private);
                    byte[] userPublicKey  = WebEncoder.Base64UrlDecode(sub.Keys.P256DH);

                    string decrypted = Decryptor.Decrypt(encryptedPayload, cryptoKey, contentEncoding, encryption, userPrivateKey, userPublicKey, sub.Keys.Auth);

                    // Make sure we've deleted any old channels now that we successfully received with this one
                    await storage.DeleteSubscriptionsOlderThanAsync(notification.ChannelId, sub);

                    return(decrypted);
                }
                catch
                {
                }
            }

            throw new Exception("Failed to decrypt");
        }