Utility.cs
A general utility class for things such as BASE64 encoding and decoding etc
// ------------------------------------------------------------------------------------------
// <copyright file="Utility.cs" company="Pointsharp AB">
// Pointsharp AB
// </copyright>
// <summary>
// Defines the Utility class.
// </summary>
// ------------------------------------------------------------------------------------------
namespace SecMaker.NiP.Client
{
using System;
using System.Linq;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using System.Security.Cryptography;
using Newtonsoft.Json;
public class Utility
{
public static string ToString(DateTime dateTime)
{
var sSortableDateTime =
dateTime.ToString("s");
var sDateTime =
sSortableDateTime.ToUpper().Replace("T", " ");
return sDateTime;
}
public static string ToBase64String(byte[] data)
{
return Convert.ToBase64String(data);
}
public static byte[] ToBytes(string value)
{
value =
value.Replace("\r", string.Empty);
value =
value.Replace("\n", string.Empty);
var regex =
new Regex(@"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$",
RegexOptions.Compiled);
return
regex.IsMatch(value)
? Convert.FromBase64String(value)
: Encoding.UTF8.GetBytes(value);
}
public static string ParseXmlElem(string xmlFile, string xmlTag)
{
var sSubStr =
xmlFile.Substring(xmlFile.IndexOf(xmlTag, StringComparison.Ordinal) + xmlTag.Length);
sSubStr =
sSubStr.Substring(0, sSubStr.IndexOf("<", StringComparison.Ordinal));
if (sSubStr.Contains("<") || sSubStr.Contains(">"))
{
return string.Empty;
}
return sSubStr;
}
public static byte[] GenerateNonce(int size)
{
var bytes = new byte[size];
using (var rnd = RandomNumberGenerator.Create())
{
rnd.GetBytes(bytes);
}
return bytes;
}
public static byte[] GenerateHmac(string hashAlgorithm, byte[] value, byte[] key)
{
HashAlgorithm hashGen;
switch (hashAlgorithm)
{
case "1.3.14.3.2.26":
{
hashGen = new HMACSHA1(key);
break;
}
case "2.16.840.1.101.3.4.2.1":
{
hashGen = new HMACSHA256(key);
break;
}
case "2.16.840.1.101.3.4.2.2":
{
hashGen = new HMACSHA384(key);
break;
}
case "2.16.840.1.101.3.4.2.3":
{
hashGen = new HMACSHA512(key);
break;
}
default:
{
hashGen = new HMACSHA1(key);
break;
}
}
var hash =
hashGen.ComputeHash(value);
return hash;
}
/// <summary>
/// Formats the info blob correctly for the encryption process
/// </summary>
/// <param name="data">XML formatted input to format</param>
/// <param name="mode">JSON format or not. In the future more modes than JSON or XML may be used.</param>
/// <returns></returns>
public static string FormatInfoBlob(string data, string mode)
{
if (string.IsNullOrEmpty(data))
{
return data;
}
string toReturn = null;
switch (mode)
{
case "XML":
{
toReturn = data;
break;
}
case "JSON":
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(data);
//Set JSON NameSpace so that we can add json:array to force list of only one obj to be properly formatted
XmlAttribute jsonNS = doc.CreateAttribute("xmlns", "json", "http://www.w3.org/2000/xmlns/");
jsonNS.Value = "http://james.newtonking.com/projects/json";
doc.DocumentElement.SetAttributeNode(jsonNS);
//Force all XML lists to be rendered as arrays, this is to avoid error with lists of length one.
var xpath = "//*[contains(local-name(), 'List')]";
var elements = doc.SelectNodes(xpath);
foreach (var element in elements)
{
var el = element as XmlElement;
if (el != null)
{
var jsonArray = doc.CreateAttribute("json", "Array", "http://james.newtonking.com/projects/json");
jsonArray.Value = "true";
el.SetAttributeNode(jsonArray);
}
}
//Now convert
string jsonText = JsonConvert.SerializeXmlNode(doc);
toReturn = jsonText.Substring(8, jsonText.Length - 9); //send info object without info:tag
break;
}
}
return toReturn;
}
/// <summary>
/// Reformats the infoblob to xml
/// </summary>
/// <param name="data">Data either XML or JSON formatted for now</param>
/// <param name="mode">The current format for the encrypted blob</param>
/// <returns></returns>
public static string ReformatInfoBlob(string data, string mode)
{
if (string.IsNullOrEmpty(data))
{
return data;
}
string toReturn = null;
switch (mode)
{
case "XML":
{
toReturn = data;
break;
}
case "JSON":
{
data = "{\"Info\":" + data+ "}";
string xml = (JsonConvert.DeserializeXmlNode(data)).OuterXml;
toReturn = xml;
break;
}
}
return toReturn;
}
public static byte[] Compress(byte[] data, string mode)
{
if (string.IsNullOrEmpty(mode) || mode == "NONE")
{
return data;
}
byte[] toReturn = null;
switch (mode)
{
case "GZ":
{
using (var memory = new MemoryStream())
{
using (var gzip = new GZipStream(memory, CompressionMode.Compress, true))
{
gzip.Write(data, 0, data.Length);
}
toReturn =
memory.ToArray();
break;
}
}
}
return toReturn;
}
public static byte[] Decompress(byte[] data, string mode)
{
if (string.IsNullOrEmpty(mode) || mode == "NONE")
{
return data;
}
byte[] toReturn = null;
switch (mode)
{
case "GZ":
{
using (var stream = new GZipStream(new MemoryStream(data), CompressionMode.Decompress))
{
const int size =
4096;
var buffer =
new byte[size];
using (var memory = new MemoryStream())
{
int count;
do
{
count =
stream.Read(buffer, 0, size);
if (count > 0)
{
memory.Write(buffer, 0, count);
}
} while (count > 0);
{
toReturn =
memory.ToArray();
}
}
}
break;
}
}
return toReturn;
}
public static byte[] AesEncryption(byte[] data, byte[] key, byte[] iv)
{
if (data == null)
{
throw new Exception("Data is null.");
}
if (key == null)
{
throw new Exception("Key is null.");
}
if (iv == null)
{
throw new Exception("IV is null.");
}
using (var provider = new AesCryptoServiceProvider())
{
provider.IV = iv;
provider.Key = key;
using (var encryptor = provider.CreateEncryptor(provider.Key, provider.IV))
{
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(data, 0, data.Length);
cs.Close();
return ms.ToArray();
}
}
}
}
}
public static byte[] AesDecryption(byte[] data, byte[] key, byte[] iv)
{
if (data == null)
{
throw new Exception("Data is null.");
}
if (key == null)
{
throw new Exception("Key is null.");
}
if (iv == null)
{
throw new Exception("IV is null.");
}
using (var provider = new AesCryptoServiceProvider())
{
provider.Key = key;
provider.IV = iv;
using (var decryptor = provider.CreateDecryptor(provider.Key, provider.IV))
{
using (var memoryStream = new MemoryStream(data))
{
using (var cs = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
var buffer = new byte[data.Length];
using (var ms = new MemoryStream())
{
int read;
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
}
}
}
}
public static string ToString(byte[] bytes)
{
string output;
using (var stream = new MemoryStream(bytes))
{
stream.Position = 0;
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
output = reader.ReadToEnd();
}
}
return output;
}
public static string GetNodeName(string xml)
{
var xDoc = new XmlDocument();
xDoc.LoadXml(xml);
var elem =
xDoc.DocumentElement;
if (elem == null)
{
return string.Empty;
}
var node =
elem.FirstChild;
var childNode = node.LastChild;
return childNode.Name;
}
public static string GetNodeContent(string document, string nodePath)
{
if (string.IsNullOrEmpty(document))
{
return string.Empty;
}
var xDoc = new XmlDocument();
xDoc.LoadXml(document);
var xRoot =
xDoc.DocumentElement;
if (xRoot == null)
{
const string sMessage =
"DocumentElement is null.";
throw new Exception(sMessage);
}
var childNode =
xRoot.SelectSingleNode("//" + nodePath);
return
childNode == null
? string.Empty
: childNode.InnerXml;
}
public static string GetInfoTest(string message)
{
message =
RemoveNameSpaces(message);
var xDoc = new XmlDocument();
xDoc.LoadXml(message);
var xRoot =
xDoc.DocumentElement;
if (xRoot == null)
{
const string sMessage =
"DocumentElement is null.";
throw new Exception(sMessage);
}
xDoc.LoadXml(xRoot.InnerXml);
var node =
xDoc.LastChild;
node =
node.LastChild;
return node.InnerXml;
}
public static string RemoveNameSpaces(string xml)
{
var xElem =
RemoveNameSpaces(XElement.Parse(xml));
return xElem.ToString();
}
private static XElement RemoveNameSpaces(XElement xmlDocument)
{
if (!xmlDocument.HasElements)
{
var xElem = new XElement(xmlDocument.Name.LocalName)
{
Value = xmlDocument.Value
};
foreach (var attribute in xmlDocument.Attributes())
{
xElem.Add(attribute);
}
return xElem;
}
return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(RemoveNameSpaces));
}
/// <summary>
/// Verifies that the response from server was a success. If not, throws an exception
/// </summary>
/// <param name="soapMessage"></param>
/// <remarks>
/// You may not want to be so harsh as to throw an exception. Your call.
/// </remarks>
static public bool VerifySuccess(String soapMessage)
{
if (soapMessage.IndexOf("NPR_SUCCESS") == -1)
{
var soapError =
soapMessage.Substring(soapMessage.IndexOf("<Status>", StringComparison.Ordinal));
soapError =
soapError.Substring(0, soapError.IndexOf("</Status>", StringComparison.Ordinal) + "</Status>".Length);
throw new Exception("API Call failed, error was: " + soapError);
}
return true;
}
/// <summary>
/// Returns the Task ID from a given <Task></Task> XML
/// </summary>
/// <param name="taskXml"></param>
/// <returns></returns>
public static string GetTaskIdFromTask(string taskXml)
{
XmlDocument task = new XmlDocument();
task.LoadXml(taskXml);
return task.SelectSingleNode(".//Id").InnerText;
}
/// <summary>
/// Quick and naive way to get contents of xml tag. Instead of loading entire soap response as xml we handle it as a string
/// </summary>
/// <param name="xmlString">String representation of the xml</param>
/// <param name="tagName"></param>
/// <param name="keepOuterTags">If true returns OuterXML, if false returns innerXML</param>
/// <returns>An empty string if the tag doesnt exist. If not returns the inner/outerXML for that tag</returns>
static public string NaiveParseXmlTag(String xmlString, String tagName, bool keepOuterTags)
{
string openTag = "<" + tagName + ">";
string closeTag = "</" + tagName + ">";
if (!xmlString.Contains(openTag))
{
return "";
}
int offSetStart = keepOuterTags ? 0 : openTag.Length;
int offSetEnd = keepOuterTags ? closeTag.Length : 0;
string returnValue = xmlString.Substring(xmlString.IndexOf(openTag, StringComparison.Ordinal) + offSetStart);
returnValue =
returnValue.Substring(0, returnValue.LastIndexOf(closeTag, StringComparison.Ordinal) + offSetEnd);
return returnValue;
}
/// <summary>
/// Parses out the <Task></Task> tag from a soapMessage if there is one
/// </summary>
/// <param name="xmlFile"></param>
/// <returns>The <Task></Task> elements outerXML</returns>
public static string ParseTaskElem(string xmlFile)
{
if (xmlFile.IndexOf("NPR_SUCCESS") == -1)
{
throw new Exception("Task creation failed: response was " + xmlFile);
}
var task =
xmlFile.Substring(xmlFile.IndexOf("<Task>", StringComparison.Ordinal));
task =
task.Substring(0, task.IndexOf("</Task>", StringComparison.Ordinal) + "</Task>".Length);
return task;
}
}
}