You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by robotk <ro...@163.com> on 2008/06/11 09:49:37 UTC

suggest a new feature: adding smart card support to windows svn client in version 1.5

suggest a new feature: adding smart card support to windows svn client in version 1.5
 
Hi:
  Maybe someone have posted this suggestion before, and the Linux build now can support smart card thanks to Joe Orton's greate work(http://svn.haxx.se/users/archive-2008-04/0377.shtml).
  I think it is not difficult to implement this feature on windows. Last month, we made an effort to implement smart card authentication by using Microsoft's CSP and openSSL library. We found that it is simple to manipulate the smart card by CSP API. Microsoft's CSP is a software interface standard. Almost all the smart card manufacturers support this standard and provide the software realization(dll).  The CSP standard allows us to use the public-private key pair to encrypt,decrypt data and sign message digest while know nothing about the hardware details. All the CSPs are registered in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider. This page(http://msdn.microsoft.com/en-us/library/aa380245%28VS.85%29.aspx) describes the CSP in detail.
  Most smart card manufacturers also provide a standards-based PKCS#11 library. PKCS#11(http://www.rsa.com/rsalabs/node.asp?id=2133) is a cryptographic token interface standard developed by RSA laboratories. It is the counterpart of Microsoft's CSP. PuTTY, openVPN and some other software on windows platform use PKCS#11 instead of CSP. The specifications of the PKCS#11 standard are described in ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs-11v2-20.pdf.
 
The following are several typical examples of using CSP API. (without error handling)
All the CSP APIs are declared in header file wincrypt.h.
1. Enumerate all the certificates stored in USB KEY:
    #include <wincrypt.h>
    #pragma comment(lib, "crypt32.lib")
    HCRYPTPROV hCryptProv = NULL;
    CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, hCryptProv, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
    // just access to the publicly available information, the CSP would not ask for a PIN
    PCCERT_CONTEXT pCertContext = NULL;
    while (1)
   {
     pCertContext = CertEnumCertificatesInStore (hCertStore, pCertContext);
     if (!pCertContext) break;
     //suppose the maximum length of all the fileds doesn't exceed 512
     const int iMaxFldLen = 512;
     char szSubjectName[iMaxFldLen]={0}, szIssuerName[iMaxFldLen]={0};
     // get common name, 
     CertGetNameString (pCertContext, CERT_NAME_ATTR_TYPE, NULL, szOID_COMMON_NAME, szSubjectName, iMaxFldLen); 
     // get issuer name
     CertGetNameString (pCertContext, CERT_NAME_ATTR_TYPE, CERT_NAME_ISSUER_FLAG, 
              szOID_COMMON_NAME, szIssuerName, iMaxFldLen);
     printf ("%s %s\n", szSubjectName, szIssuerName);
     // get the CSP name and key container name
     char szContName[iMaxFldLen]={0}, szProvName[iMaxFldLen]={0}, pvData[iMaxFldLen]={0};
     DWORD cbData = iMaxFldLen;
     CertGetCertificateContextProperty (pCertContext, CERT_KEY_PROV_INFO_PROP_ID, pvData, &cbData);
     CRYPT_KEY_PROV_INFO* pProvInfo = (CRYPT_KEY_PROV_INFO *)pvData;
     sprintf (szContName, "%S", pProvInfo->pwszContainerName);
     sprintf (szProvName, "%S", pProvInfo->pwszProvName);
   
     printf ("%s %s\n", szContName, szProvName);
     // get other fields of the X509 certificate
     // ...
    }
    CryptReleaseContext (hCryptProv, 0); // release the handle

2. Using private key stored in the USB KEY to sign the digest of message
    #include <wincrypt.h>
    #pragma comment(lib, "crypt32.lib")
    // the container name and CSP name can be retrieved in example 1
    // char szContName[] = {"61aecdd2-65b4-4919-a56c-0b2f5f7833d1"};
    // char szProvName[] = {"SafeSign CSP Version 1.0"};
    char szMsg[] = {"something"};
    DWORD dwMsgLen = strlen(szMsg);
    HCRYPTPROV hCryptProv = NULL;
    CryptAcquireContext (&hCryptProv, szContName, szProvName, PROV_RSA_FULL, 0);
    HCRYPTHASH hHash = NULL;
    CryptCreateHash (hCryptProv, CALG_MD5, 0, 0, &hHash);
    CryptHashData (hHash, (BYTE*)szMsg, dwMsgLen, 0);
    DWORD dwSignLen = 0;
    CryptSignHash (hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSignLen);
    char* szSignBuf = (char*) malloc(dwSignLen*sizeof(char));
    if (!CryptSignHash (hHash, AT_SIGNATURE, NULL, 0, (BYTE*)szSignBuf, &dwSignLen))
    {
      printf ("CryptSignHash failed\n");
    }
    else
    {
      printf ("CryptSignHash done\n");
    }
  
    free (szSignBuf);
    CryptReleaseContext (hCryptProv, 0); // release the handle

3. Using private key to decrypt the ciphertext encrypted by the public key
    #include <wincrypt.h>
    #pragma comment(lib, "crypt32.lib")
    // the container name and CSP name can be retrieved in example 1
    // char szContName[] = {"61aecdd2-65b4-4919-a56c-0b2f5f7833d1"};
    // char szProvName[] = {"SafeSign CSP Version 1.0"};
    char pEncryptedData[] = {"top secret encrypted by public key"};
    DWORD dwEncryptDataLen = strlen(pEncryptedData);
    HCRYPTPROV hCryptProv = NULL;
    CryptAcquireContext (&hCryptProv, szContName, szProvName, PROV_RSA_FULL, 0);
    HCRYPTKEY hUserKey = NULL;
    BOOL bRet= CryptGetUserKey (hCryptProv, AT_KEYEXCHANGE, &hUserKey);
    // pEncryptedData point to the ciphertext encrypted by the public key and 
    // dwEncryptDataLen is the length of the ciphertext
    if (!CryptDecrypt(hUserKey, 0, true, 0, (BYTE*)pEncryptedData, &dwEncryptDataLen))
    {
      // CryptDecrypt() will failed if the pEncryptedData was NOT 
      // encrypted by the corresponding public key
      printf ("CryptDecrypt failed\n");
    }
    else
    {
      printf ("CryptDecrypt done\n");
    }
    // now pEncryptedData point to plaintext and 
    // dwEncryptDataLen is the length of the plaintext
    CryptReleaseContext (hCryptProv, 0);
 
 
 
Thanks
 
Setven Zhang

RE: suggest a new feature: adding smart card support to windows svn client in version 1.5

Posted by Bert Huijben <be...@vmoo.com>.
> -----Original Message-----
> From: Karl Fogel [mailto:kfogel@red-bean.com]
> Sent: donderdag 12 juni 2008 9:54
> To: robotk
> Cc: dev@subversion.tigris.org
> Subject: Re: suggest a new feature: adding smart card support to
> windows svn client in version 1.5
> 
> robotk <ro...@163.com> writes:
> > suggest a new feature: adding smart card support to windows svn
> client in
> > version 1.5
> 
> Search for "smartcard" in
> http://svn.collab.net/repos/svn/trunk/CHANGES,
> you will see it's in upcoming 1.5.0.

The neon support will be in 1.5.0, but is currently unix (/linux/posix?) only. The fix to support smartcards on Windows should probably be included in a future neon (and/or serf ? ;-) version.

	Bert
> 
> -Karl
> 
> > Hi:
> >   Maybe someone have posted this suggestion before, and the Linux
> build now can
> > support smart card thanks to Joe Orton's greate
> work(http://svn.haxx.se/users/
> > archive-2008-04/0377.shtml).
> >   I think it is not difficult to implement this feature on windows.

<snip>

>
> > Thanks
> >
> > Setven Zhang


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org


Re: suggest a new feature: adding smart card support to windows svn client in version 1.5

Posted by Karl Fogel <kf...@red-bean.com>.
robotk <ro...@163.com> writes:
> suggest a new feature: adding smart card support to windows svn client in
> version 1.5

Search for "smartcard" in http://svn.collab.net/repos/svn/trunk/CHANGES,
you will see it's in upcoming 1.5.0.

-Karl

> Hi:
>   Maybe someone have posted this suggestion before, and the Linux build now can
> support smart card thanks to Joe Orton's greate work(http://svn.haxx.se/users/
> archive-2008-04/0377.shtml).
>   I think it is not difficult to implement this feature on windows. Last month,
> we made an effort to implement smart card authentication by using Microsoft's
> CSP and openSSL library. We found that it is simple to manipulate the smart
> card by CSP API. Microsoft's CSP is a software interface standard. Almost all
> the smart card manufacturers support this standard and provide the software
> realization(dll).  The CSP standard allows us to use the public-private key
> pair to encrypt,decrypt data and sign message digest while know nothing about
> the hardware details. All the CSPs are registered in HKEY_LOCAL_MACHINE\
> SOFTWARE\Microsoft\Cryptography\Defaults\Provider. This page(http://
> msdn.microsoft.com/en-us/library/aa380245%28VS.85%29.aspx) describes the CSP in
> detail.
>   Most smart card manufacturers also provide a standards-based PKCS#11 library.
> PKCS#11(http://www.rsa.com/rsalabs/node.asp?id=2133) is a cryptographic token
> interface standard developed by RSA laboratories. It is the counterpart of
> Microsoft's CSP. PuTTY, openVPN and some other software on windows platform use
> PKCS#11 instead of CSP. The specifications of the PKCS#11 standard are
> described in ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs-11v2-20.pdf.
>  
> The following are several typical examples of using CSP API. (without error
> handling)
> All the CSP APIs are declared in header file wincrypt.h.
> 1. Enumerate all the certificates stored in USB KEY:
>     #include <wincrypt.h>
>     #pragma comment(lib, "crypt32.lib")
>     HCRYPTPROV hCryptProv = NULL;
>     CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
> CRYPT_VERIFYCONTEXT);
>     HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0,
> hCryptProv, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
>     // just access to the publicly available information, the CSP would not ask
> for a PIN
>     PCCERT_CONTEXT pCertContext = NULL;
>     while (1)
>    {
>      pCertContext = CertEnumCertificatesInStore (hCertStore, pCertContext);
>      if (!pCertContext) break;
>      //suppose the maximum length of all the fileds doesn't exceed 512
>      const int iMaxFldLen = 512;
>      char szSubjectName[iMaxFldLen]={0}, szIssuerName[iMaxFldLen]={0};
>      // get common name,
>      CertGetNameString (pCertContext, CERT_NAME_ATTR_TYPE, NULL,
> szOID_COMMON_NAME, szSubjectName, iMaxFldLen);
>      // get issuer name
>      CertGetNameString (pCertContext, CERT_NAME_ATTR_TYPE,
> CERT_NAME_ISSUER_FLAG,
>               szOID_COMMON_NAME, szIssuerName, iMaxFldLen);
>      printf ("%s %s\n", szSubjectName, szIssuerName);
>      // get the CSP name and key container name
>      char szContName[iMaxFldLen]={0}, szProvName[iMaxFldLen]={0}, pvData
> [iMaxFldLen]={0};
>      DWORD cbData = iMaxFldLen;
>      CertGetCertificateContextProperty (pCertContext,
> CERT_KEY_PROV_INFO_PROP_ID, pvData, &cbData);
>      CRYPT_KEY_PROV_INFO* pProvInfo = (CRYPT_KEY_PROV_INFO *)pvData;
>      sprintf (szContName, "%S", pProvInfo->pwszContainerName);
>      sprintf (szProvName, "%S", pProvInfo->pwszProvName);
>    
>      printf ("%s %s\n", szContName, szProvName);
>      // get other fields of the X509 certificate
>      // ...
>     }
>     CryptReleaseContext (hCryptProv, 0); // release the handle
>
> 2. Using private key stored in the USB KEY to sign the digest of message
>     #include <wincrypt.h>
>     #pragma comment(lib, "crypt32.lib")
>     // the container name and CSP name can be retrieved in example 1
>     // char szContName[] = {"61aecdd2-65b4-4919-a56c-0b2f5f7833d1"};
>     // char szProvName[] = {"SafeSign CSP Version 1.0"};
>     char szMsg[] = {"something"};
>     DWORD dwMsgLen = strlen(szMsg);
>     HCRYPTPROV hCryptProv = NULL;
>     CryptAcquireContext (&hCryptProv, szContName, szProvName, PROV_RSA_FULL,
> 0);
>     HCRYPTHASH hHash = NULL;
>     CryptCreateHash (hCryptProv, CALG_MD5, 0, 0, &hHash);
>     CryptHashData (hHash, (BYTE*)szMsg, dwMsgLen, 0);
>     DWORD dwSignLen = 0;
>     CryptSignHash (hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSignLen);
>     char* szSignBuf = (char*) malloc(dwSignLen*sizeof(char));
>     if (!CryptSignHash (hHash, AT_SIGNATURE, NULL, 0, (BYTE*)szSignBuf, &
> dwSignLen))
>     {
>       printf ("CryptSignHash failed\n");
>     }
>     else
>     {
>       printf ("CryptSignHash done\n");
>     }
>   
>     free (szSignBuf);
>     CryptReleaseContext (hCryptProv, 0); // release the handle
>
> 3. Using private key to decrypt the ciphertext encrypted by the public key
>     #include <wincrypt.h>
>     #pragma comment(lib, "crypt32.lib")
>     // the container name and CSP name can be retrieved in example 1
>     // char szContName[] = {"61aecdd2-65b4-4919-a56c-0b2f5f7833d1"};
>     // char szProvName[] = {"SafeSign CSP Version 1.0"};
>     char pEncryptedData[] = {"top secret encrypted by public key"};
>     DWORD dwEncryptDataLen = strlen(pEncryptedData);
>     HCRYPTPROV hCryptProv = NULL;
>     CryptAcquireContext (&hCryptProv, szContName, szProvName, PROV_RSA_FULL,
> 0);
>     HCRYPTKEY hUserKey = NULL;
>     BOOL bRet= CryptGetUserKey (hCryptProv, AT_KEYEXCHANGE, &hUserKey);
>     // pEncryptedData point to the ciphertext encrypted by the public key and
>     // dwEncryptDataLen is the length of the ciphertext
>     if (!CryptDecrypt(hUserKey, 0, true, 0, (BYTE*)pEncryptedData, &
> dwEncryptDataLen))
>     {
>       // CryptDecrypt() will failed if the pEncryptedData was NOT
>       // encrypted by the corresponding public key
>       printf ("CryptDecrypt failed\n");
>     }
>     else
>     {
>       printf ("CryptDecrypt done\n");
>     }
>     // now pEncryptedData point to plaintext and
>     // dwEncryptDataLen is the length of the plaintext
>     CryptReleaseContext (hCryptProv, 0);
>  
>  
>  
> Thanks
>  
> Setven Zhang
>
>
> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
> 上房老大买二手房,看实景照片,挑专业经纪人

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org