Beispiel #1
0
        /// <summary>
        /// Generates a request signature using a shared <see cref="SymmetricKey" />
        /// for request arguments as well as the current time.
        /// </summary>
        /// <param name="sharedKey">The shared <see cref="SymmetricKey" />.</param>
        /// <param name="args">The request argument collection.</param>
        /// <returns>The base-64 encoded signature.</returns>
        public static string Generate(SymmetricKey sharedKey, ArgCollection args)
        {
            using (var ms = new EnhancedMemoryStream(512))
            {
                ms.WriteBytesNoLen(Crypto.GetSalt8());
                ms.WriteInt32(Magic);
                ms.WriteInt64(DateTime.UtcNow.Ticks);
                ms.WriteBytesNoLen(ComputeHash(args, null));

                return(Convert.ToBase64String(Crypto.Encrypt(ms.ToArray(), sharedKey)));
            }
        }
Beispiel #2
0
        public void EnhancedMemoryStream_ReadWriteBytesNoLen()
        {
            var es = new EnhancedMemoryStream();

            es.WriteBytesNoLen(new byte[] { 0, 1, 2, 3 });
            es.Seek(0, SeekOrigin.Begin);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3 }, es.ReadBytes(4));
        }
Beispiel #3
0
        public void EnhancedStream_ReadAllText()
        {
            const string test = "This is a test of the emergency broadcasting system.";

            var ms = new EnhancedMemoryStream();

            ms.WriteBytesNoLen(Encoding.Unicode.GetBytes(test));
            ms.Position = 0;
            Assert.AreEqual(test, ms.ReadAllText(Encoding.Unicode));
        }
Beispiel #4
0
        /// <summary>
        /// Renders the instance into a string suitable for using as an HTTP cookie.
        /// </summary>
        /// <returns>The cookie string.</returns>
        public override string ToString()
        {
            using (var ms = new EnhancedMemoryStream())
            {
                ms.WriteInt16(Magic);
                ms.WriteInt64(IssueDateUtc.Ticks);
                ms.WriteBytesNoLen(ID.ToByteArray());

                return(Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length));
            }
        }
Beispiel #5
0
        /// <summary>
        /// Encrypts authentication <see cref="Credentials" /> into a byte
        /// array using the specified public asymmetric public key and
        /// algorithm.
        /// </summary>
        /// <param name="credentials">The <see cref="Credentials" />.</param>
        /// <param name="algorithm">The encryption algorithm.</param>
        /// <param name="key">The public key.</param>
        /// <returns>The encrypted credentials.</returns>
        /// <remarks>
        /// The current implementation supports only the "RSA" provider.
        /// </remarks>
        public static byte[] EncryptCredentials(Credentials credentials, string algorithm, string key)
        {
            using (var ms = new EnhancedMemoryStream(256))
            {
                ms.WriteInt32(Crypto.CredentialMagic);
                ms.WriteString16(credentials.Realm);
                ms.WriteString16(credentials.Account);
                ms.WriteString16(credentials.Password);
                ms.WriteBytesNoLen(Crypto.GetSalt4());

                return(Encrypt(algorithm, key, ms.ToArray()));
            }
        }
Beispiel #6
0
        /// <summary>
        /// Serializes and encrypts the message into a byte array.
        /// </summary>
        /// <param name="sharedKey">The shared encryption key.</param>
        /// <returns>The serialized message.</returns>
        public byte[] ToArray(SymmetricKey sharedKey)
        {
            using (var ms = new EnhancedMemoryStream(2048))
            {
                var addressBytes = SourceAddress.GetAddressBytes();

                if (addressBytes.Length != 4)
                {
                    throw new InvalidOperationException("UdpBroadcastMessage supports only IPv4 address.");
                }

                ms.WriteInt32Le(Magic);
                ms.WriteInt64Le(TimeStampUtc.Ticks);
                ms.WriteBytesNoLen(SourceAddress.GetAddressBytes());
                ms.WriteByte((byte)MessageType);
                ms.WriteByte((byte)BroadcastGroup);
                ms.WriteBytes16(Payload);
                ms.WriteBytesNoLen(Crypto.GetSalt4());

                return(Crypto.Encrypt(ms.ToArray(), sharedKey));
            }
        }
