/// <summary>
        /// Retrieves a <see cref="SignalServiceStickerManifest"/>.
        /// </summary>
        /// <param name="packId">The 16-byte packId that identifies the sticker pack.</param>
        /// <param name="packKey">The 32-byte packKey that decrypts the sticker pack.</param>
        /// <param name="token">Cancellation token, may be null.</param>
        /// <returns>The <see cref="SignalServiceStickerManifest"/> representing the sticker pack.</returns>
        /// <exception cref="IOException"></exception>
        /// <exception cref="InvalidMessageException"></exception>
        public async Task <SignalServiceStickerManifest> RetrieveStickerManifestAsync(byte[] packId, byte[] packKey, CancellationToken?token = null)
        {
            if (token == null)
            {
                token = CancellationToken.None;
            }

            byte[] manifestBytes = await socket.RetrieveStickerManifestAsync(packId, token);

            Stream       cipherStream = AttachmentCipherInputStream.CreateForStickerData(manifestBytes, packKey);
            MemoryStream outputStream = new MemoryStream();

            Util.Copy(cipherStream, outputStream);

            sticker.Pack pack = sticker.Pack.Parser.ParseFrom(outputStream.ToArray());
            List <SignalServiceStickerManifest.StickerInfo> stickers = new List <SignalServiceStickerManifest.StickerInfo>(pack.Stickers.Count);

            SignalServiceStickerManifest.StickerInfo?cover = pack.Cover != null ? new SignalServiceStickerManifest.StickerInfo((int)pack.Cover.Id, pack.Cover.Emoji) : null;

            foreach (sticker.Pack.Types.Sticker sticker in pack.Stickers)
            {
                stickers.Add(new SignalServiceStickerManifest.StickerInfo((int)sticker.Id, sticker.Emoji));
            }

            return(new SignalServiceStickerManifest(pack.Title, pack.Author, cover, stickers));
        }
        public void Test_Sticker_EncryptDecryptEmpty()
        {
            byte[]        packKey        = Util.GetSecretBytes(32);
            byte[]        plaintextInput = Encoding.UTF8.GetBytes(string.Empty);
            EncryptResult encryptResult  = EncryptData(plaintextInput, ExpandPackKey(packKey));

            using Stream inputStream = AttachmentCipherInputStream.CreateForStickerData(encryptResult.ciphertext, packKey);
            byte[] plaintextOutput = ReadInputStreamFully(inputStream);

            CollectionAssert.AreEqual(plaintextInput, plaintextOutput);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="packId"></param>
        /// <param name="packKey"></param>
        /// <param name="stickerId"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        /// <exception cref="IOException"></exception>
        /// <exception cref="InvalidMessageException"></exception>
        public async Task <Stream> RetrieveStickerAsync(byte[] packId, byte[] packKey, int stickerId, CancellationToken?token = null)
        {
            if (token == null)
            {
                token = CancellationToken.None;
            }

            byte[] data = await socket.RetrieveStickerAsync(packId, stickerId, token);

            return(AttachmentCipherInputStream.CreateForStickerData(data, packKey));
        }
        public void Test_Sticker_DecryptFailOnBadKey()
        {
            bool hitCorrectException = false;

            try
            {
                byte[]        packKey        = Util.GetSecretBytes(32);
                byte[]        plaintextInput = Encoding.UTF8.GetBytes("Gwen Stacy");
                EncryptResult encryptResult  = EncryptData(plaintextInput, ExpandPackKey(packKey));
                byte[]        badPackKey     = new byte[32];

                AttachmentCipherInputStream.CreateForStickerData(encryptResult.ciphertext, badPackKey);
            }
            catch (InvalidMessageException)
            {
                hitCorrectException = true;
            }

            Assert.IsTrue(hitCorrectException);
        }
        public void Test_Sticker_DecryptFailOnBadMac()
        {
            bool hitCorrectException = false;

            try
            {
                byte[]        packKey          = Util.GetSecretBytes(32);
                byte[]        plaintextInput   = Encoding.UTF8.GetBytes("Uncle Ben");
                EncryptResult encryptResult    = EncryptData(plaintextInput, ExpandPackKey(packKey));
                byte[]        badMacCiphertext = new byte[encryptResult.ciphertext.Length];
                Array.Copy(encryptResult.ciphertext, badMacCiphertext, badMacCiphertext.Length);

                badMacCiphertext[badMacCiphertext.Length - 1] = 0;

                AttachmentCipherInputStream.CreateForStickerData(badMacCiphertext, packKey);
            }
            catch (InvalidMessageException)
            {
                hitCorrectException = true;
            }

            Assert.IsTrue(hitCorrectException);
        }