Steve,

The constructor you are using is quite new, and it doesn't set up the providers for the object correctly.

I've updated the constructor in CVS to require the two providers as parameters.

Actually, we could probably pull these parameters from the WinCAPI Crypto Provider instance, but it's safer to provide them directly.

Can you pull the most recent CVS and have a go with that?

Cheers,
        Berin

Cullum, Steve wrote:
Environment :-

XML-Security-C - CVS version 17/05/05
XALAN-1.7.0 and XERCES-2.5.0
Compiler VC7 (2003)
        #define HAVE_OPENSSL  0
        #define HAVE_WINCAPI  1
        #define USING_XALAN

I am trying to validate a SOAP response signed using the Verisign TSIK toolkit. The XML-SOAP response has a detached public key which I have installed into the "current user" store.
There is no "KeyInfo" or "Object" in my XML document but this seems to be 
acceptable to DSIGSignature::load();

I don't seem to be able to verify the public key via an WinCAPICryptoX509 using 
the WinCAPICryptoX509(PCCERT_CONTEXT) constructor - It loads the key correctly 
but does not set up the DSA/RSA provider handles which are needed later on 
during processing.

Using the mscrypto API - I find the certificate context and create a X509 
certificate with it.

         WinCAPICryptoX509 * x509 = new WinCAPICryptoX509(certContext);
         sig->setSigningKey(x509->clonePublicKey());        // FAILS HERE....
However WinCAPICryptoX509::clonePublicKey() fails due to the fact that WinCAPICryptoX509::m_pDSS has not been set. The only way I seem able to set WinCAPICryptoX509::m_pDSS is via the constructor WinCAPICryptoX509::WinCAPICryptoX509(HCRYPTPROV provRSA, HCRYPTPROV provDSS) but if I do this I am then unable to set WinCAPICryptoX509::mp_certContext certificate context handle.

(*) Is there a call similar to WinCAPICryptoX509::SetDSAProvider() ?
(*) As an aside the MSDN documentation for CryptImportPublicKeyInfo() states that it 
"is always acceptable" to use X509_ASN_ENCODING | PKCS_7_ASN_ENCODING for the 
DWORD dwCertEncodingType parameter - [is this relevant?]

To generate a DSS crypto provider handle I am using
        WinCAPICryptoProvider * cp = new WinCAPICryptoProvider(NULL, NULL, 
CRYPT_MACHINE_KEYSET);
        XSECPlatformUtils::SetCryptoProvider(cp);

(*) Would this handle be the correct one to send to 
WinCAPICryptoX509::SetDSAProvider() if it existed ie
        WinCAPICryptoX509::SetDSAProvider(cp->getProviderDSS());

I have also tried WinCAPICryptoProvider *cp = new WinCAPICryptoProvider(NULL, NULL, CRYPT_MACHINE_KEYSET);
   WinCAPICryptoX509 *x509 = (WinCAPICryptoX509 *)cp->X509();

At this stage there is no way I seem able to set the X509 certificate context eg
   x509->mp_certContext = certContext;  // no class member fn() exists to allow 
me to do this.


(*) If I manually set the value of m_pDSS (via the debugger) inside 
WinCAPICryptoX509::clonePublicKey() with a handle derived from calling new 
WinCAPICryptoProvider(NULL, NULL, CRYPT_MACHINE_KEYSET).  
WinCAPICryptoX509::clonePublicKey() does not fail and "seems" to generate a valid 
Key.  Calling sig->Verify() however gives me the error message...

        WinCAPI:DSA::VerifyBase64Signature - Expect 40 bytes in a DSA signature

-- Does this mean my document is fundementally rubbish ?? Looking at the public 
key details I can see.
[Signature Algorithm] sha1DSA
[Public Key] DSA (1024 Bits)
[Thumbprint Algorithm] sha1


Eg...
  WinCAPICryptoProvider *cp = new WinCAPICryptoProvider(NULL, NULL, 
CRYPT_MACHINE_KEYSET);
// get value of cp->m_provDSS
  WinCAPICryptoX509::clonePublicKey()
  {
    HCRYPTKEY key;
    BOOL fResult;
&m_pDSS = 1415288 /* set to valid handle gained by WinCAPICryptoProvider(NULL, NULL, CRYPT_MACHINE_KEYSET); (using debugger) if(getPublicKeyType() == XSECCryptoKey::KEY_DSA_PUBLIC) { fResult= CryptImportPublicKeyInfo(m_pDSS, X509_ASN_ENCODING, &(mp_certContext->pCertInfo->SubjectPublicKeyInfo), &key); }
}
        


Can someone verify my steps are correct..

  Load the document into DSIGSignature()
  CertOpenStore()
  certCtxt = CertFindCertificateInStore()
  Create X509 from certCtxt
  Load the signature inside DSIGSignature()
  Set the DSIGSignature signing key to a cloned copy of the public key stored 
in X509  (do I have to clone)
  verify the DSIGSignature

//
// my source code....based heavily on SimpleValidate.cpp
//
#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"TESTSIGNER"
#define CERT_STORE_NAME  L"MY"

int main (int argc, char **argv) { //.. //.. Reading and validation code ommitted
        //..

  // create a signature object to validate the document
  XSECProvider prov;

  DSIGSignature * sig = prov.newSignatureFromDOM(doc);

  sig->registerIdAttributeName(MAKE_UNICODE_STRING("ID"));

  // Register defined attribute name
  sig->registerIdAttributeNameNS(MAKE_UNICODE_STRING(IDATTRIBUTENS), 
MAKE_UNICODE_STRING(IDATTRIBUTENAME));

  // using MSCryptoAPI
try {
    HCERTSTORE     certStore = NULL;
PCCERT_CONTEXT certContext = NULL;
    // open the microsoft certiticate store
    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
    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);
    }

    // build an x509 certificate from my cert context
    WinCAPICryptoX509 * x509 = new WinCAPICryptoX509(certContext);

    sig->load();
// no keyinfo in my XML sig->setSigningKey(x509->clonePublicKey()); // FAILS HERE.... 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);
  }

  return 0;
}


Reply via email to