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 [email protected]
Automated List Manager [EMAIL PROTECTED]