FileSigner.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using System.Xml;
  7. using System.Diagnostics;
  8. using System.Reflection;
  9. using System.Security.Cryptography;
  10. using Aitex.Core.RT.Log;
  11. namespace Aitex.Core.Util
  12. {
  13. /// <summary>
  14. /// This class provides a set of static APIs that add digital signature to Xml files and verify if Xml files
  15. /// or Xml memory streams have valid signature.
  16. /// </summary>
  17. public static class FileSigner
  18. {
  19. /* This API didn't pass unit test. Will be uncommented in the future.
  20. /// <summary>
  21. /// Checks to see if the memory stream is a valid xml stream with valid signature.
  22. /// </summary>
  23. /// <param name="stream"></param>
  24. /// <returns>False if the stream is empty or null, or embedded signature doesn't match, or there is no the signature.</returns>
  25. public static bool IsValid(Stream stream)
  26. {
  27. bool retVal = false;
  28. try
  29. {
  30. Logger.LogTrace(MethodBase.GetCurrentMethod(), Logger.TraceEntry);
  31. XmlDocument doc = new XmlDocument();
  32. doc.Load(stream);
  33. Debug.Assert(doc != null && doc.DocumentElement != null);
  34. // Get root element
  35. XmlElement elemRoot = doc.DocumentElement;
  36. // Get signature element
  37. XmlElement elemSignature = elemRoot["Signature"];
  38. if (elemSignature == null)
  39. {
  40. return false; // The stream was not signed.
  41. }
  42. // Remove signature element from document
  43. elemRoot.RemoveChild(elemSignature);
  44. // Calculate hash code from file (after removing Signature element)
  45. UnicodeEncoding ue = new UnicodeEncoding();
  46. SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
  47. char[] innerXMLArray = elemRoot.InnerXml.ToCharArray();
  48. byte[] bytes = ue.GetBytes(innerXMLArray);
  49. // byte[] signature = sha1.ComputeHash(ue.GetBytes(elemRoot.InnerXml));
  50. byte[] signature = sha1.ComputeHash(bytes);
  51. string strSignature = Convert.ToBase64String(signature);
  52. // Add signature back to document
  53. elemRoot.AppendChild(elemSignature);
  54. // Compare embedded signature to calculated value
  55. if (elemSignature.InnerText == strSignature)
  56. {
  57. retVal = true;
  58. }
  59. }
  60. catch (System.Exception ex)
  61. {
  62. retVal = false;
  63. Logger.LogError(MethodBase.GetCurrentMethod(), ex);
  64. throw;
  65. }
  66. finally
  67. {
  68. Logger.LogTrace(MethodBase.GetCurrentMethod(), Logger.TraceExit);
  69. }
  70. return retVal;
  71. }
  72. */
  73. /// <summary>
  74. /// Checks to see if the file is a valid xml file with valid signature.
  75. /// </summary>
  76. /// <param name="fileName"></param>
  77. /// <returns>False if the embedded signature doesn't match, or there is no the signature.</returns>
  78. public static bool IsValid(string fileName)
  79. {
  80. bool retVal = false;
  81. try
  82. {
  83. XmlDocument doc = new XmlDocument();
  84. doc.Load(fileName);
  85. Debug.Assert(doc != null && doc.DocumentElement != null);
  86. // Get root element
  87. XmlElement elemRoot = doc.DocumentElement;
  88. // Get signature element
  89. XmlElement elemSignature = elemRoot["Signature"];
  90. if (elemSignature == null)
  91. {
  92. return false; // The file was not signed.
  93. }
  94. // Remove signature element from document
  95. elemRoot.RemoveChild(elemSignature);
  96. // Calculate hash code from file (after removing Signature element)
  97. UnicodeEncoding ue = new UnicodeEncoding();
  98. SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
  99. byte[] signature = sha1.ComputeHash(ue.GetBytes(elemRoot.InnerXml));
  100. string strSignature = Convert.ToBase64String(signature);
  101. // Add signature back to document
  102. elemRoot.AppendChild(elemSignature);
  103. // Compare embedded signature to calculated value
  104. if (elemSignature.InnerText == strSignature)
  105. {
  106. retVal = true;
  107. }
  108. }
  109. catch (System.Exception e)
  110. {
  111. retVal = false;
  112. LOG.Write(e);
  113. throw;
  114. }
  115. finally
  116. {
  117. }
  118. return retVal;
  119. }
  120. /* This API didn't pass unit test. Will be uncommented in the future.
  121. /// <summary>
  122. /// Add signature to the end of the xml memory stream
  123. /// </summary>
  124. /// <param name="stream"></param>
  125. /// <returns></returns>
  126. public static Stream Sign(Stream stream)
  127. {
  128. try
  129. {
  130. Logger.LogTrace(MethodBase.GetCurrentMethod(), Logger.TraceEntry);
  131. XmlDocument doc = new XmlDocument();
  132. if (stream == null || stream.Length == 0)
  133. {
  134. throw new InvalidOperationException("Empty stream, no XML file to Sign");
  135. }
  136. else
  137. {
  138. doc.Load(stream);
  139. XmlElement elemRoot = doc.DocumentElement;
  140. // Remove any existing signature
  141. XmlElement elemSignature = elemRoot["Signature"];
  142. if (elemSignature != null)
  143. {
  144. elemRoot.RemoveChild(elemSignature);
  145. }
  146. // Calculate hash code (after removing Signature element)
  147. UnicodeEncoding ue = new UnicodeEncoding();
  148. SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
  149. char[] innerXMLArray = elemRoot.InnerXml.ToCharArray();
  150. byte[] bytes = ue.GetBytes(innerXMLArray);
  151. // byte[] nSignature = sha1.ComputeHash(ue.GetBytes(elemRoot.InnerXml));
  152. byte[] nSignature = sha1.ComputeHash(bytes);
  153. string strSignature = Convert.ToBase64String(nSignature);
  154. // Add signature to XML document
  155. elemSignature = doc.CreateElement("Signature");
  156. elemSignature.InnerText = strSignature;
  157. elemRoot.AppendChild(elemSignature);
  158. // memStream.Flush();
  159. stream.Seek(0, SeekOrigin.Begin);
  160. doc.Save(stream);
  161. return stream;
  162. }
  163. }
  164. catch (Exception ex)
  165. {
  166. Logger.LogError(MethodBase.GetCurrentMethod(), ex);
  167. throw;
  168. }
  169. finally
  170. {
  171. Logger.LogTrace(MethodBase.GetCurrentMethod(), Logger.TraceExit);
  172. }
  173. }
  174. */
  175. /// <summary>
  176. /// Add signature to the end of the xml file.
  177. /// </summary>
  178. /// <param name="fileName"></param>
  179. public static void Sign(string fileName)
  180. {
  181. try
  182. {
  183. XmlDocument doc = new XmlDocument();
  184. bool writeable = true;
  185. if (File.Exists(fileName) && (File.GetAttributes(fileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
  186. {
  187. writeable = false;
  188. File.SetAttributes(fileName, FileAttributes.Normal);
  189. }
  190. doc.Load(fileName);
  191. XmlElement elemRoot = doc.DocumentElement;
  192. // Remove any existing signature
  193. XmlElement elemSignature = elemRoot["Signature"];
  194. if (elemSignature != null)
  195. {
  196. elemRoot.RemoveChild(elemSignature);
  197. }
  198. // Calculate hash code (after removing Signature element)
  199. UnicodeEncoding ue = new UnicodeEncoding();
  200. SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
  201. byte[] nSignature = sha1.ComputeHash(ue.GetBytes(elemRoot.InnerXml));
  202. string strSignature = Convert.ToBase64String(nSignature);
  203. // Add signature to XML document
  204. elemSignature = doc.CreateElement("Signature");
  205. elemSignature.InnerText = strSignature;
  206. elemRoot.AppendChild(elemSignature);
  207. doc.Save(fileName);
  208. if (!writeable)
  209. {
  210. File.SetAttributes(fileName, FileAttributes.ReadOnly);
  211. }
  212. }
  213. catch (Exception ex)
  214. {
  215. LOG.Write(ex);
  216. throw;
  217. }
  218. finally
  219. {
  220. }
  221. }
  222. }
  223. }