Hi everybody. I need advice. I zip and crypt SOAP message on web service and client side.
Client is winforms app.
If I only crypt SOAP message, it works good.
If I only zip SOAP message it also works good.
I use SOAP extension on crypt and zip SOAP.
I use AES - Advanced Encryption Standard - Rijndael and on compresion I use SharpZipLib from http://sourceforge.net/projects/sharpdevelop/.
The problem is I send dataset on client.
Firstly I zip and secondly encrypt SOAP on web service side.
Send on client.
On client side I load XML from stream. But it finish with this error : Data at the root level is invalid. Line 1, position 2234.
Here is the code, where I load XML from stream:
var doc = new XmlDocument();
using (var reader = new XmlTextReader(inputStream))
{
doc.Load(reader);
}
Any advice ? Thank you...
Here are methods on web service side which zip and crypt SOAP :
//encrypt string
private static string EncryptString(string @string, string initialVector, string salt, string password,
string hashAlgorithm, int keySize, int passwordIterations)
{
byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(@string);
var derivedPassword = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm, passwordIterations);
byte[] keyBytes = derivedPassword.GetBytes(keySize / 8);
var symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initialVectorBytes);
using (var memStream = new MemoryStream())
{
var cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
var serializer = new XmlSerializer(typeof(byte[]));
var sb = new StringBuilder();
TextWriter writer = new StringWriter(sb);
serializer.Serialize(writer, memStream.ToArray());
writer.Flush();
var doc = new XmlDocument();
doc.LoadXml(sb.ToString());
if (doc.DocumentElement != null) return doc.DocumentElement.InnerXml;
}
return "";
}
//zip string
private static byte[] ZipArray(string stringToZip)
{
byte[] inputByteArray = Encoding.UTF8.GetBytes(stringToZip);
var ms = new MemoryStream();
// SharpZipLib.Zip,
var zipOut = new ZipOutputStream(ms);
var zipEntry = new ZipEntry("ZippedFile");
zipOut.PutNextEntry(zipEntry);
zipOut.SetLevel(7);
zipOut.Write(inputByteArray, 0, inputByteArray.Length);
zipOut.Finish();
zipOut.Close();
return ms.ToArray();
}
//zip and encrypt SOAP
public virtual Stream OutSoap(string[] soapElement, Stream inputStream)
{
#region Load XML from SOAP
var doc = new XmlDocument();
using (XmlReader reader = XmlReader.Create(inputStream))
{
doc.Load(reader);
}
var nsMan = new XmlNamespaceManager(doc.NameTable);
nsMan.AddNamespace("soap",
"http://schemas.xmlsoap.org/soap/envelope/");
#endregion Load XML from SOAP
#region Zip SOAP
XmlNode bodyNode = doc.SelectSingleNode(@"//soap:Body", nsMan);
bodyNode = bodyNode.FirstChild.FirstChild;
while (bodyNode != null)
{
if (bodyNode.InnerXml.Length > 0)
{
// Zip
byte[] outData = ZipArray(bodyNode.InnerXml);
bodyNode.InnerXml = Convert.ToBase64String(outData);
}
bodyNode = bodyNode.NextSibling;
}
#endregion Zip SOAP
#region Crypt SOAP
foreach (string xPathQuery in soapElement)
{
XmlNodeList nodesToEncrypt = doc.SelectNodes(xPathQuery, nsMan);
if (nodesToEncrypt != null)
foreach (XmlNode nodeToEncrypt in nodesToEncrypt)
{
//Encrypt
nodeToEncrypt.InnerXml = EncryptString(nodeToEncrypt.InnerXml,
user.IV, user.Salt, user.Password, user.HashType,
user.KeySize, user.PasswordIterations);
}
}
#endregion Crypt SOAP
inputStream.Position = 0;
var settings = new XmlWriterSettings { Encoding = Encoding.UTF8 };
using (XmlWriter writer = XmlWriter.Create(inputStream, settings))
{
doc.WriteTo(writer);
return inputStream;
}
}
Here is a code on client side which decrypt and uzip SOAP :
//decrypt string
private static string DecryptString(string @string, string initialVector, string salt, string password,
string hashAlgorithm, int keySize, int passwordIterations)
{
byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt);
byte[] cipherTextBytes = Convert.FromBase64String(@string);
var derivedPassword = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm, passwordIterations);
byte[] keyBytes = derivedPassword.GetBytes(keySize / 8);
var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC };
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initialVectorBytes);
using (var memStream = new MemoryStream(cipherTextBytes))
{
var cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read);
var plainTextBytes = new byte[cipherTextBytes.Length];
int byteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
return Encoding.UTF8.GetString(plainTextBytes, 0, byteCount);
}
}
//unzip string
private static byte[] UnzipArray(string stringToUnzip)
{
byte[] inputByteArray = Convert.FromBase64String(stringToUnzip);
var ms = new MemoryStream(inputByteArray);
var ret = new MemoryStream();
// SharpZipLib.Zip
var zipIn = new ZipInputStream(ms);
var theEntry = zipIn.GetNextEntry();
var buffer = new Byte[2048];
int size = 2048;
while (true)
{
size = zipIn.Read(buffer, 0, buffer.Length);
if (size > 0)
{
ret.Write(buffer, 0, size);
}
else
{
break;
}
}
return ret.ToArray();
}
public virtual Stream InSoap(Stream inputStream, string[] soapElement)
{
#region Load XML from SOAP
var doc = new XmlDocument();
using (var reader = new XmlTextReader(inputStream))
{
doc.Load(reader);
}
var nsMan = new XmlNamespaceManager(doc.NameTable);
nsMan.AddNamespace("soap",
"http://schemas.xmlsoap.org/soap/envelope/");
#endregion Load XML from SOAP
#region Decrypt SOAP
foreach (string xPathQuery in soapElement)
{
XmlNodeList nodesToEncrypt = doc.SelectNodes(xPathQuery, nsMan);
if (nodesToEncrypt != null)
foreach (XmlNode nodeToEncrypt in nodesToEncrypt)
{
nodeToEncrypt.InnerXml = DecryptString(nodeToEncrypt.InnerXml, saltPhrase, passwordPhrase, initialVector,
hashAlgorithm, passwordIterations, keySize);
}
}
#endregion Decrypt SOAP
#region UnZip SOAP
XmlNode node = doc.SelectSingleNode("//soap:Body", nsMan);
node = node.FirstChild.FirstChild;
while (node != null)
{
if (node.InnerXml.Length > 0)
{
byte[] outData = UnzipArray(node.InnerXml);
string sTmp = Encoding.UTF8.GetString(outData);
node.InnerXml = sTmp;
}
node = node.NextSibling;
}
#endregion UnZip SOAP
var retStream = new MemoryStream();
doc.Save(retStream);
return retStream;
}
strong text