public static void Main()
Console.WriteLine("Hello World");
using System.Threading.Tasks;
using SMBC.CM.Interface.File;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;
using SMBC.CM.Model.Enums;
using System.Security.Cryptography;
using SMBC.CM.Model.File.Response;
namespace SMBC.CM.Service.File
public class VerifyDocumentService : BaseCommand<bool>, IVerifyDocumentService
private XmlDocument _xmlDocument;
private readonly string _digestValue;
private readonly HashAlgorithmEnum _hashAlgorithm;
private readonly Stream _signedStream;
private readonly X509Certificate2 _publicKey;
private const string SIGNATURE = "Signature";
public VerifyDocumentService(XmlDocument xmlDocument, X509Certificate2 publicKey, string digestValue, HashAlgorithmEnum hashAlgorithm)
_xmlDocument = xmlDocument;
_digestValue = digestValue;
_hashAlgorithm = hashAlgorithm;
public VerifyDocumentService(Stream signedStream, X509Certificate2 publicKey, string digestValue, HashAlgorithmEnum hashAlgorithm)
_signedStream = signedStream;
_digestValue = digestValue;
_hashAlgorithm = hashAlgorithm;
public void ExecuteCommandTest()
protected override Task ExecuteAsyncCommandProcess()
throw new NotImplementedException();
protected override void ExecuteCommandProcess()
if (_signedStream != null)
_signedStream.Position = 0;
_xmlDocument = new XmlDocument();
_xmlDocument.Load(new XmlTextReader(_signedStream));
XmlNodeList nl = _xmlDocument.GetElementsByTagName(SIGNATURE, "http://www.w3.org/2000/09/xmldsig#");
throw new Exception("Cannot find Signature element");
throw new Exception("Correct certificate required - Required for name/serial checking on signatue file, but was not found/loaded");
string certIssuerName = _publicKey.Issuer;
string certSerialNum = _publicKey.SerialNumber;
string sigFileIssuerName = _xmlDocument.GetElementsByTagName("X509IssuerName", "http://www.w3.org/2000/09/xmldsig#").Item(0).InnerText;
string sigFileSerialNum = _xmlDocument.GetElementsByTagName("X509SerialNumber", "http://www.w3.org/2000/09/xmldsig#").Item(0).InnerText;
if (certIssuerName != sigFileIssuerName)
throw new Exception($"WARNING: given Certificate issuer name [{certIssuerName}] does not match with Signature file's issuer name: [{sigFileIssuerName}]");
var serialNum = GetSerialNum(certIssuerName, certSerialNum);
if (serialNum != sigFileSerialNum)
throw new Exception($"WARNING: given Certificate serial number [{serialNum}] does not match with Signature file's serial Number: [{sigFileSerialNum }]");
SignedXml signedXml = new SignedXml(_xmlDocument);
XmlNodeList nodeList = _xmlDocument.GetElementsByTagName(SIGNATURE);
signedXml.LoadXml((XmlElement)nodeList[0]);
#endregion Load signature
#region Verify digestValue ex:compare file content doesn't get change
var digestValueToVerify = Utility.Functions.Base64Encode(((Reference)signedXml.SignedInfo.References[0]).DigestValue);
if (_digestValue != digestValueToVerify)
throw new Exception("Invalid digest value!");
#endregion Verify digestValue ex:compare file content doesn't get change
#region Hash signedInfo Stream by sha256Bytes
HashStreamResponse signatureHash;
var xmlString = signedXml.SignedInfo.GetXml().OuterXml;
using (var svc = new HashService(Utility.Functions.StringXml2Stream(xmlString), _hashAlgorithm))
signatureHash = svc.Result;
#endregion Hash signedInfo Stream by sha256Bytes
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)_publicKey.PublicKey.Key;
var halg = Dictionaries.HashAlgorithmDictionary(_hashAlgorithm);
Result = csp.VerifyData(signatureHash.Bytes, halg, signedXml.Signature.SignatureValue);
#endregion Verify signature
private string GetSerialNum(string certIssuerName, string certSerialNum)
KeyInfoX509Data x509DataType = new KeyInfoX509Data();
x509DataType.AddIssuerSerial(_publicKey.Issuer, _publicKey.SerialNumber);
return ((X509IssuerSerial)x509DataType.IssuerSerials[0]).SerialNumber;