I have written the code below to sign an XML document that has TWO URI reference section to sign. It all appears to work fine BUT when I POST my XML to the web service I receive a response of Invalid Signature. Can anyone see where I might be going wrong, or sugest a better way to digiatlly sign an XML document.
Here is some of my code: bool CDigitalCerts::SignXml() { try { // Get our Base64 string of the certificate: m_rGWDoc.SetX509CertificateValue( GetX509Certificate( m_sFilepath ) ); // Compute digests: VSSignatureRefs vSigRefs; VSDigestValues vDigests; m_rGWDoc.GetNodesToSign( vSigRefs ); size_t nCount = vSigRefs.size(); for ( int n = 0; n < nCount; ++n ) { SSignatureRefs data = vSigRefs[n]; SDigestValue dv; dv.sURI = data.sURI; char* szBuffer = data.sNode.GetBuffer(0); dv.sDigest = ComputeDigest( "sha1", szBuffer, strlen(szBuffer) ); // Store computed digests: vDigests.push_back( dv ); } // Compute the Signature value: unsigned char* pszSig; unsigned int nLen = 0; int nSigSize = EVP_PKEY_size( m_pKey ); pszSig = new unsigned char[ nSigSize * 2 ]; ComputeSignatureValue( vDigests, pszSig, nLen ); // Convert to Base64: for ( int n = 0; n < nCount; ++n ) { SDigestValue dv = vDigests[n]; vDigests[n].sDigest = EncodeBase64( dv.sDigest ); } CString sSigValue = EncodeBase64( pszSig, nLen ); delete[] pszSig; // Add digests and signature to our xml doc: m_rGWDoc.SetDigestValues( vDigests ); m_rGWDoc.SetSignatureValue( sSigValue ); vDigests.empty(); return true; } catch( CString sMsg ) { MessageBox( m_hParentWnd, sMsg, "Error", MB_ICONEXCLAMATION | MB_OK ); return false; } } CString CDigitalCerts::GetX509Certificate( const CString& rsFilepath ) { m_sFilepath = rsFilepath; CString sCert = ""; if ( !m_pCert ) { ReadPKCS12(); } if ( m_pCert ) { // Get certificate data into memory BIO* pBio = BIO_new( BIO_s_mem() ); PEM_write_bio_X509_AUX( pBio, m_pCert ); char* pszData = NULL; int count = BIO_get_mem_data( pBio, &pszData ); // xfer to CString: CString sOut( pszData ); BIO_free( pBio ); const CString sStart = _T("-----BEGIN TRUSTED CERTIFICATE-----"); const CString sEnd = _T("-----END TRUSTED CERTIFICATE-----"); int nIndex = sOut.Find( sStart, 0 ); sOut.Delete( nIndex, sStart.GetLength() ); nIndex = sOut.Find( sEnd, 0 ); sOut.Delete( nIndex, sOut.GetLength() - nIndex ); sCert = sOut; } return sCert; } void CDigitalCerts::ComputeSignatureValue( vector<SDigestValue>& vecBuffers, unsigned char* pszSig, unsigned int& nLen ) { if ( !m_pKey ) { ReadPKCS12(); } if ( m_pKey ) { EVP_MD_CTX ctx; EVP_MD_CTX_init( &ctx ); int res = EVP_SignInit_ex( &ctx, EVP_sha1(), NULL ); // Feed buffers in to be signed: size_t nCount = vecBuffers.size(); for ( int n = 0; n < nCount; ++n ) { char* szBuffer = vecBuffers[n].sDigest.GetBuffer(0); res = EVP_SignUpdate( &ctx, szBuffer, strlen(szBuffer) ); } // Compute signature: res = EVP_SignFinal( &ctx, pszSig, &nLen, m_pKey ); if ( res != 0 ) { // ??? } } } CString CDigitalCerts::ComputeDigest( const char* szAlgorithm, char* szBuffer, unsigned int nLen ) { const EVP_MD* pMd; unsigned char* pszOut = new unsigned char[ 128 ]; EVP_MD_CTX ctx; unsigned int unLen; OpenSSL_add_all_digests(); if ( !( pMd = EVP_get_digestbyname( szAlgorithm ) ) ) { return ""; } EVP_DigestInit( &ctx, pMd ); EVP_DigestUpdate( &ctx, szBuffer, nLen ); EVP_DigestFinal( &ctx, pszOut, &unLen ); pszOut[ unLen ] = '\0'; CString sHash( pszOut ); delete[] pszOut; return sHash; } bool CDigitalCerts::ReadPKCS12() { bool retval = false; BIO* pBio = (BIO*)NULL; PKCS12* p12 = (PKCS12*)NULL; pBio = BIO_new_file( m_sFilepath, _T("r") ); if( (BIO*)NULL != pBio ) { p12 = d2i_PKCS12_bio( pBio, (PKCS12**)NULL ); BIO_free( pBio ); } if (!p12) { CString sMsg; sMsg.Format( _T("Error reading the file: \n\n%s!\n\nPlease check your installation."), m_sFilepath ); throw sMsg; } STACK_OF(X509)* pCa = NULL; if ( !PKCS12_parse( p12, m_sPwd, &m_pKey, &m_pCert, &pCa ) ) { CString sMsg; sMsg.Format( _T("Unable to read from the digital certificate file: \n\n %s!\n\nPlease enter the correct password or obtain a new certificate."), m_sFilepath ); throw sMsg; } PKCS12_free( p12 ); sk_X509_free( pCa ); if ( m_pCert ) { return true; } else { CString sMsg; sMsg.Format( _T("Unable to read from the digital certificate file: \n\n %s!\n\nPlease obtain a fresh certificate file."), m_sFilepath ); throw sMsg; } return false; } -- View this message in context: http://www.nabble.com/Signing-XML-document-with-2-references-tf3894124.html#a11039640 Sent from the OpenSSL - Dev mailing list archive at Nabble.com. ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager [EMAIL PROTECTED]