Beispiel #7
0
        /// <summary>
        /// Decrypts data encrypted using <see cref="Encrypt(SymmetricKey,byte[],int)" />.
        /// </summary>
        /// <param name="symmetricKey">The symmetric algorithm arguments.</param>
        /// <param name="cipherText">The encrypted data.</param>
        /// <returns>The decrypted result.</returns>
        public static byte[] Decrypt(SymmetricKey symmetricKey, byte[] cipherText)
        {
            EnhancedMemoryStream input     = new EnhancedMemoryStream(cipherText);
            EnhancedMemoryStream ms        = new EnhancedMemoryStream(cipherText.Length);
            BlockDecryptor       decryptor = null;

            try
            {
                // Read the header fields

                if (input.ReadInt32() != Magic)
                {
                    throw new CryptographicException(BadFormatMsg);
                }

                if (input.ReadInt32() != 0)
                {
                    throw new CryptographicException("Unsupported secure data format version.");
                }

                decryptor = new BlockDecryptor(symmetricKey);

                // Decrypt the contents

                ms.WriteBytesNoLen(decryptor.Decrypt(input.ReadBytes32()));
                ms.Position = 0;

                if (ms.ReadInt32() != Magic)
                {
                    throw new CryptographicException("Secure data content is corrupt.");
                }

                ms.Position += 8;   // Skip over the salt

                return(ms.ReadBytes32());
            }
            finally
            {
                if (decryptor != null)
                {
                    decryptor.Dispose();
                }

                input.Close();
                ms.Close();
            }
        }
Beispiel #8
0
        /// <summary>
        /// Encrypts the keys using the symmetric key passed.
        /// </summary>
        /// <returns>The encrypted key chain.</returns>
        public byte[] Encrypt(SymmetricKey key)
        {
            using (var ms = new EnhancedMemoryStream())
            {
                ms.WriteInt32(Magic);
                ms.WriteInt32(keys.Count);

                foreach (string privateKey in keys.Values)
                {
                    ms.WriteString16(privateKey);
                }

                ms.WriteBytesNoLen(Crypto.GetSalt8());

                return(Crypto.Encrypt(ms.ToArray(), key));
            }
        }
Beispiel #9
0
        /// <summary>
        /// Serializes and encrypts the message into a byte array.
        /// </summary>
        /// <param name="sharedKey">The shared encryption key.</param>
        /// <returns>The serialized message.</returns>
        public byte[] ToArray(SymmetricKey sharedKey)
        {
            if (this.HostEntry == null)
            {
                throw new InvalidOperationException("HostEntry property cannot be null.");
            }

            using (var ms = new EnhancedMemoryStream(2048))
            {
                ms.WriteInt32Le(Magic);
                ms.WriteByte((byte)FormatVer);
                ms.WriteInt64Le(TimeStampUtc.Ticks);
                ms.WriteInt32Le((int)Flags);
                ms.WriteString16(this.HostEntry.ToString());
                ms.WriteBytesNoLen(Crypto.GetSalt4());

                return(Crypto.Encrypt(ms.ToArray(), sharedKey));
            }
        }
Beispiel #10
0
        /// <summary>
        /// Performs a secure symmetric encryption including cryptographic salt, padding, and
        /// data validation.
        /// </summary>
        /// <param name="symmetricKey">The symmetric algorithm arguments.</param>
        /// <param name="plainText">The unencrypted data.</param>
        /// <param name="paddedSize">Specifies the minimum padded size of the encrypted content.</param>
        /// <returns>The encrypted result.</returns>
        public static byte[] Encrypt(SymmetricKey symmetricKey, byte[] plainText, int paddedSize)
        {
            EnhancedMemoryStream output    = new EnhancedMemoryStream(Math.Max(plainText.Length, paddedSize) + 512);
            EnhancedMemoryStream ms        = new EnhancedMemoryStream(512);
            BlockEncryptor       encryptor = new BlockEncryptor(symmetricKey);

            try
            {
                // Write header fields

                output.WriteInt32(Magic);
                output.WriteInt32(0);

                // Write encrypted contents

                ms.WriteInt32(Magic);
                ms.WriteBytesNoLen(Crypto.GetSalt8());
                ms.WriteBytes32(plainText);

                for (int i = plainText.Length; i < paddedSize; i++)
                {
                    ms.WriteByte((byte)i);     // Padding bytes
                }
                output.WriteBytes32(encryptor.Encrypt(ms.ToArray()));

                // That's it, we're done.

                return(output.ToArray());
            }
            finally
            {
                if (encryptor != null)
                {
                    encryptor.Dispose();
                }

                output.Close();
                ms.Close();
            }
        }
