Ooops.. My last post didn't actually make a point...
Q) Is it a limitation in xml-security to only allow keys of length 40. The following thread - discusses this topic in more detail... http://groups-beta.google.com/group/microsoft.public.platformsdk.security/br owse_frm/thread/b24b3cfdeac53dd1/ea4a951d04202694?q=DSA+signature+length+46& rnum=15&hl=en#ea4a951d04202694 -----Original Message----- From: Cullum, Steve Sent: 23 May 2005 16:52 To: 'security-dev@xml.apache.org' Subject: RE: XML Security-C:: HCRYPTPROV DSS/RSA providers not set via Win CAPI CryptoX509 using just the PCCERT_CONTEXT cosntructor Berin, Using the latest version of xml-security from CVS - I can clone the X509 cert using WINCAPI but I get errors during sig->validate() regarding and invalid signature. I tried the same sequence of code using the OpenSSL providers and got something very similar. Using WINCAPI - the message An error occured in the XML-Security-C Crypto routines Message: WinCAPI:DSA::VerifyBase64Signature - Expect 40 bytes in a DSA signature Using OPENSSL - the message An error occured in the XML-Security-C Crypto routines Message: OpenSSL:DSA - Signature Length incorrect (*) Do these errors relate to the certificte or the signature in the XML document? (*) For the OpenSSL test, I exported the key as a BASE64 DER encoded certificate and manually removed the ----BEGIN CERTIFICATE---- and ----END CERTIFICATE---- headers. Was this the correct thing to do? bool WinCAPICryptoKeyDSA::verifyBase64Signature(unsigned char * hashBuf, unsigned int hashLen, char * base64Signature, unsigned int sigLen) { .. hashBuf= [data] .. hashLen= 20 .. base64Signature "MCwCFFiTYY7/B+tYizrqccMZJKVQC6RyAhQUoVXtXfNUVEFZlaE3USajTEqUzQ==" .. sigLen= 64 b64.decodeInit(); rawSigLen = b64.decode((unsigned char *) base64Signature, sigLen, rawSig, sigLen); rawSigLen += b64.decodeFinish(&rawSig[rawSigLen], sigLen - rawSigLen); .. rawSigLen = 46 if (rawSigLen != 40) { throw XSECCryptoException(XSECCryptoException::DSAError, "WinCAPI:DSA::VerifyBase64Signature - Expect 40 bytes in a DSA signature"); } } // // validate.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "IOStreamOutputter.hpp" #define USE_WINCAPI // XML-Security-C (XSEC) #pragma comment (lib, "crypt32.lib") #pragma comment (lib, "xerces-c_2D.lib") #pragma comment (lib, "xsec_1D.lib") #include <xsec/framework/XSECProvider.hpp> #include <xsec/dsig/DSIGReference.hpp> #ifdef USE_WINCAPI #include <xsec/enc/WinCAPI/WinCAPICryptoKeyHMAC.hpp> #include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp> #include <xsec/enc/WinCAPI/WinCAPICryptoX509.hpp> #endif #ifdef USE_OPENSSL #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyHMAC.hpp> #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp> #include <xsec/enc/XSECCryptoException.hpp> #endif // USE_OPENSSL #include <xsec/framework/XSECException.hpp> #include <xsec/enc/XSECCryptoException.hpp> // Xerces #include <xercesc/util/PlatformUtils.hpp> #include <xercesc/parsers/XercesDOMParser.hpp> #include <xercesc/framework/MemBufInputSource.hpp> #if defined(_WIN32) # include <xsec/utils/winutils/XSECURIResolverGenericWin32.hpp> #else # include <xsec/utils/unixutils/XSECURIResolverGenericUnix.hpp> #endif XERCES_CPP_NAMESPACE_USE TCHAR *docToValidate = 0x00; #define IDATTRIBUTENS "http://schemas.xmlsoap.org/ws/2002/07/utility" #define IDATTRIBUTENAME "Id" #define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) #define SIGNER_NAME L"MYSIGNER" #define CERT_STORE_NAME L"MY" void ReadFile(TCHAR *fileName, TCHAR **chars, DWORD *len /* in TCHARS */) { DWORD bytesRead = 0; HANDLE hfp = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); *len = GetFileSize(hfp, NULL); *len /= sizeof(TCHAR); // convert length from bytes to TCHAR's *chars = (TCHAR *)malloc(*len * sizeof(TCHAR)); // dont mul by sizeof(TCHAR) ReadFile(hfp, (LPVOID)*chars, *len * sizeof(TCHAR), &bytesRead, NULL); CloseHandle(hfp); } int main (int argc, char **argv) { try { XMLPlatformUtils::Initialize(); XSECPlatformUtils::Initialise(); } catch (const XMLException &e) { cerr << "Error during initialisation of Xerces" << endl; cerr << "Error Message = : " << e.getMessage() << endl; } // Use xerces to parse the document XercesDOMParser * parser = new XercesDOMParser; parser->setDoNamespaces(true); parser->setCreateEntityReferenceNodes(true); parser->setDoSchema(true); // Create an input source DWORD len = 0; ReadFile(_T("c:\\apache\\signedxml\\nocert.xml"), &docToValidate, &len); MemBufInputSource* memIS = new MemBufInputSource ((const XMLByte*) docToValidate, (unsigned int) len, "XSECMem"); parser->parse(*memIS); int errorCount = parser->getErrorCount(); if (errorCount > 0) { cerr << "Error parsing input document\n"; exit (1); } DOMDocument *doc = parser->getDocument(); docSetup(doc); // Now create a signature object to validate the document XSECProvider prov; DSIGSignature * sig = prov.newSignatureFromDOM(doc); // Register defined attribute name sig->registerIdAttributeName(MAKE_UNICODE_STRING("ID")); sig->registerIdAttributeNameNS(MAKE_UNICODE_STRING(IDATTRIBUTENS), MAKE_UNICODE_STRING(IDATTRIBUTENAME)); try { #ifdef USE_WINCAPI HCERTSTORE certStore = NULL; PCCERT_CONTEXT certContext = NULL; certStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, CERT_STORE_NAME); if(certStore == NULL) { cout << "Certificate store cannot be opened\n"; exit (1); } // find signer's certificate. -- this certificate must have access to the signer's private key. certContext = CertFindCertificateInStore(certStore, MY_TYPE, 0, CERT_FIND_SUBJECT_STR, SIGNER_NAME, NULL); if(certContext == NULL) { cout << "unable to find signers certificate\n"; exit (1); } WinCAPICryptoProvider * cp = new WinCAPICryptoProvider(NULL, NULL, CRYPT_MACHINE_KEYSET); XSECPlatformUtils::SetCryptoProvider(cp); WinCAPICryptoX509 * x509 = new WinCAPICryptoX509(certContext, cp->getProviderRSA(), cp->getProviderDSS()); #endif // USE_WINCAPI #ifdef USE_OPENSSL OpenSSLCryptoX509 * x509 = new OpenSSLCryptoX509(); TCHAR *b64; DWORD b64Len; ReadFile(_T("c:\\apache\\signedxml\\nocert.cer"), &b64, &b64Len); x509->loadX509Base64Bin(b64, (unsigned int) b64Len); #endif // USE_OPENSSL // in my XML file i have no keyinfo sig->load(); sig->setSigningKey(x509->clonePublicKey()); if (sig->verify()) { cout << "Signature Valid\n"; } else { char * err = XMLString::transcode(sig->getErrMsgs()); cout << "Incorrect Signature\n"; cout << err << endl; XSEC_RELEASE_XMLCH(err); } } catch (XSECException &e) { cerr << "An error occured during a signature load\n Message: " << e.getMsg() << endl; exit(1); } catch (XSECCryptoException &e) { cerr << "An error occured in the XML-Security-C Crypto routines\n Message: " << e.getMsg() << endl; exit(1); } // Clean up delete memIS; delete parser; return 0; }