/// <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))); } }
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)); }
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)); }
/// <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)); } }
/// <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())); } }
/// <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)); } }
/// <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(); } }
/// <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)); } }
/// <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)); } }
/// <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(); } }
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()); }
/// <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(); } }
/// <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(); } }
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)); }