Beispiel #11
0
        public void HttpRequest_Content_ChunkedTransfer()
        {
            HttpRequest          r;
            EnhancedMemoryStream ms;

            byte[] bufOut;
            byte[] buf;

            bufOut = new byte[300];
            for (int i = 0; i < bufOut.Length; i++)
            {
                bufOut[i] = (byte)i;
            }

            // Test parsing where the entire request is in a single input block.

            ms = new EnhancedMemoryStream();
            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("GET /foo.htm HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"));

            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("12c; extra crap\r\n"));     // 12c = 300 as hex
            ms.WriteBytesNoLen(bufOut);
            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("\r\n"));

            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("0; extra crap\r\n\r\n"));

            buf = ms.ToArray();
            r   = new HttpRequest();
            r.BeginParse(80);
            Assert.IsTrue(r.Parse(buf, buf.Length));
            r.EndParse();

            Assert.AreEqual(bufOut.Length, r.Content.Size);
            CollectionAssert.AreEqual(bufOut, r.Content.ToByteArray());

            // Test parsing of two chunks in a single input block.

            ms = new EnhancedMemoryStream();
            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("GET /foo.htm HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"));

            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("FF\r\n"));     // FF = 255 as hex
            ms.Write(bufOut, 0, 255);
            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("\r\n"));

            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("2D\r\n"));     // 2D = 45 as hex (300 - 255)
            ms.Write(bufOut, 255, 45);
            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("\r\n"));

            ms.WriteBytesNoLen(Encoding.ASCII.GetBytes("0\r\n\r\n"));

            buf = ms.ToArray();
            r   = new HttpRequest();
            r.BeginParse(80);
            Assert.IsTrue(r.Parse(buf, buf.Length));
            r.EndParse();

            Assert.AreEqual(bufOut.Length, r.Content.Size);
            CollectionAssert.AreEqual(bufOut, r.Content.ToByteArray());

            // Repeat the 2 chunk test but this time break the input into blocks of
            // only a single byte each.  This will torture test the parsing state machines.

            buf = ms.ToArray();
            r   = new HttpRequest();
            r.BeginParse(80);

            for (int i = 0; i < buf.Length - 1; i++)
            {
                Assert.IsFalse(r.Parse(new byte[] { buf[i] }, 1));
            }

            Assert.IsTrue(r.Parse(new byte[] { buf[buf.Length - 1] }, 1));

            r.EndParse();

            Assert.AreEqual(bufOut.Length, r.Content.Size);
            CollectionAssert.AreEqual(bufOut, r.Content.ToByteArray());
        }
