Attribute VB_Name = "X509_TestCerts" ' $Id: X509_TestCerts.bas $ ' $Date: 2006-05-26 12:28:00 $ ' This module uses functions from the CryptoSys (tm) PKI Toolkit ' available from . ' Include the module `basCrPKI.bas' in your project. '***************** COPYRIGHT NOTICE ******************** ' This code was originally written by David Ireland and ' is copyright (C) 2006 DI Management Services Pty Ltd ' . ' Provided "as is". No warranties. Use at your own risk. ' You must make your own assessment of its accuracy and ' suitability for your own purposes. ' It is not to be altered or distributed, ' except as part of an application. ' You are free to use it in any application, ' provided this copyright notice is left unchanged. '************** END OF COPYRIGHT NOTICE **************** Option Explicit Option Base 0 Public Function TestTheChain() As Boolean Dim nRet As Long Dim strCertName As String Dim strIssuerCert As String Dim strThumbPrint As String ' Chain: [Enid] issued by [Ian] issued by [Carl] self-issued by [Carl]. ' Given the three certs, can we trust that Enid's certificate really is the one issued to her? ' Assumes we trust the CA's certificate and all certificates issued by it. ' Does not deal with certificate revokation (CRL) issues. ' 1. Is Enid's certificate currently valid? strCertName = "EnidRSASignedByIan.cer" nRet = X509_CertIsValidNow(strCertName, 0) If nRet > 0 Then Debug.Print "Error: " & nRet & " " & pkiGetLastError() ElseIf nRet < 0 Then MsgBox "Validation error: cert '" & strCertName & "' is no longer valid at this time.", vbCritical Exit Function Else Debug.Print "Cert '" & strCertName & "' is currently valid." End If ' 2. Was Enid's certificate issued by Ian? strIssuerCert = "IanRSASignedByCarl.cer" nRet = X509_VerifyCert(strCertName, strIssuerCert, 0) If nRet > 0 Then Debug.Print "Error: " & nRet & " " & pkiGetLastError() ElseIf nRet < 0 Then MsgBox "Validation error: cert '" & strCertName & "' was not issued by '" & strIssuerCert & "'.", vbCritical Exit Function Else Debug.Print "Verified that cert '" & strCertName & "' was issued by '" & strIssuerCert & "'." End If ' Continuing up the chain... ' 3. Is Ian's certificate currently valid? strCertName = "IanRSASignedByCarl.cer" nRet = X509_CertIsValidNow(strCertName, 0) If nRet > 0 Then Debug.Print "Error: " & nRet & " " & pkiGetLastError() ElseIf nRet < 0 Then MsgBox "Validation error: cert '" & strCertName & "' is no longer valid at this time.", vbCritical Exit Function Else Debug.Print "Cert '" & strCertName & "' is currently valid." End If ' 4. Was Ian's certificate issued by Carl? strIssuerCert = "CarlRSASelf.cer" nRet = X509_VerifyCert(strCertName, strIssuerCert, 0) If nRet > 0 Then Debug.Print "Error: " & nRet & " " & pkiGetLastError() ElseIf nRet < 0 Then MsgBox "Validation error: cert '" & strCertName & "' was not issued by '" & strIssuerCert & "'.", vbCritical Exit Function Else Debug.Print "Verified that cert '" & strCertName & "' was issued by '" & strIssuerCert & "'." End If ' At the top of the chain we have a self-signed certificate... ' 5. Is Carl's certificate currently valid? strCertName = "CarlRSASelf.cer" nRet = X509_CertIsValidNow(strCertName, 0) If nRet > 0 Then Debug.Print "Error: " & nRet & " " & pkiGetLastError() ElseIf nRet < 0 Then MsgBox "Validation error: cert '" & strCertName & "' is no longer valid at this time.", vbCritical Exit Function Else Debug.Print "Cert '" & strCertName & "' is currently valid." End If ' 6. Was Carl's certificate issued by Carl? strIssuerCert = "CarlRSASelf.cer" nRet = X509_VerifyCert(strCertName, strIssuerCert, 0) If nRet > 0 Then Debug.Print "Error: " & nRet & " " & pkiGetLastError() ElseIf nRet < 0 Then MsgBox "Validation error: cert '" & strCertName & "' was not issued by '" & strIssuerCert & "'.", vbCritical Exit Function Else Debug.Print "Verified that cert '" & strCertName & "' was issued by '" & strIssuerCert & "'." End If ' Finally, we can hard-code the "thumbprint" (hash digest) of the ultimate CA's certificate ' and check that it matches what we have in hand ' (you can get this value using CERTMGR.EXE). ' 7. Is Carl's certificate the one we expected? Const HARD_CODED_THUMBPRINT As String = "4110908F77C64C0EDFC2DE6273BFA9A98A9C5CE5" strCertName = "CarlRSASelf.cer" strThumbPrint = String(PKI_SHA1_CHARS, " ") nRet = X509_CertThumb(strCertName, strThumbPrint, Len(strThumbPrint), PKI_HASH_SHA1) Debug.Print "ThumbPrint(SHA-1, '" & strCertName & "')=" & strThumbPrint If UCase(strThumbPrint) = HARD_CODED_THUMBPRINT Then Debug.Print "CA cert's thumbprint matches what we expect." Else MsgBox "Validation error: cert '" & strCertName & "' does not have the thumbprint we expect.", vbCritical Exit Function End If ' If we got to here, we have validated the entire chain Debug.Print "OK, certificate chain has been validated." ' RETURN SUCCESS TestTheChain = True End Function Public Sub MakeAChain() Dim nRet As Long Dim strCertCA As String Dim strCertInt As String Dim strCertEnd As String Dim strPriKeyCA As String Dim strPriKeyInt As String Dim strPriKeyEnd As String Dim strPubKeyInt As String Dim strPubKeyEnd As String Dim nKeyUsageFlags As Long Dim nCertOptions As Long Dim nYears As Long ' Use S/MIME's Carl as CA strCertCA = "CarlRSASelf.cer" strPriKeyCA = "CarlPrivRSASign.epk" ' Intermediate authority Ian creates a pair of RSA keys strPubKeyInt = "IanPublicKey.bin" strPriKeyInt = "IanEncPrivKey.bin" nRet = RSA_MakeKeys(strPubKeyInt, strPriKeyInt, 512, PKI_RSAEXP_EQ_3, 50, 1000, "ianspassword", "", 0, PKI_KEYGEN_INDICATE) Debug.Print "RSA_MakeKeys returns " & nRet & " (expecting 0)" ' End user Enid creates a pair of RSA keys strPubKeyEnd = "EnidPublicKey.bin" strPriKeyEnd = "EnidEncPrivKey.bin" nRet = RSA_MakeKeys(strPubKeyEnd, strPriKeyEnd, 512, PKI_RSAEXP_EQ_3, 50, 1000, "enidspassword", "", 0, PKI_KEYGEN_INDICATE) Debug.Print "RSA_MakeKeys returns " & nRet & " (expecting 0)" ' Carl issues an "intermediate CA" certificate to Ian valid for 5 years strCertInt = "IanRSASignedByCarl.cer" nYears = 5 nKeyUsageFlags = PKI_X509_KEYUSAGE_KEYCERTSIGN + PKI_X509_KEYUSAGE_CRLSIGN + PKI_X509_KEYUSAGE_DIGITALSIGNATURE nCertOptions = PKI_X509_CA_TRUE + PKI_X509_UTF8 nRet = X509_MakeCert(strCertInt, strCertCA, strPubKeyInt, strPriKeyCA, &H3001, nYears, "CN=Ian", "", nKeyUsageFlags, "password", nCertOptions) Debug.Print "X509_MakeCert returns " & nRet & " (expecting 0)" ' Ian issues a certificate to Enid valid for 2 years strCertEnd = "EnidRSASignedByIan.cer" nYears = 2 nKeyUsageFlags = 0 nCertOptions = PKI_X509_NO_BASIC + PKI_X509_UTF8 nRet = X509_MakeCert(strCertEnd, strCertInt, strPubKeyEnd, strPriKeyInt, &H1, nYears, "CN=Enid", "", nKeyUsageFlags, "ianspassword", nCertOptions) Debug.Print "X509_MakeCert returns " & nRet & " (expecting 0)" End Sub Public Sub X509_TestParentAndChild() ' Returns 0 if OK, -1 if fails to validate, or +ve other error Dim nRet As Long nRet = X509_VerifyCert("EnidRSASignedByIan.cer", "IanRSASignedByCarl.cer", 0) If nRet = 0 Then Debug.Print "Verification is OK" ElseIf nRet > 0 Then Debug.Print "Error: " & nRet & " " & pkiGetLastError() Else Debug.Print "Cert not issued by this Issuer" End If End Sub Public Sub MakeCertHash() Dim nRet As Long Dim strCertName As String Dim strThumbPrint As String strCertName = "CarlRSASelf.cer" strThumbPrint = String(PKI_SHA1_CHARS, " ") nRet = X509_CertThumb(strCertName, strThumbPrint, Len(strThumbPrint), PKI_HASH_SHA1) Debug.Print "ThumbPrint(SHA-1, '" & strCertName & "')=" & strThumbPrint End Sub