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]

Reply via email to