Beispiel #12
0
        /// <summary>
        /// Decrypts a byte array encrypted using <see cref="Encrypt(string ,byte[],string,int,int,out SymmetricKey)" />.
        /// </summary>
        /// <param name="rsaKey">The decrypting RSA key as XML or as a secure key container name.</param>
        /// <param name="cipherText">The encrypted data.</param>
        /// <param name="symmetricKey">Returns as the symmetric encryption algorithm arguments.</param>
        /// <returns>The decrypted data.</returns>
        /// <exception cref="CryptographicException">Thrown is the encrypted data block is incorrectly formatted.</exception>
        /// <remarks>
        /// Note that applications should take some care to ensure that the <paramref name="symmetricKey" />
        /// value return is disposed so that the symmetric encryption key will be cleared.
        /// </remarks>
        public static byte[] Decrypt(string rsaKey, byte[] cipherText, out SymmetricKey symmetricKey)
        {
            EnhancedMemoryStream input     = new EnhancedMemoryStream(cipherText);
            EnhancedMemoryStream ms        = new EnhancedMemoryStream(cipherText.Length);
            BlockDecryptor       decryptor = null;

            byte[] symKey;
            byte[] symIV;
            string algorithm;

            try
            {
                // Read the header fields

                if (input.ReadInt32() != Magic)
                {
                    throw new CryptographicException(BadFormatMsg);
                }

                if (input.ReadInt32() != 0)
                {
                    throw new CryptographicException("Unsupported secure data format version.");
                }

                // Decrypt the encryption info

                ms.WriteBytesNoLen(AsymmetricCrypto.Decrypt(CryptoAlgorithm.RSA, rsaKey, input.ReadBytes16()));
                ms.Position = 0;

                algorithm    = ms.ReadString16();
                symKey       = ms.ReadBytes16();
                symIV        = ms.ReadBytes16();
                symmetricKey = new SymmetricKey(algorithm, symKey, symIV);
                decryptor    = new BlockDecryptor(algorithm, symKey, symIV);

                // Decrypt the contents

                ms.SetLength(0);
                ms.WriteBytesNoLen(decryptor.Decrypt(input.ReadBytes32()));
                ms.Position = 0;

                if (ms.ReadInt32() != Magic)
                {
                    throw new CryptographicException("Secure data content is corrupt.");
                }

                ms.Position += 8;   // Skip over the salt

                return(ms.ReadBytes32());
            }
            finally
            {
                if (decryptor != null)
                {
                    decryptor.Dispose();
                }

                input.Close();
                ms.Close();
            }
        }
Beispiel #13
0
        /// <summary>
        /// Encrypts a byte array using a combination of an asymmetric RSA key and the
        /// specified symmetric encryption algorithm and a one-time key generated by
        /// the method.
        /// </summary>
        /// <param name="rsaKey">The encrypting RSA key as XML or as a secure key container name.</param>
        /// <param name="plainText">The data to be encrypted.</param>
        /// <param name="algorithm">The symmetric encryption algorithm name.</param>
        /// <param name="keySize">The one-time symmetric key size to generate in bits.</param>
        /// <param name="paddedSize">Specifies the minimum padded size of the encrypted content.</param>
        /// <param name="symmetricKey">Returns as the symmetric encryption algorithm arguments.</param>
        /// <returns>The encrypted result.</returns>
        /// <remarks>
        /// <para>
        /// Note that applications should take some care to ensure that the <paramref name="symmetricKey" />
        /// value return is disposed so that the symmetric encryption key will be cleared.
        /// </para>
        /// <para>
        /// The current supported cross platform encryption algorithms
        /// are: "DES", "RC2", "TripleDES", and "AES" (Rijndael).
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentException">Thrown if the requested encryption algorithm is unknown.</exception>
        public static byte[] Encrypt(string rsaKey, byte[] plainText, string algorithm, int keySize, int paddedSize,
                                     out SymmetricKey symmetricKey)
        {
            EnhancedMemoryStream output    = new EnhancedMemoryStream(Math.Max(plainText.Length, paddedSize) + 512);
            EnhancedMemoryStream ms        = new EnhancedMemoryStream(512);
            BlockEncryptor       encryptor = null;

            byte[] symKey;
            byte[] symIV;

            Crypto.GenerateSymmetricKey(algorithm, keySize, out symKey, out symIV);

            encryptor    = new BlockEncryptor(algorithm, symKey, symIV);
            symmetricKey = new SymmetricKey(algorithm, (byte[])symKey.Clone(), (byte[])symIV.Clone());

            try
            {
                // Write header fields

                output.WriteInt32(Magic);
                output.WriteInt32(0);

                // Write encryption Info

                ms.WriteString16(algorithm);
                ms.WriteBytes16(symKey);
                ms.WriteBytes16(symIV);
                ms.WriteBytesNoLen(Crypto.GetSalt8());
                output.WriteBytes16(AsymmetricCrypto.Encrypt(CryptoAlgorithm.RSA, rsaKey, ms.ToArray()));

                // Write encrypted contents

                ms.SetLength(0);
                ms.WriteInt32(Magic);
                ms.WriteBytesNoLen(Crypto.GetSalt8());
                ms.WriteBytes32(plainText);

                for (int i = plainText.Length; i < paddedSize; i++)
                {
                    ms.WriteByte((byte)i);     // Padding bytes
                }
                output.WriteBytes32(encryptor.Encrypt(ms.ToArray()));

                // That's it, we're done.

                return(output.ToArray());
            }
            finally
            {
                if (symKey != null)
                {
                    Array.Clear(symKey, 0, symKey.Length);
                }

                if (symIV != null)
                {
                    Array.Clear(symIV, 0, symIV.Length);
                }

                if (encryptor != null)
                {
                    encryptor.Dispose();
                }

                output.Close();
                ms.Close();
            }
        }
