public static SignatureDetails ValidateXMLSignature(string SignedXML) { if (SignedXML == null) { throw new ArgumentNullException("SignedXML"); } //Make sure the SAPI Library is loaded SAPIInit(); SignatureDetails SigDetails = new SignatureDetails(); SigFieldSettings SigFieldSettings = new SigFieldSettingsClass(); SigFieldInfo SignatureFieldInfo = new SigFieldInfoClass(); SAPICrypt SAPI = new SAPICryptClass(); SigFieldHandle hField = null; int rc; SESHandle hSession = new SESHandleClass(); if ((rc = SAPI.HandleAcquire(out hSession)) != 0) { throw new Exception(string.Format( "Memory allocation error (#{0})", rc.ToString("X"))); } SAPIContext ctxValidateSignature = new SAPIContextClass(); int num = 0; if ((rc = SAPI.SignatureFieldEnumInit(hSession, ctxValidateSignature, SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_XML, SignedXML, 0, ref num)) != 0) { SAPI.HandleRelease(hSession); throw new Exception(string.Format( "An error occured while initializing the signature validation process (#{0})", rc.ToString("X"))); } if (num < 1) { throw new Exception("The XML file is not signed!"); } if (num > 1) { throw new Exception("SAPI only supports a single signature per XML file!"); } if ((rc = SAPI.SignatureFieldEnumCont(hSession, ctxValidateSignature, out hField)) != 0) { SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); throw new Exception(string.Format( "Failed to retrieve signature (#{0})", rc.ToString("X"))); } if ((rc = SAPI.SignatureFieldInfoGet(hSession, hField, SigFieldSettings, SignatureFieldInfo)) != 0) { SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); throw new Exception(string.Format( "Failed to parse signature details (#{0})", rc.ToString("X"))); } CertStatus not_used = new CertStatus(); SigDetails.isValid = SAPI.SignatureFieldVerify(hSession, hField, not_used, 0) == 0; SigDetails.SignerCertificate = new X509Certificate2( (byte[])(((SAPIByteArray)SignatureFieldInfo.Certificate).ToArray())); SigDetails.SignerName = SignatureFieldInfo.SignerName; //Convert FILE_TIME to ticks ulong filetime = SignatureFieldInfo.SignatureTime.HighDateTime; filetime <<= 32; filetime += SignatureFieldInfo.SignatureTime.LowDateTime; SigDetails.SignatureTimeTicks = DateTime.FromFileTimeUtc((long)filetime).Ticks; //Cleanup memory SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); return(SigDetails); }
public static SignatureDetails ValidateSignature(Stream SignedData, Stream Signature) { if (SignedData == null) { throw new ArgumentNullException("SignedData"); } if (Signature == null) { throw new ArgumentNullException("Signature"); } //Make sure the SAPI Library is loaded SAPIInit(); SignatureDetails SigDetails = new SignatureDetails(); int rc; SAPICrypt SAPI = new SAPICryptClass(); SESHandle hSession = new SESHandleClass(); if ((rc = SAPI.HandleAcquire(out hSession)) != 0) { throw new Exception(string.Format( "Memory allocation error (#{0})", rc.ToString("X"))); } //Extract Signer Data from the Signature stream //Read Signature content from stream to the SAPI bytes array Array baSignature = new byte[(int)Signature.Length]; Signature.Read((byte[])baSignature, 0, (int)Signature.Length); SAPIByteArray sSignature = new SAPIByteArrayClass(); sSignature.FromArray(ref baSignature); //SAPIByteArray sSignedData = new SAPIByteArrayClass(); //Array t1 = (Array)SignedData; sSignedData.FromArray(ref t1); object Certificate; // Extract the signer's certificate from signature SAPI_ENUM_DATA_TYPE SAPIType = SAPI_ENUM_DATA_TYPE.SAPI_ENUM_DATA_TYPE_NONE; if ((rc = SAPI.PKCS7BlobGetValue(hSession, sSignature, SAPI_ENUM_PKCS7_FIELD.SAPI_ENUM_PKCS7_FIELD_CERT, out Certificate, ref SAPIType)) != 0) { SAPI.HandleRelease(hSession); throw new Exception(string.Format( "An error occured while extracting the signer's certificate from the signature stream (#{0})", rc.ToString("X"))); } SigDetails.SignerCertificate = new X509Certificate2((byte[])(((SAPIByteArray)Certificate).ToArray())); SigDetails.SignerName = SigDetails.SignerCertificate.GetNameInfo(X509NameType.SimpleName, false); SigDetails.SignerEmail = SigDetails.SignerCertificate.GetNameInfo(X509NameType.EmailName, false); //Run the signature validation process SAPIContext ctxValidateSignature = new SAPIContextClass(); if ((rc = SAPI.BufferVerifySignatureInit(hSession, ctxValidateSignature, sSignature, 0)) != 0) { SAPI.HandleRelease(hSession); throw new Exception(string.Format( "An error occured while initializing the signature validation process (#{0})", rc.ToString("X"))); } int remaining = (int)SignedData.Length; int chunkMaxSize = 1 << 20; //1MB //Calculate first chunk size int chunkSize = remaining < chunkMaxSize ? remaining : chunkMaxSize; while (remaining > 0) { Array chunk = new byte[chunkSize]; //Read in chunks of 1MB int read = SignedData.Read((byte[])chunk, 0, chunkSize); if (read <= 0) { throw new EndOfStreamException(String.Format("End of stream reached with {0} bytes left to read", remaining)); } //Build SAPI-Compatible byte array SAPIByteArray tmpBuff = new SAPIByteArrayClass(); tmpBuff.FromArray(ref chunk); //Add read buffer to the validation calculation if ((rc = SAPI.BufferVerifySignatureCont(hSession, ctxValidateSignature, tmpBuff)) != 0) { SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); throw new Exception(string.Format( "An error occured while validating the digital signature (#{0})", rc.ToString("X"))); } remaining -= read; chunkSize = Math.Min(remaining, chunkSize); } //Get the final validation result SAPIFileTime signingTime = new SAPIFileTimeClass(); rc = SAPI.BufferVerifySignatureEnd(hSession, ctxValidateSignature, signingTime, new CertStatusClass()); if ((uint)rc == 0x90030360) //SAPI_SIGNATURE_NOT_VALID { SigDetails.isValid = false; SigDetails.SignatureTimeTicks = 0; } else if (rc == 0) { SigDetails.isValid = true; //Convert FILE_TIME to ticks ulong filetime = signingTime.HighDateTime; filetime <<= 32; filetime += signingTime.LowDateTime; SigDetails.SignatureTimeTicks = DateTime.FromFileTimeUtc((long)filetime).Ticks; } else { SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); throw new Exception(string.Format( "Failed to validate Digital Signature (#{0})", rc.ToString("X"))); } //Cleanup memory SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); return(SigDetails); }
public static SignatureDetails ValidateXMLSignature(string SignedXML) { if (SignedXML == null) throw new ArgumentNullException("SignedXML"); //Make sure the SAPI Library is loaded SAPIInit(); SignatureDetails SigDetails = new SignatureDetails(); SigFieldSettings SigFieldSettings = new SigFieldSettingsClass(); SigFieldInfo SignatureFieldInfo = new SigFieldInfoClass(); SAPICrypt SAPI = new SAPICryptClass(); SigFieldHandle hField = null; int rc; SESHandle hSession = new SESHandleClass(); if ((rc = SAPI.HandleAcquire(out hSession)) != 0) { throw new Exception(string.Format( "Memory allocation error (#{0})", rc.ToString("X"))); } SAPIContext ctxValidateSignature = new SAPIContextClass(); int num = 0; if ((rc = SAPI.SignatureFieldEnumInit(hSession, ctxValidateSignature, SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_XML, SignedXML, 0, ref num)) != 0) { SAPI.HandleRelease(hSession); throw new Exception(string.Format( "An error occured while initializing the signature validation process (#{0})", rc.ToString("X"))); } if (num < 1) throw new Exception("The XML file is not signed!"); if (num > 1) throw new Exception("SAPI only supports a single signature per XML file!"); if ((rc = SAPI.SignatureFieldEnumCont(hSession, ctxValidateSignature, out hField)) != 0) { SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); throw new Exception(string.Format( "Failed to retrieve signature (#{0})", rc.ToString("X"))); } if ((rc = SAPI.SignatureFieldInfoGet(hSession, hField, SigFieldSettings, SignatureFieldInfo)) != 0) { SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); throw new Exception(string.Format( "Failed to parse signature details (#{0})", rc.ToString("X"))); } CertStatus not_used = new CertStatus(); SigDetails.isValid = SAPI.SignatureFieldVerify(hSession, hField, not_used, 0) == 0; SigDetails.SignerCertificate = new X509Certificate2( (byte[])(((SAPIByteArray)SignatureFieldInfo.Certificate).ToArray())); SigDetails.SignerName = SignatureFieldInfo.SignerName; //Convert FILE_TIME to ticks ulong filetime = SignatureFieldInfo.SignatureTime.HighDateTime; filetime <<= 32; filetime += SignatureFieldInfo.SignatureTime.LowDateTime; SigDetails.SignatureTimeTicks = DateTime.FromFileTimeUtc((long)filetime).Ticks; //Cleanup memory SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); return SigDetails; }
public static SignatureDetails ValidateSignature(Stream SignedData, Stream Signature) { if (SignedData == null) throw new ArgumentNullException("SignedData"); if (Signature == null) throw new ArgumentNullException ("Signature"); //Make sure the SAPI Library is loaded SAPIInit(); SignatureDetails SigDetails = new SignatureDetails(); int rc; SAPICrypt SAPI = new SAPICryptClass(); SESHandle hSession = new SESHandleClass(); if ((rc = SAPI.HandleAcquire(out hSession)) != 0) { throw new Exception(string.Format( "Memory allocation error (#{0})", rc.ToString("X"))); } //Extract Signer Data from the Signature stream //Read Signature content from stream to the SAPI bytes array Array baSignature = new byte[(int)Signature.Length]; Signature.Read((byte[])baSignature, 0, (int)Signature.Length); SAPIByteArray sSignature = new SAPIByteArrayClass(); sSignature.FromArray(ref baSignature); //SAPIByteArray sSignedData = new SAPIByteArrayClass(); //Array t1 = (Array)SignedData; sSignedData.FromArray(ref t1); object Certificate; // Extract the signer's certificate from signature SAPI_ENUM_DATA_TYPE SAPIType = SAPI_ENUM_DATA_TYPE.SAPI_ENUM_DATA_TYPE_NONE; if ((rc = SAPI.PKCS7BlobGetValue(hSession, sSignature, SAPI_ENUM_PKCS7_FIELD.SAPI_ENUM_PKCS7_FIELD_CERT, out Certificate, ref SAPIType)) != 0) { SAPI.HandleRelease(hSession); throw new Exception(string.Format( "An error occured while extracting the signer's certificate from the signature stream (#{0})", rc.ToString("X"))); } SigDetails.SignerCertificate = new X509Certificate2((byte[])(((SAPIByteArray)Certificate).ToArray())); SigDetails.SignerName = SigDetails.SignerCertificate.GetNameInfo (X509NameType.SimpleName, false); SigDetails.SignerEmail = SigDetails.SignerCertificate.GetNameInfo (X509NameType.EmailName, false); //Run the signature validation process SAPIContext ctxValidateSignature = new SAPIContextClass(); if ((rc = SAPI.BufferVerifySignatureInit (hSession, ctxValidateSignature, sSignature, 0)) != 0) { SAPI.HandleRelease(hSession); throw new Exception(string.Format( "An error occured while initializing the signature validation process (#{0})", rc.ToString("X"))); } int remaining = (int) SignedData.Length; int chunkMaxSize = 1 << 20; //1MB //Calculate first chunk size int chunkSize = remaining < chunkMaxSize ? remaining : chunkMaxSize; while (remaining > 0) { Array chunk = new byte[chunkSize]; //Read in chunks of 1MB int read = SignedData.Read((byte[])chunk, 0, chunkSize); if (read <= 0) throw new EndOfStreamException (String.Format("End of stream reached with {0} bytes left to read", remaining)); //Build SAPI-Compatible byte array SAPIByteArray tmpBuff = new SAPIByteArrayClass(); tmpBuff.FromArray(ref chunk); //Add read buffer to the validation calculation if ((rc = SAPI.BufferVerifySignatureCont(hSession, ctxValidateSignature, tmpBuff)) != 0) { SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); throw new Exception(string.Format( "An error occured while validating the digital signature (#{0})", rc.ToString("X"))); } remaining -= read; chunkSize = Math.Min(remaining, chunkSize); } //Get the final validation result SAPIFileTime signingTime = new SAPIFileTimeClass(); rc = SAPI.BufferVerifySignatureEnd(hSession, ctxValidateSignature, signingTime, new CertStatusClass()); if ((uint)rc == 0x90030360) //SAPI_SIGNATURE_NOT_VALID { SigDetails.isValid = false; SigDetails.SignatureTimeTicks = 0; } else if (rc == 0) { SigDetails.isValid = true; //Convert FILE_TIME to ticks ulong filetime = signingTime.HighDateTime; filetime <<= 32; filetime += signingTime.LowDateTime; SigDetails.SignatureTimeTicks = DateTime.FromFileTimeUtc((long)filetime).Ticks; } else { SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); throw new Exception(string.Format( "Failed to validate Digital Signature (#{0})", rc.ToString("X"))); } //Cleanup memory SAPI.ContextRelease(ctxValidateSignature); SAPI.HandleRelease(hSession); return SigDetails; }