Beispiel #14
0
        public void MailHelper_MessageSerializeAdvanced()
        {
            MailMessage          message;
            EnhancedMemoryStream stream;
            Attachment           attachment;
            EnhancedMemoryStream dataStream;

            // Write

            message                 = new MailMessage("*****@*****.**", "*****@*****.**");
            message.Priority        = MailPriority.High;
            message.From            = new MailAddress("*****@*****.**");
            message.Sender          = new MailAddress("*****@*****.**");
            message.Subject         = "Test Message";
            message.SubjectEncoding = Encoding.UTF8;
            message.IsBodyHtml      = true;
            message.Body            = "<html><body>Test</body></html>";
            message.BodyEncoding    = Encoding.Unicode;

            message.ReplyToList.Add(new MailAddress("*****@*****.**"));

            message.To.Add(new MailAddress("*****@*****.**"));

            message.CC.Add(new MailAddress("*****@*****.**"));
            message.CC.Add(new MailAddress("*****@*****.**"));

            message.Bcc.Add(new MailAddress("*****@*****.**"));
            message.Bcc.Add(new MailAddress("*****@*****.**"));

            dataStream = new EnhancedMemoryStream();
            dataStream.WriteBytesNoLen(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
            dataStream.Position = 0;

            attachment = new Attachment(dataStream, "application/octet-stream");
            attachment.ContentDisposition.FileName = "test.dat";
            message.Attachments.Add(attachment);

            stream = new EnhancedMemoryStream();
            MailHelper.WriteMessage(stream, message);

            // Read

            stream.Position = 0;
            message         = MailHelper.ReadMessage(stream);

            Assert.AreEqual(MailPriority.High, message.Priority);
            Assert.AreEqual("*****@*****.**", message.From.ToString());
            Assert.AreEqual("*****@*****.**", message.Sender.ToString());

            Assert.AreEqual(1, message.ReplyToList.Count);
            Assert.AreEqual("*****@*****.**", message.ReplyToList[0].ToString());

            Assert.AreEqual(2, message.To.Count);
            Assert.AreEqual("*****@*****.**", message.To[0].ToString());
            Assert.AreEqual("*****@*****.**", message.To[1].ToString());

            Assert.AreEqual(2, message.CC.Count);
            Assert.AreEqual("*****@*****.**", message.CC[0].ToString());
            Assert.AreEqual("*****@*****.**", message.CC[1].ToString());

            Assert.AreEqual(2, message.Bcc.Count);
            Assert.AreEqual("*****@*****.**", message.Bcc[0].ToString());
            Assert.AreEqual("*****@*****.**", message.Bcc[1].ToString());

            Assert.AreEqual("Test Message", message.Subject);
            Assert.AreEqual(Encoding.UTF8.WebName, message.SubjectEncoding.WebName);

            Assert.IsTrue(message.IsBodyHtml);
            Assert.AreEqual("<html><body>Test</body></html>", message.Body);
            Assert.AreEqual(Encoding.Unicode.WebName, message.BodyEncoding.WebName);

            Assert.AreEqual(1, message.Attachments.Count);

            attachment = message.Attachments[0];
            Assert.AreEqual("application/octet-stream", attachment.ContentType.MediaType);
            Assert.AreEqual("test.dat", attachment.ContentDisposition.FileName);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, new EnhancedStream(attachment.ContentStream).ReadBytes(10));
        }